Merge tag 'media/v6.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Apr 2023 23:27:13 +0000 (16:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Apr 2023 23:27:13 +0000 (16:27 -0700)
Pull media updates from Mauro Carvalho Chehab:

 - Removal of some old unused sensor drivers: ad9389b, m5mols, mt9m032,
   mt9t001, noon010pc30, s5k6aa, sr030pc30 and vs6624

 - New i.MX8 image sensor interface driver

 - Some new RC keymaps

 - lots of cleanups at atomisp driver to make it support standard
   features present on other webcam drivers

 - the cx18 and saa7146 now uses VB2

 - lots of cleanups and driver improvements

* tag 'media/v6.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (460 commits)
  media: ov5670: Fix probe on ACPI
  media: nxp: imx8-isi: Remove 300ms sleep after enabling channel
  media: nxp: imx8-isi: Replace udelay() with fsleep()
  media: nxp: imx8-isi: Drop partial support for i.MX8QM and i.MX8QXP
  media: nxp: Add i.MX8 ISI driver
  media: dt-bindings: media: Add i.MX8 ISI DT bindings
  media: atomisp: gmin_platform: Add Lenovo Ideapad Miix 310 gmin_vars
  media: atomisp: gmin_platform: Make DMI quirks take precedence over the _DSM table
  media: atomisp: Remove struct atomisp_sub_device index field
  media: atomisp: Drop support for streaming from 2 sensors at once
  media: atomisp: Remove atomisp_try_fmt() call from atomisp_set_fmt()
  media: atomisp: Remove unused ATOM_ISP_MAX_WIDTH_TMP and ATOM_ISP_MAX_HEIGHT_TMP
  media: atomisp: Remove snr_mbus_fmt local var from atomisp_try_fmt()
  media: atomisp: Remove custom V4L2_CID_FMT_AUTO control
  media: atomisp: Remove continuous mode related code from atomisp_set_fmt()
  media: atomisp: Remove duplicate atomisp_[start|stop]_streaming() prototypes
  media: atomisp: gc0310: Switch over to ACPI powermanagement
  media: atomisp: gc0310: Use devm_kzalloc() for data struct
  media: atomisp: gc0310: Add runtime-pm support
  media: atomisp: gc0310: Delay power-on till streaming is started
  ...

442 files changed:
Documentation/admin-guide/media/cec.rst
Documentation/admin-guide/media/i2c-cardlist.rst
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
Documentation/devicetree/bindings/media/allwinner,sun50i-h6-vpu-g2.yaml
Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml
Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml
Documentation/devicetree/bindings/media/amlogic,meson-ir-tx.yaml
Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/exynos-fimc-lite.txt [deleted file]
Documentation/devicetree/bindings/media/exynos4-fimc-is.txt [deleted file]
Documentation/devicetree/bindings/media/gpio-ir-receiver.yaml
Documentation/devicetree/bindings/media/i2c/chrontel,ch7322.yaml
Documentation/devicetree/bindings/media/i2c/dongwoon,dw9768.yaml
Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml
Documentation/devicetree/bindings/media/i2c/ov2685.txt [deleted file]
Documentation/devicetree/bindings/media/i2c/ov8856.yaml
Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml
Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/i2c/samsung,s5k5baf.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/i2c/samsung,s5k6a3.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml
Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml
Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
Documentation/devicetree/bindings/media/meson-ir.txt [deleted file]
Documentation/devicetree/bindings/media/microchip,sama5d4-vdec.yaml
Documentation/devicetree/bindings/media/nxp,imx8-isi.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/nxp,imx8mq-vpu.yaml
Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml
Documentation/devicetree/bindings/media/qcom,msm8916-venus.yaml
Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml
Documentation/devicetree/bindings/media/qcom,msm8996-venus.yaml
Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml
Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml
Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml
Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml
Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml
Documentation/devicetree/bindings/media/qcom,sdm845-venus-v2.yaml
Documentation/devicetree/bindings/media/qcom,sdm845-venus.yaml
Documentation/devicetree/bindings/media/qcom,sm8250-camss.yaml
Documentation/devicetree/bindings/media/qcom,sm8250-venus.yaml
Documentation/devicetree/bindings/media/qcom,venus-common.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/rc.yaml
Documentation/devicetree/bindings/media/renesas,csi2.yaml
Documentation/devicetree/bindings/media/renesas,fcp.yaml
Documentation/devicetree/bindings/media/renesas,isp.yaml
Documentation/devicetree/bindings/media/renesas,vin.yaml
Documentation/devicetree/bindings/media/renesas,vsp1.yaml
Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml
Documentation/devicetree/bindings/media/rockchip-isp1.yaml
Documentation/devicetree/bindings/media/rockchip-vpu.yaml
Documentation/devicetree/bindings/media/samsung,exynos4210-csis.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/samsung,exynos4210-fimc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-lite.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/samsung,fimc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/samsung,s5c73m3.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/samsung-fimc.txt [deleted file]
Documentation/devicetree/bindings/media/samsung-mipi-csis.txt [deleted file]
Documentation/devicetree/bindings/media/samsung-s5c73m3.txt [deleted file]
Documentation/devicetree/bindings/media/samsung-s5k5baf.txt [deleted file]
Documentation/devicetree/bindings/media/samsung-s5k6a3.txt [deleted file]
Documentation/devicetree/bindings/media/si470x.txt [deleted file]
Documentation/devicetree/bindings/media/silabs,si470x.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/media/st,stm32-cec.yaml [deleted file]
Documentation/devicetree/bindings/media/ti,cal.yaml
Documentation/driver-api/media/drivers/ccs/ccs.rst
Documentation/userspace-api/media/v4l/dev-overlay.rst
Documentation/userspace-api/media/v4l/pixfmt-compressed.rst
Documentation/userspace-api/media/v4l/pixfmt-packed-yuv.rst
Documentation/userspace-api/media/v4l/pixfmt-rgb.rst
Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst
Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst
Documentation/userspace-api/media/v4l/user-func.rst
Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst
Documentation/userspace-api/media/v4l/vidioc-g-fbuf.rst
Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-size.rst
Documentation/userspace-api/media/v4l/vidioc-subdev-enum-mbus-code.rst
Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst [new file with mode: 0644]
MAINTAINERS
drivers/media/cec/core/cec-adap.c
drivers/media/cec/platform/cec-gpio/cec-gpio.c
drivers/media/cec/platform/cros-ec/cros-ec-cec.c
drivers/media/cec/platform/meson/ao-cec-g12a.c
drivers/media/cec/platform/meson/ao-cec.c
drivers/media/cec/platform/s5p/s5p_cec.c
drivers/media/cec/platform/seco/seco-cec.c
drivers/media/cec/platform/sti/stih-cec.c
drivers/media/cec/platform/stm32/stm32-cec.c
drivers/media/cec/platform/tegra/tegra_cec.c
drivers/media/common/btcx-risc.h [deleted file]
drivers/media/common/saa7146/Kconfig
drivers/media/common/saa7146/saa7146_core.c
drivers/media/common/saa7146/saa7146_fops.c
drivers/media/common/saa7146/saa7146_hlp.c
drivers/media/common/saa7146/saa7146_vbi.c
drivers/media/common/saa7146/saa7146_video.c
drivers/media/common/videobuf2/videobuf2-v4l2.c
drivers/media/dvb-frontends/drx39xyj/drxj.c
drivers/media/dvb-frontends/drxk_hard.c
drivers/media/dvb-frontends/rtl2832_sdr.c
drivers/media/dvb-frontends/zd1301_demod.c
drivers/media/i2c/Kconfig
drivers/media/i2c/Makefile
drivers/media/i2c/ad9389b.c [deleted file]
drivers/media/i2c/adv748x/adv748x-hdmi.c
drivers/media/i2c/adv7604.c
drivers/media/i2c/ccs/ccs-core.c
drivers/media/i2c/ccs/ccs.h
drivers/media/i2c/hi556.c
drivers/media/i2c/hi846.c
drivers/media/i2c/imx258.c
drivers/media/i2c/imx290.c
drivers/media/i2c/imx296.c
drivers/media/i2c/imx334.c
drivers/media/i2c/m5mols/Kconfig [deleted file]
drivers/media/i2c/m5mols/Makefile [deleted file]
drivers/media/i2c/m5mols/m5mols.h [deleted file]
drivers/media/i2c/m5mols/m5mols_capture.c [deleted file]
drivers/media/i2c/m5mols/m5mols_controls.c [deleted file]
drivers/media/i2c/m5mols/m5mols_core.c [deleted file]
drivers/media/i2c/m5mols/m5mols_reg.h [deleted file]
drivers/media/i2c/max9286.c
drivers/media/i2c/mt9m032.c [deleted file]
drivers/media/i2c/mt9t001.c [deleted file]
drivers/media/i2c/noon010pc30.c [deleted file]
drivers/media/i2c/ov13b10.c
drivers/media/i2c/ov2685.c
drivers/media/i2c/ov5647.c
drivers/media/i2c/ov5670.c
drivers/media/i2c/ov7670.c
drivers/media/i2c/ov8856.c
drivers/media/i2c/s5k6aa.c [deleted file]
drivers/media/i2c/sr030pc30.c [deleted file]
drivers/media/i2c/st-vgxy61.c
drivers/media/i2c/tc358746.c
drivers/media/i2c/vs6624.c [deleted file]
drivers/media/i2c/vs6624_regs.h [deleted file]
drivers/media/mc/mc-device.c
drivers/media/pci/bt8xx/Kconfig
drivers/media/pci/bt8xx/btcx-risc.c
drivers/media/pci/bt8xx/btcx-risc.h
drivers/media/pci/bt8xx/bttv-cards.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/bt8xx/bttv-risc.c
drivers/media/pci/bt8xx/bttvp.h
drivers/media/pci/cobalt/cobalt-v4l2.c
drivers/media/pci/cx18/Kconfig
drivers/media/pci/cx18/cx18-driver.c
drivers/media/pci/cx18/cx18-driver.h
drivers/media/pci/cx18/cx18-fileops.c
drivers/media/pci/cx18/cx18-fileops.h
drivers/media/pci/cx18/cx18-ioctl.c
drivers/media/pci/cx18/cx18-mailbox.c
drivers/media/pci/cx18/cx18-streams.c
drivers/media/pci/cx23885/cx23885-core.c
drivers/media/pci/cx23885/cx23885-video.c
drivers/media/pci/dm1105/dm1105.c
drivers/media/pci/intel/ipu3/cio2-bridge.c
drivers/media/pci/intel/ipu3/cio2-bridge.h
drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
drivers/media/pci/saa7134/saa7134-cards.c
drivers/media/pci/saa7134/saa7134-core.c
drivers/media/pci/saa7134/saa7134-empress.c
drivers/media/pci/saa7134/saa7134-ts.c
drivers/media/pci/saa7134/saa7134-vbi.c
drivers/media/pci/saa7134/saa7134-video.c
drivers/media/pci/saa7134/saa7134.h
drivers/media/pci/saa7146/hexium_gemini.c
drivers/media/pci/saa7146/hexium_orion.c
drivers/media/pci/saa7146/mxb.c
drivers/media/pci/ttpci/budget-av.c
drivers/media/pci/tw68/tw68-video.c
drivers/media/pci/zoran/zoran_device.h
drivers/media/platform/allegro-dvt/allegro-core.c
drivers/media/platform/amlogic/meson-ge2d/ge2d.c
drivers/media/platform/amphion/vdec.c
drivers/media/platform/amphion/vpu_codec.h
drivers/media/platform/amphion/vpu_core.c
drivers/media/platform/amphion/vpu_drv.c
drivers/media/platform/amphion/vpu_malone.c
drivers/media/platform/amphion/vpu_malone.h
drivers/media/platform/aspeed/aspeed-video.c
drivers/media/platform/atmel/atmel-isi.c
drivers/media/platform/cadence/cdns-csi2rx.c
drivers/media/platform/cadence/cdns-csi2tx.c
drivers/media/platform/chips-media/coda-common.c
drivers/media/platform/intel/pxa_camera.c
drivers/media/platform/m2m-deinterlace.c
drivers/media/platform/marvell/mcam-core.c
drivers/media/platform/marvell/mmp-driver.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h
drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
drivers/media/platform/mediatek/mdp/mtk_mdp_core.c
drivers/media/platform/mediatek/mdp3/Makefile
drivers/media/platform/mediatek/mdp3/mdp_cfg_data.c [new file with mode: 0644]
drivers/media/platform/mediatek/mdp3/mdp_sm_mt8183.h [new file with mode: 0644]
drivers/media/platform/mediatek/mdp3/mtk-img-ipi.h
drivers/media/platform/mediatek/mdp3/mtk-mdp3-cfg.h [new file with mode: 0644]
drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c
drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c
drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.h
drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c
drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.h
drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c
drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.h
drivers/media/platform/mediatek/mdp3/mtk-mdp3-regs.c
drivers/media/platform/mediatek/mdp3/mtk-mdp3-regs.h
drivers/media/platform/mediatek/mdp3/mtk-mdp3-type.h [new file with mode: 0644]
drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c
drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.h
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateful.c
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c
drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c
drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c
drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c
drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c
drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h
drivers/media/platform/mediatek/vpu/mtk_vpu.c
drivers/media/platform/microchip/microchip-csi2dc.c
drivers/media/platform/microchip/microchip-isc-base.c
drivers/media/platform/microchip/microchip-sama5d2-isc.c
drivers/media/platform/microchip/microchip-sama7g5-isc.c
drivers/media/platform/nvidia/tegra-vde/vde.c
drivers/media/platform/nxp/Kconfig
drivers/media/platform/nxp/Makefile
drivers/media/platform/nxp/dw100/dw100.c
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
drivers/media/platform/nxp/imx-mipi-csis.c
drivers/media/platform/nxp/imx-pxp.c
drivers/media/platform/nxp/imx7-media-csi.c
drivers/media/platform/nxp/imx8-isi/Kconfig [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/Makefile [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/imx8-isi-debug.c [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/imx8-isi-regs.h [new file with mode: 0644]
drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c [new file with mode: 0644]
drivers/media/platform/nxp/mx2_emmaprp.c
drivers/media/platform/qcom/camss/camss-csid-gen2.c
drivers/media/platform/qcom/camss/camss-csid.c
drivers/media/platform/qcom/camss/camss-csid.h
drivers/media/platform/qcom/camss/camss-vfe-170.c
drivers/media/platform/qcom/camss/camss-vfe-480.c
drivers/media/platform/qcom/camss/camss-vfe-gen1.c
drivers/media/platform/qcom/camss/camss-vfe.c
drivers/media/platform/qcom/camss/camss-video.c
drivers/media/platform/qcom/camss/camss.c
drivers/media/platform/qcom/venus/core.c
drivers/media/platform/qcom/venus/core.h
drivers/media/platform/qcom/venus/helpers.c
drivers/media/platform/qcom/venus/hfi_cmds.c
drivers/media/platform/qcom/venus/hfi_helper.h
drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c
drivers/media/platform/qcom/venus/vdec.c
drivers/media/platform/qcom/venus/venc.c
drivers/media/platform/renesas/rcar-fcp.c
drivers/media/platform/renesas/rcar-isp.c
drivers/media/platform/renesas/rcar-vin/rcar-core.c
drivers/media/platform/renesas/rcar-vin/rcar-csi2.c
drivers/media/platform/renesas/rcar_drif.c
drivers/media/platform/renesas/rcar_fdp1.c
drivers/media/platform/renesas/rcar_jpu.c
drivers/media/platform/renesas/renesas-ceu.c
drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c
drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c
drivers/media/platform/renesas/sh_vou.c
drivers/media/platform/renesas/vsp1/vsp1_drm.c
drivers/media/platform/renesas/vsp1/vsp1_drv.c
drivers/media/platform/renesas/vsp1/vsp1_entity.c
drivers/media/platform/renesas/vsp1/vsp1_entity.h
drivers/media/platform/renesas/vsp1/vsp1_pipe.h
drivers/media/platform/renesas/vsp1/vsp1_regs.h
drivers/media/platform/renesas/vsp1/vsp1_video.c
drivers/media/platform/rockchip/rga/rga.c
drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c
drivers/media/platform/samsung/exynos-gsc/gsc-core.c
drivers/media/platform/samsung/exynos4-is/fimc-capture.c
drivers/media/platform/samsung/exynos4-is/fimc-core.c
drivers/media/platform/samsung/exynos4-is/fimc-is-errno.c
drivers/media/platform/samsung/exynos4-is/fimc-is-errno.h
drivers/media/platform/samsung/exynos4-is/fimc-is-i2c.c
drivers/media/platform/samsung/exynos4-is/fimc-is.c
drivers/media/platform/samsung/exynos4-is/fimc-isp-video.c
drivers/media/platform/samsung/exynos4-is/fimc-lite.c
drivers/media/platform/samsung/exynos4-is/media-dev.c
drivers/media/platform/samsung/exynos4-is/mipi-csis.c
drivers/media/platform/samsung/s3c-camif/camif-capture.c
drivers/media/platform/samsung/s3c-camif/camif-core.c
drivers/media/platform/samsung/s5p-g2d/g2d.c
drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c
drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c
drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
drivers/media/platform/st/sti/delta/delta-v4l2.c
drivers/media/platform/st/sti/hva/hva-v4l2.c
drivers/media/platform/st/stm32/dma2d/dma2d.c
drivers/media/platform/st/stm32/dma2d/dma2d.h
drivers/media/platform/st/stm32/stm32-dcmi.c
drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c
drivers/media/platform/ti/am437x/am437x-vpfe.c
drivers/media/platform/ti/cal/cal-video.c
drivers/media/platform/ti/cal/cal.c
drivers/media/platform/ti/davinci/vpif.c
drivers/media/platform/ti/davinci/vpif_capture.c
drivers/media/platform/ti/davinci/vpif_display.c
drivers/media/platform/ti/omap/omap_vout.c
drivers/media/platform/ti/omap3isp/isp.c
drivers/media/platform/ti/omap3isp/ispccdc.c
drivers/media/platform/ti/omap3isp/ispvideo.c
drivers/media/platform/ti/vpe/vpe.c
drivers/media/platform/verisilicon/hantro_drv.c
drivers/media/platform/verisilicon/hantro_postproc.c
drivers/media/platform/verisilicon/hantro_v4l2.c
drivers/media/platform/verisilicon/hantro_v4l2.h
drivers/media/platform/verisilicon/imx8m_vpu_hw.c
drivers/media/platform/via/via-camera.c
drivers/media/platform/video-mux.c
drivers/media/platform/xilinx/xilinx-csi2rxss.c
drivers/media/platform/xilinx/xilinx-dma.c
drivers/media/platform/xilinx/xilinx-tpg.c
drivers/media/platform/xilinx/xilinx-vipp.c
drivers/media/platform/xilinx/xilinx-vtc.c
drivers/media/radio/radio-si476x.c
drivers/media/radio/radio-timb.c
drivers/media/radio/radio-wl1273.c
drivers/media/radio/si4713/radio-platform-si4713.c
drivers/media/rc/gpio-ir-recv.c
drivers/media/rc/img-ir/img-ir-core.c
drivers/media/rc/ir-hix5hd2.c
drivers/media/rc/keymaps/Makefile
drivers/media/rc/keymaps/rc-beelink-mxiii.c [new file with mode: 0644]
drivers/media/rc/keymaps/rc-dreambox.c [new file with mode: 0644]
drivers/media/rc/meson-ir-tx.c
drivers/media/rc/meson-ir.c
drivers/media/rc/mtk-cir.c
drivers/media/rc/st_rc.c
drivers/media/rc/sunxi-cir.c
drivers/media/test-drivers/vicodec/vicodec-core.c
drivers/media/test-drivers/vidtv/vidtv_bridge.c
drivers/media/test-drivers/vim2m.c
drivers/media/test-drivers/vimc/vimc-common.c
drivers/media/test-drivers/vimc/vimc-core.c
drivers/media/test-drivers/visl/visl-core.c
drivers/media/test-drivers/vivid/vivid-core.c
drivers/media/test-drivers/vivid/vivid-core.h
drivers/media/test-drivers/vivid/vivid-kthread-cap.c
drivers/media/test-drivers/vivid/vivid-vid-cap.c
drivers/media/test-drivers/vivid/vivid-vid-cap.h
drivers/media/test-drivers/vivid/vivid-vid-out.c
drivers/media/tuners/it913x.c
drivers/media/tuners/mxl5005s.c
drivers/media/usb/au0828/au0828-core.c
drivers/media/usb/au0828/au0828-dvb.c
drivers/media/usb/dvb-usb/cxusb-analog.c
drivers/media/usb/dvb-usb/pctv452e.c
drivers/media/usb/pvrusb2/Kconfig
drivers/media/usb/usbtv/usbtv-core.c
drivers/media/v4l2-core/v4l2-async.c
drivers/media/v4l2-core/v4l2-common.c
drivers/media/v4l2-core/v4l2-compat-ioctl32.c
drivers/media/v4l2-core/v4l2-dev.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/media/v4l2-core/v4l2-mc.c
drivers/media/v4l2-core/v4l2-subdev.c
drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
drivers/staging/media/atomisp/i2c/gc0310.h
drivers/staging/media/atomisp/i2c/ov2680.h
drivers/staging/media/atomisp/include/linux/atomisp.h
drivers/staging/media/atomisp/include/linux/atomisp_platform.h
drivers/staging/media/atomisp/pci/atomisp_cmd.c
drivers/staging/media/atomisp/pci/atomisp_cmd.h
drivers/staging/media/atomisp/pci/atomisp_compat.h
drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
drivers/staging/media/atomisp/pci/atomisp_fops.c
drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
drivers/staging/media/atomisp/pci/atomisp_internal.h
drivers/staging/media/atomisp/pci/atomisp_ioctl.c
drivers/staging/media/atomisp/pci/atomisp_ioctl.h
drivers/staging/media/atomisp/pci/atomisp_subdev.c
drivers/staging/media/atomisp/pci/atomisp_subdev.h
drivers/staging/media/atomisp/pci/atomisp_v4l2.c
drivers/staging/media/av7110/av7110.c
drivers/staging/media/av7110/av7110_av.c
drivers/staging/media/av7110/av7110_hw.c
drivers/staging/media/av7110/av7110_v4l.c
drivers/staging/media/deprecated/atmel/atmel-isc-base.c
drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
drivers/staging/media/imx/imx-media-capture.c
drivers/staging/media/imx/imx-media-csi.c
drivers/staging/media/imx/imx-media-dev-common.c
drivers/staging/media/imx/imx-media-dev.c
drivers/staging/media/imx/imx-media-of.c
drivers/staging/media/imx/imx-media-utils.c
drivers/staging/media/imx/imx-media.h
drivers/staging/media/imx/imx6-mipi-csi2.c
drivers/staging/media/imx/imx8mq-mipi-csi2.c
drivers/staging/media/meson/vdec/vdec.c
drivers/staging/media/omap4iss/iss.c
drivers/staging/media/omap4iss/iss_video.c
drivers/staging/media/rkvdec/rkvdec.c
drivers/staging/media/sunxi/cedrus/cedrus.c
drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c
drivers/staging/media/tegra-video/vi.c
include/media/drv-intf/saa7146_vv.h
include/media/dvb_net.h
include/media/i2c/ad9389b.h [deleted file]
include/media/i2c/m5mols.h [deleted file]
include/media/i2c/mt9m032.h [deleted file]
include/media/i2c/mt9t001.h [deleted file]
include/media/i2c/noon010pc30.h [deleted file]
include/media/i2c/s5k6aa.h [deleted file]
include/media/i2c/sr030pc30.h [deleted file]
include/media/media-device.h
include/media/rc-map.h
include/media/tveeprom.h
include/media/v4l2-ctrls.h
include/media/v4l2-mc.h
include/media/v4l2-subdev.h
include/uapi/linux/v4l2-subdev.h
include/uapi/linux/videodev2.h

index 14ec3ff317c269a5d9b08679eaa142aed9a93544..6b30e355cf23d8498e13f7f8c5cca7db4d124e3a 100644 (file)
@@ -55,6 +55,15 @@ Miscellaneous:
   you can control the CEC line through this driver. This supports error
   injection as well.
 
+- cec-gpio and Allwinner A10 (or any other driver that uses the CEC pin
+  framework to drive the CEC pin directly): the CEC pin framework uses
+  high-resolution timers. These timers are affected by NTP daemons that
+  speed up or slow down the clock to sync with the official time. The
+  chronyd server will by default increase or decrease the clock by
+  1/12th. This will cause the CEC timings to go out of spec. To fix this,
+  add a 'maxslewrate 40000' line to chronyd.conf. This limits the clock
+  frequency change to 1/25th, which keeps the CEC timings within spec.
+
 
 Utilities
 =========
@@ -296,69 +305,71 @@ broadcast messages twice to reduce the chance of them being lost. Specifically
 Making a CEC debugger
 =====================
 
-By using a Raspberry Pi 2B/3/4 and some cheap components you can make
+By using a Raspberry Pi 4B and some cheap components you can make
 your own low-level CEC debugger.
 
-Here is a picture of my setup:
-
-https://hverkuil.home.xs4all.nl/rpi3-cec.jpg
-
-It's a Raspberry Pi 3 together with a breadboard and some breadboard wires:
-
-http://www.dx.com/p/diy-40p-male-to-female-male-to-male-female-to-female-dupont-line-wire-3pcs-356089#.WYLOOXWGN7I
-
-Finally on of these HDMI female-female passthrough connectors (full soldering type 1):
+The critical component is one of these HDMI female-female passthrough connectors
+(full soldering type 1):
 
 https://elabbay.myshopify.com/collections/camera/products/hdmi-af-af-v1a-hdmi-type-a-female-to-hdmi-type-a-female-pass-through-adapter-breakout-board?variant=45533926147
 
-We've tested this and it works up to 4kp30 (297 MHz). The quality is not high
-enough to pass-through 4kp60 (594 MHz).
-
-I also added an RTC and a breakout shield:
-
-https://www.amazon.com/Makerfire%C2%AE-Raspberry-Module-DS1307-Battery/dp/B00ZOXWHK4
+The video quality is variable and certainly not enough to pass-through 4kp60
+(594 MHz) video. You might be able to support 4kp30, but more likely you will
+be limited to 1080p60 (148.5 MHz). But for CEC testing that is fine.
 
-https://www.dx.com/p/raspberry-pi-gpio-expansion-board-breadboard-easy-multiplexing-board-one-to-three-with-screw-for-raspberry-pi-2-3-b-b-2729992.html#.YGRCG0MzZ7I
+You need a breadboard and some breadboard wires:
 
-These two are not needed but they make life a bit easier.
+http://www.dx.com/p/diy-40p-male-to-female-male-to-male-female-to-female-dupont-line-wire-3pcs-356089#.WYLOOXWGN7I
 
-If you want to monitor the HPD line as well, then you need one of these
-level shifters:
+If you want to monitor the HPD and/or 5V lines as well, then you need one of
+these 5V to 3.3V level shifters:
 
 https://www.adafruit.com/product/757
 
 (This is just where I got these components, there are many other places you
 can get similar things).
 
+The ground pin of the HDMI connector needs to be connected to a ground
+pin of the Raspberry Pi, of course.
+
 The CEC pin of the HDMI connector needs to be connected to these pins:
-CE0/IO8 and CE1/IO7 (pull-up GPIOs). The (optional) HPD pin of the HDMI
-connector should be connected (via a level shifter to convert the 5V
-to 3.3V) to these pins: IO17 and IO27. The (optional) 5V pin of the HDMI
-connector should be connected (via a level shifter) to these pins: IO22
-and IO24. Monitoring the HPD an 5V lines is not necessary, but it is helpful.
+GPIO 6 and GPIO 7. The optional HPD pin of the HDMI connector should
+be connected via the level shifter to these pins: GPIO 23 and GPIO 12.
+The optional 5V pin of the HDMI connector should be connected via the
+level shifter to these pins: GPIO 25 and GPIO 22. Monitoring the HPD and
+5V lines is not necessary, but it is helpful.
 
-This kernel patch will hook up the cec-gpio driver correctly to
-e.g. ``arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts``::
+This device tree addition in ``arch/arm/boot/dts/bcm2711-rpi-4-b.dts``
+will hook up the cec-gpio driver correctly::
+
+       cec@6 {
+               compatible = "cec-gpio";
+               cec-gpios = <&gpio 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+               hpd-gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
+               v5-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
+       };
 
        cec@7 {
                compatible = "cec-gpio";
                cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
-               hpd-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+               hpd-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
                v5-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
        };
 
-       cec@8 {
-               compatible = "cec-gpio";
-               cec-gpios = <&gpio 8 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
-               hpd-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
-               v5-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
-       };
+If you haven't hooked up the HPD and/or 5V lines, then just delete those
+lines.
 
 This dts change will enable two cec GPIO devices: I typically use one to
 send/receive CEC commands and the other to monitor. If you monitor using
 an unconfigured CEC adapter then it will use GPIO interrupts which makes
 monitoring very accurate.
 
+If you just want to monitor traffic, then a single instance is sufficient.
+The minimum configuration is one HDMI female-female passthrough connector
+and two female-female breadboard wires: one for connecting the HDMI ground
+pin to a ground pin on the Raspberry Pi, and the other to connect the HDMI
+CEC pin to GPIO 6 on the Raspberry Pi.
+
 The documentation on how to use the error injection is here: :ref:`cec_pin_error_inj`.
 
 ``cec-ctl --monitor-pin`` will do low-level CEC bus sniffing and analysis.
index ef3b5fff3b01bd1a11677aeea2dd831101359d4c..1825a0bb47bddbbcee11e7aa1899cae6f1bcf2f3 100644 (file)
@@ -72,17 +72,13 @@ imx319        Sony IMX319 sensor
 imx334        Sony IMX334 sensor
 imx355        Sony IMX355 sensor
 imx412        Sony IMX412 sensor
-m5mols        Fujitsu M-5MOLS 8MP sensor
 mt9m001       mt9m001
-mt9m032       MT9M032 camera sensor
 mt9m111       mt9m111, mt9m112 and mt9m131
 mt9p031       Aptina MT9P031
-mt9t001       Aptina MT9T001
 mt9t112       Aptina MT9T111/MT9T112
 mt9v011       Micron mt9v011 sensor
 mt9v032       Micron MT9V032 sensor
 mt9v111       Aptina MT9V111 sensor
-noon010pc30   Siliconfile NOON010PC30 sensor
 ov13858       OmniVision OV13858 sensor
 ov13b10       OmniVision OV13B10 sensor
 ov2640        OmniVision OV2640 sensor
@@ -109,9 +105,6 @@ s5c73m3       Samsung S5C73M3 sensor
 s5k4ecgx      Samsung S5K4ECGX sensor
 s5k5baf       Samsung S5K5BAF sensor
 s5k6a3        Samsung S5K6A3 sensor
-s5k6aa        Samsung S5K6AAFX sensor
-sr030pc30     Siliconfile SR030PC30 sensor
-vs6624        ST VS6624 sensor
 ============  ==========================================================
 
 Flash devices
@@ -222,7 +215,6 @@ Video encoders
 ============  ==========================================================
 Driver        Name
 ============  ==========================================================
-ad9389b       Analog Devices AD9389B encoder
 adv7170       Analog Devices ADV7170 video encoder
 adv7175       Analog Devices ADV7175 video encoder
 adv7343       ADV7343 video encoder
index 53945c61325c72aa9c93dbda00ce826c7f3c571f..42dfe22ad5f1d86e7a7fac5f691f274512920dfc 100644 (file)
@@ -11,7 +11,7 @@ maintainers:
   - Maxime Ripard <mripard@kernel.org>
 
 allOf:
-  - $ref: "rc.yaml#"
+  - $ref: rc.yaml#
 
 properties:
   compatible:
index 9d44236f2debdca6df9386ce5bf660d8b8a48c2f..a4f06bbdfe499d8e3381897b4c6ca3b13c01f78f 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/allwinner,sun50i-h6-vpu-g2.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/allwinner,sun50i-h6-vpu-g2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Hantro G2 VPU codec implemented on Allwinner H6 SoC
 
index e551be5e680e36cb06a96a73fe1fea3c32694499..f23fa6d06ad066162668f9464c58815bdfd5e940 100644 (file)
@@ -2,8 +2,8 @@
 # Copyright 2020 BayLibre, SAS
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/amlogic,axg-ge2d.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/amlogic,axg-ge2d.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic GE2D Acceleration Unit
 
index b827edabcafaa475437b88d3d2b66e350f3a119c..55930f6107c9c5462267fedcc88a6428b8e5ac34 100644 (file)
@@ -2,8 +2,8 @@
 # Copyright 2019 BayLibre, SAS
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/amlogic,gx-vdec.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/amlogic,gx-vdec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic Video Decoder
 
index 4432fea32650723141e11ee5b18bf13b0277245f..377acce934234bfa894060579c6a369c30013b90 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/amlogic,meson-ir-tx.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/amlogic,meson-ir-tx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic Meson IR transmitter
 
diff --git a/Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml b/Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml
new file mode 100644 (file)
index 0000000..3f9fa92
--- /dev/null
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/amlogic,meson6-ir.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic Meson IR remote control receiver
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+allOf:
+  - $ref: rc.yaml#
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+          - amlogic,meson6-ir
+          - amlogic,meson8b-ir
+          - amlogic,meson-gxbb-ir
+      - items:
+          - const: amlogic,meson-gx-ir
+          - const: amlogic,meson-gxbb-ir
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    ir-receiver@c8100480 {
+        compatible = "amlogic,meson6-ir";
+        reg = <0xc8100480 0x20>;
+        interrupts = <GIC_SPI 15 IRQ_TYPE_EDGE_RISING>;
+    };
diff --git a/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt b/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt
deleted file mode 100644 (file)
index 0bf6fb7..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Exynos4x12/Exynos5 SoC series camera host interface (FIMC-LITE)
-
-Required properties:
-
-- compatible   : should be one of:
-                 "samsung,exynos4212-fimc-lite" for Exynos4212/4412 SoCs,
-                 "samsung,exynos5250-fimc-lite" for Exynos5250 compatible
-                  devices;
-- reg          : physical base address and size of the device memory mapped
-                 registers;
-- interrupts   : should contain FIMC-LITE interrupt;
-- clocks       : FIMC LITE gate clock should be specified in this property.
-- clock-names  : should contain "flite" entry.
-
-Each FIMC device should have an alias in the aliases node, in the form of
-fimc-lite<n>, where <n> is an integer specifying the IP block instance.
diff --git a/Documentation/devicetree/bindings/media/exynos4-fimc-is.txt b/Documentation/devicetree/bindings/media/exynos4-fimc-is.txt
deleted file mode 100644 (file)
index 32ced99..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-Exynos4x12 SoC series Imaging Subsystem (FIMC-IS)
-
-The FIMC-IS is a subsystem for processing image signal from an image sensor.
-The Exynos4x12 SoC series FIMC-IS V1.5 comprises of a dedicated ARM Cortex-A5
-processor, ISP, DRC and FD IP blocks and peripheral devices such as UART, I2C
-and SPI bus controllers, PWM and ADC.
-
-fimc-is node
-------------
-
-Required properties:
-- compatible   : should be "samsung,exynos4212-fimc-is" for Exynos4212 and
-                 Exynos4412 SoCs;
-- reg          : physical base address and length of the registers set;
-- interrupts   : must contain two FIMC-IS interrupts, in order: ISP0, ISP1;
-- clocks       : list of clock specifiers, corresponding to entries in
-                 clock-names property;
-- clock-names  : must contain "ppmuispx", "ppmuispx", "lite0", "lite1"
-                 "mpll", "sysreg", "isp", "drc", "fd", "mcuisp", "gicisp",
-                 "pwm_isp", "mcuctl_isp", "uart", "ispdiv0", "ispdiv1",
-                 "mcuispdiv0", "mcuispdiv1", "aclk200", "div_aclk200",
-                 "aclk400mcuisp", "div_aclk400mcuisp" entries,
-                 matching entries in the clocks property.
-pmu subnode
------------
-
-Required properties:
- - reg : must contain PMU physical base address and size of the register set.
-
-The following are the FIMC-IS peripheral device nodes and can be specified
-either standalone or as the fimc-is node child nodes.
-
-i2c-isp (ISP I2C bus controller) nodes
-------------------------------------------
-
-Required properties:
-
-- compatible   : should be "samsung,exynos4212-i2c-isp" for Exynos4212 and
-                 Exynos4412 SoCs;
-- reg          : physical base address and length of the registers set;
-- clocks       : must contain gate clock specifier for this controller;
-- clock-names  : must contain "i2c_isp" entry.
-
-For the above nodes it is required to specify a pinctrl state named "default",
-according to the pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt.
-
-Device tree nodes of the image sensors' controlled directly by the FIMC-IS
-firmware must be child nodes of their corresponding ISP I2C bus controller node.
-The data link of these image sensors must be specified using the common video
-interfaces bindings, defined in video-interfaces.txt.
index 61072745b983b16dab7bed67bba05f3bd5fb2013..008c007ed702b6e3d9881d8bb95798d2541d9f45 100644 (file)
@@ -23,6 +23,9 @@ properties:
     description: autosuspend delay time in milliseconds
     $ref: /schemas/types.yaml#/definitions/uint32
 
+  wakeup-source:
+    description: IR receiver can wake-up the system.
+
 required:
   - compatible
   - gpios
index af8ada55b3f266ff706d2e0d75fe437224a881fa..4e69b6a7ffcc5f7e7bfb55723ef66575d30e722c 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/i2c/chrontel,ch7322.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/i2c/chrontel,ch7322.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Chrontel HDMI-CEC Controller
 
index 82d3d18c16a18c10c8e1ea535b10f053c2050f80..a0855d3b75771acb72907e218756d794657231c2 100644 (file)
@@ -38,7 +38,7 @@ properties:
   dongwoon,aac-mode:
     description:
       Indication of AAC mode select.
-    $ref: "/schemas/types.yaml#/definitions/uint32"
+    $ref: /schemas/types.yaml#/definitions/uint32
     enum:
       - 1    #  AAC2 mode(operation time# 0.48 x Tvib)
       - 2    #  AAC3 mode(operation time# 0.70 x Tvib)
@@ -50,7 +50,7 @@ properties:
     description:
       Number of AAC Timing count that controlled by one 6-bit period of
       vibration register AACT[5:0], the unit of which is 100 us.
-    $ref: "/schemas/types.yaml#/definitions/uint32"
+    $ref: /schemas/types.yaml#/definitions/uint32
     default: 0x20
     minimum: 0x00
     maximum: 0x3f
@@ -59,7 +59,7 @@ properties:
     description:
       Indication of VCM internal clock dividing rate select, as one multiple
       factor to calculate VCM ring periodic time Tvib.
-    $ref: "/schemas/types.yaml#/definitions/uint32"
+    $ref: /schemas/types.yaml#/definitions/uint32
     enum:
       - 0    #  Dividing Rate -  2
       - 1    #  Dividing Rate -  1
index 0c4213adbf6aaca6824d7ff58d0d0a8dc5386cc0..8df8591360474bf536f8a0f1588c98a8c95cd77b 100644 (file)
@@ -86,7 +86,7 @@ properties:
       is 100000 micro volts
 
   maxim,gpio-poc:
-    $ref: '/schemas/types.yaml#/definitions/uint32-array'
+    $ref: /schemas/types.yaml#/definitions/uint32-array
     minItems: 2
     maxItems: 2
     description: |
diff --git a/Documentation/devicetree/bindings/media/i2c/ov2685.txt b/Documentation/devicetree/bindings/media/i2c/ov2685.txt
deleted file mode 100644 (file)
index 625c4a8..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-* Omnivision OV2685 MIPI CSI-2 sensor
-
-Required Properties:
-- compatible: shall be "ovti,ov2685"
-- clocks: reference to the xvclk input clock
-- clock-names: shall be "xvclk"
-- avdd-supply: Analog voltage supply, 2.8 volts
-- dovdd-supply: Digital I/O voltage supply, 1.8 volts
-- dvdd-supply: Digital core voltage supply, 1.8 volts
-- reset-gpios: Low active reset gpio
-
-The device node shall contain one 'port' child node with an
-'endpoint' subnode for its digital output video port,
-in accordance with the video interface bindings defined in
-Documentation/devicetree/bindings/media/video-interfaces.txt.
-The endpoint optional property 'data-lanes' shall be "<1>".
-
-Example:
-&i2c7 {
-       ov2685: camera-sensor@3c {
-               compatible = "ovti,ov2685";
-               reg = <0x3c>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&clk_24m_cam>;
-
-               clocks = <&cru SCLK_TESTCLKOUT1>;
-               clock-names = "xvclk";
-
-               avdd-supply = <&pp2800_cam>;
-               dovdd-supply = <&pp1800>;
-               dvdd-supply = <&pp1800>;
-               reset-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
-
-               port {
-                       ucam_out: endpoint {
-                               remote-endpoint = <&mipi_in_ucam>;
-                               data-lanes = <1>;
-                       };
-               };
-       };
-};
index e17288d579812018a26b1fb79698158b68ebf316..57f5e48fd8e03c3c799ab5593a1b637e8bff0394 100644 (file)
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Omnivision OV8856 CMOS Sensor
 
 maintainers:
-  - Dongchun Zhu <dongchun.zhu@mediatek.com>
+  - Sakari Ailus <sakari.ailus@linux.intel.com>
 
 description: |-
   The Omnivision OV8856 is a high performance, 1/4-inch, 8 megapixel, CMOS
index 54df9d73dc86f39682bce33351e07e5e659749c3..763cebe03dc20d772f61710421d9eed212788ea9 100644 (file)
@@ -88,7 +88,7 @@ properties:
         properties:
           link-frequencies: true
           ovti,mipi-clock-voltage:
-            $ref: "/schemas/types.yaml#/definitions/uint32"
+            $ref: /schemas/types.yaml#/definitions/uint32
             description:
               Definition of MIPI clock voltage unit. This entry corresponds to
               the link speed defined by the 'link-frequencies' property.
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml
new file mode 100644 (file)
index 0000000..8b38931
--- /dev/null
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ovti,ov2685.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: OmniVision OV2685 Image Sensor
+
+maintainers:
+  - Shunqian Zheng <zhengsq@rock-chips.com>
+
+properties:
+  compatible:
+    const: ovti,ov2685
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: XVCLK clock
+
+  clock-names:
+    items:
+      - const: xvclk
+
+  dvdd-supply:
+    description: Digital Domain Power Supply
+
+  avdd-supply:
+    description: Analog Domain Power Supply
+
+  dovdd-supply:
+    description: I/O Domain Power Supply
+
+  reset-gpios:
+    maxItems: 1
+    description: Reset Pin GPIO Control (active low)
+
+  port:
+    description: MIPI CSI-2 transmitter port
+    $ref: /schemas/graph.yaml#/$defs/port-base
+    additionalProperties: false
+
+    properties:
+      endpoint:
+        $ref: /schemas/media/video-interfaces.yaml#
+        unevaluatedProperties: false
+
+        properties:
+          data-lanes:
+            maxItems: 2
+
+        required:
+          - data-lanes
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - dvdd-supply
+  - avdd-supply
+  - dovdd-supply
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3399-cru.h>
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        ov2685: camera-sensor@3c {
+            compatible = "ovti,ov2685";
+            reg = <0x3c>;
+            pinctrl-names = "default";
+            pinctrl-0 = <&clk_24m_cam>;
+
+            clocks = <&cru SCLK_TESTCLKOUT1>;
+            clock-names = "xvclk";
+
+            avdd-supply = <&pp2800_cam>;
+            dovdd-supply = <&pp1800>;
+            dvdd-supply = <&pp1800>;
+            reset-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+
+            port {
+                ucam_out: endpoint {
+                    remote-endpoint = <&mipi_in_ucam>;
+                    data-lanes = <1>;
+                };
+            };
+        };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/samsung,s5k5baf.yaml b/Documentation/devicetree/bindings/media/i2c/samsung,s5k5baf.yaml
new file mode 100644 (file)
index 0000000..c8f2955
--- /dev/null
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/samsung,s5k5baf.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S5K5BAF UXGA 1/5" 2M CMOS Image Sensor with embedded SoC ISP
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+properties:
+  compatible:
+    const: samsung,s5k5baf
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: mclk
+
+  clock-frequency:
+    default: 24000000
+    description: mclk clock frequency
+
+  rstn-gpios:
+    maxItems: 1
+    description: RSTN pin
+
+  stbyn-gpios:
+    maxItems: 1
+    description: STDBYN pin
+
+  vdda-supply:
+    description: Analog power supply 2.8V (2.6V to 3.0V)
+
+  vddio-supply:
+    description: I/O power supply 1.8V (1.65V to 1.95V) or 2.8V (2.5V to 3.1V)
+
+  vddreg-supply:
+    description:
+      Regulator input power supply 1.8V (1.7V to 1.9V) or 2.8V (2.6V to 3.0)
+
+  port:
+    $ref: /schemas/graph.yaml#/$defs/port-base
+    additionalProperties: false
+
+    properties:
+      endpoint:
+        $ref: /schemas/media/video-interfaces.yaml#
+        unevaluatedProperties: false
+
+        properties:
+          data-lanes:
+            items:
+              - const: 1
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+  - rstn-gpios
+  - stbyn-gpios
+  - vdda-supply
+  - vddio-supply
+  - vddreg-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        sensor@2d {
+            compatible = "samsung,s5k5baf";
+            reg = <0x2d>;
+            clocks = <&camera 0>;
+            clock-names = "mclk";
+            clock-frequency = <24000000>;
+            rstn-gpios = <&gpl2 1 GPIO_ACTIVE_LOW>;
+            stbyn-gpios = <&gpl2 0 GPIO_ACTIVE_LOW>;
+            vdda-supply = <&cam_io_en_reg>;
+            vddio-supply = <&vtcam_reg>;
+            vddreg-supply = <&vt_core_15v_reg>;
+
+            port {
+                endpoint {
+                    remote-endpoint = <&csis1_ep>;
+                    data-lanes = <1>;
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/media/i2c/samsung,s5k6a3.yaml b/Documentation/devicetree/bindings/media/i2c/samsung,s5k6a3.yaml
new file mode 100644 (file)
index 0000000..7e83a94
--- /dev/null
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/samsung,s5k6a3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S5K6A3(YX) raw image sensor
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+  S5K6A3(YX) is a raw image sensor with MIPI CSI-2 and CCP2 image data
+  interfaces and CCI (I2C compatible) control bus.
+
+properties:
+  compatible:
+    const: samsung,s5k6a3
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: extclk
+
+  clock-frequency:
+    default: 24000000
+    description: extclk clock frequency
+
+  gpios:
+    maxItems: 1
+    description: GPIO connected to the RESET pin
+
+  afvdd-supply:
+    description: AF (actuator) voltage supply
+
+  svdda-supply:
+    description: Core voltage supply
+
+  svddio-supply:
+    description: I/O voltage supply
+
+  port:
+    $ref: /schemas/graph.yaml#/$defs/port-base
+    additionalProperties: false
+
+    properties:
+      endpoint:
+        $ref: /schemas/media/video-interfaces.yaml#
+        unevaluatedProperties: false
+
+        properties:
+          data-lanes:
+            items:
+              - const: 1
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+  - gpios
+  - afvdd-supply
+  - svdda-supply
+  - svddio-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        sensor@10 {
+            compatible = "samsung,s5k6a3";
+            reg = <0x10>;
+            clock-frequency = <24000000>;
+            clocks = <&camera 1>;
+            clock-names = "extclk";
+            gpios = <&gpm1 6 GPIO_ACTIVE_LOW>;
+            afvdd-supply = <&ldo19_reg>;
+            svdda-supply = <&cam_io_reg>;
+            svddio-supply = <&ldo19_reg>;
+
+            port {
+                endpoint {
+                    remote-endpoint = <&csis1_ep>;
+                    data-lanes = <1>;
+                };
+            };
+        };
+    };
index 21377daae02687d7a13347699bd0de78665904bf..a531badc16c98bd94db63e53bd68493ba09d0c8e 100644 (file)
@@ -12,15 +12,26 @@ maintainers:
 
 description: |-
   The Sony IMX290 is a 1/2.8-Inch CMOS Solid-state image sensor with Square
-  Pixel for Color Cameras. It is programmable through I2C and 4-wire
-  interfaces. The sensor output is available via CMOS logic parallel SDR
-  output, Low voltage LVDS DDR output and CSI-2 serial data output. The CSI-2
-  bus is the default. No bindings have been defined for the other busses.
+  Pixel, available in either mono or colour variants. It is programmable
+  through I2C and 4-wire interfaces.
+
+  The sensor output is available via CMOS logic parallel SDR output, Low voltage
+  LVDS DDR output and CSI-2 serial data output. The CSI-2 bus is the default.
+  No bindings have been defined for the other busses.
+
+  imx290lqr is the full model identifier for the colour variant. "sony,imx290"
+  is treated the same as this as it was the original compatible string.
+  imx290llr is the mono version of the sensor.
 
 properties:
   compatible:
-    enum:
-      - sony,imx290
+    oneOf:
+      - enum:
+          - sony,imx290lqr # Colour
+          - sony,imx290llr # Monochrome
+          - sony,imx327lqr # Colour
+      - const: sony,imx290
+        deprecated: true
 
   reg:
     maxItems: 1
@@ -101,7 +112,7 @@ examples:
         #size-cells = <0>;
 
         imx290: camera-sensor@1a {
-            compatible = "sony,imx290";
+            compatible = "sony,imx290lqr";
             reg = <0x1a>;
 
             pinctrl-names = "default";
index f5055b9db693625881853ea168a63d1493500b1a..09533496b20c528c6491681b536df7458914e3a5 100644 (file)
@@ -82,7 +82,7 @@ examples:
                 imx334: endpoint {
                     remote-endpoint = <&cam>;
                     data-lanes = <1 2 3 4>;
-                    link-frequencies = /bits/ 64 <891000000>;
+                    link-frequencies = /bits/ 64 <891000000 445500000>;
                 };
             };
         };
index 9cfc0c7d23e0688937f5e4f53a4688c2e595eaba..7032c7e15039004f6a0e7576c27592e067ec8fc5 100644 (file)
@@ -27,7 +27,7 @@ properties:
     maxItems: 1
 
   mediatek,gce-client-reg:
-    $ref: '/schemas/types.yaml#/definitions/phandle-array'
+    $ref: /schemas/types.yaml#/definitions/phandle-array
     items:
       items:
         - description: phandle of GCE
index c4f20acdc1f8cf8fe4c14d130e1f2b49b2db2d81..dca9b0c5e1063fdb728ed1c555dd5fdafa67d39c 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/mediatek,vcodec-subdev-decoder.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/mediatek,vcodec-subdev-decoder.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Mediatek Video Decode Accelerator With Multi Hardware
 
@@ -61,7 +61,10 @@ properties:
       - mediatek,mt8195-vcodec-dec
 
   reg:
-    maxItems: 1
+    minItems: 1
+    items:
+      - description: VDEC_SYS register space
+      - description: VDEC_RACING_CTRL register space
 
   iommus:
     minItems: 1
@@ -76,11 +79,6 @@ properties:
       The node of system control processor (SCP), using
       the remoteproc & rpmsg framework.
 
-  dma-ranges:
-    maxItems: 1
-    description: |
-      Describes the physical address space of IOMMU maps to memory.
-
   "#address-cells":
     const: 2
 
@@ -91,17 +89,19 @@ properties:
 
 # Required child node:
 patternProperties:
-  '^vcodec-lat@[0-9a-f]+$':
+  '^video-codec@[0-9a-f]+$':
     type: object
 
     properties:
       compatible:
         enum:
+          - mediatek,mtk-vcodec-core
           - mediatek,mtk-vcodec-lat
           - mediatek,mtk-vcodec-lat-soc
 
       reg:
         maxItems: 1
+        description: VDEC_MISC register space
 
       interrupts:
         maxItems: 1
@@ -114,68 +114,13 @@ patternProperties:
           Refer to bindings/iommu/mediatek,iommu.yaml.
 
       clocks:
+        minItems: 4
         maxItems: 5
 
       clock-names:
-        items:
-          - const: sel
-          - const: soc-vdec
-          - const: soc-lat
-          - const: vdec
-          - const: top
-
-      assigned-clocks:
-        maxItems: 1
-
-      assigned-clock-parents:
-        maxItems: 1
-
-      power-domains:
-        maxItems: 1
-
-    required:
-      - compatible
-      - reg
-      - iommus
-      - clocks
-      - clock-names
-      - assigned-clocks
-      - assigned-clock-parents
-      - power-domains
-
-    additionalProperties: false
-
-  '^vcodec-core@[0-9a-f]+$':
-    type: object
-
-    properties:
-      compatible:
-        const: mediatek,mtk-vcodec-core
-
-      reg:
-        maxItems: 1
-
-      interrupts:
-        maxItems: 1
-
-      iommus:
-        minItems: 1
-        maxItems: 32
-        description: |
-          List of the hardware port in respective IOMMU block for current Socs.
-          Refer to bindings/iommu/mediatek,iommu.yaml.
-
-      clocks:
+        minItems: 4
         maxItems: 5
 
-      clock-names:
-        items:
-          - const: sel
-          - const: soc-vdec
-          - const: soc-lat
-          - const: vdec
-          - const: top
-
       assigned-clocks:
         maxItems: 1
 
@@ -188,7 +133,6 @@ patternProperties:
     required:
       - compatible
       - reg
-      - interrupts
       - iommus
       - clocks
       - clock-names
@@ -203,7 +147,6 @@ required:
   - reg
   - iommus
   - mediatek,scp
-  - dma-ranges
   - ranges
 
 if:
@@ -211,12 +154,45 @@ if:
     compatible:
       contains:
         enum:
+          - mediatek,mtk-vcodec-core
           - mediatek,mtk-vcodec-lat
 
 then:
   required:
     - interrupts
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - mediatek,mt8192-vcodec-dec
+    then:
+      properties:
+        clock-names:
+          items:
+            - const: sel
+            - const: soc-vdec
+            - const: soc-lat
+            - const: vdec
+            - const: top
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - mediatek,mt8195-vcodec-dec
+    then:
+      properties:
+        clock-names:
+          items:
+            - const: sel
+            - const: vdec
+            - const: lat
+            - const: top
+
 additionalProperties: false
 
 examples:
@@ -236,12 +212,11 @@ examples:
             compatible = "mediatek,mt8192-vcodec-dec";
             mediatek,scp = <&scp>;
             iommus = <&iommu0 M4U_PORT_L4_VDEC_MC_EXT>;
-            dma-ranges = <0x1 0x0 0x0 0x40000000 0x0 0xfff00000>;
             #address-cells = <2>;
             #size-cells = <2>;
             ranges = <0 0 0 0x16000000 0 0x40000>;
             reg = <0 0x16000000 0 0x1000>;             /* VDEC_SYS */
-            vcodec-lat@10000 {
+            video-codec@10000 {
                 compatible = "mediatek,mtk-vcodec-lat";
                 reg = <0 0x10000 0 0x800>;
                 interrupts = <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH 0>;
@@ -264,7 +239,7 @@ examples:
                 power-domains = <&spm MT8192_POWER_DOMAIN_VDEC>;
             };
 
-            vcodec-core@25000 {
+            video-codec@25000 {
                 compatible = "mediatek,mtk-vcodec-core";
                 reg = <0 0x25000 0 0x1000>;
                 interrupts = <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH 0>;
diff --git a/Documentation/devicetree/bindings/media/meson-ir.txt b/Documentation/devicetree/bindings/media/meson-ir.txt
deleted file mode 100644 (file)
index efd9d29..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-* Amlogic Meson IR remote control receiver
-
-Required properties:
- - compatible  : depending on the platform this should be one of:
-                 - "amlogic,meson6-ir"
-                 - "amlogic,meson8b-ir"
-                 - "amlogic,meson-gxbb-ir"
- - reg         : physical base address and length of the device registers
- - interrupts  : a single specifier for the interrupt from the device
-
-Optional properties:
- - linux,rc-map-name:  see rc.txt file in the same directory.
-
-Example:
-
-       ir-receiver@c8100480 {
-               compatible= "amlogic,meson6-ir";
-               reg = <0xc8100480 0x20>;
-               interrupts = <0 15 1>;
-       };
index 4b77103ca9132eae5c132ef21f62fa924534bb3b..59b805ca47c57aa407cbca048b8c85f53aaf9d67 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/microchip,sama5d4-vdec.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/microchip,sama5d4-vdec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Hantro G1 VPU codec implemented on Microchip SAMA5D4 SoCs
 
diff --git a/Documentation/devicetree/bindings/media/nxp,imx8-isi.yaml b/Documentation/devicetree/bindings/media/nxp,imx8-isi.yaml
new file mode 100644 (file)
index 0000000..6038b9b
--- /dev/null
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/nxp,imx8-isi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: i.MX8 Image Sensing Interface
+
+maintainers:
+  - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+description: |
+  The Image Sensing Interface (ISI) combines image processing pipelines with
+  DMA engines to process and capture frames originating from a variety of
+  sources. The inputs to the ISI go through Pixel Link interfaces, and their
+  number and nature is SoC-dependent. They cover both capture interfaces (MIPI
+  CSI-2 RX, HDMI RX, ...) and display engine outputs for writeback support.
+
+properties:
+  compatible:
+    enum:
+      - fsl,imx8mn-isi
+      - fsl,imx8mp-isi
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: The AXI clock
+      - description: The APB clock
+      # TODO: Check if the per-channel ipg_proc_clk clocks need to be specified
+      # as well, in case some SoCs have the ability to control them separately.
+      # This may be the case of the i.MX8[DQ]X(P)
+
+  clock-names:
+    items:
+      - const: axi
+      - const: apb
+
+  fsl,blk-ctrl:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      A phandle referencing the block control that contains the CSIS to ISI
+      gasket.
+
+  interrupts:
+    description: Processing pipeline interrupts, one per pipeline
+    minItems: 1
+    maxItems: 2
+
+  power-domains:
+    maxItems: 1
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+    description: |
+      Ports represent the Pixel Link inputs to the ISI. Their number and
+      assignment are model-dependent. Each port shall have a single endpoint.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - fsl,blk-ctrl
+  - ports
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: fsl,imx8mn-isi
+    then:
+      properties:
+        interrupts:
+          maxItems: 1
+        ports:
+          properties:
+            port@0:
+              description: MIPI CSI-2 RX
+          required:
+            - port@0
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: fsl,imx8mp-isi
+    then:
+      properties:
+        interrupts:
+          maxItems: 2
+        ports:
+          properties:
+            port@0:
+              description: MIPI CSI-2 RX 0
+            port@1:
+              description: MIPI CSI-2 RX 1
+          required:
+            - port@0
+            - port@1
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/imx8mn-clock.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/power/imx8mn-power.h>
+
+    isi@32e20000 {
+        compatible = "fsl,imx8mn-isi";
+        reg = <0x32e20000 0x100>;
+        interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clk IMX8MN_CLK_DISP_AXI_ROOT>,
+                 <&clk IMX8MN_CLK_DISP_APB_ROOT>;
+        clock-names = "axi", "apb";
+        fsl,blk-ctrl = <&disp_blk_ctrl>;
+        power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_ISI>;
+
+        ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            port@0 {
+                reg = <0>;
+                isi_in: endpoint {
+                    remote-endpoint = <&mipi_csi_out>;
+                };
+            };
+        };
+    };
+
+  - |
+    #include <dt-bindings/clock/imx8mp-clock.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    isi@32e00000 {
+        compatible = "fsl,imx8mp-isi";
+        reg = <0x32e00000 0x4000>;
+        interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>,
+                 <&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
+        clock-names = "axi", "apb";
+        fsl,blk-ctrl = <&media_blk_ctrl>;
+        power-domains = <&mediamix_pd>;
+
+        ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            port@0 {
+                reg = <0>;
+                isi_in_0: endpoint {
+                    remote-endpoint = <&mipi_csi_0_out>;
+                };
+            };
+
+            port@1 {
+                reg = <1>;
+                isi_in_1: endpoint {
+                    remote-endpoint = <&mipi_csi_1_out>;
+                };
+            };
+        };
+    };
+...
index 7dc13a4b180501f1c202b951afc202ca9a580a1a..3d58f02b0c5dcba390e4cf7dee21daafcb62fdd7 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/nxp,imx8mq-vpu.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/nxp,imx8mq-vpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Hantro G1/G2 VPU codecs implemented on i.MX8M SoCs
 
index 12ec3e1ea869c08d528f7a27189c8a22ca0f1fa5..eb1499912c58415093371dded1dc12c4103c94fd 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,msm8916-camss.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,msm8916-camss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Qualcomm CAMSS ISP
 
index 2abb7d21c0d1d49814eaba46feafa14c72d07e52..2350bf4b370ebc06af7f6e1322b7206cd4c0b9a1 100644 (file)
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,msm8916-venus.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,msm8916-venus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Qualcomm Venus video encode and decode accelerators
+title: Qualcomm MSM8916 Venus video encode and decode accelerators
 
 maintainers:
   - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: |
   The Venus IP is a video encode and decode accelerator present
   on Qualcomm platforms
 
+allOf:
+  - $ref: qcom,venus-common.yaml#
+
 properties:
   compatible:
     const: qcom,msm8916-venus
 
-  reg:
-    maxItems: 1
-
-  interrupts:
-    maxItems: 1
-
   power-domains:
     maxItems: 1
 
@@ -39,9 +35,6 @@ properties:
   iommus:
     maxItems: 1
 
-  memory-region:
-    maxItems: 1
-
   video-decoder:
     type: object
 
@@ -66,57 +59,36 @@ properties:
 
     additionalProperties: false
 
-  video-firmware:
-    type: object
-    additionalProperties: false
-
-    description: |
-      Firmware subnode is needed when the platform does not
-      have TrustZone.
-
-    properties:
-      iommus:
-        maxItems: 1
-
-    required:
-      - iommus
-
 required:
   - compatible
-  - reg
-  - interrupts
-  - power-domains
-  - clocks
-  - clock-names
   - iommus
-  - memory-region
   - video-decoder
   - video-encoder
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-        #include <dt-bindings/interrupt-controller/arm-gic.h>
-        #include <dt-bindings/clock/qcom,gcc-msm8916.h>
-
-        video-codec@1d00000 {
-                compatible = "qcom,msm8916-venus";
-                reg = <0x01d00000 0xff000>;
-                interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
-                clocks = <&gcc GCC_VENUS0_VCODEC0_CLK>,
-                        <&gcc GCC_VENUS0_AHB_CLK>,
-                        <&gcc GCC_VENUS0_AXI_CLK>;
-                clock-names = "core", "iface", "bus";
-                power-domains = <&gcc VENUS_GDSC>;
-                iommus = <&apps_iommu 5>;
-                memory-region = <&venus_mem>;
-
-                video-decoder {
-                        compatible = "venus-decoder";
-                };
-
-                video-encoder {
-                        compatible = "venus-encoder";
-                };
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/qcom,gcc-msm8916.h>
+
+    video-codec@1d00000 {
+        compatible = "qcom,msm8916-venus";
+        reg = <0x01d00000 0xff000>;
+        interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&gcc GCC_VENUS0_VCODEC0_CLK>,
+                 <&gcc GCC_VENUS0_AHB_CLK>,
+                 <&gcc GCC_VENUS0_AXI_CLK>;
+        clock-names = "core", "iface", "bus";
+        power-domains = <&gcc VENUS_GDSC>;
+        iommus = <&apps_iommu 5>;
+        memory-region = <&venus_mem>;
+
+        video-decoder {
+            compatible = "venus-decoder";
+        };
+
+        video-encoder {
+            compatible = "venus-encoder";
         };
+    };
index 6aeb3d6d02d56b611b13abda0ecfb768701fcda4..8a10aa1cafc50308d92f9d159651d422542d4565 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,msm8996-camss.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,msm8996-camss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Qualcomm CAMSS ISP
 
index 29d0cb6c6ebe0423db86a9fbef74f61b4b22d756..3a4d817e544e2e3b4ebbe6368c6f44c6d0b3f4e3 100644 (file)
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,msm8996-venus.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,msm8996-venus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Qualcomm Venus video encode and decode accelerators
+title: Qualcomm MSM8996 Venus video encode and decode accelerators
 
 maintainers:
   - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: |
   The Venus IP is a video encode and decode accelerator present
   on Qualcomm platforms
 
+allOf:
+  - $ref: qcom,venus-common.yaml#
+
 properties:
   compatible:
     const: qcom,msm8996-venus
 
-  reg:
-    maxItems: 1
-
-  interrupts:
-    maxItems: 1
-
   power-domains:
     maxItems: 1
 
@@ -37,12 +33,17 @@ properties:
       - const: bus
       - const: mbus
 
+  interconnects:
+    maxItems: 2
+
+  interconnect-names:
+    items:
+      - const: video-mem
+      - const: cpu-cfg
+
   iommus:
     maxItems: 20
 
-  memory-region:
-    maxItems: 1
-
   video-decoder:
     type: object
 
@@ -93,83 +94,62 @@ properties:
 
     additionalProperties: false
 
-  video-firmware:
-    type: object
-    additionalProperties: false
-
-    description: |
-      Firmware subnode is needed when the platform does not
-      have TrustZone.
-
-    properties:
-      iommus:
-        maxItems: 1
-
-    required:
-      - iommus
-
 required:
   - compatible
-  - reg
-  - interrupts
-  - power-domains
-  - clocks
-  - clock-names
   - iommus
-  - memory-region
   - video-decoder
   - video-encoder
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-        #include <dt-bindings/interrupt-controller/arm-gic.h>
-        #include <dt-bindings/clock/qcom,mmcc-msm8996.h>
-
-        video-codec@c00000 {
-                compatible = "qcom,msm8996-venus";
-                reg = <0x00c00000 0xff000>;
-                interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
-                clocks = <&mmcc VIDEO_CORE_CLK>,
-                         <&mmcc VIDEO_AHB_CLK>,
-                         <&mmcc VIDEO_AXI_CLK>,
-                         <&mmcc VIDEO_MAXI_CLK>;
-                clock-names = "core", "iface", "bus", "mbus";
-                power-domains = <&mmcc VENUS_GDSC>;
-                iommus =  <&venus_smmu 0x00>,
-                          <&venus_smmu 0x01>,
-                          <&venus_smmu 0x0a>,
-                          <&venus_smmu 0x07>,
-                          <&venus_smmu 0x0e>,
-                          <&venus_smmu 0x0f>,
-                          <&venus_smmu 0x08>,
-                          <&venus_smmu 0x09>,
-                          <&venus_smmu 0x0b>,
-                          <&venus_smmu 0x0c>,
-                          <&venus_smmu 0x0d>,
-                          <&venus_smmu 0x10>,
-                          <&venus_smmu 0x11>,
-                          <&venus_smmu 0x21>,
-                          <&venus_smmu 0x28>,
-                          <&venus_smmu 0x29>,
-                          <&venus_smmu 0x2b>,
-                          <&venus_smmu 0x2c>,
-                          <&venus_smmu 0x2d>,
-                          <&venus_smmu 0x31>;
-                memory-region = <&venus_mem>;
-
-                video-decoder {
-                        compatible = "venus-decoder";
-                        clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
-                        clock-names = "core";
-                        power-domains = <&mmcc VENUS_CORE0_GDSC>;
-                };
-
-                video-encoder {
-                        compatible = "venus-encoder";
-                        clocks = <&mmcc VIDEO_SUBCORE1_CLK>;
-                        clock-names = "core";
-                        power-domains = <&mmcc VENUS_CORE1_GDSC>;
-                };
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/qcom,mmcc-msm8996.h>
+
+    video-codec@c00000 {
+        compatible = "qcom,msm8996-venus";
+        reg = <0x00c00000 0xff000>;
+        interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&mmcc VIDEO_CORE_CLK>,
+                 <&mmcc VIDEO_AHB_CLK>,
+                 <&mmcc VIDEO_AXI_CLK>,
+                 <&mmcc VIDEO_MAXI_CLK>;
+        clock-names = "core", "iface", "bus", "mbus";
+        power-domains = <&mmcc VENUS_GDSC>;
+        iommus =  <&venus_smmu 0x00>,
+                  <&venus_smmu 0x01>,
+                  <&venus_smmu 0x0a>,
+                  <&venus_smmu 0x07>,
+                  <&venus_smmu 0x0e>,
+                  <&venus_smmu 0x0f>,
+                  <&venus_smmu 0x08>,
+                  <&venus_smmu 0x09>,
+                  <&venus_smmu 0x0b>,
+                  <&venus_smmu 0x0c>,
+                  <&venus_smmu 0x0d>,
+                  <&venus_smmu 0x10>,
+                  <&venus_smmu 0x11>,
+                  <&venus_smmu 0x21>,
+                  <&venus_smmu 0x28>,
+                  <&venus_smmu 0x29>,
+                  <&venus_smmu 0x2b>,
+                  <&venus_smmu 0x2c>,
+                  <&venus_smmu 0x2d>,
+                  <&venus_smmu 0x31>;
+        memory-region = <&venus_mem>;
+
+        video-decoder {
+            compatible = "venus-decoder";
+            clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
+            clock-names = "core";
+            power-domains = <&mmcc VENUS_CORE0_GDSC>;
+        };
+
+        video-encoder {
+            compatible = "venus-encoder";
+            clocks = <&mmcc VIDEO_SUBCORE1_CLK>;
+            clock-names = "core";
+            power-domains = <&mmcc VENUS_CORE1_GDSC>;
         };
+    };
index 42ee3f06c6bec844aa414e3e8a821e3e8377563c..5cec1d077cda77817f6d876109defcb0abbfeb2c 100644 (file)
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,sc7180-venus.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,sc7180-venus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Qualcomm Venus video encode and decode accelerators
+title: Qualcomm SC7180 Venus video encode and decode accelerators
 
 maintainers:
   - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: |
   The Venus IP is a video encode and decode accelerator present
   on Qualcomm platforms
 
+allOf:
+  - $ref: qcom,venus-common.yaml#
+
 properties:
   compatible:
     const: qcom,sc7180-venus
 
-  reg:
-    maxItems: 1
-
-  interrupts:
-    maxItems: 1
-
   power-domains:
     minItems: 2
     maxItems: 3
@@ -60,6 +56,10 @@ properties:
       - const: video-mem
       - const: cpu-cfg
 
+  operating-points-v2: true
+  opp-table:
+    type: object
+
   video-decoder:
     type: object
 
@@ -84,63 +84,42 @@ properties:
 
     additionalProperties: false
 
-  video-firmware:
-    type: object
-    additionalProperties: false
-
-    description: |
-      Firmware subnode is needed when the platform does not
-      have TrustZone.
-
-    properties:
-      iommus:
-        maxItems: 1
-
-    required:
-      - iommus
-
 required:
   - compatible
-  - reg
-  - interrupts
-  - power-domains
   - power-domain-names
-  - clocks
-  - clock-names
   - iommus
-  - memory-region
   - video-decoder
   - video-encoder
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-        #include <dt-bindings/interrupt-controller/arm-gic.h>
-        #include <dt-bindings/clock/qcom,videocc-sc7180.h>
-
-        venus: video-codec@aa00000 {
-                compatible = "qcom,sc7180-venus";
-                reg = <0x0aa00000 0xff000>;
-                interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
-                power-domains = <&videocc VENUS_GDSC>,
-                                <&videocc VCODEC0_GDSC>;
-                power-domain-names = "venus", "vcodec0";
-                clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
-                         <&videocc VIDEO_CC_VENUS_AHB_CLK>,
-                         <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,
-                         <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
-                         <&videocc VIDEO_CC_VCODEC0_AXI_CLK>;
-                clock-names = "core", "iface", "bus",
-                              "vcodec0_core", "vcodec0_bus";
-                iommus = <&apps_smmu 0x0c00 0x60>;
-                memory-region = <&venus_mem>;
-
-                video-decoder {
-                        compatible = "venus-decoder";
-                };
-
-                video-encoder {
-                        compatible = "venus-encoder";
-                };
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/qcom,videocc-sc7180.h>
+
+    venus: video-codec@aa00000 {
+        compatible = "qcom,sc7180-venus";
+        reg = <0x0aa00000 0xff000>;
+        interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+        power-domains = <&videocc VENUS_GDSC>,
+                        <&videocc VCODEC0_GDSC>;
+        power-domain-names = "venus", "vcodec0";
+        clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
+                 <&videocc VIDEO_CC_VENUS_AHB_CLK>,
+                 <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,
+                 <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
+                 <&videocc VIDEO_CC_VCODEC0_AXI_CLK>;
+        clock-names = "core", "iface", "bus",
+                      "vcodec0_core", "vcodec0_bus";
+        iommus = <&apps_smmu 0x0c00 0x60>;
+        memory-region = <&venus_mem>;
+
+        video-decoder {
+            compatible = "venus-decoder";
+        };
+
+        video-encoder {
+            compatible = "venus-encoder";
         };
+    };
index cf361dd9de08614b885a27347682749b27972e86..8f9b6433aeb8c130b8895916d3a53c9a836a3eac 100644 (file)
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,sc7280-venus.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,sc7280-venus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Qualcomm Venus video encode and decode accelerators
+title: Qualcomm SC7280 Venus video encode and decode accelerators
 
 maintainers:
   - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: |
   The Venus Iris2 IP is a video encode and decode accelerator present
   on Qualcomm platforms
 
+allOf:
+  - $ref: qcom,venus-common.yaml#
+
 properties:
   compatible:
     const: qcom,sc7280-venus
 
-  reg:
-    maxItems: 1
-
-  interrupts:
-    maxItems: 1
-
   power-domains:
     minItems: 2
     maxItems: 3
@@ -49,9 +45,6 @@ properties:
   iommus:
     maxItems: 2
 
-  memory-region:
-    maxItems: 1
-
   interconnects:
     maxItems: 2
 
@@ -60,6 +53,10 @@ properties:
       - const: cpu-cfg
       - const: video-mem
 
+  operating-points-v2: true
+  opp-table:
+    type: object
+
   video-decoder:
     type: object
 
@@ -84,79 +81,58 @@ properties:
 
     additionalProperties: false
 
-  video-firmware:
-    type: object
-    additionalProperties: false
-
-    description: |
-      Firmware subnode is needed when the platform does not
-      have TrustZone.
-
-    properties:
-      iommus:
-        maxItems: 1
-
-    required:
-      - iommus
-
 required:
   - compatible
-  - reg
-  - interrupts
-  - power-domains
   - power-domain-names
-  - clocks
-  - clock-names
   - iommus
-  - memory-region
   - video-decoder
   - video-encoder
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-        #include <dt-bindings/interrupt-controller/arm-gic.h>
-        #include <dt-bindings/clock/qcom,videocc-sc7280.h>
-        #include <dt-bindings/interconnect/qcom,sc7280.h>
-        #include <dt-bindings/power/qcom-rpmpd.h>
-
-        venus: video-codec@aa00000 {
-                compatible = "qcom,sc7280-venus";
-                reg = <0x0aa00000 0xd0600>;
-                interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
-
-                clocks = <&videocc VIDEO_CC_MVSC_CORE_CLK>,
-                         <&videocc VIDEO_CC_MVSC_CTL_AXI_CLK>,
-                         <&videocc VIDEO_CC_VENUS_AHB_CLK>,
-                         <&videocc VIDEO_CC_MVS0_CORE_CLK>,
-                         <&videocc VIDEO_CC_MVS0_AXI_CLK>;
-                clock-names = "core", "bus", "iface",
-                              "vcodec_core", "vcodec_bus";
-
-                power-domains = <&videocc MVSC_GDSC>,
-                                <&videocc MVS0_GDSC>,
-                                <&rpmhpd SC7280_CX>;
-                power-domain-names = "venus", "vcodec0", "cx";
-
-                interconnects = <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_VENUS_CFG 0>,
-                                <&mmss_noc MASTER_VIDEO_P0 0 &mc_virt SLAVE_EBI1 0>;
-                interconnect-names = "cpu-cfg", "video-mem";
-
-                iommus = <&apps_smmu 0x2180 0x20>,
-                         <&apps_smmu 0x2184 0x20>;
-
-                memory-region = <&video_mem>;
-
-                video-decoder {
-                        compatible = "venus-decoder";
-                };
-
-                video-encoder {
-                        compatible = "venus-encoder";
-                };
-
-                video-firmware {
-                        iommus = <&apps_smmu 0x21a2 0x0>;
-                };
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/qcom,videocc-sc7280.h>
+    #include <dt-bindings/interconnect/qcom,sc7280.h>
+    #include <dt-bindings/power/qcom-rpmpd.h>
+
+    venus: video-codec@aa00000 {
+        compatible = "qcom,sc7280-venus";
+        reg = <0x0aa00000 0xd0600>;
+        interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+
+        clocks = <&videocc VIDEO_CC_MVSC_CORE_CLK>,
+                 <&videocc VIDEO_CC_MVSC_CTL_AXI_CLK>,
+                 <&videocc VIDEO_CC_VENUS_AHB_CLK>,
+                 <&videocc VIDEO_CC_MVS0_CORE_CLK>,
+                 <&videocc VIDEO_CC_MVS0_AXI_CLK>;
+        clock-names = "core", "bus", "iface",
+                      "vcodec_core", "vcodec_bus";
+
+        power-domains = <&videocc MVSC_GDSC>,
+                        <&videocc MVS0_GDSC>,
+                        <&rpmhpd SC7280_CX>;
+        power-domain-names = "venus", "vcodec0", "cx";
+
+        interconnects = <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_VENUS_CFG 0>,
+                        <&mmss_noc MASTER_VIDEO_P0 0 &mc_virt SLAVE_EBI1 0>;
+        interconnect-names = "cpu-cfg", "video-mem";
+
+        iommus = <&apps_smmu 0x2180 0x20>,
+                 <&apps_smmu 0x2184 0x20>;
+
+        memory-region = <&video_mem>;
+
+        video-decoder {
+            compatible = "venus-decoder";
+        };
+
+        video-encoder {
+            compatible = "venus-encoder";
+        };
+
+        video-firmware {
+            iommus = <&apps_smmu 0x21a2 0x0>;
         };
+    };
index b28c8e17f158166bd571c4ed8c755a16e58c2fe6..0a109e126064d8e105cea9edee9fca650b393554 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,sdm660-camss.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,sdm660-camss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Qualcomm CAMSS ISP
 
index 45e3f58f52bde49108d0c468561714b29b33cb44..a51835b220452efec7439c10eb253b08d2172209 100644 (file)
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,sdm660-venus.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,sdm660-venus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Qualcomm Venus video encode and decode accelerators
+title: Qualcomm SDM660 Venus video encode and decode accelerators
 
 maintainers:
   - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -15,13 +14,13 @@ description: |
   The Venus IP is a video encode and decode accelerator present
   on Qualcomm platforms
 
+allOf:
+  - $ref: qcom,venus-common.yaml#
+
 properties:
   compatible:
     const: qcom,sdm660-venus
 
-  reg:
-    maxItems: 1
-
   clocks:
     maxItems: 4
 
@@ -40,15 +39,9 @@ properties:
       - const: cpu-cfg
       - const: video-mem
 
-  interrupts:
-    maxItems: 1
-
   iommus:
     maxItems: 20
 
-  memory-region:
-    maxItems: 1
-
   power-domains:
     maxItems: 1
 
@@ -102,86 +95,65 @@ properties:
 
     additionalProperties: false
 
-  video-firmware:
-    type: object
-    additionalProperties: false
-
-    description: |
-      Firmware subnode is needed when the platform does not
-      have TrustZone.
-
-    properties:
-      iommus:
-        maxItems: 1
-
-    required:
-      - iommus
-
 required:
   - compatible
-  - reg
-  - clocks
-  - clock-names
-  - interrupts
   - iommus
-  - memory-region
-  - power-domains
   - video-decoder
   - video-encoder
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-        #include <dt-bindings/clock/qcom,mmcc-sdm660.h>
-        #include <dt-bindings/interrupt-controller/arm-gic.h>
-
-        video-codec@cc00000 {
-                compatible = "qcom,sdm660-venus";
-                reg = <0x0cc00000 0xff000>;
-                clocks = <&mmcc VIDEO_CORE_CLK>,
-                         <&mmcc VIDEO_AHB_CLK>,
-                         <&mmcc VIDEO_AXI_CLK>,
-                         <&mmcc THROTTLE_VIDEO_AXI_CLK>;
-                clock-names = "core", "iface", "bus", "bus_throttle";
-                interconnects = <&gnoc 0 &mnoc 13>,
-                                <&mnoc 4 &bimc 5>;
-                interconnect-names = "cpu-cfg", "video-mem";
-                interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
-                iommus = <&mmss_smmu 0x400>,
-                         <&mmss_smmu 0x401>,
-                         <&mmss_smmu 0x40a>,
-                         <&mmss_smmu 0x407>,
-                         <&mmss_smmu 0x40e>,
-                         <&mmss_smmu 0x40f>,
-                         <&mmss_smmu 0x408>,
-                         <&mmss_smmu 0x409>,
-                         <&mmss_smmu 0x40b>,
-                         <&mmss_smmu 0x40c>,
-                         <&mmss_smmu 0x40d>,
-                         <&mmss_smmu 0x410>,
-                         <&mmss_smmu 0x421>,
-                         <&mmss_smmu 0x428>,
-                         <&mmss_smmu 0x429>,
-                         <&mmss_smmu 0x42b>,
-                         <&mmss_smmu 0x42c>,
-                         <&mmss_smmu 0x42d>,
-                         <&mmss_smmu 0x411>,
-                         <&mmss_smmu 0x431>;
-                memory-region = <&venus_region>;
-                power-domains = <&mmcc VENUS_GDSC>;
-
-                video-decoder {
-                        compatible = "venus-decoder";
-                        clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
-                        clock-names = "vcodec0_core";
-                        power-domains = <&mmcc VENUS_CORE0_GDSC>;
-                };
-
-                video-encoder {
-                        compatible = "venus-encoder";
-                        clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
-                        clock-names = "vcodec0_core";
-                        power-domains = <&mmcc VENUS_CORE0_GDSC>;
-                };
+    #include <dt-bindings/clock/qcom,mmcc-sdm660.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    video-codec@cc00000 {
+        compatible = "qcom,sdm660-venus";
+        reg = <0x0cc00000 0xff000>;
+        clocks = <&mmcc VIDEO_CORE_CLK>,
+                 <&mmcc VIDEO_AHB_CLK>,
+                 <&mmcc VIDEO_AXI_CLK>,
+                 <&mmcc THROTTLE_VIDEO_AXI_CLK>;
+        clock-names = "core", "iface", "bus", "bus_throttle";
+        interconnects = <&gnoc 0 &mnoc 13>,
+                        <&mnoc 4 &bimc 5>;
+        interconnect-names = "cpu-cfg", "video-mem";
+        interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+        iommus = <&mmss_smmu 0x400>,
+                 <&mmss_smmu 0x401>,
+                 <&mmss_smmu 0x40a>,
+                 <&mmss_smmu 0x407>,
+                 <&mmss_smmu 0x40e>,
+                 <&mmss_smmu 0x40f>,
+                 <&mmss_smmu 0x408>,
+                 <&mmss_smmu 0x409>,
+                 <&mmss_smmu 0x40b>,
+                 <&mmss_smmu 0x40c>,
+                 <&mmss_smmu 0x40d>,
+                 <&mmss_smmu 0x410>,
+                 <&mmss_smmu 0x421>,
+                 <&mmss_smmu 0x428>,
+                 <&mmss_smmu 0x429>,
+                 <&mmss_smmu 0x42b>,
+                 <&mmss_smmu 0x42c>,
+                 <&mmss_smmu 0x42d>,
+                 <&mmss_smmu 0x411>,
+                 <&mmss_smmu 0x431>;
+        memory-region = <&venus_region>;
+        power-domains = <&mmcc VENUS_GDSC>;
+
+        video-decoder {
+            compatible = "venus-decoder";
+            clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
+            clock-names = "vcodec0_core";
+            power-domains = <&mmcc VENUS_CORE0_GDSC>;
+        };
+
+        video-encoder {
+            compatible = "venus-encoder";
+            clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
+            clock-names = "vcodec0_core";
+            power-domains = <&mmcc VENUS_CORE0_GDSC>;
         };
+    };
index f9a003882f84fb6697536304c6eaefd2a9f3057f..1530ad0d80bdcacd44408b901b370fda18f7e8f3 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,sdm845-camss.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,sdm845-camss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Qualcomm CAMSS ISP
 
index 8edc8a2f43a5cb01524efba0ceffe60ca7a60cda..d5f80976f4cfec7236bd329aba80b10c80cd0b04 100644 (file)
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,sdm845-venus-v2.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,sdm845-venus-v2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Qualcomm Venus video encode and decode accelerators
+title: Qualcomm SDM845 Venus v2 video encode and decode accelerators
 
 maintainers:
   - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: |
   The Venus IP is a video encode and decode accelerator present
   on Qualcomm platforms
 
+allOf:
+  - $ref: qcom,venus-common.yaml#
+
 properties:
   compatible:
     const: qcom,sdm845-venus-v2
 
-  reg:
-    maxItems: 1
-
-  interrupts:
-    maxItems: 1
-
   power-domains:
     minItems: 3
     maxItems: 4
@@ -52,8 +48,9 @@ properties:
   iommus:
     maxItems: 2
 
-  memory-region:
-    maxItems: 1
+  operating-points-v2: true
+  opp-table:
+    type: object
 
   video-core0:
     type: object
@@ -79,68 +76,47 @@ properties:
 
     additionalProperties: false
 
-  video-firmware:
-    type: object
-    additionalProperties: false
-
-    description: |
-      Firmware subnode is needed when the platform does not
-      have TrustZone.
-
-    properties:
-      iommus:
-        maxItems: 1
-
-    required:
-      - iommus
-
 required:
   - compatible
-  - reg
-  - interrupts
-  - power-domains
   - power-domain-names
-  - clocks
-  - clock-names
   - iommus
-  - memory-region
   - video-core0
   - video-core1
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-        #include <dt-bindings/interrupt-controller/arm-gic.h>
-        #include <dt-bindings/clock/qcom,videocc-sdm845.h>
-
-        video-codec@aa00000 {
-                compatible = "qcom,sdm845-venus-v2";
-                reg = <0x0aa00000 0xff000>;
-                interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
-                clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
-                         <&videocc VIDEO_CC_VENUS_AHB_CLK>,
-                         <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,
-                         <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
-                         <&videocc VIDEO_CC_VCODEC0_AXI_CLK>,
-                         <&videocc VIDEO_CC_VCODEC1_CORE_CLK>,
-                         <&videocc VIDEO_CC_VCODEC1_AXI_CLK>;
-                clock-names = "core", "iface", "bus",
-                              "vcodec0_core", "vcodec0_bus",
-                              "vcodec1_core", "vcodec1_bus";
-                power-domains = <&videocc VENUS_GDSC>,
-                                <&videocc VCODEC0_GDSC>,
-                                <&videocc VCODEC1_GDSC>;
-                power-domain-names = "venus", "vcodec0", "vcodec1";
-                iommus = <&apps_smmu 0x10a0 0x8>,
-                         <&apps_smmu 0x10b0 0x0>;
-                memory-region = <&venus_mem>;
-
-                video-core0 {
-                        compatible = "venus-decoder";
-                };
-
-                video-core1 {
-                        compatible = "venus-encoder";
-                };
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/qcom,videocc-sdm845.h>
+
+    video-codec@aa00000 {
+        compatible = "qcom,sdm845-venus-v2";
+        reg = <0x0aa00000 0xff000>;
+        interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
+                 <&videocc VIDEO_CC_VENUS_AHB_CLK>,
+                 <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,
+                 <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
+                 <&videocc VIDEO_CC_VCODEC0_AXI_CLK>,
+                 <&videocc VIDEO_CC_VCODEC1_CORE_CLK>,
+                 <&videocc VIDEO_CC_VCODEC1_AXI_CLK>;
+        clock-names = "core", "iface", "bus",
+                      "vcodec0_core", "vcodec0_bus",
+                      "vcodec1_core", "vcodec1_bus";
+        power-domains = <&videocc VENUS_GDSC>,
+                        <&videocc VCODEC0_GDSC>,
+                        <&videocc VCODEC1_GDSC>;
+        power-domain-names = "venus", "vcodec0", "vcodec1";
+        iommus = <&apps_smmu 0x10a0 0x8>,
+                 <&apps_smmu 0x10b0 0x0>;
+        memory-region = <&venus_mem>;
+
+        video-core0 {
+            compatible = "venus-decoder";
+        };
+
+        video-core1 {
+            compatible = "venus-encoder";
         };
+    };
index 57d503373efe8cc0f8fd18466c6695664d649fad..eabc0957b2416bfe7499720e5f7021e42ecc4801 100644 (file)
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,sdm845-venus.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,sdm845-venus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Qualcomm Venus video encode and decode accelerators
+title: Qualcomm SDM845 Venus video encode and decode accelerators
 
 maintainers:
   - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: |
   The Venus IP is a video encode and decode accelerator present
   on Qualcomm platforms
 
+allOf:
+  - $ref: qcom,venus-common.yaml#
+
 properties:
   compatible:
     const: qcom,sdm845-venus
 
-  reg:
-    maxItems: 1
-
-  interrupts:
-    maxItems: 1
-
   power-domains:
     maxItems: 1
 
@@ -39,9 +35,6 @@ properties:
   iommus:
     maxItems: 2
 
-  memory-region:
-    maxItems: 1
-
   video-core0:
     type: object
 
@@ -94,66 +87,45 @@ properties:
 
     additionalProperties: false
 
-  video-firmware:
-    type: object
-    additionalProperties: false
-
-    description: |
-      Firmware subnode is needed when the platform does not
-      have TrustZone.
-
-    properties:
-      iommus:
-        maxItems: 1
-
-    required:
-      - iommus
-
 required:
   - compatible
-  - reg
-  - interrupts
-  - power-domains
-  - clocks
-  - clock-names
   - iommus
-  - memory-region
   - video-core0
   - video-core1
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-        #include <dt-bindings/interrupt-controller/arm-gic.h>
-        #include <dt-bindings/clock/qcom,videocc-sdm845.h>
-
-        video-codec@aa00000 {
-                compatible = "qcom,sdm845-venus";
-                reg = <0x0aa00000 0xff000>;
-                interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
-                clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
-                         <&videocc VIDEO_CC_VENUS_AHB_CLK>,
-                         <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>;
-                clock-names = "core", "iface", "bus";
-                power-domains = <&videocc VENUS_GDSC>;
-                iommus = <&apps_smmu 0x10a0 0x8>,
-                         <&apps_smmu 0x10b0 0x0>;
-                memory-region = <&venus_mem>;
-
-                video-core0 {
-                        compatible = "venus-decoder";
-                        clocks = <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
-                                 <&videocc VIDEO_CC_VCODEC0_AXI_CLK>;
-                        clock-names = "core", "bus";
-                        power-domains = <&videocc VCODEC0_GDSC>;
-                };
-
-                video-core1 {
-                        compatible = "venus-encoder";
-                        clocks = <&videocc VIDEO_CC_VCODEC1_CORE_CLK>,
-                                 <&videocc VIDEO_CC_VCODEC1_AXI_CLK>;
-                        clock-names = "core", "bus";
-                        power-domains = <&videocc VCODEC1_GDSC>;
-                };
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/qcom,videocc-sdm845.h>
+
+    video-codec@aa00000 {
+        compatible = "qcom,sdm845-venus";
+        reg = <0x0aa00000 0xff000>;
+        interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
+                 <&videocc VIDEO_CC_VENUS_AHB_CLK>,
+                 <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>;
+        clock-names = "core", "iface", "bus";
+        power-domains = <&videocc VENUS_GDSC>;
+        iommus = <&apps_smmu 0x10a0 0x8>,
+                 <&apps_smmu 0x10b0 0x0>;
+        memory-region = <&venus_mem>;
+
+        video-core0 {
+            compatible = "venus-decoder";
+            clocks = <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
+                     <&videocc VIDEO_CC_VCODEC0_AXI_CLK>;
+            clock-names = "core", "bus";
+            power-domains = <&videocc VCODEC0_GDSC>;
+        };
+
+        video-core1 {
+            compatible = "venus-encoder";
+            clocks = <&videocc VIDEO_CC_VCODEC1_CORE_CLK>,
+                     <&videocc VIDEO_CC_VCODEC1_AXI_CLK>;
+            clock-names = "core", "bus";
+            power-domains = <&videocc VCODEC1_GDSC>;
         };
+    };
index 07a2af12f37df1be9b6f31516a7079d6ca3e3170..fa5073c0fd1efaa94f171e4ec26b918d8a5261d6 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,sm8250-camss.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,sm8250-camss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Qualcomm CAMSS ISP
 
index 4b7a12523dcff521a1a0d17b890dc4f3aca8cb3a..7915dcd2d99f8fe9f9ea12dd3e730bb1713b0952 100644 (file)
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/qcom,sm8250-venus.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/qcom,sm8250-venus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Qualcomm Venus video encode and decode accelerators
+title: Qualcomm SM8250 Venus video encode and decode accelerators
 
 maintainers:
   - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: |
   The Venus IP is a video encode and decode accelerator present
   on Qualcomm platforms
 
+allOf:
+  - $ref: qcom,venus-common.yaml#
+
 properties:
   compatible:
     const: qcom,sm8250-venus
 
-  reg:
-    maxItems: 1
-
-  interrupts:
-    maxItems: 1
-
   power-domains:
     minItems: 2
     maxItems: 3
@@ -47,9 +43,6 @@ properties:
   iommus:
     maxItems: 1
 
-  memory-region:
-    maxItems: 1
-
   interconnects:
     maxItems: 2
 
@@ -58,6 +51,10 @@ properties:
       - const: cpu-cfg
       - const: video-mem
 
+  operating-points-v2: true
+  opp-table:
+    type: object
+
   resets:
     maxItems: 2
 
@@ -90,78 +87,57 @@ properties:
 
     additionalProperties: false
 
-  video-firmware:
-    type: object
-    additionalProperties: false
-
-    description: |
-      Firmware subnode is needed when the platform does not
-      have TrustZone.
-
-    properties:
-      iommus:
-        maxItems: 1
-
-    required:
-      - iommus
-
 required:
   - compatible
-  - reg
-  - interrupts
-  - power-domains
   - power-domain-names
-  - clocks
-  - clock-names
   - interconnects
   - interconnect-names
   - iommus
-  - memory-region
   - resets
   - reset-names
   - video-decoder
   - video-encoder
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-        #include <dt-bindings/interrupt-controller/arm-gic.h>
-        #include <dt-bindings/clock/qcom,videocc-sm8250.h>
-        #include <dt-bindings/interconnect/qcom,sm8250.h>
-        #include <dt-bindings/clock/qcom,gcc-sm8250.h>
-        #include <dt-bindings/power/qcom-rpmpd.h>
-
-        venus: video-codec@aa00000 {
-            compatible = "qcom,sm8250-venus";
-            reg = <0x0aa00000 0xff000>;
-            interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
-            power-domains = <&videocc MVS0C_GDSC>,
-                            <&videocc MVS0_GDSC>,
-                            <&rpmhpd SM8250_MX>;
-            power-domain-names = "venus", "vcodec0", "mx";
-
-            clocks = <&gcc GCC_VIDEO_AXI0_CLK>,
-                     <&videocc VIDEO_CC_MVS0C_CLK>,
-                     <&videocc VIDEO_CC_MVS0_CLK>;
-            clock-names = "iface", "core", "vcodec0_core";
-
-            interconnects = <&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_VENUS_CFG>,
-                            <&mmss_noc MASTER_VIDEO_P0 &mc_virt SLAVE_EBI_CH0>;
-            interconnect-names = "cpu-cfg", "video-mem";
-
-            iommus = <&apps_smmu 0x2100 0x0400>;
-            memory-region = <&video_mem>;
-
-            resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>,
-                     <&videocc VIDEO_CC_MVS0C_CLK_ARES>;
-            reset-names = "bus", "core";
-
-            video-decoder {
-                compatible = "venus-decoder";
-            };
-
-            video-encoder {
-                compatible = "venus-encoder";
-            };
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/qcom,videocc-sm8250.h>
+    #include <dt-bindings/interconnect/qcom,sm8250.h>
+    #include <dt-bindings/clock/qcom,gcc-sm8250.h>
+    #include <dt-bindings/power/qcom-rpmpd.h>
+
+    venus: video-codec@aa00000 {
+        compatible = "qcom,sm8250-venus";
+        reg = <0x0aa00000 0xff000>;
+        interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+        power-domains = <&videocc MVS0C_GDSC>,
+                        <&videocc MVS0_GDSC>,
+                        <&rpmhpd SM8250_MX>;
+        power-domain-names = "venus", "vcodec0", "mx";
+
+        clocks = <&gcc GCC_VIDEO_AXI0_CLK>,
+                 <&videocc VIDEO_CC_MVS0C_CLK>,
+                 <&videocc VIDEO_CC_MVS0_CLK>;
+        clock-names = "iface", "core", "vcodec0_core";
+
+        interconnects = <&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_VENUS_CFG>,
+                        <&mmss_noc MASTER_VIDEO_P0 &mc_virt SLAVE_EBI_CH0>;
+        interconnect-names = "cpu-cfg", "video-mem";
+
+        iommus = <&apps_smmu 0x2100 0x0400>;
+        memory-region = <&video_mem>;
+
+        resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>,
+                 <&videocc VIDEO_CC_MVS0C_CLK_ARES>;
+        reset-names = "bus", "core";
+
+        video-decoder {
+            compatible = "venus-decoder";
+        };
+
+        video-encoder {
+            compatible = "venus-encoder";
         };
+    };
diff --git a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml
new file mode 100644 (file)
index 0000000..3153d91
--- /dev/null
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/qcom,venus-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SoC Venus Video Encode and Decode Accelerators Common Properties
+
+maintainers:
+  - Stanimir Varbanov <stanimir.k.varbanov@gmail.com>
+  - Vikash Garodia <quic_vgarodia@quicinc.com>
+
+description: |
+  The Venus IP is a video encode and decode accelerator present
+  on Qualcomm platforms
+
+properties:
+  reg:
+    maxItems: 1
+
+  clocks:
+    minItems: 3
+    maxItems: 7
+
+  clock-names:
+    minItems: 3
+    maxItems: 7
+
+  firmware-name:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  iommus:
+    minItems: 1
+    maxItems: 20
+
+  memory-region:
+    maxItems: 1
+
+  power-domains:
+    minItems: 1
+    maxItems: 4
+
+  power-domain-names:
+    minItems: 1
+    maxItems: 4
+
+  video-firmware:
+    type: object
+    additionalProperties: false
+
+    description: |
+      Firmware subnode is needed when the platform does not
+      have TrustZone.
+
+    properties:
+      iommus:
+        maxItems: 1
+
+    required:
+      - iommus
+
+required:
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - memory-region
+  - power-domains
+
+additionalProperties: true
index e732b7f3a635ce721668ee50a5dc4d7e7ebab9f8..7bbe580c80f7c0a839a32ab2b6fab9b0ef620890 100644 (file)
@@ -18,7 +18,7 @@ properties:
     description:
       Specifies the scancode/key mapping table defined in-kernel for
       the remote controller.
-    $ref: '/schemas/types.yaml#/definitions/string'
+    $ref: /schemas/types.yaml#/definitions/string
     enum:
       - rc-adstech-dvb-t-pci
       - rc-alink-dtu-m
@@ -39,6 +39,7 @@ properties:
       - rc-avertv-303
       - rc-azurewave-ad-tu700
       - rc-beelink-gs1
+      - rc-beelink-mxiii
       - rc-behold
       - rc-behold-columbus
       - rc-budget-ci-old
@@ -55,6 +56,7 @@ properties:
       - rc-dm1105-nec
       - rc-dntv-live-dvb-t
       - rc-dntv-live-dvbt-pro
+      - rc-dreambox
       - rc-dtt200u
       - rc-dvbsky
       - rc-dvico-mce
index b520d6c5c1021cbf697b82681b21f9768eaa1469..977ab188d6547fb71e0c35f2453b2e767af2df7f 100644 (file)
@@ -31,6 +31,7 @@ properties:
           - renesas,r8a77980-csi2 # R-Car V3H
           - renesas,r8a77990-csi2 # R-Car E3
           - renesas,r8a779a0-csi2 # R-Car V3U
+          - renesas,r8a779g0-csi2 # R-Car V4H
 
   reg:
     maxItems: 1
index 43f2fed8cd33b0e5afdfae186aa50cb7ce106671..c6abe719881b8557b431beeee11d9bff2b08623e 100644 (file)
@@ -21,15 +21,22 @@ description: |
 
 properties:
   compatible:
-    enum:
-      - renesas,fcpv # FCP for VSP
-      - renesas,fcpf # FCP for FDP
+    oneOf:
+      - enum:
+          - renesas,fcpv # FCP for VSP
+          - renesas,fcpf # FCP for FDP
+      - items:
+          - enum:
+              - renesas,r9a07g044-fcpvd # RZ/G2{L,LC}
+              - renesas,r9a07g054-fcpvd # RZ/V2L
+          - const: renesas,fcpv         # Generic FCP for VSP fallback
 
   reg:
     maxItems: 1
 
-  clocks:
-    maxItems: 1
+  clocks: true
+
+  clock-names: true
 
   iommus:
     maxItems: 1
@@ -49,6 +56,34 @@ required:
 
 additionalProperties: false
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - renesas,r9a07g044-fcpvd
+              - renesas,r9a07g054-fcpvd
+    then:
+      properties:
+        clocks:
+          items:
+            - description: Main clock
+            - description: Register access clock
+            - description: Video clock
+        clock-names:
+          items:
+            - const: aclk
+            - const: pclk
+            - const: vclk
+      required:
+        - clock-names
+    else:
+      properties:
+        clocks:
+          maxItems: 1
+        clock-names: false
+
 examples:
   # R8A7795 (R-Car H3) FCP for VSP-D1
   - |
index 514857d36f6b7d7437b251d25da661af29759569..33650a1ea034585491f52ca2f7cb883ba4786423 100644 (file)
@@ -21,6 +21,7 @@ properties:
     items:
       - enum:
           - renesas,r8a779a0-isp # V3U
+          - renesas,r8a779g0-isp # V4H
   reg:
     maxItems: 1
 
index c0442e79cbb4fbc5a661b26372d4ff89123b4fc5..7073d1936c34f6db943f9ef8649b97d803d7b67c 100644 (file)
@@ -53,6 +53,7 @@ properties:
               - renesas,vin-r8a77990 # R-Car E3
               - renesas,vin-r8a77995 # R-Car D3
               - renesas,vin-r8a779a0 # R-Car V3U
+              - renesas,vin-r8a779g0 # R-Car V4H
 
   reg:
     maxItems: 1
index 7a8f32473852b4955b6625bc69e1f8844a8e430d..3265e922647c762f60b63d88e3d1f618b87baacf 100644 (file)
@@ -16,10 +16,15 @@ description:
 
 properties:
   compatible:
-    enum:
-      - renesas,r9a07g044-vsp2 # RZ/G2L
-      - renesas,vsp1 # R-Car Gen2 and RZ/G1
-      - renesas,vsp2 # R-Car Gen3 and RZ/G2
+    oneOf:
+      - enum:
+          - renesas,r9a07g044-vsp2 # RZ/G2L
+          - renesas,vsp1 # R-Car Gen2 and RZ/G1
+          - renesas,vsp2 # R-Car Gen3 and RZ/G2
+      - items:
+          - enum:
+              - renesas,r9a07g054-vsp2    # RZ/V2L
+          - const: renesas,r9a07g044-vsp2 # RZ/G2L fallback
 
   reg:
     maxItems: 1
index 81b26eb4cd354a32675ec93739e9b092d333ca4a..9d90d8d0565a1561d808280f487129bc7968a37c 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/rockchip,rk3568-vepu.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/rockchip,rk3568-vepu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Hantro G1 VPU encoders implemented on Rockchip SoCs
 
index b3661d7d43572d047d94a19bd9e3450e83f2beb1..0bad7e640148601b4a518ae65962013c4bd67fa4 100644 (file)
@@ -212,12 +212,19 @@ examples:
                 compatible = "ovti,ov2685";
                 reg = <0x3c>;
 
-                  port {
-                      ucam_out: endpoint {
-                          remote-endpoint = <&mipi_in_ucam>;
-                          data-lanes = <1>;
-                      };
-                  };
+                clocks = <&cru SCLK_TESTCLKOUT1>;
+                clock-names = "xvclk";
+
+                avdd-supply = <&pp2800_cam>;
+                dovdd-supply = <&pp1800>;
+                dvdd-supply = <&pp1800>;
+
+                port {
+                    ucam_out: endpoint {
+                        remote-endpoint = <&mipi_in_ucam>;
+                        data-lanes = <1>;
+                    };
+                };
             };
         };
     };
index 6cc4d3e5a61db709c7b0929d1f93d731e341c95c..ee622a8ee1ccb6b2e99894996d735dee20f5ea13 100644 (file)
@@ -2,8 +2,8 @@
 
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/media/rockchip-vpu.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/media/rockchip-vpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Hantro G1 VPU codecs implemented on Rockchip SoCs
 
diff --git a/Documentation/devicetree/bindings/media/samsung,exynos4210-csis.yaml b/Documentation/devicetree/bindings/media/samsung,exynos4210-csis.yaml
new file mode 100644 (file)
index 0000000..dd6cc7a
--- /dev/null
@@ -0,0 +1,170 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/samsung,exynos4210-csis.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S5P/Exynos SoC series MIPI CSI-2 receiver (MIPI CSIS)
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+  - Sylwester Nawrocki <s.nawrocki@samsung.com>
+
+properties:
+  compatible:
+    enum:
+      - samsung,s5pv210-csis
+      - samsung,exynos4210-csis
+      - samsung,exynos4212-csis
+      - samsung,exynos5250-csis
+
+  reg:
+    maxItems: 1
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  bus-width:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [2, 4]
+    description:
+      Number of data lines supported.
+
+  clocks:
+    maxItems: 2
+
+  clock-names:
+    items:
+      - const: csis
+      - const: sclk_csis
+
+  clock-frequency:
+    default: 166000000
+    description:
+      The IP's main (system bus) clock frequency in Hz.
+
+  interrupts:
+    maxItems: 1
+
+  phys:
+    maxItems: 1
+
+  phy-names:
+    items:
+      - const: csis
+
+  power-domains:
+    maxItems: 1
+
+  vddio-supply:
+    description: MIPI CSIS I/O and PLL voltage supply (e.g. 1.8V).
+
+  vddcore-supply:
+    description: MIPI CSIS Core voltage supply (e.g. 1.1V).
+
+patternProperties:
+  "^port@[34]$":
+    $ref: /schemas/graph.yaml#/$defs/port-base
+    additionalProperties: false
+    description:
+      Camera input port.
+
+    properties:
+      reg:
+        enum: [3, 4]
+
+      endpoint:
+        $ref: video-interfaces.yaml#
+        unevaluatedProperties: false
+
+        properties:
+          data-lanes:
+            minItems: 1
+            maxItems: 4
+
+          samsung,csis-hs-settle:
+            $ref: /schemas/types.yaml#/definitions/uint32
+            description: Differential receiver (HS-RX) settle time.
+
+          samsung,csis-wclk:
+            type: boolean
+            description:
+              CSI-2 wrapper clock selection. If this property is present external clock
+              from CMU will be used, or the bus clock if it's not specified.
+
+        required:
+          - data-lanes
+
+    required:
+      - reg
+
+required:
+  - compatible
+  - reg
+  - bus-width
+  - clocks
+  - clock-names
+  - interrupts
+  - vddio-supply
+  - vddcore-supply
+
+anyOf:
+  - required:
+      - port@3
+  - required:
+      - port@4
+
+allOf:
+  - if:
+      required:
+        - samsung,isp-wb
+    then:
+      required:
+        - samsung,sysreg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/exynos4.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    csis@11890000 {
+        compatible = "samsung,exynos4210-csis";
+        reg = <0x11890000 0x4000>;
+        clocks = <&clock CLK_CSIS1>,
+                 <&clock CLK_SCLK_CSIS1>;
+        clock-names = "csis", "sclk_csis";
+        assigned-clocks = <&clock CLK_MOUT_CSIS1>,
+                          <&clock CLK_SCLK_CSIS1>;
+        assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+        assigned-clock-rates = <0>, <176000000>;
+
+        interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+
+        bus-width = <2>;
+        power-domains = <&pd_cam>;
+        phys = <&mipi_phy 2>;
+        phy-names = "csis";
+
+        vddcore-supply = <&ldo8_reg>;
+        vddio-supply = <&ldo10_reg>;
+
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        /* Camera D (4) MIPI CSI-2 (CSIS1) */
+        port@4 {
+            reg = <4>;
+
+            endpoint {
+                remote-endpoint = <&is_s5k6a3_ep>;
+                data-lanes = <1>;
+                samsung,csis-hs-settle = <18>;
+                samsung,csis-wclk;
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/media/samsung,exynos4210-fimc.yaml b/Documentation/devicetree/bindings/media/samsung,exynos4210-fimc.yaml
new file mode 100644 (file)
index 0000000..271d057
--- /dev/null
@@ -0,0 +1,152 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/samsung,exynos4210-fimc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S5P/Exynos SoC Fully Integrated Mobile Camera
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+  - Sylwester Nawrocki <s.nawrocki@samsung.com>
+
+description:
+  Each FIMC device should have an alias in the aliases node, in the form of
+  fimc<n>, where <n> is an integer specifying the IP block instance.
+
+properties:
+  compatible:
+    enum:
+      - samsung,exynos4210-fimc
+      - samsung,exynos4212-fimc
+      - samsung,s5pv210-fimc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 2
+
+  clock-names:
+    items:
+      - const: fimc
+      - const: sclk_fimc
+
+  clock-frequency:
+    description:
+      Maximum FIMC local clock (LCLK) frequency.
+
+  interrupts:
+    maxItems: 1
+
+  iommus:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  samsung,cam-if:
+    type: boolean
+    description:
+      The FIMC IP block includes the camera input interface.
+
+  samsung,isp-wb:
+    type: boolean
+    description: |
+      The FIMC IP block has the ISP writeback input.
+
+  samsung,lcd-wb:
+    type: boolean
+    description: |
+      The FIMC IP block has the LCD writeback input.
+
+  samsung,mainscaler-ext:
+    type: boolean
+    description:
+      FIMC IP supports extended image size and has CIEXTEN register.
+
+  samsung,min-pix-alignment:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    items:
+      - description: Minimum supported image height alignment.
+      - description: Horizontal image offset.
+    description:
+      The values are in pixels and default is <2 1>.
+
+  samsung,min-pix-sizes:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    maxItems: 2
+    description: |
+      An array specyfing minimum image size in pixels at the FIMC input and
+      output DMA, in the first and second cell respectively.  Default value
+      is <16 16>.
+
+  samsung,pix-limits:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    maxItems: 4
+    description: |
+      An array of maximum supported image sizes in pixels, for details refer to
+      Table 2-1 in the S5PV210 SoC User Manual. The meaning of each cell is as
+      follows:
+       0 - scaler input horizontal size
+       1 - input horizontal size for the scaler bypassed
+       2 - REAL_WIDTH without input rotation
+       3 - REAL_HEIGHT with input rotation
+
+  samsung,rotators:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    default: 0x11
+    description: |
+      A bitmask specifying whether this IP has the input and the output
+      rotator. Bits 4 and 0 correspond to input and output rotator
+      respectively. If a rotator is present its corresponding bit should be
+      set.
+
+  samsung,sysreg:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      System Registers (SYSREG) node.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - samsung,pix-limits
+
+allOf:
+  - if:
+      required:
+        - samsung,isp-wb
+    then:
+      required:
+        - samsung,sysreg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/exynos4.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    fimc@11800000 {
+        compatible = "samsung,exynos4212-fimc";
+        reg = <0x11800000 0x1000>;
+        clocks = <&clock CLK_FIMC0>,
+                 <&clock CLK_SCLK_FIMC0>;
+        clock-names = "fimc", "sclk_fimc";
+        interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+        iommus = <&sysmmu_fimc0>;
+        power-domains = <&pd_cam>;
+        samsung,sysreg = <&sys_reg>;
+
+        samsung,pix-limits = <4224 8192 1920 4224>;
+        samsung,mainscaler-ext;
+        samsung,isp-wb;
+        samsung,cam-if;
+
+        assigned-clocks = <&clock CLK_MOUT_FIMC0>,
+                          <&clock CLK_SCLK_FIMC0>;
+        assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+        assigned-clock-rates = <0>, <176000000>;
+    };
diff --git a/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml b/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml
new file mode 100644 (file)
index 0000000..3691cd4
--- /dev/null
@@ -0,0 +1,220 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/samsung,exynos4212-fimc-is.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos4212/4412 SoC Imaging Subsystem (FIMC-IS)
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+  - Sylwester Nawrocki <s.nawrocki@samsung.com>
+
+description:
+  The FIMC-IS is a subsystem for processing image signal from an image sensor.
+  The Exynos4x12 SoC series FIMC-IS V1.5 comprises of a dedicated ARM Cortex-A5
+  processor, ISP, DRC and FD IP blocks and peripheral devices such as UART, I2C
+  and SPI bus controllers, PWM and ADC.
+
+properties:
+  compatible:
+    enum:
+      - samsung,exynos4212-fimc-is
+
+  reg:
+    maxItems: 1
+
+  ranges: true
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 1
+
+  clocks:
+    maxItems: 21
+
+  clock-names:
+    items:
+      - const: lite0
+      - const: lite1
+      - const: ppmuispx
+      - const: ppmuispmx
+      - const: isp
+      - const: drc
+      - const: fd
+      - const: mcuisp
+      - const: gicisp
+      - const: mcuctl_isp
+      - const: pwm_isp
+      - const: ispdiv0
+      - const: ispdiv1
+      - const: mcuispdiv0
+      - const: mcuispdiv1
+      - const: mpll
+      - const: aclk200
+      - const: aclk400mcuisp
+      - const: div_aclk200
+      - const: div_aclk400mcuisp
+      - const: uart
+
+  interrupts:
+    maxItems: 2
+
+  iommus:
+    maxItems: 4
+
+  iommu-names:
+    items:
+      - const: isp
+      - const: drc
+      - const: fd
+      - const: mcuctl
+
+  power-domains:
+    maxItems: 1
+
+patternProperties:
+  "^pmu@[0-9a-f]+$":
+    type: object
+    additionalProperties: false
+    description:
+      Node representing the SoC's Power Management Unit (duplicated with the
+      correct PMU node in the SoC).
+
+    properties:
+      reg:
+        maxItems: 1
+
+    required:
+      - reg
+
+  "^i2c-isp@[0-9a-f]+$":
+    type: object
+    $ref: /schemas/i2c/i2c-controller.yaml#
+    unevaluatedProperties: false
+    description:
+      ISP I2C bus controller
+
+    properties:
+      compatible:
+        const: samsung,exynos4212-i2c-isp
+
+      reg:
+        maxItems: 1
+
+
+      clocks:
+        maxItems: 1
+
+      clock-names:
+        items:
+          - const: i2c_isp
+
+      pinctrl-0: true
+      pinctrl-names:
+        items:
+          - const: default
+
+    required:
+      - compatible
+      - reg
+      - clocks
+      - clock-names
+
+required:
+  - compatible
+  - reg
+  - '#address-cells'
+  - clocks
+  - clock-names
+  - interrupts
+  - ranges
+  - '#size-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/exynos4.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    fimc-is@12000000 {
+        compatible = "samsung,exynos4212-fimc-is";
+        reg = <0x12000000 0x260000>;
+        interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&isp_clock CLK_ISP_FIMC_LITE0>,
+                 <&isp_clock CLK_ISP_FIMC_LITE1>,
+                 <&isp_clock CLK_ISP_PPMUISPX>,
+                 <&isp_clock CLK_ISP_PPMUISPMX>,
+                 <&isp_clock CLK_ISP_FIMC_ISP>,
+                 <&isp_clock CLK_ISP_FIMC_DRC>,
+                 <&isp_clock CLK_ISP_FIMC_FD>,
+                 <&isp_clock CLK_ISP_MCUISP>,
+                 <&isp_clock CLK_ISP_GICISP>,
+                 <&isp_clock CLK_ISP_MCUCTL_ISP>,
+                 <&isp_clock CLK_ISP_PWM_ISP>,
+                 <&isp_clock CLK_ISP_DIV_ISP0>,
+                 <&isp_clock CLK_ISP_DIV_ISP1>,
+                 <&isp_clock CLK_ISP_DIV_MCUISP0>,
+                 <&isp_clock CLK_ISP_DIV_MCUISP1>,
+                 <&clock CLK_MOUT_MPLL_USER_T>,
+                 <&clock CLK_ACLK200>,
+                 <&clock CLK_ACLK400_MCUISP>,
+                 <&clock CLK_DIV_ACLK200>,
+                 <&clock CLK_DIV_ACLK400_MCUISP>,
+                 <&clock CLK_UART_ISP_SCLK>;
+        clock-names = "lite0", "lite1", "ppmuispx",
+                      "ppmuispmx", "isp",
+                      "drc", "fd", "mcuisp",
+                      "gicisp", "mcuctl_isp", "pwm_isp",
+                      "ispdiv0", "ispdiv1", "mcuispdiv0",
+                      "mcuispdiv1", "mpll", "aclk200",
+                      "aclk400mcuisp", "div_aclk200",
+                      "div_aclk400mcuisp", "uart";
+        iommus = <&sysmmu_fimc_isp>, <&sysmmu_fimc_drc>,
+                 <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>;
+        iommu-names = "isp", "drc", "fd", "mcuctl";
+        power-domains = <&pd_isp>;
+
+        #address-cells = <1>;
+        #size-cells = <1>;
+        ranges;
+
+        pmu@10020000 {
+            reg = <0x10020000 0x3000>;
+        };
+
+        i2c-isp@12140000 {
+            compatible = "samsung,exynos4212-i2c-isp";
+            reg = <0x12140000 0x100>;
+            clocks = <&isp_clock CLK_ISP_I2C1_ISP>;
+            clock-names = "i2c_isp";
+            pinctrl-0 = <&fimc_is_i2c1>;
+            pinctrl-names = "default";
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            image-sensor@10 {
+                compatible = "samsung,s5k6a3";
+                reg = <0x10>;
+                svdda-supply = <&cam_io_reg>;
+                svddio-supply = <&ldo19_reg>;
+                afvdd-supply = <&ldo19_reg>;
+                clock-frequency = <24000000>;
+                clocks = <&camera 1>;
+                clock-names = "extclk";
+                gpios = <&gpm1 6 GPIO_ACTIVE_LOW>;
+
+                port {
+                    endpoint {
+                        remote-endpoint = <&csis1_ep>;
+                        data-lanes = <1>;
+                    };
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-lite.yaml b/Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-lite.yaml
new file mode 100644 (file)
index 0000000..f80eca0
--- /dev/null
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/samsung,exynos4212-fimc-lite.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung Exynos SoC series camera host interface (FIMC-LITE)
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+  - Sylwester Nawrocki <s.nawrocki@samsung.com>
+
+description:
+  Each FIMC device should have an alias in the aliases node, in the form of
+  fimc-lite<n>, where <n> is an integer specifying the IP block instance.
+
+properties:
+  compatible:
+    enum:
+      - samsung,exynos4212-fimc-lite
+      - samsung,exynos5250-fimc-lite
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: flite
+
+  interrupts:
+    maxItems: 1
+
+  iommus:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/exynos4.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    fimc-lite@12390000 {
+        compatible = "samsung,exynos4212-fimc-lite";
+        reg = <0x12390000 0x1000>;
+        clocks = <&isp_clock CLK_ISP_FIMC_LITE0>;
+        clock-names = "flite";
+        interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+        power-domains = <&pd_isp>;
+        iommus = <&sysmmu_fimc_lite0>;
+    };
diff --git a/Documentation/devicetree/bindings/media/samsung,fimc.yaml b/Documentation/devicetree/bindings/media/samsung,fimc.yaml
new file mode 100644 (file)
index 0000000..79ff6d8
--- /dev/null
@@ -0,0 +1,279 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/samsung,fimc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S5P/Exynos SoC Camera Subsystem (FIMC)
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+  - Sylwester Nawrocki <s.nawrocki@samsung.com>
+
+description: |
+  The S5P/Exynos SoC Camera subsystem comprises of multiple sub-devices
+  represented by separate device tree nodes. Currently this includes: Fully
+  Integrated Mobile Camera (FIMC, in the S5P SoCs series known as CAMIF), MIPI
+  CSIS, FIMC-LITE and FIMC-IS (ISP).
+
+properties:
+  compatible:
+    const: samsung,fimc
+
+  ranges: true
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 1
+
+  '#clock-cells':
+    const: 1
+    description: |
+      The clock specifier cell stores an index of a clock: 0, 1 for
+      CAM_A_CLKOUT, CAM_B_CLKOUT clocks respectively.
+
+  clocks:
+    minItems: 2
+    maxItems: 4
+
+  clock-names:
+    minItems: 2
+    items:
+      - const: sclk_cam0
+      - const: sclk_cam1
+      - const: pxl_async0
+      - const: pxl_async1
+
+  clock-output-names:
+    maxItems: 2
+
+  parallel-ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+    description:
+      Active parallel video input ports.
+
+    patternProperties:
+      "^port@[01]$":
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        description:
+          Camera A and camera B inputs.
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+
+  pinctrl-names:
+    minItems: 1
+    items:
+      - const: default
+      - const: idle
+      - const: active_a
+      - const: active_b
+
+patternProperties:
+  "^csis@[0-9a-f]+$":
+    type: object
+    $ref: samsung,exynos4210-csis.yaml#
+    description: MIPI CSI-2 receiver.
+
+  "^fimc@[0-9a-f]+$":
+    type: object
+    $ref: samsung,exynos4210-fimc.yaml#
+    description: Fully Integrated Mobile Camera.
+
+  "^fimc-is@[0-9a-f]+$":
+    type: object
+    $ref: samsung,exynos4212-fimc-is.yaml#
+    description: Imaging Subsystem (FIMC-IS).
+
+  "^fimc-lite@[0-9a-f]+$":
+    type: object
+    $ref: samsung,exynos4212-fimc-lite.yaml#
+    description: Camera host interface (FIMC-LITE).
+
+required:
+  - compatible
+  - '#address-cells'
+  - '#clock-cells'
+  - clocks
+  - clock-names
+  - clock-output-names
+  - ranges
+  - '#size-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/exynos4.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    camera@11800000 {
+        compatible = "samsung,fimc";
+        #clock-cells = <1>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+        ranges = <0x0 0x0 0x18000000>;
+
+        clocks = <&clock CLK_SCLK_CAM0>, <&clock CLK_SCLK_CAM1>,
+                 <&clock CLK_PIXELASYNCM0>, <&clock CLK_PIXELASYNCM1>;
+        clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0", "pxl_async1";
+        clock-output-names = "cam_a_clkout", "cam_b_clkout";
+
+        assigned-clocks = <&clock CLK_MOUT_CAM0>,
+                          <&clock CLK_MOUT_CAM1>;
+        assigned-clock-parents = <&clock CLK_XUSBXTI>,
+                                 <&clock CLK_XUSBXTI>;
+
+        pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>;
+        pinctrl-names = "default";
+
+        fimc@11800000 {
+            compatible = "samsung,exynos4212-fimc";
+            reg = <0x11800000 0x1000>;
+            interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+            clocks = <&clock CLK_FIMC0>,
+                     <&clock CLK_SCLK_FIMC0>;
+            clock-names = "fimc", "sclk_fimc";
+            power-domains = <&pd_cam>;
+            samsung,sysreg = <&sys_reg>;
+            iommus = <&sysmmu_fimc0>;
+
+            samsung,pix-limits = <4224 8192 1920 4224>;
+            samsung,mainscaler-ext;
+            samsung,isp-wb;
+            samsung,cam-if;
+        };
+
+        /* ... FIMC 1-3 */
+
+        csis@11880000 {
+            compatible = "samsung,exynos4210-csis";
+            reg = <0x11880000 0x4000>;
+            interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+            clocks = <&clock CLK_CSIS0>,
+                     <&clock CLK_SCLK_CSIS0>;
+            clock-names = "csis", "sclk_csis";
+            assigned-clocks = <&clock CLK_MOUT_CSIS0>,
+                              <&clock CLK_SCLK_CSIS0>;
+            assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+            assigned-clock-rates = <0>, <176000000>;
+
+            bus-width = <4>;
+            power-domains = <&pd_cam>;
+            phys = <&mipi_phy 0>;
+            phy-names = "csis";
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            vddcore-supply = <&ldo8_reg>;
+            vddio-supply = <&ldo10_reg>;
+
+            /* Camera C (3) MIPI CSI-2 (CSIS0) */
+            port@3 {
+                reg = <3>;
+                endpoint {
+                    remote-endpoint = <&s5c73m3_ep>;
+                    data-lanes = <1 2 3 4>;
+                    samsung,csis-hs-settle = <12>;
+                };
+            };
+        };
+
+        /* ... CSIS 1 */
+
+        fimc-lite@12390000 {
+              compatible = "samsung,exynos4212-fimc-lite";
+              reg = <0x12390000 0x1000>;
+              interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+              power-domains = <&pd_isp>;
+              clocks = <&isp_clock CLK_ISP_FIMC_LITE0>;
+              clock-names = "flite";
+              iommus = <&sysmmu_fimc_lite0>;
+        };
+
+        /* ... FIMC-LITE 1 */
+
+        fimc-is@12000000 {
+            compatible = "samsung,exynos4212-fimc-is";
+            reg = <0x12000000 0x260000>;
+            interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+            clocks = <&isp_clock CLK_ISP_FIMC_LITE0>,
+                     <&isp_clock CLK_ISP_FIMC_LITE1>,
+                     <&isp_clock CLK_ISP_PPMUISPX>,
+                     <&isp_clock CLK_ISP_PPMUISPMX>,
+                     <&isp_clock CLK_ISP_FIMC_ISP>,
+                     <&isp_clock CLK_ISP_FIMC_DRC>,
+                     <&isp_clock CLK_ISP_FIMC_FD>,
+                     <&isp_clock CLK_ISP_MCUISP>,
+                     <&isp_clock CLK_ISP_GICISP>,
+                     <&isp_clock CLK_ISP_MCUCTL_ISP>,
+                     <&isp_clock CLK_ISP_PWM_ISP>,
+                     <&isp_clock CLK_ISP_DIV_ISP0>,
+                     <&isp_clock CLK_ISP_DIV_ISP1>,
+                     <&isp_clock CLK_ISP_DIV_MCUISP0>,
+                     <&isp_clock CLK_ISP_DIV_MCUISP1>,
+                     <&clock CLK_MOUT_MPLL_USER_T>,
+                     <&clock CLK_ACLK200>,
+                     <&clock CLK_ACLK400_MCUISP>,
+                     <&clock CLK_DIV_ACLK200>,
+                     <&clock CLK_DIV_ACLK400_MCUISP>,
+                     <&clock CLK_UART_ISP_SCLK>;
+            clock-names = "lite0", "lite1", "ppmuispx",
+                          "ppmuispmx", "isp",
+                          "drc", "fd", "mcuisp",
+                          "gicisp", "mcuctl_isp", "pwm_isp",
+                          "ispdiv0", "ispdiv1", "mcuispdiv0",
+                          "mcuispdiv1", "mpll", "aclk200",
+                          "aclk400mcuisp", "div_aclk200",
+                          "div_aclk400mcuisp", "uart";
+            iommus = <&sysmmu_fimc_isp>, <&sysmmu_fimc_drc>,
+                     <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>;
+            iommu-names = "isp", "drc", "fd", "mcuctl";
+            power-domains = <&pd_isp>;
+
+            #address-cells = <1>;
+            #size-cells = <1>;
+            ranges;
+
+            pmu@10020000 {
+                reg = <0x10020000 0x3000>;
+            };
+
+            i2c-isp@12140000 {
+                compatible = "samsung,exynos4212-i2c-isp";
+                reg = <0x12140000 0x100>;
+                clocks = <&isp_clock CLK_ISP_I2C1_ISP>;
+                clock-names = "i2c_isp";
+                pinctrl-0 = <&fimc_is_i2c1>;
+                pinctrl-names = "default";
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                image-sensor@10 {
+                    compatible = "samsung,s5k6a3";
+                    reg = <0x10>;
+                    svdda-supply = <&cam_io_reg>;
+                    svddio-supply = <&ldo19_reg>;
+                    afvdd-supply = <&ldo19_reg>;
+                    clock-frequency = <24000000>;
+                    /* CAM_B_CLKOUT */
+                    clocks = <&camera 1>;
+                    clock-names = "extclk";
+                    gpios = <&gpm1 6 GPIO_ACTIVE_LOW>;
+
+                    port {
+                        endpoint {
+                            remote-endpoint = <&csis1_ep>;
+                            data-lanes = <1>;
+                        };
+                    };
+                };
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/media/samsung,s5c73m3.yaml b/Documentation/devicetree/bindings/media/samsung,s5c73m3.yaml
new file mode 100644 (file)
index 0000000..1b75390
--- /dev/null
@@ -0,0 +1,165 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/samsung,s5c73m3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S5C73M3 8Mp camera ISP
+
+maintainers:
+  - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+  - Sylwester Nawrocki <s.nawrocki@samsung.com>
+
+description:
+  The S5C73M3 camera ISP supports MIPI CSI-2 and parallel (ITU-R BT.656)
+  video data busses. The I2C bus is the main control bus and additionally the
+  SPI bus is used, mostly for transferring the firmware to and from the
+  device. Two slave device nodes corresponding to these control bus
+  interfaces are required and should be placed under respective bus
+  controller nodes.
+
+properties:
+  compatible:
+    const: samsung,s5c73m3
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: cis_extclk
+
+  clock-frequency:
+    default: 24000000
+    description: cis_extclk clock frequency.
+
+  standby-gpios:
+    maxItems: 1
+    description: STANDBY pin.
+
+  vdda-supply:
+    description: Analog power supply (1.2V).
+
+  vdd-af-supply:
+    description: lens power supply (2.8V).
+
+  vddio-cis-supply:
+    description: CIS I/O power supply (1.2V to 1.8V).
+
+  vddio-host-supply:
+    description: Host I/O power supply (1.8V to 2.8V).
+
+  vdd-int-supply:
+    description: Digital power supply (1.2V).
+
+  vdd-reg-supply:
+    description: Regulator input power supply (2.8V).
+
+  xshutdown-gpios:
+    maxItems: 1
+    description: XSHUTDOWN pin.
+
+  port:
+    $ref: /schemas/graph.yaml#/$defs/port-base
+    additionalProperties: false
+
+    properties:
+      endpoint:
+        $ref: /schemas/media/video-interfaces.yaml#
+        unevaluatedProperties: false
+
+        properties:
+          data-lanes:
+            items:
+              - const: 1
+              - const: 2
+              - const: 3
+              - const: 4
+
+required:
+  - compatible
+  - reg
+
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+  - if:
+      required:
+        - spi-max-frequency
+    then:
+      properties:
+        # The SPI node is simplified firmware-transfer interface only
+        clocks: false
+        clock-names: false
+        standby-gpios: false
+        vdda-supply: false
+        vdd-af-supply: false
+        vddio-cis-supply: false
+        vddio-host-supply: false
+        vdd-int-supply: false
+        vdd-reg-supply: false
+        xshutdown-gpios: false
+        port: false
+    else:
+      required:
+        - clocks
+        - clock-names
+        - standby-gpios
+        - vdda-supply
+        - vdd-af-supply
+        - vddio-cis-supply
+        - vddio-host-supply
+        - vdd-int-supply
+        - vdd-reg-supply
+        - xshutdown-gpios
+        - port
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        image-sensor@3c {
+            compatible = "samsung,s5c73m3";
+            reg = <0x3c>;
+            clock-frequency = <24000000>;
+            clocks = <&camera 0>;
+            clock-names = "cis_extclk";
+            standby-gpios = <&gpm0 6 GPIO_ACTIVE_LOW>;
+            vdda-supply = <&cam_vdda_reg>;
+            vdd-af-supply = <&cam_af_reg>;
+            vddio-cis-supply = <&ldo9_reg>;
+            vddio-host-supply = <&ldo18_reg>;
+            vdd-int-supply = <&buck9_reg>;
+            vdd-reg-supply = <&cam_io_reg>;
+            xshutdown-gpios = <&gpf1 3 GPIO_ACTIVE_LOW>; /* ISP_RESET */
+
+            port {
+                s5c73m3_ep: endpoint {
+                    remote-endpoint = <&csis0_ep>;
+                    data-lanes = <1 2 3 4>;
+                };
+            };
+        };
+    };
+
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        image-sensor@0 {
+            compatible = "samsung,s5c73m3";
+            reg = <0>;
+            spi-max-frequency = <50000000>;
+            controller-data {
+                samsung,spi-feedback-delay = <2>;
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/media/samsung-fimc.txt b/Documentation/devicetree/bindings/media/samsung-fimc.txt
deleted file mode 100644 (file)
index 2044752..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-Samsung S5P/Exynos SoC Camera Subsystem (FIMC)
-----------------------------------------------
-
-The S5P/Exynos SoC Camera subsystem comprises of multiple sub-devices
-represented by separate device tree nodes. Currently this includes: FIMC (in
-the S5P SoCs series known as CAMIF), MIPI CSIS, FIMC-LITE and FIMC-IS (ISP).
-
-The sub-subdevices are defined as child nodes of the common 'camera' node which
-also includes common properties of the whole subsystem not really specific to
-any single sub-device, like common camera port pins or the CAMCLK clock outputs
-for external image sensors attached to an SoC.
-
-Common 'camera' node
---------------------
-
-Required properties:
-
-- compatible: must be "samsung,fimc", "simple-bus"
-- clocks: list of clock specifiers, corresponding to entries in
-  the clock-names property;
-- clock-names : must contain "sclk_cam0", "sclk_cam1", "pxl_async0",
-  "pxl_async1" entries, matching entries in the clocks property.
-
-- #clock-cells: from the common clock bindings (../clock/clock-bindings.txt),
-  must be 1. A clock provider is associated with the 'camera' node and it should
-  be referenced by external sensors that use clocks provided by the SoC on
-  CAM_*_CLKOUT pins. The clock specifier cell stores an index of a clock.
-  The indices are 0, 1 for CAM_A_CLKOUT, CAM_B_CLKOUT clocks respectively.
-
-- clock-output-names: from the common clock bindings, should contain names of
-  clocks registered by the camera subsystem corresponding to CAM_A_CLKOUT,
-  CAM_B_CLKOUT output clocks respectively.
-
-The pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt must be used
-to define a required pinctrl state named "default" and optional pinctrl states:
-"idle", "active-a", active-b". These optional states can be used to switch the
-camera port pinmux at runtime. The "idle" state should configure both the camera
-ports A and B into high impedance state, especially the CAMCLK clock output
-should be inactive. For the "active-a" state the camera port A must be activated
-and the port B deactivated and for the state "active-b" it should be the other
-way around.
-
-The 'camera' node must include at least one 'fimc' child node.
-
-
-'fimc' device nodes
--------------------
-
-Required properties:
-
-- compatible: "samsung,s5pv210-fimc" for S5PV210, "samsung,exynos4210-fimc"
-  for Exynos4210 and "samsung,exynos4212-fimc" for Exynos4x12 SoCs;
-- reg: physical base address and length of the registers set for the device;
-- interrupts: should contain FIMC interrupt;
-- clocks: list of clock specifiers, must contain an entry for each required
-  entry in clock-names;
-- clock-names: must contain "fimc", "sclk_fimc" entries.
-- samsung,pix-limits: an array of maximum supported image sizes in pixels, for
-  details refer to Table 2-1 in the S5PV210 SoC User Manual; The meaning of
-  each cell is as follows:
-  0 - scaler input horizontal size,
-  1 - input horizontal size for the scaler bypassed,
-  2 - REAL_WIDTH without input rotation,
-  3 - REAL_HEIGHT with input rotation,
-- samsung,sysreg: a phandle to the SYSREG node.
-
-Each FIMC device should have an alias in the aliases node, in the form of
-fimc<n>, where <n> is an integer specifying the IP block instance.
-
-Optional properties:
-
-- clock-frequency: maximum FIMC local clock (LCLK) frequency;
-- samsung,min-pix-sizes: an array specyfing minimum image size in pixels at
-  the FIMC input and output DMA, in the first and second cell respectively.
-  Default value when this property is not present is <16 16>;
-- samsung,min-pix-alignment: minimum supported image height alignment (first
-  cell) and the horizontal image offset (second cell). The values are in pixels
-  and default to <2 1> when this property is not present;
-- samsung,mainscaler-ext: a boolean property indicating whether the FIMC IP
-  supports extended image size and has CIEXTEN register;
-- samsung,rotators: a bitmask specifying whether this IP has the input and
-  the output rotator. Bits 4 and 0 correspond to input and output rotator
-  respectively. If a rotator is present its corresponding bit should be set.
-  Default value when this property is not specified is 0x11.
-- samsung,cam-if: a bolean property indicating whether the IP block includes
-  the camera input interface.
-- samsung,isp-wb: this property must be present if the IP block has the ISP
-  writeback input.
-- samsung,lcd-wb: this property must be present if the IP block has the LCD
-  writeback input.
-
-
-'parallel-ports' node
----------------------
-
-This node should contain child 'port' nodes specifying active parallel video
-input ports. It includes camera A and camera B inputs. 'reg' property in the
-port nodes specifies data input - 1, 2 indicates input A, B respectively.
-
-Optional properties
-
-- samsung,camclk-out (deprecated) : specifies clock output for remote sensor,
-  0 - CAM_A_CLKOUT, 1 - CAM_B_CLKOUT;
-
-Image sensor nodes
-------------------
-
-The sensor device nodes should be added to their control bus controller (e.g.
-I2C0) nodes and linked to a port node in the csis or the parallel-ports node,
-using the common video interfaces bindings, defined in video-interfaces.txt.
-
-Example:
-
-       aliases {
-               fimc0 = &fimc_0;
-       };
-
-       /* Parallel bus IF sensor */
-       i2c_0: i2c@13860000 {
-               s5k6aa: sensor@3c {
-                       compatible = "samsung,s5k6aafx";
-                       reg = <0x3c>;
-                       vddio-supply = <...>;
-
-                       clock-frequency = <24000000>;
-                       clocks = <&camera 1>;
-                       clock-names = "mclk";
-
-                       port {
-                               s5k6aa_ep: endpoint {
-                                       remote-endpoint = <&fimc0_ep>;
-                                       bus-width = <8>;
-                                       hsync-active = <0>;
-                                       vsync-active = <1>;
-                                       pclk-sample = <1>;
-                               };
-                       };
-               };
-
-               /* MIPI CSI-2 bus IF sensor */
-               s5c73m3: sensor@1a {
-                       compatible = "samsung,s5c73m3";
-                       reg = <0x1a>;
-                       vddio-supply = <...>;
-
-                       clock-frequency = <24000000>;
-                       clocks = <&camera 0>;
-                       clock-names = "mclk";
-
-                       port {
-                               s5c73m3_1: endpoint {
-                                       data-lanes = <1 2 3 4>;
-                                       remote-endpoint = <&csis0_ep>;
-                               };
-                       };
-               };
-       };
-
-       camera {
-               compatible = "samsung,fimc", "simple-bus";
-               clocks = <&clock 132>, <&clock 133>, <&clock 351>,
-                        <&clock 352>;
-               clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0",
-                             "pxl_async1";
-               #clock-cells = <1>;
-               clock-output-names = "cam_a_clkout", "cam_b_clkout";
-               pinctrl-names = "default";
-               pinctrl-0 = <&cam_port_a_clk_active>;
-               #address-cells = <1>;
-               #size-cells = <1>;
-
-               /* parallel camera ports */
-               parallel-ports {
-                       /* camera A input */
-                       port@1 {
-                               reg = <1>;
-                               fimc0_ep: endpoint {
-                                       remote-endpoint = <&s5k6aa_ep>;
-                                       bus-width = <8>;
-                                       hsync-active = <0>;
-                                       vsync-active = <1>;
-                                       pclk-sample = <1>;
-                               };
-                       };
-               };
-
-               fimc_0: fimc@11800000 {
-                       compatible = "samsung,exynos4210-fimc";
-                       reg = <0x11800000 0x1000>;
-                       interrupts = <0 85 0>;
-               };
-
-               csis_0: csis@11880000 {
-                       compatible = "samsung,exynos4210-csis";
-                       reg = <0x11880000 0x1000>;
-                       interrupts = <0 78 0>;
-                       /* camera C input */
-                       port@3 {
-                               reg = <3>;
-                               csis0_ep: endpoint {
-                                       remote-endpoint = <&s5c73m3_ep>;
-                                       data-lanes = <1 2 3 4>;
-                                       samsung,csis-hs-settle = <12>;
-                               };
-                       };
-               };
-       };
-
-The MIPI-CSIS device binding is defined in samsung-mipi-csis.txt.
diff --git a/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt b/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt
deleted file mode 100644 (file)
index a4149c9..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-Samsung S5P/Exynos SoC series MIPI CSI-2 receiver (MIPI CSIS)
--------------------------------------------------------------
-
-Required properties:
-
-- compatible     : "samsung,s5pv210-csis" for S5PV210 (S5PC110),
-                   "samsung,exynos4210-csis" for Exynos4210 (S5PC210),
-                   "samsung,exynos4212-csis" for Exynos4212/Exynos4412,
-                   "samsung,exynos5250-csis" for Exynos5250;
-- reg            : offset and length of the register set for the device;
-- interrupts      : should contain MIPI CSIS interrupt; the format of the
-                   interrupt specifier depends on the interrupt controller;
-- bus-width      : maximum number of data lanes supported (SoC specific);
-- vddio-supply    : MIPI CSIS I/O and PLL voltage supply (e.g. 1.8V);
-- vddcore-supply  : MIPI CSIS Core voltage supply (e.g. 1.1V);
-- clocks         : list of clock specifiers, corresponding to entries in
-                   clock-names property;
-- clock-names    : must contain "csis", "sclk_csis" entries, matching entries
-                   in the clocks property.
-
-Optional properties:
-
-- clock-frequency : The IP's main (system bus) clock frequency in Hz, default
-                   value when this property is not specified is 166 MHz;
-- samsung,csis-wclk : CSI-2 wrapper clock selection. If this property is present
-                   external clock from CMU will be used, or the bus clock if
-                   if it's not specified.
-
-The device node should contain one 'port' child node with one child 'endpoint'
-node, according to the bindings defined in Documentation/devicetree/bindings/
-media/video-interfaces.txt. The following are properties specific to those nodes.
-
-port node
----------
-
-- reg            : (required) must be 3 for camera C input (CSIS0) or 4 for
-                   camera D input (CSIS1);
-
-endpoint node
--------------
-
-- data-lanes     : (required) an array specifying active physical MIPI-CSI2
-                   data input lanes and their mapping to logical lanes; the
-                   array's content is unused, only its length is meaningful;
-
-- samsung,csis-hs-settle : (optional) differential receiver (HS-RX) settle time;
-
-
-Example:
-
-       reg0: regulator@0 {
-       };
-
-       reg1: regulator@1 {
-       };
-
-/* SoC properties */
-
-       csis_0: csis@11880000 {
-               compatible = "samsung,exynos4210-csis";
-               reg = <0x11880000 0x1000>;
-               interrupts = <0 78 0>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-       };
-
-/* Board properties */
-
-       csis_0: csis@11880000 {
-               clock-frequency = <166000000>;
-               vddio-supply = <&reg0>;
-               vddcore-supply = <&reg1>;
-               port {
-                       reg = <3>; /* 3 - CSIS0, 4 - CSIS1 */
-                       csis0_ep: endpoint {
-                               remote-endpoint = <...>;
-                               data-lanes = <1>, <2>;
-                               samsung,csis-hs-settle = <12>;
-                       };
-               };
-       };
diff --git a/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
deleted file mode 100644 (file)
index f0ea9ad..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-Samsung S5C73M3 8Mp camera ISP
-------------------------------
-
-The S5C73M3 camera ISP supports MIPI CSI-2 and parallel (ITU-R BT.656) video
-data busses. The I2C bus is the main control bus and additionally the SPI bus
-is used, mostly for transferring the firmware to and from the device. Two
-slave device nodes corresponding to these control bus interfaces are required
-and should be placed under respective bus controller nodes.
-
-I2C slave device node
----------------------
-
-Required properties:
-
-- compatible       : "samsung,s5c73m3";
-- reg              : I2C slave address of the sensor;
-- vdd-int-supply    : digital power supply (1.2V);
-- vdda-supply      : analog power supply (1.2V);
-- vdd-reg-supply    : regulator input power supply (2.8V);
-- vddio-host-supply : host I/O power supply (1.8V to 2.8V);
-- vddio-cis-supply  : CIS I/O power supply (1.2V to 1.8V);
-- vdd-af-supply     : lens power supply (2.8V);
-- xshutdown-gpios   : specifier of GPIO connected to the XSHUTDOWN pin;
-- standby-gpios     : specifier of GPIO connected to the STANDBY pin;
-- clocks           : should contain list of phandle and clock specifier pairs
-                     according to common clock bindings for the clocks described
-                     in the clock-names property;
-- clock-names      : should contain "cis_extclk" entry for the CIS_EXTCLK clock;
-
-Optional properties:
-
-- clock-frequency   : the frequency at which the "cis_extclk" clock should be
-                     configured to operate, in Hz; if this property is not
-                     specified default 24 MHz value will be used.
-
-The common video interfaces bindings (see video-interfaces.txt) should be used
-to specify link from the S5C73M3 to an external image data receiver. The S5C73M3
-device node should contain one 'port' child node with an 'endpoint' subnode for
-this purpose. The data link from a raw image sensor to the S5C73M3 can be
-similarly specified, but it is optional since the S5C73M3 ISP and a raw image
-sensor are usually inseparable and form a hybrid module.
-
-Following properties are valid for the endpoint node(s):
-
-endpoint subnode
-----------------
-
-- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
-  video-interfaces.txt. This sensor doesn't support data lane remapping
-  and physical lane indexes in subsequent elements of the array should
-  be only consecutive ascending values.
-
-SPI device node
----------------
-
-Required properties:
-
-- compatible       : "samsung,s5c73m3";
-
-For more details see description of the SPI busses bindings
-(../spi/spi-bus.txt) and bindings of a specific bus controller.
-
-Example:
-
-i2c@138a000000 {
-       ...
-       s5c73m3@3c {
-               compatible = "samsung,s5c73m3";
-               reg = <0x3c>;
-               vdd-int-supply = <&buck9_reg>;
-               vdda-supply = <&ldo17_reg>;
-               vdd-reg-supply = <&cam_io_reg>;
-               vddio-host-supply = <&ldo18_reg>;
-               vddio-cis-supply = <&ldo9_reg>;
-               vdd-af-supply = <&cam_af_reg>;
-               clock-frequency = <24000000>;
-               clocks = <&clk 0>;
-               clock-names = "cis_extclk";
-               xshutdown-gpios = <&gpf1 3 1>;
-               standby-gpios = <&gpm0 1 1>;
-               port {
-                       s5c73m3_ep: endpoint {
-                               remote-endpoint = <&csis0_ep>;
-                               data-lanes = <1 2 3 4>;
-                       };
-               };
-       };
-};
-
-spi@1392000 {
-       ...
-       s5c73m3_spi: s5c73m3@0 {
-               compatible = "samsung,s5c73m3";
-               reg = <0>;
-               ...
-       };
-};
diff --git a/Documentation/devicetree/bindings/media/samsung-s5k5baf.txt b/Documentation/devicetree/bindings/media/samsung-s5k5baf.txt
deleted file mode 100644 (file)
index 1f51e04..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-Samsung S5K5BAF UXGA 1/5" 2M CMOS Image Sensor with embedded SoC ISP
---------------------------------------------------------------------
-
-Required properties:
-
-- compatible     : "samsung,s5k5baf";
-- reg            : I2C slave address of the sensor;
-- vdda-supply    : analog power supply 2.8V (2.6V to 3.0V);
-- vddreg-supply          : regulator input power supply 1.8V (1.7V to 1.9V)
-                   or 2.8V (2.6V to 3.0);
-- vddio-supply   : I/O power supply 1.8V (1.65V to 1.95V)
-                   or 2.8V (2.5V to 3.1V);
-- stbyn-gpios    : GPIO connected to STDBYN pin;
-- rstn-gpios     : GPIO connected to RSTN pin;
-- clocks         : list of phandle and clock specifier pairs
-                   according to common clock bindings for the
-                   clocks described in clock-names;
-- clock-names    : should include "mclk" for the sensor's master clock;
-
-Optional properties:
-
-- clock-frequency : the frequency at which the "mclk" clock should be
-                   configured to operate, in Hz; if this property is not
-                   specified default 24 MHz value will be used.
-
-The device node should contain one 'port' child node with one child 'endpoint'
-node, according to the bindings defined in Documentation/devicetree/bindings/
-media/video-interfaces.txt. The following are properties specific to those
-nodes.
-
-endpoint node
--------------
-
-- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
-              video-interfaces.txt. If present it should be <1> - the device
-              supports only one data lane without re-mapping.
-
-Example:
-
-s5k5bafx@2d {
-       compatible = "samsung,s5k5baf";
-       reg = <0x2d>;
-       vdda-supply = <&cam_io_en_reg>;
-       vddreg-supply = <&vt_core_15v_reg>;
-       vddio-supply = <&vtcam_reg>;
-       stbyn-gpios = <&gpl2 0 1>;
-       rstn-gpios = <&gpl2 1 1>;
-       clock-names = "mclk";
-       clocks = <&clock_cam 0>;
-       clock-frequency = <24000000>;
-
-       port {
-               s5k5bafx_ep: endpoint {
-                       remote-endpoint = <&csis1_ep>;
-                       data-lanes = <1>;
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/media/samsung-s5k6a3.txt b/Documentation/devicetree/bindings/media/samsung-s5k6a3.txt
deleted file mode 100644 (file)
index cce01e8..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-Samsung S5K6A3(YX) raw image sensor
----------------------------------
-
-S5K6A3(YX) is a raw image sensor with MIPI CSI-2 and CCP2 image data interfaces
-and CCI (I2C compatible) control bus.
-
-Required properties:
-
-- compatible   : "samsung,s5k6a3";
-- reg          : I2C slave address of the sensor;
-- svdda-supply : core voltage supply;
-- svddio-supply        : I/O voltage supply;
-- afvdd-supply : AF (actuator) voltage supply;
-- gpios                : specifier of a GPIO connected to the RESET pin;
-- clocks       : should contain list of phandle and clock specifier pairs
-                 according to common clock bindings for the clocks described
-                 in the clock-names property;
-- clock-names  : should contain "extclk" entry for the sensor's EXTCLK clock;
-
-Optional properties:
-
-- clock-frequency : the frequency at which the "extclk" clock should be
-                   configured to operate, in Hz; if this property is not
-                   specified default 24 MHz value will be used.
-
-The common video interfaces bindings (see video-interfaces.txt) should be
-used to specify link to the image data receiver. The S5K6A3(YX) device
-node should contain one 'port' child node with an 'endpoint' subnode.
-
-Following properties are valid for the endpoint node:
-
-- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
-  video-interfaces.txt.  The sensor supports only one data lane.
diff --git a/Documentation/devicetree/bindings/media/si470x.txt b/Documentation/devicetree/bindings/media/si470x.txt
deleted file mode 100644 (file)
index a940355..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-* Silicon Labs FM Radio receiver
-
-The Silicon Labs Si470x is family of FM radio receivers with receive power scan
-supporting 76-108 MHz, programmable through an I2C interface.
-Some of them includes an RDS encoder.
-
-Required Properties:
-- compatible: Should contain "silabs,si470x"
-- reg: the I2C address of the device
-
-Optional Properties:
-- interrupts : The interrupt number
-- reset-gpios: GPIO specifier for the chips reset line
-
-Example:
-
-&i2c2 {
-        si470x@63 {
-                compatible = "silabs,si470x";
-                reg = <0x63>;
-
-                interrupt-parent = <&gpj2>;
-                interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
-                reset-gpios = <&gpj2 5 GPIO_ACTIVE_HIGH>;
-        };
-};
diff --git a/Documentation/devicetree/bindings/media/silabs,si470x.yaml b/Documentation/devicetree/bindings/media/silabs,si470x.yaml
new file mode 100644 (file)
index 0000000..a3d19c5
--- /dev/null
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/silabs,si470x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Silicon Labs Si470x FM Radio Receiver
+
+maintainers:
+  - Hans Verkuil <hverkuil@xs4all.nl>
+  - PaweÅ‚ Chmiel <pawel.mikolaj.chmiel@gmail.com>
+
+properties:
+  compatible:
+    const: silabs,si470x
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  reset-gpios:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        fmradio@10 {
+            compatible = "silabs,si470x";
+            reg = <0x10>;
+            interrupt-parent = <&gpj2>;
+            interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+            reset-gpios = <&gpj2 5 GPIO_ACTIVE_HIGH>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/media/st,stm32-cec.yaml b/Documentation/devicetree/bindings/media/st,stm32-cec.yaml
deleted file mode 100644 (file)
index 7f545a5..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/media/st,stm32-cec.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: STMicroelectronics STM32 CEC
-
-maintainers:
-  - Yannick Fertre <yannick.fertre@foss.st.com>
-
-properties:
-  compatible:
-    const: st,stm32-cec
-
-  reg:
-    maxItems: 1
-
-  interrupts:
-    maxItems: 1
-
-  clocks:
-    items:
-      - description: Module Clock
-      - description: Bus Clock
-
-  clock-names:
-    items:
-      - const: cec
-      - const: hdmi-cec
-
-required:
-  - compatible
-  - reg
-  - interrupts
-  - clocks
-  - clock-names
-
-additionalProperties: false
-
-examples:
-  - |
-    #include <dt-bindings/interrupt-controller/arm-gic.h>
-    #include <dt-bindings/clock/stm32mp1-clks.h>
-    cec: cec@40006c00 {
-        compatible = "st,stm32-cec";
-        reg = <0x40006c00 0x400>;
-        interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
-        clocks = <&rcc CEC_K>, <&clk_lse>;
-        clock-names = "cec", "hdmi-cec";
-    };
-
-...
index f8e4d260d10a03a8a4251c4ad4f4c79a827360e1..478bdbe3d759597e0ba5a686b2974302546d5abc 100644 (file)
@@ -47,7 +47,7 @@ properties:
     maxItems: 1
 
   ti,camerrx-control:
-    $ref: "/schemas/types.yaml#/definitions/phandle-array"
+    $ref: /schemas/types.yaml#/definitions/phandle-array
     items:
       - items:
           - description: phandle to device control module
index b461c8aa2a1664874a4f9f3f31fa4d6118f9f866..7389204afcb8235abf733026f09ea447891f9069 100644 (file)
@@ -56,6 +56,28 @@ analogue data is never read from the pixel matrix that are outside the
 configured selection rectangle that designates crop. The difference has an
 effect in device timing and likely also in power consumption.
 
+CCS static data
+---------------
+
+The MIPI CCS driver supports CCS static data for all compliant devices,
+including not just those compliant with CCS 1.1 but also CCS 1.0 and SMIA(++).
+For CCS the file names are formed as
+
+       ccs/ccs-sensor-vvvv-mmmm-rrrr.fw (sensor) and
+       ccs/ccs-module-vvvv-mmmm-rrrr.fw (module).
+
+For SMIA++ compliant devices the corresponding file names are
+
+       ccs/smiapp-sensor-vv-mmmm-rr.fw (sensor) and
+       ccs/smiapp-module-vv-mmmm-rrrr.fw (module).
+
+For SMIA (non-++) compliant devices the static data file name is
+
+       ccs/smia-sensor-vv-mmmm-rr.fw (sensor).
+
+vvvv or vv denotes MIPI and SMIA manufacturer IDs respectively, mmmm model ID
+and rrrr or rr revision number.
+
 Register definition generator
 -----------------------------
 
index 4f4b23b95b9b525893670294c8ceb7ab1e018771..d52977120b419c45da20026452e0bbd353b39106 100644 (file)
@@ -67,6 +67,7 @@ ioctls must be supported by all video overlay devices.
 Setup
 =====
 
+*Note: support for this has been removed.*
 Before overlay can commence applications must program the driver with
 frame buffer parameters, namely the address and size of the frame buffer
 and the image format, for example RGB 5:6:5. The
@@ -92,11 +93,13 @@ A driver may support any (or none) of five clipping/blending methods:
 1. Chroma-keying displays the overlaid image only where pixels in the
    primary graphics surface assume a certain color.
 
-2. A bitmap can be specified where each bit corresponds to a pixel in
+2. *Note: support for this has been removed.*
+   A bitmap can be specified where each bit corresponds to a pixel in
    the overlaid image. When the bit is set, the corresponding video
    pixel is displayed, otherwise a pixel of the graphics surface.
 
-3. A list of clipping rectangles can be specified. In these regions *no*
+3. *Note: support for this has been removed.*
+   A list of clipping rectangles can be specified. In these regions *no*
    video is displayed, so the graphics surface can be seen here.
 
 4. The framebuffer has an alpha channel that can be used to clip or
@@ -185,6 +188,7 @@ struct v4l2_window
     be 0xRRGGBB on a little endian, 0xBBGGRR on a big endian host.
 
 ``struct v4l2_clip * clips``
+    *Note: support for this has been removed.*
     When chroma-keying has *not* been negotiated and
     :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>` indicated this capability,
     applications can set this field to point to an array of clipping
@@ -201,6 +205,7 @@ struct v4l2_window
     are undefined.
 
 ``__u32 clipcount``
+    *Note: support for this has been removed.*
     When the application set the ``clips`` field, this field must
     contain the number of clipping rectangles in the list. When clip
     lists are not supported the driver ignores this field, its contents
@@ -208,6 +213,7 @@ struct v4l2_window
     supported but no clipping is desired this field must be set to zero.
 
 ``void * bitmap``
+    *Note: support for this has been removed.*
     When chroma-keying has *not* been negotiated and
     :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>` indicated this capability,
     applications can set this field to point to a clipping bit mask.
index 506dd3c988841e714949807df7f3c3e3dc5515f2..06b78e5589d27eda1bf1f9502eb9d7aef4d2486c 100644 (file)
@@ -88,6 +88,11 @@ Compressed Formats
       - ``V4L2_PIX_FMT_H263``
       - 'H263'
       - H263 video elementary stream.
+    * .. _V4L2-PIX-FMT-SPK:
+
+      - ``V4L2_PIX_FMT_SPK``
+      - 'SPK0'
+      - Sorenson Spark is an implementation of H.263 for use in Flash Video and Adobe Flash files
     * .. _V4L2-PIX-FMT-MPEG1:
 
       - ``V4L2_PIX_FMT_MPEG1``
@@ -232,6 +237,26 @@ Compressed Formats
         Metadata associated with the frame to decode is required to be passed
         through the ``V4L2_CID_STATELESS_FWHT_PARAMS`` control.
        See the :ref:`associated Codec Control ID <codec-stateless-fwht>`.
+    * .. _V4L2-PIX-FMT-RV30:
+
+      - ``V4L2_PIX_FMT_RV30``
+      - 'RV30'
+      - RealVideo, or also spelled as Real Video, is a suite of
+        proprietary video compression formats developed by
+        RealNetworks - the specific format changes with the version.
+        RealVideo codecs are identified by four-character codes.
+        RV30 corresponds to RealVideo 8, suspected to be based
+        largely on an early draft of H.264
+    * .. _V4L2-PIX-FMT-RV40:
+
+      - ``V4L2_PIX_FMT_RV40``
+      - 'RV40'
+      - RV40 represents RealVideo 9 and RealVideo 10.
+        RealVideo 9, suspected to be based on H.264.
+        RealVideo 10, aka RV9 EHQ, This refers to an improved encoder
+        for the RV9 format that is fully backwards compatible with
+        RV9 players - the format and decoder did not change, only
+        the encoder did. As a result, it uses the same FourCC.
 
 .. raw:: latex
 
index 24a7715420594a1b8e5c17f09aef0f7b8a07a16b..9f111ed594d275fa161e835dd579ac0c6d51d8ca 100644 (file)
@@ -257,6 +257,34 @@ the second byte and Y'\ :sub:`7-0` in the third byte.
     - The padding bits contain undefined values that must be ignored by all
       applications and drivers.
 
+The next table lists the packed YUV 4:4:4 formats with 12 bits per component.
+Expand the bits per component to 16 bits, data in the high bits, zeros in the low bits,
+arranged in little endian order, storing 1 pixel in 6 bytes.
+
+.. flat-table:: Packed YUV 4:4:4 Image Formats (12bpc)
+    :header-rows: 1
+    :stub-columns: 0
+
+    * - Identifier
+      - Code
+      - Byte 1-0
+      - Byte 3-2
+      - Byte 5-4
+      - Byte 7-6
+      - Byte 9-8
+      - Byte 11-10
+
+    * .. _V4L2-PIX-FMT-YUV48-12:
+
+      - ``V4L2_PIX_FMT_YUV48_12``
+      - 'Y312'
+
+      - Y'\ :sub:`0`
+      - Cb\ :sub:`0`
+      - Cr\ :sub:`0`
+      - Y'\ :sub:`1`
+      - Cb\ :sub:`1`
+      - Cr\ :sub:`1`
 
 4:2:2 Subsampling
 =================
index d9d7b7621d8cef4fb597122c30e7a4f856151fb9..b71b80d634d6f79322e374453bd2233e21a75c2e 100644 (file)
@@ -953,6 +953,48 @@ number of bits for each component.
 
     \endgroup
 
+12 Bits Per Component
+==============================
+
+These formats store an RGB triplet in six or eight bytes, with 12 bits per component.
+Expand the bits per component to 16 bits, data in the high bits, zeros in the low bits,
+arranged in little endian order.
+
+.. raw:: latex
+
+    \small
+
+.. flat-table:: RGB Formats With 12 Bits Per Component
+    :header-rows:  1
+
+    * - Identifier
+      - Code
+      - Byte 1-0
+      - Byte 3-2
+      - Byte 5-4
+      - Byte 7-6
+    * .. _V4L2-PIX-FMT-BGR48-12:
+
+      - ``V4L2_PIX_FMT_BGR48_12``
+      - 'B312'
+
+      - B\ :sub:`15-4`
+      - G\ :sub:`15-4`
+      - R\ :sub:`15-4`
+      -
+    * .. _V4L2-PIX-FMT-ABGR64-12:
+
+      - ``V4L2_PIX_FMT_ABGR64_12``
+      - 'B412'
+
+      - B\ :sub:`15-4`
+      - G\ :sub:`15-4`
+      - R\ :sub:`15-4`
+      - A\ :sub:`15-4`
+
+.. raw:: latex
+
+    \normalsize
 
 Deprecated RGB Formats
 ======================
index 62078a01de76241f5c0be307ba4ac8b96651e26d..cf8e4dfbfbd41df077d7aeaa9f3c0ff8b985fa36 100644 (file)
@@ -103,6 +103,17 @@ are often referred to as greyscale formats.
       - ...
       - ...
 
+    * .. _V4L2-PIX-FMT-Y012:
+
+      - ``V4L2_PIX_FMT_Y012``
+      - 'Y012'
+
+      - Y'\ :sub:`0`\ [3:0] `0000`
+      - Y'\ :sub:`0`\ [11:4]
+      - ...
+      - ...
+      - ...
+
     * .. _V4L2-PIX-FMT-Y14:
 
       - ``V4L2_PIX_FMT_Y14``
@@ -146,3 +157,7 @@ are often referred to as greyscale formats.
     than 16 bits. For example, 10 bits per pixel uses values in the range 0 to
     1023. For the IPU3_Y10 format 25 pixels are packed into 32 bytes, which
     leaves the 6 most significant bits of the last byte padded with 0.
+
+    For Y012 and Y12 formats, Y012 places its data in the 12 high bits, with
+    padding zeros in the 4 low bits, in contrast to the Y12 format, which has
+    its padding located in the most significant bits of the 16 bit word.
index f1d5bb7b806dc00b0348cf2f7a0e7ad99929db58..72324274f20c945284c138b43f28f5ac28c592a0 100644 (file)
@@ -123,6 +123,20 @@ All components are stored with the same number of bits per component.
       - Cb, Cr
       - Yes
       - 4x4 tiles
+    * - V4L2_PIX_FMT_P012
+      - 'P012'
+      - 12
+      - 4:2:0
+      - Cb, Cr
+      - Yes
+      - Linear
+    * - V4L2_PIX_FMT_P012M
+      - 'PM12'
+      - 12
+      - 4:2:0
+      - Cb, Cr
+      - No
+      - Linear
     * - V4L2_PIX_FMT_NV16
       - 'NV16'
       - 8
@@ -586,6 +600,86 @@ Data in the 10 high bits, zeros in the 6 low bits, arranged in little endian ord
       - Cb\ :sub:`11`
       - Cr\ :sub:`11`
 
+.. _V4L2-PIX-FMT-P012:
+.. _V4L2-PIX-FMT-P012M:
+
+P012 and P012M
+--------------
+
+P012 is like NV12 with 12 bits per component, expanded to 16 bits.
+Data in the 12 high bits, zeros in the 4 low bits, arranged in little endian order.
+
+.. flat-table:: Sample 4x4 P012 Image
+    :header-rows:  0
+    :stub-columns: 0
+
+    * - start + 0:
+      - Y'\ :sub:`00`
+      - Y'\ :sub:`01`
+      - Y'\ :sub:`02`
+      - Y'\ :sub:`03`
+    * - start + 8:
+      - Y'\ :sub:`10`
+      - Y'\ :sub:`11`
+      - Y'\ :sub:`12`
+      - Y'\ :sub:`13`
+    * - start + 16:
+      - Y'\ :sub:`20`
+      - Y'\ :sub:`21`
+      - Y'\ :sub:`22`
+      - Y'\ :sub:`23`
+    * - start + 24:
+      - Y'\ :sub:`30`
+      - Y'\ :sub:`31`
+      - Y'\ :sub:`32`
+      - Y'\ :sub:`33`
+    * - start + 32:
+      - Cb\ :sub:`00`
+      - Cr\ :sub:`00`
+      - Cb\ :sub:`01`
+      - Cr\ :sub:`01`
+    * - start + 40:
+      - Cb\ :sub:`10`
+      - Cr\ :sub:`10`
+      - Cb\ :sub:`11`
+      - Cr\ :sub:`11`
+
+.. flat-table:: Sample 4x4 P012M Image
+    :header-rows:  0
+    :stub-columns: 0
+
+    * - start0 + 0:
+      - Y'\ :sub:`00`
+      - Y'\ :sub:`01`
+      - Y'\ :sub:`02`
+      - Y'\ :sub:`03`
+    * - start0 + 8:
+      - Y'\ :sub:`10`
+      - Y'\ :sub:`11`
+      - Y'\ :sub:`12`
+      - Y'\ :sub:`13`
+    * - start0 + 16:
+      - Y'\ :sub:`20`
+      - Y'\ :sub:`21`
+      - Y'\ :sub:`22`
+      - Y'\ :sub:`23`
+    * - start0 + 24:
+      - Y'\ :sub:`30`
+      - Y'\ :sub:`31`
+      - Y'\ :sub:`32`
+      - Y'\ :sub:`33`
+    * -
+    * - start1 + 0:
+      - Cb\ :sub:`00`
+      - Cr\ :sub:`00`
+      - Cb\ :sub:`01`
+      - Cr\ :sub:`01`
+    * - start1 + 8:
+      - Cb\ :sub:`10`
+      - Cr\ :sub:`10`
+      - Cb\ :sub:`11`
+      - Cr\ :sub:`11`
+
 
 Fully Planar YUV Formats
 ========================
index 228c1521f190e91e375fccc33b619a7c93e2f30f..15ff0bf7bbe6224f9b9119f3d7d94eb505933645 100644 (file)
@@ -72,6 +72,7 @@ Function Reference
     vidioc-subdev-g-frame-interval
     vidioc-subdev-g-routing
     vidioc-subdev-g-selection
+    vidioc-subdev-g-client-cap
     vidioc-subdev-querycap
     vidioc-subscribe-event
     func-mmap
index 892cfeb8b9880b733bfbe05c275dfb719bfa1a70..5292d5e1a91f6f39d7801d6c92efd79822118a6b 100644 (file)
@@ -185,6 +185,16 @@ still cause this situation.
       - ``p_u32``
       - A pointer to a matrix control of unsigned 32-bit values. Valid if
        this control is of type ``V4L2_CTRL_TYPE_U32``.
+    * - __u32 *
+      - ``p_s32``
+      - A pointer to a matrix control of signed 32-bit values. Valid if
+        this control is of type ``V4L2_CTRL_TYPE_INTEGER`` and
+        ``V4L2_CTRL_FLAG_HAS_PAYLOAD`` is set.
+    * - __u32 *
+      - ``p_s64``
+      - A pointer to a matrix control of signed 64-bit values. Valid if
+        this control is of type ``V4L2_CTRL_TYPE_INTEGER64`` and
+        ``V4L2_CTRL_FLAG_HAS_PAYLOAD`` is set.
     * - struct :c:type:`v4l2_area` *
       - ``p_area``
       - A pointer to a struct :c:type:`v4l2_area`. Valid if this control is
index b6cc1a82320751d37354a5aca08a68433baa1e46..b651e53643dd1f744145e1a90b68993a13ea2301 100644 (file)
@@ -49,6 +49,9 @@ of a graphics card. A non-destructive overlay blends video images into a
 VGA signal or graphics into a video signal. *Video Output Overlays* are
 always non-destructive.
 
+Destructive overlay support has been removed: with modern GPUs and CPUs
+this is no longer needed, and it was always a very dangerous feature.
+
 To get the current parameters applications call the :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`
 ioctl with a pointer to a struct :c:type:`v4l2_framebuffer`
 structure. The driver fills all fields of the structure or returns an
@@ -63,18 +66,12 @@ this structure, the driver prepares for the overlay and returns the
 framebuffer parameters as :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>` does, or it returns an error
 code.
 
-To set the parameters for a *non-destructive Video Overlay*,
+To set the parameters for a *Video Capture Overlay*
 applications must initialize the ``flags`` field, the ``fmt``
 substructure, and call :ref:`VIDIOC_S_FBUF <VIDIOC_G_FBUF>`. Again the driver prepares for
 the overlay and returns the framebuffer parameters as :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`
 does, or it returns an error code.
 
-For a *destructive Video Overlay* applications must additionally provide
-a ``base`` address. Setting up a DMA to a random memory location can
-jeopardize the system security, its stability or even damage the
-hardware, therefore only the superuser can set the parameters for a
-destructive video overlay.
-
 .. tabularcolumns:: |p{3.5cm}|p{3.5cm}|p{3.5cm}|p{6.6cm}|
 
 .. c:type:: v4l2_framebuffer
@@ -100,17 +97,14 @@ destructive video overlay.
       - ``base``
       -
       - Physical base address of the framebuffer, that is the address of
-       the pixel in the top left corner of the framebuffer. [#f1]_
-    * -
-      -
-      -
-      - This field is irrelevant to *non-destructive Video Overlays*. For
-       *destructive Video Overlays* applications must provide a base
-       address. The driver may accept only base addresses which are a
-       multiple of two, four or eight bytes. For *Video Output Overlays*
-       the driver must return a valid base address, so applications can
+       the pixel in the top left corner of the framebuffer.
+       For :ref:`VIDIOC_S_FBUF <VIDIOC_G_FBUF>` this field is no longer supported
+       and the kernel will always set this to NULL.
+       For *Video Output Overlays*
+       the driver will return a valid base address, so applications can
        find the corresponding Linux framebuffer device (see
-       :ref:`osd`).
+       :ref:`osd`). For *Video Capture Overlays* this field will always be
+       NULL.
     * - struct
       - ``fmt``
       -
@@ -136,8 +130,7 @@ destructive video overlay.
     * -
       -
       -
-      - For *destructive Video Overlays* applications must initialize this
-       field. For *Video Output Overlays* the driver must return a valid
+      - For *Video Output Overlays* the driver must return a valid
        format.
     * -
       -
@@ -165,13 +158,6 @@ destructive video overlay.
 
        This field is irrelevant to *non-destructive Video Overlays*.
 
-       For *destructive Video Overlays* both applications and drivers can
-       set this field to request padding bytes at the end of each line.
-       Drivers however may ignore the requested value, returning
-       ``width`` times bytes-per-pixel or a larger value required by the
-       hardware. That implies applications can just set this field to
-       zero to get a reasonable default.
-
        For *Video Output Overlays* the driver must return a valid value.
 
        Video hardware may access padding bytes, therefore they must
@@ -190,9 +176,8 @@ destructive video overlay.
     * -
       - __u32
       - ``sizeimage``
-      - This field is irrelevant to *non-destructive Video Overlays*. For
-       *destructive Video Overlays* applications must initialize this
-       field. For *Video Output Overlays* the driver must return a valid
+      - This field is irrelevant to *non-destructive Video Overlays*.
+       For *Video Output Overlays* the driver must return a valid
        format.
 
        Together with ``base`` it defines the framebuffer memory
@@ -232,9 +217,11 @@ destructive video overlay.
     * - ``V4L2_FBUF_CAP_LIST_CLIPPING``
       - 0x0004
       - The device supports clipping using a list of clip rectangles.
+        Note that this is no longer supported.
     * - ``V4L2_FBUF_CAP_BITMAP_CLIPPING``
       - 0x0008
       - The device supports clipping using a bit mask.
+        Note that this is no longer supported.
     * - ``V4L2_FBUF_CAP_LOCAL_ALPHA``
       - 0x0010
       - The device supports clipping/blending using the alpha channel of
@@ -342,10 +329,3 @@ EPERM
 
 EINVAL
     The :ref:`VIDIOC_S_FBUF <VIDIOC_G_FBUF>` parameters are unsuitable.
-
-.. [#f1]
-   A physical base address may not suit all platforms. GK notes in
-   theory we should pass something like PCI device + memory region +
-   offset instead. If you encounter problems please discuss on the
-   linux-media mailing list:
-   `https://linuxtv.org/lists.php <https://linuxtv.org/lists.php>`__.
index 3ef361c0dca7a4c6c5ef34ea5610aafea61c68ab..e3ae84df5486c00fc903fb498ccc5949284f898a 100644 (file)
@@ -31,18 +31,30 @@ Arguments
 Description
 ===========
 
-This ioctl allows applications to enumerate all frame sizes supported by
-a sub-device on the given pad for the given media bus format. Supported
-formats can be retrieved with the
+This ioctl allows applications to access the enumeration of frame sizes
+supported by a sub-device on the specified pad
+for the specified media bus format.
+Supported formats can be retrieved with the
 :ref:`VIDIOC_SUBDEV_ENUM_MBUS_CODE`
 ioctl.
 
-To enumerate frame sizes applications initialize the ``pad``, ``which``
-, ``code`` and ``index`` fields of the struct
-:c:type:`v4l2_subdev_mbus_code_enum` and
-call the :ref:`VIDIOC_SUBDEV_ENUM_FRAME_SIZE` ioctl with a pointer to the
-structure. Drivers fill the minimum and maximum frame sizes or return an
-EINVAL error code if one of the input parameters is invalid.
+The enumerations are defined by the driver, and indexed using the ``index`` field
+of the struct :c:type:`v4l2_subdev_frame_size_enum`.
+Each pair of ``pad`` and ``code`` correspond to a separate enumeration.
+Each enumeration starts with the ``index`` of 0, and
+the lowest invalid index marks the end of the enumeration.
+
+Therefore, to enumerate frame sizes allowed on the specified pad
+and using the specified mbus format, initialize the
+``pad``, ``which``, and ``code`` fields to desired values,
+and set ``index`` to 0.
+Then call the :ref:`VIDIOC_SUBDEV_ENUM_FRAME_SIZE` ioctl with a pointer to the
+structure.
+
+A successful call will return with minimum and maximum frame sizes filled in.
+Repeat with increasing ``index`` until ``EINVAL`` is received.
+``EINVAL`` means that either no more entries are available in the enumeration,
+or that an input parameter was invalid.
 
 Sub-devices that only support discrete frame sizes (such as most
 sensors) will return one or more frame sizes with identical minimum and
@@ -72,26 +84,28 @@ information about try formats.
 
     * - __u32
       - ``index``
-      - Number of the format in the enumeration, set by the application.
+      - Index of the frame size in the enumeration belonging to the given pad
+       and format. Filled in by the application.
     * - __u32
       - ``pad``
       - Pad number as reported by the media controller API.
+       Filled in by the application.
     * - __u32
       - ``code``
       - The media bus format code, as defined in
-       :ref:`v4l2-mbus-format`.
+       :ref:`v4l2-mbus-format`. Filled in by the application.
     * - __u32
       - ``min_width``
-      - Minimum frame width, in pixels.
+      - Minimum frame width, in pixels. Filled in by the driver.
     * - __u32
       - ``max_width``
-      - Maximum frame width, in pixels.
+      - Maximum frame width, in pixels. Filled in by the driver.
     * - __u32
       - ``min_height``
-      - Minimum frame height, in pixels.
+      - Minimum frame height, in pixels. Filled in by the driver.
     * - __u32
       - ``max_height``
-      - Maximum frame height, in pixels.
+      - Maximum frame height, in pixels. Filled in by the driver.
     * - __u32
       - ``which``
       - Frame sizes to be enumerated, from enum
index 248f6f9ee7c59fd36d52f45d67a67bdcb56264d2..4ad7dec27e259812743f644f2381438ffbbd1084 100644 (file)
@@ -31,15 +31,28 @@ Arguments
 Description
 ===========
 
-To enumerate media bus formats available at a given sub-device pad
-applications initialize the ``pad``, ``which`` and ``index`` fields of
-struct
-:c:type:`v4l2_subdev_mbus_code_enum` and
-call the :ref:`VIDIOC_SUBDEV_ENUM_MBUS_CODE` ioctl with a pointer to this
-structure. Drivers fill the rest of the structure or return an ``EINVAL``
-error code if either the ``pad`` or ``index`` are invalid. All media bus
-formats are enumerable by beginning at index zero and incrementing by
-one until ``EINVAL`` is returned.
+This call is used by the application to access the enumeration
+of media bus formats for the selected pad.
+
+The enumerations are defined by the driver, and indexed using the ``index`` field
+of struct :c:type:`v4l2_subdev_mbus_code_enum`.
+Each enumeration starts with the ``index`` of 0, and
+the lowest invalid index marks the end of enumeration.
+
+Therefore, to enumerate media bus formats available at a given sub-device pad,
+initialize the ``pad``, and ``which`` fields to desired values,
+and set ``index`` to 0.
+Then call the :ref:`VIDIOC_SUBDEV_ENUM_MBUS_CODE` ioctl
+with a pointer to this structure.
+
+A successful call will return with the ``code`` field filled in
+with a mbus code value.
+Repeat with increasing ``index`` until ``EINVAL`` is received.
+``EINVAL`` means that either ``pad`` is invalid,
+or that there are no more codes available at this pad.
+
+The driver must not return the same value of ``code`` for different indices
+at the same pad.
 
 Available media bus formats may depend on the current 'try' formats at
 other pads of the sub-device, as well as on the current active links.
@@ -57,14 +70,16 @@ information about the try formats.
 
     * - __u32
       - ``pad``
-      - Pad number as reported by the media controller API.
+      - Pad number as reported by the media controller API. Filled in by the
+        application.
     * - __u32
       - ``index``
-      - Number of the format in the enumeration, set by the application.
+      - Index of the mbus code in the enumeration belonging to the given pad.
+        Filled in by the application.
     * - __u32
       - ``code``
       - The media bus format code, as defined in
-       :ref:`v4l2-mbus-format`.
+       :ref:`v4l2-mbus-format`. Filled in by the driver.
     * - __u32
       - ``which``
       - Media bus format codes to be enumerated, from enum
diff --git a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst
new file mode 100644 (file)
index 0000000..20f12a1
--- /dev/null
@@ -0,0 +1,83 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: V4L
+
+.. _VIDIOC_SUBDEV_G_CLIENT_CAP:
+
+************************************************************
+ioctl VIDIOC_SUBDEV_G_CLIENT_CAP, VIDIOC_SUBDEV_S_CLIENT_CAP
+************************************************************
+
+Name
+====
+
+VIDIOC_SUBDEV_G_CLIENT_CAP - VIDIOC_SUBDEV_S_CLIENT_CAP - Get or set client
+capabilities.
+
+Synopsis
+========
+
+.. c:macro:: VIDIOC_SUBDEV_G_CLIENT_CAP
+
+``int ioctl(int fd, VIDIOC_SUBDEV_G_CLIENT_CAP, struct v4l2_subdev_client_capability *argp)``
+
+.. c:macro:: VIDIOC_SUBDEV_S_CLIENT_CAP
+
+``int ioctl(int fd, VIDIOC_SUBDEV_S_CLIENT_CAP, struct v4l2_subdev_client_capability *argp)``
+
+Arguments
+=========
+
+``fd``
+    File descriptor returned by :ref:`open() <func-open>`.
+
+``argp``
+    Pointer to struct :c:type:`v4l2_subdev_client_capability`.
+
+Description
+===========
+
+These ioctls are used to get and set the client (the application using the
+subdevice ioctls) capabilities. The client capabilities are stored in the file
+handle of the opened subdev device node, and the client must set the
+capabilities for each opened subdev separately.
+
+By default no client capabilities are set when a subdev device node is opened.
+
+The purpose of the client capabilities are to inform the kernel of the behavior
+of the client, mainly related to maintaining compatibility with different
+kernel and userspace versions.
+
+The ``VIDIOC_SUBDEV_G_CLIENT_CAP`` ioctl returns the current client capabilities
+associated with the file handle ``fd``.
+
+The ``VIDIOC_SUBDEV_S_CLIENT_CAP`` ioctl sets client capabilities for the file
+handle ``fd``. The new capabilities fully replace the current capabilities, the
+ioctl can therefore also be used to remove capabilities that have previously
+been set.
+
+``VIDIOC_SUBDEV_S_CLIENT_CAP`` modifies the struct
+:c:type:`v4l2_subdev_client_capability` to reflect the capabilities that have
+been accepted. A common case for the kernel not accepting a capability is that
+the kernel is older than the headers the userspace uses, and thus the capability
+is unknown to the kernel.
+
+.. flat-table:: Client Capabilities
+    :header-rows:  1
+
+    * - Capability
+      - Description
+    * - ``V4L2_SUBDEV_CLIENT_CAP_STREAMS``
+      - The client is aware of streams. Setting this flag enables the use
+        of 'stream' fields (referring to the stream number) with various
+        ioctls. If this is not set (which is the default), the 'stream' fields
+        will be forced to 0 by the kernel.
+
+Return Value
+============
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
+
+ENOIOCTLCMD
+   The kernel does not support this ioctl.
index 62591c88f436121f2d9fbd61b0667836cd7146af..bd28bbdb3c09cbffaab715b854b970470257f5af 100644 (file)
@@ -1227,12 +1227,6 @@ F:       Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml
 F:     drivers/iio/addac/ad74413r.c
 F:     include/dt-bindings/iio/addac/adi,ad74413r.h
 
-ANALOG DEVICES INC AD9389B DRIVER
-M:     Hans Verkuil <hverkuil-cisco@xs4all.nl>
-L:     linux-media@vger.kernel.org
-S:     Maintained
-F:     drivers/media/i2c/ad9389b*
-
 ANALOG DEVICES INC ADA4250 DRIVER
 M:     Antoniu Miclaus <antoniu.miclaus@analog.com>
 L:     linux-iio@vger.kernel.org
@@ -8441,14 +8435,6 @@ L:       platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/fujitsu-laptop.c
 
-FUJITSU M-5MO LS CAMERA ISP DRIVER
-M:     Kyungmin Park <kyungmin.park@samsung.com>
-M:     Heungjun Kim <riverful.kim@samsung.com>
-L:     linux-media@vger.kernel.org
-S:     Maintained
-F:     drivers/media/i2c/m5mols/
-F:     include/media/i2c/m5mols.h
-
 FUJITSU TABLET EXTRAS
 M:     Robert Gerlach <khnz@gmx.de>
 L:     platform-driver-x86@vger.kernel.org
@@ -14206,14 +14192,6 @@ L:     linux-mtd@lists.infradead.org
 S:     Maintained
 F:     drivers/mtd/devices/docg3*
 
-MT9M032 APTINA SENSOR DRIVER
-M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-L:     linux-media@vger.kernel.org
-S:     Maintained
-T:     git git://linuxtv.org/media_tree.git
-F:     drivers/media/i2c/mt9m032.c
-F:     include/media/i2c/mt9m032.h
-
 MT9P031 APTINA CAMERA SENSOR
 M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:     linux-media@vger.kernel.org
@@ -14223,14 +14201,6 @@ F:     Documentation/devicetree/bindings/media/i2c/aptina,mt9p031.yaml
 F:     drivers/media/i2c/mt9p031.c
 F:     include/media/i2c/mt9p031.h
 
-MT9T001 APTINA CAMERA SENSOR
-M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-L:     linux-media@vger.kernel.org
-S:     Maintained
-T:     git git://linuxtv.org/media_tree.git
-F:     drivers/media/i2c/mt9t001.c
-F:     include/media/i2c/mt9t001.h
-
 MT9T112 APTINA CAMERA SENSOR
 M:     Jacopo Mondi <jacopo@jmondi.org>
 L:     linux-media@vger.kernel.org
@@ -14983,6 +14953,13 @@ F:     Documentation/devicetree/bindings/clock/imx*
 F:     drivers/clk/imx/
 F:     include/dt-bindings/clock/imx*
 
+NXP i.MX 8M ISI DRIVER
+M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/media/nxp,imx8-isi.yaml
+F:     drivers/media/platform/nxp/imx8-isi/
+
 NXP i.MX 8MQ DCSS DRIVER
 M:     Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
 R:     Lucas Stach <l.stach@pengutronix.de>
@@ -15410,6 +15387,7 @@ M:      Shunqian Zheng <zhengsq@rock-chips.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
 T:     git git://linuxtv.org/media_tree.git
+F:     Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml
 F:     drivers/media/i2c/ov2685.c
 
 OMNIVISION OV2740 SENSOR DRIVER
@@ -15501,7 +15479,7 @@ F:      Documentation/devicetree/bindings/media/i2c/ov7740.txt
 F:     drivers/media/i2c/ov7740.c
 
 OMNIVISION OV8856 SENSOR DRIVER
-M:     Dongchun Zhu <dongchun.zhu@mediatek.com>
+M:     Sakari Ailus <sakari.ailus@linux.intel.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
 T:     git git://linuxtv.org/media_tree.git
@@ -17260,6 +17238,7 @@ F:      drivers/net/wwan/qcom_bam_dmux.c
 QUALCOMM CAMERA SUBSYSTEM DRIVER
 M:     Robert Foss <rfoss@kernel.org>
 M:     Todor Tomov <todor.too@gmail.com>
+M:     Bryan O'Donoghue <bryan.odonoghue@linaro.org>
 L:     linux-media@vger.kernel.org
 S:     Maintained
 F:     Documentation/admin-guide/media/qcom_camss.rst
@@ -18536,6 +18515,7 @@ M:      Sylwester Nawrocki <s.nawrocki@samsung.com>
 M:     Andrzej Hajda <andrzej.hajda@intel.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
+F:     Documentation/devicetree/bindings/media/samsung,s5c73m3.yaml
 F:     drivers/media/i2c/s5c73m3/*
 
 SAMSUNG S5K5BAF CAMERA DRIVER
@@ -18560,6 +18540,11 @@ M:     Sylwester Nawrocki <s.nawrocki@samsung.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
 Q:     https://patchwork.linuxtv.org/project/linux-media/list/
+F:     Documentation/devicetree/bindings/media/samsung,exynos4210-csis.yaml
+F:     Documentation/devicetree/bindings/media/samsung,exynos4210-fimc.yaml
+F:     Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml
+F:     Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-lite.yaml
+F:     Documentation/devicetree/bindings/media/samsung,fimc.yaml
 F:     drivers/media/platform/samsung/exynos4-is/
 
 SAMSUNG SOC CLOCK DRIVERS
@@ -19038,6 +19023,7 @@ L:      linux-media@vger.kernel.org
 S:     Odd Fixes
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
+F:     Documentation/devicetree/bindings/media/silabs,si470x.yaml
 F:     drivers/media/radio/si470x/radio-si470x-i2c.c
 
 SI470X FM RADIO RECEIVER USB DRIVER
index 4f5ab3cae8a71dbbf8b4b8b2b8eaa40ac4d5b61b..769ea6b2e1d0b6776f16e78a0ccb71d4c03e8668 100644 (file)
@@ -1052,6 +1052,7 @@ void cec_received_msg_ts(struct cec_adapter *adap,
        u8 cmd = msg->msg[1];
        bool is_reply = false;
        bool valid_la = true;
+       bool monitor_valid_la = true;
        u8 min_len = 0;
 
        if (WARN_ON(!msg->len || msg->len > CEC_MAX_MSG_SIZE))
@@ -1093,8 +1094,10 @@ void cec_received_msg_ts(struct cec_adapter *adap,
        adap->last_initiator = 0xff;
 
        /* Check if this message was for us (directed or broadcast). */
-       if (!cec_msg_is_broadcast(msg))
+       if (!cec_msg_is_broadcast(msg)) {
                valid_la = cec_has_log_addr(adap, msg_dest);
+               monitor_valid_la = valid_la;
+       }
 
        /*
         * Check if the length is not too short or if the message is a
@@ -1227,7 +1230,7 @@ void cec_received_msg_ts(struct cec_adapter *adap,
        mutex_unlock(&adap->lock);
 
        /* Pass the message on to any monitoring filehandles */
-       cec_queue_msg_monitor(adap, msg, valid_la);
+       cec_queue_msg_monitor(adap, msg, monitor_valid_la);
 
        /* We're done if it is not for us or a poll message */
        if (!valid_la || msg->len <= 1)
index c8c4efc83f5f06f162cfcd5dde12f031c474d74c..ff34490fd8694add8137f4a48fd80410ad07a0f8 100644 (file)
@@ -269,13 +269,12 @@ del_adap:
        return ret;
 }
 
-static int cec_gpio_remove(struct platform_device *pdev)
+static void cec_gpio_remove(struct platform_device *pdev)
 {
        struct cec_gpio *cec = platform_get_drvdata(pdev);
 
        cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
        cec_unregister_adapter(cec->adap);
-       return 0;
 }
 
 static const struct of_device_id cec_gpio_match[] = {
@@ -288,7 +287,7 @@ MODULE_DEVICE_TABLE(of, cec_gpio_match);
 
 static struct platform_driver cec_gpio_pdrv = {
        .probe  = cec_gpio_probe,
-       .remove = cec_gpio_remove,
+       .remove_new = cec_gpio_remove,
        .driver = {
                .name           = "cec-gpio",
                .of_match_table = cec_gpio_match,
index 6ebedc71d67d4d574daea2b407fd1ca49b58aed5..c17faf002877d463ba7b24fbb6cbb84f964395c0 100644 (file)
@@ -225,6 +225,12 @@ static const struct cec_dmi_match cec_dmi_match_table[] = {
        { "Google", "Kinox", "0000:00:02.0", "Port B" },
        /* Google Kuldax */
        { "Google", "Kuldax", "0000:00:02.0", "Port B" },
+       /* Google Aurash */
+       { "Google", "Aurash", "0000:00:02.0", "Port B" },
+       /* Google Gladios */
+       { "Google", "Gladios", "0000:00:02.0", "Port B" },
+       /* Google Lisbon */
+       { "Google", "Lisbon", "0000:00:02.0", "Port B" },
 };
 
 static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev,
@@ -326,31 +332,31 @@ out_probe_adapter:
        return ret;
 }
 
-static int cros_ec_cec_remove(struct platform_device *pdev)
+static void cros_ec_cec_remove(struct platform_device *pdev)
 {
        struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev);
        struct device *dev = &pdev->dev;
        int ret;
 
+       /*
+        * blocking_notifier_chain_unregister() only fails if the notifier isn't
+        * in the list. We know it was added to it by .probe(), so there should
+        * be no need for error checking. Be cautious and still check.
+        */
        ret = blocking_notifier_chain_unregister(
                        &cros_ec_cec->cros_ec->event_notifier,
                        &cros_ec_cec->notifier);
-
-       if (ret) {
+       if (ret)
                dev_err(dev, "failed to unregister notifier\n");
-               return ret;
-       }
 
        cec_notifier_cec_adap_unregister(cros_ec_cec->notify,
                                         cros_ec_cec->adap);
        cec_unregister_adapter(cros_ec_cec->adap);
-
-       return 0;
 }
 
 static struct platform_driver cros_ec_cec_driver = {
        .probe = cros_ec_cec_probe,
-       .remove  = cros_ec_cec_remove,
+       .remove_new = cros_ec_cec_remove,
        .driver = {
                .name = DRV_NAME,
                .pm = &cros_ec_cec_pm_ops,
index 68fe6d6a81786f332c2dfb6340cc5c930d709e80..51294b9b6cd5912abc80e46ad45450fe572f0e4f 100644 (file)
@@ -744,7 +744,7 @@ out_probe_adapter:
        return ret;
 }
 
-static int meson_ao_cec_g12a_remove(struct platform_device *pdev)
+static void meson_ao_cec_g12a_remove(struct platform_device *pdev)
 {
        struct meson_ao_cec_g12a_device *ao_cec = platform_get_drvdata(pdev);
 
@@ -753,8 +753,6 @@ static int meson_ao_cec_g12a_remove(struct platform_device *pdev)
        cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
 
        cec_unregister_adapter(ao_cec->adap);
-
-       return 0;
 }
 
 static const struct meson_ao_cec_g12a_data ao_cec_g12a_data = {
@@ -780,7 +778,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match);
 
 static struct platform_driver meson_ao_cec_g12a_driver = {
        .probe   = meson_ao_cec_g12a_probe,
-       .remove  = meson_ao_cec_g12a_remove,
+       .remove_new = meson_ao_cec_g12a_remove,
        .driver  = {
                .name = "meson-ao-cec-g12a",
                .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
index 6b440f0635d91b1ff2346f58cd5acc09475da48a..f6f51a34f7bd52358c72168601c362feb4ec1c38 100644 (file)
@@ -696,7 +696,7 @@ out_probe_adapter:
        return ret;
 }
 
-static int meson_ao_cec_remove(struct platform_device *pdev)
+static void meson_ao_cec_remove(struct platform_device *pdev)
 {
        struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);
 
@@ -704,8 +704,6 @@ static int meson_ao_cec_remove(struct platform_device *pdev)
 
        cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
        cec_unregister_adapter(ao_cec->adap);
-
-       return 0;
 }
 
 static const struct of_device_id meson_ao_cec_of_match[] = {
@@ -716,7 +714,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match);
 
 static struct platform_driver meson_ao_cec_driver = {
        .probe   = meson_ao_cec_probe,
-       .remove  = meson_ao_cec_remove,
+       .remove_new = meson_ao_cec_remove,
        .driver  = {
                .name = "meson-ao-cec",
                .of_match_table = of_match_ptr(meson_ao_cec_of_match),
index 0a30e7acdc10e98b96376e9ea55980a762d0abfd..51ab4a80aafe63a149b650fcfd4789abe1940196 100644 (file)
@@ -249,14 +249,13 @@ err_delete_adapter:
        return ret;
 }
 
-static int s5p_cec_remove(struct platform_device *pdev)
+static void s5p_cec_remove(struct platform_device *pdev)
 {
        struct s5p_cec_dev *cec = platform_get_drvdata(pdev);
 
        cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
        cec_unregister_adapter(cec->adap);
        pm_runtime_disable(&pdev->dev);
-       return 0;
 }
 
 static int __maybe_unused s5p_cec_runtime_suspend(struct device *dev)
@@ -295,7 +294,7 @@ MODULE_DEVICE_TABLE(of, s5p_cec_match);
 
 static struct platform_driver s5p_cec_pdrv = {
        .probe  = s5p_cec_probe,
-       .remove = s5p_cec_remove,
+       .remove_new = s5p_cec_remove,
        .driver = {
                .name           = CEC_NAME,
                .of_match_table = s5p_cec_match,
index 580905e3d066760e60a8824cb60c1d8e11ae593c..5d4c5a2cae097e6b9edbc5d5fe7200221fbd54d6 100644 (file)
@@ -668,7 +668,7 @@ err:
        return ret;
 }
 
-static int secocec_remove(struct platform_device *pdev)
+static void secocec_remove(struct platform_device *pdev)
 {
        struct secocec_data *secocec = platform_get_drvdata(pdev);
        u16 val;
@@ -686,8 +686,6 @@ static int secocec_remove(struct platform_device *pdev)
        release_region(BRA_SMB_BASE_ADDR, 7);
 
        dev_dbg(&pdev->dev, "CEC device removed\n");
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -780,7 +778,7 @@ static struct platform_driver secocec_driver = {
                   .pm = SECOCEC_PM_OPS,
        },
        .probe = secocec_probe,
-       .remove = secocec_remove,
+       .remove_new = secocec_remove,
 };
 
 module_platform_driver(secocec_driver);
index 4edbdd09535dd45c0b4f5bb3d1d04f6e638606d0..a20fc5c0c88d0e78eaebf6441a8640d364aba3b1 100644 (file)
@@ -364,14 +364,12 @@ err_delete_adapter:
        return ret;
 }
 
-static int stih_cec_remove(struct platform_device *pdev)
+static void stih_cec_remove(struct platform_device *pdev)
 {
        struct stih_cec *cec = platform_get_drvdata(pdev);
 
        cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
        cec_unregister_adapter(cec->adap);
-
-       return 0;
 }
 
 static const struct of_device_id stih_cec_match[] = {
@@ -384,7 +382,7 @@ MODULE_DEVICE_TABLE(of, stih_cec_match);
 
 static struct platform_driver stih_cec_pdrv = {
        .probe  = stih_cec_probe,
-       .remove = stih_cec_remove,
+       .remove_new = stih_cec_remove,
        .driver = {
                .name           = CEC_NAME,
                .of_match_table = stih_cec_match,
index 7b2db46a572226f75fb4e369f3484ba6321596a8..ada3d153362a0213091a7a88c64c509121805db1 100644 (file)
@@ -344,7 +344,7 @@ err_unprepare_cec_clk:
        return ret;
 }
 
-static int stm32_cec_remove(struct platform_device *pdev)
+static void stm32_cec_remove(struct platform_device *pdev)
 {
        struct stm32_cec *cec = platform_get_drvdata(pdev);
 
@@ -352,8 +352,6 @@ static int stm32_cec_remove(struct platform_device *pdev)
        clk_unprepare(cec->clk_hdmi_cec);
 
        cec_unregister_adapter(cec->adap);
-
-       return 0;
 }
 
 static const struct of_device_id stm32_cec_of_match[] = {
@@ -364,7 +362,7 @@ MODULE_DEVICE_TABLE(of, stm32_cec_of_match);
 
 static struct platform_driver stm32_cec_driver = {
        .probe  = stm32_cec_probe,
-       .remove = stm32_cec_remove,
+       .remove_new = stm32_cec_remove,
        .driver = {
                .name           = CEC_NAME,
                .of_match_table = stm32_cec_of_match,
index 5e907395ca2e5283bd8ebdf06b8dce85adc7b60f..04dc06e3c42adf3d73adc062b18ba96f321ecc5c 100644 (file)
@@ -421,7 +421,7 @@ err_clk:
        return ret;
 }
 
-static int tegra_cec_remove(struct platform_device *pdev)
+static void tegra_cec_remove(struct platform_device *pdev)
 {
        struct tegra_cec *cec = platform_get_drvdata(pdev);
 
@@ -429,8 +429,6 @@ static int tegra_cec_remove(struct platform_device *pdev)
 
        cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
        cec_unregister_adapter(cec->adap);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -467,7 +465,7 @@ static struct platform_driver tegra_cec_driver = {
                .of_match_table = of_match_ptr(tegra_cec_of_match),
        },
        .probe = tegra_cec_probe,
-       .remove = tegra_cec_remove,
+       .remove_new = tegra_cec_remove,
 
 #ifdef CONFIG_PM
        .suspend = tegra_cec_suspend,
diff --git a/drivers/media/common/btcx-risc.h b/drivers/media/common/btcx-risc.h
deleted file mode 100644 (file)
index 76dc16f..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- */
-struct btcx_riscmem {
-       unsigned int   size;
-       __le32         *cpu;
-       __le32         *jmp;
-       dma_addr_t     dma;
-};
-
-struct btcx_skiplist {
-       int start;
-       int end;
-};
-
-int  btcx_riscmem_alloc(struct pci_dev *pci,
-                       struct btcx_riscmem *risc,
-                       unsigned int size);
-void btcx_riscmem_free(struct pci_dev *pci,
-                      struct btcx_riscmem *risc);
-
-int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
-                     struct v4l2_clip *clips, unsigned int n);
-int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
-              unsigned int n, int mask);
-void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
-void btcx_calc_skips(int line, int width, int *maxy,
-                    struct btcx_skiplist *skips, unsigned int *nskips,
-                    const struct v4l2_clip *clips, unsigned int nclips);
index a0aa155e5d857c1e534b4bc24637142ae3b6f635..dfec86e50dff47d789b7c980edfff30576b56237 100644 (file)
@@ -6,5 +6,5 @@ config VIDEO_SAA7146
 config VIDEO_SAA7146_VV
        tristate
        depends on VIDEO_DEV
-       select VIDEOBUF_DMA_SG
+       select VIDEOBUF2_DMA_SG
        select VIDEO_SAA7146
index e50fa0ff7c5d5486fce4548e9fefa40f532bac6a..bcb957883044c77138af70e80614dd94687c63a6 100644 (file)
@@ -37,7 +37,8 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
 {
        u32 value = 0;
 
-       BUG_ON(port > 3);
+       if (WARN_ON(port > 3))
+               return;
 
        value = saa7146_read(dev, GPIO_CTRL);
        value &= ~(0xff << (8*port));
@@ -148,7 +149,8 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
                pg = vmalloc_to_page(virt);
                if (NULL == pg)
                        goto err;
-               BUG_ON(PageHighMem(pg));
+               if (WARN_ON(PageHighMem(pg)))
+                       return NULL;
                sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
        }
        return sglist;
@@ -233,46 +235,32 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
 }
 
 int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
-       struct scatterlist *list, int sglen  )
+                                struct scatterlist *list, int sglen)
 {
+       struct sg_dma_page_iter dma_iter;
        __le32 *ptr, fill;
        int nr_pages = 0;
-       int i,p;
+       int i;
 
-       BUG_ON(0 == sglen);
-       BUG_ON(list->offset > PAGE_SIZE);
+       if (WARN_ON(!sglen) ||
+           WARN_ON(list->offset > PAGE_SIZE))
+               return -EIO;
 
        /* if we have a user buffer, the first page may not be
           aligned to a page boundary. */
        pt->offset = list->offset;
 
        ptr = pt->cpu;
-       for (i = 0; i < sglen; i++, list++) {
-/*
-               pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n",
-                        i, sg_dma_address(list), sg_dma_len(list),
-                        list->offset);
-*/
-               for (p = 0; p * 4096 < sg_dma_len(list); p++, ptr++) {
-                       *ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
-                       nr_pages++;
-               }
+       for_each_sg_dma_page(list, &dma_iter, sglen, 0) {
+               *ptr++ = cpu_to_le32(sg_page_iter_dma_address(&dma_iter));
+               nr_pages++;
        }
 
 
        /* safety; fill the page table up with the last valid page */
        fill = *(ptr-1);
-       for(i=nr_pages;i<1024;i++) {
+       for (i = nr_pages; i < 1024; i++)
                *ptr++ = fill;
-       }
-
-/*
-       ptr = pt->cpu;
-       pr_debug("offset: %d\n", pt->offset);
-       for(i=0;i<5;i++) {
-               pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]);
-       }
-*/
        return 0;
 }
 
index e9a15de6126e90d117628254dbd2da5c15947706..79214459387aba65b8d76524d17db92362d0895d 100644 (file)
@@ -7,12 +7,11 @@
 /****************************************************************************/
 /* resource management functions, shamelessly stolen from saa7134 driver */
 
-int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
+int saa7146_res_get(struct saa7146_dev *dev, unsigned int bit)
 {
-       struct saa7146_dev *dev = fh->dev;
        struct saa7146_vv *vv = dev->vv_data;
 
-       if (fh->resources & bit) {
+       if (vv->resources & bit) {
                DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
                      bit, vv->resources);
                /* have it already allocated */
@@ -27,41 +26,22 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
                return 0;
        }
        /* it's free, grab it */
-       fh->resources |= bit;
        vv->resources |= bit;
        DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
        return 1;
 }
 
-void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
+void saa7146_res_free(struct saa7146_dev *dev, unsigned int bits)
 {
-       struct saa7146_dev *dev = fh->dev;
        struct saa7146_vv *vv = dev->vv_data;
 
-       BUG_ON((fh->resources & bits) != bits);
+       WARN_ON((vv->resources & bits) != bits);
 
-       fh->resources &= ~bits;
        vv->resources &= ~bits;
        DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
 }
 
 
-/********************************************************************************/
-/* common dma functions */
-
-void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
-                                               struct saa7146_buf *buf)
-{
-       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-       DEB_EE("dev:%p, buf:%p\n", dev, buf);
-
-       videobuf_waiton(q, &buf->vb, 0, 0);
-       videobuf_dma_unmap(q->dev, dma);
-       videobuf_dma_free(dma);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-
 /********************************************************************************/
 /* common buffer functions */
 
@@ -72,15 +52,15 @@ int saa7146_buffer_queue(struct saa7146_dev *dev,
        assert_spin_locked(&dev->slock);
        DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
 
-       BUG_ON(!q);
+       if (WARN_ON(!q))
+               return -EIO;
 
        if (NULL == q->curr) {
                q->curr = buf;
                DEB_D("immediately activating buffer %p\n", buf);
                buf->activate(dev,buf,NULL);
        } else {
-               list_add_tail(&buf->vb.queue,&q->queue);
-               buf->vb.state = VIDEOBUF_QUEUED;
+               list_add_tail(&buf->list, &q->queue);
                DEB_D("adding buffer %p to queue. (active buffer present)\n",
                      buf);
        }
@@ -91,21 +71,31 @@ void saa7146_buffer_finish(struct saa7146_dev *dev,
                           struct saa7146_dmaqueue *q,
                           int state)
 {
+       struct saa7146_vv *vv = dev->vv_data;
+       struct saa7146_buf *buf = q->curr;
+
        assert_spin_locked(&dev->slock);
        DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
        DEB_EE("q->curr:%p\n", q->curr);
 
        /* finish current buffer */
-       if (NULL == q->curr) {
+       if (!buf) {
                DEB_D("aiii. no current buffer\n");
                return;
        }
 
-       q->curr->vb.state = state;
-       q->curr->vb.ts = ktime_get_ns();
-       wake_up(&q->curr->vb.done);
-
        q->curr = NULL;
+       buf->vb.vb2_buf.timestamp = ktime_get_ns();
+       if (vv->video_fmt.field == V4L2_FIELD_ALTERNATE)
+               buf->vb.field = vv->last_field;
+       else if (vv->video_fmt.field == V4L2_FIELD_ANY)
+               buf->vb.field = (vv->video_fmt.height > vv->standard->v_max_out / 2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_BOTTOM;
+       else
+               buf->vb.field = vv->video_fmt.field;
+       buf->vb.sequence = vv->seqnr++;
+       vb2_buffer_done(&buf->vb.vb2_buf, state);
 }
 
 void saa7146_buffer_next(struct saa7146_dev *dev,
@@ -113,17 +103,18 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
 {
        struct saa7146_buf *buf,*next = NULL;
 
-       BUG_ON(!q);
+       if (WARN_ON(!q))
+               return;
 
        DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
 
        assert_spin_locked(&dev->slock);
        if (!list_empty(&q->queue)) {
                /* activate next one from queue */
-               buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue);
-               list_del(&buf->vb.queue);
+               buf = list_entry(q->queue.next, struct saa7146_buf, list);
+               list_del(&buf->list);
                if (!list_empty(&q->queue))
-                       next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
+                       next = list_entry(q->queue.next, struct saa7146_buf, list);
                q->curr = buf;
                DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
                        buf, q->queue.prev, q->queue.next);
@@ -171,7 +162,7 @@ void saa7146_buffer_timeout(struct timer_list *t)
        spin_lock_irqsave(&dev->slock,flags);
        if (q->curr) {
                DEB_D("timeout on %p\n", q->curr);
-               saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
+               saa7146_buffer_finish(dev, q, VB2_BUF_STATE_ERROR);
        }
 
        /* we don't restart the transfer here like other drivers do. when
@@ -180,256 +171,39 @@ void saa7146_buffer_timeout(struct timer_list *t)
           we mess up our capture logic. if a timeout occurs on another buffer,
           then something is seriously broken before, so no need to buffer the
           next capture IMHO... */
-/*
-       saa7146_buffer_next(dev,q);
-*/
+
+       saa7146_buffer_next(dev, q, 0);
+
        spin_unlock_irqrestore(&dev->slock,flags);
 }
 
 /********************************************************************************/
 /* file operations */
 
-static int fops_open(struct file *file)
+static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
 {
        struct video_device *vdev = video_devdata(file);
        struct saa7146_dev *dev = video_drvdata(file);
-       struct saa7146_fh *fh = NULL;
-       int result = 0;
-
-       DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
-
-       if (mutex_lock_interruptible(vdev->lock))
-               return -ERESTARTSYS;
-
-       DEB_D("using: %p\n", dev);
-
-       /* check if an extension is registered */
-       if( NULL == dev->ext ) {
-               DEB_S("no extension registered for this device\n");
-               result = -ENODEV;
-               goto out;
-       }
-
-       /* allocate per open data */
-       fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-       if (NULL == fh) {
-               DEB_S("cannot allocate memory for per open data\n");
-               result = -ENOMEM;
-               goto out;
-       }
-
-       v4l2_fh_init(&fh->fh, vdev);
-
-       file->private_data = &fh->fh;
-       fh->dev = dev;
-
-       if (vdev->vfl_type == VFL_TYPE_VBI) {
-               DEB_S("initializing vbi...\n");
-               if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
-                       result = saa7146_vbi_uops.open(dev,file);
-               if (dev->ext_vv_data->vbi_fops.open)
-                       dev->ext_vv_data->vbi_fops.open(file);
-       } else {
-               DEB_S("initializing video...\n");
-               result = saa7146_video_uops.open(dev,file);
-       }
-
-       if (0 != result) {
-               goto out;
-       }
-
-       if( 0 == try_module_get(dev->ext->module)) {
-               result = -EINVAL;
-               goto out;
-       }
-
-       result = 0;
-       v4l2_fh_add(&fh->fh);
-out:
-       if (fh && result != 0) {
-               kfree(fh);
-               file->private_data = NULL;
-       }
-       mutex_unlock(vdev->lock);
-       return result;
-}
-
-static int fops_release(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct saa7146_fh  *fh  = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-
-       DEB_EE("file:%p\n", file);
-
-       mutex_lock(vdev->lock);
-
-       if (vdev->vfl_type == VFL_TYPE_VBI) {
-               if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
-                       saa7146_vbi_uops.release(dev,file);
-               if (dev->ext_vv_data->vbi_fops.release)
-                       dev->ext_vv_data->vbi_fops.release(file);
-       } else {
-               saa7146_video_uops.release(dev,file);
-       }
-
-       v4l2_fh_del(&fh->fh);
-       v4l2_fh_exit(&fh->fh);
-       module_put(dev->ext->module);
-       file->private_data = NULL;
-       kfree(fh);
-
-       mutex_unlock(vdev->lock);
-
-       return 0;
-}
-
-static int fops_mmap(struct file *file, struct vm_area_struct * vma)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct saa7146_fh *fh = file->private_data;
-       struct videobuf_queue *q;
-       int res;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_VIDEO: {
-               DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
-                      file, vma);
-               q = &fh->video_q;
-               break;
-               }
-       case VFL_TYPE_VBI: {
-               DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
-                      file, vma);
-               if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
-                       return -ENODEV;
-               q = &fh->vbi_q;
-               break;
-               }
-       default:
-               BUG();
-       }
+       int ret;
 
+       if (vdev->vfl_type != VFL_TYPE_VBI || !dev->ext_vv_data->vbi_fops.write)
+               return -EINVAL;
        if (mutex_lock_interruptible(vdev->lock))
                return -ERESTARTSYS;
-       res = videobuf_mmap_mapper(q, vma);
+       ret = dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
        mutex_unlock(vdev->lock);
-       return res;
-}
-
-static __poll_t __fops_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct saa7146_fh *fh = file->private_data;
-       struct videobuf_buffer *buf = NULL;
-       struct videobuf_queue *q;
-       __poll_t res = v4l2_ctrl_poll(file, wait);
-
-       DEB_EE("file:%p, poll:%p\n", file, wait);
-
-       if (vdev->vfl_type == VFL_TYPE_VBI) {
-               if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
-                       return res | EPOLLOUT | EPOLLWRNORM;
-               if( 0 == fh->vbi_q.streaming )
-                       return res | videobuf_poll_stream(file, &fh->vbi_q, wait);
-               q = &fh->vbi_q;
-       } else {
-               DEB_D("using video queue\n");
-               q = &fh->video_q;
-       }
-
-       if (!list_empty(&q->stream))
-               buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
-
-       if (!buf) {
-               DEB_D("buf == NULL!\n");
-               return res | EPOLLERR;
-       }
-
-       poll_wait(file, &buf->done, wait);
-       if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
-               DEB_D("poll succeeded!\n");
-               return res | EPOLLIN | EPOLLRDNORM;
-       }
-
-       DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
-       return res;
-}
-
-static __poll_t fops_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct video_device *vdev = video_devdata(file);
-       __poll_t res;
-
-       mutex_lock(vdev->lock);
-       res = __fops_poll(file, wait);
-       mutex_unlock(vdev->lock);
-       return res;
-}
-
-static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct saa7146_fh *fh = file->private_data;
-       int ret;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_VIDEO:
-/*
-               DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
-                      file, data, (unsigned long)count);
-*/
-               return saa7146_video_uops.read(file,data,count,ppos);
-       case VFL_TYPE_VBI:
-/*
-               DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
-                      file, data, (unsigned long)count);
-*/
-               if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) {
-                       if (mutex_lock_interruptible(vdev->lock))
-                               return -ERESTARTSYS;
-                       ret = saa7146_vbi_uops.read(file, data, count, ppos);
-                       mutex_unlock(vdev->lock);
-                       return ret;
-               }
-               return -EINVAL;
-       default:
-               BUG();
-       }
-}
-
-static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct saa7146_fh *fh = file->private_data;
-       int ret;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_VIDEO:
-               return -EINVAL;
-       case VFL_TYPE_VBI:
-               if (fh->dev->ext_vv_data->vbi_fops.write) {
-                       if (mutex_lock_interruptible(vdev->lock))
-                               return -ERESTARTSYS;
-                       ret = fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
-                       mutex_unlock(vdev->lock);
-                       return ret;
-               }
-               return -EINVAL;
-       default:
-               BUG();
-       }
+       return ret;
 }
 
 static const struct v4l2_file_operations video_fops =
 {
        .owner          = THIS_MODULE,
-       .open           = fops_open,
-       .release        = fops_release,
-       .read           = fops_read,
+       .open           = v4l2_fh_open,
+       .release        = vb2_fop_release,
+       .read           = vb2_fop_read,
        .write          = fops_write,
-       .poll           = fops_poll,
-       .mmap           = fops_mmap,
+       .poll           = vb2_fop_poll,
+       .mmap           = vb2_fop_mmap,
        .unlocked_ioctl = video_ioctl2,
 };
 
@@ -516,33 +290,15 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
           configuration data) */
        dev->ext_vv_data = ext_vv;
 
-       vv->d_clipping.cpu_addr =
-               dma_alloc_coherent(&dev->pci->dev, SAA7146_CLIPPING_MEM,
-                                  &vv->d_clipping.dma_handle, GFP_KERNEL);
-       if( NULL == vv->d_clipping.cpu_addr ) {
-               ERR("out of memory. aborting.\n");
-               kfree(vv);
-               v4l2_ctrl_handler_free(hdl);
-               v4l2_device_unregister(&dev->v4l2_dev);
-               return -ENOMEM;
-       }
-
        saa7146_video_uops.init(dev,vv);
        if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
                saa7146_vbi_uops.init(dev,vv);
 
-       vv->ov_fb.fmt.width = vv->standard->h_max_out;
-       vv->ov_fb.fmt.height = vv->standard->v_max_out;
-       vv->ov_fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
-       vv->ov_fb.fmt.bytesperline = 2 * vv->ov_fb.fmt.width;
-       vv->ov_fb.fmt.sizeimage = vv->ov_fb.fmt.bytesperline * vv->ov_fb.fmt.height;
-       vv->ov_fb.fmt.colorspace = V4L2_COLORSPACE_SRGB;
-
        fmt = &vv->video_fmt;
        fmt->width = 384;
        fmt->height = 288;
        fmt->pixelformat = V4L2_PIX_FMT_BGR24;
-       fmt->field = V4L2_FIELD_ANY;
+       fmt->field = V4L2_FIELD_INTERLACED;
        fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
        fmt->bytesperline = 3 * fmt->width;
        fmt->sizeimage = fmt->bytesperline * fmt->height;
@@ -561,8 +317,6 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
 
        timer_setup(&vv->vbi_read_timeout, NULL, 0);
 
-       vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-       vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY;
        dev->vv_data = vv;
        dev->vv_callback = &vv_callback;
 
@@ -577,8 +331,6 @@ int saa7146_vv_release(struct saa7146_dev* dev)
        DEB_EE("dev:%p\n", dev);
 
        v4l2_device_unregister(&dev->v4l2_dev);
-       dma_free_coherent(&dev->pci->dev, SAA7146_CLIPPING_MEM,
-                         vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
        v4l2_ctrl_handler_free(&dev->ctrl_handler);
        kfree(vv);
        dev->vv_data = NULL;
@@ -591,16 +343,20 @@ EXPORT_SYMBOL_GPL(saa7146_vv_release);
 int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev,
                            char *name, int type)
 {
+       struct vb2_queue *q;
        int err;
        int i;
 
        DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
 
        vfd->fops = &video_fops;
-       if (type == VFL_TYPE_VIDEO)
+       if (type == VFL_TYPE_VIDEO) {
                vfd->ioctl_ops = &dev->ext_vv_data->vid_ops;
-       else
+               q = &dev->vv_data->video_dmaq.q;
+       } else {
                vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;
+               q = &dev->vv_data->vbi_dmaq.q;
+       }
        vfd->release = video_device_release_empty;
        vfd->lock = &dev->v4l2_lock;
        vfd->v4l2_dev = &dev->v4l2_dev;
@@ -608,15 +364,36 @@ int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev,
        for (i = 0; i < dev->ext_vv_data->num_stds; i++)
                vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
        strscpy(vfd->name, name, sizeof(vfd->name));
-       vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
+       vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE |
                           V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
        vfd->device_caps |= dev->ext_vv_data->capabilities;
-       if (type == VFL_TYPE_VIDEO)
+       if (type == VFL_TYPE_VIDEO) {
                vfd->device_caps &=
                        ~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT);
-       else
-               vfd->device_caps &=
-                       ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO);
+       } else if (vfd->device_caps & V4L2_CAP_SLICED_VBI_OUTPUT) {
+               vfd->vfl_dir = VFL_DIR_TX;
+               vfd->device_caps &= ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+                                     V4L2_CAP_AUDIO | V4L2_CAP_TUNER);
+       } else {
+               vfd->device_caps &= ~V4L2_CAP_VIDEO_CAPTURE;
+       }
+
+       q->type = type == VFL_TYPE_VIDEO ? V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VBI_CAPTURE;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
+       q->ops = type == VFL_TYPE_VIDEO ? &video_qops : &vbi_qops;
+       q->mem_ops = &vb2_dma_sg_memops;
+       q->drv_priv = dev;
+       q->gfp_flags = __GFP_DMA32;
+       q->buf_struct_size = sizeof(struct saa7146_buf);
+       q->lock = &dev->v4l2_lock;
+       q->min_buffers_needed = 2;
+       q->dev = &dev->pci->dev;
+       err = vb2_queue_init(q);
+       if (err)
+               return err;
+       vfd->queue = q;
+
        video_set_drvdata(vfd, dev);
 
        err = video_register_device(vfd, type, -1);
index 6c9946a402eefec8d2941119fd127a9b8768388f..7569d8cdd4d8d75e0cdf59fd00e09fa8d6355160 100644 (file)
@@ -306,221 +306,6 @@ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field
 }
 
 /* simple bubble-sort algorithm with duplicate elimination */
-static int sort_and_eliminate(u32* values, int* count)
-{
-       int low = 0, high = 0, top = 0;
-       int cur = 0, next = 0;
-
-       /* sanity checks */
-       if( (0 > *count) || (NULL == values) ) {
-               return -EINVAL;
-       }
-
-       /* bubble sort the first @count items of the array @values */
-       for( top = *count; top > 0; top--) {
-               for( low = 0, high = 1; high < top; low++, high++) {
-                       if( values[low] > values[high] )
-                               swap(values[low], values[high]);
-               }
-       }
-
-       /* remove duplicate items */
-       for( cur = 0, next = 1; next < *count; next++) {
-               if( values[cur] != values[next])
-                       values[++cur] = values[next];
-       }
-
-       *count = cur + 1;
-
-       return 0;
-}
-
-static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh,
-       struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field)
-{
-       struct saa7146_vv *vv = dev->vv_data;
-       __le32 *clipping = vv->d_clipping.cpu_addr;
-
-       int width = vv->ov.win.w.width;
-       int height =  vv->ov.win.w.height;
-       int clipcount = vv->ov.nclips;
-
-       u32 line_list[32];
-       u32 pixel_list[32];
-       int numdwords = 0;
-
-       int i = 0, j = 0;
-       int cnt_line = 0, cnt_pixel = 0;
-
-       int x[32], y[32], w[32], h[32];
-
-       /* clear out memory */
-       memset(&line_list[0],  0x00, sizeof(u32)*32);
-       memset(&pixel_list[0], 0x00, sizeof(u32)*32);
-       memset(clipping,  0x00, SAA7146_CLIPPING_MEM);
-
-       /* fill the line and pixel-lists */
-       for(i = 0; i < clipcount; i++) {
-               int l = 0, r = 0, t = 0, b = 0;
-
-               x[i] = vv->ov.clips[i].c.left;
-               y[i] = vv->ov.clips[i].c.top;
-               w[i] = vv->ov.clips[i].c.width;
-               h[i] = vv->ov.clips[i].c.height;
-
-               if( w[i] < 0) {
-                       x[i] += w[i]; w[i] = -w[i];
-               }
-               if( h[i] < 0) {
-                       y[i] += h[i]; h[i] = -h[i];
-               }
-               if( x[i] < 0) {
-                       w[i] += x[i]; x[i] = 0;
-               }
-               if( y[i] < 0) {
-                       h[i] += y[i]; y[i] = 0;
-               }
-               if( 0 != vv->vflip ) {
-                       y[i] = height - y[i] - h[i];
-               }
-
-               l = x[i];
-               r = x[i]+w[i];
-               t = y[i];
-               b = y[i]+h[i];
-
-               /* insert left/right coordinates */
-               pixel_list[ 2*i   ] = min_t(int, l, width);
-               pixel_list[(2*i)+1] = min_t(int, r, width);
-               /* insert top/bottom coordinates */
-               line_list[ 2*i   ] = min_t(int, t, height);
-               line_list[(2*i)+1] = min_t(int, b, height);
-       }
-
-       /* sort and eliminate lists */
-       cnt_line = cnt_pixel = 2*clipcount;
-       sort_and_eliminate( &pixel_list[0], &cnt_pixel );
-       sort_and_eliminate( &line_list[0], &cnt_line );
-
-       /* calculate the number of used u32s */
-       numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2;
-       numdwords = max_t(int, 4, numdwords);
-       numdwords = min_t(int, 64, numdwords);
-
-       /* fill up cliptable */
-       for(i = 0; i < cnt_pixel; i++) {
-               clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16);
-       }
-       for(i = 0; i < cnt_line; i++) {
-               clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16);
-       }
-
-       /* fill up cliptable with the display infos */
-       for(j = 0; j < clipcount; j++) {
-
-               for(i = 0; i < cnt_pixel; i++) {
-
-                       if( x[j] < 0)
-                               x[j] = 0;
-
-                       if( pixel_list[i] < (x[j] + w[j])) {
-
-                               if ( pixel_list[i] >= x[j] ) {
-                                       clipping[2*i] |= cpu_to_le32(1 << j);
-                               }
-                       }
-               }
-               for(i = 0; i < cnt_line; i++) {
-
-                       if( y[j] < 0)
-                               y[j] = 0;
-
-                       if( line_list[i] < (y[j] + h[j]) ) {
-
-                               if( line_list[i] >= y[j] ) {
-                                       clipping[(2*i)+1] |= cpu_to_le32(1 << j);
-                               }
-                       }
-               }
-       }
-
-       /* adjust arbitration control register */
-       *arbtr_ctrl &= 0xffff00ff;
-       *arbtr_ctrl |= 0x00001c00;
-
-       vdma2->base_even        = vv->d_clipping.dma_handle;
-       vdma2->base_odd         = vv->d_clipping.dma_handle;
-       vdma2->prot_addr        = vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords));
-       vdma2->base_page        = 0x04;
-       vdma2->pitch            = 0x00;
-       vdma2->num_line_byte    = (0 << 16 | (sizeof(u32))*(numdwords-1) );
-
-       /* set clipping-mode. this depends on the field(s) used */
-       *clip_format &= 0xfffffff7;
-       if (V4L2_FIELD_HAS_BOTH(field)) {
-               *clip_format |= 0x00000008;
-       } else {
-               *clip_format |= 0x00000000;
-       }
-}
-
-/* disable clipping */
-static void saa7146_disable_clipping(struct saa7146_dev *dev)
-{
-       u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
-
-       /* mask out relevant bits (=lower word)*/
-       clip_format &= MASK_W1;
-
-       /* upload clipping-registers*/
-       saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
-       saa7146_write(dev, MC2, (MASK_05 | MASK_21));
-
-       /* disable video dma2 */
-       saa7146_write(dev, MC1, MASK_21);
-}
-
-static void saa7146_set_clipping_rect(struct saa7146_fh *fh)
-{
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       enum v4l2_field field = vv->ov.win.field;
-       struct  saa7146_video_dma vdma2;
-       u32 clip_format;
-       u32 arbtr_ctrl;
-
-       /* check clipcount, disable clipping if clipcount == 0*/
-       if (vv->ov.nclips == 0) {
-               saa7146_disable_clipping(dev);
-               return;
-       }
-
-       clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
-       arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
-
-       calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field);
-
-       /* set clipping format */
-       clip_format &= 0xffff0008;
-       clip_format |= (SAA7146_CLIPPING_RECT << 4);
-
-       /* prepare video dma2 */
-       saa7146_write(dev, BASE_EVEN2,          vdma2.base_even);
-       saa7146_write(dev, BASE_ODD2,           vdma2.base_odd);
-       saa7146_write(dev, PROT_ADDR2,          vdma2.prot_addr);
-       saa7146_write(dev, BASE_PAGE2,          vdma2.base_page);
-       saa7146_write(dev, PITCH2,              vdma2.pitch);
-       saa7146_write(dev, NUM_LINE_BYTE2,      vdma2.num_line_byte);
-
-       /* prepare the rest */
-       saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
-       saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
-
-       /* upload clip_control-register, clipping-registers, enable video dma2 */
-       saa7146_write(dev, MC2, (MASK_05 | MASK_21 | MASK_03 | MASK_19));
-       saa7146_write(dev, MC1, (MASK_05 | MASK_21));
-}
-
 static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field)
 {
        struct saa7146_vv *vv = dev->vv_data;
@@ -556,62 +341,6 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e
        saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) );
 }
 
-/* calculate the new memory offsets for a desired position */
-static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
-{
-       struct saa7146_vv *vv = dev->vv_data;
-       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);
-
-       int b_depth = vv->ov_fmt->depth;
-       int b_bpl = vv->ov_fb.fmt.bytesperline;
-       /* The unsigned long cast is to remove a 64-bit compile warning since
-          it looks like a 64-bit address is cast to a 32-bit value, even
-          though the base pointer is really a 32-bit physical address that
-          goes into a 32-bit DMA register.
-          FIXME: might not work on some 64-bit platforms, but see the FIXME
-          in struct v4l2_framebuffer (videodev2.h) for that.
-        */
-       u32 base = (u32)(unsigned long)vv->ov_fb.base;
-
-       struct  saa7146_video_dma vdma1;
-
-       /* calculate memory offsets for picture, look if we shall top-down-flip */
-       vdma1.pitch     = 2*b_bpl;
-       if ( 0 == vv->vflip ) {
-               vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
-               vdma1.base_odd  = vdma1.base_even + (vdma1.pitch / 2);
-               vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
-       }
-       else {
-               vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
-               vdma1.base_odd  = vdma1.base_even - (vdma1.pitch / 2);
-               vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
-       }
-
-       if (V4L2_FIELD_HAS_BOTH(field)) {
-       } else if (field == V4L2_FIELD_ALTERNATE) {
-               /* fixme */
-               vdma1.base_odd = vdma1.prot_addr;
-               vdma1.pitch /= 2;
-       } else if (field == V4L2_FIELD_TOP) {
-               vdma1.base_odd = vdma1.prot_addr;
-               vdma1.pitch /= 2;
-       } else if (field == V4L2_FIELD_BOTTOM) {
-               vdma1.base_odd = vdma1.base_even;
-               vdma1.base_even = vdma1.prot_addr;
-               vdma1.pitch /= 2;
-       }
-
-       if ( 0 != vv->vflip ) {
-               vdma1.pitch *= -1;
-       }
-
-       vdma1.base_page = sfmt->swap;
-       vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels;
-
-       saa7146_write_out_dma(dev, 1, &vdma1);
-}
-
 static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette)
 {
        u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
@@ -645,30 +374,6 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy
 }
 EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
 
-int saa7146_enable_overlay(struct saa7146_fh *fh)
-{
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-
-       saa7146_set_window(dev, vv->ov.win.w.width, vv->ov.win.w.height, vv->ov.win.field);
-       saa7146_set_position(dev, vv->ov.win.w.left, vv->ov.win.w.top, vv->ov.win.w.height, vv->ov.win.field, vv->ov_fmt->pixelformat);
-       saa7146_set_output_format(dev, vv->ov_fmt->trans);
-       saa7146_set_clipping_rect(fh);
-
-       /* enable video dma1 */
-       saa7146_write(dev, MC1, (MASK_06 | MASK_22));
-       return 0;
-}
-
-void saa7146_disable_overlay(struct saa7146_fh *fh)
-{
-       struct saa7146_dev *dev = fh->dev;
-
-       /* disable clipping + video dma1 */
-       saa7146_disable_clipping(dev);
-       saa7146_write(dev, MC1, MASK_22);
-}
-
 void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma)
 {
        int where = 0;
@@ -702,14 +407,14 @@ void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_vi
 static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf)
 {
        struct saa7146_vv *vv = dev->vv_data;
+       struct v4l2_pix_format *pix = &vv->video_fmt;
        struct saa7146_video_dma vdma1;
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
 
-       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
-
-       int width = buf->fmt->width;
-       int height = buf->fmt->height;
-       int bytesperline = buf->fmt->bytesperline;
-       enum v4l2_field field = buf->fmt->field;
+       int width = pix->width;
+       int height = pix->height;
+       int bytesperline = pix->bytesperline;
+       enum v4l2_field field = pix->field;
 
        int depth = sfmt->depth;
 
@@ -764,8 +469,9 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
 
 static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
 {
-       int height = buf->fmt->height;
-       int width = buf->fmt->width;
+       struct v4l2_pix_format *pix = &vv->video_fmt;
+       int height = pix->height;
+       int width = pix->width;
 
        vdma2->pitch    = width;
        vdma3->pitch    = width;
@@ -795,8 +501,9 @@ static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struc
 
 static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
 {
-       int height = buf->fmt->height;
-       int width = buf->fmt->width;
+       struct v4l2_pix_format *pix = &vv->video_fmt;
+       int height = pix->height;
+       int width = pix->width;
 
        vdma2->pitch    = width/2;
        vdma3->pitch    = width/2;
@@ -825,19 +532,20 @@ static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struc
 static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf)
 {
        struct saa7146_vv *vv = dev->vv_data;
+       struct v4l2_pix_format *pix = &vv->video_fmt;
        struct saa7146_video_dma vdma1;
        struct saa7146_video_dma vdma2;
        struct saa7146_video_dma vdma3;
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
 
-       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
+       int width = pix->width;
+       int height = pix->height;
+       enum v4l2_field field = pix->field;
 
-       int width = buf->fmt->width;
-       int height = buf->fmt->height;
-       enum v4l2_field field = buf->fmt->field;
-
-       BUG_ON(0 == buf->pt[0].dma);
-       BUG_ON(0 == buf->pt[1].dma);
-       BUG_ON(0 == buf->pt[2].dma);
+       if (WARN_ON(!buf->pt[0].dma) ||
+           WARN_ON(!buf->pt[1].dma) ||
+           WARN_ON(!buf->pt[2].dma))
+               return -1;
 
        DEB_CAP("[size=%dx%d,fields=%s]\n",
                width, height, v4l2_field_names[field]);
@@ -994,10 +702,27 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)
        WRITE_RPS0(CMD_STOP);
 }
 
+/* disable clipping */
+static void saa7146_disable_clipping(struct saa7146_dev *dev)
+{
+       u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
+
+       /* mask out relevant bits (=lower word)*/
+       clip_format &= MASK_W1;
+
+       /* upload clipping-registers*/
+       saa7146_write(dev, CLIP_FORMAT_CTRL, clip_format);
+       saa7146_write(dev, MC2, (MASK_05 | MASK_21));
+
+       /* disable video dma2 */
+       saa7146_write(dev, MC1, MASK_21);
+}
+
 void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
 {
-       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
        struct saa7146_vv *vv = dev->vv_data;
+       struct v4l2_pix_format *pix = &vv->video_fmt;
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
        u32 vdma1_prot_addr;
 
        DEB_CAP("buf:%p, next:%p\n", buf, next);
@@ -1009,7 +734,7 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struc
                saa7146_write(dev, MC2, MASK_27 );
        }
 
-       saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field);
+       saa7146_set_window(dev, pix->width, pix->height, pix->field);
        saa7146_set_output_format(dev, sfmt->trans);
        saa7146_disable_clipping(dev);
 
index bd442b984423feb1c8dfc6ce25760c642ed08f58..bb7d81f7eba624d5baf25b218f9171eb6ae7a5ef 100644 (file)
@@ -207,7 +207,6 @@ static int buffer_activate(struct saa7146_dev *dev,
                           struct saa7146_buf *next)
 {
        struct saa7146_vv *vv = dev->vv_data;
-       buf->vb.state = VIDEOBUF_ACTIVE;
 
        DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);
        saa7146_set_vbi_capture(dev,buf,next);
@@ -216,114 +215,101 @@ static int buffer_activate(struct saa7146_dev *dev,
        return 0;
 }
 
-static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field)
-{
-       struct file *file = q->priv_data;
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+/* ------------------------------------------------------------------ */
 
-       int err = 0;
-       int lines, llength, size;
+static int queue_setup(struct vb2_queue *q,
+                      unsigned int *num_buffers, unsigned int *num_planes,
+                      unsigned int sizes[], struct device *alloc_devs[])
+{
+       unsigned int size = 16 * 2 * vbi_pixel_to_capture;
 
-       lines   = 16 * 2 ; /* 2 fields */
-       llength = vbi_pixel_to_capture;
-       size = lines * llength;
+       if (*num_planes)
+               return sizes[0] < size ? -EINVAL : 0;
+       *num_planes = 1;
+       sizes[0] = size;
 
-       DEB_VBI("vb:%p\n", vb);
+       return 0;
+}
 
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size) {
-               DEB_VBI("size mismatch\n");
-               return -EINVAL;
-       }
+static void buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct saa7146_dev *dev = vb2_get_drv_priv(vq);
+       struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
+       unsigned long flags;
 
-       if (buf->vb.size != size)
-               saa7146_dma_free(dev,q,buf);
+       spin_lock_irqsave(&dev->slock, flags);
 
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+       saa7146_buffer_queue(dev, &dev->vv_data->vbi_dmaq, buf);
+       spin_unlock_irqrestore(&dev->slock, flags);
+}
 
-               buf->vb.width  = llength;
-               buf->vb.height = lines;
-               buf->vb.size   = size;
-               buf->vb.field  = field; // FIXME: check this
+static int buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
+       struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
+       struct scatterlist *list = sgt->sgl;
+       int length = sgt->nents;
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct saa7146_dev *dev = vb2_get_drv_priv(vq);
+       int ret;
 
-               saa7146_pgtable_free(dev->pci, &buf->pt[2]);
-               saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
-
-               err = videobuf_iolock(q,&buf->vb, NULL);
-               if (err)
-                       goto oops;
-               err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
-                                                dma->sglist, dma->sglen);
-               if (0 != err)
-                       return err;
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
        buf->activate = buffer_activate;
 
-       return 0;
-
- oops:
-       DEB_VBI("error out\n");
-       saa7146_dma_free(dev,q,buf);
+       saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
 
-       return err;
+       ret = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
+                                          list, length);
+       if (ret)
+               saa7146_pgtable_free(dev->pci, &buf->pt[2]);
+       return ret;
 }
 
-static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+static int buf_prepare(struct vb2_buffer *vb)
 {
-       int llength,lines;
-
-       lines   = 16 * 2 ; /* 2 fields */
-       llength = vbi_pixel_to_capture;
-
-       *size = lines * llength;
-       *count = 2;
-
-       DEB_VBI("count:%d, size:%d\n", *count, *size);
+       unsigned int size = 16 * 2 * vbi_pixel_to_capture;
 
+       if (vb2_plane_size(vb, 0) < size)
+               return -EINVAL;
+       vb2_set_plane_payload(vb, 0, size);
        return 0;
 }
 
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static void buf_cleanup(struct vb2_buffer *vb)
 {
-       struct file *file = q->priv_data;
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct saa7146_dev *dev = vb2_get_drv_priv(vq);
 
-       DEB_VBI("vb:%p\n", vb);
-       saa7146_buffer_queue(dev, &vv->vbi_dmaq, buf);
+       saa7146_pgtable_free(dev->pci, &buf->pt[2]);
 }
 
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static void return_buffers(struct vb2_queue *q, int state)
 {
-       struct file *file = q->priv_data;
-       struct saa7146_fh *fh   = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
-       DEB_VBI("vb:%p\n", vb);
-       saa7146_dma_free(dev,q,buf);
+       struct saa7146_dev *dev = vb2_get_drv_priv(q);
+       struct saa7146_dmaqueue *dq = &dev->vv_data->vbi_dmaq;
+       struct saa7146_buf *buf;
+
+       if (dq->curr) {
+               buf = dq->curr;
+               dq->curr = NULL;
+               vb2_buffer_done(&buf->vb.vb2_buf, state);
+       }
+       while (!list_empty(&dq->queue)) {
+               buf = list_entry(dq->queue.next, struct saa7146_buf, list);
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb.vb2_buf, state);
+       }
 }
 
-static const struct videobuf_queue_ops vbi_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
-};
-
-/* ------------------------------------------------------------------ */
-
-static void vbi_stop(struct saa7146_fh *fh, struct file *file)
+static void vbi_stop(struct saa7146_dev *dev)
 {
-       struct saa7146_dev *dev = fh->dev;
        struct saa7146_vv *vv = dev->vv_data;
        unsigned long flags;
-       DEB_VBI("dev:%p, fh:%p\n", dev, fh);
+       DEB_VBI("dev:%p\n", dev);
 
        spin_lock_irqsave(&dev->slock,flags);
 
@@ -336,13 +322,6 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file)
        /* shut down dma 3 transfers */
        saa7146_write(dev, MC1, MASK_20);
 
-       if (vv->vbi_dmaq.curr)
-               saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE);
-
-       videobuf_queue_cancel(&fh->vbi_q);
-
-       vv->vbi_streaming = NULL;
-
        del_timer(&vv->vbi_dmaq.timeout);
        del_timer(&vv->vbi_read_timeout);
 
@@ -352,38 +331,22 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file)
 static void vbi_read_timeout(struct timer_list *t)
 {
        struct saa7146_vv *vv = from_timer(vv, t, vbi_read_timeout);
-       struct file *file = vv->vbi_read_timeout_file;
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-
-       DEB_VBI("dev:%p, fh:%p\n", dev, fh);
+       struct saa7146_dev *dev = vv->vbi_dmaq.dev;
 
-       vbi_stop(fh, file);
-}
-
-static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
-{
        DEB_VBI("dev:%p\n", dev);
 
-       INIT_LIST_HEAD(&vv->vbi_dmaq.queue);
-
-       timer_setup(&vv->vbi_dmaq.timeout, saa7146_buffer_timeout, 0);
-       vv->vbi_dmaq.dev              = dev;
-
-       init_waitqueue_head(&vv->vbi_wq);
+       vbi_stop(dev);
 }
 
-static int vbi_open(struct saa7146_dev *dev, struct file *file)
+static int vbi_begin(struct saa7146_dev *dev)
 {
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_vv *vv = fh->dev->vv_data;
-
+       struct saa7146_vv *vv = dev->vv_data;
        u32 arbtr_ctrl  = saa7146_read(dev, PCI_BT_V1);
        int ret = 0;
 
-       DEB_VBI("dev:%p, fh:%p\n", dev, fh);
+       DEB_VBI("dev:%p\n", dev);
 
-       ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
+       ret = saa7146_res_get(dev, RESOURCE_DMA3_BRS);
        if (0 == ret) {
                DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");
                return -EBUSY;
@@ -395,15 +358,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
        saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
        saa7146_write(dev, MC2, (MASK_04|MASK_20));
 
-       videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
-                           &dev->pci->dev, &dev->slock,
-                           V4L2_BUF_TYPE_VBI_CAPTURE,
-                           V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
-                           sizeof(struct saa7146_buf),
-                           file, &dev->v4l2_lock);
-
        vv->vbi_read_timeout.function = vbi_read_timeout;
-       vv->vbi_read_timeout_file = file;
 
        /* initialize the brs */
        if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
@@ -422,16 +377,52 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
        return 0;
 }
 
-static void vbi_close(struct saa7146_dev *dev, struct file *file)
+static int start_streaming(struct vb2_queue *q, unsigned int count)
 {
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_vv *vv = dev->vv_data;
-       DEB_VBI("dev:%p, fh:%p\n", dev, fh);
+       struct saa7146_dev *dev = vb2_get_drv_priv(q);
+       int ret;
+
+       if (!vb2_is_streaming(&dev->vv_data->vbi_dmaq.q))
+               dev->vv_data->seqnr = 0;
+       ret = vbi_begin(dev);
+       if (ret)
+               return_buffers(q, VB2_BUF_STATE_QUEUED);
+       return ret;
+}
 
-       if( fh == vv->vbi_streaming ) {
-               vbi_stop(fh, file);
-       }
-       saa7146_res_free(fh, RESOURCE_DMA3_BRS);
+static void stop_streaming(struct vb2_queue *q)
+{
+       struct saa7146_dev *dev = vb2_get_drv_priv(q);
+
+       vbi_stop(dev);
+       return_buffers(q, VB2_BUF_STATE_ERROR);
+       saa7146_res_free(dev, RESOURCE_DMA3_BRS);
+}
+
+const struct vb2_ops vbi_qops = {
+       .queue_setup    = queue_setup,
+       .buf_queue      = buf_queue,
+       .buf_init       = buf_init,
+       .buf_prepare    = buf_prepare,
+       .buf_cleanup    = buf_cleanup,
+       .start_streaming = start_streaming,
+       .stop_streaming = stop_streaming,
+       .wait_prepare   = vb2_ops_wait_prepare,
+       .wait_finish    = vb2_ops_wait_finish,
+};
+
+/* ------------------------------------------------------------------ */
+
+static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
+{
+       DEB_VBI("dev:%p\n", dev);
+
+       INIT_LIST_HEAD(&vv->vbi_dmaq.queue);
+
+       timer_setup(&vv->vbi_dmaq.timeout, saa7146_buffer_timeout, 0);
+       vv->vbi_dmaq.dev              = dev;
+
+       init_waitqueue_head(&vv->vbi_wq);
 }
 
 static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
@@ -441,10 +432,7 @@ static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
 
        if (vv->vbi_dmaq.curr) {
                DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_dmaq.curr);
-               /* this must be += 2, one count for each field */
-               vv->vbi_fieldcount+=2;
-               vv->vbi_dmaq.curr->vb.field_count = vv->vbi_fieldcount;
-               saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE);
+               saa7146_buffer_finish(dev, &vv->vbi_dmaq, VB2_BUF_STATE_DONE);
        } else {
                DEB_VBI("dev:%p\n", dev);
        }
@@ -453,46 +441,7 @@ static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
        spin_unlock(&dev->slock);
 }
 
-static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       ssize_t ret = 0;
-
-       DEB_VBI("dev:%p, fh:%p\n", dev, fh);
-
-       if( NULL == vv->vbi_streaming ) {
-               // fixme: check if dma3 is available
-               // fixme: activate vbi engine here if necessary. (really?)
-               vv->vbi_streaming = fh;
-       }
-
-       if( fh != vv->vbi_streaming ) {
-               DEB_VBI("open %p is already using vbi capture\n",
-                       vv->vbi_streaming);
-               return -EBUSY;
-       }
-
-       mod_timer(&vv->vbi_read_timeout, jiffies+BUFFER_TIMEOUT);
-       ret = videobuf_read_stream(&fh->vbi_q, data, count, ppos, 1,
-                                  file->f_flags & O_NONBLOCK);
-/*
-       printk("BASE_ODD3:      0x%08x\n", saa7146_read(dev, BASE_ODD3));
-       printk("BASE_EVEN3:     0x%08x\n", saa7146_read(dev, BASE_EVEN3));
-       printk("PROT_ADDR3:     0x%08x\n", saa7146_read(dev, PROT_ADDR3));
-       printk("PITCH3:         0x%08x\n", saa7146_read(dev, PITCH3));
-       printk("BASE_PAGE3:     0x%08x\n", saa7146_read(dev, BASE_PAGE3));
-       printk("NUM_LINE_BYTE3: 0x%08x\n", saa7146_read(dev, NUM_LINE_BYTE3));
-       printk("BRS_CTRL:       0x%08x\n", saa7146_read(dev, BRS_CTRL));
-*/
-       return ret;
-}
-
 const struct saa7146_use_ops saa7146_vbi_uops = {
        .init           = vbi_init,
-       .open           = vbi_open,
-       .release        = vbi_close,
        .irq_done       = vbi_irq_done,
-       .read           = vbi_read,
 };
index 2296765079a41d503cf77e94f2a4ded828924147..040489e15ea0c32c2646f8c77db83e3ebae10ae5 100644 (file)
@@ -6,17 +6,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 
-static int max_memory = 32;
-
-module_param(max_memory, int, 0644);
-MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)");
-
-#define IS_CAPTURE_ACTIVE(fh) \
-       (((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh))
-
-#define IS_OVERLAY_ACTIVE(fh) \
-       (((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh))
-
 /* format descriptions for capture and preview */
 static struct saa7146_format formats[] = {
        {
@@ -54,7 +43,7 @@ static struct saa7146_format formats[] = {
                .pixelformat    = V4L2_PIX_FMT_YUV422P,
                .trans          = YUV422_DECOMPOSED,
                .depth          = 16,
-               .flags          = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
+               .flags          = FORMAT_IS_PLANAR,
        }, {
                .pixelformat    = V4L2_PIX_FMT_YVU420,
                .trans          = YUV420_DECOMPOSED,
@@ -91,115 +80,18 @@ struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fou
        return NULL;
 }
 
-static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f);
-
-int saa7146_start_preview(struct saa7146_fh *fh)
-{
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       struct v4l2_format fmt;
-       int ret = 0, err = 0;
-
-       DEB_EE("dev:%p, fh:%p\n", dev, fh);
-
-       /* check if we have overlay information */
-       if (vv->ov.fh == NULL) {
-               DEB_D("no overlay data available. try S_FMT first.\n");
-               return -EAGAIN;
-       }
-
-       /* check if streaming capture is running */
-       if (IS_CAPTURE_ACTIVE(fh) != 0) {
-               DEB_D("streaming capture is active\n");
-               return -EBUSY;
-       }
-
-       /* check if overlay is running */
-       if (IS_OVERLAY_ACTIVE(fh) != 0) {
-               if (vv->video_fh == fh) {
-                       DEB_D("overlay is already active\n");
-                       return 0;
-               }
-               DEB_D("overlay is already active in another open\n");
-               return -EBUSY;
-       }
-
-       if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
-               DEB_D("cannot get necessary overlay resources\n");
-               return -EBUSY;
-       }
-
-       fmt.fmt.win = vv->ov.win;
-       err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt);
-       if (0 != err) {
-               saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
-               return -EBUSY;
-       }
-       vv->ov.win = fmt.fmt.win;
-
-       DEB_D("%dx%d+%d+%d 0x%08x field=%s\n",
-             vv->ov.win.w.width, vv->ov.win.w.height,
-             vv->ov.win.w.left, vv->ov.win.w.top,
-             vv->ov_fmt->pixelformat, v4l2_field_names[vv->ov.win.field]);
-
-       if (0 != (ret = saa7146_enable_overlay(fh))) {
-               DEB_D("enabling overlay failed: %d\n", ret);
-               saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
-               return ret;
-       }
-
-       vv->video_status = STATUS_OVERLAY;
-       vv->video_fh = fh;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(saa7146_start_preview);
-
-int saa7146_stop_preview(struct saa7146_fh *fh)
-{
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-
-       DEB_EE("dev:%p, fh:%p\n", dev, fh);
-
-       /* check if streaming capture is running */
-       if (IS_CAPTURE_ACTIVE(fh) != 0) {
-               DEB_D("streaming capture is active\n");
-               return -EBUSY;
-       }
-
-       /* check if overlay is running at all */
-       if ((vv->video_status & STATUS_OVERLAY) == 0) {
-               DEB_D("no active overlay\n");
-               return 0;
-       }
-
-       if (vv->video_fh != fh) {
-               DEB_D("overlay is active, but in another open\n");
-               return -EBUSY;
-       }
-
-       vv->video_status = 0;
-       vv->video_fh = NULL;
-
-       saa7146_disable_overlay(fh);
-
-       saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(saa7146_stop_preview);
-
 /********************************************************************************/
 /* common pagetable functions */
 
 static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
 {
+       struct saa7146_vv *vv = dev->vv_data;
        struct pci_dev *pci = dev->pci;
-       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-       struct scatterlist *list = dma->sglist;
-       int length = dma->sglen;
-       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
+       struct scatterlist *list = sgt->sgl;
+       int length = sgt->nents;
+       struct v4l2_pix_format *pix = &vv->video_fmt;
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
 
        DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
 
@@ -207,31 +99,32 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
                struct saa7146_pgtable *pt1 = &buf->pt[0];
                struct saa7146_pgtable *pt2 = &buf->pt[1];
                struct saa7146_pgtable *pt3 = &buf->pt[2];
+               struct sg_dma_page_iter dma_iter;
                __le32  *ptr1, *ptr2, *ptr3;
                __le32 fill;
 
-               int size = buf->fmt->width*buf->fmt->height;
-               int i,p,m1,m2,m3,o1,o2;
+               int size = pix->width * pix->height;
+               int i, m1, m2, m3, o1, o2;
 
                switch( sfmt->depth ) {
                        case 12: {
                                /* create some offsets inside the page table */
-                               m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
-                               m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1;
-                               m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
-                               o1 = size%PAGE_SIZE;
-                               o2 = (size+(size/4))%PAGE_SIZE;
+                               m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
+                               m2 = ((size + (size / 4) + PAGE_SIZE) / PAGE_SIZE) - 1;
+                               m3 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
+                               o1 = size % PAGE_SIZE;
+                               o2 = (size + (size / 4)) % PAGE_SIZE;
                                DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
                                        size, m1, m2, m3, o1, o2);
                                break;
                        }
                        case 16: {
                                /* create some offsets inside the page table */
-                               m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
-                               m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
-                               m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
-                               o1 = size%PAGE_SIZE;
-                               o2 = (size+(size/2))%PAGE_SIZE;
+                               m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
+                               m2 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
+                               m3 = ((2 * size + PAGE_SIZE) / PAGE_SIZE) - 1;
+                               o1 = size % PAGE_SIZE;
+                               o2 = (size + (size / 2)) % PAGE_SIZE;
                                DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
                                        size, m1, m2, m3, o1, o2);
                                break;
@@ -245,64 +138,37 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
                ptr2 = pt2->cpu;
                ptr3 = pt3->cpu;
 
-               /* walk all pages, copy all page addresses to ptr1 */
-               for (i = 0; i < length; i++, list++) {
-                       for (p = 0; p * 4096 < sg_dma_len(list); p++, ptr1++)
-                               *ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset);
-               }
-/*
-               ptr1 = pt1->cpu;
-               for(j=0;j<40;j++) {
-                       printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
-               }
-*/
+               for_each_sg_dma_page(list, &dma_iter, length, 0)
+                       *ptr1++ = cpu_to_le32(sg_page_iter_dma_address(&dma_iter) - list->offset);
 
                /* if we have a user buffer, the first page may not be
                   aligned to a page boundary. */
-               pt1->offset = dma->sglist->offset;
-               pt2->offset = pt1->offset+o1;
-               pt3->offset = pt1->offset+o2;
+               pt1->offset = sgt->sgl->offset;
+               pt2->offset = pt1->offset + o1;
+               pt3->offset = pt1->offset + o2;
 
                /* create video-dma2 page table */
                ptr1 = pt1->cpu;
-               for(i = m1; i <= m2 ; i++, ptr2++) {
+               for (i = m1; i <= m2; i++, ptr2++)
                        *ptr2 = ptr1[i];
-               }
-               fill = *(ptr2-1);
-               for(;i<1024;i++,ptr2++) {
+               fill = *(ptr2 - 1);
+               for (; i < 1024; i++, ptr2++)
                        *ptr2 = fill;
-               }
                /* create video-dma3 page table */
                ptr1 = pt1->cpu;
-               for(i = m2; i <= m3; i++,ptr3++) {
+               for (i = m2; i <= m3; i++, ptr3++)
                        *ptr3 = ptr1[i];
-               }
-               fill = *(ptr3-1);
-               for(;i<1024;i++,ptr3++) {
+               fill = *(ptr3 - 1);
+               for (; i < 1024; i++, ptr3++)
                        *ptr3 = fill;
-               }
                /* finally: finish up video-dma1 page table */
-               ptr1 = pt1->cpu+m1;
+               ptr1 = pt1->cpu + m1;
                fill = pt1->cpu[m1];
-               for(i=m1;i<1024;i++,ptr1++) {
+               for (i = m1; i < 1024; i++, ptr1++)
                        *ptr1 = fill;
-               }
-/*
-               ptr1 = pt1->cpu;
-               ptr2 = pt2->cpu;
-               ptr3 = pt3->cpu;
-               for(j=0;j<40;j++) {
-                       printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
-               }
-               for(j=0;j<40;j++) {
-                       printk("ptr2 %d: 0x%08x\n",j,ptr2[j]);
-               }
-               for(j=0;j<40;j++) {
-                       printk("ptr3 %d: 0x%08x\n",j,ptr3[j]);
-               }
-*/
        } else {
                struct saa7146_pgtable *pt = &buf->pt[0];
+
                return saa7146_pgtable_build_single(pci, pt, list, length);
        }
 
@@ -313,34 +179,14 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
 /********************************************************************************/
 /* file operations */
 
-static int video_begin(struct saa7146_fh *fh)
+static int video_begin(struct saa7146_dev *dev)
 {
-       struct saa7146_dev *dev = fh->dev;
        struct saa7146_vv *vv = dev->vv_data;
        struct saa7146_format *fmt = NULL;
        unsigned int resource;
-       int ret = 0, err = 0;
-
-       DEB_EE("dev:%p, fh:%p\n", dev, fh);
-
-       if ((vv->video_status & STATUS_CAPTURE) != 0) {
-               if (vv->video_fh == fh) {
-                       DEB_S("already capturing\n");
-                       return 0;
-               }
-               DEB_S("already capturing in another open\n");
-               return -EBUSY;
-       }
+       int ret = 0;
 
-       if ((vv->video_status & STATUS_OVERLAY) != 0) {
-               DEB_S("warning: suspending overlay video for streaming capture\n");
-               vv->ov_suspend = vv->video_fh;
-               err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
-               if (0 != err) {
-                       DEB_D("suspending video failed. aborting\n");
-                       return err;
-               }
-       }
+       DEB_EE("dev:%p\n", dev);
 
        fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
        /* we need to have a valid format set here */
@@ -353,13 +199,9 @@ static int video_begin(struct saa7146_fh *fh)
                resource = RESOURCE_DMA1_HPS;
        }
 
-       ret = saa7146_res_get(fh, resource);
+       ret = saa7146_res_get(dev, resource);
        if (0 == ret) {
                DEB_S("cannot get capture resource %d\n", resource);
-               if (vv->ov_suspend != NULL) {
-                       saa7146_start_preview(vv->ov_suspend);
-                       vv->ov_suspend = NULL;
-               }
                return -EBUSY;
        }
 
@@ -369,37 +211,22 @@ static int video_begin(struct saa7146_fh *fh)
        /* enable rps0 irqs */
        SAA7146_IER_ENABLE(dev, MASK_27);
 
-       vv->video_fh = fh;
-       vv->video_status = STATUS_CAPTURE;
-
        return 0;
 }
 
-static int video_end(struct saa7146_fh *fh, struct file *file)
+static void video_end(struct saa7146_dev *dev)
 {
-       struct saa7146_dev *dev = fh->dev;
        struct saa7146_vv *vv = dev->vv_data;
-       struct saa7146_dmaqueue *q = &vv->video_dmaq;
        struct saa7146_format *fmt = NULL;
        unsigned long flags;
        unsigned int resource;
        u32 dmas = 0;
-       DEB_EE("dev:%p, fh:%p\n", dev, fh);
-
-       if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
-               DEB_S("not capturing\n");
-               return 0;
-       }
-
-       if (vv->video_fh != fh) {
-               DEB_S("capturing, but in another open\n");
-               return -EBUSY;
-       }
+       DEB_EE("dev:%p\n", dev);
 
        fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
        /* we need to have a valid format set here */
        if (!fmt)
-               return -EINVAL;
+               return;
 
        if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
                resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
@@ -419,88 +246,24 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
        /* shut down all used video dma transfers */
        saa7146_write(dev, MC1, dmas);
 
-       if (q->curr)
-               saa7146_buffer_finish(dev, q, VIDEOBUF_DONE);
-
        spin_unlock_irqrestore(&dev->slock, flags);
 
-       vv->video_fh = NULL;
-       vv->video_status = 0;
-
-       saa7146_res_free(fh, resource);
-
-       if (vv->ov_suspend != NULL) {
-               saa7146_start_preview(vv->ov_suspend);
-               vv->ov_suspend = NULL;
-       }
-
-       return 0;
+       saa7146_res_free(dev, resource);
 }
 
 static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
 
        strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));
        strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
                            V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
                            V4L2_CAP_DEVICE_CAPS;
        cap->capabilities |= dev->ext_vv_data->capabilities;
        return 0;
 }
 
-static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
-{
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-
-       *fb = vv->ov_fb;
-       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-       fb->flags = V4L2_FBUF_FLAG_PRIMARY;
-       return 0;
-}
-
-static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
-{
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       struct saa7146_format *fmt;
-
-       DEB_EE("VIDIOC_S_FBUF\n");
-
-       if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       /* check args */
-       fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-
-       /* planar formats are not allowed for overlay video, clipping and video dma would clash */
-       if (fmt->flags & FORMAT_IS_PLANAR)
-               DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n",
-                     (char *)&fmt->pixelformat);
-
-       /* check if overlay is running */
-       if (IS_OVERLAY_ACTIVE(fh) != 0) {
-               if (vv->video_fh != fh) {
-                       DEB_D("refusing to change framebuffer information while overlay is active in another open\n");
-                       return -EBUSY;
-               }
-       }
-
-       /* ok, accept it */
-       vv->ov_fb = *fb;
-       vv->ov_fmt = fmt;
-
-       if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
-               vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
-               DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
-       }
-       return 0;
-}
-
 static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
 {
        if (f->index >= ARRAY_SIZE(formats))
@@ -543,13 +306,13 @@ int saa7146_s_ctrl(struct v4l2_ctrl *ctrl)
 
        case V4L2_CID_HFLIP:
                /* fixme: we can support changing VFLIP and HFLIP here... */
-               if ((vv->video_status & STATUS_CAPTURE))
+               if (vb2_is_busy(&vv->video_dmaq.q))
                        return -EBUSY;
                vv->hflip = ctrl->val;
                break;
 
        case V4L2_CID_VFLIP:
-               if ((vv->video_status & STATUS_CAPTURE))
+               if (vb2_is_busy(&vv->video_dmaq.q))
                        return -EBUSY;
                vv->vflip = ctrl->val;
                break;
@@ -557,20 +320,13 @@ int saa7146_s_ctrl(struct v4l2_ctrl *ctrl)
        default:
                return -EINVAL;
        }
-
-       if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */
-               struct saa7146_fh *fh = vv->video_fh;
-
-               saa7146_stop_preview(fh);
-               saa7146_start_preview(fh);
-       }
        return 0;
 }
 
 static int vidioc_g_parm(struct file *file, void *fh,
                struct v4l2_streamparm *parm)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct saa7146_vv *vv = dev->vv_data;
 
        if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -583,25 +339,16 @@ static int vidioc_g_parm(struct file *file, void *fh,
 
 static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct saa7146_vv *vv = dev->vv_data;
 
        f->fmt.pix = vv->video_fmt;
        return 0;
 }
 
-static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
-{
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-
-       f->fmt.win = vv->ov.win;
-       return 0;
-}
-
 static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct saa7146_vv *vv = dev->vv_data;
 
        f->fmt.vbi = vv->vbi_fmt;
@@ -610,7 +357,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format
 
 static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct saa7146_vv *vv = dev->vv_data;
        struct saa7146_format *fmt;
        enum v4l2_field field;
@@ -634,24 +381,21 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
        }
        switch (field) {
        case V4L2_FIELD_ALTERNATE:
-               vv->last_field = V4L2_FIELD_TOP;
-               maxh = maxh / 2;
-               break;
        case V4L2_FIELD_TOP:
        case V4L2_FIELD_BOTTOM:
-               vv->last_field = V4L2_FIELD_INTERLACED;
                maxh = maxh / 2;
                break;
-       case V4L2_FIELD_INTERLACED:
-               vv->last_field = V4L2_FIELD_INTERLACED;
-               break;
        default:
-               DEB_D("no known field mode '%d'\n", field);
-               return -EINVAL;
+               field = V4L2_FIELD_INTERLACED;
+               break;
        }
 
        f->fmt.pix.field = field;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.height < 32)
+               f->fmt.pix.height = 32;
        if (f->fmt.pix.width > maxw)
                f->fmt.pix.width = maxw;
        if (f->fmt.pix.height > maxh)
@@ -673,169 +417,65 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
        return 0;
 }
 
-
-static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
+static int vidioc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       struct v4l2_window *win = &f->fmt.win;
-       enum v4l2_field field;
-       int maxw, maxh;
-
-       DEB_EE("dev:%p\n", dev);
-
-       if (NULL == vv->ov_fb.base) {
-               DEB_D("no fb base set\n");
-               return -EINVAL;
-       }
-       if (NULL == vv->ov_fmt) {
-               DEB_D("no fb fmt set\n");
-               return -EINVAL;
-       }
-       if (win->w.width < 48 || win->w.height < 32) {
-               DEB_D("min width/height. (%d,%d)\n",
-                     win->w.width, win->w.height);
-               return -EINVAL;
-       }
-       if (win->clipcount > 16) {
-               DEB_D("clipcount too big\n");
-               return -EINVAL;
-       }
-
-       field = win->field;
-       maxw  = vv->standard->h_max_out;
-       maxh  = vv->standard->v_max_out;
-
-       if (V4L2_FIELD_ANY == field) {
-               field = (win->w.height > maxh / 2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_TOP;
-               }
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-       case V4L2_FIELD_ALTERNATE:
-               maxh = maxh / 2;
-               break;
-       case V4L2_FIELD_INTERLACED:
-               break;
-       default:
-               DEB_D("no known field mode '%d'\n", field);
-               return -EINVAL;
-       }
-
-       win->field = field;
-       if (win->w.width > maxw)
-               win->w.width = maxw;
-       if (win->w.height > maxh)
-               win->w.height = maxh;
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f)
-{
-       struct saa7146_fh *fh = __fh;
-       struct saa7146_dev *dev = fh->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct saa7146_vv *vv = dev->vv_data;
        int err;
 
-       DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
-       if (IS_CAPTURE_ACTIVE(fh) != 0) {
+       DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p\n", dev);
+       if (vb2_is_busy(&vv->video_dmaq.q)) {
                DEB_EE("streaming capture is active\n");
                return -EBUSY;
        }
        err = vidioc_try_fmt_vid_cap(file, fh, f);
        if (0 != err)
                return err;
+       switch (f->fmt.pix.field) {
+       case V4L2_FIELD_ALTERNATE:
+               vv->last_field = V4L2_FIELD_TOP;
+               break;
+       default:
+               vv->last_field = V4L2_FIELD_INTERLACED;
+               break;
+       }
        vv->video_fmt = f->fmt.pix;
        DEB_EE("set to pixelformat '%4.4s'\n",
               (char *)&vv->video_fmt.pixelformat);
        return 0;
 }
 
-static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f)
-{
-       struct saa7146_fh *fh = __fh;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       int err;
-
-       DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh);
-       err = vidioc_try_fmt_vid_overlay(file, fh, f);
-       if (0 != err)
-               return err;
-       vv->ov.win    = f->fmt.win;
-       vv->ov.nclips = f->fmt.win.clipcount;
-       if (vv->ov.nclips > 16)
-               vv->ov.nclips = 16;
-       memcpy(vv->ov.clips, f->fmt.win.clips,
-              sizeof(struct v4l2_clip) * vv->ov.nclips);
-
-       /* vv->ov.fh is used to indicate that we have valid overlay information, too */
-       vv->ov.fh = fh;
-
-       /* check if our current overlay is active */
-       if (IS_OVERLAY_ACTIVE(fh) != 0) {
-               saa7146_stop_preview(fh);
-               saa7146_start_preview(fh);
-       }
-       return 0;
-}
-
 static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct saa7146_vv *vv = dev->vv_data;
 
        *norm = vv->standard->id;
        return 0;
 }
 
-       /* the saa7146 supfhrts (used in conjunction with the saa7111a for example)
-          PAL / NTSC / SECAM. if your hardware does not (or does more)
-          -- override this function in your extension */
-/*
-       case VIDIOC_ENUMSTD:
-       {
-               struct v4l2_standard *e = arg;
-               if (e->index < 0 )
-                       return -EINVAL;
-               if( e->index < dev->ext_vv_data->num_stds ) {
-                       DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
-                       v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
-                       return 0;
-               }
-               return -EINVAL;
-       }
-       */
-
 static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct saa7146_vv *vv = dev->vv_data;
        int found = 0;
-       int err, i;
+       int i;
 
        DEB_EE("VIDIOC_S_STD\n");
 
-       if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
+       for (i = 0; i < dev->ext_vv_data->num_stds; i++)
+               if (id & dev->ext_vv_data->stds[i].id)
+                       break;
+
+       if (i != dev->ext_vv_data->num_stds &&
+           vv->standard == &dev->ext_vv_data->stds[i])
+               return 0;
+
+       if (vb2_is_busy(&vv->video_dmaq.q) || vb2_is_busy(&vv->vbi_dmaq.q)) {
                DEB_D("cannot change video standard while streaming capture is active\n");
                return -EBUSY;
        }
 
-       if ((vv->video_status & STATUS_OVERLAY) != 0) {
-               vv->ov_suspend = vv->video_fh;
-               err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
-               if (0 != err) {
-                       DEB_D("suspending video failed. aborting\n");
-                       return err;
-               }
-       }
-
-       for (i = 0; i < dev->ext_vv_data->num_stds; i++)
-               if (id & dev->ext_vv_data->stds[i].id)
-                       break;
        if (i != dev->ext_vv_data->num_stds) {
                vv->standard = &dev->ext_vv_data->stds[i];
                if (NULL != dev->ext_vv_data->std_callback)
@@ -843,11 +483,6 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
                found = 1;
        }
 
-       if (vv->ov_suspend != NULL) {
-               saa7146_start_preview(vv->ov_suspend);
-               vv->ov_suspend = NULL;
-       }
-
        if (!found) {
                DEB_EE("VIDIOC_S_STD: standard not found\n");
                return -EINVAL;
@@ -857,138 +492,22 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
        return 0;
 }
 
-static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
-{
-       int err;
-
-       DEB_D("VIDIOC_OVERLAY on:%d\n", on);
-       if (on)
-               err = saa7146_start_preview(fh);
-       else
-               err = saa7146_stop_preview(fh);
-       return err;
-}
-
-static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b)
-{
-       struct saa7146_fh *fh = __fh;
-
-       if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return videobuf_reqbufs(&fh->video_q, b);
-       if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               return videobuf_reqbufs(&fh->vbi_q, b);
-       return -EINVAL;
-}
-
-static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
-{
-       struct saa7146_fh *fh = __fh;
-
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return videobuf_querybuf(&fh->video_q, buf);
-       if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               return videobuf_querybuf(&fh->vbi_q, buf);
-       return -EINVAL;
-}
-
-static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
-{
-       struct saa7146_fh *fh = __fh;
-
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return videobuf_qbuf(&fh->video_q, buf);
-       if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               return videobuf_qbuf(&fh->vbi_q, buf);
-       return -EINVAL;
-}
-
-static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
-{
-       struct saa7146_fh *fh = __fh;
-
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK);
-       if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK);
-       return -EINVAL;
-}
-
-static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
-{
-       struct saa7146_fh *fh = __fh;
-       int err;
-
-       DEB_D("VIDIOC_STREAMON, type:%d\n", type);
-
-       err = video_begin(fh);
-       if (err)
-               return err;
-       if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return videobuf_streamon(&fh->video_q);
-       if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               return videobuf_streamon(&fh->vbi_q);
-       return -EINVAL;
-}
-
-static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
-{
-       struct saa7146_fh *fh = __fh;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       int err;
-
-       DEB_D("VIDIOC_STREAMOFF, type:%d\n", type);
-
-       /* ugly: we need to copy some checks from video_end(),
-          because videobuf_streamoff() relies on the capture running.
-          check and fix this */
-       if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
-               DEB_S("not capturing\n");
-               return 0;
-       }
-
-       if (vv->video_fh != fh) {
-               DEB_S("capturing, but in another open\n");
-               return -EBUSY;
-       }
-
-       err = -EINVAL;
-       if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               err = videobuf_streamoff(&fh->video_q);
-       else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               err = videobuf_streamoff(&fh->vbi_q);
-       if (0 != err) {
-               DEB_D("warning: videobuf_streamoff() failed\n");
-               video_end(fh, file);
-       } else {
-               err = video_end(fh, file);
-       }
-       return err;
-}
-
 const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
        .vidioc_querycap             = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap     = vidioc_enum_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap        = vidioc_g_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap      = vidioc_try_fmt_vid_cap,
        .vidioc_s_fmt_vid_cap        = vidioc_s_fmt_vid_cap,
-       .vidioc_g_fmt_vid_overlay    = vidioc_g_fmt_vid_overlay,
-       .vidioc_try_fmt_vid_overlay  = vidioc_try_fmt_vid_overlay,
-       .vidioc_s_fmt_vid_overlay    = vidioc_s_fmt_vid_overlay,
-
-       .vidioc_overlay              = vidioc_overlay,
-       .vidioc_g_fbuf               = vidioc_g_fbuf,
-       .vidioc_s_fbuf               = vidioc_s_fbuf,
-       .vidioc_reqbufs              = vidioc_reqbufs,
-       .vidioc_querybuf             = vidioc_querybuf,
-       .vidioc_qbuf                 = vidioc_qbuf,
-       .vidioc_dqbuf                = vidioc_dqbuf,
        .vidioc_g_std                = vidioc_g_std,
        .vidioc_s_std                = vidioc_s_std,
-       .vidioc_streamon             = vidioc_streamon,
-       .vidioc_streamoff            = vidioc_streamoff,
        .vidioc_g_parm               = vidioc_g_parm,
+       .vidioc_reqbufs              = vb2_ioctl_reqbufs,
+       .vidioc_create_bufs          = vb2_ioctl_create_bufs,
+       .vidioc_querybuf             = vb2_ioctl_querybuf,
+       .vidioc_qbuf                 = vb2_ioctl_qbuf,
+       .vidioc_dqbuf                = vb2_ioctl_dqbuf,
+       .vidioc_streamon             = vb2_ioctl_streamon,
+       .vidioc_streamoff            = vb2_ioctl_streamoff,
        .vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
        .vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
 };
@@ -996,16 +515,18 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
 const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
        .vidioc_querycap             = vidioc_querycap,
        .vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
-
-       .vidioc_reqbufs              = vidioc_reqbufs,
-       .vidioc_querybuf             = vidioc_querybuf,
-       .vidioc_qbuf                 = vidioc_qbuf,
-       .vidioc_dqbuf                = vidioc_dqbuf,
+       .vidioc_try_fmt_vbi_cap      = vidioc_g_fmt_vbi_cap,
+       .vidioc_s_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
        .vidioc_g_std                = vidioc_g_std,
        .vidioc_s_std                = vidioc_s_std,
-       .vidioc_streamon             = vidioc_streamon,
-       .vidioc_streamoff            = vidioc_streamoff,
        .vidioc_g_parm               = vidioc_g_parm,
+       .vidioc_reqbufs              = vb2_ioctl_reqbufs,
+       .vidioc_create_bufs          = vb2_ioctl_create_bufs,
+       .vidioc_querybuf             = vb2_ioctl_querybuf,
+       .vidioc_qbuf                 = vb2_ioctl_qbuf,
+       .vidioc_dqbuf                = vb2_ioctl_dqbuf,
+       .vidioc_streamon             = vb2_ioctl_streamon,
+       .vidioc_streamoff            = vb2_ioctl_streamoff,
        .vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
        .vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
 };
@@ -1019,7 +540,6 @@ static int buffer_activate (struct saa7146_dev *dev,
 {
        struct saa7146_vv *vv = dev->vv_data;
 
-       buf->vb.state = VIDEOBUF_ACTIVE;
        saa7146_set_capture(dev,buf,next);
 
        mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
@@ -1033,140 +553,136 @@ static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *
        saa7146_pgtable_free(dev->pci, &buf->pt[2]);
 }
 
-static int buffer_prepare(struct videobuf_queue *q,
-                         struct videobuf_buffer *vb, enum v4l2_field field)
+static int queue_setup(struct vb2_queue *q,
+                      unsigned int *num_buffers, unsigned int *num_planes,
+                      unsigned int sizes[], struct device *alloc_devs[])
 {
-       struct file *file = q->priv_data;
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-       int size,err = 0;
-
-       DEB_CAP("vbuf:%p\n", vb);
-
-       /* sanity checks */
-       if (vv->video_fmt.width  < 48 ||
-           vv->video_fmt.height < 32 ||
-           vv->video_fmt.width  > vv->standard->h_max_out ||
-           vv->video_fmt.height > vv->standard->v_max_out) {
-               DEB_D("w (%d) / h (%d) out of bounds\n",
-                     vv->video_fmt.width, vv->video_fmt.height);
-               return -EINVAL;
-       }
+       struct saa7146_dev *dev = vb2_get_drv_priv(q);
+       unsigned int size = dev->vv_data->video_fmt.sizeimage;
 
-       size = vv->video_fmt.sizeimage;
-       if (0 != buf->vb.baddr && buf->vb.bsize < size) {
-               DEB_D("size mismatch\n");
-               return -EINVAL;
-       }
+       if (*num_planes)
+               return sizes[0] < size ? -EINVAL : 0;
+       *num_planes = 1;
+       sizes[0] = size;
 
-       DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
-               vv->video_fmt.width, vv->video_fmt.height,
-               size, v4l2_field_names[vv->video_fmt.field]);
-       if (buf->vb.width  != vv->video_fmt.width  ||
-           buf->vb.bytesperline != vv->video_fmt.bytesperline ||
-           buf->vb.height != vv->video_fmt.height ||
-           buf->vb.size   != size ||
-           buf->vb.field  != field      ||
-           buf->vb.field  != vv->video_fmt.field  ||
-           buf->fmt       != &vv->video_fmt) {
-               saa7146_dma_free(dev,q,buf);
-       }
+       return 0;
+}
 
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               struct saa7146_format *sfmt;
+static void buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct saa7146_dev *dev = vb2_get_drv_priv(vq);
+       struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
+       unsigned long flags;
 
-               buf->vb.bytesperline  = vv->video_fmt.bytesperline;
-               buf->vb.width  = vv->video_fmt.width;
-               buf->vb.height = vv->video_fmt.height;
-               buf->vb.size   = size;
-               buf->vb.field  = field;
-               buf->fmt       = &vv->video_fmt;
-               buf->vb.field  = vv->video_fmt.field;
+       spin_lock_irqsave(&dev->slock, flags);
 
-               sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
+       saa7146_buffer_queue(dev, &dev->vv_data->video_dmaq, buf);
+       spin_unlock_irqrestore(&dev->slock, flags);
+}
 
-               release_all_pagetables(dev, buf);
-               if( 0 != IS_PLANAR(sfmt->trans)) {
-                       saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
-                       saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
-                       saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
-               } else {
-                       saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
-               }
+static int buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct saa7146_dev *dev = vb2_get_drv_priv(vq);
+       struct saa7146_vv *vv = dev->vv_data;
+       struct saa7146_format *sfmt;
+       int ret;
 
-               err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
-               if (err)
-                       goto oops;
-               err = saa7146_pgtable_build(dev,buf);
-               if (err)
-                       goto oops;
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
        buf->activate = buffer_activate;
+       sfmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
 
-       return 0;
-
- oops:
-       DEB_D("error out\n");
-       saa7146_dma_free(dev,q,buf);
+       if (IS_PLANAR(sfmt->trans)) {
+               saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
+               saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
+               saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
+       } else {
+               saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
+       }
 
-       return err;
+       ret = saa7146_pgtable_build(dev, buf);
+       if (ret)
+               release_all_pagetables(dev, buf);
+       return ret;
 }
 
-static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+static int buf_prepare(struct vb2_buffer *vb)
 {
-       struct file *file = q->priv_data;
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_vv *vv = fh->dev->vv_data;
-
-       if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)
-               *count = MAX_SAA7146_CAPTURE_BUFFERS;
-
-       *size = vv->video_fmt.sizeimage;
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct saa7146_dev *dev = vb2_get_drv_priv(vq);
+       struct saa7146_vv *vv = dev->vv_data;
+       unsigned int size = vv->video_fmt.sizeimage;
 
-       /* check if we exceed the "max_memory" parameter */
-       if( (*count * *size) > (max_memory*1048576) ) {
-               *count = (max_memory*1048576) / *size;
-       }
+       if (vb2_plane_size(vb, 0) < size)
+               return -EINVAL;
+       vb2_set_plane_payload(vb, 0, size);
+       return 0;
+}
 
-       DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
+static void buf_cleanup(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct saa7146_dev *dev = vb2_get_drv_priv(vq);
 
-       return 0;
+       release_all_pagetables(dev, buf);
 }
 
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static void return_buffers(struct vb2_queue *q, int state)
 {
-       struct file *file = q->priv_data;
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+       struct saa7146_dev *dev = vb2_get_drv_priv(q);
+       struct saa7146_dmaqueue *dq = &dev->vv_data->video_dmaq;
+       struct saa7146_buf *buf;
 
-       DEB_CAP("vbuf:%p\n", vb);
-       saa7146_buffer_queue(fh->dev, &vv->video_dmaq, buf);
+       if (dq->curr) {
+               buf = dq->curr;
+               dq->curr = NULL;
+               vb2_buffer_done(&buf->vb.vb2_buf, state);
+       }
+       while (!list_empty(&dq->queue)) {
+               buf = list_entry(dq->queue.next, struct saa7146_buf, list);
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb.vb2_buf, state);
+       }
 }
 
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static int start_streaming(struct vb2_queue *q, unsigned int count)
 {
-       struct file *file = q->priv_data;
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+       struct saa7146_dev *dev = vb2_get_drv_priv(q);
+       int ret;
 
-       DEB_CAP("vbuf:%p\n", vb);
+       if (!vb2_is_streaming(&dev->vv_data->video_dmaq.q))
+               dev->vv_data->seqnr = 0;
+       ret = video_begin(dev);
+       if (ret)
+               return_buffers(q, VB2_BUF_STATE_QUEUED);
+       return ret;
+}
 
-       saa7146_dma_free(dev,q,buf);
+static void stop_streaming(struct vb2_queue *q)
+{
+       struct saa7146_dev *dev = vb2_get_drv_priv(q);
+       struct saa7146_dmaqueue *dq = &dev->vv_data->video_dmaq;
 
-       release_all_pagetables(dev, buf);
+       del_timer(&dq->timeout);
+       video_end(dev);
+       return_buffers(q, VB2_BUF_STATE_ERROR);
 }
 
-static const struct videobuf_queue_ops video_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
+const struct vb2_ops video_qops = {
+       .queue_setup    = queue_setup,
+       .buf_queue      = buf_queue,
+       .buf_init       = buf_init,
+       .buf_prepare    = buf_prepare,
+       .buf_cleanup    = buf_cleanup,
+       .start_streaming = start_streaming,
+       .stop_streaming = stop_streaming,
+       .wait_prepare   = vb2_ops_wait_prepare,
+       .wait_finish    = vb2_ops_wait_finish,
 };
 
 /********************************************************************************/
@@ -1187,38 +703,6 @@ static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
        vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
 }
 
-
-static int video_open(struct saa7146_dev *dev, struct file *file)
-{
-       struct saa7146_fh *fh = file->private_data;
-
-       videobuf_queue_sg_init(&fh->video_q, &video_qops,
-                           &dev->pci->dev, &dev->slock,
-                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                           V4L2_FIELD_INTERLACED,
-                           sizeof(struct saa7146_buf),
-                           file, &dev->v4l2_lock);
-
-       return 0;
-}
-
-
-static void video_close(struct saa7146_dev *dev, struct file *file)
-{
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_vv *vv = dev->vv_data;
-       struct videobuf_queue *q = &fh->video_q;
-
-       if (IS_CAPTURE_ACTIVE(fh) != 0)
-               video_end(fh, file);
-       else if (IS_OVERLAY_ACTIVE(fh) != 0)
-               saa7146_stop_preview(fh);
-
-       videobuf_stop(q);
-       /* hmm, why is this function declared void? */
-}
-
-
 static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
 {
        struct saa7146_vv *vv = dev->vv_data;
@@ -1228,59 +712,14 @@ static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
        DEB_CAP("called\n");
 
        /* only finish the buffer if we have one... */
-       if( NULL != q->curr ) {
-               saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);
-       }
+       if (q->curr)
+               saa7146_buffer_finish(dev, q, VB2_BUF_STATE_DONE);
        saa7146_buffer_next(dev,q,0);
 
        spin_unlock(&dev->slock);
 }
 
-static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
-       ssize_t ret = 0;
-
-       DEB_EE("called\n");
-
-       if ((vv->video_status & STATUS_CAPTURE) != 0) {
-               /* fixme: should we allow read() captures while streaming capture? */
-               if (vv->video_fh == fh) {
-                       DEB_S("already capturing\n");
-                       return -EBUSY;
-               }
-               DEB_S("already capturing in another open\n");
-               return -EBUSY;
-       }
-
-       ret = video_begin(fh);
-       if( 0 != ret) {
-               goto out;
-       }
-
-       ret = videobuf_read_one(&fh->video_q , data, count, ppos,
-                               file->f_flags & O_NONBLOCK);
-       if (ret != 0) {
-               video_end(fh, file);
-       } else {
-               ret = video_end(fh, file);
-       }
-out:
-       /* restart overlay if it was active before */
-       if (vv->ov_suspend != NULL) {
-               saa7146_start_preview(vv->ov_suspend);
-               vv->ov_suspend = NULL;
-       }
-
-       return ret;
-}
-
 const struct saa7146_use_ops saa7146_video_uops = {
        .init = video_init,
-       .open = video_open,
-       .release = video_close,
        .irq_done = video_irq_done,
-       .read = video_read,
 };
index 1f5d235a844171b822ae87e0682801b8082e289c..c7a54d82a55e5b79bf11f8d87c16458b9f863c86 100644 (file)
@@ -1171,10 +1171,11 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf,
                return -ERESTARTSYS;
        if (vb2_queue_is_busy(vdev->queue, file))
                goto exit;
+       vdev->queue->owner = file->private_data;
        err = vb2_read(vdev->queue, buf, count, ppos,
                       file->f_flags & O_NONBLOCK);
-       if (vdev->queue->fileio)
-               vdev->queue->owner = file->private_data;
+       if (!vdev->queue->fileio)
+               vdev->queue->owner = NULL;
 exit:
        if (lock)
                mutex_unlock(lock);
index 6bf6559b127f2df1cc70d55b7c7c8cb36d43d6e5..68f4e8b5a0abbda6667e58c60e874db9af039f23 100644 (file)
@@ -11070,7 +11070,7 @@ ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode)
                sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
                break;
        default:
-               /* Unknow sleep mode */
+               /* Unknown sleep mode */
                return -EINVAL;
        }
 
index 9807f541199659e5af26f4f153732198912157dd..3301ef75d44173692d39fca0656e489987e3ea83 100644 (file)
@@ -1585,7 +1585,7 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode)
                sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
                break;
        default:
-               /* Unknow sleep mode */
+               /* Unknown sleep mode */
                return -EINVAL;
        }
 
index 05f71d1697267ee940c3c5ee5802e611dbd7f633..02c619e51641d90dd92de291a5b3e5f65c08cda6 100644 (file)
@@ -1463,7 +1463,7 @@ err:
        return ret;
 }
 
-static int rtl2832_sdr_remove(struct platform_device *pdev)
+static void rtl2832_sdr_remove(struct platform_device *pdev)
 {
        struct rtl2832_sdr_dev *dev = platform_get_drvdata(pdev);
 
@@ -1479,8 +1479,6 @@ static int rtl2832_sdr_remove(struct platform_device *pdev)
        mutex_unlock(&dev->vb_queue_lock);
        v4l2_device_put(&dev->v4l2_dev);
        module_put(pdev->dev.parent->driver->owner);
-
-       return 0;
 }
 
 static struct platform_driver rtl2832_sdr_driver = {
@@ -1488,7 +1486,7 @@ static struct platform_driver rtl2832_sdr_driver = {
                .name   = "rtl2832_sdr",
        },
        .probe          = rtl2832_sdr_probe,
-       .remove         = rtl2832_sdr_remove,
+       .remove_new     = rtl2832_sdr_remove,
 };
 module_platform_driver(rtl2832_sdr_driver);
 
index bbabe6a2d4f476e04a055d027120bfdd9c7abccb..17f6e373c13d890b3e77758e45e23e613b79db39 100644 (file)
@@ -515,7 +515,7 @@ err:
        return ret;
 }
 
-static int zd1301_demod_remove(struct platform_device *pdev)
+static void zd1301_demod_remove(struct platform_device *pdev)
 {
        struct zd1301_demod_dev *dev = platform_get_drvdata(pdev);
 
@@ -523,8 +523,6 @@ static int zd1301_demod_remove(struct platform_device *pdev)
 
        i2c_del_adapter(&dev->adapter);
        kfree(dev);
-
-       return 0;
 }
 
 static struct platform_driver zd1301_demod_driver = {
@@ -533,7 +531,7 @@ static struct platform_driver zd1301_demod_driver = {
                .suppress_bind_attrs = true,
        },
        .probe          = zd1301_demod_probe,
-       .remove         = zd1301_demod_remove,
+       .remove_new     = zd1301_demod_remove,
 };
 module_platform_driver(zd1301_demod_driver);
 
index c3d5952ca27e6268a269e75924b762162534d039..256d55bb2b1da33070e4c04e44778278bea3b096 100644 (file)
@@ -267,16 +267,6 @@ config VIDEO_MT9M001
          This driver supports MT9M001 cameras from Micron, monochrome
          and colour models.
 
-config VIDEO_MT9M032
-       tristate "MT9M032 camera sensor support"
-       depends on I2C && VIDEO_DEV
-       select MEDIA_CONTROLLER
-       select VIDEO_V4L2_SUBDEV_API
-       select VIDEO_APTINA_PLL
-       help
-         This driver supports MT9M032 camera sensors from Aptina, monochrome
-         models only.
-
 config VIDEO_MT9M111
        tristate "mt9m111, mt9m112 and mt9m131 support"
        depends on I2C && VIDEO_DEV
@@ -296,15 +286,6 @@ config VIDEO_MT9P031
          This is a Video4Linux2 sensor driver for the Aptina
          (Micron) mt9p031 5 Mpixel camera.
 
-config VIDEO_MT9T001
-       tristate "Aptina MT9T001 support"
-       depends on I2C && VIDEO_DEV
-       select MEDIA_CONTROLLER
-       select VIDEO_V4L2_SUBDEV_API
-       help
-         This is a Video4Linux2 sensor driver for the Aptina
-         (Micron) mt0t001 3 Mpixel camera.
-
 config VIDEO_MT9T112
        tristate "Aptina MT9T111/MT9T112 support"
        depends on I2C && VIDEO_DEV
@@ -344,14 +325,6 @@ config VIDEO_MT9V111
          To compile this driver as a module, choose M here: the
          module will be called mt9v111.
 
-config VIDEO_NOON010PC30
-       tristate "Siliconfile NOON010PC30 sensor support"
-       depends on I2C && VIDEO_DEV
-       select MEDIA_CONTROLLER
-       select VIDEO_V4L2_SUBDEV_API
-       help
-         This driver supports NOON010PC30 CIF camera from Siliconfile
-
 config VIDEO_OG01A1B
        tristate "OmniVision OG01A1B sensor support"
        depends on I2C && VIDEO_DEV
@@ -462,6 +435,7 @@ config VIDEO_OV2685
        tristate "OmniVision OV2685 sensor support"
        depends on VIDEO_DEV && I2C
        select MEDIA_CONTROLLER
+       select VIDEO_V4L2_SUBDEV_API
        select V4L2_FWNODE
        help
          This is a Video4Linux2 sensor driver for the OmniVision
@@ -810,21 +784,6 @@ config VIDEO_S5K6A3
          This is a V4L2 sensor driver for Samsung S5K6A3 raw
          camera sensor.
 
-config VIDEO_S5K6AA
-       tristate "Samsung S5K6AAFX sensor support"
-       depends on I2C && VIDEO_DEV
-       select MEDIA_CONTROLLER
-       select VIDEO_V4L2_SUBDEV_API
-       help
-         This is a V4L2 sensor driver for Samsung S5K6AA(FX) 1.3M
-         camera sensor with an embedded SoC image signal processor.
-
-config VIDEO_SR030PC30
-       tristate "Siliconfile SR030PC30 sensor support"
-       depends on I2C && VIDEO_DEV
-       help
-         This driver supports SR030PC30 VGA camera from Siliconfile
-
 config VIDEO_ST_VGXY61
        tristate "ST VGXY61 sensor support"
        depends on OF && GPIOLIB && VIDEO_DEV && I2C
@@ -835,19 +794,8 @@ config VIDEO_ST_VGXY61
          This is a Video4Linux2 sensor driver for the ST VGXY61
          camera sensor.
 
-config VIDEO_VS6624
-       tristate "ST VS6624 sensor support"
-       depends on VIDEO_DEV && I2C
-       help
-         This is a Video4Linux2 sensor driver for the ST VS6624
-         camera.
-
-         To compile this driver as a module, choose M here: the
-         module will be called vs6624.
-
 source "drivers/media/i2c/ccs/Kconfig"
 source "drivers/media/i2c/et8ek8/Kconfig"
-source "drivers/media/i2c/m5mols/Kconfig"
 
 endmenu
 
@@ -1453,20 +1401,6 @@ endmenu
 menu "Video encoders"
        visible if !MEDIA_HIDE_ANCILLARY_SUBDRV
 
-config VIDEO_AD9389B
-       tristate "Analog Devices AD9389B encoder"
-       depends on VIDEO_DEV && I2C
-       select MEDIA_CONTROLLER
-       select VIDEO_V4L2_SUBDEV_API
-
-       help
-         Support for the Analog Devices AD9389B video encoder.
-
-         This is a Analog Devices HDMI transmitter.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ad9389b.
-
 config VIDEO_ADV7170
        tristate "Analog Devices ADV7170 video encoder"
        depends on VIDEO_DEV && I2C
index 4f5e9d9cee85574d05d80a49ecc1383e63de93c8..b44dacf935f44bfa8147d73c795a6c13a4324b2f 100644 (file)
@@ -4,7 +4,6 @@ msp3400-objs    :=      msp3400-driver.o msp3400-kthreads.o
 
 obj-$(CONFIG_SDR_MAX2175) += max2175.o
 obj-$(CONFIG_VIDEO_AD5820) += ad5820.o
-obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
 obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
@@ -56,21 +55,17 @@ obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
 obj-$(CONFIG_VIDEO_LM3560) += lm3560.o
 obj-$(CONFIG_VIDEO_LM3646) += lm3646.o
 obj-$(CONFIG_VIDEO_M52790) += m52790.o
-obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
 obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
 obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
 obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
 obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
-obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
 obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o
 obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
-obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
 obj-$(CONFIG_VIDEO_MT9T112) += mt9t112.o
 obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
 obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
 obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o
-obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
 obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o
 obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o
 obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o
@@ -110,7 +105,6 @@ obj-$(CONFIG_VIDEO_RJ54N1) += rj54n1cb0c.o
 obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
 obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o
 obj-$(CONFIG_VIDEO_S5K6A3) += s5k6a3.o
-obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o
 obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
 obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
 obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
@@ -119,7 +113,6 @@ obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
-obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
 obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
 obj-$(CONFIG_VIDEO_ST_VGXY61) += st-vgxy61.o
 obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
@@ -145,6 +138,5 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
 obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
 obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
-obj-$(CONFIG_VIDEO_VS6624) += vs6624.o
 obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
 obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
deleted file mode 100644 (file)
index ad17097..0000000
+++ /dev/null
@@ -1,1215 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Analog Devices AD9389B/AD9889B video encoder driver
- *
- * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-/*
- * References (c = chapter, p = page):
- * REF_01 - Analog Devices, Programming Guide, AD9889B/AD9389B,
- * HDMI Transitter, Rev. A, October 2010
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <linux/workqueue.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-dv-timings.h>
-#include <media/v4l2-ctrls.h>
-#include <media/i2c/ad9389b.h>
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "debug level (0-2)");
-
-MODULE_DESCRIPTION("Analog Devices AD9389B/AD9889B video encoder driver");
-MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
-MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>");
-MODULE_LICENSE("GPL");
-
-#define MASK_AD9389B_EDID_RDY_INT   0x04
-#define MASK_AD9389B_MSEN_INT       0x40
-#define MASK_AD9389B_HPD_INT        0x80
-
-#define MASK_AD9389B_HPD_DETECT     0x40
-#define MASK_AD9389B_MSEN_DETECT    0x20
-#define MASK_AD9389B_EDID_RDY       0x10
-
-#define EDID_MAX_RETRIES (8)
-#define EDID_DELAY 250
-#define EDID_MAX_SEGM 8
-
-/*
-**********************************************************************
-*
-*  Arrays with configuration parameters for the AD9389B
-*
-**********************************************************************
-*/
-
-struct ad9389b_state_edid {
-       /* total number of blocks */
-       u32 blocks;
-       /* Number of segments read */
-       u32 segments;
-       u8 data[EDID_MAX_SEGM * 256];
-       /* Number of EDID read retries left */
-       unsigned read_retries;
-};
-
-struct ad9389b_state {
-       struct ad9389b_platform_data pdata;
-       struct v4l2_subdev sd;
-       struct media_pad pad;
-       struct v4l2_ctrl_handler hdl;
-       int chip_revision;
-       /* Is the ad9389b powered on? */
-       bool power_on;
-       /* Did we receive hotplug and rx-sense signals? */
-       bool have_monitor;
-       /* timings from s_dv_timings */
-       struct v4l2_dv_timings dv_timings;
-       /* controls */
-       struct v4l2_ctrl *hdmi_mode_ctrl;
-       struct v4l2_ctrl *hotplug_ctrl;
-       struct v4l2_ctrl *rx_sense_ctrl;
-       struct v4l2_ctrl *have_edid0_ctrl;
-       struct v4l2_ctrl *rgb_quantization_range_ctrl;
-       struct i2c_client *edid_i2c_client;
-       struct ad9389b_state_edid edid;
-       /* Running counter of the number of detected EDIDs (for debugging) */
-       unsigned edid_detect_counter;
-       struct delayed_work edid_handler; /* work entry */
-};
-
-static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd);
-static bool ad9389b_check_edid_status(struct v4l2_subdev *sd);
-static void ad9389b_setup(struct v4l2_subdev *sd);
-static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq);
-static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
-
-static inline struct ad9389b_state *get_ad9389b_state(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct ad9389b_state, sd);
-}
-
-static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
-{
-       return &container_of(ctrl->handler, struct ad9389b_state, hdl)->sd;
-}
-
-/* ------------------------ I2C ----------------------------------------------- */
-
-static int ad9389b_rd(struct v4l2_subdev *sd, u8 reg)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-       return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int ad9389b_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret;
-       int i;
-
-       for (i = 0; i < 3; i++) {
-               ret = i2c_smbus_write_byte_data(client, reg, val);
-               if (ret == 0)
-                       return 0;
-       }
-       v4l2_err(sd, "%s: failed reg 0x%x, val 0x%x\n", __func__, reg, val);
-       return ret;
-}
-
-/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
-   and then the value-mask (to be OR-ed). */
-static inline void ad9389b_wr_and_or(struct v4l2_subdev *sd, u8 reg,
-                                    u8 clr_mask, u8 val_mask)
-{
-       ad9389b_wr(sd, reg, (ad9389b_rd(sd, reg) & clr_mask) | val_mask);
-}
-
-static void ad9389b_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-       int i;
-
-       v4l2_dbg(1, debug, sd, "%s:\n", __func__);
-
-       for (i = 0; i < len; i++)
-               buf[i] = i2c_smbus_read_byte_data(state->edid_i2c_client, i);
-}
-
-static inline bool ad9389b_have_hotplug(struct v4l2_subdev *sd)
-{
-       return ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT;
-}
-
-static inline bool ad9389b_have_rx_sense(struct v4l2_subdev *sd)
-{
-       return ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT;
-}
-
-static void ad9389b_csc_conversion_mode(struct v4l2_subdev *sd, u8 mode)
-{
-       ad9389b_wr_and_or(sd, 0x17, 0xe7, (mode & 0x3)<<3);
-       ad9389b_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5);
-}
-
-static void ad9389b_csc_coeff(struct v4l2_subdev *sd,
-                             u16 A1, u16 A2, u16 A3, u16 A4,
-                             u16 B1, u16 B2, u16 B3, u16 B4,
-                             u16 C1, u16 C2, u16 C3, u16 C4)
-{
-       /* A */
-       ad9389b_wr_and_or(sd, 0x18, 0xe0, A1>>8);
-       ad9389b_wr(sd, 0x19, A1);
-       ad9389b_wr_and_or(sd, 0x1A, 0xe0, A2>>8);
-       ad9389b_wr(sd, 0x1B, A2);
-       ad9389b_wr_and_or(sd, 0x1c, 0xe0, A3>>8);
-       ad9389b_wr(sd, 0x1d, A3);
-       ad9389b_wr_and_or(sd, 0x1e, 0xe0, A4>>8);
-       ad9389b_wr(sd, 0x1f, A4);
-
-       /* B */
-       ad9389b_wr_and_or(sd, 0x20, 0xe0, B1>>8);
-       ad9389b_wr(sd, 0x21, B1);
-       ad9389b_wr_and_or(sd, 0x22, 0xe0, B2>>8);
-       ad9389b_wr(sd, 0x23, B2);
-       ad9389b_wr_and_or(sd, 0x24, 0xe0, B3>>8);
-       ad9389b_wr(sd, 0x25, B3);
-       ad9389b_wr_and_or(sd, 0x26, 0xe0, B4>>8);
-       ad9389b_wr(sd, 0x27, B4);
-
-       /* C */
-       ad9389b_wr_and_or(sd, 0x28, 0xe0, C1>>8);
-       ad9389b_wr(sd, 0x29, C1);
-       ad9389b_wr_and_or(sd, 0x2A, 0xe0, C2>>8);
-       ad9389b_wr(sd, 0x2B, C2);
-       ad9389b_wr_and_or(sd, 0x2C, 0xe0, C3>>8);
-       ad9389b_wr(sd, 0x2D, C3);
-       ad9389b_wr_and_or(sd, 0x2E, 0xe0, C4>>8);
-       ad9389b_wr(sd, 0x2F, C4);
-}
-
-static void ad9389b_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable)
-{
-       if (enable) {
-               u8 csc_mode = 0;
-
-               ad9389b_csc_conversion_mode(sd, csc_mode);
-               ad9389b_csc_coeff(sd,
-                                 4096-564, 0, 0, 256,
-                                 0, 4096-564, 0, 256,
-                                 0, 0, 4096-564, 256);
-               /* enable CSC */
-               ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x1);
-               /* AVI infoframe: Limited range RGB (16-235) */
-               ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x02);
-       } else {
-               /* disable CSC */
-               ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x0);
-               /* AVI infoframe: Full range RGB (0-255) */
-               ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x04);
-       }
-}
-
-static void ad9389b_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-
-       if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
-               /* CE format, not IT  */
-               ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x00);
-       } else {
-               /* IT format */
-               ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x40);
-       }
-}
-
-static int ad9389b_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-
-       switch (ctrl->val) {
-       case V4L2_DV_RGB_RANGE_AUTO:
-               /* automatic */
-               if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
-                       /* CE format, RGB limited range (16-235) */
-                       ad9389b_csc_rgb_full2limit(sd, true);
-               } else {
-                       /* not CE format, RGB full range (0-255) */
-                       ad9389b_csc_rgb_full2limit(sd, false);
-               }
-               break;
-       case V4L2_DV_RGB_RANGE_LIMITED:
-               /* RGB limited range (16-235) */
-               ad9389b_csc_rgb_full2limit(sd, true);
-               break;
-       case V4L2_DV_RGB_RANGE_FULL:
-               /* RGB full range (0-255) */
-               ad9389b_csc_rgb_full2limit(sd, false);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void ad9389b_set_manual_pll_gear(struct v4l2_subdev *sd, u32 pixelclock)
-{
-       u8 gear;
-
-       /* Workaround for TMDS PLL problem
-        * The TMDS PLL in AD9389b change gear when the chip is heated above a
-        * certain temperature. The output is disabled when the PLL change gear
-        * so the monitor has to lock on the signal again. A workaround for
-        * this is to use the manual PLL gears. This is a solution from Analog
-        * Devices that is not documented in the datasheets.
-        * 0x98 [7] = enable manual gearing. 0x98 [6:4] = gear
-        *
-        * The pixel frequency ranges are based on readout of the gear the
-        * automatic gearing selects for different pixel clocks
-        * (read from 0x9e [3:1]).
-        */
-
-       if (pixelclock > 140000000)
-               gear = 0xc0; /* 4th gear */
-       else if (pixelclock > 117000000)
-               gear = 0xb0; /* 3rd gear */
-       else if (pixelclock > 87000000)
-               gear = 0xa0; /* 2nd gear */
-       else if (pixelclock > 60000000)
-               gear = 0x90; /* 1st gear */
-       else
-               gear = 0x80; /* 0th gear */
-
-       ad9389b_wr_and_or(sd, 0x98, 0x0f, gear);
-}
-
-/* ------------------------------ CTRL OPS ------------------------------ */
-
-static int ad9389b_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct v4l2_subdev *sd = to_sd(ctrl);
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-
-       v4l2_dbg(1, debug, sd,
-                "%s: ctrl id: %d, ctrl->val %d\n", __func__, ctrl->id, ctrl->val);
-
-       if (state->hdmi_mode_ctrl == ctrl) {
-               /* Set HDMI or DVI-D */
-               ad9389b_wr_and_or(sd, 0xaf, 0xfd,
-                                 ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00);
-               return 0;
-       }
-       if (state->rgb_quantization_range_ctrl == ctrl)
-               return ad9389b_set_rgb_quantization_mode(sd, ctrl);
-       return -EINVAL;
-}
-
-static const struct v4l2_ctrl_ops ad9389b_ctrl_ops = {
-       .s_ctrl = ad9389b_s_ctrl,
-};
-
-/* ---------------------------- CORE OPS ------------------------------------------- */
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
-{
-       reg->val = ad9389b_rd(sd, reg->reg & 0xff);
-       reg->size = 1;
-       return 0;
-}
-
-static int ad9389b_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
-{
-       ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff);
-       return 0;
-}
-#endif
-
-static int ad9389b_log_status(struct v4l2_subdev *sd)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-       struct ad9389b_state_edid *edid = &state->edid;
-
-       static const char * const states[] = {
-               "in reset",
-               "reading EDID",
-               "idle",
-               "initializing HDCP",
-               "HDCP enabled",
-               "initializing HDCP repeater",
-               "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
-       };
-       static const char * const errors[] = {
-               "no error",
-               "bad receiver BKSV",
-               "Ri mismatch",
-               "Pj mismatch",
-               "i2c error",
-               "timed out",
-               "max repeater cascade exceeded",
-               "hash check failed",
-               "too many devices",
-               "9", "A", "B", "C", "D", "E", "F"
-       };
-
-       u8 manual_gear;
-
-       v4l2_info(sd, "chip revision %d\n", state->chip_revision);
-       v4l2_info(sd, "power %s\n", state->power_on ? "on" : "off");
-       v4l2_info(sd, "%s hotplug, %s Rx Sense, %s EDID (%d block(s))\n",
-                 (ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT) ?
-                 "detected" : "no",
-                 (ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT) ?
-                 "detected" : "no",
-                 edid->segments ? "found" : "no", edid->blocks);
-       v4l2_info(sd, "%s output %s\n",
-                 (ad9389b_rd(sd, 0xaf) & 0x02) ?
-                 "HDMI" : "DVI-D",
-                 (ad9389b_rd(sd, 0xa1) & 0x3c) ?
-                 "disabled" : "enabled");
-       v4l2_info(sd, "ad9389b: %s\n", (ad9389b_rd(sd, 0xb8) & 0x40) ?
-                 "encrypted" : "no encryption");
-       v4l2_info(sd, "state: %s, error: %s, detect count: %u, msk/irq: %02x/%02x\n",
-                 states[ad9389b_rd(sd, 0xc8) & 0xf],
-                 errors[ad9389b_rd(sd, 0xc8) >> 4],
-                 state->edid_detect_counter,
-                 ad9389b_rd(sd, 0x94), ad9389b_rd(sd, 0x96));
-       manual_gear = ad9389b_rd(sd, 0x98) & 0x80;
-       v4l2_info(sd, "ad9389b: RGB quantization: %s range\n",
-                 ad9389b_rd(sd, 0x3b) & 0x01 ? "limited" : "full");
-       v4l2_info(sd, "ad9389b: %s gear %d\n",
-                 manual_gear ? "manual" : "automatic",
-                 manual_gear ? ((ad9389b_rd(sd, 0x98) & 0x70) >> 4) :
-                 ((ad9389b_rd(sd, 0x9e) & 0x0e) >> 1));
-       if (ad9389b_rd(sd, 0xaf) & 0x02) {
-               /* HDMI only */
-               u8 manual_cts = ad9389b_rd(sd, 0x0a) & 0x80;
-               u32 N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 |
-                       ad9389b_rd(sd, 0x02) << 8 |
-                       ad9389b_rd(sd, 0x03);
-               u8 vic_detect = ad9389b_rd(sd, 0x3e) >> 2;
-               u8 vic_sent = ad9389b_rd(sd, 0x3d) & 0x3f;
-               u32 CTS;
-
-               if (manual_cts)
-                       CTS = (ad9389b_rd(sd, 0x07) & 0xf) << 16 |
-                             ad9389b_rd(sd, 0x08) << 8 |
-                             ad9389b_rd(sd, 0x09);
-               else
-                       CTS = (ad9389b_rd(sd, 0x04) & 0xf) << 16 |
-                             ad9389b_rd(sd, 0x05) << 8 |
-                             ad9389b_rd(sd, 0x06);
-               N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 |
-                   ad9389b_rd(sd, 0x02) << 8 |
-                   ad9389b_rd(sd, 0x03);
-
-               v4l2_info(sd, "ad9389b: CTS %s mode: N %d, CTS %d\n",
-                         manual_cts ? "manual" : "automatic", N, CTS);
-
-               v4l2_info(sd, "ad9389b: VIC: detected %d, sent %d\n",
-                         vic_detect, vic_sent);
-       }
-       if (state->dv_timings.type == V4L2_DV_BT_656_1120)
-               v4l2_print_dv_timings(sd->name, "timings: ",
-                               &state->dv_timings, false);
-       else
-               v4l2_info(sd, "no timings set\n");
-       return 0;
-}
-
-/* Power up/down ad9389b */
-static int ad9389b_s_power(struct v4l2_subdev *sd, int on)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-       struct ad9389b_platform_data *pdata = &state->pdata;
-       const int retries = 20;
-       int i;
-
-       v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off");
-
-       state->power_on = on;
-
-       if (!on) {
-               /* Power down */
-               ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40);
-               return true;
-       }
-
-       /* Power up */
-       /* The ad9389b does not always come up immediately.
-          Retry multiple times. */
-       for (i = 0; i < retries; i++) {
-               ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x0);
-               if ((ad9389b_rd(sd, 0x41) & 0x40) == 0)
-                       break;
-               ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40);
-               msleep(10);
-       }
-       if (i == retries) {
-               v4l2_dbg(1, debug, sd, "failed to powerup the ad9389b\n");
-               ad9389b_s_power(sd, 0);
-               return false;
-       }
-       if (i > 1)
-               v4l2_dbg(1, debug, sd,
-                        "needed %d retries to powerup the ad9389b\n", i);
-
-       /* Select chip: AD9389B */
-       ad9389b_wr_and_or(sd, 0xba, 0xef, 0x10);
-
-       /* Reserved registers that must be set according to REF_01 p. 11*/
-       ad9389b_wr_and_or(sd, 0x98, 0xf0, 0x07);
-       ad9389b_wr(sd, 0x9c, 0x38);
-       ad9389b_wr_and_or(sd, 0x9d, 0xfc, 0x01);
-
-       /* Differential output drive strength */
-       if (pdata->diff_data_drive_strength > 0)
-               ad9389b_wr(sd, 0xa2, pdata->diff_data_drive_strength);
-       else
-               ad9389b_wr(sd, 0xa2, 0x87);
-
-       if (pdata->diff_clk_drive_strength > 0)
-               ad9389b_wr(sd, 0xa3, pdata->diff_clk_drive_strength);
-       else
-               ad9389b_wr(sd, 0xa3, 0x87);
-
-       ad9389b_wr(sd, 0x0a, 0x01);
-       ad9389b_wr(sd, 0xbb, 0xff);
-
-       /* Set number of attempts to read the EDID */
-       ad9389b_wr(sd, 0xc9, 0xf);
-       return true;
-}
-
-/* Enable interrupts */
-static void ad9389b_set_isr(struct v4l2_subdev *sd, bool enable)
-{
-       u8 irqs = MASK_AD9389B_HPD_INT | MASK_AD9389B_MSEN_INT;
-       u8 irqs_rd;
-       int retries = 100;
-
-       /* The datasheet says that the EDID ready interrupt should be
-          disabled if there is no hotplug. */
-       if (!enable)
-               irqs = 0;
-       else if (ad9389b_have_hotplug(sd))
-               irqs |= MASK_AD9389B_EDID_RDY_INT;
-
-       /*
-        * This i2c write can fail (approx. 1 in 1000 writes). But it
-        * is essential that this register is correct, so retry it
-        * multiple times.
-        *
-        * Note that the i2c write does not report an error, but the readback
-        * clearly shows the wrong value.
-        */
-       do {
-               ad9389b_wr(sd, 0x94, irqs);
-               irqs_rd = ad9389b_rd(sd, 0x94);
-       } while (retries-- && irqs_rd != irqs);
-
-       if (irqs_rd != irqs)
-               v4l2_err(sd, "Could not set interrupts: hw failure?\n");
-}
-
-/* Interrupt handler */
-static int ad9389b_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
-{
-       u8 irq_status;
-
-       /* disable interrupts to prevent a race condition */
-       ad9389b_set_isr(sd, false);
-       irq_status = ad9389b_rd(sd, 0x96);
-       /* clear detected interrupts */
-       ad9389b_wr(sd, 0x96, irq_status);
-       /* enable interrupts */
-       ad9389b_set_isr(sd, true);
-
-       v4l2_dbg(1, debug, sd, "%s: irq_status 0x%x\n", __func__, irq_status);
-
-       if (irq_status & (MASK_AD9389B_HPD_INT))
-               ad9389b_check_monitor_present_status(sd);
-       if (irq_status & MASK_AD9389B_EDID_RDY_INT)
-               ad9389b_check_edid_status(sd);
-
-       *handled = true;
-       return 0;
-}
-
-static const struct v4l2_subdev_core_ops ad9389b_core_ops = {
-       .log_status = ad9389b_log_status,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .g_register = ad9389b_g_register,
-       .s_register = ad9389b_s_register,
-#endif
-       .s_power = ad9389b_s_power,
-       .interrupt_service_routine = ad9389b_isr,
-};
-
-/* ------------------------------ VIDEO OPS ------------------------------ */
-
-/* Enable/disable ad9389b output */
-static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable)
-{
-       v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
-
-       ad9389b_wr_and_or(sd, 0xa1, ~0x3c, (enable ? 0 : 0x3c));
-       if (enable) {
-               ad9389b_check_monitor_present_status(sd);
-       } else {
-               ad9389b_s_power(sd, 0);
-       }
-       return 0;
-}
-
-static const struct v4l2_dv_timings_cap ad9389b_timings_cap = {
-       .type = V4L2_DV_BT_656_1120,
-       /* keep this initialization for compatibility with GCC < 4.4.6 */
-       .reserved = { 0 },
-       V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 25000000, 170000000,
-               V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
-                       V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
-               V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
-               V4L2_DV_BT_CAP_CUSTOM)
-};
-
-static int ad9389b_s_dv_timings(struct v4l2_subdev *sd,
-                               struct v4l2_dv_timings *timings)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-
-       v4l2_dbg(1, debug, sd, "%s:\n", __func__);
-
-       /* quick sanity check */
-       if (!v4l2_valid_dv_timings(timings, &ad9389b_timings_cap, NULL, NULL))
-               return -EINVAL;
-
-       /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
-          if the format is one of the CEA or DMT timings. */
-       v4l2_find_dv_timings_cap(timings, &ad9389b_timings_cap, 0, NULL, NULL);
-
-       timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS;
-
-       /* save timings */
-       state->dv_timings = *timings;
-
-       /* update quantization range based on new dv_timings */
-       ad9389b_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl);
-
-       /* update PLL gear based on new dv_timings */
-       if (state->pdata.tmds_pll_gear == AD9389B_TMDS_PLL_GEAR_SEMI_AUTOMATIC)
-               ad9389b_set_manual_pll_gear(sd, (u32)timings->bt.pixelclock);
-
-       /* update AVI infoframe */
-       ad9389b_set_IT_content_AVI_InfoFrame(sd);
-
-       return 0;
-}
-
-static int ad9389b_g_dv_timings(struct v4l2_subdev *sd,
-                               struct v4l2_dv_timings *timings)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-
-       v4l2_dbg(1, debug, sd, "%s:\n", __func__);
-
-       if (!timings)
-               return -EINVAL;
-
-       *timings = state->dv_timings;
-
-       return 0;
-}
-
-static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd,
-                                  struct v4l2_enum_dv_timings *timings)
-{
-       if (timings->pad != 0)
-               return -EINVAL;
-
-       return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap,
-                       NULL, NULL);
-}
-
-static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd,
-                                 struct v4l2_dv_timings_cap *cap)
-{
-       if (cap->pad != 0)
-               return -EINVAL;
-
-       *cap = ad9389b_timings_cap;
-       return 0;
-}
-
-static const struct v4l2_subdev_video_ops ad9389b_video_ops = {
-       .s_stream = ad9389b_s_stream,
-       .s_dv_timings = ad9389b_s_dv_timings,
-       .g_dv_timings = ad9389b_g_dv_timings,
-};
-
-/* ------------------------------ PAD OPS ------------------------------ */
-
-static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-
-       if (edid->pad != 0)
-               return -EINVAL;
-       if (edid->blocks == 0 || edid->blocks > 256)
-               return -EINVAL;
-       if (!state->edid.segments) {
-               v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
-               return -ENODATA;
-       }
-       if (edid->start_block >= state->edid.segments * 2)
-               return -E2BIG;
-       if (edid->blocks + edid->start_block >= state->edid.segments * 2)
-               edid->blocks = state->edid.segments * 2 - edid->start_block;
-       memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
-              128 * edid->blocks);
-       return 0;
-}
-
-static const struct v4l2_subdev_pad_ops ad9389b_pad_ops = {
-       .get_edid = ad9389b_get_edid,
-       .enum_dv_timings = ad9389b_enum_dv_timings,
-       .dv_timings_cap = ad9389b_dv_timings_cap,
-};
-
-/* ------------------------------ AUDIO OPS ------------------------------ */
-
-static int ad9389b_s_audio_stream(struct v4l2_subdev *sd, int enable)
-{
-       v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
-
-       if (enable)
-               ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x80);
-       else
-               ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x40);
-
-       return 0;
-}
-
-static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
-{
-       u32 N;
-
-       switch (freq) {
-       case 32000:  N = 4096;  break;
-       case 44100:  N = 6272;  break;
-       case 48000:  N = 6144;  break;
-       case 88200:  N = 12544; break;
-       case 96000:  N = 12288; break;
-       case 176400: N = 25088; break;
-       case 192000: N = 24576; break;
-       default:
-            return -EINVAL;
-       }
-
-       /* Set N (used with CTS to regenerate the audio clock) */
-       ad9389b_wr(sd, 0x01, (N >> 16) & 0xf);
-       ad9389b_wr(sd, 0x02, (N >> 8) & 0xff);
-       ad9389b_wr(sd, 0x03, N & 0xff);
-
-       return 0;
-}
-
-static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq)
-{
-       u32 i2s_sf;
-
-       switch (freq) {
-       case 32000:  i2s_sf = 0x30; break;
-       case 44100:  i2s_sf = 0x00; break;
-       case 48000:  i2s_sf = 0x20; break;
-       case 88200:  i2s_sf = 0x80; break;
-       case 96000:  i2s_sf = 0xa0; break;
-       case 176400: i2s_sf = 0xc0; break;
-       case 192000: i2s_sf = 0xe0; break;
-       default:
-            return -EINVAL;
-       }
-
-       /* Set sampling frequency for I2S audio to 48 kHz */
-       ad9389b_wr_and_or(sd, 0x15, 0xf, i2s_sf);
-
-       return 0;
-}
-
-static int ad9389b_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config)
-{
-       /* TODO based on input/output/config */
-       /* TODO See datasheet "Programmers guide" p. 39-40 */
-
-       /* Only 2 channels in use for application */
-       ad9389b_wr_and_or(sd, 0x50, 0x1f, 0x20);
-       /* Speaker mapping */
-       ad9389b_wr(sd, 0x51, 0x00);
-
-       /* TODO Where should this be placed? */
-       /* 16 bit audio word length */
-       ad9389b_wr_and_or(sd, 0x14, 0xf0, 0x02);
-
-       return 0;
-}
-
-static const struct v4l2_subdev_audio_ops ad9389b_audio_ops = {
-       .s_stream = ad9389b_s_audio_stream,
-       .s_clock_freq = ad9389b_s_clock_freq,
-       .s_i2s_clock_freq = ad9389b_s_i2s_clock_freq,
-       .s_routing = ad9389b_s_routing,
-};
-
-/* --------------------- SUBDEV OPS --------------------------------------- */
-
-static const struct v4l2_subdev_ops ad9389b_ops = {
-       .core  = &ad9389b_core_ops,
-       .video = &ad9389b_video_ops,
-       .audio = &ad9389b_audio_ops,
-       .pad = &ad9389b_pad_ops,
-};
-
-/* ----------------------------------------------------------------------- */
-static void ad9389b_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd,
-                                 int segment, u8 *buf)
-{
-       int i, j;
-
-       if (debug < lvl)
-               return;
-
-       v4l2_dbg(lvl, debug, sd, "edid segment %d\n", segment);
-       for (i = 0; i < 256; i += 16) {
-               u8 b[128];
-               u8 *bp = b;
-
-               if (i == 128)
-                       v4l2_dbg(lvl, debug, sd, "\n");
-               for (j = i; j < i + 16; j++) {
-                       sprintf(bp, "0x%02x, ", buf[j]);
-                       bp += 6;
-               }
-               bp[0] = '\0';
-               v4l2_dbg(lvl, debug, sd, "%s\n", b);
-       }
-}
-
-static void ad9389b_edid_handler(struct work_struct *work)
-{
-       struct delayed_work *dwork = to_delayed_work(work);
-       struct ad9389b_state *state =
-               container_of(dwork, struct ad9389b_state, edid_handler);
-       struct v4l2_subdev *sd = &state->sd;
-       struct ad9389b_edid_detect ed;
-
-       v4l2_dbg(1, debug, sd, "%s:\n", __func__);
-
-       if (ad9389b_check_edid_status(sd)) {
-               /* Return if we received the EDID. */
-               return;
-       }
-
-       if (ad9389b_have_hotplug(sd)) {
-               /* We must retry reading the EDID several times, it is possible
-                * that initially the EDID couldn't be read due to i2c errors
-                * (DVI connectors are particularly prone to this problem). */
-               if (state->edid.read_retries) {
-                       state->edid.read_retries--;
-                       v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__);
-                       ad9389b_s_power(sd, false);
-                       ad9389b_s_power(sd, true);
-                       schedule_delayed_work(&state->edid_handler, EDID_DELAY);
-                       return;
-               }
-       }
-
-       /* We failed to read the EDID, so send an event for this. */
-       ed.present = false;
-       ed.segment = ad9389b_rd(sd, 0xc4);
-       v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed);
-       v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__);
-}
-
-static void ad9389b_audio_setup(struct v4l2_subdev *sd)
-{
-       v4l2_dbg(1, debug, sd, "%s\n", __func__);
-
-       ad9389b_s_i2s_clock_freq(sd, 48000);
-       ad9389b_s_clock_freq(sd, 48000);
-       ad9389b_s_routing(sd, 0, 0, 0);
-}
-
-/* Initial setup of AD9389b */
-
-/* Configure hdmi transmitter. */
-static void ad9389b_setup(struct v4l2_subdev *sd)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-
-       v4l2_dbg(1, debug, sd, "%s\n", __func__);
-
-       /* Input format: RGB 4:4:4 */
-       ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0);
-       /* Output format: RGB 4:4:4 */
-       ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0);
-       /* 1st order interpolation 4:2:2 -> 4:4:4 up conversion,
-          Aspect ratio: 16:9 */
-       ad9389b_wr_and_or(sd, 0x17, 0xf9, 0x06);
-       /* Output format: RGB 4:4:4, Active Format Information is valid. */
-       ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08);
-       /* Underscanned */
-       ad9389b_wr_and_or(sd, 0x46, 0x3f, 0x80);
-       /* Setup video format */
-       ad9389b_wr(sd, 0x3c, 0x0);
-       /* Active format aspect ratio: same as picure. */
-       ad9389b_wr(sd, 0x47, 0x80);
-       /* No encryption */
-       ad9389b_wr_and_or(sd, 0xaf, 0xef, 0x0);
-       /* Positive clk edge capture for input video clock */
-       ad9389b_wr_and_or(sd, 0xba, 0x1f, 0x60);
-
-       ad9389b_audio_setup(sd);
-
-       v4l2_ctrl_handler_setup(&state->hdl);
-
-       ad9389b_set_IT_content_AVI_InfoFrame(sd);
-}
-
-static void ad9389b_notify_monitor_detect(struct v4l2_subdev *sd)
-{
-       struct ad9389b_monitor_detect mdt;
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-
-       mdt.present = state->have_monitor;
-       v4l2_subdev_notify(sd, AD9389B_MONITOR_DETECT, (void *)&mdt);
-}
-
-static void ad9389b_update_monitor_present_status(struct v4l2_subdev *sd)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-       /* read hotplug and rx-sense state */
-       u8 status = ad9389b_rd(sd, 0x42);
-
-       v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n",
-                __func__,
-                status,
-                status & MASK_AD9389B_HPD_DETECT ? ", hotplug" : "",
-                status & MASK_AD9389B_MSEN_DETECT ? ", rx-sense" : "");
-
-       if (status & MASK_AD9389B_HPD_DETECT) {
-               v4l2_dbg(1, debug, sd, "%s: hotplug detected\n", __func__);
-               state->have_monitor = true;
-               if (!ad9389b_s_power(sd, true)) {
-                       v4l2_dbg(1, debug, sd,
-                                "%s: monitor detected, powerup failed\n", __func__);
-                       return;
-               }
-               ad9389b_setup(sd);
-               ad9389b_notify_monitor_detect(sd);
-               state->edid.read_retries = EDID_MAX_RETRIES;
-               schedule_delayed_work(&state->edid_handler, EDID_DELAY);
-       } else if (!(status & MASK_AD9389B_HPD_DETECT)) {
-               v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__);
-               state->have_monitor = false;
-               ad9389b_notify_monitor_detect(sd);
-               ad9389b_s_power(sd, false);
-               memset(&state->edid, 0, sizeof(struct ad9389b_state_edid));
-       }
-
-       /* update read only ctrls */
-       v4l2_ctrl_s_ctrl(state->hotplug_ctrl, ad9389b_have_hotplug(sd) ? 0x1 : 0x0);
-       v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, ad9389b_have_rx_sense(sd) ? 0x1 : 0x0);
-       v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
-
-       /* update with setting from ctrls */
-       ad9389b_s_ctrl(state->rgb_quantization_range_ctrl);
-       ad9389b_s_ctrl(state->hdmi_mode_ctrl);
-}
-
-static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-       int retry = 0;
-
-       ad9389b_update_monitor_present_status(sd);
-
-       /*
-        * Rapid toggling of the hotplug may leave the chip powered off,
-        * even if we think it is on. In that case reset and power up again.
-        */
-       while (state->power_on && (ad9389b_rd(sd, 0x41) & 0x40)) {
-               if (++retry > 5) {
-                       v4l2_err(sd, "retried %d times, give up\n", retry);
-                       return;
-               }
-               v4l2_dbg(1, debug, sd, "%s: reset and re-check status (%d)\n", __func__, retry);
-               ad9389b_notify_monitor_detect(sd);
-               cancel_delayed_work_sync(&state->edid_handler);
-               memset(&state->edid, 0, sizeof(struct ad9389b_state_edid));
-               ad9389b_s_power(sd, false);
-               ad9389b_update_monitor_present_status(sd);
-       }
-}
-
-static bool edid_block_verify_crc(u8 *edid_block)
-{
-       u8 sum = 0;
-       int i;
-
-       for (i = 0; i < 128; i++)
-               sum += edid_block[i];
-       return sum == 0;
-}
-
-static bool edid_verify_crc(struct v4l2_subdev *sd, u32 segment)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-       u32 blocks = state->edid.blocks;
-       u8 *data = state->edid.data;
-
-       if (edid_block_verify_crc(&data[segment * 256])) {
-               if ((segment + 1) * 2 <= blocks)
-                       return edid_block_verify_crc(&data[segment * 256 + 128]);
-               return true;
-       }
-       return false;
-}
-
-static bool edid_verify_header(struct v4l2_subdev *sd, u32 segment)
-{
-       static const u8 hdmi_header[] = {
-               0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
-       };
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-       u8 *data = state->edid.data;
-       int i;
-
-       if (segment)
-               return true;
-
-       for (i = 0; i < ARRAY_SIZE(hdmi_header); i++)
-               if (data[i] != hdmi_header[i])
-                       return false;
-
-       return true;
-}
-
-static bool ad9389b_check_edid_status(struct v4l2_subdev *sd)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-       struct ad9389b_edid_detect ed;
-       int segment;
-       u8 edidRdy = ad9389b_rd(sd, 0xc5);
-
-       v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n",
-                __func__, EDID_MAX_RETRIES - state->edid.read_retries);
-
-       if (!(edidRdy & MASK_AD9389B_EDID_RDY))
-               return false;
-
-       segment = ad9389b_rd(sd, 0xc4);
-       if (segment >= EDID_MAX_SEGM) {
-               v4l2_err(sd, "edid segment number too big\n");
-               return false;
-       }
-       v4l2_dbg(1, debug, sd, "%s: got segment %d\n", __func__, segment);
-       ad9389b_edid_rd(sd, 256, &state->edid.data[segment * 256]);
-       ad9389b_dbg_dump_edid(2, debug, sd, segment,
-                             &state->edid.data[segment * 256]);
-       if (segment == 0) {
-               state->edid.blocks = state->edid.data[0x7e] + 1;
-               v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n",
-                        __func__, state->edid.blocks);
-       }
-       if (!edid_verify_crc(sd, segment) ||
-           !edid_verify_header(sd, segment)) {
-               /* edid crc error, force reread of edid segment */
-               v4l2_err(sd, "%s: edid crc or header error\n", __func__);
-               ad9389b_s_power(sd, false);
-               ad9389b_s_power(sd, true);
-               return false;
-       }
-       /* one more segment read ok */
-       state->edid.segments = segment + 1;
-       if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) {
-               /* Request next EDID segment */
-               v4l2_dbg(1, debug, sd, "%s: request segment %d\n",
-                        __func__, state->edid.segments);
-               ad9389b_wr(sd, 0xc9, 0xf);
-               ad9389b_wr(sd, 0xc4, state->edid.segments);
-               state->edid.read_retries = EDID_MAX_RETRIES;
-               schedule_delayed_work(&state->edid_handler, EDID_DELAY);
-               return false;
-       }
-
-       /* report when we have all segments but report only for segment 0 */
-       ed.present = true;
-       ed.segment = 0;
-       v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed);
-       state->edid_detect_counter++;
-       v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
-       return ed.present;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static void ad9389b_init_setup(struct v4l2_subdev *sd)
-{
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-       struct ad9389b_state_edid *edid = &state->edid;
-
-       v4l2_dbg(1, debug, sd, "%s\n", __func__);
-
-       /* clear all interrupts */
-       ad9389b_wr(sd, 0x96, 0xff);
-
-       memset(edid, 0, sizeof(struct ad9389b_state_edid));
-       state->have_monitor = false;
-       ad9389b_set_isr(sd, false);
-}
-
-static int ad9389b_probe(struct i2c_client *client)
-{
-       const struct v4l2_dv_timings dv1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
-       struct ad9389b_state *state;
-       struct ad9389b_platform_data *pdata = client->dev.platform_data;
-       struct v4l2_ctrl_handler *hdl;
-       struct v4l2_subdev *sd;
-       int err = -EIO;
-
-       /* Check if the adapter supports the needed features */
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-               return -EIO;
-
-       v4l_dbg(1, debug, client, "detecting ad9389b client on address 0x%x\n",
-               client->addr << 1);
-
-       state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
-       if (!state)
-               return -ENOMEM;
-
-       /* Platform data */
-       if (pdata == NULL) {
-               v4l_err(client, "No platform data!\n");
-               return -ENODEV;
-       }
-       memcpy(&state->pdata, pdata, sizeof(state->pdata));
-
-       sd = &state->sd;
-       v4l2_i2c_subdev_init(sd, client, &ad9389b_ops);
-       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-
-       hdl = &state->hdl;
-       v4l2_ctrl_handler_init(hdl, 5);
-
-       state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
-                       V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
-                       0, V4L2_DV_TX_MODE_DVI_D);
-       state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL,
-                       V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0);
-       state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL,
-                       V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0);
-       state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL,
-                       V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0);
-       state->rgb_quantization_range_ctrl =
-               v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
-                       V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
-                       0, V4L2_DV_RGB_RANGE_AUTO);
-       sd->ctrl_handler = hdl;
-       if (hdl->error) {
-               err = hdl->error;
-
-               goto err_hdl;
-       }
-       state->pad.flags = MEDIA_PAD_FL_SINK;
-       sd->entity.function = MEDIA_ENT_F_DV_ENCODER;
-       err = media_entity_pads_init(&sd->entity, 1, &state->pad);
-       if (err)
-               goto err_hdl;
-
-       state->chip_revision = ad9389b_rd(sd, 0x0);
-       if (state->chip_revision != 2) {
-               v4l2_err(sd, "chip_revision %d != 2\n", state->chip_revision);
-               err = -EIO;
-               goto err_entity;
-       }
-       v4l2_dbg(1, debug, sd, "reg 0x41 0x%x, chip version (reg 0x00) 0x%x\n",
-                ad9389b_rd(sd, 0x41), state->chip_revision);
-
-       state->edid_i2c_client = i2c_new_dummy_device(client->adapter, (0x7e >> 1));
-       if (IS_ERR(state->edid_i2c_client)) {
-               v4l2_err(sd, "failed to register edid i2c client\n");
-               err = PTR_ERR(state->edid_i2c_client);
-               goto err_entity;
-       }
-
-       INIT_DELAYED_WORK(&state->edid_handler, ad9389b_edid_handler);
-       state->dv_timings = dv1080p60;
-
-       ad9389b_init_setup(sd);
-       ad9389b_set_isr(sd, true);
-
-       v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
-                 client->addr << 1, client->adapter->name);
-       return 0;
-
-err_entity:
-       media_entity_cleanup(&sd->entity);
-err_hdl:
-       v4l2_ctrl_handler_free(&state->hdl);
-       return err;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static void ad9389b_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-       struct ad9389b_state *state = get_ad9389b_state(sd);
-
-       state->chip_revision = -1;
-
-       v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,
-                client->addr << 1, client->adapter->name);
-
-       ad9389b_s_stream(sd, false);
-       ad9389b_s_audio_stream(sd, false);
-       ad9389b_init_setup(sd);
-       cancel_delayed_work_sync(&state->edid_handler);
-       i2c_unregister_device(state->edid_i2c_client);
-       v4l2_device_unregister_subdev(sd);
-       media_entity_cleanup(&sd->entity);
-       v4l2_ctrl_handler_free(sd->ctrl_handler);
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const struct i2c_device_id ad9389b_id[] = {
-       { "ad9389b", 0 },
-       { "ad9889b", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, ad9389b_id);
-
-static struct i2c_driver ad9389b_driver = {
-       .driver = {
-               .name = "ad9389b",
-       },
-       .probe_new = ad9389b_probe,
-       .remove = ad9389b_remove,
-       .id_table = ad9389b_id,
-};
-
-module_i2c_driver(ad9389b_driver);
index 52fa7bd75660515b939c7d98dd72cef2c883018a..400d71c2745cdeeb780a2084b5d712e9994c7a7b 100644 (file)
@@ -176,9 +176,9 @@ static int adv748x_hdmi_set_video_timings(struct adv748x_state *state,
        unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(adv748x_hdmi_video_standards); i++) {
-               if (!v4l2_match_dv_timings(timings, &stds[i].timings, 250000,
-                                          false))
-                       continue;
+               if (v4l2_match_dv_timings(timings, &stds[i].timings, 250000,
+                                         false))
+                       break;
        }
 
        if (i >= ARRAY_SIZE(adv748x_hdmi_video_standards))
@@ -283,6 +283,16 @@ static int adv748x_hdmi_query_dv_timings(struct v4l2_subdev *sd,
 
        memset(timings, 0, sizeof(struct v4l2_dv_timings));
 
+       /*
+        * If the pattern generator is enabled the device shall not be queried
+        * for timings. Instead the timings programmed shall be reported as they
+        * are the ones being used to generate the pattern.
+        */
+       if (cp_read(state, ADV748X_CP_PAT_GEN) & ADV748X_CP_PAT_GEN_EN) {
+               *timings = hdmi->timings;
+               return 0;
+       }
+
        if (!adv748x_hdmi_has_signal(state))
                return -ENOLINK;
 
@@ -721,11 +731,10 @@ static int adv748x_hdmi_init_controls(struct adv748x_hdmi *hdmi)
 int adv748x_hdmi_init(struct adv748x_hdmi *hdmi)
 {
        struct adv748x_state *state = adv748x_hdmi_to_state(hdmi);
-       static const struct v4l2_dv_timings cea1280x720 =
-               V4L2_DV_BT_CEA_1280X720P30;
+       struct v4l2_dv_timings cea1280x720 = V4L2_DV_BT_CEA_1280X720P30;
        int ret;
 
-       hdmi->timings = cea1280x720;
+       adv748x_hdmi_s_dv_timings(&hdmi->sd, &cea1280x720);
 
        /* Initialise a default 16:9 aspect ratio */
        hdmi->aspect_ratio.numerator = 16;
index 9d218962d7c83046da66f23a6432680b041c15be..3d0898c4175e0dc20e3952ccd1f8be179fd82b2b 100644 (file)
@@ -1805,6 +1805,9 @@ static void select_input(struct v4l2_subdev *sd)
                v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
                                __func__, state->selected_input);
        }
+
+       /* Enable video adjustment (contrast, saturation, brightness and hue) */
+       cp_write_clr_set(sd, 0x3e, 0x80, 0x80);
 }
 
 static int adv76xx_s_routing(struct v4l2_subdev *sd,
@@ -3545,7 +3548,7 @@ static int adv76xx_probe(struct i2c_client *client)
        v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
                        V4L2_CID_SATURATION, 0, 255, 1, 128);
        v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
-                       V4L2_CID_HUE, 0, 128, 1, 0);
+                       V4L2_CID_HUE, 0, 255, 1, 0);
        ctrl = v4l2_ctrl_new_std_menu(hdl, &adv76xx_ctrl_ops,
                        V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC,
                        0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC);
index 4a14d7e5d9f25174c9a142d5c6eafe7ddf09c167..559a415fd827f4f99688ca5aaf17341a4542eeb3 100644 (file)
@@ -569,8 +569,6 @@ static u32 ccs_pixel_order(struct ccs_sensor *sensor)
                        flip |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP;
        }
 
-       flip ^= sensor->hvflip_inv_mask;
-
        dev_dbg(&client->dev, "flip %u\n", flip);
        return sensor->default_pixel_order ^ flip;
 }
@@ -632,8 +630,6 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl)
                if (sensor->vflip->val)
                        orient |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP;
 
-               orient ^= sensor->hvflip_inv_mask;
-
                ccs_update_mbus_formats(sensor);
 
                break;
@@ -800,14 +796,24 @@ static const struct v4l2_ctrl_ops ccs_ctrl_ops = {
 static int ccs_init_controls(struct ccs_sensor *sensor)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+       struct v4l2_fwnode_device_properties props;
        int rval;
 
-       rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 17);
+       rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 19);
        if (rval)
                return rval;
 
        sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
 
+       rval = v4l2_fwnode_device_parse(&client->dev, &props);
+       if (rval)
+               return rval;
+
+       rval = v4l2_ctrl_new_fwnode_properties(&sensor->pixel_array->ctrl_handler,
+                                              &ccs_ctrl_ops, &props);
+       if (rval)
+               return rval;
+
        switch (CCS_LIM(sensor, ANALOG_GAIN_CAPABILITY)) {
        case CCS_ANALOG_GAIN_CAPABILITY_GLOBAL: {
                struct {
@@ -2828,6 +2834,10 @@ static int ccs_identify_module(struct ccs_sensor *sensor)
                rval = ccs_read_addr_8only(sensor,
                                           CCS_R_SENSOR_REVISION_NUMBER,
                                           &minfo->sensor_revision_number);
+       if (!rval && !minfo->sensor_revision_number)
+               rval = ccs_read_addr_8only(sensor,
+                                          CCS_R_SENSOR_REVISION_NUMBER_16,
+                                          &minfo->sensor_revision_number);
        if (!rval)
                rval = ccs_read_addr_8only(sensor,
                                           CCS_R_SENSOR_FIRMWARE_VERSION,
@@ -2870,7 +2880,7 @@ static int ccs_identify_module(struct ccs_sensor *sensor)
                        minfo->sensor_model_id);
 
        dev_dbg(&client->dev,
-               "sensor revision 0x%2.2x firmware version 0x%2.2x\n",
+               "sensor revision 0x%4.4x firmware version 0x%2.2x\n",
                minfo->sensor_revision_number, minfo->sensor_firmware_version);
 
        if (minfo->ccs_version) {
@@ -2884,19 +2894,18 @@ static int ccs_identify_module(struct ccs_sensor *sensor)
                        "smia version %2.2d smiapp version %2.2d\n",
                        minfo->smia_version, minfo->smiapp_version);
                minfo->name = SMIAPP_NAME;
-       }
-
-       /*
-        * Some modules have bad data in the lvalues below. Hope the
-        * rvalues have better stuff. The lvalues are module
-        * parameters whereas the rvalues are sensor parameters.
-        */
-       if (minfo->sensor_smia_manufacturer_id &&
-           !minfo->smia_manufacturer_id && !minfo->model_id) {
-               minfo->smia_manufacturer_id =
-                       minfo->sensor_smia_manufacturer_id;
-               minfo->model_id = minfo->sensor_model_id;
-               minfo->revision_number = minfo->sensor_revision_number;
+               /*
+                * Some modules have bad data in the lvalues below. Hope the
+                * rvalues have better stuff. The lvalues are module
+                * parameters whereas the rvalues are sensor parameters.
+                */
+               if (minfo->sensor_smia_manufacturer_id &&
+                   !minfo->smia_manufacturer_id && !minfo->model_id) {
+                       minfo->smia_manufacturer_id =
+                               minfo->sensor_smia_manufacturer_id;
+                       minfo->model_id = minfo->sensor_model_id;
+                       minfo->revision_number = minfo->sensor_revision_number;
+               }
        }
 
        for (i = 0; i < ARRAY_SIZE(ccs_module_idents); i++) {
@@ -3185,7 +3194,6 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev)
        struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_UNKNOWN };
        struct fwnode_handle *ep;
        struct fwnode_handle *fwnode = dev_fwnode(dev);
-       u32 rotation;
        unsigned int i;
        int rval;
 
@@ -3224,22 +3232,6 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev)
                goto out_err;
        }
 
-       rval = fwnode_property_read_u32(fwnode, "rotation", &rotation);
-       if (!rval) {
-               switch (rotation) {
-               case 180:
-                       hwcfg->module_board_orient =
-                               CCS_MODULE_BOARD_ORIENT_180;
-                       fallthrough;
-               case 0:
-                       break;
-               default:
-                       dev_err(dev, "invalid rotation %u\n", rotation);
-                       rval = -EINVAL;
-                       goto out_err;
-               }
-       }
-
        rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
                                        &hwcfg->ext_clk);
        if (rval)
@@ -3279,8 +3271,47 @@ out_err:
        return rval;
 }
 
+static int ccs_firmware_name(struct i2c_client *client,
+                            struct ccs_sensor *sensor, char *filename,
+                            size_t filename_size, bool is_module)
+{
+       const struct ccs_device *ccsdev = device_get_match_data(&client->dev);
+       bool is_ccs = !(ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA);
+       bool is_smiapp = sensor->minfo.smiapp_version;
+       u16 manufacturer_id;
+       u16 model_id;
+       u16 revision_number;
+
+       /*
+        * Old SMIA is module-agnostic. Its sensor identification is based on
+        * what now are those of the module.
+        */
+       if (is_module || (!is_ccs && !is_smiapp)) {
+               manufacturer_id = is_ccs ?
+                       sensor->minfo.mipi_manufacturer_id :
+                       sensor->minfo.smia_manufacturer_id;
+               model_id = sensor->minfo.model_id;
+               revision_number = sensor->minfo.revision_number;
+       } else {
+               manufacturer_id = is_ccs ?
+                       sensor->minfo.sensor_mipi_manufacturer_id :
+                       sensor->minfo.sensor_smia_manufacturer_id;
+               model_id = sensor->minfo.sensor_model_id;
+               revision_number = sensor->minfo.sensor_revision_number;
+       }
+
+       return snprintf(filename, filename_size,
+                       "ccs/%s-%s-%0*x-%4.4x-%0*x.fw",
+                       is_ccs ? "ccs" : is_smiapp ? "smiapp" : "smia",
+                       is_module || (!is_ccs && !is_smiapp) ?
+                               "module" : "sensor",
+                       is_ccs ? 4 : 2, manufacturer_id, model_id,
+                       !is_ccs && !is_module ? 2 : 4, revision_number);
+}
+
 static int ccs_probe(struct i2c_client *client)
 {
+       const struct ccs_device *ccsdev = device_get_match_data(&client->dev);
        struct ccs_sensor *sensor;
        const struct firmware *fw;
        char filename[40];
@@ -3389,11 +3420,8 @@ static int ccs_probe(struct i2c_client *client)
                goto out_power_off;
        }
 
-       rval = snprintf(filename, sizeof(filename),
-                       "ccs/ccs-sensor-%4.4x-%4.4x-%4.4x.fw",
-                       sensor->minfo.sensor_mipi_manufacturer_id,
-                       sensor->minfo.sensor_model_id,
-                       sensor->minfo.sensor_revision_number);
+       rval = ccs_firmware_name(client, sensor, filename, sizeof(filename),
+                                false);
        if (rval >= sizeof(filename)) {
                rval = -ENOMEM;
                goto out_power_off;
@@ -3406,21 +3434,21 @@ static int ccs_probe(struct i2c_client *client)
                release_firmware(fw);
        }
 
-       rval = snprintf(filename, sizeof(filename),
-                       "ccs/ccs-module-%4.4x-%4.4x-%4.4x.fw",
-                       sensor->minfo.mipi_manufacturer_id,
-                       sensor->minfo.model_id,
-                       sensor->minfo.revision_number);
-       if (rval >= sizeof(filename)) {
-               rval = -ENOMEM;
-               goto out_release_sdata;
-       }
+       if (!(ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA) ||
+           sensor->minfo.smiapp_version) {
+               rval = ccs_firmware_name(client, sensor, filename,
+                                        sizeof(filename), true);
+               if (rval >= sizeof(filename)) {
+                       rval = -ENOMEM;
+                       goto out_release_sdata;
+               }
 
-       rval = request_firmware(&fw, filename, &client->dev);
-       if (!rval) {
-               ccs_data_parse(&sensor->mdata, fw->data, fw->size, &client->dev,
-                              true);
-               release_firmware(fw);
+               rval = request_firmware(&fw, filename, &client->dev);
+               if (!rval) {
+                       ccs_data_parse(&sensor->mdata, fw->data, fw->size,
+                                      &client->dev, true);
+                       release_firmware(fw);
+               }
        }
 
        rval = ccs_read_all_limits(sensor);
@@ -3437,25 +3465,6 @@ static int ccs_probe(struct i2c_client *client)
        if (rval < 0)
                goto out_free_ccs_limits;
 
-       /*
-        * Handle Sensor Module orientation on the board.
-        *
-        * The application of H-FLIP and V-FLIP on the sensor is modified by
-        * the sensor orientation on the board.
-        *
-        * For CCS_BOARD_SENSOR_ORIENT_180 the default behaviour is to set
-        * both H-FLIP and V-FLIP for normal operation which also implies
-        * that a set/unset operation for user space HFLIP and VFLIP v4l2
-        * controls will need to be internally inverted.
-        *
-        * Rotation also changes the bayer pattern.
-        */
-       if (sensor->hwcfg.module_board_orient ==
-           CCS_MODULE_BOARD_ORIENT_180)
-               sensor->hvflip_inv_mask =
-                       CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR |
-                       CCS_IMAGE_ORIENTATION_VERTICAL_FLIP;
-
        rval = ccs_call_quirk(sensor, limits);
        if (rval) {
                dev_err(&client->dev, "limits quirks failed\n");
index 6beac375cc4863918d574b9945684088d124a5e9..a94c796cea487153b013301a37276d02b60cbd40 100644 (file)
 #define CCS_LIM_AT(sensor, limit, offset)      \
        ccs_get_limit(sensor, CCS_L_##limit, CCS_L_##limit##_OFFSET(offset))
 
-/*
- * Sometimes due to board layout considerations the camera module can be
- * mounted rotated. The typical rotation used is 180 degrees which can be
- * corrected by giving a default H-FLIP and V-FLIP in the sensor readout.
- * FIXME: rotation also changes the bayer pattern.
- */
-enum ccs_module_board_orient {
-       CCS_MODULE_BOARD_ORIENT_0 = 0,
-       CCS_MODULE_BOARD_ORIENT_180,
-};
-
 struct ccs_flash_strobe_parms {
        u8 mode;
        u32 strobe_width_high_us;
@@ -90,8 +79,6 @@ struct ccs_hwconfig {
        u32 csi_signalling_mode;        /* CCS_CSI_SIGNALLING_MODE_* */
        u64 *op_sys_clock;
 
-       enum ccs_module_board_orient module_board_orient;
-
        struct ccs_flash_strobe_parms *strobe_setup;
 };
 
@@ -243,7 +230,6 @@ struct ccs_sensor {
        u8 scale_m;
        u8 scaling_mode;
 
-       u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
        u8 frame_skip;
        u16 embedded_start; /* embedded data start line */
        u16 embedded_end;
index e422ac7609b5ce9c6153d8cf8feb95aee89d513b..7daefab35cf02e45b5cdb73932a111a3c0262b94 100644 (file)
 #define HI556_REG_ISP_TPG_EN           0x01
 #define HI556_REG_TEST_PATTERN         0x0201
 
+/* HI556 native and active pixel array size. */
+#define HI556_NATIVE_WIDTH             2592U
+#define HI556_NATIVE_HEIGHT            1944U
+#define HI556_PIXEL_ARRAY_LEFT         0U
+#define HI556_PIXEL_ARRAY_TOP          0U
+#define HI556_PIXEL_ARRAY_WIDTH        2592U
+#define HI556_PIXEL_ARRAY_HEIGHT       1944U
+
 enum {
        HI556_LINK_FREQ_437MHZ_INDEX,
 };
@@ -88,6 +96,9 @@ struct hi556_mode {
        /* Frame height in pixels */
        u32 height;
 
+       /* Analog crop rectangle. */
+       struct v4l2_rect crop;
+
        /* Horizontal timining size */
        u32 llp;
 
@@ -378,6 +389,49 @@ static const struct hi556_reg mode_2592x1944_regs[] = {
        {0x0958, 0xbb80},
 };
 
+static const struct hi556_reg mode_2592x1444_regs[] = {
+       {0x0a00, 0x0000},
+       {0x0b0a, 0x8252},
+       {0x0f30, 0xe545},
+       {0x0f32, 0x7067},
+       {0x004a, 0x0100},
+       {0x004c, 0x0000},
+       {0x000c, 0x0022},
+       {0x0008, 0x0b00},
+       {0x005a, 0x0202},
+       {0x0012, 0x000e},
+       {0x0018, 0x0a33},
+       {0x0022, 0x0008},
+       {0x0028, 0x0017},
+       {0x0024, 0x0122},
+       {0x002a, 0x0127},
+       {0x0026, 0x012a},
+       {0x002c, 0x06cf},
+       {0x002e, 0x1111},
+       {0x0030, 0x1111},
+       {0x0032, 0x1111},
+       {0x0006, 0x0821},
+       {0x0a22, 0x0000},
+       {0x0a12, 0x0a20},
+       {0x0a14, 0x05a4},
+       {0x003e, 0x0000},
+       {0x0074, 0x081f},
+       {0x0070, 0x040f},
+       {0x0804, 0x0300},
+       {0x0806, 0x0100},
+       {0x0a04, 0x014a},
+       {0x090c, 0x0fdc},
+       {0x090e, 0x002d},
+       {0x0902, 0x4319},
+       {0x0914, 0xc10a},
+       {0x0916, 0x071f},
+       {0x0918, 0x0408},
+       {0x091a, 0x0c0d},
+       {0x091c, 0x0f09},
+       {0x091e, 0x0a00},
+       {0x0958, 0xbb80},
+};
+
 static const struct hi556_reg mode_1296x972_regs[] = {
        {0x0a00, 0x0000},
        {0x0b0a, 0x8259},
@@ -450,8 +504,14 @@ static const struct hi556_link_freq_config link_freq_configs[] = {
 
 static const struct hi556_mode supported_modes[] = {
        {
-               .width = 2592,
-               .height = 1944,
+               .width = HI556_PIXEL_ARRAY_WIDTH,
+               .height = HI556_PIXEL_ARRAY_HEIGHT,
+               .crop = {
+                       .left = HI556_PIXEL_ARRAY_LEFT,
+                       .top = HI556_PIXEL_ARRAY_TOP,
+                       .width = HI556_PIXEL_ARRAY_WIDTH,
+                       .height = HI556_PIXEL_ARRAY_HEIGHT
+               },
                .fll_def = HI556_FLL_30FPS,
                .fll_min = HI556_FLL_30FPS_MIN,
                .llp = 0x0b00,
@@ -461,9 +521,33 @@ static const struct hi556_mode supported_modes[] = {
                },
                .link_freq_index = HI556_LINK_FREQ_437MHZ_INDEX,
        },
+       {
+               .width = HI556_PIXEL_ARRAY_WIDTH,
+               .height = 1444,
+               .crop = {
+                       .left = HI556_PIXEL_ARRAY_LEFT,
+                       .top = 250,
+                       .width = HI556_PIXEL_ARRAY_WIDTH,
+                       .height = 1444
+               },
+               .fll_def = 0x821,
+               .fll_min = 0x821,
+               .llp = 0x0b00,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_2592x1444_regs),
+                       .regs = mode_2592x1444_regs,
+               },
+               .link_freq_index = HI556_LINK_FREQ_437MHZ_INDEX,
+       },
        {
                .width = 1296,
                .height = 972,
+               .crop = {
+                       .left = HI556_PIXEL_ARRAY_LEFT,
+                       .top = HI556_PIXEL_ARRAY_TOP,
+                       .width = HI556_PIXEL_ARRAY_WIDTH,
+                       .height = HI556_PIXEL_ARRAY_HEIGHT
+               },
                .fll_def = HI556_FLL_30FPS,
                .fll_min = HI556_FLL_30FPS_MIN,
                .llp = 0x0b00,
@@ -785,6 +869,58 @@ static int hi556_identify_module(struct hi556 *hi556)
        return 0;
 }
 
+static const struct v4l2_rect *
+__hi556_get_pad_crop(struct hi556 *hi556,
+                    struct v4l2_subdev_state *sd_state,
+                    unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+       switch (which) {
+       case V4L2_SUBDEV_FORMAT_TRY:
+               return v4l2_subdev_get_try_crop(&hi556->sd, sd_state, pad);
+       case V4L2_SUBDEV_FORMAT_ACTIVE:
+               return &hi556->cur_mode->crop;
+       }
+
+       return NULL;
+}
+
+static int hi556_get_selection(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_state *sd_state,
+                              struct v4l2_subdev_selection *sel)
+{
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP: {
+               struct hi556 *hi556 = to_hi556(sd);
+
+               mutex_lock(&hi556->mutex);
+               sel->r = *__hi556_get_pad_crop(hi556, sd_state, sel->pad,
+                                               sel->which);
+               mutex_unlock(&hi556->mutex);
+
+               return 0;
+       }
+
+       case V4L2_SEL_TGT_NATIVE_SIZE:
+               sel->r.top = 0;
+               sel->r.left = 0;
+               sel->r.width = HI556_NATIVE_WIDTH;
+               sel->r.height = HI556_NATIVE_HEIGHT;
+
+               return 0;
+
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               sel->r.top = HI556_PIXEL_ARRAY_TOP;
+               sel->r.left = HI556_PIXEL_ARRAY_LEFT;
+               sel->r.width = HI556_PIXEL_ARRAY_WIDTH;
+               sel->r.height = HI556_PIXEL_ARRAY_HEIGHT;
+
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
 static int hi556_start_streaming(struct hi556 *hi556)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd);
@@ -1000,10 +1136,19 @@ static int hi556_enum_frame_size(struct v4l2_subdev *sd,
 static int hi556_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
        struct hi556 *hi556 = to_hi556(sd);
+       struct v4l2_rect *try_crop;
 
        mutex_lock(&hi556->mutex);
        hi556_assign_pad_format(&supported_modes[0],
                                v4l2_subdev_get_try_format(sd, fh->state, 0));
+
+       /* Initialize try_crop rectangle. */
+       try_crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
+       try_crop->top = HI556_PIXEL_ARRAY_TOP;
+       try_crop->left = HI556_PIXEL_ARRAY_LEFT;
+       try_crop->width = HI556_PIXEL_ARRAY_WIDTH;
+       try_crop->height = HI556_PIXEL_ARRAY_HEIGHT;
+
        mutex_unlock(&hi556->mutex);
 
        return 0;
@@ -1016,6 +1161,7 @@ static const struct v4l2_subdev_video_ops hi556_video_ops = {
 static const struct v4l2_subdev_pad_ops hi556_pad_ops = {
        .set_fmt = hi556_set_format,
        .get_fmt = hi556_get_format,
+       .get_selection = hi556_get_selection,
        .enum_mbus_code = hi556_enum_mbus_code,
        .enum_frame_size = hi556_enum_frame_size,
 };
index 7c61873b719812c6c64bb80467bc81e72d1f9f71..306dc35e925fd00ad4943f386e15794e30542564 100644 (file)
@@ -1472,21 +1472,26 @@ static int hi846_init_controls(struct hi846 *hi846)
        if (ctrl_hdlr->error) {
                dev_err(&client->dev, "v4l ctrl handler error: %d\n",
                        ctrl_hdlr->error);
-               return ctrl_hdlr->error;
+               ret = ctrl_hdlr->error;
+               goto error;
        }
 
        ret = v4l2_fwnode_device_parse(&client->dev, &props);
        if (ret)
-               return ret;
+               goto error;
 
        ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &hi846_ctrl_ops,
                                              &props);
        if (ret)
-               return ret;
+               goto error;
 
        hi846->sd.ctrl_handler = ctrl_hdlr;
 
        return 0;
+
+error:
+       v4l2_ctrl_handler_free(ctrl_hdlr);
+       return ret;
 }
 
 static int hi846_set_video_mode(struct hi846 *hi846, int fps)
index eab5fc1ee2f7403de4a9fb62e9146f7594618191..85d73b1861111c1f67ca7a372ca7441333e7ac25 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/pm_runtime.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
 #include <asm/unaligned.h>
 
 #define IMX258_REG_VALUE_08BIT         1
@@ -1148,7 +1149,9 @@ static const struct v4l2_subdev_internal_ops imx258_internal_ops = {
 static int imx258_init_controls(struct imx258 *imx258)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
+       struct v4l2_fwnode_device_properties props;
        struct v4l2_ctrl_handler *ctrl_hdlr;
+       struct v4l2_ctrl *vflip, *hflip;
        s64 vblank_def;
        s64 vblank_min;
        s64 pixel_rate_min;
@@ -1156,7 +1159,7 @@ static int imx258_init_controls(struct imx258 *imx258)
        int ret;
 
        ctrl_hdlr = &imx258->ctrl_handler;
-       ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);
+       ret = v4l2_ctrl_handler_init(ctrl_hdlr, 13);
        if (ret)
                return ret;
 
@@ -1172,6 +1175,17 @@ static int imx258_init_controls(struct imx258 *imx258)
        if (imx258->link_freq)
                imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
+       /* The driver only supports one bayer order and flips by default. */
+       hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
+                                 V4L2_CID_HFLIP, 1, 1, 1, 1);
+       if (hflip)
+               hflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+       vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
+                                 V4L2_CID_VFLIP, 1, 1, 1, 1);
+       if (vflip)
+               vflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
        pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
        pixel_rate_min = link_freq_to_pixel_rate(link_freq_menu_items[1]);
        /* By default, PIXEL_RATE is read only */
@@ -1232,6 +1246,15 @@ static int imx258_init_controls(struct imx258 *imx258)
                goto error;
        }
 
+       ret = v4l2_fwnode_device_parse(&client->dev, &props);
+       if (ret)
+               goto error;
+
+       ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx258_ctrl_ops,
+                                             &props);
+       if (ret)
+               goto error;
+
        imx258->sd.ctrl_handler = ctrl_hdlr;
 
        return 0;
@@ -1276,14 +1299,6 @@ static int imx258_probe(struct i2c_client *client)
                return -EINVAL;
        }
 
-       /*
-        * Check that the device is mounted upside down. The driver only
-        * supports a single pixel order right now.
-        */
-       ret = device_property_read_u32(&client->dev, "rotation", &val);
-       if (ret || val != 180)
-               return -EINVAL;
-
        /* Initialize subdev */
        v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);
 
index 48ae2e0adf9ea84615f00fa0d50a13a7ccdad860..5ea25b7acc55f04e6069a0767569882ceaf96fb0 100644 (file)
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
+
+#include <asm/unaligned.h>
+
 #include <media/media-entity.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
@@ -44,7 +49,9 @@
 #define IMX290_BLKLEVEL                                        IMX290_REG_16BIT(0x300a)
 #define IMX290_GAIN                                    IMX290_REG_8BIT(0x3014)
 #define IMX290_VMAX                                    IMX290_REG_24BIT(0x3018)
+#define IMX290_VMAX_MAX                                        0x3ffff
 #define IMX290_HMAX                                    IMX290_REG_16BIT(0x301c)
+#define IMX290_HMAX_MAX                                        0xffff
 #define IMX290_SHS1                                    IMX290_REG_24BIT(0x3020)
 #define IMX290_WINWV_OB                                        IMX290_REG_8BIT(0x303a)
 #define IMX290_WINPV                                   IMX290_REG_16BIT(0x303c)
 #define IMX290_TCLKPREPARE                             IMX290_REG_16BIT(0x3452)
 #define IMX290_TLPX                                    IMX290_REG_16BIT(0x3454)
 #define IMX290_X_OUT_SIZE                              IMX290_REG_16BIT(0x3472)
+#define IMX290_INCKSEL7                                        IMX290_REG_8BIT(0x3480)
 
 #define IMX290_PGCTRL_REGEN                            BIT(0)
 #define IMX290_PGCTRL_THRU                             BIT(1)
 #define IMX290_PGCTRL_MODE(n)                          ((n) << 4)
 
-#define IMX290_VMAX_DEFAULT                            1125
+/* Number of lines by which exposure must be less than VMAX */
+#define IMX290_EXPOSURE_OFFSET                         2
 
+#define IMX290_PIXEL_RATE                              148500000
 
 /*
  * The IMX290 pixel array is organized as follows:
 
 #define IMX290_NUM_SUPPLIES                            3
 
+enum imx290_colour_variant {
+       IMX290_VARIANT_COLOUR,
+       IMX290_VARIANT_MONO,
+       IMX290_VARIANT_MAX
+};
+
+enum imx290_model {
+       IMX290_MODEL_IMX290LQR,
+       IMX290_MODEL_IMX290LLR,
+       IMX290_MODEL_IMX327LQR,
+};
+
+struct imx290_model_info {
+       enum imx290_colour_variant colour_variant;
+       const struct imx290_regval *init_regs;
+       size_t init_regs_num;
+       const char *name;
+};
+
+enum imx290_clk_freq {
+       IMX290_CLK_37_125,
+       IMX290_CLK_74_25,
+       IMX290_NUM_CLK
+};
+
 struct imx290_regval {
        u32 reg;
        u32 val;
 };
 
+/*
+ * Clock configuration for registers INCKSEL1 to INCKSEL6.
+ */
+struct imx290_clk_cfg {
+       u8 incksel1;
+       u8 incksel2;
+       u8 incksel3;
+       u8 incksel4;
+       u8 incksel5;
+       u8 incksel6;
+};
+
 struct imx290_mode {
        u32 width;
        u32 height;
-       u32 hmax;
+       u32 hmax_min;
+       u32 vmax_min;
        u8 link_freq_index;
+       u8 ctrl_07;
 
        const struct imx290_regval *data;
        u32 data_size;
+
+       const struct imx290_clk_cfg *clk_cfg;
+};
+
+struct imx290_csi_cfg {
+       u16 repetition;
+       u16 tclkpost;
+       u16 thszero;
+       u16 thsprepare;
+       u16 tclktrail;
+       u16 thstrail;
+       u16 tclkzero;
+       u16 tclkprepare;
+       u16 tlpx;
 };
 
 struct imx290 {
        struct device *dev;
        struct clk *xclk;
        struct regmap *regmap;
+       enum imx290_clk_freq xclk_idx;
        u8 nlanes;
+       const struct imx290_model_info *model;
 
        struct v4l2_subdev sd;
        struct media_pad pad;
@@ -188,9 +253,13 @@ struct imx290 {
 
        struct v4l2_ctrl_handler ctrls;
        struct v4l2_ctrl *link_freq;
-       struct v4l2_ctrl *pixel_rate;
        struct v4l2_ctrl *hblank;
        struct v4l2_ctrl *vblank;
+       struct v4l2_ctrl *exposure;
+       struct {
+               struct v4l2_ctrl *hflip;
+               struct v4l2_ctrl *vflip;
+       };
 };
 
 static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
@@ -203,9 +272,6 @@ static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
  */
 
 static const struct imx290_regval imx290_global_init_settings[] = {
-       { IMX290_CTRL_07, IMX290_WINMODE_1080P },
-       { IMX290_VMAX, IMX290_VMAX_DEFAULT },
-       { IMX290_EXTCK_FREQ, 0x2520 },
        { IMX290_WINWV_OB, 12 },
        { IMX290_WINPH, 0 },
        { IMX290_WINPV, 0 },
@@ -213,10 +279,14 @@ static const struct imx290_regval imx290_global_init_settings[] = {
        { IMX290_WINWV, 1097 },
        { IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |
                           IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },
-       { IMX290_REG_8BIT(0x300f), 0x00 },
-       { IMX290_REG_8BIT(0x3010), 0x21 },
+       { IMX290_REG_8BIT(0x3011), 0x02 },
        { IMX290_REG_8BIT(0x3012), 0x64 },
        { IMX290_REG_8BIT(0x3013), 0x00 },
+};
+
+static const struct imx290_regval imx290_global_init_settings_290[] = {
+       { IMX290_REG_8BIT(0x300f), 0x00 },
+       { IMX290_REG_8BIT(0x3010), 0x21 },
        { IMX290_REG_8BIT(0x3016), 0x09 },
        { IMX290_REG_8BIT(0x3070), 0x02 },
        { IMX290_REG_8BIT(0x3071), 0x11 },
@@ -255,57 +325,40 @@ static const struct imx290_regval imx290_global_init_settings[] = {
        { IMX290_REG_8BIT(0x33b0), 0x50 },
        { IMX290_REG_8BIT(0x33b2), 0x1a },
        { IMX290_REG_8BIT(0x33b3), 0x04 },
-       { IMX290_REG_8BIT(0x3480), 0x49 },
+};
+
+#define IMX290_NUM_CLK_REGS    2
+static const struct imx290_regval xclk_regs[][IMX290_NUM_CLK_REGS] = {
+       [IMX290_CLK_37_125] = {
+               { IMX290_EXTCK_FREQ, (37125 * 256) / 1000 },
+               { IMX290_INCKSEL7, 0x49 },
+       },
+       [IMX290_CLK_74_25] = {
+               { IMX290_EXTCK_FREQ, (74250 * 256) / 1000 },
+               { IMX290_INCKSEL7, 0x92 },
+       },
+};
+
+static const struct imx290_regval imx290_global_init_settings_327[] = {
+       { IMX290_REG_8BIT(0x309e), 0x4A },
+       { IMX290_REG_8BIT(0x309f), 0x4A },
+       { IMX290_REG_8BIT(0x313b), 0x61 },
 };
 
 static const struct imx290_regval imx290_1080p_settings[] = {
        /* mode settings */
-       { IMX290_CTRL_07, IMX290_WINMODE_1080P },
        { IMX290_WINWV_OB, 12 },
        { IMX290_OPB_SIZE_V, 10 },
        { IMX290_X_OUT_SIZE, 1920 },
        { IMX290_Y_OUT_SIZE, 1080 },
-       { IMX290_INCKSEL1, 0x18 },
-       { IMX290_INCKSEL2, 0x03 },
-       { IMX290_INCKSEL3, 0x20 },
-       { IMX290_INCKSEL4, 0x01 },
-       { IMX290_INCKSEL5, 0x1a },
-       { IMX290_INCKSEL6, 0x1a },
-       /* data rate settings */
-       { IMX290_REPETITION, 0x10 },
-       { IMX290_TCLKPOST, 87 },
-       { IMX290_THSZERO, 55 },
-       { IMX290_THSPREPARE, 31 },
-       { IMX290_TCLKTRAIL, 31 },
-       { IMX290_THSTRAIL, 31 },
-       { IMX290_TCLKZERO, 119 },
-       { IMX290_TCLKPREPARE, 31 },
-       { IMX290_TLPX, 23 },
 };
 
 static const struct imx290_regval imx290_720p_settings[] = {
        /* mode settings */
-       { IMX290_CTRL_07, IMX290_WINMODE_720P },
        { IMX290_WINWV_OB, 6 },
        { IMX290_OPB_SIZE_V, 4 },
        { IMX290_X_OUT_SIZE, 1280 },
        { IMX290_Y_OUT_SIZE, 720 },
-       { IMX290_INCKSEL1, 0x20 },
-       { IMX290_INCKSEL2, 0x00 },
-       { IMX290_INCKSEL3, 0x20 },
-       { IMX290_INCKSEL4, 0x01 },
-       { IMX290_INCKSEL5, 0x1a },
-       { IMX290_INCKSEL6, 0x1a },
-       /* data rate settings */
-       { IMX290_REPETITION, 0x10 },
-       { IMX290_TCLKPOST, 79 },
-       { IMX290_THSZERO, 47 },
-       { IMX290_THSPREPARE, 23 },
-       { IMX290_TCLKTRAIL, 23 },
-       { IMX290_THSTRAIL, 23 },
-       { IMX290_TCLKZERO, 87 },
-       { IMX290_TCLKPREPARE, 23 },
-       { IMX290_TLPX, 23 },
 };
 
 static const struct imx290_regval imx290_10bit_settings[] = {
@@ -326,6 +379,58 @@ static const struct imx290_regval imx290_12bit_settings[] = {
        { IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW12 },
 };
 
+static const struct imx290_csi_cfg imx290_csi_222_75mhz = {
+       /* 222.75MHz or 445.5Mbit/s per lane */
+       .repetition = 0x10,
+       .tclkpost = 87,
+       .thszero = 55,
+       .thsprepare = 31,
+       .tclktrail = 31,
+       .thstrail = 31,
+       .tclkzero = 119,
+       .tclkprepare = 31,
+       .tlpx = 23,
+};
+
+static const struct imx290_csi_cfg imx290_csi_445_5mhz = {
+       /* 445.5MHz or 891Mbit/s per lane */
+       .repetition = 0x00,
+       .tclkpost = 119,
+       .thszero = 103,
+       .thsprepare = 71,
+       .tclktrail = 55,
+       .thstrail = 63,
+       .tclkzero = 255,
+       .tclkprepare = 63,
+       .tlpx = 55,
+};
+
+static const struct imx290_csi_cfg imx290_csi_148_5mhz = {
+       /* 148.5MHz or 297Mbit/s per lane */
+       .repetition = 0x10,
+       .tclkpost = 79,
+       .thszero = 47,
+       .thsprepare = 23,
+       .tclktrail = 23,
+       .thstrail = 23,
+       .tclkzero = 87,
+       .tclkprepare = 23,
+       .tlpx = 23,
+};
+
+static const struct imx290_csi_cfg imx290_csi_297mhz = {
+       /* 297MHz or 594Mbit/s per lane */
+       .repetition = 0x00,
+       .tclkpost = 103,
+       .thszero = 87,
+       .thsprepare = 47,
+       .tclktrail = 39,
+       .thstrail = 47,
+       .tclkzero = 191,
+       .tclkprepare = 47,
+       .tlpx = 39,
+};
+
 /* supported link frequencies */
 #define FREQ_INDEX_1080P       0
 #define FREQ_INDEX_720P                1
@@ -333,6 +438,7 @@ static const s64 imx290_link_freq_2lanes[] = {
        [FREQ_INDEX_1080P] = 445500000,
        [FREQ_INDEX_720P] = 297000000,
 };
+
 static const s64 imx290_link_freq_4lanes[] = {
        [FREQ_INDEX_1080P] = 222750000,
        [FREQ_INDEX_720P] = 148500000,
@@ -358,23 +464,71 @@ static inline int imx290_link_freqs_num(const struct imx290 *imx290)
                return ARRAY_SIZE(imx290_link_freq_4lanes);
 }
 
+static const struct imx290_clk_cfg imx290_1080p_clock_config[] = {
+       [IMX290_CLK_37_125] = {
+               /* 37.125MHz clock config */
+               .incksel1 = 0x18,
+               .incksel2 = 0x03,
+               .incksel3 = 0x20,
+               .incksel4 = 0x01,
+               .incksel5 = 0x1a,
+               .incksel6 = 0x1a,
+       },
+       [IMX290_CLK_74_25] = {
+               /* 74.25MHz clock config */
+               .incksel1 = 0x0c,
+               .incksel2 = 0x03,
+               .incksel3 = 0x10,
+               .incksel4 = 0x01,
+               .incksel5 = 0x1b,
+               .incksel6 = 0x1b,
+       },
+};
+
+static const struct imx290_clk_cfg imx290_720p_clock_config[] = {
+       [IMX290_CLK_37_125] = {
+               /* 37.125MHz clock config */
+               .incksel1 = 0x20,
+               .incksel2 = 0x00,
+               .incksel3 = 0x20,
+               .incksel4 = 0x01,
+               .incksel5 = 0x1a,
+               .incksel6 = 0x1a,
+       },
+       [IMX290_CLK_74_25] = {
+               /* 74.25MHz clock config */
+               .incksel1 = 0x10,
+               .incksel2 = 0x00,
+               .incksel3 = 0x10,
+               .incksel4 = 0x01,
+               .incksel5 = 0x1b,
+               .incksel6 = 0x1b,
+       },
+};
+
 /* Mode configs */
 static const struct imx290_mode imx290_modes_2lanes[] = {
        {
                .width = 1920,
                .height = 1080,
-               .hmax = 4400,
+               .hmax_min = 2200,
+               .vmax_min = 1125,
                .link_freq_index = FREQ_INDEX_1080P,
+               .ctrl_07 = IMX290_WINMODE_1080P,
                .data = imx290_1080p_settings,
                .data_size = ARRAY_SIZE(imx290_1080p_settings),
+               .clk_cfg = imx290_1080p_clock_config,
        },
        {
                .width = 1280,
                .height = 720,
-               .hmax = 6600,
+               .hmax_min = 3300,
+               .vmax_min = 750,
                .link_freq_index = FREQ_INDEX_720P,
+               .ctrl_07 = IMX290_WINMODE_720P,
                .data = imx290_720p_settings,
                .data_size = ARRAY_SIZE(imx290_720p_settings),
+               .clk_cfg = imx290_720p_clock_config,
        },
 };
 
@@ -382,18 +536,24 @@ static const struct imx290_mode imx290_modes_4lanes[] = {
        {
                .width = 1920,
                .height = 1080,
-               .hmax = 2200,
+               .hmax_min = 2200,
+               .vmax_min = 1125,
                .link_freq_index = FREQ_INDEX_1080P,
+               .ctrl_07 = IMX290_WINMODE_1080P,
                .data = imx290_1080p_settings,
                .data_size = ARRAY_SIZE(imx290_1080p_settings),
+               .clk_cfg = imx290_1080p_clock_config,
        },
        {
                .width = 1280,
                .height = 720,
-               .hmax = 3300,
+               .hmax_min = 3300,
+               .vmax_min = 750,
                .link_freq_index = FREQ_INDEX_720P,
+               .ctrl_07 = IMX290_WINMODE_720P,
                .data = imx290_720p_settings,
                .data_size = ARRAY_SIZE(imx290_720p_settings),
+               .clk_cfg = imx290_720p_clock_config,
        },
 };
 
@@ -414,7 +574,7 @@ static inline int imx290_modes_num(const struct imx290 *imx290)
 }
 
 struct imx290_format_info {
-       u32 code;
+       u32 code[IMX290_VARIANT_MAX];
        u8 bpp;
        const struct imx290_regval *regs;
        unsigned int num_regs;
@@ -422,26 +582,33 @@ struct imx290_format_info {
 
 static const struct imx290_format_info imx290_formats[] = {
        {
-               .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+               .code = {
+                       [IMX290_VARIANT_COLOUR] = MEDIA_BUS_FMT_SRGGB10_1X10,
+                       [IMX290_VARIANT_MONO] = MEDIA_BUS_FMT_Y10_1X10
+               },
                .bpp = 10,
                .regs = imx290_10bit_settings,
                .num_regs = ARRAY_SIZE(imx290_10bit_settings),
        }, {
-               .code = MEDIA_BUS_FMT_SRGGB12_1X12,
+               .code = {
+                       [IMX290_VARIANT_COLOUR] = MEDIA_BUS_FMT_SRGGB12_1X12,
+                       [IMX290_VARIANT_MONO] = MEDIA_BUS_FMT_Y12_1X12
+               },
                .bpp = 12,
                .regs = imx290_12bit_settings,
                .num_regs = ARRAY_SIZE(imx290_12bit_settings),
        }
 };
 
-static const struct imx290_format_info *imx290_format_info(u32 code)
+static const struct imx290_format_info *
+imx290_format_info(const struct imx290 *imx290, u32 code)
 {
        unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(imx290_formats); ++i) {
                const struct imx290_format_info *info = &imx290_formats[i];
 
-               if (info->code == code)
+               if (info->code[imx290->model->colour_variant] == code)
                        return info;
        }
 
@@ -461,28 +628,30 @@ static int __always_unused imx290_read(struct imx290 *imx290, u32 addr, u32 *val
                              data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
        if (ret < 0) {
                dev_err(imx290->dev, "%u-bit read from 0x%04x failed: %d\n",
-                        ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
+                       ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
                         addr & IMX290_REG_ADDR_MASK, ret);
                return ret;
        }
 
-       *value = (data[2] << 16) | (data[1] << 8) | data[0];
+       *value = get_unaligned_le24(data);
        return 0;
 }
 
 static int imx290_write(struct imx290 *imx290, u32 addr, u32 value, int *err)
 {
-       u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
+       u8 data[3];
        int ret;
 
        if (err && *err)
                return *err;
 
+       put_unaligned_le24(value, data);
+
        ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
                               data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
        if (ret < 0) {
                dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",
-                        ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
+                       ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
                         addr & IMX290_REG_ADDR_MASK, ret);
                if (err)
                        *err = ret;
@@ -510,24 +679,33 @@ static int imx290_set_register_array(struct imx290 *imx290,
        return 0;
 }
 
+static int imx290_set_clock(struct imx290 *imx290)
+{
+       const struct imx290_mode *mode = imx290->current_mode;
+       enum imx290_clk_freq clk_idx = imx290->xclk_idx;
+       const struct imx290_clk_cfg *clk_cfg = &mode->clk_cfg[clk_idx];
+       int ret;
+
+       ret = imx290_set_register_array(imx290, xclk_regs[clk_idx],
+                                       IMX290_NUM_CLK_REGS);
+
+       imx290_write(imx290, IMX290_INCKSEL1, clk_cfg->incksel1, &ret);
+       imx290_write(imx290, IMX290_INCKSEL2, clk_cfg->incksel2, &ret);
+       imx290_write(imx290, IMX290_INCKSEL3, clk_cfg->incksel3, &ret);
+       imx290_write(imx290, IMX290_INCKSEL4, clk_cfg->incksel4, &ret);
+       imx290_write(imx290, IMX290_INCKSEL5, clk_cfg->incksel5, &ret);
+       imx290_write(imx290, IMX290_INCKSEL6, clk_cfg->incksel6, &ret);
+
+       return ret;
+}
+
 static int imx290_set_data_lanes(struct imx290 *imx290)
 {
        int ret = 0;
-       u32 frsel;
-
-       switch (imx290->nlanes) {
-       case 2:
-       default:
-               frsel = 0x02;
-               break;
-       case 4:
-               frsel = 0x01;
-               break;
-       }
 
        imx290_write(imx290, IMX290_PHY_LANE_NUM, imx290->nlanes - 1, &ret);
        imx290_write(imx290, IMX290_CSI_LANE_MODE, imx290->nlanes - 1, &ret);
-       imx290_write(imx290, IMX290_FR_FDG_SEL, frsel, &ret);
+       imx290_write(imx290, IMX290_FR_FDG_SEL, 0x01, &ret);
 
        return ret;
 }
@@ -536,19 +714,55 @@ static int imx290_set_black_level(struct imx290 *imx290,
                                  const struct v4l2_mbus_framefmt *format,
                                  unsigned int black_level, int *err)
 {
-       unsigned int bpp = imx290_format_info(format->code)->bpp;
+       unsigned int bpp = imx290_format_info(imx290, format->code)->bpp;
 
        return imx290_write(imx290, IMX290_BLKLEVEL,
                            black_level >> (16 - bpp), err);
 }
 
+static int imx290_set_csi_config(struct imx290 *imx290)
+{
+       const s64 *link_freqs = imx290_link_freqs_ptr(imx290);
+       const struct imx290_csi_cfg *csi_cfg;
+       int ret = 0;
+
+       switch (link_freqs[imx290->current_mode->link_freq_index]) {
+       case 445500000:
+               csi_cfg = &imx290_csi_445_5mhz;
+               break;
+       case 297000000:
+               csi_cfg = &imx290_csi_297mhz;
+               break;
+       case 222750000:
+               csi_cfg = &imx290_csi_222_75mhz;
+               break;
+       case 148500000:
+               csi_cfg = &imx290_csi_148_5mhz;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       imx290_write(imx290, IMX290_REPETITION, csi_cfg->repetition, &ret);
+       imx290_write(imx290, IMX290_TCLKPOST, csi_cfg->tclkpost, &ret);
+       imx290_write(imx290, IMX290_THSZERO, csi_cfg->thszero, &ret);
+       imx290_write(imx290, IMX290_THSPREPARE, csi_cfg->thsprepare, &ret);
+       imx290_write(imx290, IMX290_TCLKTRAIL, csi_cfg->tclktrail, &ret);
+       imx290_write(imx290, IMX290_THSTRAIL, csi_cfg->thstrail, &ret);
+       imx290_write(imx290, IMX290_TCLKZERO, csi_cfg->tclkzero, &ret);
+       imx290_write(imx290, IMX290_TCLKPREPARE, csi_cfg->tclkprepare, &ret);
+       imx290_write(imx290, IMX290_TLPX, csi_cfg->tlpx, &ret);
+
+       return ret;
+}
+
 static int imx290_setup_format(struct imx290 *imx290,
                               const struct v4l2_mbus_framefmt *format)
 {
        const struct imx290_format_info *info;
        int ret;
 
-       info = imx290_format_info(format->code);
+       info = imx290_format_info(imx290, format->code);
 
        ret = imx290_set_register_array(imx290, info->regs, info->num_regs);
        if (ret < 0) {
@@ -563,6 +777,16 @@ static int imx290_setup_format(struct imx290 *imx290,
 /* ----------------------------------------------------------------------------
  * Controls
  */
+static void imx290_exposure_update(struct imx290 *imx290,
+                                  const struct imx290_mode *mode)
+{
+       unsigned int exposure_max;
+
+       exposure_max = imx290->vblank->val + mode->height -
+                      IMX290_EXPOSURE_OFFSET;
+       __v4l2_ctrl_modify_range(imx290->exposure, 1, exposure_max, 1,
+                                exposure_max);
+}
 
 static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 {
@@ -570,7 +794,7 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
                                             struct imx290, ctrls);
        const struct v4l2_mbus_framefmt *format;
        struct v4l2_subdev_state *state;
-       int ret = 0;
+       int ret = 0, vmax;
 
        /*
         * Return immediately for controls that don't need to be applied to the
@@ -579,6 +803,11 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
        if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
                return 0;
 
+       if (ctrl->id == V4L2_CID_VBLANK) {
+               /* Changing vblank changes the allowed range for exposure. */
+               imx290_exposure_update(imx290, imx290->current_mode);
+       }
+
        /* V4L2 controls values will be applied only when power is already up */
        if (!pm_runtime_get_if_in_use(imx290->dev))
                return 0;
@@ -591,9 +820,23 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
                ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
                break;
 
+       case V4L2_CID_VBLANK:
+               ret = imx290_write(imx290, IMX290_VMAX,
+                                  ctrl->val + imx290->current_mode->height,
+                                  NULL);
+               /*
+                * Due to the way that exposure is programmed in this sensor in
+                * relation to VMAX, we have to reprogramme it whenever VMAX is
+                * changed.
+                * Update ctrl so that the V4L2_CID_EXPOSURE case can refer to
+                * it.
+                */
+               ctrl = imx290->exposure;
+               fallthrough;
        case V4L2_CID_EXPOSURE:
+               vmax = imx290->vblank->val + imx290->current_mode->height;
                ret = imx290_write(imx290, IMX290_SHS1,
-                                  IMX290_VMAX_DEFAULT - ctrl->val - 1, NULL);
+                                  vmax - ctrl->val - 1, NULL);
                break;
 
        case V4L2_CID_TEST_PATTERN:
@@ -612,6 +855,26 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
                }
                break;
 
+       case V4L2_CID_HBLANK:
+               ret = imx290_write(imx290, IMX290_HMAX,
+                                  ctrl->val + imx290->current_mode->width,
+                                  NULL);
+               break;
+
+       case V4L2_CID_HFLIP:
+       case V4L2_CID_VFLIP:
+       {
+               u32 reg;
+
+               reg = imx290->current_mode->ctrl_07;
+               if (imx290->hflip->val)
+                       reg |= IMX290_HREVERSE;
+               if (imx290->vflip->val)
+                       reg |= IMX290_VREVERSE;
+               ret = imx290_write(imx290, IMX290_CTRL_07, reg, NULL);
+               break;
+       }
+
        default:
                ret = -EINVAL;
                break;
@@ -642,20 +905,17 @@ static void imx290_ctrl_update(struct imx290 *imx290,
                               const struct v4l2_mbus_framefmt *format,
                               const struct imx290_mode *mode)
 {
-       unsigned int hblank = mode->hmax - mode->width;
-       unsigned int vblank = IMX290_VMAX_DEFAULT - mode->height;
-       s64 link_freq = imx290_link_freqs_ptr(imx290)[mode->link_freq_index];
-       u64 pixel_rate;
-
-       /* pixel rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
-       pixel_rate = link_freq * 2 * imx290->nlanes;
-       do_div(pixel_rate, imx290_format_info(format->code)->bpp);
+       unsigned int hblank_min = mode->hmax_min - mode->width;
+       unsigned int hblank_max = IMX290_HMAX_MAX - mode->width;
+       unsigned int vblank_min = mode->vmax_min - mode->height;
+       unsigned int vblank_max = IMX290_VMAX_MAX - mode->height;
 
        __v4l2_ctrl_s_ctrl(imx290->link_freq, mode->link_freq_index);
-       __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate, pixel_rate);
 
-       __v4l2_ctrl_modify_range(imx290->hblank, hblank, hblank, 1, hblank);
-       __v4l2_ctrl_modify_range(imx290->vblank, vblank, vblank, 1, vblank);
+       __v4l2_ctrl_modify_range(imx290->hblank, hblank_min, hblank_max, 1,
+                                hblank_min);
+       __v4l2_ctrl_modify_range(imx290->vblank, vblank_min, vblank_max, 1,
+                                vblank_min);
 }
 
 static int imx290_ctrl_init(struct imx290 *imx290)
@@ -667,7 +927,7 @@ static int imx290_ctrl_init(struct imx290 *imx290)
        if (ret < 0)
                return ret;
 
-       v4l2_ctrl_handler_init(&imx290->ctrls, 9);
+       v4l2_ctrl_handler_init(&imx290->ctrls, 11);
 
        /*
         * The sensor has an analog gain and a digital gain, both controlled
@@ -685,9 +945,13 @@ static int imx290_ctrl_init(struct imx290 *imx290)
        v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
                          V4L2_CID_ANALOGUE_GAIN, 0, 100, 1, 0);
 
-       v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
-                         V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,
-                         IMX290_VMAX_DEFAULT - 2);
+       /*
+        * Correct range will be determined through imx290_ctrl_update setting
+        * V4L2_CID_VBLANK.
+        */
+       imx290->exposure = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+                                            V4L2_CID_EXPOSURE, 1, 65535, 1,
+                                            65535);
 
        /*
         * Set the link frequency, pixel rate, horizontal blanking and vertical
@@ -702,24 +966,29 @@ static int imx290_ctrl_init(struct imx290 *imx290)
        if (imx290->link_freq)
                imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
-       imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
-                                              V4L2_CID_PIXEL_RATE,
-                                              1, INT_MAX, 1, 1);
+       v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops, V4L2_CID_PIXEL_RATE,
+                         IMX290_PIXEL_RATE, IMX290_PIXEL_RATE, 1,
+                         IMX290_PIXEL_RATE);
 
        v4l2_ctrl_new_std_menu_items(&imx290->ctrls, &imx290_ctrl_ops,
                                     V4L2_CID_TEST_PATTERN,
                                     ARRAY_SIZE(imx290_test_pattern_menu) - 1,
                                     0, 0, imx290_test_pattern_menu);
 
+       /*
+        * Actual range will be set from imx290_ctrl_update later in the probe.
+        */
        imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
                                           V4L2_CID_HBLANK, 1, 1, 1, 1);
-       if (imx290->hblank)
-               imx290->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
        imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
                                           V4L2_CID_VBLANK, 1, 1, 1, 1);
-       if (imx290->vblank)
-               imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+       imx290->hflip = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+                                         V4L2_CID_HFLIP, 0, 1, 1, 0);
+       imx290->vflip = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+                                         V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_cluster(2, &imx290->hflip);
 
        v4l2_ctrl_new_fwnode_properties(&imx290->ctrls, &imx290_ctrl_ops,
                                        &props);
@@ -748,17 +1017,37 @@ static int imx290_start_streaming(struct imx290 *imx290,
 
        /* Set init register settings */
        ret = imx290_set_register_array(imx290, imx290_global_init_settings,
-                                       ARRAY_SIZE(
-                                               imx290_global_init_settings));
+                                       ARRAY_SIZE(imx290_global_init_settings));
        if (ret < 0) {
                dev_err(imx290->dev, "Could not set init registers\n");
                return ret;
        }
 
+       /* Set mdel specific init register settings */
+       ret = imx290_set_register_array(imx290, imx290->model->init_regs,
+                                       imx290->model->init_regs_num);
+       if (ret < 0) {
+               dev_err(imx290->dev, "Could not set model specific init registers\n");
+               return ret;
+       }
+
+       /* Set clock parameters based on mode and xclk */
+       ret = imx290_set_clock(imx290);
+       if (ret < 0) {
+               dev_err(imx290->dev, "Could not set clocks - %d\n", ret);
+               return ret;
+       }
+
        /* Set data lane count */
        ret = imx290_set_data_lanes(imx290);
        if (ret < 0) {
-               dev_err(imx290->dev, "Could not set data lanes\n");
+               dev_err(imx290->dev, "Could not set data lanes - %d\n", ret);
+               return ret;
+       }
+
+       ret = imx290_set_csi_config(imx290);
+       if (ret < 0) {
+               dev_err(imx290->dev, "Could not set csi cfg - %d\n", ret);
                return ret;
        }
 
@@ -766,7 +1055,7 @@ static int imx290_start_streaming(struct imx290 *imx290,
        format = v4l2_subdev_get_pad_format(&imx290->sd, state, 0);
        ret = imx290_setup_format(imx290, format);
        if (ret < 0) {
-               dev_err(imx290->dev, "Could not set frame format\n");
+               dev_err(imx290->dev, "Could not set frame format - %d\n", ret);
                return ret;
        }
 
@@ -774,19 +1063,14 @@ static int imx290_start_streaming(struct imx290 *imx290,
        ret = imx290_set_register_array(imx290, imx290->current_mode->data,
                                        imx290->current_mode->data_size);
        if (ret < 0) {
-               dev_err(imx290->dev, "Could not set current mode\n");
+               dev_err(imx290->dev, "Could not set current mode - %d\n", ret);
                return ret;
        }
 
-       ret = imx290_write(imx290, IMX290_HMAX, imx290->current_mode->hmax,
-                          NULL);
-       if (ret)
-               return ret;
-
        /* Apply customized values from user */
        ret = __v4l2_ctrl_handler_setup(imx290->sd.ctrl_handler);
        if (ret) {
-               dev_err(imx290->dev, "Could not sync v4l2 controls\n");
+               dev_err(imx290->dev, "Could not sync v4l2 controls - %d\n", ret);
                return ret;
        }
 
@@ -835,6 +1119,13 @@ static int imx290_set_stream(struct v4l2_subdev *sd, int enable)
                pm_runtime_put_autosuspend(imx290->dev);
        }
 
+       /*
+        * vflip and hflip should not be changed during streaming as the sensor
+        * will produce an invalid frame.
+        */
+       __v4l2_ctrl_grab(imx290->vflip, enable);
+       __v4l2_ctrl_grab(imx290->hflip, enable);
+
 unlock:
        v4l2_subdev_unlock_state(state);
        return ret;
@@ -844,10 +1135,12 @@ static int imx290_enum_mbus_code(struct v4l2_subdev *sd,
                                 struct v4l2_subdev_state *sd_state,
                                 struct v4l2_subdev_mbus_code_enum *code)
 {
+       const struct imx290 *imx290 = to_imx290(sd);
+
        if (code->index >= ARRAY_SIZE(imx290_formats))
                return -EINVAL;
 
-       code->code = imx290_formats[code->index].code;
+       code->code = imx290_formats[code->index].code[imx290->model->colour_variant];
 
        return 0;
 }
@@ -859,7 +1152,7 @@ static int imx290_enum_frame_size(struct v4l2_subdev *sd,
        const struct imx290 *imx290 = to_imx290(sd);
        const struct imx290_mode *imx290_modes = imx290_modes_ptr(imx290);
 
-       if (!imx290_format_info(fse->code))
+       if (!imx290_format_info(imx290, fse->code))
                return -EINVAL;
 
        if (fse->index >= imx290_modes_num(imx290))
@@ -888,10 +1181,14 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
        fmt->format.width = mode->width;
        fmt->format.height = mode->height;
 
-       if (!imx290_format_info(fmt->format.code))
-               fmt->format.code = imx290_formats[0].code;
+       if (!imx290_format_info(imx290, fmt->format.code))
+               fmt->format.code = imx290_formats[0].code[imx290->model->colour_variant];
 
        fmt->format.field = V4L2_FIELD_NONE;
+       fmt->format.colorspace = V4L2_COLORSPACE_RAW;
+       fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_601;
+       fmt->format.quantization = V4L2_QUANTIZATION_FULL_RANGE;
+       fmt->format.xfer_func = V4L2_XFER_FUNC_NONE;
 
        format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
 
@@ -899,6 +1196,7 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
                imx290->current_mode = mode;
 
                imx290_ctrl_update(imx290, &fmt->format, mode);
+               imx290_exposure_update(imx290, mode);
        }
 
        *format = fmt->format;
@@ -910,16 +1208,23 @@ static int imx290_get_selection(struct v4l2_subdev *sd,
                                struct v4l2_subdev_state *sd_state,
                                struct v4l2_subdev_selection *sel)
 {
+       struct imx290 *imx290 = to_imx290(sd);
        struct v4l2_mbus_framefmt *format;
 
        switch (sel->target) {
        case V4L2_SEL_TGT_CROP: {
                format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
 
+               /*
+                * The sensor moves the readout by 1 pixel based on flips to
+                * keep the Bayer order the same.
+                */
                sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP
-                          + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2;
+                          + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2
+                          + imx290->vflip->val;
                sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT
-                           + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2;
+                           + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2
+                           + imx290->hflip->val;
                sel->r.width = format->width;
                sel->r.height = format->height;
 
@@ -964,6 +1269,11 @@ static int imx290_entity_init_cfg(struct v4l2_subdev *subdev,
        return 0;
 }
 
+static const struct v4l2_subdev_core_ops imx290_core_ops = {
+       .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+       .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
 static const struct v4l2_subdev_video_ops imx290_video_ops = {
        .s_stream = imx290_set_stream,
 };
@@ -978,6 +1288,7 @@ static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
 };
 
 static const struct v4l2_subdev_ops imx290_subdev_ops = {
+       .core = &imx290_core_ops,
        .video = &imx290_video_ops,
        .pad = &imx290_pad_ops,
 };
@@ -996,7 +1307,8 @@ static int imx290_subdev_init(struct imx290 *imx290)
        imx290->current_mode = &imx290_modes_ptr(imx290)[0];
 
        v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);
-       imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+                           V4L2_SUBDEV_FL_HAS_EVENTS;
        imx290->sd.dev = imx290->dev;
        imx290->sd.entity.ops = &imx290_subdev_entity_ops;
        imx290->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
@@ -1132,15 +1444,22 @@ static int imx290_init_clk(struct imx290 *imx290)
        u32 xclk_freq;
        int ret;
 
-       ret = fwnode_property_read_u32(dev_fwnode(imx290->dev),
-                                      "clock-frequency", &xclk_freq);
+       ret = device_property_read_u32(imx290->dev, "clock-frequency",
+                                      &xclk_freq);
        if (ret) {
                dev_err(imx290->dev, "Could not get xclk frequency\n");
                return ret;
        }
 
-       /* external clock must be 37.125 MHz */
-       if (xclk_freq != 37125000) {
+       /* external clock must be 37.125 MHz or 74.25MHz */
+       switch (xclk_freq) {
+       case 37125000:
+               imx290->xclk_idx = IMX290_CLK_37_125;
+               break;
+       case 74250000:
+               imx290->xclk_idx = IMX290_CLK_74_25;
+               break;
+       default:
                dev_err(imx290->dev, "External clock frequency %u is not supported\n",
                        xclk_freq);
                return -EINVAL;
@@ -1177,6 +1496,27 @@ static s64 imx290_check_link_freqs(const struct imx290 *imx290,
        return 0;
 }
 
+static const struct imx290_model_info imx290_models[] = {
+       [IMX290_MODEL_IMX290LQR] = {
+               .colour_variant = IMX290_VARIANT_COLOUR,
+               .init_regs = imx290_global_init_settings_290,
+               .init_regs_num = ARRAY_SIZE(imx290_global_init_settings_290),
+               .name = "imx290",
+       },
+       [IMX290_MODEL_IMX290LLR] = {
+               .colour_variant = IMX290_VARIANT_MONO,
+               .init_regs = imx290_global_init_settings_290,
+               .init_regs_num = ARRAY_SIZE(imx290_global_init_settings_290),
+               .name = "imx290",
+       },
+       [IMX290_MODEL_IMX327LQR] = {
+               .colour_variant = IMX290_VARIANT_COLOUR,
+               .init_regs = imx290_global_init_settings_327,
+               .init_regs_num = ARRAY_SIZE(imx290_global_init_settings_327),
+               .name = "imx327",
+       },
+};
+
 static int imx290_parse_dt(struct imx290 *imx290)
 {
        /* Only CSI2 is supported for now: */
@@ -1187,6 +1527,8 @@ static int imx290_parse_dt(struct imx290 *imx290)
        int ret;
        s64 fq;
 
+       imx290->model = of_device_get_match_data(imx290->dev);
+
        endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(imx290->dev), NULL);
        if (!endpoint) {
                dev_err(imx290->dev, "Endpoint node not found\n");
@@ -1260,7 +1602,7 @@ static int imx290_probe(struct i2c_client *client)
        imx290->xclk = devm_clk_get(dev, "xclk");
        if (IS_ERR(imx290->xclk))
                return dev_err_probe(dev, PTR_ERR(imx290->xclk),
-                                    "Could not get xclk");
+                                    "Could not get xclk\n");
 
        ret = imx290_get_regulators(dev, imx290);
        if (ret < 0)
@@ -1304,6 +1646,9 @@ static int imx290_probe(struct i2c_client *client)
        if (ret)
                goto err_pm;
 
+       v4l2_i2c_subdev_set_name(&imx290->sd, client,
+                                imx290->model->name, NULL);
+
        /*
         * Finally, register the V4L2 subdev. This must be done after
         * initializing everything as the subdev can be used immediately after
@@ -1352,8 +1697,21 @@ static void imx290_remove(struct i2c_client *client)
 }
 
 static const struct of_device_id imx290_of_match[] = {
-       { .compatible = "sony,imx290" },
-       { /* sentinel */ }
+       {
+               /* Deprecated - synonym for "sony,imx290lqr" */
+               .compatible = "sony,imx290",
+               .data = &imx290_models[IMX290_MODEL_IMX290LQR],
+       }, {
+               .compatible = "sony,imx290lqr",
+               .data = &imx290_models[IMX290_MODEL_IMX290LQR],
+       }, {
+               .compatible = "sony,imx290llr",
+               .data = &imx290_models[IMX290_MODEL_IMX290LLR],
+       }, {
+               .compatible = "sony,imx327lqr",
+               .data = &imx290_models[IMX290_MODEL_IMX327LQR],
+       },
+       { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, imx290_of_match);
 
index 3c12b6edeac9121d98fd336fd767c9300a348abe..4f22c0515ef8dcef6131276c5d888e2488dc793e 100644 (file)
@@ -685,15 +685,6 @@ static int imx296_enum_frame_size(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int imx296_get_format(struct v4l2_subdev *sd,
-                            struct v4l2_subdev_state *state,
-                            struct v4l2_subdev_format *fmt)
-{
-       fmt->format = *v4l2_subdev_get_pad_format(sd, state, fmt->pad);
-
-       return 0;
-}
-
 static int imx296_set_format(struct v4l2_subdev *sd,
                             struct v4l2_subdev_state *state,
                             struct v4l2_subdev_format *fmt)
@@ -845,7 +836,7 @@ static const struct v4l2_subdev_video_ops imx296_subdev_video_ops = {
 static const struct v4l2_subdev_pad_ops imx296_subdev_pad_ops = {
        .enum_mbus_code = imx296_enum_mbus_code,
        .enum_frame_size = imx296_enum_frame_size,
-       .get_fmt = imx296_get_format,
+       .get_fmt = v4l2_subdev_get_fmt,
        .set_fmt = imx296_set_format,
        .get_selection = imx296_get_selection,
        .set_selection = imx296_set_selection,
index 7b0a9086447d1fff0d4b80b31d118b5d38904542..309c706114d2862dc5844c76e7bc2be30d815ff6 100644 (file)
@@ -79,7 +79,6 @@ struct imx334_reg_list {
  * struct imx334_mode - imx334 sensor mode structure
  * @width: Frame width
  * @height: Frame height
- * @code: Format code
  * @hblank: Horizontal blanking in lines
  * @vblank: Vertical blanking in lines
  * @vblank_min: Minimal vertical blanking in lines
@@ -91,7 +90,6 @@ struct imx334_reg_list {
 struct imx334_mode {
        u32 width;
        u32 height;
-       u32 code;
        u32 hblank;
        u32 vblank;
        u32 vblank_min;
@@ -119,6 +117,7 @@ struct imx334_mode {
  * @vblank: Vertical blanking in lines
  * @cur_mode: Pointer to current selected sensor mode
  * @mutex: Mutex for serializing sensor controls
+ * @cur_code: current selected format code
  * @streaming: Flag indicating streaming state
  */
 struct imx334 {
@@ -140,6 +139,7 @@ struct imx334 {
        u32 vblank;
        const struct imx334_mode *cur_mode;
        struct mutex mutex;
+       u32 cur_code;
        bool streaming;
 };
 
@@ -147,7 +147,170 @@ static const s64 link_freq[] = {
        IMX334_LINK_FREQ,
 };
 
-/* Sensor mode registers */
+/* Sensor mode registers for 1920x1080@30fps */
+static const struct imx334_reg mode_1920x1080_regs[] = {
+       {0x3000, 0x01},
+       {0x3018, 0x04},
+       {0x3030, 0xca},
+       {0x3031, 0x08},
+       {0x3032, 0x00},
+       {0x3034, 0x4c},
+       {0x3035, 0x04},
+       {0x302c, 0xf0},
+       {0x302d, 0x03},
+       {0x302e, 0x80},
+       {0x302f, 0x07},
+       {0x3074, 0xcc},
+       {0x3075, 0x02},
+       {0x308e, 0xcd},
+       {0x308f, 0x02},
+       {0x3076, 0x38},
+       {0x3077, 0x04},
+       {0x3090, 0x38},
+       {0x3091, 0x04},
+       {0x3308, 0x38},
+       {0x3309, 0x04},
+       {0x30C6, 0x00},
+       {0x30c7, 0x00},
+       {0x30ce, 0x00},
+       {0x30cf, 0x00},
+       {0x30d8, 0x18},
+       {0x30d9, 0x0a},
+       {0x304c, 0x00},
+       {0x304e, 0x00},
+       {0x304f, 0x00},
+       {0x3050, 0x00},
+       {0x30b6, 0x00},
+       {0x30b7, 0x00},
+       {0x3116, 0x08},
+       {0x3117, 0x00},
+       {0x31a0, 0x20},
+       {0x31a1, 0x0f},
+       {0x300c, 0x3b},
+       {0x300d, 0x29},
+       {0x314c, 0x29},
+       {0x314d, 0x01},
+       {0x315a, 0x06},
+       {0x3168, 0xa0},
+       {0x316a, 0x7e},
+       {0x319e, 0x02},
+       {0x3199, 0x00},
+       {0x319d, 0x00},
+       {0x31dd, 0x03},
+       {0x3300, 0x00},
+       {0x341c, 0xff},
+       {0x341d, 0x01},
+       {0x3a01, 0x03},
+       {0x3a18, 0x7f},
+       {0x3a19, 0x00},
+       {0x3a1a, 0x37},
+       {0x3a1b, 0x00},
+       {0x3a1c, 0x37},
+       {0x3a1d, 0x00},
+       {0x3a1e, 0xf7},
+       {0x3a1f, 0x00},
+       {0x3a20, 0x3f},
+       {0x3a21, 0x00},
+       {0x3a20, 0x6f},
+       {0x3a21, 0x00},
+       {0x3a20, 0x3f},
+       {0x3a21, 0x00},
+       {0x3a20, 0x5f},
+       {0x3a21, 0x00},
+       {0x3a20, 0x2f},
+       {0x3a21, 0x00},
+       {0x3078, 0x02},
+       {0x3079, 0x00},
+       {0x307a, 0x00},
+       {0x307b, 0x00},
+       {0x3080, 0x02},
+       {0x3081, 0x00},
+       {0x3082, 0x00},
+       {0x3083, 0x00},
+       {0x3088, 0x02},
+       {0x3094, 0x00},
+       {0x3095, 0x00},
+       {0x3096, 0x00},
+       {0x309b, 0x02},
+       {0x309c, 0x00},
+       {0x309d, 0x00},
+       {0x309e, 0x00},
+       {0x30a4, 0x00},
+       {0x30a5, 0x00},
+       {0x3288, 0x21},
+       {0x328a, 0x02},
+       {0x3414, 0x05},
+       {0x3416, 0x18},
+       {0x35Ac, 0x0e},
+       {0x3648, 0x01},
+       {0x364a, 0x04},
+       {0x364c, 0x04},
+       {0x3678, 0x01},
+       {0x367c, 0x31},
+       {0x367e, 0x31},
+       {0x3708, 0x02},
+       {0x3714, 0x01},
+       {0x3715, 0x02},
+       {0x3716, 0x02},
+       {0x3717, 0x02},
+       {0x371c, 0x3d},
+       {0x371d, 0x3f},
+       {0x372c, 0x00},
+       {0x372d, 0x00},
+       {0x372e, 0x46},
+       {0x372f, 0x00},
+       {0x3730, 0x89},
+       {0x3731, 0x00},
+       {0x3732, 0x08},
+       {0x3733, 0x01},
+       {0x3734, 0xfe},
+       {0x3735, 0x05},
+       {0x375d, 0x00},
+       {0x375e, 0x00},
+       {0x375f, 0x61},
+       {0x3760, 0x06},
+       {0x3768, 0x1b},
+       {0x3769, 0x1b},
+       {0x376a, 0x1a},
+       {0x376b, 0x19},
+       {0x376c, 0x18},
+       {0x376d, 0x14},
+       {0x376e, 0x0f},
+       {0x3776, 0x00},
+       {0x3777, 0x00},
+       {0x3778, 0x46},
+       {0x3779, 0x00},
+       {0x377a, 0x08},
+       {0x377b, 0x01},
+       {0x377c, 0x45},
+       {0x377d, 0x01},
+       {0x377e, 0x23},
+       {0x377f, 0x02},
+       {0x3780, 0xd9},
+       {0x3781, 0x03},
+       {0x3782, 0xf5},
+       {0x3783, 0x06},
+       {0x3784, 0xa5},
+       {0x3788, 0x0f},
+       {0x378a, 0xd9},
+       {0x378b, 0x03},
+       {0x378c, 0xeb},
+       {0x378d, 0x05},
+       {0x378e, 0x87},
+       {0x378f, 0x06},
+       {0x3790, 0xf5},
+       {0x3792, 0x43},
+       {0x3794, 0x7a},
+       {0x3796, 0xa1},
+       {0x37b0, 0x37},
+       {0x3e04, 0x0e},
+       {0x30e8, 0x50},
+       {0x30e9, 0x00},
+       {0x3e04, 0x0e},
+       {0x3002, 0x00},
+};
+
+/* Sensor mode registers for 3840x2160@30fps */
 static const struct imx334_reg mode_3840x2160_regs[] = {
        {0x3000, 0x01},
        {0x3002, 0x00},
@@ -166,6 +329,7 @@ static const struct imx334_reg mode_3840x2160_regs[] = {
        {0x3288, 0x21},
        {0x328a, 0x02},
        {0x302c, 0x3c},
+       {0x302d, 0x00},
        {0x302e, 0x00},
        {0x302f, 0x0f},
        {0x3076, 0x70},
@@ -240,23 +404,75 @@ static const struct imx334_reg mode_3840x2160_regs[] = {
        {0x3794, 0x7a},
        {0x3796, 0xa1},
        {0x3e04, 0x0e},
+       {0x319e, 0x00},
        {0x3a00, 0x01},
+       {0x3a18, 0xbf},
+       {0x3a19, 0x00},
+       {0x3a1a, 0x67},
+       {0x3a1b, 0x00},
+       {0x3a1c, 0x6f},
+       {0x3a1d, 0x00},
+       {0x3a1e, 0xd7},
+       {0x3a1f, 0x01},
+       {0x3a20, 0x6f},
+       {0x3a21, 0x00},
+       {0x3a22, 0xcf},
+       {0x3a23, 0x00},
+       {0x3a24, 0x6f},
+       {0x3a25, 0x00},
+       {0x3a26, 0xb7},
+       {0x3a27, 0x00},
+       {0x3a28, 0x5f},
+       {0x3a29, 0x00},
+};
+
+static const struct imx334_reg raw10_framefmt_regs[] = {
+       {0x3050, 0x00},
+       {0x319d, 0x00},
+       {0x341c, 0xff},
+       {0x341d, 0x01},
+};
+
+static const struct imx334_reg raw12_framefmt_regs[] = {
+       {0x3050, 0x01},
+       {0x319d, 0x01},
+       {0x341c, 0x47},
+       {0x341d, 0x00},
+};
+
+static const u32 imx334_mbus_codes[] = {
+       MEDIA_BUS_FMT_SRGGB12_1X12,
+       MEDIA_BUS_FMT_SRGGB10_1X10,
 };
 
 /* Supported sensor mode configurations */
-static const struct imx334_mode supported_mode = {
-       .width = 3840,
-       .height = 2160,
-       .hblank = 560,
-       .vblank = 2340,
-       .vblank_min = 90,
-       .vblank_max = 132840,
-       .pclk = 594000000,
-       .link_freq_idx = 0,
-       .code = MEDIA_BUS_FMT_SRGGB12_1X12,
-       .reg_list = {
-               .num_of_regs = ARRAY_SIZE(mode_3840x2160_regs),
-               .regs = mode_3840x2160_regs,
+static const struct imx334_mode supported_modes[] = {
+       {
+               .width = 3840,
+               .height = 2160,
+               .hblank = 560,
+               .vblank = 2340,
+               .vblank_min = 90,
+               .vblank_max = 132840,
+               .pclk = 594000000,
+               .link_freq_idx = 0,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_3840x2160_regs),
+                       .regs = mode_3840x2160_regs,
+               },
+       }, {
+               .width = 1920,
+               .height = 1080,
+               .hblank = 2480,
+               .vblank = 1170,
+               .vblank_min = 45,
+               .vblank_max = 132840,
+               .pclk = 297000000,
+               .link_freq_idx = 0,
+               .reg_list = {
+                       .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),
+                       .regs = mode_1920x1080_regs,
+               },
        },
 };
 
@@ -382,7 +598,8 @@ static int imx334_update_controls(struct imx334 *imx334,
        if (ret)
                return ret;
 
-       ret = __v4l2_ctrl_s_ctrl(imx334->hblank_ctrl, mode->hblank);
+       ret = __v4l2_ctrl_modify_range(imx334->hblank_ctrl, mode->hblank,
+                                      mode->hblank, 1, mode->hblank);
        if (ret)
                return ret;
 
@@ -480,6 +697,9 @@ static int imx334_set_ctrl(struct v4l2_ctrl *ctrl)
 
                pm_runtime_put(imx334->dev);
 
+               break;
+       case V4L2_CID_HBLANK:
+               ret = 0;
                break;
        default:
                dev_err(imx334->dev, "Invalid control %d", ctrl->id);
@@ -494,6 +714,18 @@ static const struct v4l2_ctrl_ops imx334_ctrl_ops = {
        .s_ctrl = imx334_set_ctrl,
 };
 
+static int imx334_get_format_code(struct imx334 *imx334, u32 code)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(imx334_mbus_codes); i++) {
+               if (imx334_mbus_codes[i] == code)
+                       return imx334_mbus_codes[i];
+       }
+
+       return imx334_mbus_codes[0];
+}
+
 /**
  * imx334_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes
  * @sd: pointer to imx334 V4L2 sub-device structure
@@ -506,10 +738,10 @@ static int imx334_enum_mbus_code(struct v4l2_subdev *sd,
                                 struct v4l2_subdev_state *sd_state,
                                 struct v4l2_subdev_mbus_code_enum *code)
 {
-       if (code->index > 0)
+       if (code->index >= ARRAY_SIZE(imx334_mbus_codes))
                return -EINVAL;
 
-       code->code = supported_mode.code;
+       code->code = imx334_mbus_codes[code->index];
 
        return 0;
 }
@@ -526,15 +758,20 @@ static int imx334_enum_frame_size(struct v4l2_subdev *sd,
                                  struct v4l2_subdev_state *sd_state,
                                  struct v4l2_subdev_frame_size_enum *fsize)
 {
-       if (fsize->index > 0)
+       struct imx334 *imx334 = to_imx334(sd);
+       u32 code;
+
+       if (fsize->index >= ARRAY_SIZE(supported_modes))
                return -EINVAL;
 
-       if (fsize->code != supported_mode.code)
+       code = imx334_get_format_code(imx334, fsize->code);
+
+       if (fsize->code != code)
                return -EINVAL;
 
-       fsize->min_width = supported_mode.width;
+       fsize->min_width = supported_modes[fsize->index].width;
        fsize->max_width = fsize->min_width;
-       fsize->min_height = supported_mode.height;
+       fsize->min_height = supported_modes[fsize->index].height;
        fsize->max_height = fsize->min_height;
 
        return 0;
@@ -553,7 +790,6 @@ static void imx334_fill_pad_format(struct imx334 *imx334,
 {
        fmt->format.width = mode->width;
        fmt->format.height = mode->height;
-       fmt->format.code = mode->code;
        fmt->format.field = V4L2_FIELD_NONE;
        fmt->format.colorspace = V4L2_COLORSPACE_RAW;
        fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
@@ -583,6 +819,7 @@ static int imx334_get_pad_format(struct v4l2_subdev *sd,
                framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
                fmt->format = *framefmt;
        } else {
+               fmt->format.code = imx334->cur_code;
                imx334_fill_pad_format(imx334, imx334->cur_mode, fmt);
        }
 
@@ -609,15 +846,21 @@ static int imx334_set_pad_format(struct v4l2_subdev *sd,
 
        mutex_lock(&imx334->mutex);
 
-       mode = &supported_mode;
+       mode = v4l2_find_nearest_size(supported_modes,
+                                     ARRAY_SIZE(supported_modes),
+                                     width, height,
+                                     fmt->format.width, fmt->format.height);
+
        imx334_fill_pad_format(imx334, mode, fmt);
+       fmt->format.code = imx334_get_format_code(imx334, fmt->format.code);
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
                struct v4l2_mbus_framefmt *framefmt;
 
                framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
                *framefmt = fmt->format;
-       } else {
+       } else if (imx334->cur_mode != mode || imx334->cur_code != fmt->format.code) {
+               imx334->cur_code = fmt->format.code;
                ret = imx334_update_controls(imx334, mode);
                if (!ret)
                        imx334->cur_mode = mode;
@@ -642,11 +885,26 @@ static int imx334_init_pad_cfg(struct v4l2_subdev *sd,
        struct v4l2_subdev_format fmt = { 0 };
 
        fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-       imx334_fill_pad_format(imx334, &supported_mode, &fmt);
+       imx334_fill_pad_format(imx334, &supported_modes[0], &fmt);
 
        return imx334_set_pad_format(sd, sd_state, &fmt);
 }
 
+static int imx334_set_framefmt(struct imx334 *imx334)
+{
+       switch (imx334->cur_code) {
+       case MEDIA_BUS_FMT_SRGGB10_1X10:
+               return imx334_write_regs(imx334, raw10_framefmt_regs,
+                                        ARRAY_SIZE(raw10_framefmt_regs));
+
+       case MEDIA_BUS_FMT_SRGGB12_1X12:
+               return imx334_write_regs(imx334, raw12_framefmt_regs,
+                                        ARRAY_SIZE(raw12_framefmt_regs));
+       }
+
+       return -EINVAL;
+}
+
 /**
  * imx334_start_streaming() - Start sensor stream
  * @imx334: pointer to imx334 device
@@ -667,6 +925,13 @@ static int imx334_start_streaming(struct imx334 *imx334)
                return ret;
        }
 
+       ret = imx334_set_framefmt(imx334);
+       if (ret) {
+               dev_err(imx334->dev, "%s failed to set frame format: %d\n",
+                       __func__, ret);
+               return ret;
+       }
+
        /* Setup handler will write actual exposure and gain */
        ret =  __v4l2_ctrl_handler_setup(imx334->sd.ctrl_handler);
        if (ret) {
@@ -1037,7 +1302,8 @@ static int imx334_probe(struct i2c_client *client)
        }
 
        /* Set default mode to max resolution */
-       imx334->cur_mode = &supported_mode;
+       imx334->cur_mode = &supported_modes[0];
+       imx334->cur_code = imx334_mbus_codes[0];
        imx334->vblank = imx334->cur_mode->vblank;
 
        ret = imx334_init_controls(imx334);
diff --git a/drivers/media/i2c/m5mols/Kconfig b/drivers/media/i2c/m5mols/Kconfig
deleted file mode 100644 (file)
index 7f0af32..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_M5MOLS
-       tristate "Fujitsu M-5MOLS 8MP sensor support"
-       depends on I2C && VIDEO_DEV
-       select MEDIA_CONTROLLER
-       select VIDEO_V4L2_SUBDEV_API
-       help
-         This driver supports Fujitsu M-5MOLS camera sensor with ISP
diff --git a/drivers/media/i2c/m5mols/Makefile b/drivers/media/i2c/m5mols/Makefile
deleted file mode 100644 (file)
index 13fa8ec..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-m5mols-objs    := m5mols_core.o m5mols_controls.o m5mols_capture.o
-
-obj-$(CONFIG_VIDEO_M5MOLS)             += m5mols.o
diff --git a/drivers/media/i2c/m5mols/m5mols.h b/drivers/media/i2c/m5mols/m5mols.h
deleted file mode 100644 (file)
index d8545d2..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Header for M-5MOLS 8M Pixel camera sensor with ISP
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim <riverful.kim@samsung.com>
- *
- * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
- */
-
-#ifndef M5MOLS_H
-#define M5MOLS_H
-
-#include <linux/sizes.h>
-#include <linux/gpio/consumer.h>
-#include <media/v4l2-subdev.h>
-#include "m5mols_reg.h"
-
-
-/* An amount of data transmitted in addition to the value
- * determined by CAPP_JPEG_SIZE_MAX register.
- */
-#define M5MOLS_JPEG_TAGS_SIZE          0x20000
-#define M5MOLS_MAIN_JPEG_SIZE_MAX      (5 * SZ_1M)
-
-extern int m5mols_debug;
-
-enum m5mols_restype {
-       M5MOLS_RESTYPE_MONITOR,
-       M5MOLS_RESTYPE_CAPTURE,
-       M5MOLS_RESTYPE_MAX,
-};
-
-/**
- * struct m5mols_resolution - structure for the resolution
- * @type: resolution type according to the pixel code
- * @width: width of the resolution
- * @height: height of the resolution
- * @reg: resolution preset register value
- */
-struct m5mols_resolution {
-       u8 reg;
-       enum m5mols_restype type;
-       u16 width;
-       u16 height;
-};
-
-/**
- * struct m5mols_exif - structure for the EXIF information of M-5MOLS
- * @exposure_time: exposure time register value
- * @shutter_speed: speed of the shutter register value
- * @aperture: aperture register value
- * @brightness: brightness register value
- * @exposure_bias: it calls also EV bias
- * @iso_speed: ISO register value
- * @flash: status register value of the flash
- * @sdr: status register value of the Subject Distance Range
- * @qval: not written exact meaning in document
- */
-struct m5mols_exif {
-       u32 exposure_time;
-       u32 shutter_speed;
-       u32 aperture;
-       u32 brightness;
-       u32 exposure_bias;
-       u16 iso_speed;
-       u16 flash;
-       u16 sdr;
-       u16 qval;
-};
-
-/**
- * struct m5mols_capture - Structure for the capture capability
- * @exif: EXIF information
- * @buf_size: internal JPEG frame buffer size, in bytes
- * @main: size in bytes of the main image
- * @thumb: size in bytes of the thumb image, if it was accompanied
- * @total: total size in bytes of the produced image
- */
-struct m5mols_capture {
-       struct m5mols_exif exif;
-       unsigned int buf_size;
-       u32 main;
-       u32 thumb;
-       u32 total;
-};
-
-/**
- * struct m5mols_scenemode - structure for the scenemode capability
- * @metering: metering light register value
- * @ev_bias: EV bias register value
- * @wb_mode: mode which means the WhiteBalance is Auto or Manual
- * @wb_preset: whitebalance preset register value in the Manual mode
- * @chroma_en: register value whether the Chroma capability is enabled or not
- * @chroma_lvl: chroma's level register value
- * @edge_en: register value Whether the Edge capability is enabled or not
- * @edge_lvl: edge's level register value
- * @af_range: Auto Focus's range
- * @fd_mode: Face Detection mode
- * @mcc: Multi-axis Color Conversion which means emotion color
- * @light: status of the Light
- * @flash: status of the Flash
- * @tone: Tone color which means Contrast
- * @iso: ISO register value
- * @capt_mode: Mode of the Image Stabilization while the camera capturing
- * @wdr: Wide Dynamic Range register value
- *
- * The each value according to each scenemode is recommended in the documents.
- */
-struct m5mols_scenemode {
-       u8 metering;
-       u8 ev_bias;
-       u8 wb_mode;
-       u8 wb_preset;
-       u8 chroma_en;
-       u8 chroma_lvl;
-       u8 edge_en;
-       u8 edge_lvl;
-       u8 af_range;
-       u8 fd_mode;
-       u8 mcc;
-       u8 light;
-       u8 flash;
-       u8 tone;
-       u8 iso;
-       u8 capt_mode;
-       u8 wdr;
-};
-
-#define VERSION_STRING_SIZE    22
-
-/**
- * struct m5mols_version - firmware version information
- * @customer:  customer information
- * @project:   version of project information according to customer
- * @fw:                firmware revision
- * @hw:                hardware revision
- * @param:     version of the parameter
- * @awb:       Auto WhiteBalance algorithm version
- * @str:       information about manufacturer and packaging vendor
- * @af:                Auto Focus version
- *
- * The register offset starts the customer version at 0x0, and it ends
- * the awb version at 0x09. The customer, project information occupies 1 bytes
- * each. And also the fw, hw, param, awb each requires 2 bytes. The str is
- * unique string associated with firmware's version. It includes information
- * about manufacturer and the vendor of the sensor's packaging. The least
- * significant 2 bytes of the string indicate packaging manufacturer.
- */
-struct m5mols_version {
-       u8      customer;
-       u8      project;
-       u16     fw;
-       u16     hw;
-       u16     param;
-       u16     awb;
-       u8      str[VERSION_STRING_SIZE];
-       u8      af;
-};
-
-/**
- * struct m5mols_info - M-5MOLS driver data structure
- * @pdata: platform data
- * @sd: v4l-subdev instance
- * @pad: media pad
- * @irq_waitq: waitqueue for the capture
- * @irq_done: set to 1 in the interrupt handler
- * @handle: control handler
- * @auto_exposure: auto/manual exposure control
- * @exposure_bias: exposure compensation control
- * @exposure: manual exposure control
- * @metering: exposure metering control
- * @auto_iso: auto/manual ISO sensitivity control
- * @iso: manual ISO sensitivity control
- * @auto_wb: auto white balance control
- * @lock_3a: 3A lock control
- * @colorfx: color effect control
- * @saturation: saturation control
- * @zoom: zoom control
- * @wdr: wide dynamic range control
- * @stabilization: image stabilization control
- * @jpeg_quality: JPEG compression quality control
- * @set_power: optional power callback to the board code
- * @reset: GPIO driving the reset pin of M-5MOLS
- * @lock: mutex protecting the structure fields below
- * @ffmt: current fmt according to resolution type
- * @res_type: current resolution type
- * @ver: information of the version
- * @cap: the capture mode attributes
- * @isp_ready: 1 when the ISP controller has completed booting
- * @power: current sensor's power status
- * @ctrl_sync: 1 when the control handler state is restored in H/W
- * @resolution:        register value for current resolution
- * @mode: register value for current operation mode
- */
-struct m5mols_info {
-       const struct m5mols_platform_data *pdata;
-       struct v4l2_subdev sd;
-       struct media_pad pad;
-
-       wait_queue_head_t irq_waitq;
-       atomic_t irq_done;
-
-       struct v4l2_ctrl_handler handle;
-       struct {
-               /* exposure/exposure bias/auto exposure cluster */
-               struct v4l2_ctrl *auto_exposure;
-               struct v4l2_ctrl *exposure_bias;
-               struct v4l2_ctrl *exposure;
-               struct v4l2_ctrl *metering;
-       };
-       struct {
-               /* iso/auto iso cluster */
-               struct v4l2_ctrl *auto_iso;
-               struct v4l2_ctrl *iso;
-       };
-       struct v4l2_ctrl *auto_wb;
-
-       struct v4l2_ctrl *lock_3a;
-       struct v4l2_ctrl *colorfx;
-       struct v4l2_ctrl *saturation;
-       struct v4l2_ctrl *zoom;
-       struct v4l2_ctrl *wdr;
-       struct v4l2_ctrl *stabilization;
-       struct v4l2_ctrl *jpeg_quality;
-
-       int (*set_power)(struct device *dev, int on);
-       struct gpio_desc *reset;
-
-       struct mutex lock;
-
-       struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
-       int res_type;
-
-       struct m5mols_version ver;
-       struct m5mols_capture cap;
-
-       unsigned int isp_ready:1;
-       unsigned int power:1;
-       unsigned int ctrl_sync:1;
-
-       u8 resolution;
-       u8 mode;
-};
-
-#define is_available_af(__info)        (__info->ver.af)
-#define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code)
-#define is_manufacturer(__info, __manufacturer)        \
-                               (__info->ver.str[0] == __manufacturer[0] && \
-                                __info->ver.str[1] == __manufacturer[1])
-/*
- * I2C operation of the M-5MOLS
- *
- * The I2C read operation of the M-5MOLS requires 2 messages. The first
- * message sends the information about the command, command category, and total
- * message size. The second message is used to retrieve the data specified in
- * the first message
- *
- *   1st message                                2nd message
- *   +-------+---+----------+-----+-------+     +------+------+------+------+
- *   | size1 | R | category | cmd | size2 |     | d[0] | d[1] | d[2] | d[3] |
- *   +-------+---+----------+-----+-------+     +------+------+------+------+
- *   - size1: message data size(5 in this case)
- *   - size2: desired buffer size of the 2nd message
- *   - d[0..3]: according to size2
- *
- * The I2C write operation needs just one message. The message includes
- * category, command, total size, and desired data.
- *
- *   1st message
- *   +-------+---+----------+-----+------+------+------+------+
- *   | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] |
- *   +-------+---+----------+-----+------+------+------+------+
- *   - d[0..3]: according to size1
- */
-int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
-int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
-int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
-int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
-
-int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
-                    int timeout);
-
-/* Mask value for busy waiting until M-5MOLS I2C interface is initialized */
-#define M5MOLS_I2C_RDY_WAIT_FL         (1 << 16)
-/* ISP state transition timeout, in ms */
-#define M5MOLS_MODE_CHANGE_TIMEOUT     200
-#define M5MOLS_BUSY_WAIT_DEF_TIMEOUT   250
-
-/*
- * Mode operation of the M-5MOLS
- *
- * Changing the mode of the M-5MOLS is needed right executing order.
- * There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed
- * by user. There are various categories associated with each mode.
- *
- * +============================================================+
- * | mode      | category                                      |
- * +============================================================+
- * | FLASH     | FLASH(only after Stand-by or Power-on)        |
- * | SYSTEM    | SYSTEM(only after sensor arm-booting)         |
- * | PARAMETER | PARAMETER                                     |
- * | MONITOR   | MONITOR(preview), Auto Focus, Face Detection  |
- * | CAPTURE   | Single CAPTURE, Preview(recording)            |
- * +============================================================+
- *
- * The available executing order between each modes are as follows:
- *   PARAMETER <---> MONITOR <---> CAPTURE
- */
-int m5mols_set_mode(struct m5mols_info *info, u8 mode);
-
-int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg);
-int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout);
-int m5mols_restore_controls(struct m5mols_info *info);
-int m5mols_start_capture(struct m5mols_info *info);
-int m5mols_do_scenemode(struct m5mols_info *info, u8 mode);
-int m5mols_lock_3a(struct m5mols_info *info, bool lock);
-int m5mols_set_ctrl(struct v4l2_ctrl *ctrl);
-int m5mols_init_controls(struct v4l2_subdev *sd);
-
-/* The firmware function */
-int m5mols_update_fw(struct v4l2_subdev *sd,
-                    int (*set_power)(struct m5mols_info *, bool));
-
-static inline struct m5mols_info *to_m5mols(struct v4l2_subdev *subdev)
-{
-       return container_of(subdev, struct m5mols_info, sd);
-}
-
-static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
-{
-       struct m5mols_info *info = container_of(ctrl->handler,
-                                               struct m5mols_info, handle);
-       return &info->sd;
-}
-
-static inline void m5mols_set_ctrl_mode(struct v4l2_ctrl *ctrl,
-                                       unsigned int mode)
-{
-       ctrl->priv = (void *)(uintptr_t)mode;
-}
-
-static inline unsigned int m5mols_get_ctrl_mode(struct v4l2_ctrl *ctrl)
-{
-       return (unsigned int)(uintptr_t)ctrl->priv;
-}
-
-#endif /* M5MOLS_H */
diff --git a/drivers/media/i2c/m5mols/m5mols_capture.c b/drivers/media/i2c/m5mols/m5mols_capture.c
deleted file mode 100644 (file)
index 275c5b2..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-/*
- * The Capture code for Fujitsu M-5MOLS ISP
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim <riverful.kim@samsung.com>
- *
- * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/regulator/consumer.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-subdev.h>
-#include <media/i2c/m5mols.h>
-#include <media/drv-intf/exynos-fimc.h>
-
-#include "m5mols.h"
-#include "m5mols_reg.h"
-
-/**
- * m5mols_read_rational - I2C read of a rational number
- * @sd: sub-device, as pointed by struct v4l2_subdev
- * @addr_num: numerator register
- * @addr_den: denominator register
- * @val: place to store the division result
- *
- * Read numerator and denominator from registers @addr_num and @addr_den
- * respectively and return the division result in @val.
- */
-static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num,
-                               u32 addr_den, u32 *val)
-{
-       u32 num, den;
-
-       int ret = m5mols_read_u32(sd, addr_num, &num);
-       if (!ret)
-               ret = m5mols_read_u32(sd, addr_den, &den);
-       if (ret)
-               return ret;
-       *val = den == 0 ? 0 : num / den;
-       return ret;
-}
-
-/**
- * m5mols_capture_info - Gather captured image information
- * @info: M-5MOLS driver data structure
- *
- * For now it gathers only EXIF information and file size.
- */
-static int m5mols_capture_info(struct m5mols_info *info)
-{
-       struct m5mols_exif *exif = &info->cap.exif;
-       struct v4l2_subdev *sd = &info->sd;
-       int ret;
-
-       ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU,
-                                  EXIF_INFO_EXPTIME_DE, &exif->exposure_time);
-       if (ret)
-               return ret;
-       ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE,
-                                  &exif->shutter_speed);
-       if (ret)
-               return ret;
-       ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE,
-                                  &exif->aperture);
-       if (ret)
-               return ret;
-       ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE,
-                                  &exif->brightness);
-       if (ret)
-               return ret;
-       ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE,
-                                  &exif->exposure_bias);
-       if (ret)
-               return ret;
-
-       ret = m5mols_read_u16(sd, EXIF_INFO_ISO, &exif->iso_speed);
-       if (!ret)
-               ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash);
-       if (!ret)
-               ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr);
-       if (!ret)
-               ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval);
-       if (ret)
-               return ret;
-
-       if (!ret)
-               ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main);
-       if (!ret)
-               ret = m5mols_read_u32(sd, CAPC_THUMB_SIZE, &info->cap.thumb);
-       if (!ret)
-               info->cap.total = info->cap.main + info->cap.thumb;
-
-       return ret;
-}
-
-int m5mols_start_capture(struct m5mols_info *info)
-{
-       unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE;
-       struct v4l2_subdev *sd = &info->sd;
-       int ret;
-
-       /*
-        * Synchronize the controls, set the capture frame resolution and color
-        * format. The frame capture is initiated during switching from Monitor
-        * to Capture mode.
-        */
-       ret = m5mols_set_mode(info, REG_MONITOR);
-       if (!ret)
-               ret = m5mols_restore_controls(info);
-       if (!ret)
-               ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
-       if (!ret)
-               ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution);
-       if (!ret)
-               ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize);
-       if (!ret)
-               ret = m5mols_set_mode(info, REG_CAPTURE);
-       if (!ret)
-               /* Wait until a frame is captured to ISP internal memory */
-               ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
-       if (ret)
-               return ret;
-
-       /*
-        * Initiate the captured data transfer to a MIPI-CSI receiver.
-        */
-       ret = m5mols_write(sd, CAPC_SEL_FRAME, 1);
-       if (!ret)
-               ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN);
-       if (!ret) {
-               bool captured = false;
-               unsigned int size;
-
-               /* Wait for the capture completion interrupt */
-               ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
-               if (!ret) {
-                       captured = true;
-                       ret = m5mols_capture_info(info);
-               }
-               size = captured ? info->cap.main : 0;
-               v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n",
-                        __func__, size, info->cap.thumb);
-
-               v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size);
-       }
-
-       return ret;
-}
diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c
deleted file mode 100644 (file)
index b45e0e0..0000000
+++ /dev/null
@@ -1,625 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Controls for M-5MOLS 8M Pixel camera sensor with ISP
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim <riverful.kim@samsung.com>
- *
- * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-ctrls.h>
-
-#include "m5mols.h"
-#include "m5mols_reg.h"
-
-static struct m5mols_scenemode m5mols_default_scenemode[] = {
-       [REG_SCENE_NORMAL] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF,
-               5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_PORTRAIT] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 4,
-               REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_LANDSCAPE] = {
-               REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 4, REG_EDGE_ON, 6,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_SPORTS] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_PARTY_INDOOR] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_BEACH_SNOW] = {
-               REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_SUNSET] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
-               REG_AWB_DAYLIGHT,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_DAWN_DUSK] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
-               REG_AWB_FLUORESCENT_1,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_FALL] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 5, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_NIGHT] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_AGAINST_LIGHT] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_FIRE] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
-       },
-       [REG_SCENE_TEXT] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 7,
-               REG_AF_MACRO, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON,
-       },
-       [REG_SCENE_CANDLE] = {
-               REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
-               REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
-               REG_AF_NORMAL, REG_FD_OFF,
-               REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
-               6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
-       },
-};
-
-/**
- * m5mols_do_scenemode() - Change current scenemode
- * @info: M-5MOLS driver data structure
- * @mode:      Desired mode of the scenemode
- *
- * WARNING: The execution order is important. Do not change the order.
- */
-int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)
-{
-       struct v4l2_subdev *sd = &info->sd;
-       struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode];
-       int ret;
-
-       if (mode > REG_SCENE_CANDLE)
-               return -EINVAL;
-
-       ret = v4l2_ctrl_s_ctrl(info->lock_3a, 0);
-       if (!ret)
-               ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode);
-       if (!ret)
-               ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode);
-       if (!ret)
-               ret = m5mols_write(sd, AE_MODE, scenemode.metering);
-       if (!ret)
-               ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias);
-       if (!ret)
-               ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode);
-       if (!ret)
-               ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset);
-       if (!ret)
-               ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en);
-       if (!ret)
-               ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl);
-       if (!ret)
-               ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en);
-       if (!ret)
-               ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl);
-       if (!ret && is_available_af(info))
-               ret = m5mols_write(sd, AF_MODE, scenemode.af_range);
-       if (!ret && is_available_af(info))
-               ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode);
-       if (!ret)
-               ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone);
-       if (!ret)
-               ret = m5mols_write(sd, AE_ISO, scenemode.iso);
-       if (!ret)
-               ret = m5mols_set_mode(info, REG_CAPTURE);
-       if (!ret)
-               ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr);
-       if (!ret)
-               ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc);
-       if (!ret)
-               ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light);
-       if (!ret)
-               ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash);
-       if (!ret)
-               ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode);
-       if (!ret)
-               ret = m5mols_set_mode(info, REG_MONITOR);
-
-       return ret;
-}
-
-static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
-{
-       bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
-       int ret = 0;
-
-       if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
-               bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;
-
-               ret = m5mols_write(&info->sd, AE_LOCK, ae_lock ?
-                                  REG_AE_LOCK : REG_AE_UNLOCK);
-               if (ret)
-                       return ret;
-       }
-
-       if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
-           && info->auto_wb->val) {
-               bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;
-
-               ret = m5mols_write(&info->sd, AWB_LOCK, awb_lock ?
-                                  REG_AWB_LOCK : REG_AWB_UNLOCK);
-               if (ret)
-                       return ret;
-       }
-
-       if (!info->ver.af || !af_lock)
-               return ret;
-
-       if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
-               ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
-
-       return ret;
-}
-
-static int m5mols_set_metering_mode(struct m5mols_info *info, int mode)
-{
-       unsigned int metering;
-
-       switch (mode) {
-       case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
-               metering = REG_AE_CENTER;
-               break;
-       case V4L2_EXPOSURE_METERING_SPOT:
-               metering = REG_AE_SPOT;
-               break;
-       default:
-               metering = REG_AE_ALL;
-               break;
-       }
-
-       return m5mols_write(&info->sd, AE_MODE, metering);
-}
-
-static int m5mols_set_exposure(struct m5mols_info *info, int exposure)
-{
-       struct v4l2_subdev *sd = &info->sd;
-       int ret = 0;
-
-       if (exposure == V4L2_EXPOSURE_AUTO) {
-               /* Unlock auto exposure */
-               info->lock_3a->val &= ~V4L2_LOCK_EXPOSURE;
-               m5mols_3a_lock(info, info->lock_3a);
-
-               ret = m5mols_set_metering_mode(info, info->metering->val);
-               if (ret < 0)
-                       return ret;
-
-               v4l2_dbg(1, m5mols_debug, sd,
-                        "%s: exposure bias: %#x, metering: %#x\n",
-                        __func__, info->exposure_bias->val,
-                        info->metering->val);
-
-               return m5mols_write(sd, AE_INDEX, info->exposure_bias->val);
-       }
-
-       if (exposure == V4L2_EXPOSURE_MANUAL) {
-               ret = m5mols_write(sd, AE_MODE, REG_AE_OFF);
-               if (ret == 0)
-                       ret = m5mols_write(sd, AE_MAN_GAIN_MON,
-                                          info->exposure->val);
-               if (ret == 0)
-                       ret = m5mols_write(sd, AE_MAN_GAIN_CAP,
-                                          info->exposure->val);
-
-               v4l2_dbg(1, m5mols_debug, sd, "%s: exposure: %#x\n",
-                        __func__, info->exposure->val);
-       }
-
-       return ret;
-}
-
-static int m5mols_set_white_balance(struct m5mols_info *info, int val)
-{
-       static const unsigned short wb[][2] = {
-               { V4L2_WHITE_BALANCE_INCANDESCENT,  REG_AWB_INCANDESCENT },
-               { V4L2_WHITE_BALANCE_FLUORESCENT,   REG_AWB_FLUORESCENT_1 },
-               { V4L2_WHITE_BALANCE_FLUORESCENT_H, REG_AWB_FLUORESCENT_2 },
-               { V4L2_WHITE_BALANCE_HORIZON,       REG_AWB_HORIZON },
-               { V4L2_WHITE_BALANCE_DAYLIGHT,      REG_AWB_DAYLIGHT },
-               { V4L2_WHITE_BALANCE_FLASH,         REG_AWB_LEDLIGHT },
-               { V4L2_WHITE_BALANCE_CLOUDY,        REG_AWB_CLOUDY },
-               { V4L2_WHITE_BALANCE_SHADE,         REG_AWB_SHADE },
-               { V4L2_WHITE_BALANCE_AUTO,          REG_AWB_AUTO },
-       };
-       int i;
-       struct v4l2_subdev *sd = &info->sd;
-       int ret = -EINVAL;
-
-       for (i = 0; i < ARRAY_SIZE(wb); i++) {
-               int awb;
-               if (wb[i][0] != val)
-                       continue;
-
-               v4l2_dbg(1, m5mols_debug, sd,
-                        "Setting white balance to: %#x\n", wb[i][0]);
-
-               awb = wb[i][0] == V4L2_WHITE_BALANCE_AUTO;
-               ret = m5mols_write(sd, AWB_MODE, awb ? REG_AWB_AUTO :
-                                                REG_AWB_PRESET);
-               if (ret < 0)
-                       return ret;
-
-               if (!awb)
-                       ret = m5mols_write(sd, AWB_MANUAL, wb[i][1]);
-       }
-
-       return ret;
-}
-
-static int m5mols_set_saturation(struct m5mols_info *info, int val)
-{
-       int ret = m5mols_write(&info->sd, MON_CHROMA_LVL, val);
-       if (ret < 0)
-               return ret;
-
-       return m5mols_write(&info->sd, MON_CHROMA_EN, REG_CHROMA_ON);
-}
-
-static int m5mols_set_color_effect(struct m5mols_info *info, int val)
-{
-       unsigned int m_effect = REG_COLOR_EFFECT_OFF;
-       unsigned int p_effect = REG_EFFECT_OFF;
-       unsigned int cfix_r = 0, cfix_b = 0;
-       struct v4l2_subdev *sd = &info->sd;
-       int ret = 0;
-
-       switch (val) {
-       case V4L2_COLORFX_BW:
-               m_effect = REG_COLOR_EFFECT_ON;
-               break;
-       case V4L2_COLORFX_NEGATIVE:
-               p_effect = REG_EFFECT_NEGA;
-               break;
-       case V4L2_COLORFX_EMBOSS:
-               p_effect = REG_EFFECT_EMBOSS;
-               break;
-       case V4L2_COLORFX_SEPIA:
-               m_effect = REG_COLOR_EFFECT_ON;
-               cfix_r = REG_CFIXR_SEPIA;
-               cfix_b = REG_CFIXB_SEPIA;
-               break;
-       }
-
-       ret = m5mols_write(sd, PARM_EFFECT, p_effect);
-       if (!ret)
-               ret = m5mols_write(sd, MON_EFFECT, m_effect);
-
-       if (ret == 0 && m_effect == REG_COLOR_EFFECT_ON) {
-               ret = m5mols_write(sd, MON_CFIXR, cfix_r);
-               if (!ret)
-                       ret = m5mols_write(sd, MON_CFIXB, cfix_b);
-       }
-
-       v4l2_dbg(1, m5mols_debug, sd,
-                "p_effect: %#x, m_effect: %#x, r: %#x, b: %#x (%d)\n",
-                p_effect, m_effect, cfix_r, cfix_b, ret);
-
-       return ret;
-}
-
-static int m5mols_set_iso(struct m5mols_info *info, int auto_iso)
-{
-       u32 iso = auto_iso ? 0 : info->iso->val + 1;
-
-       return m5mols_write(&info->sd, AE_ISO, iso);
-}
-
-static int m5mols_set_wdr(struct m5mols_info *info, int wdr)
-{
-       int ret;
-
-       ret = m5mols_write(&info->sd, MON_TONE_CTL, wdr ? 9 : 5);
-       if (ret < 0)
-               return ret;
-
-       ret = m5mols_set_mode(info, REG_CAPTURE);
-       if (ret < 0)
-               return ret;
-
-       return m5mols_write(&info->sd, CAPP_WDR_EN, wdr);
-}
-
-static int m5mols_set_stabilization(struct m5mols_info *info, int val)
-{
-       struct v4l2_subdev *sd = &info->sd;
-       unsigned int evp = val ? 0xe : 0x0;
-       int ret;
-
-       ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, evp);
-       if (ret < 0)
-               return ret;
-
-       return m5mols_write(sd, AE_EV_PRESET_CAPTURE, evp);
-}
-
-static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct v4l2_subdev *sd = to_sd(ctrl);
-       struct m5mols_info *info = to_m5mols(sd);
-       int ret = 0;
-       u8 status = REG_ISO_AUTO;
-
-       v4l2_dbg(1, m5mols_debug, sd, "%s: ctrl: %s (%d)\n",
-                __func__, ctrl->name, info->isp_ready);
-
-       if (!info->isp_ready)
-               return -EBUSY;
-
-       switch (ctrl->id) {
-       case V4L2_CID_ISO_SENSITIVITY_AUTO:
-               ret = m5mols_read_u8(sd, AE_ISO, &status);
-               if (ret == 0)
-                       ctrl->val = !status;
-               if (status != REG_ISO_AUTO)
-                       info->iso->val = status - 1;
-               break;
-
-       case V4L2_CID_3A_LOCK:
-               ctrl->val &= ~0x7;
-
-               ret = m5mols_read_u8(sd, AE_LOCK, &status);
-               if (ret)
-                       return ret;
-               if (status)
-                       info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
-
-               ret = m5mols_read_u8(sd, AWB_LOCK, &status);
-               if (ret)
-                       return ret;
-               if (status)
-                       info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
-
-               ret = m5mols_read_u8(sd, AF_EXECUTE, &status);
-               if (!status)
-                       info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
-               break;
-       }
-
-       return ret;
-}
-
-static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       unsigned int ctrl_mode = m5mols_get_ctrl_mode(ctrl);
-       struct v4l2_subdev *sd = to_sd(ctrl);
-       struct m5mols_info *info = to_m5mols(sd);
-       int last_mode = info->mode;
-       int ret = 0;
-
-       /*
-        * If needed, defer restoring the controls until
-        * the device is fully initialized.
-        */
-       if (!info->isp_ready) {
-               info->ctrl_sync = 0;
-               return 0;
-       }
-
-       v4l2_dbg(1, m5mols_debug, sd, "%s: %s, val: %d, priv: %p\n",
-                __func__, ctrl->name, ctrl->val, ctrl->priv);
-
-       if (ctrl_mode && ctrl_mode != info->mode) {
-               ret = m5mols_set_mode(info, ctrl_mode);
-               if (ret < 0)
-                       return ret;
-       }
-
-       switch (ctrl->id) {
-       case V4L2_CID_3A_LOCK:
-               ret = m5mols_3a_lock(info, ctrl);
-               break;
-
-       case V4L2_CID_ZOOM_ABSOLUTE:
-               ret = m5mols_write(sd, MON_ZOOM, ctrl->val);
-               break;
-
-       case V4L2_CID_EXPOSURE_AUTO:
-               ret = m5mols_set_exposure(info, ctrl->val);
-               break;
-
-       case V4L2_CID_ISO_SENSITIVITY:
-               ret = m5mols_set_iso(info, ctrl->val);
-               break;
-
-       case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
-               ret = m5mols_set_white_balance(info, ctrl->val);
-               break;
-
-       case V4L2_CID_SATURATION:
-               ret = m5mols_set_saturation(info, ctrl->val);
-               break;
-
-       case V4L2_CID_COLORFX:
-               ret = m5mols_set_color_effect(info, ctrl->val);
-               break;
-
-       case V4L2_CID_WIDE_DYNAMIC_RANGE:
-               ret = m5mols_set_wdr(info, ctrl->val);
-               break;
-
-       case V4L2_CID_IMAGE_STABILIZATION:
-               ret = m5mols_set_stabilization(info, ctrl->val);
-               break;
-
-       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-               ret = m5mols_write(sd, CAPP_JPEG_RATIO, ctrl->val);
-               break;
-       }
-
-       if (ret == 0 && info->mode != last_mode)
-               ret = m5mols_set_mode(info, last_mode);
-
-       return ret;
-}
-
-static const struct v4l2_ctrl_ops m5mols_ctrl_ops = {
-       .g_volatile_ctrl        = m5mols_g_volatile_ctrl,
-       .s_ctrl                 = m5mols_s_ctrl,
-};
-
-/* Supported manual ISO values */
-static const s64 iso_qmenu[] = {
-       /* AE_ISO: 0x01...0x07 (ISO: 50...3200) */
-       50000, 100000, 200000, 400000, 800000, 1600000, 3200000
-};
-
-/* Supported Exposure Bias values, -2.0EV...+2.0EV */
-static const s64 ev_bias_qmenu[] = {
-       /* AE_INDEX: 0x00...0x08 */
-       -2000, -1500, -1000, -500, 0, 500, 1000, 1500, 2000
-};
-
-int m5mols_init_controls(struct v4l2_subdev *sd)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-       u16 exposure_max;
-       u16 zoom_step;
-       int ret;
-
-       /* Determine the firmware dependent control range and step values */
-       ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &exposure_max);
-       if (ret < 0)
-               return ret;
-
-       zoom_step = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1;
-       v4l2_ctrl_handler_init(&info->handle, 20);
-
-       info->auto_wb = v4l2_ctrl_new_std_menu(&info->handle,
-                       &m5mols_ctrl_ops, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
-                       9, ~0x3fe, V4L2_WHITE_BALANCE_AUTO);
-
-       /* Exposure control cluster */
-       info->auto_exposure = v4l2_ctrl_new_std_menu(&info->handle,
-                       &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
-                       1, ~0x03, V4L2_EXPOSURE_AUTO);
-
-       info->exposure = v4l2_ctrl_new_std(&info->handle,
-                       &m5mols_ctrl_ops, V4L2_CID_EXPOSURE,
-                       0, exposure_max, 1, exposure_max / 2);
-
-       info->exposure_bias = v4l2_ctrl_new_int_menu(&info->handle,
-                       &m5mols_ctrl_ops, V4L2_CID_AUTO_EXPOSURE_BIAS,
-                       ARRAY_SIZE(ev_bias_qmenu) - 1,
-                       ARRAY_SIZE(ev_bias_qmenu)/2 - 1,
-                       ev_bias_qmenu);
-
-       info->metering = v4l2_ctrl_new_std_menu(&info->handle,
-                       &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_METERING,
-                       2, ~0x7, V4L2_EXPOSURE_METERING_AVERAGE);
-
-       /* ISO control cluster */
-       info->auto_iso = v4l2_ctrl_new_std_menu(&info->handle, &m5mols_ctrl_ops,
-                       V4L2_CID_ISO_SENSITIVITY_AUTO, 1, ~0x03, 1);
-
-       info->iso = v4l2_ctrl_new_int_menu(&info->handle, &m5mols_ctrl_ops,
-                       V4L2_CID_ISO_SENSITIVITY, ARRAY_SIZE(iso_qmenu) - 1,
-                       ARRAY_SIZE(iso_qmenu)/2 - 1, iso_qmenu);
-
-       info->saturation = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
-                       V4L2_CID_SATURATION, 1, 5, 1, 3);
-
-       info->zoom = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
-                       V4L2_CID_ZOOM_ABSOLUTE, 1, 70, zoom_step, 1);
-
-       info->colorfx = v4l2_ctrl_new_std_menu(&info->handle, &m5mols_ctrl_ops,
-                       V4L2_CID_COLORFX, 4, 0, V4L2_COLORFX_NONE);
-
-       info->wdr = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
-                       V4L2_CID_WIDE_DYNAMIC_RANGE, 0, 1, 1, 0);
-
-       info->stabilization = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
-                       V4L2_CID_IMAGE_STABILIZATION, 0, 1, 1, 0);
-
-       info->jpeg_quality = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
-                       V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 80);
-
-       info->lock_3a = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
-                       V4L2_CID_3A_LOCK, 0, 0x7, 0, 0);
-
-       if (info->handle.error) {
-               int ret = info->handle.error;
-               v4l2_err(sd, "Failed to initialize controls: %d\n", ret);
-               v4l2_ctrl_handler_free(&info->handle);
-               return ret;
-       }
-
-       v4l2_ctrl_auto_cluster(4, &info->auto_exposure, 1, false);
-       info->auto_iso->flags |= V4L2_CTRL_FLAG_VOLATILE |
-                               V4L2_CTRL_FLAG_UPDATE;
-       v4l2_ctrl_auto_cluster(2, &info->auto_iso, 0, false);
-
-       info->lock_3a->flags |= V4L2_CTRL_FLAG_VOLATILE;
-
-       m5mols_set_ctrl_mode(info->auto_exposure, REG_PARAMETER);
-       m5mols_set_ctrl_mode(info->auto_wb, REG_PARAMETER);
-       m5mols_set_ctrl_mode(info->colorfx, REG_MONITOR);
-
-       sd->ctrl_handler = &info->handle;
-
-       return 0;
-}
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c
deleted file mode 100644 (file)
index 5c2336f..0000000
+++ /dev/null
@@ -1,1051 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Driver for M-5MOLS 8M Pixel camera sensor with ISP
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim <riverful.kim@samsung.com>
- *
- * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/gpio/consumer.h>
-#include <linux/regulator/consumer.h>
-#include <linux/videodev2.h>
-#include <linux/module.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-subdev.h>
-#include <media/i2c/m5mols.h>
-
-#include "m5mols.h"
-#include "m5mols_reg.h"
-
-int m5mols_debug;
-module_param(m5mols_debug, int, 0644);
-
-#define MODULE_NAME            "M5MOLS"
-#define M5MOLS_I2C_CHECK_RETRY 500
-
-/* The regulator consumer names for external voltage regulators */
-static struct regulator_bulk_data supplies[] = {
-       {
-               .supply = "core",       /* ARM core power, 1.2V */
-       }, {
-               .supply = "dig_18",     /* digital power 1, 1.8V */
-       }, {
-               .supply = "d_sensor",   /* sensor power 1, 1.8V */
-       }, {
-               .supply = "dig_28",     /* digital power 2, 2.8V */
-       }, {
-               .supply = "a_sensor",   /* analog power */
-       }, {
-               .supply = "dig_12",     /* digital power 3, 1.2V */
-       },
-};
-
-static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = {
-       [M5MOLS_RESTYPE_MONITOR] = {
-               .width          = 1920,
-               .height         = 1080,
-               .code           = MEDIA_BUS_FMT_VYUY8_2X8,
-               .field          = V4L2_FIELD_NONE,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-       },
-       [M5MOLS_RESTYPE_CAPTURE] = {
-               .width          = 1920,
-               .height         = 1080,
-               .code           = MEDIA_BUS_FMT_JPEG_1X8,
-               .field          = V4L2_FIELD_NONE,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-       },
-};
-#define SIZE_DEFAULT_FFMT      ARRAY_SIZE(m5mols_default_ffmt)
-
-static const struct m5mols_resolution m5mols_reg_res[] = {
-       { 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 },      /* SUB-QCIF */
-       { 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 },     /* QQVGA */
-       { 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 },     /* QCIF */
-       { 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 },
-       { 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 },     /* QVGA */
-       { 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 },     /* QVGA */
-       { 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 },     /* WQVGA */
-       { 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 },     /* WQVGA */
-       { 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 },     /* CIF */
-       { 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 },
-       { 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 },     /* qHD */
-       { 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 },     /* VGA */
-       { 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 },
-       { 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 },     /* WVGA */
-       { 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 },     /* SVGA */
-       { 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 },    /* HD */
-       { 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 },   /* 1080p */
-       { 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 },   /* 2.63fps 8M */
-       { 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 },     /* AHS_MON debug */
-
-       { 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 },     /* QVGA */
-       { 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 },     /* WQVGA */
-       { 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 },
-       { 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 },     /* qHD */
-       { 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 },     /* VGA */
-       { 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 },     /* WVGA */
-       { 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 },    /* HD */
-       { 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 },    /* 1M */
-       { 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 },   /* 2M */
-       { 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 },   /* Full-HD */
-       { 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 },   /* 3Mega */
-       { 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 },
-       { 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 },   /* 4Mega */
-       { 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 },
-       { 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 },   /* 5Mega */
-       { 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 },   /* 6Mega */
-       { 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 },
-       { 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 },   /* 8Mega */
-};
-
-/**
- * m5mols_swap_byte - an byte array to integer conversion function
- * @data: byte array
- * @length: size in bytes of I2C packet defined in the M-5MOLS datasheet
- *
- * Convert I2C data byte array with performing any required byte
- * reordering to assure proper values for each data type, regardless
- * of the architecture endianness.
- */
-static u32 m5mols_swap_byte(u8 *data, u8 length)
-{
-       if (length == 1)
-               return *data;
-       else if (length == 2)
-               return be16_to_cpu(*((__be16 *)data));
-       else
-               return be32_to_cpu(*((__be32 *)data));
-}
-
-/**
- * m5mols_read -  I2C read function
- * @sd: sub-device, as pointed by struct v4l2_subdev
- * @size: desired size of I2C packet
- * @reg: combination of size, category and command for the I2C packet
- * @val: read value
- *
- * Returns 0 on success, or else negative errno.
- */
-static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct m5mols_info *info = to_m5mols(sd);
-       u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
-       u8 category = I2C_CATEGORY(reg);
-       u8 cmd = I2C_COMMAND(reg);
-       struct i2c_msg msg[2];
-       u8 wbuf[5];
-       int ret;
-
-       if (!client->adapter)
-               return -ENODEV;
-
-       msg[0].addr = client->addr;
-       msg[0].flags = 0;
-       msg[0].len = 5;
-       msg[0].buf = wbuf;
-       wbuf[0] = 5;
-       wbuf[1] = M5MOLS_BYTE_READ;
-       wbuf[2] = category;
-       wbuf[3] = cmd;
-       wbuf[4] = size;
-
-       msg[1].addr = client->addr;
-       msg[1].flags = I2C_M_RD;
-       msg[1].len = size + 1;
-       msg[1].buf = rbuf;
-
-       /* minimum stabilization time */
-       usleep_range(200, 300);
-
-       ret = i2c_transfer(client->adapter, msg, 2);
-
-       if (ret == 2) {
-               *val = m5mols_swap_byte(&rbuf[1], size);
-               return 0;
-       }
-
-       if (info->isp_ready)
-               v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
-                        size, category, cmd, ret);
-
-       return ret < 0 ? ret : -EIO;
-}
-
-int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
-{
-       u32 val_32;
-       int ret;
-
-       if (I2C_SIZE(reg) != 1) {
-               v4l2_err(sd, "Wrong data size\n");
-               return -EINVAL;
-       }
-
-       ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
-       if (ret)
-               return ret;
-
-       *val = (u8)val_32;
-       return ret;
-}
-
-int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val)
-{
-       u32 val_32;
-       int ret;
-
-       if (I2C_SIZE(reg) != 2) {
-               v4l2_err(sd, "Wrong data size\n");
-               return -EINVAL;
-       }
-
-       ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
-       if (ret)
-               return ret;
-
-       *val = (u16)val_32;
-       return ret;
-}
-
-int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
-{
-       if (I2C_SIZE(reg) != 4) {
-               v4l2_err(sd, "Wrong data size\n");
-               return -EINVAL;
-       }
-
-       return m5mols_read(sd, I2C_SIZE(reg), reg, val);
-}
-
-/**
- * m5mols_write - I2C command write function
- * @sd: sub-device, as pointed by struct v4l2_subdev
- * @reg: combination of size, category and command for the I2C packet
- * @val: value to write
- *
- * Returns 0 on success, or else negative errno.
- */
-int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct m5mols_info *info = to_m5mols(sd);
-       u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4];
-       u8 category = I2C_CATEGORY(reg);
-       u8 cmd = I2C_COMMAND(reg);
-       u8 size = I2C_SIZE(reg);
-       u32 *buf = (u32 *)&wbuf[4];
-       struct i2c_msg msg[1];
-       int ret;
-
-       if (!client->adapter)
-               return -ENODEV;
-
-       if (size != 1 && size != 2 && size != 4) {
-               v4l2_err(sd, "Wrong data size\n");
-               return -EINVAL;
-       }
-
-       msg->addr = client->addr;
-       msg->flags = 0;
-       msg->len = (u16)size + 4;
-       msg->buf = wbuf;
-       wbuf[0] = size + 4;
-       wbuf[1] = M5MOLS_BYTE_WRITE;
-       wbuf[2] = category;
-       wbuf[3] = cmd;
-
-       *buf = m5mols_swap_byte((u8 *)&val, size);
-
-       /* minimum stabilization time */
-       usleep_range(200, 300);
-
-       ret = i2c_transfer(client->adapter, msg, 1);
-       if (ret == 1)
-               return 0;
-
-       if (info->isp_ready)
-               v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n",
-                        category, cmd, ret);
-
-       return ret < 0 ? ret : -EIO;
-}
-
-/**
- * m5mols_busy_wait - Busy waiting with I2C register polling
- * @sd: sub-device, as pointed by struct v4l2_subdev
- * @reg: the I2C_REG() address of an 8-bit status register to check
- * @value: expected status register value
- * @mask: bit mask for the read status register value
- * @timeout: timeout in milliseconds, or -1 for default timeout
- *
- * The @reg register value is ORed with @mask before comparing with @value.
- *
- * Return: 0 if the requested condition became true within less than
- *         @timeout ms, or else negative errno.
- */
-int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
-                    int timeout)
-{
-       int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout;
-       unsigned long end = jiffies + msecs_to_jiffies(ms);
-       u8 status;
-
-       do {
-               int ret = m5mols_read_u8(sd, reg, &status);
-
-               if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL))
-                       return ret;
-               if (!ret && (status & mask & 0xff) == (value & 0xff))
-                       return 0;
-               usleep_range(100, 250);
-       } while (ms > 0 && time_is_after_jiffies(end));
-
-       return -EBUSY;
-}
-
-/**
- * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts
- * @sd: sub-device, as pointed by struct v4l2_subdev
- * @reg: combination of size, category and command for the I2C packet
- *
- * Before writing desired interrupt value the INT_FACTOR register should
- * be read to clear pending interrupts.
- */
-int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-       u8 mask = is_available_af(info) ? REG_INT_AF : 0;
-       u8 dummy;
-       int ret;
-
-       ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy);
-       if (!ret)
-               ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask);
-       return ret;
-}
-
-int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-
-       int ret = wait_event_interruptible_timeout(info->irq_waitq,
-                               atomic_add_unless(&info->irq_done, -1, 0),
-                               msecs_to_jiffies(timeout));
-       if (ret <= 0)
-               return ret ? ret : -ETIMEDOUT;
-
-       return m5mols_busy_wait(sd, SYSTEM_INT_FACTOR, irq_mask,
-                               M5MOLS_I2C_RDY_WAIT_FL | irq_mask, -1);
-}
-
-/**
- * m5mols_reg_mode - Write the mode and check busy status
- * @sd: sub-device, as pointed by struct v4l2_subdev
- * @mode: the required operation mode
- *
- * It always accompanies a little delay changing the M-5MOLS mode, so it is
- * needed checking current busy status to guarantee right mode.
- */
-static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
-{
-       int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
-       if (ret < 0)
-               return ret;
-       return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
-                               M5MOLS_MODE_CHANGE_TIMEOUT);
-}
-
-/**
- * m5mols_set_mode - set the M-5MOLS controller mode
- * @info: M-5MOLS driver data structure
- * @mode: the required operation mode
- *
- * The commands of M-5MOLS are grouped into specific modes. Each functionality
- * can be guaranteed only when the sensor is operating in mode which a command
- * belongs to.
- */
-int m5mols_set_mode(struct m5mols_info *info, u8 mode)
-{
-       struct v4l2_subdev *sd = &info->sd;
-       int ret = -EINVAL;
-       u8 reg;
-
-       if (mode < REG_PARAMETER || mode > REG_CAPTURE)
-               return ret;
-
-       ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
-       if (ret || reg == mode)
-               return ret;
-
-       switch (reg) {
-       case REG_PARAMETER:
-               ret = m5mols_reg_mode(sd, REG_MONITOR);
-               if (mode == REG_MONITOR)
-                       break;
-               if (!ret)
-                       ret = m5mols_reg_mode(sd, REG_CAPTURE);
-               break;
-
-       case REG_MONITOR:
-               if (mode == REG_PARAMETER) {
-                       ret = m5mols_reg_mode(sd, REG_PARAMETER);
-                       break;
-               }
-
-               ret = m5mols_reg_mode(sd, REG_CAPTURE);
-               break;
-
-       case REG_CAPTURE:
-               ret = m5mols_reg_mode(sd, REG_MONITOR);
-               if (mode == REG_MONITOR)
-                       break;
-               if (!ret)
-                       ret = m5mols_reg_mode(sd, REG_PARAMETER);
-               break;
-
-       default:
-               v4l2_warn(sd, "Wrong mode: %d\n", mode);
-       }
-
-       if (!ret)
-               info->mode = mode;
-
-       return ret;
-}
-
-/**
- * m5mols_get_version - retrieve full revisions information of M-5MOLS
- * @sd: sub-device, as pointed by struct v4l2_subdev
- *
- * The version information includes revisions of hardware and firmware,
- * AutoFocus alghorithm version and the version string.
- */
-static int m5mols_get_version(struct v4l2_subdev *sd)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-       struct m5mols_version *ver = &info->ver;
-       u8 *str = ver->str;
-       int i;
-       int ret;
-
-       ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer);
-       if (!ret)
-               ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project);
-       if (!ret)
-               ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw);
-       if (!ret)
-               ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw);
-       if (!ret)
-               ret = m5mols_read_u16(sd, SYSTEM_VER_PARAMETER, &ver->param);
-       if (!ret)
-               ret = m5mols_read_u16(sd, SYSTEM_VER_AWB, &ver->awb);
-       if (!ret)
-               ret = m5mols_read_u8(sd, AF_VERSION, &ver->af);
-       if (ret)
-               return ret;
-
-       for (i = 0; i < VERSION_STRING_SIZE; i++) {
-               ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]);
-               if (ret)
-                       return ret;
-       }
-
-       v4l2_info(sd, "Manufacturer\t[%s]\n",
-                       is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
-                       "Samsung Electro-Mechanics" :
-                       is_manufacturer(info, REG_SAMSUNG_OPTICS) ?
-                       "Samsung Fiber-Optics" :
-                       is_manufacturer(info, REG_SAMSUNG_TECHWIN) ?
-                       "Samsung Techwin" : "None");
-       v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n",
-                       info->ver.customer, info->ver.project);
-
-       if (!is_available_af(info))
-               v4l2_info(sd, "No support Auto Focus on this firmware\n");
-
-       return ret;
-}
-
-/**
- * __find_restype - Lookup M-5MOLS resolution type according to pixel code
- * @code: pixel code
- */
-static enum m5mols_restype __find_restype(u32 code)
-{
-       enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR;
-
-       do {
-               if (code == m5mols_default_ffmt[type].code)
-                       return type;
-       } while (++type != SIZE_DEFAULT_FFMT);
-
-       return 0;
-}
-
-/**
- * __find_resolution - Lookup preset and type of M-5MOLS's resolution
- * @sd: sub-device, as pointed by struct v4l2_subdev
- * @mf: pixel format to find/negotiate the resolution preset for
- * @type: M-5MOLS resolution type
- * @resolution:        M-5MOLS resolution preset register value
- *
- * Find nearest resolution matching resolution preset and adjust mf
- * to supported values.
- */
-static int __find_resolution(struct v4l2_subdev *sd,
-                            struct v4l2_mbus_framefmt *mf,
-                            enum m5mols_restype *type,
-                            u32 *resolution)
-{
-       const struct m5mols_resolution *fsize = &m5mols_reg_res[0];
-       const struct m5mols_resolution *match = NULL;
-       enum m5mols_restype stype = __find_restype(mf->code);
-       int i = ARRAY_SIZE(m5mols_reg_res);
-       unsigned int min_err = ~0;
-
-       while (i--) {
-               int err;
-               if (stype == fsize->type) {
-                       err = abs(fsize->width - mf->width)
-                               + abs(fsize->height - mf->height);
-
-                       if (err < min_err) {
-                               min_err = err;
-                               match = fsize;
-                       }
-               }
-               fsize++;
-       }
-       if (match) {
-               mf->width  = match->width;
-               mf->height = match->height;
-               *resolution = match->reg;
-               *type = stype;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info,
-                               struct v4l2_subdev_state *sd_state,
-                               enum v4l2_subdev_format_whence which,
-                               enum m5mols_restype type)
-{
-       if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return sd_state ? v4l2_subdev_get_try_format(&info->sd,
-                                                            sd_state, 0) : NULL;
-
-       return &info->ffmt[type];
-}
-
-static int m5mols_get_fmt(struct v4l2_subdev *sd,
-                         struct v4l2_subdev_state *sd_state,
-                         struct v4l2_subdev_format *fmt)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-       struct v4l2_mbus_framefmt *format;
-       int ret = 0;
-
-       mutex_lock(&info->lock);
-
-       format = __find_format(info, sd_state, fmt->which, info->res_type);
-       if (format)
-               fmt->format = *format;
-       else
-               ret = -EINVAL;
-
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-static int m5mols_set_fmt(struct v4l2_subdev *sd,
-                         struct v4l2_subdev_state *sd_state,
-                         struct v4l2_subdev_format *fmt)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-       struct v4l2_mbus_framefmt *format = &fmt->format;
-       struct v4l2_mbus_framefmt *sfmt;
-       enum m5mols_restype type;
-       u32 resolution = 0;
-       int ret;
-
-       ret = __find_resolution(sd, format, &type, &resolution);
-       if (ret < 0)
-               return ret;
-
-       sfmt = __find_format(info, sd_state, fmt->which, type);
-       if (!sfmt)
-               return 0;
-
-       mutex_lock(&info->lock);
-
-       format->code = m5mols_default_ffmt[type].code;
-       format->colorspace = V4L2_COLORSPACE_JPEG;
-       format->field = V4L2_FIELD_NONE;
-
-       if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
-               *sfmt = *format;
-               info->resolution = resolution;
-               info->res_type = type;
-       }
-
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-static int m5mols_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
-                                struct v4l2_mbus_frame_desc *fd)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-
-       if (pad != 0 || fd == NULL)
-               return -EINVAL;
-
-       mutex_lock(&info->lock);
-       /*
-        * .get_frame_desc is only used for compressed formats,
-        * thus we always return the capture frame parameters here.
-        */
-       fd->entry[0].length = info->cap.buf_size;
-       fd->entry[0].pixelcode = info->ffmt[M5MOLS_RESTYPE_CAPTURE].code;
-       mutex_unlock(&info->lock);
-
-       fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
-       fd->num_entries = 1;
-
-       return 0;
-}
-
-static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
-                                struct v4l2_mbus_frame_desc *fd)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-       struct v4l2_mbus_framefmt *mf = &info->ffmt[M5MOLS_RESTYPE_CAPTURE];
-
-       if (pad != 0 || fd == NULL)
-               return -EINVAL;
-
-       fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
-       fd->num_entries = 1;
-       fd->entry[0].length = clamp_t(u32, fd->entry[0].length,
-                                     mf->width * mf->height,
-                                     M5MOLS_MAIN_JPEG_SIZE_MAX);
-       mutex_lock(&info->lock);
-       info->cap.buf_size = fd->entry[0].length;
-       mutex_unlock(&info->lock);
-
-       return 0;
-}
-
-
-static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_state *sd_state,
-                                struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (!code || code->index >= SIZE_DEFAULT_FFMT)
-               return -EINVAL;
-
-       code->code = m5mols_default_ffmt[code->index].code;
-
-       return 0;
-}
-
-static const struct v4l2_subdev_pad_ops m5mols_pad_ops = {
-       .enum_mbus_code = m5mols_enum_mbus_code,
-       .get_fmt        = m5mols_get_fmt,
-       .set_fmt        = m5mols_set_fmt,
-       .get_frame_desc = m5mols_get_frame_desc,
-       .set_frame_desc = m5mols_set_frame_desc,
-};
-
-/**
- * m5mols_restore_controls - Apply current control values to the registers
- * @info: M-5MOLS driver data structure
- *
- * m5mols_do_scenemode() handles all parameters for which there is yet no
- * individual control. It should be replaced at some point by setting each
- * control individually, in required register set up order.
- */
-int m5mols_restore_controls(struct m5mols_info *info)
-{
-       int ret;
-
-       if (info->ctrl_sync)
-               return 0;
-
-       ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
-       if (ret)
-               return ret;
-
-       ret = v4l2_ctrl_handler_setup(&info->handle);
-       info->ctrl_sync = !ret;
-
-       return ret;
-}
-
-/**
- * m5mols_start_monitor - Start the monitor mode
- * @info: M-5MOLS driver data structure
- *
- * Before applying the controls setup the resolution and frame rate
- * in PARAMETER mode, and then switch over to MONITOR mode.
- */
-static int m5mols_start_monitor(struct m5mols_info *info)
-{
-       struct v4l2_subdev *sd = &info->sd;
-       int ret;
-
-       ret = m5mols_set_mode(info, REG_PARAMETER);
-       if (!ret)
-               ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution);
-       if (!ret)
-               ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30);
-       if (!ret)
-               ret = m5mols_set_mode(info, REG_MONITOR);
-       if (!ret)
-               ret = m5mols_restore_controls(info);
-
-       return ret;
-}
-
-static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-       u32 code;
-       int ret;
-
-       mutex_lock(&info->lock);
-       code = info->ffmt[info->res_type].code;
-
-       if (enable) {
-               if (is_code(code, M5MOLS_RESTYPE_MONITOR))
-                       ret = m5mols_start_monitor(info);
-               else if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
-                       ret = m5mols_start_capture(info);
-               else
-                       ret = -EINVAL;
-       } else {
-               ret = m5mols_set_mode(info, REG_PARAMETER);
-       }
-
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-static const struct v4l2_subdev_video_ops m5mols_video_ops = {
-       .s_stream       = m5mols_s_stream,
-};
-
-static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
-{
-       struct v4l2_subdev *sd = &info->sd;
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret;
-
-       if (info->power == enable)
-               return 0;
-
-       if (enable) {
-               if (info->set_power) {
-                       ret = info->set_power(&client->dev, 1);
-                       if (ret)
-                               return ret;
-               }
-
-               ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
-               if (ret) {
-                       if (info->set_power)
-                               info->set_power(&client->dev, 0);
-                       return ret;
-               }
-
-               gpiod_set_value(info->reset, 0);
-               info->power = 1;
-
-               return ret;
-       }
-
-       ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
-       if (ret)
-               return ret;
-
-       if (info->set_power)
-               info->set_power(&client->dev, 0);
-
-       gpiod_set_value(info->reset, 1);
-
-       info->isp_ready = 0;
-       info->power = 0;
-
-       return ret;
-}
-
-/* m5mols_update_fw - optional firmware update routine */
-int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd,
-               int (*set_power)(struct m5mols_info *, bool))
-{
-       return 0;
-}
-
-/**
- * m5mols_fw_start - M-5MOLS internal ARM controller initialization
- * @sd: sub-device, as pointed by struct v4l2_subdev
- *
- * Execute the M-5MOLS internal ARM controller initialization sequence.
- * This function should be called after the supply voltage has been
- * applied and before any requests to the device are made.
- */
-static int m5mols_fw_start(struct v4l2_subdev *sd)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-       int ret;
-
-       atomic_set(&info->irq_done, 0);
-       /* Wait until I2C slave is initialized in Flash Writer mode */
-       ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE,
-                              M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1);
-       if (!ret)
-               ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
-       if (!ret)
-               ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000);
-       if (ret < 0)
-               return ret;
-
-       info->isp_ready = 1;
-
-       ret = m5mols_get_version(sd);
-       if (!ret)
-               ret = m5mols_update_fw(sd, m5mols_sensor_power);
-       if (ret)
-               return ret;
-
-       v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n");
-
-       ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
-       if (!ret)
-               ret = m5mols_enable_interrupt(sd,
-                               REG_INT_AF | REG_INT_CAPTURE);
-
-       return ret;
-}
-
-/* Execute the lens soft-landing algorithm */
-static int m5mols_auto_focus_stop(struct m5mols_info *info)
-{
-       int ret;
-
-       ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
-       if (!ret)
-               ret = m5mols_write(&info->sd, AF_MODE, REG_AF_POWEROFF);
-       if (!ret)
-               ret = m5mols_busy_wait(&info->sd, SYSTEM_STATUS, REG_AF_IDLE,
-                                      0xff, -1);
-       return ret;
-}
-
-/**
- * m5mols_s_power - Main sensor power control function
- * @sd: sub-device, as pointed by struct v4l2_subdev
- * @on: if true, powers on the device; powers off otherwise.
- *
- * To prevent breaking the lens when the sensor is powered off the Soft-Landing
- * algorithm is called where available. The Soft-Landing algorithm availability
- * dependends on the firmware provider.
- */
-static int m5mols_s_power(struct v4l2_subdev *sd, int on)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-       int ret;
-
-       mutex_lock(&info->lock);
-
-       if (on) {
-               ret = m5mols_sensor_power(info, true);
-               if (!ret)
-                       ret = m5mols_fw_start(sd);
-       } else {
-               if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
-                       ret = m5mols_set_mode(info, REG_MONITOR);
-                       if (!ret)
-                               ret = m5mols_auto_focus_stop(info);
-                       if (ret < 0)
-                               v4l2_warn(sd, "Soft landing lens failed\n");
-               }
-               ret = m5mols_sensor_power(info, false);
-
-               info->ctrl_sync = 0;
-       }
-
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-static int m5mols_log_status(struct v4l2_subdev *sd)
-{
-       struct m5mols_info *info = to_m5mols(sd);
-
-       v4l2_ctrl_handler_log_status(&info->handle, sd->name);
-
-       return 0;
-}
-
-static const struct v4l2_subdev_core_ops m5mols_core_ops = {
-       .s_power        = m5mols_s_power,
-       .log_status     = m5mols_log_status,
-};
-
-/*
- * V4L2 subdev internal operations
- */
-static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-{
-       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd,
-                                                                      fh->state,
-                                                                      0);
-
-       *format = m5mols_default_ffmt[0];
-       return 0;
-}
-
-static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = {
-       .open           = m5mols_open,
-};
-
-static const struct v4l2_subdev_ops m5mols_ops = {
-       .core           = &m5mols_core_ops,
-       .pad            = &m5mols_pad_ops,
-       .video          = &m5mols_video_ops,
-};
-
-static irqreturn_t m5mols_irq_handler(int irq, void *data)
-{
-       struct m5mols_info *info = to_m5mols(data);
-
-       atomic_set(&info->irq_done, 1);
-       wake_up_interruptible(&info->irq_waitq);
-
-       return IRQ_HANDLED;
-}
-
-static int m5mols_probe(struct i2c_client *client)
-{
-       const struct m5mols_platform_data *pdata = client->dev.platform_data;
-       struct m5mols_info *info;
-       struct v4l2_subdev *sd;
-       int ret;
-
-       if (pdata == NULL) {
-               dev_err(&client->dev, "No platform data\n");
-               return -EINVAL;
-       }
-
-       if (!client->irq) {
-               dev_err(&client->dev, "Interrupt not assigned\n");
-               return -EINVAL;
-       }
-
-       info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       /* This asserts reset, descriptor shall have polarity specified */
-       info->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(info->reset))
-               return PTR_ERR(info->reset);
-       /* Notice: the "N" in M5MOLS_NRST implies active low */
-       gpiod_set_consumer_name(info->reset, "M5MOLS_NRST");
-
-       info->pdata = pdata;
-       info->set_power = pdata->set_power;
-
-       ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies),
-                                     supplies);
-       if (ret) {
-               dev_err(&client->dev, "Failed to get regulators: %d\n", ret);
-               return ret;
-       }
-
-       sd = &info->sd;
-       v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
-       /* 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;
-       info->pad.flags = MEDIA_PAD_FL_SOURCE;
-       ret = media_entity_pads_init(&sd->entity, 1, &info->pad);
-       if (ret < 0)
-               return ret;
-       sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
-
-       init_waitqueue_head(&info->irq_waitq);
-       mutex_init(&info->lock);
-
-       ret = devm_request_irq(&client->dev, client->irq, m5mols_irq_handler,
-                              IRQF_TRIGGER_RISING, MODULE_NAME, sd);
-       if (ret) {
-               dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
-               goto error;
-       }
-       info->res_type = M5MOLS_RESTYPE_MONITOR;
-       info->ffmt[0] = m5mols_default_ffmt[0];
-       info->ffmt[1] = m5mols_default_ffmt[1];
-
-       ret = m5mols_sensor_power(info, true);
-       if (ret)
-               goto error;
-
-       ret = m5mols_fw_start(sd);
-       if (!ret)
-               ret = m5mols_init_controls(sd);
-
-       ret = m5mols_sensor_power(info, false);
-       if (!ret)
-               return 0;
-error:
-       media_entity_cleanup(&sd->entity);
-       return ret;
-}
-
-static void m5mols_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-       v4l2_device_unregister_subdev(sd);
-       v4l2_ctrl_handler_free(sd->ctrl_handler);
-       media_entity_cleanup(&sd->entity);
-}
-
-static const struct i2c_device_id m5mols_id[] = {
-       { MODULE_NAME, 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(i2c, m5mols_id);
-
-static struct i2c_driver m5mols_i2c_driver = {
-       .driver = {
-               .name   = MODULE_NAME,
-       },
-       .probe_new      = m5mols_probe,
-       .remove         = m5mols_remove,
-       .id_table       = m5mols_id,
-};
-
-module_i2c_driver(m5mols_i2c_driver);
-
-MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
-MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>");
-MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/m5mols/m5mols_reg.h b/drivers/media/i2c/m5mols/m5mols_reg.h
deleted file mode 100644 (file)
index 947ee33..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Register map for M-5MOLS 8M Pixel camera sensor with ISP
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim <riverful.kim@samsung.com>
- *
- * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
- */
-
-#ifndef M5MOLS_REG_H
-#define M5MOLS_REG_H
-
-#define M5MOLS_I2C_MAX_SIZE    4
-#define M5MOLS_BYTE_READ       0x01
-#define M5MOLS_BYTE_WRITE      0x02
-
-#define I2C_CATEGORY(__cat)            ((__cat >> 16) & 0xff)
-#define I2C_COMMAND(__comm)            ((__comm >> 8) & 0xff)
-#define I2C_SIZE(__reg_s)              ((__reg_s) & 0xff)
-#define I2C_REG(__cat, __cmd, __reg_s) ((__cat << 16) | (__cmd << 8) | __reg_s)
-
-/*
- * Category section register
- *
- * The category means set including relevant command of M-5MOLS.
- */
-#define CAT_SYSTEM             0x00
-#define CAT_PARAM              0x01
-#define CAT_MONITOR            0x02
-#define CAT_AE                 0x03
-#define CAT_WB                 0x06
-#define CAT_EXIF               0x07
-#define CAT_FD                 0x09
-#define CAT_LENS               0x0a
-#define CAT_CAPT_PARM          0x0b
-#define CAT_CAPT_CTRL          0x0c
-#define CAT_FLASH              0x0f    /* related to FW, revisions, booting */
-
-/*
- * Category 0 - SYSTEM mode
- *
- * The SYSTEM mode in the M-5MOLS means area available to handle with the whole
- * & all-round system of sensor. It deals with version/interrupt/setting mode &
- * even sensor's status. Especially, the M-5MOLS sensor with ISP varies by
- * packaging & manufacturer, even the customer and project code. And the
- * function details may vary among them. The version information helps to
- * determine what methods shall be used in the driver.
- *
- * There is many registers between customer version address and awb one. For
- * more specific contents, see definition if file m5mols.h.
- */
-#define SYSTEM_VER_CUSTOMER    I2C_REG(CAT_SYSTEM, 0x00, 1)
-#define SYSTEM_VER_PROJECT     I2C_REG(CAT_SYSTEM, 0x01, 1)
-#define SYSTEM_VER_FIRMWARE    I2C_REG(CAT_SYSTEM, 0x02, 2)
-#define SYSTEM_VER_HARDWARE    I2C_REG(CAT_SYSTEM, 0x04, 2)
-#define SYSTEM_VER_PARAMETER   I2C_REG(CAT_SYSTEM, 0x06, 2)
-#define SYSTEM_VER_AWB         I2C_REG(CAT_SYSTEM, 0x08, 2)
-
-#define SYSTEM_SYSMODE         I2C_REG(CAT_SYSTEM, 0x0b, 1)
-#define REG_SYSINIT            0x00    /* SYSTEM mode */
-#define REG_PARAMETER          0x01    /* PARAMETER mode */
-#define REG_MONITOR            0x02    /* MONITOR mode */
-#define REG_CAPTURE            0x03    /* CAPTURE mode */
-
-#define SYSTEM_CMD(__cmd)      I2C_REG(CAT_SYSTEM, cmd, 1)
-#define SYSTEM_VER_STRING      I2C_REG(CAT_SYSTEM, 0x0a, 1)
-#define REG_SAMSUNG_ELECTRO    "SE"    /* Samsung Electro-Mechanics */
-#define REG_SAMSUNG_OPTICS     "OP"    /* Samsung Fiber-Optics */
-#define REG_SAMSUNG_TECHWIN    "TB"    /* Samsung Techwin */
-/* SYSTEM mode status */
-#define SYSTEM_STATUS  I2C_REG(CAT_SYSTEM, 0x0c, 1)
-
-/* Interrupt pending register */
-#define SYSTEM_INT_FACTOR      I2C_REG(CAT_SYSTEM, 0x10, 1)
-/* interrupt enable register */
-#define SYSTEM_INT_ENABLE      I2C_REG(CAT_SYSTEM, 0x11, 1)
-#define REG_INT_MODE           (1 << 0)
-#define REG_INT_AF             (1 << 1)
-#define REG_INT_ZOOM           (1 << 2)
-#define REG_INT_CAPTURE                (1 << 3)
-#define REG_INT_FRAMESYNC      (1 << 4)
-#define REG_INT_FD             (1 << 5)
-#define REG_INT_LENS_INIT      (1 << 6)
-#define REG_INT_SOUND          (1 << 7)
-#define REG_INT_MASK           0x0f
-
-/*
- * category 1 - PARAMETER mode
- *
- * This category supports function of camera features of M-5MOLS. It means we
- * can handle with preview(MONITOR) resolution size/frame per second/interface
- * between the sensor and the Application Processor/even the image effect.
- */
-
-/* Resolution in the MONITOR mode */
-#define PARM_MON_SIZE          I2C_REG(CAT_PARAM, 0x01, 1)
-
-/* Frame rate */
-#define PARM_MON_FPS           I2C_REG(CAT_PARAM, 0x02, 1)
-#define REG_FPS_30             0x02
-
-/* Video bus between the sensor and a host processor */
-#define PARM_INTERFACE         I2C_REG(CAT_PARAM, 0x00, 1)
-#define REG_INTERFACE_MIPI     0x02
-
-/* Image effects */
-#define PARM_EFFECT            I2C_REG(CAT_PARAM, 0x0b, 1)
-#define REG_EFFECT_OFF         0x00
-#define REG_EFFECT_NEGA                0x01
-#define REG_EFFECT_EMBOSS      0x06
-#define REG_EFFECT_OUTLINE     0x07
-#define REG_EFFECT_WATERCOLOR  0x08
-
-/*
- * Category 2 - MONITOR mode
- *
- * The MONITOR mode is same as preview mode as we said. The M-5MOLS has another
- * mode named "Preview", but this preview mode is used at the case specific
- * vider-recording mode. This mmode supports only YUYV format. On the other
- * hand, the JPEG & RAW formats is supports by CAPTURE mode. And, there are
- * another options like zoom/color effect(different with effect in PARAMETER
- * mode)/anti hand shaking algorithm.
- */
-
-/* Target digital zoom position */
-#define MON_ZOOM               I2C_REG(CAT_MONITOR, 0x01, 1)
-
-/* CR value for color effect */
-#define MON_CFIXR              I2C_REG(CAT_MONITOR, 0x0a, 1)
-/* CB value for color effect */
-#define MON_CFIXB              I2C_REG(CAT_MONITOR, 0x09, 1)
-#define REG_CFIXB_SEPIA                0xd8
-#define REG_CFIXR_SEPIA                0x18
-
-#define MON_EFFECT             I2C_REG(CAT_MONITOR, 0x0b, 1)
-#define REG_COLOR_EFFECT_OFF   0x00
-#define REG_COLOR_EFFECT_ON    0x01
-
-/* Chroma enable */
-#define MON_CHROMA_EN          I2C_REG(CAT_MONITOR, 0x10, 1)
-/* Chroma level */
-#define MON_CHROMA_LVL         I2C_REG(CAT_MONITOR, 0x0f, 1)
-#define REG_CHROMA_OFF         0x00
-#define REG_CHROMA_ON          0x01
-
-/* Sharpness on/off */
-#define MON_EDGE_EN            I2C_REG(CAT_MONITOR, 0x12, 1)
-/* Sharpness level */
-#define MON_EDGE_LVL           I2C_REG(CAT_MONITOR, 0x11, 1)
-#define REG_EDGE_OFF           0x00
-#define REG_EDGE_ON            0x01
-
-/* Set color tone (contrast) */
-#define MON_TONE_CTL           I2C_REG(CAT_MONITOR, 0x25, 1)
-
-/*
- * Category 3 - Auto Exposure
- *
- * The M-5MOLS exposure capbility is detailed as which is similar to digital
- * camera. This category supports AE locking/various AE mode(range of exposure)
- * /ISO/flickering/EV bias/shutter/meteoring, and anything else. And the
- * maximum/minimum exposure gain value depending on M-5MOLS firmware, may be
- * different. So, this category also provide getting the max/min values. And,
- * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values.
- */
-
-/* Auto Exposure locking */
-#define AE_LOCK                        I2C_REG(CAT_AE, 0x00, 1)
-#define REG_AE_UNLOCK          0x00
-#define REG_AE_LOCK            0x01
-
-/* Auto Exposure algorithm mode */
-#define AE_MODE                        I2C_REG(CAT_AE, 0x01, 1)
-#define REG_AE_OFF             0x00    /* AE off */
-#define REG_AE_ALL             0x01    /* calc AE in all block integral */
-#define REG_AE_CENTER          0x03    /* calc AE in center weighted */
-#define REG_AE_SPOT            0x06    /* calc AE in specific spot */
-
-#define AE_ISO                 I2C_REG(CAT_AE, 0x05, 1)
-#define REG_ISO_AUTO           0x00
-#define REG_ISO_50             0x01
-#define REG_ISO_100            0x02
-#define REG_ISO_200            0x03
-#define REG_ISO_400            0x04
-#define REG_ISO_800            0x05
-
-/* EV (scenemode) preset for MONITOR */
-#define AE_EV_PRESET_MONITOR   I2C_REG(CAT_AE, 0x0a, 1)
-/* EV (scenemode) preset for CAPTURE */
-#define AE_EV_PRESET_CAPTURE   I2C_REG(CAT_AE, 0x0b, 1)
-#define REG_SCENE_NORMAL       0x00
-#define REG_SCENE_PORTRAIT     0x01
-#define REG_SCENE_LANDSCAPE    0x02
-#define REG_SCENE_SPORTS       0x03
-#define REG_SCENE_PARTY_INDOOR 0x04
-#define REG_SCENE_BEACH_SNOW   0x05
-#define REG_SCENE_SUNSET       0x06
-#define REG_SCENE_DAWN_DUSK    0x07
-#define REG_SCENE_FALL         0x08
-#define REG_SCENE_NIGHT                0x09
-#define REG_SCENE_AGAINST_LIGHT        0x0a
-#define REG_SCENE_FIRE         0x0b
-#define REG_SCENE_TEXT         0x0c
-#define REG_SCENE_CANDLE       0x0d
-
-/* Manual gain in MONITOR mode */
-#define AE_MAN_GAIN_MON                I2C_REG(CAT_AE, 0x12, 2)
-/* Maximum gain in MONITOR mode */
-#define AE_MAX_GAIN_MON                I2C_REG(CAT_AE, 0x1a, 2)
-/* Manual gain in CAPTURE mode */
-#define AE_MAN_GAIN_CAP                I2C_REG(CAT_AE, 0x26, 2)
-
-#define AE_INDEX               I2C_REG(CAT_AE, 0x38, 1)
-#define REG_AE_INDEX_20_NEG    0x00
-#define REG_AE_INDEX_15_NEG    0x01
-#define REG_AE_INDEX_10_NEG    0x02
-#define REG_AE_INDEX_05_NEG    0x03
-#define REG_AE_INDEX_00                0x04
-#define REG_AE_INDEX_05_POS    0x05
-#define REG_AE_INDEX_10_POS    0x06
-#define REG_AE_INDEX_15_POS    0x07
-#define REG_AE_INDEX_20_POS    0x08
-
-/*
- * Category 6 - White Balance
- */
-
-/* Auto Whitebalance locking */
-#define AWB_LOCK               I2C_REG(CAT_WB, 0x00, 1)
-#define REG_AWB_UNLOCK         0x00
-#define REG_AWB_LOCK           0x01
-
-#define AWB_MODE               I2C_REG(CAT_WB, 0x02, 1)
-#define REG_AWB_AUTO           0x01    /* AWB off */
-#define REG_AWB_PRESET         0x02    /* AWB preset */
-
-/* Manual WB (preset) */
-#define AWB_MANUAL             I2C_REG(CAT_WB, 0x03, 1)
-#define REG_AWB_INCANDESCENT   0x01
-#define REG_AWB_FLUORESCENT_1  0x02
-#define REG_AWB_FLUORESCENT_2  0x03
-#define REG_AWB_DAYLIGHT       0x04
-#define REG_AWB_CLOUDY         0x05
-#define REG_AWB_SHADE          0x06
-#define REG_AWB_HORIZON                0x07
-#define REG_AWB_LEDLIGHT       0x09
-
-/*
- * Category 7 - EXIF information
- */
-#define EXIF_INFO_EXPTIME_NU   I2C_REG(CAT_EXIF, 0x00, 4)
-#define EXIF_INFO_EXPTIME_DE   I2C_REG(CAT_EXIF, 0x04, 4)
-#define EXIF_INFO_TV_NU                I2C_REG(CAT_EXIF, 0x08, 4)
-#define EXIF_INFO_TV_DE                I2C_REG(CAT_EXIF, 0x0c, 4)
-#define EXIF_INFO_AV_NU                I2C_REG(CAT_EXIF, 0x10, 4)
-#define EXIF_INFO_AV_DE                I2C_REG(CAT_EXIF, 0x14, 4)
-#define EXIF_INFO_BV_NU                I2C_REG(CAT_EXIF, 0x18, 4)
-#define EXIF_INFO_BV_DE                I2C_REG(CAT_EXIF, 0x1c, 4)
-#define EXIF_INFO_EBV_NU       I2C_REG(CAT_EXIF, 0x20, 4)
-#define EXIF_INFO_EBV_DE       I2C_REG(CAT_EXIF, 0x24, 4)
-#define EXIF_INFO_ISO          I2C_REG(CAT_EXIF, 0x28, 2)
-#define EXIF_INFO_FLASH                I2C_REG(CAT_EXIF, 0x2a, 2)
-#define EXIF_INFO_SDR          I2C_REG(CAT_EXIF, 0x2c, 2)
-#define EXIF_INFO_QVAL         I2C_REG(CAT_EXIF, 0x2e, 2)
-
-/*
- * Category 9 - Face Detection
- */
-#define FD_CTL                 I2C_REG(CAT_FD, 0x00, 1)
-#define BIT_FD_EN              0
-#define BIT_FD_DRAW_FACE_FRAME 4
-#define BIT_FD_DRAW_SMILE_LVL  6
-#define REG_FD(shift)          (1 << shift)
-#define REG_FD_OFF             0x0
-
-/*
- * Category A - Lens Parameter
- */
-#define AF_MODE                        I2C_REG(CAT_LENS, 0x01, 1)
-#define REG_AF_NORMAL          0x00    /* Normal AF, one time */
-#define REG_AF_MACRO           0x01    /* Macro AF, one time */
-#define REG_AF_POWEROFF                0x07
-
-#define AF_EXECUTE             I2C_REG(CAT_LENS, 0x02, 1)
-#define REG_AF_STOP            0x00
-#define REG_AF_EXE_AUTO                0x01
-#define REG_AF_EXE_CAF         0x02
-
-#define AF_STATUS              I2C_REG(CAT_LENS, 0x03, 1)
-#define REG_AF_FAIL            0x00
-#define REG_AF_SUCCESS         0x02
-#define REG_AF_IDLE            0x04
-#define REG_AF_BUSY            0x05
-
-#define AF_VERSION             I2C_REG(CAT_LENS, 0x0a, 1)
-
-/*
- * Category B - CAPTURE Parameter
- */
-#define CAPP_YUVOUT_MAIN       I2C_REG(CAT_CAPT_PARM, 0x00, 1)
-#define REG_YUV422             0x00
-#define REG_BAYER10            0x05
-#define REG_BAYER8             0x06
-#define REG_JPEG               0x10
-
-#define CAPP_MAIN_IMAGE_SIZE   I2C_REG(CAT_CAPT_PARM, 0x01, 1)
-#define CAPP_JPEG_SIZE_MAX     I2C_REG(CAT_CAPT_PARM, 0x0f, 4)
-#define CAPP_JPEG_RATIO                I2C_REG(CAT_CAPT_PARM, 0x17, 1)
-
-#define CAPP_MCC_MODE          I2C_REG(CAT_CAPT_PARM, 0x1d, 1)
-#define REG_MCC_OFF            0x00
-#define REG_MCC_NORMAL         0x01
-
-#define CAPP_WDR_EN            I2C_REG(CAT_CAPT_PARM, 0x2c, 1)
-#define REG_WDR_OFF            0x00
-#define REG_WDR_ON             0x01
-#define REG_WDR_AUTO           0x02
-
-#define CAPP_LIGHT_CTRL                I2C_REG(CAT_CAPT_PARM, 0x40, 1)
-#define REG_LIGHT_OFF          0x00
-#define REG_LIGHT_ON           0x01
-#define REG_LIGHT_AUTO         0x02
-
-#define CAPP_FLASH_CTRL                I2C_REG(CAT_CAPT_PARM, 0x41, 1)
-#define REG_FLASH_OFF          0x00
-#define REG_FLASH_ON           0x01
-#define REG_FLASH_AUTO         0x02
-
-/*
- * Category C - CAPTURE Control
- */
-#define CAPC_MODE              I2C_REG(CAT_CAPT_CTRL, 0x00, 1)
-#define REG_CAP_NONE           0x00
-#define REG_CAP_ANTI_SHAKE     0x02
-
-/* Select single- or multi-shot capture */
-#define CAPC_SEL_FRAME         I2C_REG(CAT_CAPT_CTRL, 0x06, 1)
-
-#define CAPC_START             I2C_REG(CAT_CAPT_CTRL, 0x09, 1)
-#define REG_CAP_START_MAIN     0x01
-#define REG_CAP_START_THUMB    0x03
-
-#define CAPC_IMAGE_SIZE                I2C_REG(CAT_CAPT_CTRL, 0x0d, 4)
-#define CAPC_THUMB_SIZE                I2C_REG(CAT_CAPT_CTRL, 0x11, 4)
-
-/*
- * Category F - Flash
- *
- * This mode provides functions about internal flash stuff and system startup.
- */
-
-/* Starts internal ARM core booting after power-up */
-#define FLASH_CAM_START                I2C_REG(CAT_FLASH, 0x12, 1)
-#define REG_START_ARM_BOOT     0x01    /* write value */
-#define REG_IN_FLASH_MODE      0x00    /* read value */
-
-#endif /* M5MOLS_REG_H */
index 701038d6d19b1cd032706de64ec10c736be11aed..13a986b885889faf0c3481e03539503fca3ad418 100644 (file)
@@ -1122,6 +1122,7 @@ err_async:
 static void max9286_v4l2_unregister(struct max9286_priv *priv)
 {
        fwnode_handle_put(priv->sd.fwnode);
+       v4l2_ctrl_handler_free(&priv->ctrls);
        v4l2_async_unregister_subdev(&priv->sd);
        max9286_v4l2_notifier_unregister(priv);
 }
diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c
deleted file mode 100644 (file)
index 958cfdd..0000000
+++ /dev/null
@@ -1,891 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Driver for MT9M032 CMOS Image Sensor from Micron
- *
- * Copyright (C) 2010-2011 Lund Engineering
- * Contact: Gil Lund <gwlund@lundeng.com>
- * Author: Martin Hostettler <martin@neutronstar.dyndns.org>
- */
-
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/math64.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/v4l2-mediabus.h>
-
-#include <media/media-entity.h>
-#include <media/i2c/mt9m032.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-subdev.h>
-
-#include "aptina-pll.h"
-
-/*
- * width and height include active boundary and black parts
- *
- * column    0-  15 active boundary
- * column   16-1455 image
- * column 1456-1471 active boundary
- * column 1472-1599 black
- *
- * row       0-  51 black
- * row      53-  59 active boundary
- * row      60-1139 image
- * row    1140-1147 active boundary
- * row    1148-1151 black
- */
-
-#define MT9M032_PIXEL_ARRAY_WIDTH                      1600
-#define MT9M032_PIXEL_ARRAY_HEIGHT                     1152
-
-#define MT9M032_CHIP_VERSION                           0x00
-#define                MT9M032_CHIP_VERSION_VALUE              0x1402
-#define MT9M032_ROW_START                              0x01
-#define                MT9M032_ROW_START_MIN                   0
-#define                MT9M032_ROW_START_MAX                   1152
-#define                MT9M032_ROW_START_DEF                   60
-#define MT9M032_COLUMN_START                           0x02
-#define                MT9M032_COLUMN_START_MIN                0
-#define                MT9M032_COLUMN_START_MAX                1600
-#define                MT9M032_COLUMN_START_DEF                16
-#define MT9M032_ROW_SIZE                               0x03
-#define                MT9M032_ROW_SIZE_MIN                    32
-#define                MT9M032_ROW_SIZE_MAX                    1152
-#define                MT9M032_ROW_SIZE_DEF                    1080
-#define MT9M032_COLUMN_SIZE                            0x04
-#define                MT9M032_COLUMN_SIZE_MIN                 32
-#define                MT9M032_COLUMN_SIZE_MAX                 1600
-#define                MT9M032_COLUMN_SIZE_DEF                 1440
-#define MT9M032_HBLANK                                 0x05
-#define MT9M032_VBLANK                                 0x06
-#define                MT9M032_VBLANK_MAX                      0x7ff
-#define MT9M032_SHUTTER_WIDTH_HIGH                     0x08
-#define MT9M032_SHUTTER_WIDTH_LOW                      0x09
-#define                MT9M032_SHUTTER_WIDTH_MIN               1
-#define                MT9M032_SHUTTER_WIDTH_MAX               1048575
-#define                MT9M032_SHUTTER_WIDTH_DEF               1943
-#define MT9M032_PIX_CLK_CTRL                           0x0a
-#define                MT9M032_PIX_CLK_CTRL_INV_PIXCLK         0x8000
-#define MT9M032_RESTART                                        0x0b
-#define MT9M032_RESET                                  0x0d
-#define MT9M032_PLL_CONFIG1                            0x11
-#define                MT9M032_PLL_CONFIG1_PREDIV_MASK         0x3f
-#define                MT9M032_PLL_CONFIG1_MUL_SHIFT           8
-#define MT9M032_READ_MODE1                             0x1e
-#define                MT9M032_READ_MODE1_OUTPUT_BAD_FRAMES    (1 << 13)
-#define                MT9M032_READ_MODE1_MAINTAIN_FRAME_RATE  (1 << 12)
-#define                MT9M032_READ_MODE1_XOR_LINE_VALID       (1 << 11)
-#define                MT9M032_READ_MODE1_CONT_LINE_VALID      (1 << 10)
-#define                MT9M032_READ_MODE1_INVERT_TRIGGER       (1 << 9)
-#define                MT9M032_READ_MODE1_SNAPSHOT             (1 << 8)
-#define                MT9M032_READ_MODE1_GLOBAL_RESET         (1 << 7)
-#define                MT9M032_READ_MODE1_BULB_EXPOSURE        (1 << 6)
-#define                MT9M032_READ_MODE1_INVERT_STROBE        (1 << 5)
-#define                MT9M032_READ_MODE1_STROBE_ENABLE        (1 << 4)
-#define                MT9M032_READ_MODE1_STROBE_START_TRIG1   (0 << 2)
-#define                MT9M032_READ_MODE1_STROBE_START_EXP     (1 << 2)
-#define                MT9M032_READ_MODE1_STROBE_START_SHUTTER (2 << 2)
-#define                MT9M032_READ_MODE1_STROBE_START_TRIG2   (3 << 2)
-#define                MT9M032_READ_MODE1_STROBE_END_TRIG1     (0 << 0)
-#define                MT9M032_READ_MODE1_STROBE_END_EXP       (1 << 0)
-#define                MT9M032_READ_MODE1_STROBE_END_SHUTTER   (2 << 0)
-#define                MT9M032_READ_MODE1_STROBE_END_TRIG2     (3 << 0)
-#define MT9M032_READ_MODE2                             0x20
-#define                MT9M032_READ_MODE2_VFLIP_SHIFT          15
-#define                MT9M032_READ_MODE2_HFLIP_SHIFT          14
-#define                MT9M032_READ_MODE2_ROW_BLC              0x40
-#define MT9M032_GAIN_GREEN1                            0x2b
-#define MT9M032_GAIN_BLUE                              0x2c
-#define MT9M032_GAIN_RED                               0x2d
-#define MT9M032_GAIN_GREEN2                            0x2e
-
-/* write only */
-#define MT9M032_GAIN_ALL                               0x35
-#define                MT9M032_GAIN_DIGITAL_MASK               0x7f
-#define                MT9M032_GAIN_DIGITAL_SHIFT              8
-#define                MT9M032_GAIN_AMUL_SHIFT                 6
-#define                MT9M032_GAIN_ANALOG_MASK                0x3f
-#define MT9M032_FORMATTER1                             0x9e
-#define                MT9M032_FORMATTER1_PLL_P1_6             (1 << 8)
-#define                MT9M032_FORMATTER1_PARALLEL             (1 << 12)
-#define MT9M032_FORMATTER2                             0x9f
-#define                MT9M032_FORMATTER2_DOUT_EN              0x1000
-#define                MT9M032_FORMATTER2_PIXCLK_EN            0x2000
-
-/*
- * The available MT9M032 datasheet is missing documentation for register 0x10
- * MT9P031 seems to be close enough, so use constants from that datasheet for
- * now.
- * But keep the name MT9P031 to remind us, that this isn't really confirmed
- * for this sensor.
- */
-#define MT9P031_PLL_CONTROL                            0x10
-#define                MT9P031_PLL_CONTROL_PWROFF              0x0050
-#define                MT9P031_PLL_CONTROL_PWRON               0x0051
-#define                MT9P031_PLL_CONTROL_USEPLL              0x0052
-
-struct mt9m032 {
-       struct v4l2_subdev subdev;
-       struct media_pad pad;
-       struct mt9m032_platform_data *pdata;
-
-       unsigned int pix_clock;
-
-       struct v4l2_ctrl_handler ctrls;
-       struct {
-               struct v4l2_ctrl *hflip;
-               struct v4l2_ctrl *vflip;
-       };
-
-       struct mutex lock; /* Protects streaming, format, interval and crop */
-
-       bool streaming;
-
-       struct v4l2_mbus_framefmt format;
-       struct v4l2_rect crop;
-       struct v4l2_fract frame_interval;
-};
-
-#define to_mt9m032(sd) container_of(sd, struct mt9m032, subdev)
-#define to_dev(sensor) \
-       (&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev)
-
-static int mt9m032_read(struct i2c_client *client, u8 reg)
-{
-       return i2c_smbus_read_word_swapped(client, reg);
-}
-
-static int mt9m032_write(struct i2c_client *client, u8 reg, const u16 data)
-{
-       return i2c_smbus_write_word_swapped(client, reg, data);
-}
-
-static u32 mt9m032_row_time(struct mt9m032 *sensor, unsigned int width)
-{
-       unsigned int effective_width;
-       u32 ns;
-
-       effective_width = width + 716; /* empirical value */
-       ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock);
-       dev_dbg(to_dev(sensor), "MT9M032 line time: %u ns\n", ns);
-       return ns;
-}
-
-static int mt9m032_update_timing(struct mt9m032 *sensor,
-                                struct v4l2_fract *interval)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
-       struct v4l2_rect *crop = &sensor->crop;
-       unsigned int min_vblank;
-       unsigned int vblank;
-       u32 row_time;
-
-       if (!interval)
-               interval = &sensor->frame_interval;
-
-       row_time = mt9m032_row_time(sensor, crop->width);
-
-       vblank = div_u64(1000000000ULL * interval->numerator,
-                        (u64)row_time * interval->denominator)
-              - crop->height;
-
-       if (vblank > MT9M032_VBLANK_MAX) {
-               /* hardware limits to 11 bit values */
-               interval->denominator = 1000;
-               interval->numerator =
-                       div_u64((crop->height + MT9M032_VBLANK_MAX) *
-                               (u64)row_time * interval->denominator,
-                               1000000000ULL);
-               vblank = div_u64(1000000000ULL * interval->numerator,
-                                (u64)row_time * interval->denominator)
-                      - crop->height;
-       }
-       /* enforce minimal 1.6ms blanking time. */
-       min_vblank = 1600000 / row_time;
-       vblank = clamp_t(unsigned int, vblank, min_vblank, MT9M032_VBLANK_MAX);
-
-       return mt9m032_write(client, MT9M032_VBLANK, vblank);
-}
-
-static int mt9m032_update_geom_timing(struct mt9m032 *sensor)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
-       int ret;
-
-       ret = mt9m032_write(client, MT9M032_COLUMN_SIZE,
-                           sensor->crop.width - 1);
-       if (!ret)
-               ret = mt9m032_write(client, MT9M032_ROW_SIZE,
-                                   sensor->crop.height - 1);
-       if (!ret)
-               ret = mt9m032_write(client, MT9M032_COLUMN_START,
-                                   sensor->crop.left);
-       if (!ret)
-               ret = mt9m032_write(client, MT9M032_ROW_START,
-                                   sensor->crop.top);
-       if (!ret)
-               ret = mt9m032_update_timing(sensor, NULL);
-       return ret;
-}
-
-static int update_formatter2(struct mt9m032 *sensor, bool streaming)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
-       u16 reg_val =   MT9M032_FORMATTER2_DOUT_EN
-                     | 0x0070;  /* parts reserved! */
-                                /* possibly for changing to 14-bit mode */
-
-       if (streaming)
-               reg_val |= MT9M032_FORMATTER2_PIXCLK_EN;   /* pixclock enable */
-
-       return mt9m032_write(client, MT9M032_FORMATTER2, reg_val);
-}
-
-static int mt9m032_setup_pll(struct mt9m032 *sensor)
-{
-       static const struct aptina_pll_limits limits = {
-               .ext_clock_min = 8000000,
-               .ext_clock_max = 16500000,
-               .int_clock_min = 2000000,
-               .int_clock_max = 24000000,
-               .out_clock_min = 322000000,
-               .out_clock_max = 693000000,
-               .pix_clock_max = 99000000,
-               .n_min = 1,
-               .n_max = 64,
-               .m_min = 16,
-               .m_max = 255,
-               .p1_min = 6,
-               .p1_max = 7,
-       };
-
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
-       struct mt9m032_platform_data *pdata = sensor->pdata;
-       struct aptina_pll pll;
-       u16 reg_val;
-       int ret;
-
-       pll.ext_clock = pdata->ext_clock;
-       pll.pix_clock = pdata->pix_clock;
-
-       ret = aptina_pll_calculate(&client->dev, &limits, &pll);
-       if (ret < 0)
-               return ret;
-
-       sensor->pix_clock = pdata->pix_clock;
-
-       ret = mt9m032_write(client, MT9M032_PLL_CONFIG1,
-                           (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT) |
-                           ((pll.n - 1) & MT9M032_PLL_CONFIG1_PREDIV_MASK));
-       if (!ret)
-               ret = mt9m032_write(client, MT9P031_PLL_CONTROL,
-                                   MT9P031_PLL_CONTROL_PWRON |
-                                   MT9P031_PLL_CONTROL_USEPLL);
-       if (!ret)               /* more reserved, Continuous, Master Mode */
-               ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8000 |
-                                   MT9M032_READ_MODE1_STROBE_START_EXP |
-                                   MT9M032_READ_MODE1_STROBE_END_SHUTTER);
-       if (!ret) {
-               reg_val = (pll.p1 == 6 ? MT9M032_FORMATTER1_PLL_P1_6 : 0)
-                       | MT9M032_FORMATTER1_PARALLEL | 0x001e; /* 14-bit */
-               ret = mt9m032_write(client, MT9M032_FORMATTER1, reg_val);
-       }
-
-       return ret;
-}
-
-/* -----------------------------------------------------------------------------
- * Subdev pad operations
- */
-
-static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_state *sd_state,
-                                 struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (code->index != 0)
-               return -EINVAL;
-
-       code->code = MEDIA_BUS_FMT_Y8_1X8;
-       return 0;
-}
-
-static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev,
-                                  struct v4l2_subdev_state *sd_state,
-                                  struct v4l2_subdev_frame_size_enum *fse)
-{
-       if (fse->index != 0 || fse->code != MEDIA_BUS_FMT_Y8_1X8)
-               return -EINVAL;
-
-       fse->min_width = MT9M032_COLUMN_SIZE_DEF;
-       fse->max_width = MT9M032_COLUMN_SIZE_DEF;
-       fse->min_height = MT9M032_ROW_SIZE_DEF;
-       fse->max_height = MT9M032_ROW_SIZE_DEF;
-
-       return 0;
-}
-
-/**
- * __mt9m032_get_pad_crop() - get crop rect
- * @sensor: pointer to the sensor struct
- * @sd_state: v4l2_subdev_state for getting the try crop rect from
- * @which: select try or active crop rect
- *
- * Returns a pointer the current active or fh relative try crop rect
- */
-static struct v4l2_rect *
-__mt9m032_get_pad_crop(struct mt9m032 *sensor,
-                      struct v4l2_subdev_state *sd_state,
-                      enum v4l2_subdev_format_whence which)
-{
-       switch (which) {
-       case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_crop(&sensor->subdev, sd_state, 0);
-       case V4L2_SUBDEV_FORMAT_ACTIVE:
-               return &sensor->crop;
-       default:
-               return NULL;
-       }
-}
-
-/**
- * __mt9m032_get_pad_format() - get format
- * @sensor: pointer to the sensor struct
- * @sd_state: v4l2_subdev_state for getting the try format from
- * @which: select try or active format
- *
- * Returns a pointer the current active or fh relative try format
- */
-static struct v4l2_mbus_framefmt *
-__mt9m032_get_pad_format(struct mt9m032 *sensor,
-                        struct v4l2_subdev_state *sd_state,
-                        enum v4l2_subdev_format_whence which)
-{
-       switch (which) {
-       case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_format(&sensor->subdev, sd_state,
-                                                 0);
-       case V4L2_SUBDEV_FORMAT_ACTIVE:
-               return &sensor->format;
-       default:
-               return NULL;
-       }
-}
-
-static int mt9m032_get_pad_format(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_state *sd_state,
-                                 struct v4l2_subdev_format *fmt)
-{
-       struct mt9m032 *sensor = to_mt9m032(subdev);
-
-       mutex_lock(&sensor->lock);
-       fmt->format = *__mt9m032_get_pad_format(sensor, sd_state, fmt->which);
-       mutex_unlock(&sensor->lock);
-
-       return 0;
-}
-
-static int mt9m032_set_pad_format(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_state *sd_state,
-                                 struct v4l2_subdev_format *fmt)
-{
-       struct mt9m032 *sensor = to_mt9m032(subdev);
-       int ret;
-
-       mutex_lock(&sensor->lock);
-
-       if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
-               ret = -EBUSY;
-               goto done;
-       }
-
-       /* Scaling is not supported, the format is thus fixed. */
-       fmt->format = *__mt9m032_get_pad_format(sensor, sd_state, fmt->which);
-       ret = 0;
-
-done:
-       mutex_unlock(&sensor->lock);
-       return ret;
-}
-
-static int mt9m032_get_pad_selection(struct v4l2_subdev *subdev,
-                                    struct v4l2_subdev_state *sd_state,
-                                    struct v4l2_subdev_selection *sel)
-{
-       struct mt9m032 *sensor = to_mt9m032(subdev);
-
-       if (sel->target != V4L2_SEL_TGT_CROP)
-               return -EINVAL;
-
-       mutex_lock(&sensor->lock);
-       sel->r = *__mt9m032_get_pad_crop(sensor, sd_state, sel->which);
-       mutex_unlock(&sensor->lock);
-
-       return 0;
-}
-
-static int mt9m032_set_pad_selection(struct v4l2_subdev *subdev,
-                                    struct v4l2_subdev_state *sd_state,
-                                    struct v4l2_subdev_selection *sel)
-{
-       struct mt9m032 *sensor = to_mt9m032(subdev);
-       struct v4l2_mbus_framefmt *format;
-       struct v4l2_rect *__crop;
-       struct v4l2_rect rect;
-       int ret = 0;
-
-       if (sel->target != V4L2_SEL_TGT_CROP)
-               return -EINVAL;
-
-       mutex_lock(&sensor->lock);
-
-       if (sensor->streaming && sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
-               ret = -EBUSY;
-               goto done;
-       }
-
-       /* Clamp the crop rectangle boundaries and align them to a multiple of 2
-        * pixels to ensure a GRBG Bayer pattern.
-        */
-       rect.left = clamp(ALIGN(sel->r.left, 2), MT9M032_COLUMN_START_MIN,
-                         MT9M032_COLUMN_START_MAX);
-       rect.top = clamp(ALIGN(sel->r.top, 2), MT9M032_ROW_START_MIN,
-                        MT9M032_ROW_START_MAX);
-       rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
-                            MT9M032_COLUMN_SIZE_MIN, MT9M032_COLUMN_SIZE_MAX);
-       rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
-                             MT9M032_ROW_SIZE_MIN, MT9M032_ROW_SIZE_MAX);
-
-       rect.width = min_t(unsigned int, rect.width,
-                          MT9M032_PIXEL_ARRAY_WIDTH - rect.left);
-       rect.height = min_t(unsigned int, rect.height,
-                           MT9M032_PIXEL_ARRAY_HEIGHT - rect.top);
-
-       __crop = __mt9m032_get_pad_crop(sensor, sd_state, sel->which);
-
-       if (rect.width != __crop->width || rect.height != __crop->height) {
-               /* Reset the output image size if the crop rectangle size has
-                * been modified.
-                */
-               format = __mt9m032_get_pad_format(sensor, sd_state,
-                                                 sel->which);
-               format->width = rect.width;
-               format->height = rect.height;
-       }
-
-       *__crop = rect;
-       sel->r = rect;
-
-       if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
-               ret = mt9m032_update_geom_timing(sensor);
-
-done:
-       mutex_unlock(&sensor->lock);
-       return ret;
-}
-
-static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev,
-                                     struct v4l2_subdev_frame_interval *fi)
-{
-       struct mt9m032 *sensor = to_mt9m032(subdev);
-
-       mutex_lock(&sensor->lock);
-       memset(fi, 0, sizeof(*fi));
-       fi->interval = sensor->frame_interval;
-       mutex_unlock(&sensor->lock);
-
-       return 0;
-}
-
-static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev,
-                                     struct v4l2_subdev_frame_interval *fi)
-{
-       struct mt9m032 *sensor = to_mt9m032(subdev);
-       int ret;
-
-       mutex_lock(&sensor->lock);
-
-       if (sensor->streaming) {
-               ret = -EBUSY;
-               goto done;
-       }
-
-       /* Avoid divisions by 0. */
-       if (fi->interval.denominator == 0)
-               fi->interval.denominator = 1;
-
-       ret = mt9m032_update_timing(sensor, &fi->interval);
-       if (!ret)
-               sensor->frame_interval = fi->interval;
-
-done:
-       mutex_unlock(&sensor->lock);
-       return ret;
-}
-
-static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming)
-{
-       struct mt9m032 *sensor = to_mt9m032(subdev);
-       int ret;
-
-       mutex_lock(&sensor->lock);
-       ret = update_formatter2(sensor, streaming);
-       if (!ret)
-               sensor->streaming = streaming;
-       mutex_unlock(&sensor->lock);
-
-       return ret;
-}
-
-/* -----------------------------------------------------------------------------
- * V4L2 subdev core operations
- */
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int mt9m032_g_register(struct v4l2_subdev *sd,
-                             struct v4l2_dbg_register *reg)
-{
-       struct mt9m032 *sensor = to_mt9m032(sd);
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
-       int val;
-
-       if (reg->reg > 0xff)
-               return -EINVAL;
-
-       val = mt9m032_read(client, reg->reg);
-       if (val < 0)
-               return -EIO;
-
-       reg->size = 2;
-       reg->val = val;
-
-       return 0;
-}
-
-static int mt9m032_s_register(struct v4l2_subdev *sd,
-                             const struct v4l2_dbg_register *reg)
-{
-       struct mt9m032 *sensor = to_mt9m032(sd);
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
-
-       if (reg->reg > 0xff)
-               return -EINVAL;
-
-       return mt9m032_write(client, reg->reg, reg->val);
-}
-#endif
-
-/* -----------------------------------------------------------------------------
- * V4L2 subdev control operations
- */
-
-static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
-       int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT)
-                   | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT)
-                   | MT9M032_READ_MODE2_ROW_BLC
-                   | 0x0007;
-
-       return mt9m032_write(client, MT9M032_READ_MODE2, reg_val);
-}
-
-static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
-       int digital_gain_val;   /* in 1/8th (0..127) */
-       int analog_mul;         /* 0 or 1 */
-       int analog_gain_val;    /* in 1/16th. (0..63) */
-       u16 reg_val;
-
-       digital_gain_val = 51; /* from setup example */
-
-       if (val < 63) {
-               analog_mul = 0;
-               analog_gain_val = val;
-       } else {
-               analog_mul = 1;
-               analog_gain_val = val / 2;
-       }
-
-       /* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */
-       /* overall_gain = a_gain * (1 + digital_gain_val / 8) */
-
-       reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK)
-                  << MT9M032_GAIN_DIGITAL_SHIFT)
-               | ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT)
-               | (analog_gain_val & MT9M032_GAIN_ANALOG_MASK);
-
-       return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val);
-}
-
-static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl)
-{
-       if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) {
-               /* round because of multiplier used for values >= 63 */
-               ctrl->val &= ~1;
-       }
-
-       return 0;
-}
-
-static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct mt9m032 *sensor =
-               container_of(ctrl->handler, struct mt9m032, ctrls);
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
-       int ret;
-
-       switch (ctrl->id) {
-       case V4L2_CID_GAIN:
-               return mt9m032_set_gain(sensor, ctrl->val);
-
-       case V4L2_CID_HFLIP:
-       /* case V4L2_CID_VFLIP: -- In the same cluster */
-               return update_read_mode2(sensor, sensor->vflip->val,
-                                        sensor->hflip->val);
-
-       case V4L2_CID_EXPOSURE:
-               ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH,
-                                   (ctrl->val >> 16) & 0xffff);
-               if (ret < 0)
-                       return ret;
-
-               return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW,
-                                    ctrl->val & 0xffff);
-       }
-
-       return 0;
-}
-
-static const struct v4l2_ctrl_ops mt9m032_ctrl_ops = {
-       .s_ctrl = mt9m032_set_ctrl,
-       .try_ctrl = mt9m032_try_ctrl,
-};
-
-/* -------------------------------------------------------------------------- */
-
-static const struct v4l2_subdev_core_ops mt9m032_core_ops = {
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .g_register = mt9m032_g_register,
-       .s_register = mt9m032_s_register,
-#endif
-};
-
-static const struct v4l2_subdev_video_ops mt9m032_video_ops = {
-       .s_stream = mt9m032_s_stream,
-       .g_frame_interval = mt9m032_get_frame_interval,
-       .s_frame_interval = mt9m032_set_frame_interval,
-};
-
-static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = {
-       .enum_mbus_code = mt9m032_enum_mbus_code,
-       .enum_frame_size = mt9m032_enum_frame_size,
-       .get_fmt = mt9m032_get_pad_format,
-       .set_fmt = mt9m032_set_pad_format,
-       .set_selection = mt9m032_set_pad_selection,
-       .get_selection = mt9m032_get_pad_selection,
-};
-
-static const struct v4l2_subdev_ops mt9m032_ops = {
-       .core = &mt9m032_core_ops,
-       .video = &mt9m032_video_ops,
-       .pad = &mt9m032_pad_ops,
-};
-
-/* -----------------------------------------------------------------------------
- * Driver initialization and probing
- */
-
-static int mt9m032_probe(struct i2c_client *client)
-{
-       struct mt9m032_platform_data *pdata = client->dev.platform_data;
-       struct i2c_adapter *adapter = client->adapter;
-       struct mt9m032 *sensor;
-       int chip_version;
-       int ret;
-
-       if (pdata == NULL) {
-               dev_err(&client->dev, "No platform data\n");
-               return -EINVAL;
-       }
-
-       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
-               dev_warn(&client->dev,
-                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
-               return -EIO;
-       }
-
-       if (!client->dev.platform_data)
-               return -ENODEV;
-
-       sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
-       if (sensor == NULL)
-               return -ENOMEM;
-
-       mutex_init(&sensor->lock);
-
-       sensor->pdata = pdata;
-
-       v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops);
-       sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-
-       chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION);
-       if (chip_version != MT9M032_CHIP_VERSION_VALUE) {
-               dev_err(&client->dev, "MT9M032 not detected, wrong version "
-                       "0x%04x\n", chip_version);
-               ret = -ENODEV;
-               goto error_sensor;
-       }
-
-       dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n",
-                client->addr);
-
-       sensor->frame_interval.numerator = 1;
-       sensor->frame_interval.denominator = 30;
-
-       sensor->crop.left = MT9M032_COLUMN_START_DEF;
-       sensor->crop.top = MT9M032_ROW_START_DEF;
-       sensor->crop.width = MT9M032_COLUMN_SIZE_DEF;
-       sensor->crop.height = MT9M032_ROW_SIZE_DEF;
-
-       sensor->format.width = sensor->crop.width;
-       sensor->format.height = sensor->crop.height;
-       sensor->format.code = MEDIA_BUS_FMT_Y8_1X8;
-       sensor->format.field = V4L2_FIELD_NONE;
-       sensor->format.colorspace = V4L2_COLORSPACE_SRGB;
-
-       v4l2_ctrl_handler_init(&sensor->ctrls, 5);
-
-       v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
-                         V4L2_CID_GAIN, 0, 127, 1, 64);
-
-       sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls,
-                                         &mt9m032_ctrl_ops,
-                                         V4L2_CID_HFLIP, 0, 1, 1, 0);
-       sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls,
-                                         &mt9m032_ctrl_ops,
-                                         V4L2_CID_VFLIP, 0, 1, 1, 0);
-
-       v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
-                         V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN,
-                         MT9M032_SHUTTER_WIDTH_MAX, 1,
-                         MT9M032_SHUTTER_WIDTH_DEF);
-       v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
-                         V4L2_CID_PIXEL_RATE, pdata->pix_clock,
-                         pdata->pix_clock, 1, pdata->pix_clock);
-
-       if (sensor->ctrls.error) {
-               ret = sensor->ctrls.error;
-               dev_err(&client->dev, "control initialization error %d\n", ret);
-               goto error_ctrl;
-       }
-
-       v4l2_ctrl_cluster(2, &sensor->hflip);
-
-       sensor->subdev.ctrl_handler = &sensor->ctrls;
-       sensor->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-       sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
-       ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad);
-       if (ret < 0)
-               goto error_ctrl;
-
-       ret = mt9m032_write(client, MT9M032_RESET, 1);  /* reset on */
-       if (ret < 0)
-               goto error_entity;
-       ret = mt9m032_write(client, MT9M032_RESET, 0);  /* reset off */
-       if (ret < 0)
-               goto error_entity;
-
-       ret = mt9m032_setup_pll(sensor);
-       if (ret < 0)
-               goto error_entity;
-       usleep_range(10000, 11000);
-
-       ret = v4l2_ctrl_handler_setup(&sensor->ctrls);
-       if (ret < 0)
-               goto error_entity;
-
-       /* SIZE */
-       ret = mt9m032_update_geom_timing(sensor);
-       if (ret < 0)
-               goto error_entity;
-
-       ret = mt9m032_write(client, 0x41, 0x0000);      /* reserved !!! */
-       if (ret < 0)
-               goto error_entity;
-       ret = mt9m032_write(client, 0x42, 0x0003);      /* reserved !!! */
-       if (ret < 0)
-               goto error_entity;
-       ret = mt9m032_write(client, 0x43, 0x0003);      /* reserved !!! */
-       if (ret < 0)
-               goto error_entity;
-       ret = mt9m032_write(client, 0x7f, 0x0000);      /* reserved !!! */
-       if (ret < 0)
-               goto error_entity;
-       if (sensor->pdata->invert_pixclock) {
-               ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL,
-                                   MT9M032_PIX_CLK_CTRL_INV_PIXCLK);
-               if (ret < 0)
-                       goto error_entity;
-       }
-
-       ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */
-       if (ret < 0)
-               goto error_entity;
-       msleep(100);
-       ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */
-       if (ret < 0)
-               goto error_entity;
-       msleep(100);
-       ret = update_formatter2(sensor, false);
-       if (ret < 0)
-               goto error_entity;
-
-       return ret;
-
-error_entity:
-       media_entity_cleanup(&sensor->subdev.entity);
-error_ctrl:
-       v4l2_ctrl_handler_free(&sensor->ctrls);
-error_sensor:
-       mutex_destroy(&sensor->lock);
-       return ret;
-}
-
-static void mt9m032_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
-       struct mt9m032 *sensor = to_mt9m032(subdev);
-
-       v4l2_device_unregister_subdev(subdev);
-       v4l2_ctrl_handler_free(&sensor->ctrls);
-       media_entity_cleanup(&subdev->entity);
-       mutex_destroy(&sensor->lock);
-}
-
-static const struct i2c_device_id mt9m032_id_table[] = {
-       { MT9M032_NAME, 0 },
-       { }
-};
-
-MODULE_DEVICE_TABLE(i2c, mt9m032_id_table);
-
-static struct i2c_driver mt9m032_i2c_driver = {
-       .driver = {
-               .name = MT9M032_NAME,
-       },
-       .probe_new = mt9m032_probe,
-       .remove = mt9m032_remove,
-       .id_table = mt9m032_id_table,
-};
-
-module_i2c_driver(mt9m032_i2c_driver);
-
-MODULE_AUTHOR("Martin Hostettler <martin@neutronstar.dyndns.org>");
-MODULE_DESCRIPTION("MT9M032 camera sensor driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c
deleted file mode 100644 (file)
index c635ed1..0000000
+++ /dev/null
@@ -1,992 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Driver for MT9T001 CMOS Image Sensor from Aptina (Micron)
- *
- * Copyright (C) 2010-2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
- *
- * Based on the MT9M001 driver,
- *
- * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
- */
-
-#include <linux/clk.h>
-#include <linux/i2c.h>
-#include <linux/log2.h>
-#include <linux/module.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include <linux/v4l2-mediabus.h>
-
-#include <media/i2c/mt9t001.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-subdev.h>
-
-#define MT9T001_PIXEL_ARRAY_HEIGHT                     1568
-#define MT9T001_PIXEL_ARRAY_WIDTH                      2112
-
-#define MT9T001_CHIP_VERSION                           0x00
-#define                MT9T001_CHIP_ID                         0x1621
-#define MT9T001_ROW_START                              0x01
-#define                MT9T001_ROW_START_MIN                   0
-#define                MT9T001_ROW_START_DEF                   20
-#define                MT9T001_ROW_START_MAX                   1534
-#define MT9T001_COLUMN_START                           0x02
-#define                MT9T001_COLUMN_START_MIN                0
-#define                MT9T001_COLUMN_START_DEF                32
-#define                MT9T001_COLUMN_START_MAX                2046
-#define MT9T001_WINDOW_HEIGHT                          0x03
-#define                MT9T001_WINDOW_HEIGHT_MIN               1
-#define                MT9T001_WINDOW_HEIGHT_DEF               1535
-#define                MT9T001_WINDOW_HEIGHT_MAX               1567
-#define MT9T001_WINDOW_WIDTH                           0x04
-#define                MT9T001_WINDOW_WIDTH_MIN                1
-#define                MT9T001_WINDOW_WIDTH_DEF                2047
-#define                MT9T001_WINDOW_WIDTH_MAX                2111
-#define MT9T001_HORIZONTAL_BLANKING                    0x05
-#define                MT9T001_HORIZONTAL_BLANKING_MIN         21
-#define                MT9T001_HORIZONTAL_BLANKING_MAX         1023
-#define MT9T001_VERTICAL_BLANKING                      0x06
-#define                MT9T001_VERTICAL_BLANKING_MIN           3
-#define                MT9T001_VERTICAL_BLANKING_MAX           1023
-#define MT9T001_OUTPUT_CONTROL                         0x07
-#define                MT9T001_OUTPUT_CONTROL_SYNC             (1 << 0)
-#define                MT9T001_OUTPUT_CONTROL_CHIP_ENABLE      (1 << 1)
-#define                MT9T001_OUTPUT_CONTROL_TEST_DATA        (1 << 6)
-#define                MT9T001_OUTPUT_CONTROL_DEF              0x0002
-#define MT9T001_SHUTTER_WIDTH_HIGH                     0x08
-#define MT9T001_SHUTTER_WIDTH_LOW                      0x09
-#define                MT9T001_SHUTTER_WIDTH_MIN               1
-#define                MT9T001_SHUTTER_WIDTH_DEF               1561
-#define                MT9T001_SHUTTER_WIDTH_MAX               (1024 * 1024)
-#define MT9T001_PIXEL_CLOCK                            0x0a
-#define                MT9T001_PIXEL_CLOCK_INVERT              (1 << 15)
-#define                MT9T001_PIXEL_CLOCK_SHIFT_MASK          (7 << 8)
-#define                MT9T001_PIXEL_CLOCK_SHIFT_SHIFT         8
-#define                MT9T001_PIXEL_CLOCK_DIVIDE_MASK         (0x7f << 0)
-#define MT9T001_FRAME_RESTART                          0x0b
-#define MT9T001_SHUTTER_DELAY                          0x0c
-#define                MT9T001_SHUTTER_DELAY_MAX               2047
-#define MT9T001_RESET                                  0x0d
-#define MT9T001_READ_MODE1                             0x1e
-#define                MT9T001_READ_MODE_SNAPSHOT              (1 << 8)
-#define                MT9T001_READ_MODE_STROBE_ENABLE         (1 << 9)
-#define                MT9T001_READ_MODE_STROBE_WIDTH          (1 << 10)
-#define                MT9T001_READ_MODE_STROBE_OVERRIDE       (1 << 11)
-#define MT9T001_READ_MODE2                             0x20
-#define                MT9T001_READ_MODE_BAD_FRAMES            (1 << 0)
-#define                MT9T001_READ_MODE_LINE_VALID_CONTINUOUS (1 << 9)
-#define                MT9T001_READ_MODE_LINE_VALID_FRAME      (1 << 10)
-#define MT9T001_READ_MODE3                             0x21
-#define                MT9T001_READ_MODE_GLOBAL_RESET          (1 << 0)
-#define                MT9T001_READ_MODE_GHST_CTL              (1 << 1)
-#define MT9T001_ROW_ADDRESS_MODE                       0x22
-#define                MT9T001_ROW_SKIP_MASK                   (7 << 0)
-#define                MT9T001_ROW_BIN_MASK                    (3 << 3)
-#define                MT9T001_ROW_BIN_SHIFT                   3
-#define MT9T001_COLUMN_ADDRESS_MODE                    0x23
-#define                MT9T001_COLUMN_SKIP_MASK                (7 << 0)
-#define                MT9T001_COLUMN_BIN_MASK                 (3 << 3)
-#define                MT9T001_COLUMN_BIN_SHIFT                3
-#define MT9T001_GREEN1_GAIN                            0x2b
-#define MT9T001_BLUE_GAIN                              0x2c
-#define MT9T001_RED_GAIN                               0x2d
-#define MT9T001_GREEN2_GAIN                            0x2e
-#define MT9T001_TEST_DATA                              0x32
-#define MT9T001_GLOBAL_GAIN                            0x35
-#define                MT9T001_GLOBAL_GAIN_MIN                 8
-#define                MT9T001_GLOBAL_GAIN_MAX                 1024
-#define MT9T001_BLACK_LEVEL                            0x49
-#define MT9T001_ROW_BLACK_DEFAULT_OFFSET               0x4b
-#define MT9T001_BLC_DELTA_THRESHOLDS                   0x5d
-#define MT9T001_CAL_THRESHOLDS                         0x5f
-#define MT9T001_GREEN1_OFFSET                          0x60
-#define MT9T001_GREEN2_OFFSET                          0x61
-#define MT9T001_BLACK_LEVEL_CALIBRATION                        0x62
-#define                MT9T001_BLACK_LEVEL_OVERRIDE            (1 << 0)
-#define                MT9T001_BLACK_LEVEL_DISABLE_OFFSET      (1 << 1)
-#define                MT9T001_BLACK_LEVEL_RECALCULATE         (1 << 12)
-#define                MT9T001_BLACK_LEVEL_LOCK_RED_BLUE       (1 << 13)
-#define                MT9T001_BLACK_LEVEL_LOCK_GREEN          (1 << 14)
-#define MT9T001_RED_OFFSET                             0x63
-#define MT9T001_BLUE_OFFSET                            0x64
-
-struct mt9t001 {
-       struct v4l2_subdev subdev;
-       struct media_pad pad;
-
-       struct clk *clk;
-       struct regulator_bulk_data regulators[2];
-
-       struct mutex power_lock; /* lock to protect power_count */
-       int power_count;
-
-       struct v4l2_mbus_framefmt format;
-       struct v4l2_rect crop;
-
-       struct v4l2_ctrl_handler ctrls;
-       struct v4l2_ctrl *gains[4];
-
-       u16 output_control;
-       u16 black_level;
-};
-
-static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct mt9t001, subdev);
-}
-
-static int mt9t001_read(struct i2c_client *client, u8 reg)
-{
-       return i2c_smbus_read_word_swapped(client, reg);
-}
-
-static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data)
-{
-       return i2c_smbus_write_word_swapped(client, reg, data);
-}
-
-static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
-                                     u16 set)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
-       u16 value = (mt9t001->output_control & ~clear) | set;
-       int ret;
-
-       if (value == mt9t001->output_control)
-               return 0;
-
-       ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, value);
-       if (ret < 0)
-               return ret;
-
-       mt9t001->output_control = value;
-       return 0;
-}
-
-static int mt9t001_reset(struct mt9t001 *mt9t001)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
-       int ret;
-
-       /* Reset the chip and stop data read out */
-       ret = mt9t001_write(client, MT9T001_RESET, 1);
-       if (ret < 0)
-               return ret;
-
-       ret = mt9t001_write(client, MT9T001_RESET, 0);
-       if (ret < 0)
-               return ret;
-
-       mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
-
-       return mt9t001_set_output_control(mt9t001,
-                                         MT9T001_OUTPUT_CONTROL_CHIP_ENABLE,
-                                         0);
-}
-
-static int mt9t001_power_on(struct mt9t001 *mt9t001)
-{
-       int ret;
-
-       /* Bring up the supplies */
-       ret = regulator_bulk_enable(ARRAY_SIZE(mt9t001->regulators),
-                                  mt9t001->regulators);
-       if (ret < 0)
-               return ret;
-
-       /* Enable clock */
-       ret = clk_prepare_enable(mt9t001->clk);
-       if (ret < 0)
-               regulator_bulk_disable(ARRAY_SIZE(mt9t001->regulators),
-                                      mt9t001->regulators);
-
-       return ret;
-}
-
-static void mt9t001_power_off(struct mt9t001 *mt9t001)
-{
-       regulator_bulk_disable(ARRAY_SIZE(mt9t001->regulators),
-                              mt9t001->regulators);
-
-       clk_disable_unprepare(mt9t001->clk);
-}
-
-static int __mt9t001_set_power(struct mt9t001 *mt9t001, bool on)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
-       int ret;
-
-       if (!on) {
-               mt9t001_power_off(mt9t001);
-               return 0;
-       }
-
-       ret = mt9t001_power_on(mt9t001);
-       if (ret < 0)
-               return ret;
-
-       ret = mt9t001_reset(mt9t001);
-       if (ret < 0) {
-               dev_err(&client->dev, "Failed to reset the camera\n");
-               goto e_power;
-       }
-
-       ret = v4l2_ctrl_handler_setup(&mt9t001->ctrls);
-       if (ret < 0) {
-               dev_err(&client->dev, "Failed to set up control handlers\n");
-               goto e_power;
-       }
-
-       return 0;
-
-e_power:
-       mt9t001_power_off(mt9t001);
-
-       return ret;
-}
-
-/* -----------------------------------------------------------------------------
- * V4L2 subdev video operations
- */
-
-static struct v4l2_mbus_framefmt *
-__mt9t001_get_pad_format(struct mt9t001 *mt9t001,
-                        struct v4l2_subdev_state *sd_state,
-                        unsigned int pad, enum v4l2_subdev_format_whence which)
-{
-       switch (which) {
-       case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_format(&mt9t001->subdev, sd_state,
-                                                 pad);
-       case V4L2_SUBDEV_FORMAT_ACTIVE:
-               return &mt9t001->format;
-       default:
-               return NULL;
-       }
-}
-
-static struct v4l2_rect *
-__mt9t001_get_pad_crop(struct mt9t001 *mt9t001,
-                      struct v4l2_subdev_state *sd_state,
-                      unsigned int pad, enum v4l2_subdev_format_whence which)
-{
-       switch (which) {
-       case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_crop(&mt9t001->subdev, sd_state,
-                                               pad);
-       case V4L2_SUBDEV_FORMAT_ACTIVE:
-               return &mt9t001->crop;
-       default:
-               return NULL;
-       }
-}
-
-static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
-{
-       const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE;
-       struct i2c_client *client = v4l2_get_subdevdata(subdev);
-       struct mt9t001_platform_data *pdata = client->dev.platform_data;
-       struct mt9t001 *mt9t001 = to_mt9t001(subdev);
-       struct v4l2_mbus_framefmt *format = &mt9t001->format;
-       struct v4l2_rect *crop = &mt9t001->crop;
-       unsigned int hratio;
-       unsigned int vratio;
-       int ret;
-
-       if (!enable)
-               return mt9t001_set_output_control(mt9t001, mode, 0);
-
-       /* Configure the pixel clock polarity */
-       if (pdata->clk_pol) {
-               ret  = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
-                                    MT9T001_PIXEL_CLOCK_INVERT);
-               if (ret < 0)
-                       return ret;
-       }
-
-       /* Configure the window size and row/column bin */
-       hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
-       vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
-
-       ret = mt9t001_write(client, MT9T001_ROW_ADDRESS_MODE, hratio - 1);
-       if (ret < 0)
-               return ret;
-
-       ret = mt9t001_write(client, MT9T001_COLUMN_ADDRESS_MODE, vratio - 1);
-       if (ret < 0)
-               return ret;
-
-       ret = mt9t001_write(client, MT9T001_COLUMN_START, crop->left);
-       if (ret < 0)
-               return ret;
-
-       ret = mt9t001_write(client, MT9T001_ROW_START, crop->top);
-       if (ret < 0)
-               return ret;
-
-       ret = mt9t001_write(client, MT9T001_WINDOW_WIDTH, crop->width - 1);
-       if (ret < 0)
-               return ret;
-
-       ret = mt9t001_write(client, MT9T001_WINDOW_HEIGHT, crop->height - 1);
-       if (ret < 0)
-               return ret;
-
-       /* Switch to master "normal" mode */
-       return mt9t001_set_output_control(mt9t001, 0, mode);
-}
-
-static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_state *sd_state,
-                                 struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (code->index > 0)
-               return -EINVAL;
-
-       code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
-       return 0;
-}
-
-static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
-                                  struct v4l2_subdev_state *sd_state,
-                                  struct v4l2_subdev_frame_size_enum *fse)
-{
-       if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
-               return -EINVAL;
-
-       fse->min_width = (MT9T001_WINDOW_WIDTH_DEF + 1) / fse->index;
-       fse->max_width = fse->min_width;
-       fse->min_height = (MT9T001_WINDOW_HEIGHT_DEF + 1) / fse->index;
-       fse->max_height = fse->min_height;
-
-       return 0;
-}
-
-static int mt9t001_get_format(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_state *sd_state,
-                             struct v4l2_subdev_format *format)
-{
-       struct mt9t001 *mt9t001 = to_mt9t001(subdev);
-
-       format->format = *__mt9t001_get_pad_format(mt9t001, sd_state,
-                                                  format->pad,
-                                                  format->which);
-       return 0;
-}
-
-static int mt9t001_set_format(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_state *sd_state,
-                             struct v4l2_subdev_format *format)
-{
-       struct mt9t001 *mt9t001 = to_mt9t001(subdev);
-       struct v4l2_mbus_framefmt *__format;
-       struct v4l2_rect *__crop;
-       unsigned int width;
-       unsigned int height;
-       unsigned int hratio;
-       unsigned int vratio;
-
-       __crop = __mt9t001_get_pad_crop(mt9t001, sd_state, format->pad,
-                                       format->which);
-
-       /* Clamp the width and height to avoid dividing by zero. */
-       width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
-                       max_t(unsigned int, __crop->width / 8,
-                             MT9T001_WINDOW_HEIGHT_MIN + 1),
-                       __crop->width);
-       height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
-                        max_t(unsigned int, __crop->height / 8,
-                              MT9T001_WINDOW_HEIGHT_MIN + 1),
-                        __crop->height);
-
-       hratio = DIV_ROUND_CLOSEST(__crop->width, width);
-       vratio = DIV_ROUND_CLOSEST(__crop->height, height);
-
-       __format = __mt9t001_get_pad_format(mt9t001, sd_state, format->pad,
-                                           format->which);
-       __format->width = __crop->width / hratio;
-       __format->height = __crop->height / vratio;
-
-       format->format = *__format;
-
-       return 0;
-}
-
-static int mt9t001_get_selection(struct v4l2_subdev *subdev,
-                                struct v4l2_subdev_state *sd_state,
-                                struct v4l2_subdev_selection *sel)
-{
-       struct mt9t001 *mt9t001 = to_mt9t001(subdev);
-
-       if (sel->target != V4L2_SEL_TGT_CROP)
-               return -EINVAL;
-
-       sel->r = *__mt9t001_get_pad_crop(mt9t001, sd_state, sel->pad,
-                                        sel->which);
-       return 0;
-}
-
-static int mt9t001_set_selection(struct v4l2_subdev *subdev,
-                                struct v4l2_subdev_state *sd_state,
-                                struct v4l2_subdev_selection *sel)
-{
-       struct mt9t001 *mt9t001 = to_mt9t001(subdev);
-       struct v4l2_mbus_framefmt *__format;
-       struct v4l2_rect *__crop;
-       struct v4l2_rect rect;
-
-       if (sel->target != V4L2_SEL_TGT_CROP)
-               return -EINVAL;
-
-       /* Clamp the crop rectangle boundaries and align them to a multiple of 2
-        * pixels.
-        */
-       rect.left = clamp(ALIGN(sel->r.left, 2),
-                         MT9T001_COLUMN_START_MIN,
-                         MT9T001_COLUMN_START_MAX);
-       rect.top = clamp(ALIGN(sel->r.top, 2),
-                        MT9T001_ROW_START_MIN,
-                        MT9T001_ROW_START_MAX);
-       rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
-                            MT9T001_WINDOW_WIDTH_MIN + 1,
-                            MT9T001_WINDOW_WIDTH_MAX + 1);
-       rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
-                             MT9T001_WINDOW_HEIGHT_MIN + 1,
-                             MT9T001_WINDOW_HEIGHT_MAX + 1);
-
-       rect.width = min_t(unsigned int, rect.width,
-                          MT9T001_PIXEL_ARRAY_WIDTH - rect.left);
-       rect.height = min_t(unsigned int, rect.height,
-                           MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
-
-       __crop = __mt9t001_get_pad_crop(mt9t001, sd_state, sel->pad,
-                                       sel->which);
-
-       if (rect.width != __crop->width || rect.height != __crop->height) {
-               /* Reset the output image size if the crop rectangle size has
-                * been modified.
-                */
-               __format = __mt9t001_get_pad_format(mt9t001, sd_state,
-                                                   sel->pad,
-                                                   sel->which);
-               __format->width = rect.width;
-               __format->height = rect.height;
-       }
-
-       *__crop = rect;
-       sel->r = rect;
-
-       return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * V4L2 subdev control operations
- */
-
-#define V4L2_CID_TEST_PATTERN_COLOR    (V4L2_CID_USER_BASE | 0x1001)
-#define V4L2_CID_BLACK_LEVEL_AUTO      (V4L2_CID_USER_BASE | 0x1002)
-#define V4L2_CID_BLACK_LEVEL_OFFSET    (V4L2_CID_USER_BASE | 0x1003)
-#define V4L2_CID_BLACK_LEVEL_CALIBRATE (V4L2_CID_USER_BASE | 0x1004)
-
-#define V4L2_CID_GAIN_RED              (V4L2_CTRL_CLASS_CAMERA | 0x1001)
-#define V4L2_CID_GAIN_GREEN_RED                (V4L2_CTRL_CLASS_CAMERA | 0x1002)
-#define V4L2_CID_GAIN_GREEN_BLUE       (V4L2_CTRL_CLASS_CAMERA | 0x1003)
-#define V4L2_CID_GAIN_BLUE             (V4L2_CTRL_CLASS_CAMERA | 0x1004)
-
-static u16 mt9t001_gain_value(s32 *gain)
-{
-       /* Gain is controlled by 2 analog stages and a digital stage. Valid
-        * values for the 3 stages are
-        *
-        * Stage                Min     Max     Step
-        * ------------------------------------------
-        * First analog stage   x1      x2      1
-        * Second analog stage  x1      x4      0.125
-        * Digital stage        x1      x16     0.125
-        *
-        * To minimize noise, the gain stages should be used in the second
-        * analog stage, first analog stage, digital stage order. Gain from a
-        * previous stage should be pushed to its maximum value before the next
-        * stage is used.
-        */
-       if (*gain <= 32)
-               return *gain;
-
-       if (*gain <= 64) {
-               *gain &= ~1;
-               return (1 << 6) | (*gain >> 1);
-       }
-
-       *gain &= ~7;
-       return ((*gain - 64) << 5) | (1 << 6) | 32;
-}
-
-static int mt9t001_ctrl_freeze(struct mt9t001 *mt9t001, bool freeze)
-{
-       return mt9t001_set_output_control(mt9t001,
-               freeze ? 0 : MT9T001_OUTPUT_CONTROL_SYNC,
-               freeze ? MT9T001_OUTPUT_CONTROL_SYNC : 0);
-}
-
-static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       static const u8 gains[4] = {
-               MT9T001_RED_GAIN, MT9T001_GREEN1_GAIN,
-               MT9T001_GREEN2_GAIN, MT9T001_BLUE_GAIN
-       };
-
-       struct mt9t001 *mt9t001 =
-                       container_of(ctrl->handler, struct mt9t001, ctrls);
-       struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
-       unsigned int count;
-       unsigned int i;
-       u16 value;
-       int ret;
-
-       switch (ctrl->id) {
-       case V4L2_CID_GAIN_RED:
-       case V4L2_CID_GAIN_GREEN_RED:
-       case V4L2_CID_GAIN_GREEN_BLUE:
-       case V4L2_CID_GAIN_BLUE:
-
-               /* Disable control updates if more than one control has changed
-                * in the cluster.
-                */
-               for (i = 0, count = 0; i < 4; ++i) {
-                       struct v4l2_ctrl *gain = mt9t001->gains[i];
-
-                       if (gain->val != gain->cur.val)
-                               count++;
-               }
-
-               if (count > 1) {
-                       ret = mt9t001_ctrl_freeze(mt9t001, true);
-                       if (ret < 0)
-                               return ret;
-               }
-
-               /* Update the gain controls. */
-               for (i = 0; i < 4; ++i) {
-                       struct v4l2_ctrl *gain = mt9t001->gains[i];
-
-                       if (gain->val == gain->cur.val)
-                               continue;
-
-                       value = mt9t001_gain_value(&gain->val);
-                       ret = mt9t001_write(client, gains[i], value);
-                       if (ret < 0) {
-                               mt9t001_ctrl_freeze(mt9t001, false);
-                               return ret;
-                       }
-               }
-
-               /* Enable control updates. */
-               if (count > 1) {
-                       ret = mt9t001_ctrl_freeze(mt9t001, false);
-                       if (ret < 0)
-                               return ret;
-               }
-
-               break;
-
-       case V4L2_CID_EXPOSURE:
-               ret = mt9t001_write(client, MT9T001_SHUTTER_WIDTH_LOW,
-                                   ctrl->val & 0xffff);
-               if (ret < 0)
-                       return ret;
-
-               return mt9t001_write(client, MT9T001_SHUTTER_WIDTH_HIGH,
-                                    ctrl->val >> 16);
-
-       case V4L2_CID_TEST_PATTERN:
-               return mt9t001_set_output_control(mt9t001,
-                       ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
-                       ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
-
-       case V4L2_CID_TEST_PATTERN_COLOR:
-               return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
-
-       case V4L2_CID_BLACK_LEVEL_AUTO:
-               value = ctrl->val ? 0 : MT9T001_BLACK_LEVEL_OVERRIDE;
-               ret = mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
-                                   value);
-               if (ret < 0)
-                       return ret;
-
-               mt9t001->black_level = value;
-               break;
-
-       case V4L2_CID_BLACK_LEVEL_OFFSET:
-               ret = mt9t001_write(client, MT9T001_GREEN1_OFFSET, ctrl->val);
-               if (ret < 0)
-                       return ret;
-
-               ret = mt9t001_write(client, MT9T001_GREEN2_OFFSET, ctrl->val);
-               if (ret < 0)
-                       return ret;
-
-               ret = mt9t001_write(client, MT9T001_RED_OFFSET, ctrl->val);
-               if (ret < 0)
-                       return ret;
-
-               return mt9t001_write(client, MT9T001_BLUE_OFFSET, ctrl->val);
-
-       case V4L2_CID_BLACK_LEVEL_CALIBRATE:
-               return mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
-                                    MT9T001_BLACK_LEVEL_RECALCULATE |
-                                    mt9t001->black_level);
-       }
-
-       return 0;
-}
-
-static const struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
-       .s_ctrl = mt9t001_s_ctrl,
-};
-
-static const char * const mt9t001_test_pattern_menu[] = {
-       "Disabled",
-       "Enabled",
-};
-
-static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
-       {
-               .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN_COLOR,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Test Pattern Color",
-               .min            = 0,
-               .max            = 1023,
-               .step           = 1,
-               .def            = 0,
-               .flags          = 0,
-       }, {
-               .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_BLACK_LEVEL_AUTO,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Black Level, Auto",
-               .min            = 0,
-               .max            = 1,
-               .step           = 1,
-               .def            = 1,
-               .flags          = 0,
-       }, {
-               .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_BLACK_LEVEL_OFFSET,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Black Level, Offset",
-               .min            = -256,
-               .max            = 255,
-               .step           = 1,
-               .def            = 32,
-               .flags          = 0,
-       }, {
-               .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_BLACK_LEVEL_CALIBRATE,
-               .type           = V4L2_CTRL_TYPE_BUTTON,
-               .name           = "Black Level, Calibrate",
-               .min            = 0,
-               .max            = 0,
-               .step           = 0,
-               .def            = 0,
-               .flags          = V4L2_CTRL_FLAG_WRITE_ONLY,
-       },
-};
-
-static const struct v4l2_ctrl_config mt9t001_gains[] = {
-       {
-               .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_GAIN_RED,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gain, Red",
-               .min            = MT9T001_GLOBAL_GAIN_MIN,
-               .max            = MT9T001_GLOBAL_GAIN_MAX,
-               .step           = 1,
-               .def            = MT9T001_GLOBAL_GAIN_MIN,
-               .flags          = 0,
-       }, {
-               .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_GAIN_GREEN_RED,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gain, Green (R)",
-               .min            = MT9T001_GLOBAL_GAIN_MIN,
-               .max            = MT9T001_GLOBAL_GAIN_MAX,
-               .step           = 1,
-               .def            = MT9T001_GLOBAL_GAIN_MIN,
-               .flags          = 0,
-       }, {
-               .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_GAIN_GREEN_BLUE,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gain, Green (B)",
-               .min            = MT9T001_GLOBAL_GAIN_MIN,
-               .max            = MT9T001_GLOBAL_GAIN_MAX,
-               .step           = 1,
-               .def            = MT9T001_GLOBAL_GAIN_MIN,
-               .flags          = 0,
-       }, {
-               .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_GAIN_BLUE,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gain, Blue",
-               .min            = MT9T001_GLOBAL_GAIN_MIN,
-               .max            = MT9T001_GLOBAL_GAIN_MAX,
-               .step           = 1,
-               .def            = MT9T001_GLOBAL_GAIN_MIN,
-               .flags          = 0,
-       },
-};
-
-/* -----------------------------------------------------------------------------
- * V4L2 subdev core operations
- */
-
-static int mt9t001_set_power(struct v4l2_subdev *subdev, int on)
-{
-       struct mt9t001 *mt9t001 = to_mt9t001(subdev);
-       int ret = 0;
-
-       mutex_lock(&mt9t001->power_lock);
-
-       /* If the power count is modified from 0 to != 0 or from != 0 to 0,
-        * update the power state.
-        */
-       if (mt9t001->power_count == !on) {
-               ret = __mt9t001_set_power(mt9t001, !!on);
-               if (ret < 0)
-                       goto out;
-       }
-
-       /* Update the power count. */
-       mt9t001->power_count += on ? 1 : -1;
-       WARN_ON(mt9t001->power_count < 0);
-
-out:
-       mutex_unlock(&mt9t001->power_lock);
-       return ret;
-}
-
-/* -----------------------------------------------------------------------------
- * V4L2 subdev internal operations
- */
-
-static int mt9t001_registered(struct v4l2_subdev *subdev)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(subdev);
-       struct mt9t001 *mt9t001 = to_mt9t001(subdev);
-       s32 data;
-       int ret;
-
-       ret = mt9t001_power_on(mt9t001);
-       if (ret < 0) {
-               dev_err(&client->dev, "MT9T001 power up failed\n");
-               return ret;
-       }
-
-       /* Read out the chip version register */
-       data = mt9t001_read(client, MT9T001_CHIP_VERSION);
-       mt9t001_power_off(mt9t001);
-
-       if (data != MT9T001_CHIP_ID) {
-               dev_err(&client->dev,
-                       "MT9T001 not detected, wrong version 0x%04x\n", data);
-               return -ENODEV;
-       }
-
-       dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
-                client->addr);
-
-       return 0;
-}
-
-static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
-{
-       struct v4l2_mbus_framefmt *format;
-       struct v4l2_rect *crop;
-
-       crop = v4l2_subdev_get_try_crop(subdev, fh->state, 0);
-       crop->left = MT9T001_COLUMN_START_DEF;
-       crop->top = MT9T001_ROW_START_DEF;
-       crop->width = MT9T001_WINDOW_WIDTH_DEF + 1;
-       crop->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
-
-       format = v4l2_subdev_get_try_format(subdev, fh->state, 0);
-       format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
-       format->width = MT9T001_WINDOW_WIDTH_DEF + 1;
-       format->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
-       format->field = V4L2_FIELD_NONE;
-       format->colorspace = V4L2_COLORSPACE_SRGB;
-
-       return mt9t001_set_power(subdev, 1);
-}
-
-static int mt9t001_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
-{
-       return mt9t001_set_power(subdev, 0);
-}
-
-static const struct v4l2_subdev_core_ops mt9t001_subdev_core_ops = {
-       .s_power = mt9t001_set_power,
-};
-
-static const struct v4l2_subdev_video_ops mt9t001_subdev_video_ops = {
-       .s_stream = mt9t001_s_stream,
-};
-
-static const struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
-       .enum_mbus_code = mt9t001_enum_mbus_code,
-       .enum_frame_size = mt9t001_enum_frame_size,
-       .get_fmt = mt9t001_get_format,
-       .set_fmt = mt9t001_set_format,
-       .get_selection = mt9t001_get_selection,
-       .set_selection = mt9t001_set_selection,
-};
-
-static const struct v4l2_subdev_ops mt9t001_subdev_ops = {
-       .core = &mt9t001_subdev_core_ops,
-       .video = &mt9t001_subdev_video_ops,
-       .pad = &mt9t001_subdev_pad_ops,
-};
-
-static const struct v4l2_subdev_internal_ops mt9t001_subdev_internal_ops = {
-       .registered = mt9t001_registered,
-       .open = mt9t001_open,
-       .close = mt9t001_close,
-};
-
-static int mt9t001_probe(struct i2c_client *client)
-{
-       struct mt9t001_platform_data *pdata = client->dev.platform_data;
-       struct mt9t001 *mt9t001;
-       unsigned int i;
-       int ret;
-
-       if (pdata == NULL) {
-               dev_err(&client->dev, "No platform data\n");
-               return -EINVAL;
-       }
-
-       if (!i2c_check_functionality(client->adapter,
-                                    I2C_FUNC_SMBUS_WORD_DATA)) {
-               dev_warn(&client->adapter->dev,
-                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
-               return -EIO;
-       }
-
-       mt9t001 = devm_kzalloc(&client->dev, sizeof(*mt9t001), GFP_KERNEL);
-       if (!mt9t001)
-               return -ENOMEM;
-
-       mutex_init(&mt9t001->power_lock);
-       mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
-
-       mt9t001->regulators[0].supply = "vdd";
-       mt9t001->regulators[1].supply = "vaa";
-
-       ret = devm_regulator_bulk_get(&client->dev, 2, mt9t001->regulators);
-       if (ret < 0) {
-               dev_err(&client->dev, "Unable to get regulators\n");
-               return ret;
-       }
-
-       mt9t001->clk = devm_clk_get(&client->dev, NULL);
-       if (IS_ERR(mt9t001->clk)) {
-               dev_err(&client->dev, "Unable to get clock\n");
-               return PTR_ERR(mt9t001->clk);
-       }
-
-       v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
-                                               ARRAY_SIZE(mt9t001_gains) + 4);
-
-       v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
-                         V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
-                         MT9T001_SHUTTER_WIDTH_MAX, 1,
-                         MT9T001_SHUTTER_WIDTH_DEF);
-       v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
-                         V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1);
-       v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
-                         V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
-                         1, pdata->ext_clk);
-       v4l2_ctrl_new_std_menu_items(&mt9t001->ctrls, &mt9t001_ctrl_ops,
-                       V4L2_CID_TEST_PATTERN,
-                       ARRAY_SIZE(mt9t001_test_pattern_menu) - 1, 0,
-                       0, mt9t001_test_pattern_menu);
-
-       for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
-               v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
-
-       for (i = 0; i < ARRAY_SIZE(mt9t001_gains); ++i)
-               mt9t001->gains[i] = v4l2_ctrl_new_custom(&mt9t001->ctrls,
-                       &mt9t001_gains[i], NULL);
-
-       v4l2_ctrl_cluster(ARRAY_SIZE(mt9t001_gains), mt9t001->gains);
-
-       mt9t001->subdev.ctrl_handler = &mt9t001->ctrls;
-
-       if (mt9t001->ctrls.error) {
-               printk(KERN_INFO "%s: control initialization error %d\n",
-                      __func__, mt9t001->ctrls.error);
-               ret = -EINVAL;
-               goto done;
-       }
-
-       mt9t001->crop.left = MT9T001_COLUMN_START_DEF;
-       mt9t001->crop.top = MT9T001_ROW_START_DEF;
-       mt9t001->crop.width = MT9T001_WINDOW_WIDTH_DEF + 1;
-       mt9t001->crop.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
-
-       mt9t001->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
-       mt9t001->format.width = MT9T001_WINDOW_WIDTH_DEF + 1;
-       mt9t001->format.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
-       mt9t001->format.field = V4L2_FIELD_NONE;
-       mt9t001->format.colorspace = V4L2_COLORSPACE_SRGB;
-
-       v4l2_i2c_subdev_init(&mt9t001->subdev, client, &mt9t001_subdev_ops);
-       mt9t001->subdev.internal_ops = &mt9t001_subdev_internal_ops;
-       mt9t001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-
-       mt9t001->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-       mt9t001->pad.flags = MEDIA_PAD_FL_SOURCE;
-       ret = media_entity_pads_init(&mt9t001->subdev.entity, 1, &mt9t001->pad);
-
-done:
-       if (ret < 0) {
-               v4l2_ctrl_handler_free(&mt9t001->ctrls);
-               media_entity_cleanup(&mt9t001->subdev.entity);
-       }
-
-       return ret;
-}
-
-static void mt9t001_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
-       struct mt9t001 *mt9t001 = to_mt9t001(subdev);
-
-       v4l2_ctrl_handler_free(&mt9t001->ctrls);
-       v4l2_device_unregister_subdev(subdev);
-       media_entity_cleanup(&subdev->entity);
-}
-
-static const struct i2c_device_id mt9t001_id[] = {
-       { "mt9t001", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, mt9t001_id);
-
-static struct i2c_driver mt9t001_driver = {
-       .driver = {
-               .name = "mt9t001",
-       },
-       .probe_new      = mt9t001_probe,
-       .remove         = mt9t001_remove,
-       .id_table       = mt9t001_id,
-};
-
-module_i2c_driver(mt9t001_driver);
-
-MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver");
-MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c
deleted file mode 100644 (file)
index 144bef2..0000000
+++ /dev/null
@@ -1,821 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Driver for SiliconFile NOON010PC30 CIF (1/11") Image Sensor with ISP
- *
- * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd.
- * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
- *
- * Initial register configuration based on a driver authored by
- * HeungJun Kim <riverful.kim@samsung.com>.
- */
-
-#include <linux/delay.h>
-#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
-#include <media/i2c/noon010pc30.h>
-#include <linux/videodev2.h>
-#include <linux/module.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-mediabus.h>
-#include <media/v4l2-subdev.h>
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable module debug trace. Set to 1 to enable.");
-
-#define MODULE_NAME            "NOON010PC30"
-
-/*
- * Register offsets within a page
- * b15..b8 - page id, b7..b0 - register address
- */
-#define POWER_CTRL_REG         0x0001
-#define PAGEMODE_REG           0x03
-#define DEVICE_ID_REG          0x0004
-#define NOON010PC30_ID         0x86
-#define VDO_CTL_REG(n)         (0x0010 + (n))
-#define SYNC_CTL_REG           0x0012
-/* Window size and position */
-#define WIN_ROWH_REG           0x0013
-#define WIN_ROWL_REG           0x0014
-#define WIN_COLH_REG           0x0015
-#define WIN_COLL_REG           0x0016
-#define WIN_HEIGHTH_REG                0x0017
-#define WIN_HEIGHTL_REG                0x0018
-#define WIN_WIDTHH_REG         0x0019
-#define WIN_WIDTHL_REG         0x001A
-#define HBLANKH_REG            0x001B
-#define HBLANKL_REG            0x001C
-#define VSYNCH_REG             0x001D
-#define VSYNCL_REG             0x001E
-/* VSYNC control */
-#define VS_CTL_REG(n)          (0x00A1 + (n))
-/* page 1 */
-#define ISP_CTL_REG(n)         (0x0110 + (n))
-#define YOFS_REG               0x0119
-#define DARK_YOFS_REG          0x011A
-#define SAT_CTL_REG            0x0120
-#define BSAT_REG               0x0121
-#define RSAT_REG               0x0122
-/* Color correction */
-#define CMC_CTL_REG            0x0130
-#define CMC_OFSGH_REG          0x0133
-#define CMC_OFSGL_REG          0x0135
-#define CMC_SIGN_REG           0x0136
-#define CMC_GOFS_REG           0x0137
-#define CMC_COEF_REG(n)                (0x0138 + (n))
-#define CMC_OFS_REG(n)         (0x0141 + (n))
-/* Gamma correction */
-#define GMA_CTL_REG            0x0160
-#define GMA_COEF_REG(n)                (0x0161 + (n))
-/* Lens Shading */
-#define LENS_CTRL_REG          0x01D0
-#define LENS_XCEN_REG          0x01D1
-#define LENS_YCEN_REG          0x01D2
-#define LENS_RC_REG            0x01D3
-#define LENS_GC_REG            0x01D4
-#define LENS_BC_REG            0x01D5
-#define L_AGON_REG             0x01D6
-#define L_AGOFF_REG            0x01D7
-/* Page 3 - Auto Exposure */
-#define AE_CTL_REG(n)          (0x0310 + (n))
-#define AE_CTL9_REG            0x032C
-#define AE_CTL10_REG           0x032D
-#define AE_YLVL_REG            0x031C
-#define AE_YTH_REG(n)          (0x031D + (n))
-#define AE_WGT_REG             0x0326
-#define EXP_TIMEH_REG          0x0333
-#define EXP_TIMEM_REG          0x0334
-#define EXP_TIMEL_REG          0x0335
-#define EXP_MMINH_REG          0x0336
-#define EXP_MMINL_REG          0x0337
-#define EXP_MMAXH_REG          0x0338
-#define EXP_MMAXM_REG          0x0339
-#define EXP_MMAXL_REG          0x033A
-/* Page 4 - Auto White Balance */
-#define AWB_CTL_REG(n)         (0x0410 + (n))
-#define AWB_ENABE              0x80
-#define AWB_WGHT_REG           0x0419
-#define BGAIN_PAR_REG(n)       (0x044F + (n))
-/* Manual white balance, when AWB_CTL2[0]=1 */
-#define MWB_RGAIN_REG          0x0466
-#define MWB_BGAIN_REG          0x0467
-
-/* The token to mark an array end */
-#define REG_TERM               0xFFFF
-
-struct noon010_format {
-       u32 code;
-       enum v4l2_colorspace colorspace;
-       u16 ispctl1_reg;
-};
-
-struct noon010_frmsize {
-       u16 width;
-       u16 height;
-       int vid_ctl1;
-};
-
-static const char * const noon010_supply_name[] = {
-       "vdd_core", "vddio", "vdda"
-};
-
-#define NOON010_NUM_SUPPLIES ARRAY_SIZE(noon010_supply_name)
-
-struct noon010_info {
-       struct v4l2_subdev sd;
-       struct media_pad pad;
-       struct v4l2_ctrl_handler hdl;
-       struct regulator_bulk_data supply[NOON010_NUM_SUPPLIES];
-       struct gpio_desc *reset;
-       struct gpio_desc *stby;
-
-       /* Protects the struct members below */
-       struct mutex lock;
-
-       const struct noon010_format *curr_fmt;
-       const struct noon010_frmsize *curr_win;
-       unsigned int apply_new_cfg:1;
-       unsigned int streaming:1;
-       unsigned int hflip:1;
-       unsigned int vflip:1;
-       unsigned int power:1;
-       u8 i2c_reg_page;
-};
-
-struct i2c_regval {
-       u16 addr;
-       u16 val;
-};
-
-/* Supported resolutions. */
-static const struct noon010_frmsize noon010_sizes[] = {
-       {
-               .width          = 352,
-               .height         = 288,
-               .vid_ctl1       = 0,
-       }, {
-               .width          = 176,
-               .height         = 144,
-               .vid_ctl1       = 0x10,
-       }, {
-               .width          = 88,
-               .height         = 72,
-               .vid_ctl1       = 0x20,
-       },
-};
-
-/* Supported pixel formats. */
-static const struct noon010_format noon010_formats[] = {
-       {
-               .code           = MEDIA_BUS_FMT_YUYV8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0x03,
-       }, {
-               .code           = MEDIA_BUS_FMT_YVYU8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0x02,
-       }, {
-               .code           = MEDIA_BUS_FMT_VYUY8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0,
-       }, {
-               .code           = MEDIA_BUS_FMT_UYVY8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0x01,
-       }, {
-               .code           = MEDIA_BUS_FMT_RGB565_2X8_BE,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0x40,
-       },
-};
-
-static const struct i2c_regval noon010_base_regs[] = {
-       { WIN_COLL_REG,         0x06 }, { HBLANKL_REG,          0x7C },
-       /* Color corection and saturation */
-       { ISP_CTL_REG(0),       0x30 }, { ISP_CTL_REG(2),       0x30 },
-       { YOFS_REG,             0x80 }, { DARK_YOFS_REG,        0x04 },
-       { SAT_CTL_REG,          0x1F }, { BSAT_REG,             0x90 },
-       { CMC_CTL_REG,          0x0F }, { CMC_OFSGH_REG,        0x3C },
-       { CMC_OFSGL_REG,        0x2C }, { CMC_SIGN_REG,         0x3F },
-       { CMC_COEF_REG(0),      0x79 }, { CMC_OFS_REG(0),       0x00 },
-       { CMC_COEF_REG(1),      0x39 }, { CMC_OFS_REG(1),       0x00 },
-       { CMC_COEF_REG(2),      0x00 }, { CMC_OFS_REG(2),       0x00 },
-       { CMC_COEF_REG(3),      0x11 }, { CMC_OFS_REG(3),       0x8B },
-       { CMC_COEF_REG(4),      0x65 }, { CMC_OFS_REG(4),       0x07 },
-       { CMC_COEF_REG(5),      0x14 }, { CMC_OFS_REG(5),       0x04 },
-       { CMC_COEF_REG(6),      0x01 }, { CMC_OFS_REG(6),       0x9C },
-       { CMC_COEF_REG(7),      0x33 }, { CMC_OFS_REG(7),       0x89 },
-       { CMC_COEF_REG(8),      0x74 }, { CMC_OFS_REG(8),       0x25 },
-       /* Automatic white balance */
-       { AWB_CTL_REG(0),       0x78 }, { AWB_CTL_REG(1),       0x2E },
-       { AWB_CTL_REG(2),       0x20 }, { AWB_CTL_REG(3),       0x85 },
-       /* Auto exposure */
-       { AE_CTL_REG(0),        0xDC }, { AE_CTL_REG(1),        0x81 },
-       { AE_CTL_REG(2),        0x30 }, { AE_CTL_REG(3),        0xA5 },
-       { AE_CTL_REG(4),        0x40 }, { AE_CTL_REG(5),        0x51 },
-       { AE_CTL_REG(6),        0x33 }, { AE_CTL_REG(7),        0x7E },
-       { AE_CTL9_REG,          0x00 }, { AE_CTL10_REG,         0x02 },
-       { AE_YLVL_REG,          0x44 }, { AE_YTH_REG(0),        0x34 },
-       { AE_YTH_REG(1),        0x30 }, { AE_WGT_REG,           0xD5 },
-       /* Lens shading compensation */
-       { LENS_CTRL_REG,        0x01 }, { LENS_XCEN_REG,        0x80 },
-       { LENS_YCEN_REG,        0x70 }, { LENS_RC_REG,          0x53 },
-       { LENS_GC_REG,          0x40 }, { LENS_BC_REG,          0x3E },
-       { REG_TERM,             0 },
-};
-
-static inline struct noon010_info *to_noon010(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct noon010_info, sd);
-}
-
-static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
-{
-       return &container_of(ctrl->handler, struct noon010_info, hdl)->sd;
-}
-
-static inline int set_i2c_page(struct noon010_info *info,
-                              struct i2c_client *client, unsigned int reg)
-{
-       u32 page = reg >> 8 & 0xFF;
-       int ret = 0;
-
-       if (info->i2c_reg_page != page && (reg & 0xFF) != 0x03) {
-               ret = i2c_smbus_write_byte_data(client, PAGEMODE_REG, page);
-               if (!ret)
-                       info->i2c_reg_page = page;
-       }
-       return ret;
-}
-
-static int cam_i2c_read(struct v4l2_subdev *sd, u32 reg_addr)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct noon010_info *info = to_noon010(sd);
-       int ret = set_i2c_page(info, client, reg_addr);
-
-       if (ret)
-               return ret;
-       return i2c_smbus_read_byte_data(client, reg_addr & 0xFF);
-}
-
-static int cam_i2c_write(struct v4l2_subdev *sd, u32 reg_addr, u32 val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct noon010_info *info = to_noon010(sd);
-       int ret = set_i2c_page(info, client, reg_addr);
-
-       if (ret)
-               return ret;
-       return i2c_smbus_write_byte_data(client, reg_addr & 0xFF, val);
-}
-
-static inline int noon010_bulk_write_reg(struct v4l2_subdev *sd,
-                                        const struct i2c_regval *msg)
-{
-       while (msg->addr != REG_TERM) {
-               int ret = cam_i2c_write(sd, msg->addr, msg->val);
-
-               if (ret)
-                       return ret;
-               msg++;
-       }
-       return 0;
-}
-
-/* Device reset and sleep mode control */
-static int noon010_power_ctrl(struct v4l2_subdev *sd, bool reset, bool sleep)
-{
-       struct noon010_info *info = to_noon010(sd);
-       u8 reg = sleep ? 0xF1 : 0xF0;
-       int ret = 0;
-
-       if (reset) {
-               ret = cam_i2c_write(sd, POWER_CTRL_REG, reg | 0x02);
-               udelay(20);
-       }
-       if (!ret) {
-               ret = cam_i2c_write(sd, POWER_CTRL_REG, reg);
-               if (reset && !ret)
-                       info->i2c_reg_page = -1;
-       }
-       return ret;
-}
-
-/* Automatic white balance control */
-static int noon010_enable_autowhitebalance(struct v4l2_subdev *sd, int on)
-{
-       int ret;
-
-       ret = cam_i2c_write(sd, AWB_CTL_REG(1), on ? 0x2E : 0x2F);
-       if (!ret)
-               ret = cam_i2c_write(sd, AWB_CTL_REG(0), on ? 0xFB : 0x7B);
-       return ret;
-}
-
-/* Called with struct noon010_info.lock mutex held */
-static int noon010_set_flip(struct v4l2_subdev *sd, int hflip, int vflip)
-{
-       struct noon010_info *info = to_noon010(sd);
-       int reg, ret;
-
-       reg = cam_i2c_read(sd, VDO_CTL_REG(1));
-       if (reg < 0)
-               return reg;
-
-       reg &= 0x7C;
-       if (hflip)
-               reg |= 0x01;
-       if (vflip)
-               reg |= 0x02;
-
-       ret = cam_i2c_write(sd, VDO_CTL_REG(1), reg | 0x80);
-       if (!ret) {
-               info->hflip = hflip;
-               info->vflip = vflip;
-       }
-       return ret;
-}
-
-/* Configure resolution and color format */
-static int noon010_set_params(struct v4l2_subdev *sd)
-{
-       struct noon010_info *info = to_noon010(sd);
-
-       int ret = cam_i2c_write(sd, VDO_CTL_REG(0),
-                               info->curr_win->vid_ctl1);
-       if (ret)
-               return ret;
-       return cam_i2c_write(sd, ISP_CTL_REG(0),
-                            info->curr_fmt->ispctl1_reg);
-}
-
-/* Find nearest matching image pixel size. */
-static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf,
-                                 const struct noon010_frmsize **size)
-{
-       unsigned int min_err = ~0;
-       int i = ARRAY_SIZE(noon010_sizes);
-       const struct noon010_frmsize *fsize = &noon010_sizes[0],
-               *match = NULL;
-
-       while (i--) {
-               int err = abs(fsize->width - mf->width)
-                               + abs(fsize->height - mf->height);
-
-               if (err < min_err) {
-                       min_err = err;
-                       match = fsize;
-               }
-               fsize++;
-       }
-       if (match) {
-               mf->width  = match->width;
-               mf->height = match->height;
-               if (size)
-                       *size = match;
-               return 0;
-       }
-       return -EINVAL;
-}
-
-/* Called with info.lock mutex held */
-static int power_enable(struct noon010_info *info)
-{
-       int ret;
-
-       if (info->power) {
-               v4l2_info(&info->sd, "%s: sensor is already on\n", __func__);
-               return 0;
-       }
-
-       /* Assert standby: line should be flagged active low in descriptor */
-       if (info->stby)
-               gpiod_set_value(info->stby, 1);
-
-       /* Assert reset: line should be flagged active low in descriptor */
-       if (info->reset)
-               gpiod_set_value(info->reset, 1);
-
-       ret = regulator_bulk_enable(NOON010_NUM_SUPPLIES, info->supply);
-       if (ret)
-               return ret;
-
-       /* De-assert reset and standby */
-       if (info->reset) {
-               msleep(50);
-               gpiod_set_value(info->reset, 0);
-       }
-       if (info->stby) {
-               udelay(1000);
-               gpiod_set_value(info->stby, 0);
-       }
-       /* Cycle reset: assert and deassert */
-       if (info->reset) {
-               udelay(1000);
-               gpiod_set_value(info->reset, 1);
-               msleep(100);
-               gpiod_set_value(info->reset, 0);
-               msleep(20);
-       }
-       info->power = 1;
-
-       v4l2_dbg(1, debug, &info->sd,  "%s: sensor is on\n", __func__);
-       return 0;
-}
-
-/* Called with info.lock mutex held */
-static int power_disable(struct noon010_info *info)
-{
-       int ret;
-
-       if (!info->power) {
-               v4l2_info(&info->sd, "%s: sensor is already off\n", __func__);
-               return 0;
-       }
-
-       ret = regulator_bulk_disable(NOON010_NUM_SUPPLIES, info->supply);
-       if (ret)
-               return ret;
-
-       /* Assert standby and reset */
-       if (info->stby)
-               gpiod_set_value(info->stby, 1);
-
-       if (info->reset)
-               gpiod_set_value(info->reset, 1);
-
-       info->power = 0;
-
-       v4l2_dbg(1, debug, &info->sd,  "%s: sensor is off\n", __func__);
-
-       return 0;
-}
-
-static int noon010_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct v4l2_subdev *sd = to_sd(ctrl);
-       struct noon010_info *info = to_noon010(sd);
-       int ret = 0;
-
-       v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
-                __func__, ctrl->id, ctrl->val);
-
-       mutex_lock(&info->lock);
-       /*
-        * If the device is not powered up by the host driver do
-        * not apply any controls to H/W at this time. Instead
-        * the controls will be restored right after power-up.
-        */
-       if (!info->power)
-               goto unlock;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               ret = noon010_enable_autowhitebalance(sd, ctrl->val);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               ret = cam_i2c_write(sd, MWB_BGAIN_REG, ctrl->val);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               ret =  cam_i2c_write(sd, MWB_RGAIN_REG, ctrl->val);
-               break;
-       default:
-               ret = -EINVAL;
-       }
-unlock:
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-static int noon010_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_state *sd_state,
-                                 struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (code->index >= ARRAY_SIZE(noon010_formats))
-               return -EINVAL;
-
-       code->code = noon010_formats[code->index].code;
-       return 0;
-}
-
-static int noon010_get_fmt(struct v4l2_subdev *sd,
-                          struct v4l2_subdev_state *sd_state,
-                          struct v4l2_subdev_format *fmt)
-{
-       struct noon010_info *info = to_noon010(sd);
-       struct v4l2_mbus_framefmt *mf;
-
-       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               if (sd_state) {
-                       mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
-                       fmt->format = *mf;
-               }
-               return 0;
-       }
-       mf = &fmt->format;
-
-       mutex_lock(&info->lock);
-       mf->width = info->curr_win->width;
-       mf->height = info->curr_win->height;
-       mf->code = info->curr_fmt->code;
-       mf->colorspace = info->curr_fmt->colorspace;
-       mf->field = V4L2_FIELD_NONE;
-
-       mutex_unlock(&info->lock);
-       return 0;
-}
-
-/* Return nearest media bus frame format. */
-static const struct noon010_format *noon010_try_fmt(struct v4l2_subdev *sd,
-                                           struct v4l2_mbus_framefmt *mf)
-{
-       int i = ARRAY_SIZE(noon010_formats);
-
-       while (--i)
-               if (mf->code == noon010_formats[i].code)
-                       break;
-       mf->code = noon010_formats[i].code;
-
-       return &noon010_formats[i];
-}
-
-static int noon010_set_fmt(struct v4l2_subdev *sd,
-                          struct v4l2_subdev_state *sd_state,
-                          struct v4l2_subdev_format *fmt)
-{
-       struct noon010_info *info = to_noon010(sd);
-       const struct noon010_frmsize *size = NULL;
-       const struct noon010_format *nf;
-       struct v4l2_mbus_framefmt *mf;
-       int ret = 0;
-
-       nf = noon010_try_fmt(sd, &fmt->format);
-       noon010_try_frame_size(&fmt->format, &size);
-       fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
-       fmt->format.field = V4L2_FIELD_NONE;
-
-       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               if (sd_state) {
-                       mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
-                       *mf = fmt->format;
-               }
-               return 0;
-       }
-       mutex_lock(&info->lock);
-       if (!info->streaming) {
-               info->apply_new_cfg = 1;
-               info->curr_fmt = nf;
-               info->curr_win = size;
-       } else {
-               ret = -EBUSY;
-       }
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-/* Called with struct noon010_info.lock mutex held */
-static int noon010_base_config(struct v4l2_subdev *sd)
-{
-       int ret = noon010_bulk_write_reg(sd, noon010_base_regs);
-       if (!ret)
-               ret = noon010_set_params(sd);
-       if (!ret)
-               ret = noon010_set_flip(sd, 1, 0);
-
-       return ret;
-}
-
-static int noon010_s_power(struct v4l2_subdev *sd, int on)
-{
-       struct noon010_info *info = to_noon010(sd);
-       int ret;
-
-       mutex_lock(&info->lock);
-       if (on) {
-               ret = power_enable(info);
-               if (!ret)
-                       ret = noon010_base_config(sd);
-       } else {
-               noon010_power_ctrl(sd, false, true);
-               ret = power_disable(info);
-       }
-       mutex_unlock(&info->lock);
-
-       /* Restore the controls state */
-       if (!ret && on)
-               ret = v4l2_ctrl_handler_setup(&info->hdl);
-
-       return ret;
-}
-
-static int noon010_s_stream(struct v4l2_subdev *sd, int on)
-{
-       struct noon010_info *info = to_noon010(sd);
-       int ret = 0;
-
-       mutex_lock(&info->lock);
-       if (!info->streaming != !on) {
-               ret = noon010_power_ctrl(sd, false, !on);
-               if (!ret)
-                       info->streaming = on;
-       }
-       if (!ret && on && info->apply_new_cfg) {
-               ret = noon010_set_params(sd);
-               if (!ret)
-                       info->apply_new_cfg = 0;
-       }
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-static int noon010_log_status(struct v4l2_subdev *sd)
-{
-       struct noon010_info *info = to_noon010(sd);
-
-       v4l2_ctrl_handler_log_status(&info->hdl, sd->name);
-       return 0;
-}
-
-static int noon010_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-{
-       struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(sd,
-                                                                  fh->state,
-                                                                  0);
-
-       mf->width = noon010_sizes[0].width;
-       mf->height = noon010_sizes[0].height;
-       mf->code = noon010_formats[0].code;
-       mf->colorspace = V4L2_COLORSPACE_JPEG;
-       mf->field = V4L2_FIELD_NONE;
-       return 0;
-}
-
-static const struct v4l2_subdev_internal_ops noon010_subdev_internal_ops = {
-       .open = noon010_open,
-};
-
-static const struct v4l2_ctrl_ops noon010_ctrl_ops = {
-       .s_ctrl = noon010_s_ctrl,
-};
-
-static const struct v4l2_subdev_core_ops noon010_core_ops = {
-       .s_power        = noon010_s_power,
-       .log_status     = noon010_log_status,
-};
-
-static const struct v4l2_subdev_pad_ops noon010_pad_ops = {
-       .enum_mbus_code = noon010_enum_mbus_code,
-       .get_fmt        = noon010_get_fmt,
-       .set_fmt        = noon010_set_fmt,
-};
-
-static const struct v4l2_subdev_video_ops noon010_video_ops = {
-       .s_stream       = noon010_s_stream,
-};
-
-static const struct v4l2_subdev_ops noon010_ops = {
-       .core   = &noon010_core_ops,
-       .pad    = &noon010_pad_ops,
-       .video  = &noon010_video_ops,
-};
-
-/* Return 0 if NOON010PC30L sensor type was detected or -ENODEV otherwise. */
-static int noon010_detect(struct i2c_client *client, struct noon010_info *info)
-{
-       int ret;
-
-       ret = power_enable(info);
-       if (ret)
-               return ret;
-
-       ret = i2c_smbus_read_byte_data(client, DEVICE_ID_REG);
-       if (ret < 0)
-               dev_err(&client->dev, "I2C read failed: 0x%X\n", ret);
-
-       power_disable(info);
-
-       return ret == NOON010PC30_ID ? 0 : -ENODEV;
-}
-
-static int noon010_probe(struct i2c_client *client)
-{
-       struct noon010_info *info;
-       struct v4l2_subdev *sd;
-       const struct noon010pc30_platform_data *pdata
-               = client->dev.platform_data;
-       int ret;
-       int i;
-
-       if (!pdata) {
-               dev_err(&client->dev, "No platform data!\n");
-               return -EIO;
-       }
-
-       info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       mutex_init(&info->lock);
-       sd = &info->sd;
-       v4l2_i2c_subdev_init(sd, client, &noon010_ops);
-       /* 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;
-
-       v4l2_ctrl_handler_init(&info->hdl, 3);
-
-       v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
-                         V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
-       v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
-                         V4L2_CID_RED_BALANCE, 0, 127, 1, 64);
-       v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
-                         V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64);
-
-       sd->ctrl_handler = &info->hdl;
-
-       ret = info->hdl.error;
-       if (ret)
-               goto np_err;
-
-       info->i2c_reg_page      = -1;
-       info->curr_fmt          = &noon010_formats[0];
-       info->curr_win          = &noon010_sizes[0];
-
-       /* Request reset asserted so we get put into reset */
-       info->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(info->reset)) {
-               ret = PTR_ERR(info->reset);
-               goto np_err;
-       }
-       gpiod_set_consumer_name(info->reset, "NOON010PC30 NRST");
-
-       /* Request standby asserted so we get put into standby */
-       info->stby = devm_gpiod_get(&client->dev, "standby", GPIOD_OUT_HIGH);
-       if (IS_ERR(info->stby)) {
-               ret = PTR_ERR(info->stby);
-               goto np_err;
-       }
-       gpiod_set_consumer_name(info->reset, "NOON010PC30 STBY");
-
-       for (i = 0; i < NOON010_NUM_SUPPLIES; i++)
-               info->supply[i].supply = noon010_supply_name[i];
-
-       ret = devm_regulator_bulk_get(&client->dev, NOON010_NUM_SUPPLIES,
-                                info->supply);
-       if (ret)
-               goto np_err;
-
-       info->pad.flags = MEDIA_PAD_FL_SOURCE;
-       sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
-       ret = media_entity_pads_init(&sd->entity, 1, &info->pad);
-       if (ret < 0)
-               goto np_err;
-
-       ret = noon010_detect(client, info);
-       if (!ret)
-               return 0;
-
-np_err:
-       v4l2_ctrl_handler_free(&info->hdl);
-       v4l2_device_unregister_subdev(sd);
-       return ret;
-}
-
-static void noon010_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-       struct noon010_info *info = to_noon010(sd);
-
-       v4l2_device_unregister_subdev(sd);
-       v4l2_ctrl_handler_free(&info->hdl);
-       media_entity_cleanup(&sd->entity);
-}
-
-static const struct i2c_device_id noon010_id[] = {
-       { MODULE_NAME, 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(i2c, noon010_id);
-
-
-static struct i2c_driver noon010_i2c_driver = {
-       .driver = {
-               .name = MODULE_NAME
-       },
-       .probe_new      = noon010_probe,
-       .remove         = noon010_remove,
-       .id_table       = noon010_id,
-};
-
-module_i2c_driver(noon010_i2c_driver);
-
-MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver");
-MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
-MODULE_LICENSE("GPL");
index 549e5d93e568e65c4961f3a6dfa4c2a210716582..c1430044fb1e96ca6a304a493c4d5c2e9e7705ea 100644 (file)
@@ -243,7 +243,6 @@ static const struct ov13b10_reg mipi_data_rate_1120mbps[] = {
        {0x5047, 0xa4},
        {0x5048, 0x20},
        {0x5049, 0xa4},
-       {0x0100, 0x01},
 };
 
 static const struct ov13b10_reg mode_4208x3120_regs[] = {
@@ -589,6 +588,9 @@ struct ov13b10 {
 
        /* Streaming on/off */
        bool streaming;
+
+       /* True if the device has been identified */
+       bool identified;
 };
 
 #define to_ov13b10(_sd)        container_of(_sd, struct ov13b10, sd)
@@ -1023,12 +1025,42 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
        return 0;
 }
 
+/* Verify chip ID */
+static int ov13b10_identify_module(struct ov13b10 *ov13b)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
+       int ret;
+       u32 val;
+
+       if (ov13b->identified)
+               return 0;
+
+       ret = ov13b10_read_reg(ov13b, OV13B10_REG_CHIP_ID,
+                              OV13B10_REG_VALUE_24BIT, &val);
+       if (ret)
+               return ret;
+
+       if (val != OV13B10_CHIP_ID) {
+               dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
+                       OV13B10_CHIP_ID, val);
+               return -EIO;
+       }
+
+       ov13b->identified = true;
+
+       return 0;
+}
+
 static int ov13b10_start_streaming(struct ov13b10 *ov13b)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
        const struct ov13b10_reg_list *reg_list;
        int ret, link_freq_index;
 
+       ret = ov13b10_identify_module(ov13b);
+       if (ret)
+               return ret;
+
        /* Get out of from software reset */
        ret = ov13b10_write_reg(ov13b, OV13B10_REG_SOFTWARE_RST,
                                OV13B10_REG_VALUE_08BIT, OV13B10_SOFTWARE_RST);
@@ -1144,27 +1176,6 @@ error:
        return ret;
 }
 
-/* Verify chip ID */
-static int ov13b10_identify_module(struct ov13b10 *ov13b)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
-       int ret;
-       u32 val;
-
-       ret = ov13b10_read_reg(ov13b, OV13B10_REG_CHIP_ID,
-                              OV13B10_REG_VALUE_24BIT, &val);
-       if (ret)
-               return ret;
-
-       if (val != OV13B10_CHIP_ID) {
-               dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
-                       OV13B10_CHIP_ID, val);
-               return -EIO;
-       }
-
-       return 0;
-}
-
 static const struct v4l2_subdev_video_ops ov13b10_video_ops = {
        .s_stream = ov13b10_set_stream,
 };
@@ -1379,6 +1390,7 @@ out_err:
 static int ov13b10_probe(struct i2c_client *client)
 {
        struct ov13b10 *ov13b;
+       bool full_power;
        int ret;
 
        /* Check HW config */
@@ -1395,11 +1407,14 @@ static int ov13b10_probe(struct i2c_client *client)
        /* Initialize subdev */
        v4l2_i2c_subdev_init(&ov13b->sd, client, &ov13b10_subdev_ops);
 
-       /* Check module identity */
-       ret = ov13b10_identify_module(ov13b);
-       if (ret) {
-               dev_err(&client->dev, "failed to find sensor: %d\n", ret);
-               return ret;
+       full_power = acpi_dev_state_d0(&client->dev);
+       if (full_power) {
+               /* Check module identity */
+               ret = ov13b10_identify_module(ov13b);
+               if (ret) {
+                       dev_err(&client->dev, "failed to find sensor: %d\n", ret);
+                       return ret;
+               }
        }
 
        /* Set default mode to max resolution */
@@ -1431,7 +1446,10 @@ static int ov13b10_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_set_active(&client->dev);
+
+       /* Set the device's state to active if it's in D0 state. */
+       if (full_power)
+               pm_runtime_set_active(&client->dev);
        pm_runtime_enable(&client->dev);
        pm_runtime_idle(&client->dev);
 
@@ -1480,6 +1498,7 @@ static struct i2c_driver ov13b10_i2c_driver = {
        },
        .probe_new = ov13b10_probe,
        .remove = ov13b10_remove,
+       .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
 };
 
 module_i2c_driver(ov13b10_i2c_driver);
index 1c80b121e7d6d0d67ae372eb8229ad35a31e3b2b..f119a93e7c647678e4f8527ef2db65c142ea8237 100644 (file)
@@ -17,6 +17,7 @@
 #include <media/media-entity.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
 #define CHIP_ID                                0x2685
@@ -55,6 +56,9 @@
 #define OV2685_REG_VALUE_16BIT         2
 #define OV2685_REG_VALUE_24BIT         3
 
+#define OV2685_NATIVE_WIDTH            1616
+#define OV2685_NATIVE_HEIGHT           1216
+
 #define OV2685_LANES                   1
 #define OV2685_BITS_PER_SAMPLE         10
 
@@ -77,6 +81,7 @@ struct ov2685_mode {
        u32 exp_def;
        u32 hts_def;
        u32 vts_def;
+       const struct v4l2_rect *analog_crop;
        const struct regval *reg_list;
 };
 
@@ -230,6 +235,13 @@ static const int ov2685_test_pattern_val[] = {
        OV2685_TEST_PATTERN_COLOR_SQUARE,
 };
 
+static const struct v4l2_rect ov2685_analog_crop = {
+       .left   = 8,
+       .top    = 8,
+       .width  = 1600,
+       .height = 1200,
+};
+
 static const struct ov2685_mode supported_modes[] = {
        {
                .width = 1600,
@@ -237,6 +249,7 @@ static const struct ov2685_mode supported_modes[] = {
                .exp_def = 0x04ee,
                .hts_def = 0x06a4,
                .vts_def = 0x050e,
+               .analog_crop = &ov2685_analog_crop,
                .reg_list = ov2685_1600x1200_regs,
        },
 };
@@ -383,6 +396,53 @@ static int ov2685_enum_frame_sizes(struct v4l2_subdev *sd,
        return 0;
 }
 
+static const struct v4l2_rect *
+__ov2685_get_pad_crop(struct ov2685 *ov2685,
+                     struct v4l2_subdev_state *state, unsigned int pad,
+                     enum v4l2_subdev_format_whence which)
+{
+       const struct ov2685_mode *mode = ov2685->cur_mode;
+
+       switch (which) {
+       case V4L2_SUBDEV_FORMAT_TRY:
+               return v4l2_subdev_get_try_crop(&ov2685->subdev, state, pad);
+       case V4L2_SUBDEV_FORMAT_ACTIVE:
+               return mode->analog_crop;
+       }
+
+       return NULL;
+}
+
+static int ov2685_get_selection(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_state *sd_state,
+                               struct v4l2_subdev_selection *sel)
+{
+       struct ov2685 *ov2685 = to_ov2685(sd);
+
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP:
+               mutex_lock(&ov2685->mutex);
+               sel->r = *__ov2685_get_pad_crop(ov2685, sd_state, sel->pad,
+                               sel->which);
+               mutex_unlock(&ov2685->mutex);
+               break;
+       case V4L2_SEL_TGT_NATIVE_SIZE:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               sel->r.top = 0;
+               sel->r.left = 0;
+               sel->r.width = OV2685_NATIVE_WIDTH;
+               sel->r.height = OV2685_NATIVE_HEIGHT;
+               break;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               sel->r = ov2685_analog_crop;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /* Calculate the delay in us by clock rate and clock cycles */
 static inline u32 ov2685_cal_delay(u32 cycles)
 {
@@ -419,8 +479,10 @@ static int __ov2685_power_on(struct ov2685 *ov2685)
         * writing register before .s_stream() as a workaround
         */
        ret = ov2685_write_array(ov2685->client, ov2685->cur_mode->reg_list);
-       if (ret)
+       if (ret) {
+               dev_err(dev, "Failed to set regs for power on\n");
                goto disable_supplies;
+       }
 
        return 0;
 
@@ -589,6 +651,8 @@ static const struct v4l2_subdev_pad_ops ov2685_pad_ops = {
        .enum_frame_size = ov2685_enum_frame_sizes,
        .get_fmt = ov2685_get_fmt,
        .set_fmt = ov2685_set_fmt,
+       .get_selection = ov2685_get_selection,
+       .set_selection = ov2685_get_selection,
 };
 
 static const struct v4l2_subdev_ops ov2685_subdev_ops = {
@@ -611,13 +675,14 @@ static int ov2685_initialize_controls(struct ov2685 *ov2685)
        const struct ov2685_mode *mode;
        struct v4l2_ctrl_handler *handler;
        struct v4l2_ctrl *ctrl;
+       struct v4l2_fwnode_device_properties props;
        u64 exposure_max;
        u32 pixel_rate, h_blank;
        int ret;
 
        handler = &ov2685->ctrl_handler;
        mode = ov2685->cur_mode;
-       ret = v4l2_ctrl_handler_init(handler, 8);
+       ret = v4l2_ctrl_handler_init(handler, 10);
        if (ret)
                return ret;
        handler->lock = &ov2685->mutex;
@@ -659,6 +724,15 @@ static int ov2685_initialize_controls(struct ov2685 *ov2685)
                                ARRAY_SIZE(ov2685_test_pattern_menu) - 1,
                                0, 0, ov2685_test_pattern_menu);
 
+       /* set properties from fwnode (e.g. rotation, orientation) */
+       ret = v4l2_fwnode_device_parse(&ov2685->client->dev, &props);
+       if (ret)
+               goto err_free_handler;
+
+       ret = v4l2_ctrl_new_fwnode_properties(handler, &ov2685_ctrl_ops, &props);
+       if (ret)
+               goto err_free_handler;
+
        if (handler->error) {
                ret = handler->error;
                dev_err(&ov2685->client->dev,
@@ -733,7 +807,7 @@ static int ov2685_probe(struct i2c_client *client)
        if (clk_get_rate(ov2685->xvclk) != OV2685_XVCLK_FREQ)
                dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
 
-       ov2685->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+       ov2685->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
        if (IS_ERR(ov2685->reset_gpio)) {
                dev_err(dev, "Failed to get reset-gpios\n");
                return -EINVAL;
index 847a7bbb69c540c6b16e7a7565d626725533418f..233576ee95038ae05d9fea9e346f7f3e95468ece 100644 (file)
@@ -58,6 +58,7 @@
 #define OV5647_REG_MIPI_CTRL00         0x4800
 #define OV5647_REG_MIPI_CTRL14         0x4814
 #define OV5647_REG_AWB                 0x5001
+#define OV5647_REG_ISPCTRL3D           0x503d
 
 #define REG_TERM 0xfffe
 #define VAL_TERM 0xfe
@@ -116,6 +117,20 @@ static inline struct ov5647 *to_sensor(struct v4l2_subdev *sd)
        return container_of(sd, struct ov5647, sd);
 }
 
+static const char * const ov5647_test_pattern_menu[] = {
+       "Disabled",
+       "Color Bars",
+       "Color Squares",
+       "Random Data",
+};
+
+static const u8 ov5647_test_pattern_val[] = {
+       0x00,   /* Disabled */
+       0x80,   /* Color Bars */
+       0x82,   /* Color Squares */
+       0x81,   /* Random Data */
+};
+
 static const struct regval_list sensor_oe_disable_regs[] = {
        {0x3000, 0x00},
        {0x3001, 0x00},
@@ -614,23 +629,29 @@ static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val)
 
 static int ov5647_read(struct v4l2_subdev *sd, u16 reg, u8 *val)
 {
-       unsigned char data_w[2] = { reg >> 8, reg & 0xff };
        struct i2c_client *client = v4l2_get_subdevdata(sd);
+       u8 buf[2] = { reg >> 8, reg & 0xff };
+       struct i2c_msg msg[2];
        int ret;
 
-       ret = i2c_master_send(client, data_w, 2);
-       if (ret < 0) {
-               dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",
-                       __func__, reg);
-               return ret;
+       msg[0].addr = client->addr;
+       msg[0].flags = client->flags;
+       msg[0].buf = buf;
+       msg[0].len = sizeof(buf);
+
+       msg[1].addr = client->addr;
+       msg[1].flags = client->flags | I2C_M_RD;
+       msg[1].buf = buf;
+       msg[1].len = 1;
+
+       ret = i2c_transfer(client->adapter, msg, 2);
+       if (ret != 2) {
+               dev_err(&client->dev, "%s: i2c read error, reg: %x = %d\n",
+                       __func__, reg, ret);
+               return ret >= 0 ? -EINVAL : ret;
        }
 
-       ret = i2c_master_recv(client, val, 1);
-       if (ret < 0) {
-               dev_dbg(&client->dev, "%s: i2c read error, reg: %x\n",
-                               __func__, reg);
-               return ret;
-       }
+       *val = buf[0];
 
        return 0;
 }
@@ -1242,6 +1263,10 @@ static int ov5647_s_ctrl(struct v4l2_ctrl *ctrl)
                ret = ov5647_write16(sd, OV5647_REG_VTS_HI,
                                     sensor->mode->format.height + ctrl->val);
                break;
+       case V4L2_CID_TEST_PATTERN:
+               ret = ov5647_write(sd, OV5647_REG_ISPCTRL3D,
+                                  ov5647_test_pattern_val[ctrl->val]);
+               break;
 
        /* Read-only, but we adjust it based on mode. */
        case V4L2_CID_PIXEL_RATE:
@@ -1270,7 +1295,7 @@ static int ov5647_init_controls(struct ov5647 *sensor)
        struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);
        int hblank, exposure_max, exposure_def;
 
-       v4l2_ctrl_handler_init(&sensor->ctrls, 8);
+       v4l2_ctrl_handler_init(&sensor->ctrls, 9);
 
        v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
                          V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
@@ -1314,6 +1339,11 @@ static int ov5647_init_controls(struct ov5647 *sensor)
                                           sensor->mode->vts -
                                           sensor->mode->format.height);
 
+       v4l2_ctrl_new_std_menu_items(&sensor->ctrls, &ov5647_ctrl_ops,
+                                    V4L2_CID_TEST_PATTERN,
+                                    ARRAY_SIZE(ov5647_test_pattern_menu) - 1,
+                                    0, 0, ov5647_test_pattern_menu);
+
        if (sensor->ctrls.error)
                goto handler_free;
 
index f79d908f4531b84c366eb3fe0f23e20e1cc0f609..c026610d0f31fcff99f358ab4988e9e9a0b3c450 100644 (file)
 #define OV5670_REG_SOFTWARE_RST                0x0103
 #define OV5670_SOFTWARE_RST            0x01
 
+#define OV5670_MIPI_SC_CTRL0_REG               0x3018
+#define OV5670_MIPI_SC_CTRL0_LANES(v)          ((((v) - 1) << 5) & \
+                                                GENMASK(7, 5))
+#define OV5670_MIPI_SC_CTRL0_MIPI_EN           BIT(4)
+#define OV5670_MIPI_SC_CTRL0_RESERVED          BIT(1)
+
 /* vertical-timings from sensor */
 #define OV5670_REG_VTS                 0x380e
 #define OV5670_VTS_30FPS               0x0808 /* default for 30 fps */
@@ -92,7 +98,6 @@ struct ov5670_reg_list {
 };
 
 struct ov5670_link_freq_config {
-       u32 pixel_rate;
        const struct ov5670_reg_list reg_list;
 };
 
@@ -163,7 +168,6 @@ static const struct ov5670_reg mode_2592x1944_regs[] = {
        {0x3005, 0xf0},
        {0x3007, 0x00},
        {0x3015, 0x0f},
-       {0x3018, 0x32},
        {0x301a, 0xf0},
        {0x301b, 0xf0},
        {0x301c, 0xf0},
@@ -429,7 +433,6 @@ static const struct ov5670_reg mode_1296x972_regs[] = {
        {0x3005, 0xf0},
        {0x3007, 0x00},
        {0x3015, 0x0f},
-       {0x3018, 0x32},
        {0x301a, 0xf0},
        {0x301b, 0xf0},
        {0x301c, 0xf0},
@@ -695,7 +698,6 @@ static const struct ov5670_reg mode_648x486_regs[] = {
        {0x3005, 0xf0},
        {0x3007, 0x00},
        {0x3015, 0x0f},
-       {0x3018, 0x32},
        {0x301a, 0xf0},
        {0x301b, 0xf0},
        {0x301c, 0xf0},
@@ -961,7 +963,6 @@ static const struct ov5670_reg mode_2560x1440_regs[] = {
        {0x3005, 0xf0},
        {0x3007, 0x00},
        {0x3015, 0x0f},
-       {0x3018, 0x32},
        {0x301a, 0xf0},
        {0x301b, 0xf0},
        {0x301c, 0xf0},
@@ -1226,7 +1227,6 @@ static const struct ov5670_reg mode_1280x720_regs[] = {
        {0x3005, 0xf0},
        {0x3007, 0x00},
        {0x3015, 0x0f},
-       {0x3018, 0x32},
        {0x301a, 0xf0},
        {0x301b, 0xf0},
        {0x301c, 0xf0},
@@ -1492,7 +1492,6 @@ static const struct ov5670_reg mode_640x360_regs[] = {
        {0x3005, 0xf0},
        {0x3007, 0x00},
        {0x3015, 0x0f},
-       {0x3018, 0x32},
        {0x301a, 0xf0},
        {0x301b, 0xf0},
        {0x301c, 0xf0},
@@ -1762,8 +1761,6 @@ static const char * const ov5670_test_pattern_menu[] = {
 #define OV5670_LINK_FREQ_422MHZ_INDEX  0
 static const struct ov5670_link_freq_config link_freq_configs[] = {
        {
-               /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
-               .pixel_rate = (OV5670_LINK_FREQ_422MHZ * 2 * 2) / 10,
                .reg_list = {
                        .num_of_regs = ARRAY_SIZE(mipi_data_rate_840mbps),
                        .regs = mipi_data_rate_840mbps,
@@ -1859,6 +1856,7 @@ static const struct ov5670_mode supported_modes[] = {
 struct ov5670 {
        struct v4l2_subdev sd;
        struct media_pad pad;
+       struct v4l2_fwnode_endpoint endpoint;
 
        struct v4l2_ctrl_handler ctrl_handler;
        /* V4L2 Controls */
@@ -2101,9 +2099,13 @@ static const struct v4l2_ctrl_ops ov5670_ctrl_ops = {
 /* Initialize control handlers */
 static int ov5670_init_controls(struct ov5670 *ov5670)
 {
+       struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 =
+               &ov5670->endpoint.bus.mipi_csi2;
        struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd);
        struct v4l2_fwnode_device_properties props;
        struct v4l2_ctrl_handler *ctrl_hdlr;
+       unsigned int lanes_count;
+       s64 mipi_pixel_rate;
        s64 vblank_max;
        s64 vblank_def;
        s64 vblank_min;
@@ -2124,12 +2126,15 @@ static int ov5670_init_controls(struct ov5670 *ov5670)
                ov5670->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
        /* By default, V4L2_CID_PIXEL_RATE is read only */
+       lanes_count = bus_mipi_csi2->num_data_lanes;
+       mipi_pixel_rate = OV5670_LINK_FREQ_422MHZ * 2 * lanes_count / 10;
+
        ov5670->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov5670_ctrl_ops,
                                               V4L2_CID_PIXEL_RATE,
-                                              link_freq_configs[0].pixel_rate,
-                                              link_freq_configs[0].pixel_rate,
+                                              mipi_pixel_rate,
+                                              mipi_pixel_rate,
                                               1,
-                                              link_freq_configs[0].pixel_rate);
+                                              mipi_pixel_rate);
 
        vblank_max = OV5670_VTS_MAX - ov5670->cur_mode->height;
        vblank_def = ov5670->cur_mode->vts_def - ov5670->cur_mode->height;
@@ -2288,8 +2293,13 @@ static int ov5670_set_pad_format(struct v4l2_subdev *sd,
                                 struct v4l2_subdev_format *fmt)
 {
        struct ov5670 *ov5670 = to_ov5670(sd);
+       struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 =
+               &ov5670->endpoint.bus.mipi_csi2;
        const struct ov5670_mode *mode;
+       unsigned int lanes_count;
+       s64 mipi_pixel_rate;
        s32 vblank_def;
+       s64 link_freq;
        s32 h_blank;
 
        mutex_lock(&ov5670->mutex);
@@ -2306,9 +2316,14 @@ static int ov5670_set_pad_format(struct v4l2_subdev *sd,
        } else {
                ov5670->cur_mode = mode;
                __v4l2_ctrl_s_ctrl(ov5670->link_freq, mode->link_freq_index);
+
+               lanes_count = bus_mipi_csi2->num_data_lanes;
+               link_freq = link_freq_menu_items[mode->link_freq_index];
+               /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
+               mipi_pixel_rate = div_s64(link_freq * 2 * lanes_count, 10);
                __v4l2_ctrl_s_ctrl_int64(
                        ov5670->pixel_rate,
-                       link_freq_configs[mode->link_freq_index].pixel_rate);
+                       mipi_pixel_rate);
                /* Update limits and set FPS to default */
                vblank_def = ov5670->cur_mode->vts_def -
                             ov5670->cur_mode->height;
@@ -2361,6 +2376,19 @@ static int ov5670_identify_module(struct ov5670 *ov5670)
        return 0;
 }
 
+static int ov5670_mipi_configure(struct ov5670 *ov5670)
+{
+       struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 =
+               &ov5670->endpoint.bus.mipi_csi2;
+       unsigned int lanes_count = bus_mipi_csi2->num_data_lanes;
+
+       return ov5670_write_reg(ov5670, OV5670_MIPI_SC_CTRL0_REG,
+                               OV5670_REG_VALUE_08BIT,
+                               OV5670_MIPI_SC_CTRL0_LANES(lanes_count) |
+                               OV5670_MIPI_SC_CTRL0_MIPI_EN |
+                               OV5670_MIPI_SC_CTRL0_RESERVED);
+}
+
 /* Prepare streaming by writing default values and customized values */
 static int ov5670_start_streaming(struct ov5670 *ov5670)
 {
@@ -2399,6 +2427,12 @@ static int ov5670_start_streaming(struct ov5670 *ov5670)
                return ret;
        }
 
+       ret = ov5670_mipi_configure(ov5670);
+       if (ret) {
+               dev_err(&client->dev, "%s failed to configure MIPI\n", __func__);
+               return ret;
+       }
+
        ret = __v4l2_ctrl_handler_setup(ov5670->sd.ctrl_handler);
        if (ret)
                return ret;
@@ -2647,23 +2681,20 @@ static int ov5670_gpio_probe(struct ov5670 *ov5670)
 
 static int ov5670_probe(struct i2c_client *client)
 {
+       struct fwnode_handle *handle;
        struct ov5670 *ov5670;
-       const char *err_msg;
        u32 input_clk = 0;
        bool full_power;
        int ret;
 
        ov5670 = devm_kzalloc(&client->dev, sizeof(*ov5670), GFP_KERNEL);
-       if (!ov5670) {
-               ret = -ENOMEM;
-               err_msg = "devm_kzalloc() error";
-               goto error_print;
-       }
+       if (!ov5670)
+               return -ENOMEM;
 
-       ov5670->xvclk = devm_clk_get(&client->dev, NULL);
+       ov5670->xvclk = devm_clk_get_optional(&client->dev, NULL);
        if (!IS_ERR_OR_NULL(ov5670->xvclk))
                input_clk = clk_get_rate(ov5670->xvclk);
-       else if (PTR_ERR(ov5670->xvclk) == -ENOENT)
+       else if (!ov5670->xvclk || PTR_ERR(ov5670->xvclk) == -ENOENT)
                device_property_read_u32(&client->dev, "clock-frequency",
                                         &input_clk);
        else
@@ -2680,29 +2711,38 @@ static int ov5670_probe(struct i2c_client *client)
        v4l2_i2c_subdev_init(&ov5670->sd, client, &ov5670_subdev_ops);
 
        ret = ov5670_regulators_probe(ov5670);
-       if (ret) {
-               err_msg = "Regulators probe failed";
-               goto error_print;
-       }
+       if (ret)
+               return dev_err_probe(&client->dev, ret, "Regulators probe failed\n");
 
        ret = ov5670_gpio_probe(ov5670);
-       if (ret) {
-               err_msg = "GPIO probe failed";
-               goto error_print;
-       }
+       if (ret)
+               return dev_err_probe(&client->dev, ret, "GPIO probe failed\n");
+
+       /* Graph Endpoint */
+       handle = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
+       if (!handle)
+               return dev_err_probe(&client->dev, -ENXIO, "Endpoint for node get failed\n");
+
+       ov5670->endpoint.bus_type = V4L2_MBUS_CSI2_DPHY;
+       ov5670->endpoint.bus.mipi_csi2.num_data_lanes = 2;
+
+       ret = v4l2_fwnode_endpoint_alloc_parse(handle, &ov5670->endpoint);
+       fwnode_handle_put(handle);
+       if (ret)
+               return dev_err_probe(&client->dev, ret, "Endpoint parse failed\n");
 
        full_power = acpi_dev_state_d0(&client->dev);
        if (full_power) {
                ret = ov5670_runtime_resume(&client->dev);
                if (ret) {
-                       err_msg = "Power up failed";
-                       goto error_print;
+                       dev_err_probe(&client->dev, ret, "Power up failed\n");
+                       goto error_endpoint;
                }
 
                /* Check module identity */
                ret = ov5670_identify_module(ov5670);
                if (ret) {
-                       err_msg = "ov5670_identify_module() error";
+                       dev_err_probe(&client->dev, ret, "ov5670_identify_module() error\n");
                        goto error_power_off;
                }
        }
@@ -2714,7 +2754,7 @@ static int ov5670_probe(struct i2c_client *client)
 
        ret = ov5670_init_controls(ov5670);
        if (ret) {
-               err_msg = "ov5670_init_controls() error";
+               dev_err_probe(&client->dev, ret, "ov5670_init_controls() error\n");
                goto error_mutex_destroy;
        }
 
@@ -2727,7 +2767,7 @@ static int ov5670_probe(struct i2c_client *client)
        ov5670->pad.flags = MEDIA_PAD_FL_SOURCE;
        ret = media_entity_pads_init(&ov5670->sd.entity, 1, &ov5670->pad);
        if (ret) {
-               err_msg = "media_entity_pads_init() error";
+               dev_err_probe(&client->dev, ret, "media_entity_pads_init() error\n");
                goto error_handler_free;
        }
 
@@ -2741,7 +2781,7 @@ static int ov5670_probe(struct i2c_client *client)
        /* Async register for subdev */
        ret = v4l2_async_register_subdev_sensor(&ov5670->sd);
        if (ret < 0) {
-               err_msg = "v4l2_async_register_subdev() error";
+               dev_err_probe(&client->dev, ret, "v4l2_async_register_subdev() error\n");
                goto error_pm_disable;
        }
 
@@ -2764,8 +2804,8 @@ error_power_off:
        if (full_power)
                ov5670_runtime_suspend(&client->dev);
 
-error_print:
-       dev_err(&client->dev, "%s: %s %d\n", __func__, err_msg, ret);
+error_endpoint:
+       v4l2_fwnode_endpoint_free(&ov5670->endpoint);
 
        return ret;
 }
@@ -2782,6 +2822,8 @@ static void ov5670_remove(struct i2c_client *client)
 
        pm_runtime_disable(&client->dev);
        ov5670_runtime_suspend(&client->dev);
+
+       v4l2_fwnode_endpoint_free(&ov5670->endpoint);
 }
 
 static const struct dev_pm_ops ov5670_pm_ops = {
index b1bb0833571e82b04036f2d18386850155ada080..ecbded4f07653e76432dfcfcaa863ffbfa6fdbbf 100644 (file)
@@ -1894,14 +1894,9 @@ static int ov7670_probe(struct i2c_client *client)
                        info->pclk_hb_disable = true;
        }
 
-       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;
-       }
+       info->clk = devm_clk_get_optional(&client->dev, "xclk");
+       if (IS_ERR(info->clk))
+               return PTR_ERR(info->clk);
 
        ret = ov7670_init_gpio(client, info);
        if (ret)
index cf8384e09413bee6e1d0b3e155e81b694c2bf210..b5c7881383ca7a2f0b4c546911b6418524d6562d 100644 (file)
@@ -1709,46 +1709,6 @@ static int ov8856_identify_module(struct ov8856 *ov8856)
                return -ENXIO;
        }
 
-       ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
-                              OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING);
-       if (ret)
-               return ret;
-
-       ret = ov8856_write_reg(ov8856, OV8856_OTP_MODE_CTRL,
-                              OV8856_REG_VALUE_08BIT, OV8856_OTP_MODE_AUTO);
-       if (ret) {
-               dev_err(&client->dev, "failed to set otp mode");
-               return ret;
-       }
-
-       ret = ov8856_write_reg(ov8856, OV8856_OTP_LOAD_CTRL,
-                              OV8856_REG_VALUE_08BIT,
-                              OV8856_OTP_LOAD_CTRL_ENABLE);
-       if (ret) {
-               dev_err(&client->dev, "failed to enable load control");
-               return ret;
-       }
-
-       ret = ov8856_read_reg(ov8856, OV8856_MODULE_REVISION,
-                             OV8856_REG_VALUE_08BIT, &val);
-       if (ret) {
-               dev_err(&client->dev, "failed to read module revision");
-               return ret;
-       }
-
-       dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n",
-                val,
-                val == OV8856_2A_MODULE ? "2A" :
-                val == OV8856_1B_MODULE ? "1B" : "unknown revision",
-                client->addr);
-
-       ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
-                              OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY);
-       if (ret) {
-               dev_err(&client->dev, "failed to exit streaming mode");
-               return ret;
-       }
-
        ov8856->identified = true;
 
        return 0;
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c
deleted file mode 100644 (file)
index 5996153..0000000
+++ /dev/null
@@ -1,1652 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Driver for Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor
- * with embedded SoC ISP.
- *
- * Copyright (C) 2011, Samsung Electronics Co., Ltd.
- * Sylwester Nawrocki <s.nawrocki@samsung.com>
- *
- * Based on a driver authored by Dongsoo Nathaniel Kim.
- * Copyright (C) 2009, Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/media.h>
-#include <linux/module.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-
-#include <media/media-entity.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-subdev.h>
-#include <media/v4l2-mediabus.h>
-#include <media/i2c/s5k6aa.h>
-
-static int debug;
-module_param(debug, int, 0644);
-
-#define DRIVER_NAME                    "S5K6AA"
-
-/* The token to indicate array termination */
-#define S5K6AA_TERM                    0xffff
-#define S5K6AA_OUT_WIDTH_DEF           640
-#define S5K6AA_OUT_HEIGHT_DEF          480
-#define S5K6AA_WIN_WIDTH_MAX           1280
-#define S5K6AA_WIN_HEIGHT_MAX          1024
-#define S5K6AA_WIN_WIDTH_MIN           8
-#define S5K6AA_WIN_HEIGHT_MIN          8
-
-/*
- * H/W register Interface (0xD0000000 - 0xD0000FFF)
- */
-#define AHB_MSB_ADDR_PTR               0xfcfc
-#define GEN_REG_OFFSH                  0xd000
-#define REG_CMDWR_ADDRH                        0x0028
-#define REG_CMDWR_ADDRL                        0x002a
-#define REG_CMDRD_ADDRH                        0x002c
-#define REG_CMDRD_ADDRL                        0x002e
-#define REG_CMDBUF0_ADDR               0x0f12
-#define REG_CMDBUF1_ADDR               0x0f10
-
-/*
- * Host S/W Register interface (0x70000000 - 0x70002000)
- * The value of the two most significant address bytes is 0x7000,
- * (HOST_SWIF_OFFS_H). The register addresses below specify 2 LSBs.
- */
-#define HOST_SWIF_OFFSH                        0x7000
-
-/* Initialization parameters */
-/* Master clock frequency in KHz */
-#define REG_I_INCLK_FREQ_L             0x01b8
-#define REG_I_INCLK_FREQ_H             0x01ba
-#define  MIN_MCLK_FREQ_KHZ             6000U
-#define  MAX_MCLK_FREQ_KHZ             27000U
-#define REG_I_USE_NPVI_CLOCKS          0x01c6
-#define REG_I_USE_NMIPI_CLOCKS         0x01c8
-
-/* Clock configurations, n = 0..2. REG_I_* frequency unit is 4 kHz. */
-#define REG_I_OPCLK_4KHZ(n)            ((n) * 6 + 0x01cc)
-#define REG_I_MIN_OUTRATE_4KHZ(n)      ((n) * 6 + 0x01ce)
-#define REG_I_MAX_OUTRATE_4KHZ(n)      ((n) * 6 + 0x01d0)
-#define  SYS_PLL_OUT_FREQ              (48000000 / 4000)
-#define  PCLK_FREQ_MIN                 (24000000 / 4000)
-#define  PCLK_FREQ_MAX                 (48000000 / 4000)
-#define REG_I_INIT_PARAMS_UPDATED      0x01e0
-#define REG_I_ERROR_INFO               0x01e2
-
-/* General purpose parameters */
-#define REG_USER_BRIGHTNESS            0x01e4
-#define REG_USER_CONTRAST              0x01e6
-#define REG_USER_SATURATION            0x01e8
-#define REG_USER_SHARPBLUR             0x01ea
-
-#define REG_G_SPEC_EFFECTS             0x01ee
-#define REG_G_ENABLE_PREV              0x01f0
-#define REG_G_ENABLE_PREV_CHG          0x01f2
-#define REG_G_NEW_CFG_SYNC             0x01f8
-#define REG_G_PREVZOOM_IN_WIDTH                0x020a
-#define REG_G_PREVZOOM_IN_HEIGHT       0x020c
-#define REG_G_PREVZOOM_IN_XOFFS                0x020e
-#define REG_G_PREVZOOM_IN_YOFFS                0x0210
-#define REG_G_INPUTS_CHANGE_REQ                0x021a
-#define REG_G_ACTIVE_PREV_CFG          0x021c
-#define REG_G_PREV_CFG_CHG             0x021e
-#define REG_G_PREV_OPEN_AFTER_CH       0x0220
-#define REG_G_PREV_CFG_ERROR           0x0222
-
-/* Preview control section. n = 0...4. */
-#define PREG(n, x)                     ((n) * 0x26 + x)
-#define REG_P_OUT_WIDTH(n)             PREG(n, 0x0242)
-#define REG_P_OUT_HEIGHT(n)            PREG(n, 0x0244)
-#define REG_P_FMT(n)                   PREG(n, 0x0246)
-#define REG_P_MAX_OUT_RATE(n)          PREG(n, 0x0248)
-#define REG_P_MIN_OUT_RATE(n)          PREG(n, 0x024a)
-#define REG_P_PVI_MASK(n)              PREG(n, 0x024c)
-#define REG_P_CLK_INDEX(n)             PREG(n, 0x024e)
-#define REG_P_FR_RATE_TYPE(n)          PREG(n, 0x0250)
-#define  FR_RATE_DYNAMIC               0
-#define  FR_RATE_FIXED                 1
-#define  FR_RATE_FIXED_ACCURATE                2
-#define REG_P_FR_RATE_Q_TYPE(n)                PREG(n, 0x0252)
-#define  FR_RATE_Q_BEST_FRRATE         1 /* Binning enabled */
-#define  FR_RATE_Q_BEST_QUALITY                2 /* Binning disabled */
-/* Frame period in 0.1 ms units */
-#define REG_P_MAX_FR_TIME(n)           PREG(n, 0x0254)
-#define REG_P_MIN_FR_TIME(n)           PREG(n, 0x0256)
-/* Conversion to REG_P_[MAX/MIN]_FR_TIME value; __t: time in us */
-#define  US_TO_FR_TIME(__t)            ((__t) / 100)
-#define  S5K6AA_MIN_FR_TIME            33300  /* us */
-#define  S5K6AA_MAX_FR_TIME            650000 /* us */
-#define  S5K6AA_MAX_HIGHRES_FR_TIME    666    /* x100 us */
-/* The below 5 registers are for "device correction" values */
-#define REG_P_COLORTEMP(n)             PREG(n, 0x025e)
-#define REG_P_PREV_MIRROR(n)           PREG(n, 0x0262)
-
-/* Extended image property controls */
-/* Exposure time in 10 us units */
-#define REG_SF_USR_EXPOSURE_L          0x03c6
-#define REG_SF_USR_EXPOSURE_H          0x03c8
-#define REG_SF_USR_EXPOSURE_CHG                0x03ca
-#define REG_SF_USR_TOT_GAIN            0x03cc
-#define REG_SF_USR_TOT_GAIN_CHG                0x03ce
-#define REG_SF_RGAIN                   0x03d0
-#define REG_SF_RGAIN_CHG               0x03d2
-#define REG_SF_GGAIN                   0x03d4
-#define REG_SF_GGAIN_CHG               0x03d6
-#define REG_SF_BGAIN                   0x03d8
-#define REG_SF_BGAIN_CHG               0x03da
-#define REG_SF_FLICKER_QUANT           0x03dc
-#define REG_SF_FLICKER_QUANT_CHG       0x03de
-
-/* Output interface (parallel/MIPI) setup */
-#define REG_OIF_EN_MIPI_LANES          0x03fa
-#define REG_OIF_EN_PACKETS             0x03fc
-#define REG_OIF_CFG_CHG                        0x03fe
-
-/* Auto-algorithms enable mask */
-#define REG_DBG_AUTOALG_EN             0x0400
-#define  AALG_ALL_EN_MASK              (1 << 0)
-#define  AALG_AE_EN_MASK               (1 << 1)
-#define  AALG_DIVLEI_EN_MASK           (1 << 2)
-#define  AALG_WB_EN_MASK               (1 << 3)
-#define  AALG_FLICKER_EN_MASK          (1 << 5)
-#define  AALG_FIT_EN_MASK              (1 << 6)
-#define  AALG_WRHW_EN_MASK             (1 << 7)
-
-/* Firmware revision information */
-#define REG_FW_APIVER                  0x012e
-#define  S5K6AAFX_FW_APIVER            0x0001
-#define REG_FW_REVISION                        0x0130
-
-/* For now we use only one user configuration register set */
-#define S5K6AA_MAX_PRESETS             1
-
-static const char * const s5k6aa_supply_names[] = {
-       "vdd_core",     /* Digital core supply 1.5V (1.4V to 1.6V) */
-       "vdda",         /* Analog power supply 2.8V (2.6V to 3.0V) */
-       "vdd_reg",      /* Regulator input power 1.8V (1.7V to 1.9V)
-                          or 2.8V (2.6V to 3.0) */
-       "vddio",        /* I/O supply 1.8V (1.65V to 1.95V)
-                          or 2.8V (2.5V to 3.1V) */
-};
-#define S5K6AA_NUM_SUPPLIES ARRAY_SIZE(s5k6aa_supply_names)
-
-enum s5k6aa_gpio_id {
-       STBY,
-       RSET,
-       GPIO_NUM,
-};
-
-struct s5k6aa_regval {
-       u16 addr;
-       u16 val;
-};
-
-struct s5k6aa_pixfmt {
-       u32 code;
-       u32 colorspace;
-       /* REG_P_FMT(x) register value */
-       u16 reg_p_fmt;
-};
-
-struct s5k6aa_preset {
-       /* output pixel format and resolution */
-       struct v4l2_mbus_framefmt mbus_fmt;
-       u8 clk_id;
-       u8 index;
-};
-
-struct s5k6aa_ctrls {
-       struct v4l2_ctrl_handler handler;
-       /* Auto / manual white balance cluster */
-       struct v4l2_ctrl *awb;
-       struct v4l2_ctrl *gain_red;
-       struct v4l2_ctrl *gain_blue;
-       struct v4l2_ctrl *gain_green;
-       /* Mirror cluster */
-       struct v4l2_ctrl *hflip;
-       struct v4l2_ctrl *vflip;
-       /* Auto exposure / manual exposure and gain cluster */
-       struct v4l2_ctrl *auto_exp;
-       struct v4l2_ctrl *exposure;
-       struct v4l2_ctrl *gain;
-};
-
-struct s5k6aa_interval {
-       u16 reg_fr_time;
-       struct v4l2_fract interval;
-       /* Maximum rectangle for the interval */
-       struct v4l2_frmsize_discrete size;
-};
-
-struct s5k6aa {
-       struct v4l2_subdev sd;
-       struct media_pad pad;
-
-       enum v4l2_mbus_type bus_type;
-       u8 mipi_lanes;
-
-       int (*s_power)(int enable);
-       struct regulator_bulk_data supplies[S5K6AA_NUM_SUPPLIES];
-       struct s5k6aa_gpio gpio[GPIO_NUM];
-
-       /* external master clock frequency */
-       unsigned long mclk_frequency;
-       /* ISP internal master clock frequency */
-       u16 clk_fop;
-       /* output pixel clock frequency range */
-       u16 pclk_fmin;
-       u16 pclk_fmax;
-
-       unsigned int inv_hflip:1;
-       unsigned int inv_vflip:1;
-
-       /* protects the struct members below */
-       struct mutex lock;
-
-       /* sensor matrix scan window */
-       struct v4l2_rect ccd_rect;
-
-       struct s5k6aa_ctrls ctrls;
-       struct s5k6aa_preset presets[S5K6AA_MAX_PRESETS];
-       struct s5k6aa_preset *preset;
-       const struct s5k6aa_interval *fiv;
-
-       unsigned int streaming:1;
-       unsigned int apply_cfg:1;
-       unsigned int apply_crop:1;
-       unsigned int power;
-};
-
-static struct s5k6aa_regval s5k6aa_analog_config[] = {
-       /* Analog settings */
-       { 0x112a, 0x0000 }, { 0x1132, 0x0000 },
-       { 0x113e, 0x0000 }, { 0x115c, 0x0000 },
-       { 0x1164, 0x0000 }, { 0x1174, 0x0000 },
-       { 0x1178, 0x0000 }, { 0x077a, 0x0000 },
-       { 0x077c, 0x0000 }, { 0x077e, 0x0000 },
-       { 0x0780, 0x0000 }, { 0x0782, 0x0000 },
-       { 0x0784, 0x0000 }, { 0x0786, 0x0000 },
-       { 0x0788, 0x0000 }, { 0x07a2, 0x0000 },
-       { 0x07a4, 0x0000 }, { 0x07a6, 0x0000 },
-       { 0x07a8, 0x0000 }, { 0x07b6, 0x0000 },
-       { 0x07b8, 0x0002 }, { 0x07ba, 0x0004 },
-       { 0x07bc, 0x0004 }, { 0x07be, 0x0005 },
-       { 0x07c0, 0x0005 }, { S5K6AA_TERM, 0 },
-};
-
-/* TODO: Add RGB888 and Bayer format */
-static const struct s5k6aa_pixfmt s5k6aa_formats[] = {
-       { MEDIA_BUS_FMT_YUYV8_2X8,      V4L2_COLORSPACE_JPEG,   5 },
-       /* range 16-240 */
-       { MEDIA_BUS_FMT_YUYV8_2X8,      V4L2_COLORSPACE_REC709, 6 },
-       { MEDIA_BUS_FMT_RGB565_2X8_BE,  V4L2_COLORSPACE_JPEG,   0 },
-};
-
-static const struct s5k6aa_interval s5k6aa_intervals[] = {
-       { 1000, {10000, 1000000}, {1280, 1024} }, /* 10 fps */
-       { 666,  {15000, 1000000}, {1280, 1024} }, /* 15 fps */
-       { 500,  {20000, 1000000}, {1280, 720} },  /* 20 fps */
-       { 400,  {25000, 1000000}, {640, 480} },   /* 25 fps */
-       { 333,  {33300, 1000000}, {640, 480} },   /* 30 fps */
-};
-
-#define S5K6AA_INTERVAL_DEF_INDEX 1 /* 15 fps */
-
-static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
-{
-       return &container_of(ctrl->handler, struct s5k6aa, ctrls.handler)->sd;
-}
-
-static inline struct s5k6aa *to_s5k6aa(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct s5k6aa, sd);
-}
-
-/* Set initial values for all preview presets */
-static void s5k6aa_presets_data_init(struct s5k6aa *s5k6aa)
-{
-       struct s5k6aa_preset *preset = &s5k6aa->presets[0];
-       int i;
-
-       for (i = 0; i < S5K6AA_MAX_PRESETS; i++) {
-               preset->mbus_fmt.width  = S5K6AA_OUT_WIDTH_DEF;
-               preset->mbus_fmt.height = S5K6AA_OUT_HEIGHT_DEF;
-               preset->mbus_fmt.code   = s5k6aa_formats[0].code;
-               preset->index           = i;
-               preset->clk_id          = 0;
-               preset++;
-       }
-
-       s5k6aa->fiv = &s5k6aa_intervals[S5K6AA_INTERVAL_DEF_INDEX];
-       s5k6aa->preset = &s5k6aa->presets[0];
-}
-
-static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
-{
-       u8 wbuf[2] = {addr >> 8, addr & 0xFF};
-       struct i2c_msg msg[2];
-       u8 rbuf[2];
-       int ret;
-
-       msg[0].addr = client->addr;
-       msg[0].flags = 0;
-       msg[0].len = 2;
-       msg[0].buf = wbuf;
-
-       msg[1].addr = client->addr;
-       msg[1].flags = I2C_M_RD;
-       msg[1].len = 2;
-       msg[1].buf = rbuf;
-
-       ret = i2c_transfer(client->adapter, msg, 2);
-       *val = be16_to_cpu(*((__be16 *)rbuf));
-
-       v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
-
-       return ret == 2 ? 0 : ret;
-}
-
-static int s5k6aa_i2c_write(struct i2c_client *client, u16 addr, u16 val)
-{
-       u8 buf[4] = {addr >> 8, addr & 0xFF, val >> 8, val & 0xFF};
-
-       int ret = i2c_master_send(client, buf, 4);
-       v4l2_dbg(3, debug, client, "i2c_write: 0x%04X : 0x%04x\n", addr, val);
-
-       return ret == 4 ? 0 : ret;
-}
-
-/* The command register write, assumes Command_Wr_addH = 0x7000. */
-static int s5k6aa_write(struct i2c_client *c, u16 addr, u16 val)
-{
-       int ret = s5k6aa_i2c_write(c, REG_CMDWR_ADDRL, addr);
-       if (ret)
-               return ret;
-       return s5k6aa_i2c_write(c, REG_CMDBUF0_ADDR, val);
-}
-
-/* The command register read, assumes Command_Rd_addH = 0x7000. */
-static int s5k6aa_read(struct i2c_client *client, u16 addr, u16 *val)
-{
-       int ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRL, addr);
-       if (ret)
-               return ret;
-       return s5k6aa_i2c_read(client, REG_CMDBUF0_ADDR, val);
-}
-
-static int s5k6aa_write_array(struct v4l2_subdev *sd,
-                             const struct s5k6aa_regval *msg)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       u16 addr_incr = 0;
-       int ret = 0;
-
-       while (msg->addr != S5K6AA_TERM) {
-               if (addr_incr != 2)
-                       ret = s5k6aa_i2c_write(client, REG_CMDWR_ADDRL,
-                                              msg->addr);
-               if (ret)
-                       break;
-               ret = s5k6aa_i2c_write(client, REG_CMDBUF0_ADDR, msg->val);
-               if (ret)
-                       break;
-               /* Assume that msg->addr is always less than 0xfffc */
-               addr_incr = (msg + 1)->addr - msg->addr;
-               msg++;
-       }
-
-       return ret;
-}
-
-/* Configure the AHB high address bytes for GTG registers access */
-static int s5k6aa_set_ahb_address(struct i2c_client *client)
-{
-       int ret = s5k6aa_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH);
-       if (ret)
-               return ret;
-       ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRH, HOST_SWIF_OFFSH);
-       if (ret)
-               return ret;
-       return s5k6aa_i2c_write(client, REG_CMDWR_ADDRH, HOST_SWIF_OFFSH);
-}
-
-/**
- * s5k6aa_configure_pixel_clocks - apply ISP main clock/PLL configuration
- * @s5k6aa: pointer to &struct s5k6aa describing the device
- *
- * Configure the internal ISP PLL for the required output frequency.
- * Locking: called with s5k6aa.lock mutex held.
- */
-static int s5k6aa_configure_pixel_clocks(struct s5k6aa *s5k6aa)
-{
-       struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
-       unsigned long fmclk = s5k6aa->mclk_frequency / 1000;
-       u16 status;
-       int ret;
-
-       if (WARN(fmclk < MIN_MCLK_FREQ_KHZ || fmclk > MAX_MCLK_FREQ_KHZ,
-                "Invalid clock frequency: %ld\n", fmclk))
-               return -EINVAL;
-
-       s5k6aa->pclk_fmin = PCLK_FREQ_MIN;
-       s5k6aa->pclk_fmax = PCLK_FREQ_MAX;
-       s5k6aa->clk_fop = SYS_PLL_OUT_FREQ;
-
-       /* External input clock frequency in kHz */
-       ret = s5k6aa_write(c, REG_I_INCLK_FREQ_H, fmclk >> 16);
-       if (!ret)
-               ret = s5k6aa_write(c, REG_I_INCLK_FREQ_L, fmclk & 0xFFFF);
-       if (!ret)
-               ret = s5k6aa_write(c, REG_I_USE_NPVI_CLOCKS, 1);
-       /* Internal PLL frequency */
-       if (!ret)
-               ret = s5k6aa_write(c, REG_I_OPCLK_4KHZ(0), s5k6aa->clk_fop);
-       if (!ret)
-               ret = s5k6aa_write(c, REG_I_MIN_OUTRATE_4KHZ(0),
-                                  s5k6aa->pclk_fmin);
-       if (!ret)
-               ret = s5k6aa_write(c, REG_I_MAX_OUTRATE_4KHZ(0),
-                                  s5k6aa->pclk_fmax);
-       if (!ret)
-               ret = s5k6aa_write(c, REG_I_INIT_PARAMS_UPDATED, 1);
-       if (!ret)
-               ret = s5k6aa_read(c, REG_I_ERROR_INFO, &status);
-
-       return ret ? ret : (status ? -EINVAL : 0);
-}
-
-/* Set horizontal and vertical image flipping */
-static int s5k6aa_set_mirror(struct s5k6aa *s5k6aa, int horiz_flip)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
-       int index = s5k6aa->preset->index;
-
-       unsigned int vflip = s5k6aa->ctrls.vflip->val ^ s5k6aa->inv_vflip;
-       unsigned int flip = (horiz_flip ^ s5k6aa->inv_hflip) | (vflip << 1);
-
-       return s5k6aa_write(client, REG_P_PREV_MIRROR(index), flip);
-}
-
-/* Configure auto/manual white balance and R/G/B gains */
-static int s5k6aa_set_awb(struct s5k6aa *s5k6aa, int awb)
-{
-       struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
-       struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
-       u16 reg;
-
-       int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &reg);
-
-       if (!ret && !awb) {
-               ret = s5k6aa_write(c, REG_SF_RGAIN, ctrls->gain_red->val);
-               if (!ret)
-                       ret = s5k6aa_write(c, REG_SF_RGAIN_CHG, 1);
-               if (ret)
-                       return ret;
-
-               ret = s5k6aa_write(c, REG_SF_GGAIN, ctrls->gain_green->val);
-               if (!ret)
-                       ret = s5k6aa_write(c, REG_SF_GGAIN_CHG, 1);
-               if (ret)
-                       return ret;
-
-               ret = s5k6aa_write(c, REG_SF_BGAIN, ctrls->gain_blue->val);
-               if (!ret)
-                       ret = s5k6aa_write(c, REG_SF_BGAIN_CHG, 1);
-       }
-       if (!ret) {
-               reg = awb ? reg | AALG_WB_EN_MASK : reg & ~AALG_WB_EN_MASK;
-               ret = s5k6aa_write(c, REG_DBG_AUTOALG_EN, reg);
-       }
-
-       return ret;
-}
-
-/* Program FW with exposure time, 'exposure' in us units */
-static int s5k6aa_set_user_exposure(struct i2c_client *client, int exposure)
-{
-       unsigned int time = exposure / 10;
-
-       int ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_L, time & 0xffff);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_H, time >> 16);
-       if (ret)
-               return ret;
-       return s5k6aa_write(client, REG_SF_USR_EXPOSURE_CHG, 1);
-}
-
-static int s5k6aa_set_user_gain(struct i2c_client *client, int gain)
-{
-       int ret = s5k6aa_write(client, REG_SF_USR_TOT_GAIN, gain);
-       if (ret)
-               return ret;
-       return s5k6aa_write(client, REG_SF_USR_TOT_GAIN_CHG, 1);
-}
-
-/* Set auto/manual exposure and total gain */
-static int s5k6aa_set_auto_exposure(struct s5k6aa *s5k6aa, int value)
-{
-       struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
-       unsigned int exp_time = s5k6aa->ctrls.exposure->val;
-       u16 auto_alg;
-
-       int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &auto_alg);
-       if (ret)
-               return ret;
-
-       v4l2_dbg(1, debug, c, "man_exp: %d, auto_exp: %d, a_alg: 0x%x\n",
-                exp_time, value, auto_alg);
-
-       if (value == V4L2_EXPOSURE_AUTO) {
-               auto_alg |= AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK;
-       } else {
-               ret = s5k6aa_set_user_exposure(c, exp_time);
-               if (ret)
-                       return ret;
-               ret = s5k6aa_set_user_gain(c, s5k6aa->ctrls.gain->val);
-               if (ret)
-                       return ret;
-               auto_alg &= ~(AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK);
-       }
-
-       return s5k6aa_write(c, REG_DBG_AUTOALG_EN, auto_alg);
-}
-
-static int s5k6aa_set_anti_flicker(struct s5k6aa *s5k6aa, int value)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
-       u16 auto_alg;
-       int ret;
-
-       ret = s5k6aa_read(client, REG_DBG_AUTOALG_EN, &auto_alg);
-       if (ret)
-               return ret;
-
-       if (value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) {
-               auto_alg |= AALG_FLICKER_EN_MASK;
-       } else {
-               auto_alg &= ~AALG_FLICKER_EN_MASK;
-               /* The V4L2_CID_LINE_FREQUENCY control values match
-                * the register values */
-               ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT, value);
-               if (ret)
-                       return ret;
-               ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT_CHG, 1);
-               if (ret)
-                       return ret;
-       }
-
-       return s5k6aa_write(client, REG_DBG_AUTOALG_EN, auto_alg);
-}
-
-static int s5k6aa_set_colorfx(struct s5k6aa *s5k6aa, int val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
-       static const struct v4l2_control colorfx[] = {
-               { V4L2_COLORFX_NONE,     0 },
-               { V4L2_COLORFX_BW,       1 },
-               { V4L2_COLORFX_NEGATIVE, 2 },
-               { V4L2_COLORFX_SEPIA,    3 },
-               { V4L2_COLORFX_SKY_BLUE, 4 },
-               { V4L2_COLORFX_SKETCH,   5 },
-       };
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(colorfx); i++) {
-               if (colorfx[i].id == val)
-                       return s5k6aa_write(client, REG_G_SPEC_EFFECTS,
-                                           colorfx[i].value);
-       }
-       return -EINVAL;
-}
-
-static int s5k6aa_preview_config_status(struct i2c_client *client)
-{
-       u16 error = 0;
-       int ret = s5k6aa_read(client, REG_G_PREV_CFG_ERROR, &error);
-
-       v4l2_dbg(1, debug, client, "error: 0x%x (%d)\n", error, ret);
-       return ret ? ret : (error ? -EINVAL : 0);
-}
-
-static int s5k6aa_get_pixfmt_index(struct s5k6aa *s5k6aa,
-                                  struct v4l2_mbus_framefmt *mf)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(s5k6aa_formats); i++)
-               if (mf->colorspace == s5k6aa_formats[i].colorspace &&
-                   mf->code == s5k6aa_formats[i].code)
-                       return i;
-       return 0;
-}
-
-static int s5k6aa_set_output_framefmt(struct s5k6aa *s5k6aa,
-                                     struct s5k6aa_preset *preset)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
-       int fmt_index = s5k6aa_get_pixfmt_index(s5k6aa, &preset->mbus_fmt);
-       int ret;
-
-       ret = s5k6aa_write(client, REG_P_OUT_WIDTH(preset->index),
-                          preset->mbus_fmt.width);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_P_OUT_HEIGHT(preset->index),
-                                  preset->mbus_fmt.height);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_P_FMT(preset->index),
-                                  s5k6aa_formats[fmt_index].reg_p_fmt);
-       return ret;
-}
-
-static int s5k6aa_set_input_params(struct s5k6aa *s5k6aa)
-{
-       struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
-       struct v4l2_rect *r = &s5k6aa->ccd_rect;
-       int ret;
-
-       ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width);
-       if (!ret)
-               ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height);
-       if (!ret)
-               ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left);
-       if (!ret)
-               ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top);
-       if (!ret)
-               ret = s5k6aa_write(c, REG_G_INPUTS_CHANGE_REQ, 1);
-       if (!ret)
-               s5k6aa->apply_crop = 0;
-
-       return ret;
-}
-
-/**
- * s5k6aa_configure_video_bus - configure the video output interface
- * @s5k6aa: pointer to &struct s5k6aa describing the device
- * @bus_type: video bus type: parallel or MIPI-CSI
- * @nlanes: number of MIPI lanes to be used (MIPI-CSI only)
- *
- * Note: Only parallel bus operation has been tested.
- */
-static int s5k6aa_configure_video_bus(struct s5k6aa *s5k6aa,
-                                     enum v4l2_mbus_type bus_type, int nlanes)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
-       u16 cfg = 0;
-       int ret;
-
-       /*
-        * TODO: The sensor is supposed to support BT.601 and BT.656
-        * 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_DPHY)
-               cfg = nlanes;
-       else if (bus_type != V4L2_MBUS_PARALLEL)
-               return -EINVAL;
-
-       ret = s5k6aa_write(client, REG_OIF_EN_MIPI_LANES, cfg);
-       if (ret)
-               return ret;
-       return s5k6aa_write(client, REG_OIF_CFG_CHG, 1);
-}
-
-/* This function should be called when switching to new user configuration set*/
-static int s5k6aa_new_config_sync(struct i2c_client *client, int timeout,
-                                 int cid)
-{
-       unsigned long end = jiffies + msecs_to_jiffies(timeout);
-       u16 reg = 1;
-       int ret;
-
-       ret = s5k6aa_write(client, REG_G_ACTIVE_PREV_CFG, cid);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_G_NEW_CFG_SYNC, 1);
-       if (timeout == 0)
-               return ret;
-
-       while (ret >= 0 && time_is_after_jiffies(end)) {
-               ret = s5k6aa_read(client, REG_G_NEW_CFG_SYNC, &reg);
-               if (!reg)
-                       return 0;
-               usleep_range(1000, 5000);
-       }
-       return ret ? ret : -ETIMEDOUT;
-}
-
-/**
- * s5k6aa_set_prev_config - write user preview register set
- * @s5k6aa: pointer to &struct s5k6aa describing the device
- * @preset: s5kaa preset to be applied
- *
- * Configure output resolution and color format, pixel clock
- * frequency range, device frame rate type and frame period range.
- */
-static int s5k6aa_set_prev_config(struct s5k6aa *s5k6aa,
-                                 struct s5k6aa_preset *preset)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
-       int idx = preset->index;
-       u16 frame_rate_q;
-       int ret;
-
-       if (s5k6aa->fiv->reg_fr_time >= S5K6AA_MAX_HIGHRES_FR_TIME)
-               frame_rate_q = FR_RATE_Q_BEST_FRRATE;
-       else
-               frame_rate_q = FR_RATE_Q_BEST_QUALITY;
-
-       ret = s5k6aa_set_output_framefmt(s5k6aa, preset);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_P_MAX_OUT_RATE(idx),
-                                  s5k6aa->pclk_fmax);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_P_MIN_OUT_RATE(idx),
-                                  s5k6aa->pclk_fmin);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_P_CLK_INDEX(idx),
-                                  preset->clk_id);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_P_FR_RATE_TYPE(idx),
-                                  FR_RATE_DYNAMIC);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_P_FR_RATE_Q_TYPE(idx),
-                                  frame_rate_q);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_P_MAX_FR_TIME(idx),
-                                  s5k6aa->fiv->reg_fr_time + 33);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_P_MIN_FR_TIME(idx),
-                                  s5k6aa->fiv->reg_fr_time - 33);
-       if (!ret)
-               ret = s5k6aa_new_config_sync(client, 250, idx);
-       if (!ret)
-               ret = s5k6aa_preview_config_status(client);
-       if (!ret)
-               s5k6aa->apply_cfg = 0;
-
-       v4l2_dbg(1, debug, client, "Frame interval: %d +/- 3.3ms. (%d)\n",
-                s5k6aa->fiv->reg_fr_time, ret);
-       return ret;
-}
-
-/**
- * s5k6aa_initialize_isp - basic ISP MCU initialization
- * @sd: pointer to V4L2 sub-device descriptor
- *
- * Configure AHB addresses for registers read/write; configure PLLs for
- * required output pixel clock. The ISP power supply needs to be already
- * enabled, with an optional H/W reset.
- * Locking: called with s5k6aa.lock mutex held.
- */
-static int s5k6aa_initialize_isp(struct v4l2_subdev *sd)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       int ret;
-
-       s5k6aa->apply_crop = 1;
-       s5k6aa->apply_cfg = 1;
-       msleep(100);
-
-       ret = s5k6aa_set_ahb_address(client);
-       if (ret)
-               return ret;
-       ret = s5k6aa_configure_video_bus(s5k6aa, s5k6aa->bus_type,
-                                        s5k6aa->mipi_lanes);
-       if (ret)
-               return ret;
-       ret = s5k6aa_write_array(sd, s5k6aa_analog_config);
-       if (ret)
-               return ret;
-       msleep(20);
-
-       return s5k6aa_configure_pixel_clocks(s5k6aa);
-}
-
-static int s5k6aa_gpio_set_value(struct s5k6aa *priv, int id, u32 val)
-{
-       if (!gpio_is_valid(priv->gpio[id].gpio))
-               return 0;
-       gpio_set_value(priv->gpio[id].gpio, !!val);
-       return 1;
-}
-
-static int s5k6aa_gpio_assert(struct s5k6aa *priv, int id)
-{
-       return s5k6aa_gpio_set_value(priv, id, priv->gpio[id].level);
-}
-
-static int s5k6aa_gpio_deassert(struct s5k6aa *priv, int id)
-{
-       return s5k6aa_gpio_set_value(priv, id, !priv->gpio[id].level);
-}
-
-static int __s5k6aa_power_on(struct s5k6aa *s5k6aa)
-{
-       int ret;
-
-       ret = regulator_bulk_enable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
-       if (ret)
-               return ret;
-       if (s5k6aa_gpio_deassert(s5k6aa, STBY))
-               usleep_range(150, 200);
-
-       if (s5k6aa->s_power)
-               ret = s5k6aa->s_power(1);
-       usleep_range(4000, 5000);
-
-       if (s5k6aa_gpio_deassert(s5k6aa, RSET))
-               msleep(20);
-
-       return ret;
-}
-
-static int __s5k6aa_power_off(struct s5k6aa *s5k6aa)
-{
-       int ret;
-
-       if (s5k6aa_gpio_assert(s5k6aa, RSET))
-               usleep_range(100, 150);
-
-       if (s5k6aa->s_power) {
-               ret = s5k6aa->s_power(0);
-               if (ret)
-                       return ret;
-       }
-       if (s5k6aa_gpio_assert(s5k6aa, STBY))
-               usleep_range(50, 100);
-       s5k6aa->streaming = 0;
-
-       return regulator_bulk_disable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
-}
-
-/*
- * V4L2 subdev core and video operations
- */
-static int s5k6aa_set_power(struct v4l2_subdev *sd, int on)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       int ret = 0;
-
-       mutex_lock(&s5k6aa->lock);
-
-       if (s5k6aa->power == !on) {
-               if (on) {
-                       ret = __s5k6aa_power_on(s5k6aa);
-                       if (!ret)
-                               ret = s5k6aa_initialize_isp(sd);
-               } else {
-                       ret = __s5k6aa_power_off(s5k6aa);
-               }
-
-               if (!ret)
-                       s5k6aa->power += on ? 1 : -1;
-       }
-
-       mutex_unlock(&s5k6aa->lock);
-
-       if (!on || ret || s5k6aa->power != 1)
-               return ret;
-
-       return v4l2_ctrl_handler_setup(sd->ctrl_handler);
-}
-
-static int __s5k6aa_stream(struct s5k6aa *s5k6aa, int enable)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
-       int ret = 0;
-
-       ret = s5k6aa_write(client, REG_G_ENABLE_PREV, enable);
-       if (!ret)
-               ret = s5k6aa_write(client, REG_G_ENABLE_PREV_CHG, 1);
-       if (!ret)
-               s5k6aa->streaming = enable;
-
-       return ret;
-}
-
-static int s5k6aa_s_stream(struct v4l2_subdev *sd, int on)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       int ret = 0;
-
-       mutex_lock(&s5k6aa->lock);
-
-       if (s5k6aa->streaming == !on) {
-               if (!ret && s5k6aa->apply_cfg)
-                       ret = s5k6aa_set_prev_config(s5k6aa, s5k6aa->preset);
-               if (s5k6aa->apply_crop)
-                       ret = s5k6aa_set_input_params(s5k6aa);
-               if (!ret)
-                       ret = __s5k6aa_stream(s5k6aa, !!on);
-       }
-       mutex_unlock(&s5k6aa->lock);
-
-       return ret;
-}
-
-static int s5k6aa_g_frame_interval(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_frame_interval *fi)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-
-       mutex_lock(&s5k6aa->lock);
-       fi->interval = s5k6aa->fiv->interval;
-       mutex_unlock(&s5k6aa->lock);
-
-       return 0;
-}
-
-static int __s5k6aa_set_frame_interval(struct s5k6aa *s5k6aa,
-                                      struct v4l2_subdev_frame_interval *fi)
-{
-       struct v4l2_mbus_framefmt *mbus_fmt = &s5k6aa->preset->mbus_fmt;
-       const struct s5k6aa_interval *fiv = &s5k6aa_intervals[0];
-       unsigned int err, min_err = UINT_MAX;
-       unsigned int i, fr_time;
-
-       if (fi->interval.denominator == 0)
-               return -EINVAL;
-
-       fr_time = fi->interval.numerator * 10000 / fi->interval.denominator;
-
-       for (i = 0; i < ARRAY_SIZE(s5k6aa_intervals); i++) {
-               const struct s5k6aa_interval *iv = &s5k6aa_intervals[i];
-
-               if (mbus_fmt->width > iv->size.width ||
-                   mbus_fmt->height > iv->size.height)
-                       continue;
-
-               err = abs(iv->reg_fr_time - fr_time);
-               if (err < min_err) {
-                       fiv = iv;
-                       min_err = err;
-               }
-       }
-       s5k6aa->fiv = fiv;
-
-       v4l2_dbg(1, debug, &s5k6aa->sd, "Changed frame interval to %d us\n",
-                fiv->reg_fr_time * 100);
-       return 0;
-}
-
-static int s5k6aa_s_frame_interval(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_frame_interval *fi)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       int ret;
-
-       v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n",
-                fi->interval.numerator, fi->interval.denominator);
-
-       mutex_lock(&s5k6aa->lock);
-       ret = __s5k6aa_set_frame_interval(s5k6aa, fi);
-       s5k6aa->apply_cfg = 1;
-
-       mutex_unlock(&s5k6aa->lock);
-       return ret;
-}
-
-/*
- * V4L2 subdev pad level and video operations
- */
-static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd,
-                             struct v4l2_subdev_state *sd_state,
-                             struct v4l2_subdev_frame_interval_enum *fie)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       const struct s5k6aa_interval *fi;
-       int ret = 0;
-
-       if (fie->index >= ARRAY_SIZE(s5k6aa_intervals))
-               return -EINVAL;
-
-       v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN,
-                             S5K6AA_WIN_WIDTH_MAX, 1,
-                             &fie->height, S5K6AA_WIN_HEIGHT_MIN,
-                             S5K6AA_WIN_HEIGHT_MAX, 1, 0);
-
-       mutex_lock(&s5k6aa->lock);
-       fi = &s5k6aa_intervals[fie->index];
-       if (fie->width > fi->size.width || fie->height > fi->size.height)
-               ret = -EINVAL;
-       else
-               fie->interval = fi->interval;
-       mutex_unlock(&s5k6aa->lock);
-
-       return ret;
-}
-
-static int s5k6aa_enum_mbus_code(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_state *sd_state,
-                                struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (code->index >= ARRAY_SIZE(s5k6aa_formats))
-               return -EINVAL;
-
-       code->code = s5k6aa_formats[code->index].code;
-       return 0;
-}
-
-static int s5k6aa_enum_frame_size(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_state *sd_state,
-                                 struct v4l2_subdev_frame_size_enum *fse)
-{
-       int i = ARRAY_SIZE(s5k6aa_formats);
-
-       if (fse->index > 0)
-               return -EINVAL;
-
-       while (--i)
-               if (fse->code == s5k6aa_formats[i].code)
-                       break;
-
-       fse->code = s5k6aa_formats[i].code;
-       fse->min_width  = S5K6AA_WIN_WIDTH_MIN;
-       fse->max_width  = S5K6AA_WIN_WIDTH_MAX;
-       fse->max_height = S5K6AA_WIN_HEIGHT_MIN;
-       fse->min_height = S5K6AA_WIN_HEIGHT_MAX;
-
-       return 0;
-}
-
-static struct v4l2_rect *
-__s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa,
-                      struct v4l2_subdev_state *sd_state,
-                      enum v4l2_subdev_format_whence which)
-{
-       if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
-               return &s5k6aa->ccd_rect;
-
-       WARN_ON(which != V4L2_SUBDEV_FORMAT_TRY);
-       return v4l2_subdev_get_try_crop(&s5k6aa->sd, sd_state, 0);
-}
-
-static void s5k6aa_try_format(struct s5k6aa *s5k6aa,
-                             struct v4l2_mbus_framefmt *mf)
-{
-       unsigned int index;
-
-       v4l_bound_align_image(&mf->width, S5K6AA_WIN_WIDTH_MIN,
-                             S5K6AA_WIN_WIDTH_MAX, 1,
-                             &mf->height, S5K6AA_WIN_HEIGHT_MIN,
-                             S5K6AA_WIN_HEIGHT_MAX, 1, 0);
-
-       if (mf->colorspace != V4L2_COLORSPACE_JPEG &&
-           mf->colorspace != V4L2_COLORSPACE_REC709)
-               mf->colorspace = V4L2_COLORSPACE_JPEG;
-
-       index = s5k6aa_get_pixfmt_index(s5k6aa, mf);
-
-       mf->colorspace  = s5k6aa_formats[index].colorspace;
-       mf->code        = s5k6aa_formats[index].code;
-       mf->field       = V4L2_FIELD_NONE;
-}
-
-static int s5k6aa_get_fmt(struct v4l2_subdev *sd,
-                         struct v4l2_subdev_state *sd_state,
-                         struct v4l2_subdev_format *fmt)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       struct v4l2_mbus_framefmt *mf;
-
-       memset(fmt->reserved, 0, sizeof(fmt->reserved));
-
-       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
-               fmt->format = *mf;
-               return 0;
-       }
-
-       mutex_lock(&s5k6aa->lock);
-       fmt->format = s5k6aa->preset->mbus_fmt;
-       mutex_unlock(&s5k6aa->lock);
-
-       return 0;
-}
-
-static int s5k6aa_set_fmt(struct v4l2_subdev *sd,
-                         struct v4l2_subdev_state *sd_state,
-                         struct v4l2_subdev_format *fmt)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       struct s5k6aa_preset *preset = s5k6aa->preset;
-       struct v4l2_mbus_framefmt *mf;
-       struct v4l2_rect *crop;
-       int ret = 0;
-
-       mutex_lock(&s5k6aa->lock);
-       s5k6aa_try_format(s5k6aa, &fmt->format);
-
-       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
-               crop = v4l2_subdev_get_try_crop(sd, sd_state, 0);
-       } else {
-               if (s5k6aa->streaming) {
-                       ret = -EBUSY;
-               } else {
-                       mf = &preset->mbus_fmt;
-                       crop = &s5k6aa->ccd_rect;
-                       s5k6aa->apply_cfg = 1;
-               }
-       }
-
-       if (ret == 0) {
-               struct v4l2_subdev_frame_interval fiv = {
-                       .interval = {0, 1}
-               };
-
-               *mf = fmt->format;
-               /*
-                * Make sure the crop window is valid, i.e. its size is
-                * greater than the output window, as the ISP supports
-                * only down-scaling.
-                */
-               crop->width = clamp_t(unsigned int, crop->width, mf->width,
-                                     S5K6AA_WIN_WIDTH_MAX);
-               crop->height = clamp_t(unsigned int, crop->height, mf->height,
-                                      S5K6AA_WIN_HEIGHT_MAX);
-               crop->left = clamp_t(unsigned int, crop->left, 0,
-                                    S5K6AA_WIN_WIDTH_MAX - crop->width);
-               crop->top  = clamp_t(unsigned int, crop->top, 0,
-                                    S5K6AA_WIN_HEIGHT_MAX - crop->height);
-
-               /* Reset to minimum possible frame interval */
-               ret = __s5k6aa_set_frame_interval(s5k6aa, &fiv);
-       }
-       mutex_unlock(&s5k6aa->lock);
-
-       return ret;
-}
-
-static int s5k6aa_get_selection(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_state *sd_state,
-                               struct v4l2_subdev_selection *sel)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       struct v4l2_rect *rect;
-
-       if (sel->target != V4L2_SEL_TGT_CROP)
-               return -EINVAL;
-
-       memset(sel->reserved, 0, sizeof(sel->reserved));
-
-       mutex_lock(&s5k6aa->lock);
-       rect = __s5k6aa_get_crop_rect(s5k6aa, sd_state, sel->which);
-       sel->r = *rect;
-       mutex_unlock(&s5k6aa->lock);
-
-       v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
-                rect->left, rect->top, rect->width, rect->height);
-
-       return 0;
-}
-
-static int s5k6aa_set_selection(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_state *sd_state,
-                               struct v4l2_subdev_selection *sel)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       struct v4l2_mbus_framefmt *mf;
-       unsigned int max_x, max_y;
-       struct v4l2_rect *crop_r;
-
-       if (sel->target != V4L2_SEL_TGT_CROP)
-               return -EINVAL;
-
-       mutex_lock(&s5k6aa->lock);
-       crop_r = __s5k6aa_get_crop_rect(s5k6aa, sd_state, sel->which);
-
-       if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
-               mf = &s5k6aa->preset->mbus_fmt;
-               s5k6aa->apply_crop = 1;
-       } else {
-               mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
-       }
-       v4l_bound_align_image(&sel->r.width, mf->width,
-                             S5K6AA_WIN_WIDTH_MAX, 1,
-                             &sel->r.height, mf->height,
-                             S5K6AA_WIN_HEIGHT_MAX, 1, 0);
-
-       max_x = (S5K6AA_WIN_WIDTH_MAX - sel->r.width) & ~1;
-       max_y = (S5K6AA_WIN_HEIGHT_MAX - sel->r.height) & ~1;
-
-       sel->r.left = clamp_t(unsigned int, sel->r.left, 0, max_x);
-       sel->r.top  = clamp_t(unsigned int, sel->r.top, 0, max_y);
-
-       *crop_r = sel->r;
-
-       mutex_unlock(&s5k6aa->lock);
-
-       v4l2_dbg(1, debug, sd, "Set crop rectangle: (%d,%d)/%dx%d\n",
-                crop_r->left, crop_r->top, crop_r->width, crop_r->height);
-
-       return 0;
-}
-
-static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = {
-       .enum_mbus_code         = s5k6aa_enum_mbus_code,
-       .enum_frame_size        = s5k6aa_enum_frame_size,
-       .enum_frame_interval    = s5k6aa_enum_frame_interval,
-       .get_fmt                = s5k6aa_get_fmt,
-       .set_fmt                = s5k6aa_set_fmt,
-       .get_selection          = s5k6aa_get_selection,
-       .set_selection          = s5k6aa_set_selection,
-};
-
-static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
-       .g_frame_interval       = s5k6aa_g_frame_interval,
-       .s_frame_interval       = s5k6aa_s_frame_interval,
-       .s_stream               = s5k6aa_s_stream,
-};
-
-/*
- * V4L2 subdev controls
- */
-
-static int s5k6aa_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       int idx, err = 0;
-
-       v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val);
-
-       mutex_lock(&s5k6aa->lock);
-       /*
-        * If the device is not powered up by the host driver do
-        * not apply any controls to H/W at this time. Instead
-        * the controls will be restored right after power-up.
-        */
-       if (s5k6aa->power == 0)
-               goto unlock;
-       idx = s5k6aa->preset->index;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               err = s5k6aa_set_awb(s5k6aa, ctrl->val);
-               break;
-
-       case V4L2_CID_BRIGHTNESS:
-               err = s5k6aa_write(client, REG_USER_BRIGHTNESS, ctrl->val);
-               break;
-
-       case V4L2_CID_COLORFX:
-               err = s5k6aa_set_colorfx(s5k6aa, ctrl->val);
-               break;
-
-       case V4L2_CID_CONTRAST:
-               err = s5k6aa_write(client, REG_USER_CONTRAST, ctrl->val);
-               break;
-
-       case V4L2_CID_EXPOSURE_AUTO:
-               err = s5k6aa_set_auto_exposure(s5k6aa, ctrl->val);
-               break;
-
-       case V4L2_CID_HFLIP:
-               err = s5k6aa_set_mirror(s5k6aa, ctrl->val);
-               if (err)
-                       break;
-               err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
-               break;
-
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               err = s5k6aa_set_anti_flicker(s5k6aa, ctrl->val);
-               break;
-
-       case V4L2_CID_SATURATION:
-               err = s5k6aa_write(client, REG_USER_SATURATION, ctrl->val);
-               break;
-
-       case V4L2_CID_SHARPNESS:
-               err = s5k6aa_write(client, REG_USER_SHARPBLUR, ctrl->val);
-               break;
-
-       case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
-               err = s5k6aa_write(client, REG_P_COLORTEMP(idx), ctrl->val);
-               if (err)
-                       break;
-               err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
-               break;
-       }
-unlock:
-       mutex_unlock(&s5k6aa->lock);
-       return err;
-}
-
-static const struct v4l2_ctrl_ops s5k6aa_ctrl_ops = {
-       .s_ctrl = s5k6aa_s_ctrl,
-};
-
-static int s5k6aa_log_status(struct v4l2_subdev *sd)
-{
-       v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
-       return 0;
-}
-
-#define V4L2_CID_RED_GAIN      (V4L2_CTRL_CLASS_CAMERA | 0x1001)
-#define V4L2_CID_GREEN_GAIN    (V4L2_CTRL_CLASS_CAMERA | 0x1002)
-#define V4L2_CID_BLUE_GAIN     (V4L2_CTRL_CLASS_CAMERA | 0x1003)
-
-static const struct v4l2_ctrl_config s5k6aa_ctrls[] = {
-       {
-               .ops    = &s5k6aa_ctrl_ops,
-               .id     = V4L2_CID_RED_GAIN,
-               .type   = V4L2_CTRL_TYPE_INTEGER,
-               .name   = "Gain, Red",
-               .min    = 0,
-               .max    = 256,
-               .def    = 127,
-               .step   = 1,
-       }, {
-               .ops    = &s5k6aa_ctrl_ops,
-               .id     = V4L2_CID_GREEN_GAIN,
-               .type   = V4L2_CTRL_TYPE_INTEGER,
-               .name   = "Gain, Green",
-               .min    = 0,
-               .max    = 256,
-               .def    = 127,
-               .step   = 1,
-       }, {
-               .ops    = &s5k6aa_ctrl_ops,
-               .id     = V4L2_CID_BLUE_GAIN,
-               .type   = V4L2_CTRL_TYPE_INTEGER,
-               .name   = "Gain, Blue",
-               .min    = 0,
-               .max    = 256,
-               .def    = 127,
-               .step   = 1,
-       },
-};
-
-static int s5k6aa_initialize_ctrls(struct s5k6aa *s5k6aa)
-{
-       const struct v4l2_ctrl_ops *ops = &s5k6aa_ctrl_ops;
-       struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
-       struct v4l2_ctrl_handler *hdl = &ctrls->handler;
-
-       int ret = v4l2_ctrl_handler_init(hdl, 16);
-       if (ret)
-               return ret;
-       /* Auto white balance cluster */
-       ctrls->awb = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE,
-                                      0, 1, 1, 1);
-       ctrls->gain_red = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[0], NULL);
-       ctrls->gain_green = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[1], NULL);
-       ctrls->gain_blue = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[2], NULL);
-       v4l2_ctrl_auto_cluster(4, &ctrls->awb, 0, false);
-
-       ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
-       ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
-       v4l2_ctrl_cluster(2, &ctrls->hflip);
-
-       ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
-                               V4L2_CID_EXPOSURE_AUTO,
-                               V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO);
-       /* Exposure time: x 1 us */
-       ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
-                                           0, 6000000U, 1, 100000U);
-       /* Total gain: 256 <=> 1x */
-       ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
-                                       0, 256, 1, 256);
-       v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 0, false);
-
-       v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_POWER_LINE_FREQUENCY,
-                              V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
-                              V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
-
-       v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_COLORFX,
-                              V4L2_COLORFX_SKY_BLUE, ~0x6f, V4L2_COLORFX_NONE);
-
-       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_WHITE_BALANCE_TEMPERATURE,
-                         0, 256, 1, 0);
-
-       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0);
-       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -127, 127, 1, 0);
-       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0);
-       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -127, 127, 1, 0);
-
-       if (hdl->error) {
-               ret = hdl->error;
-               v4l2_ctrl_handler_free(hdl);
-               return ret;
-       }
-
-       s5k6aa->sd.ctrl_handler = hdl;
-       return 0;
-}
-
-/*
- * V4L2 subdev internal operations
- */
-static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-{
-       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd,
-                                                                      fh->state,
-                                                                      0);
-       struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
-
-       format->colorspace = s5k6aa_formats[0].colorspace;
-       format->code = s5k6aa_formats[0].code;
-       format->width = S5K6AA_OUT_WIDTH_DEF;
-       format->height = S5K6AA_OUT_HEIGHT_DEF;
-       format->field = V4L2_FIELD_NONE;
-
-       crop->width = S5K6AA_WIN_WIDTH_MAX;
-       crop->height = S5K6AA_WIN_HEIGHT_MAX;
-       crop->left = 0;
-       crop->top = 0;
-
-       return 0;
-}
-
-static int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
-       u16 api_ver = 0, fw_rev = 0;
-
-       int ret = s5k6aa_set_ahb_address(client);
-
-       if (!ret)
-               ret = s5k6aa_read(client, REG_FW_APIVER, &api_ver);
-       if (!ret)
-               ret = s5k6aa_read(client, REG_FW_REVISION, &fw_rev);
-       if (ret) {
-               v4l2_err(&s5k6aa->sd, "FW revision check failed!\n");
-               return ret;
-       }
-
-       v4l2_info(&s5k6aa->sd, "FW API ver.: 0x%X, FW rev.: 0x%X\n",
-                 api_ver, fw_rev);
-
-       return api_ver == S5K6AAFX_FW_APIVER ? 0 : -ENODEV;
-}
-
-static int s5k6aa_registered(struct v4l2_subdev *sd)
-{
-       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
-       int ret;
-
-       mutex_lock(&s5k6aa->lock);
-       ret = __s5k6aa_power_on(s5k6aa);
-       if (!ret) {
-               msleep(100);
-               ret = s5k6aa_check_fw_revision(s5k6aa);
-               __s5k6aa_power_off(s5k6aa);
-       }
-       mutex_unlock(&s5k6aa->lock);
-
-       return ret;
-}
-
-static const struct v4l2_subdev_internal_ops s5k6aa_subdev_internal_ops = {
-       .registered = s5k6aa_registered,
-       .open = s5k6aa_open,
-};
-
-static const struct v4l2_subdev_core_ops s5k6aa_core_ops = {
-       .s_power = s5k6aa_set_power,
-       .log_status = s5k6aa_log_status,
-};
-
-static const struct v4l2_subdev_ops s5k6aa_subdev_ops = {
-       .core = &s5k6aa_core_ops,
-       .pad = &s5k6aa_pad_ops,
-       .video = &s5k6aa_video_ops,
-};
-
-/*
- * GPIO setup
- */
-
-static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa,
-                                 const struct s5k6aa_platform_data *pdata)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
-       const struct s5k6aa_gpio *gpio;
-       unsigned long flags;
-       int ret;
-
-       s5k6aa->gpio[STBY].gpio = -EINVAL;
-       s5k6aa->gpio[RSET].gpio  = -EINVAL;
-
-       gpio = &pdata->gpio_stby;
-       if (gpio_is_valid(gpio->gpio)) {
-               flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
-                     | GPIOF_EXPORT;
-               ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags,
-                                           "S5K6AA_STBY");
-               if (ret < 0)
-                       return ret;
-
-               s5k6aa->gpio[STBY] = *gpio;
-       }
-
-       gpio = &pdata->gpio_reset;
-       if (gpio_is_valid(gpio->gpio)) {
-               flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
-                     | GPIOF_EXPORT;
-               ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags,
-                                           "S5K6AA_RST");
-               if (ret < 0)
-                       return ret;
-
-               s5k6aa->gpio[RSET] = *gpio;
-       }
-
-       return 0;
-}
-
-static int s5k6aa_probe(struct i2c_client *client)
-{
-       const struct s5k6aa_platform_data *pdata = client->dev.platform_data;
-       struct v4l2_subdev *sd;
-       struct s5k6aa *s5k6aa;
-       int i, ret;
-
-       if (pdata == NULL) {
-               dev_err(&client->dev, "Platform data not specified\n");
-               return -EINVAL;
-       }
-
-       if (pdata->mclk_frequency == 0) {
-               dev_err(&client->dev, "MCLK frequency not specified\n");
-               return -EINVAL;
-       }
-
-       s5k6aa = devm_kzalloc(&client->dev, sizeof(*s5k6aa), GFP_KERNEL);
-       if (!s5k6aa)
-               return -ENOMEM;
-
-       mutex_init(&s5k6aa->lock);
-
-       s5k6aa->mclk_frequency = pdata->mclk_frequency;
-       s5k6aa->bus_type = pdata->bus_type;
-       s5k6aa->mipi_lanes = pdata->nlanes;
-       s5k6aa->s_power = pdata->set_power;
-       s5k6aa->inv_hflip = pdata->horiz_flip;
-       s5k6aa->inv_vflip = pdata->vert_flip;
-
-       sd = &s5k6aa->sd;
-       v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops);
-       /* 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;
-
-       s5k6aa->pad.flags = MEDIA_PAD_FL_SOURCE;
-       sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
-       ret = media_entity_pads_init(&sd->entity, 1, &s5k6aa->pad);
-       if (ret)
-               return ret;
-
-       ret = s5k6aa_configure_gpios(s5k6aa, pdata);
-       if (ret)
-               goto out_err;
-
-       for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++)
-               s5k6aa->supplies[i].supply = s5k6aa_supply_names[i];
-
-       ret = devm_regulator_bulk_get(&client->dev, S5K6AA_NUM_SUPPLIES,
-                                s5k6aa->supplies);
-       if (ret) {
-               dev_err(&client->dev, "Failed to get regulators\n");
-               goto out_err;
-       }
-
-       ret = s5k6aa_initialize_ctrls(s5k6aa);
-       if (ret)
-               goto out_err;
-
-       s5k6aa_presets_data_init(s5k6aa);
-
-       s5k6aa->ccd_rect.width = S5K6AA_WIN_WIDTH_MAX;
-       s5k6aa->ccd_rect.height = S5K6AA_WIN_HEIGHT_MAX;
-       s5k6aa->ccd_rect.left = 0;
-       s5k6aa->ccd_rect.top = 0;
-
-       return 0;
-
-out_err:
-       media_entity_cleanup(&s5k6aa->sd.entity);
-       return ret;
-}
-
-static void s5k6aa_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-       v4l2_device_unregister_subdev(sd);
-       v4l2_ctrl_handler_free(sd->ctrl_handler);
-       media_entity_cleanup(&sd->entity);
-}
-
-static const struct i2c_device_id s5k6aa_id[] = {
-       { DRIVER_NAME, 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(i2c, s5k6aa_id);
-
-
-static struct i2c_driver s5k6aa_i2c_driver = {
-       .driver = {
-               .name = DRIVER_NAME
-       },
-       .probe_new      = s5k6aa_probe,
-       .remove         = s5k6aa_remove,
-       .id_table       = s5k6aa_id,
-};
-
-module_i2c_driver(s5k6aa_i2c_driver);
-
-MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver");
-MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c
deleted file mode 100644 (file)
index a83c8bf..0000000
+++ /dev/null
@@ -1,762 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Driver for SiliconFile SR030PC30 VGA (1/10-Inch) Image Sensor with ISP
- *
- * Copyright (C) 2010 Samsung Electronics Co., Ltd
- * Author: Sylwester Nawrocki, s.nawrocki@samsung.com
- *
- * Based on original driver authored by Dongsoo Nathaniel Kim
- * and HeungJun Kim <riverful.kim@samsung.com>.
- *
- * Based on mt9v011 Micron Digital Image Sensor driver
- * Copyright (c) 2009 Mauro Carvalho Chehab
- */
-
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-subdev.h>
-#include <media/v4l2-mediabus.h>
-#include <media/v4l2-ctrls.h>
-#include <media/i2c/sr030pc30.h>
-
-static int debug;
-module_param(debug, int, 0644);
-
-#define MODULE_NAME    "SR030PC30"
-
-/*
- * Register offsets within a page
- * b15..b8 - page id, b7..b0 - register address
- */
-#define POWER_CTRL_REG         0x0001
-#define PAGEMODE_REG           0x03
-#define DEVICE_ID_REG          0x0004
-#define NOON010PC30_ID         0x86
-#define SR030PC30_ID           0x8C
-#define VDO_CTL1_REG           0x0010
-#define SUBSAMPL_NONE_VGA      0
-#define SUBSAMPL_QVGA          0x10
-#define SUBSAMPL_QQVGA         0x20
-#define VDO_CTL2_REG           0x0011
-#define SYNC_CTL_REG           0x0012
-#define WIN_ROWH_REG           0x0020
-#define WIN_ROWL_REG           0x0021
-#define WIN_COLH_REG           0x0022
-#define WIN_COLL_REG           0x0023
-#define WIN_HEIGHTH_REG                0x0024
-#define WIN_HEIGHTL_REG                0x0025
-#define WIN_WIDTHH_REG         0x0026
-#define WIN_WIDTHL_REG         0x0027
-#define HBLANKH_REG            0x0040
-#define HBLANKL_REG            0x0041
-#define VSYNCH_REG             0x0042
-#define VSYNCL_REG             0x0043
-/* page 10 */
-#define ISP_CTL_REG(n)         (0x1010 + (n))
-#define YOFS_REG               0x1040
-#define DARK_YOFS_REG          0x1041
-#define AG_ABRTH_REG           0x1050
-#define SAT_CTL_REG            0x1060
-#define BSAT_REG               0x1061
-#define RSAT_REG               0x1062
-#define AG_SAT_TH_REG          0x1063
-/* page 11 */
-#define ZLPF_CTRL_REG          0x1110
-#define ZLPF_CTRL2_REG         0x1112
-#define ZLPF_AGH_THR_REG       0x1121
-#define ZLPF_THR_REG           0x1160
-#define ZLPF_DYN_THR_REG       0x1160
-/* page 12 */
-#define YCLPF_CTL1_REG         0x1240
-#define YCLPF_CTL2_REG         0x1241
-#define YCLPF_THR_REG          0x1250
-#define BLPF_CTL_REG           0x1270
-#define BLPF_THR1_REG          0x1274
-#define BLPF_THR2_REG          0x1275
-/* page 14 - Lens Shading Compensation */
-#define LENS_CTRL_REG          0x1410
-#define LENS_XCEN_REG          0x1420
-#define LENS_YCEN_REG          0x1421
-#define LENS_R_COMP_REG                0x1422
-#define LENS_G_COMP_REG                0x1423
-#define LENS_B_COMP_REG                0x1424
-/* page 15 - Color correction */
-#define CMC_CTL_REG            0x1510
-#define CMC_OFSGH_REG          0x1514
-#define CMC_OFSGL_REG          0x1516
-#define CMC_SIGN_REG           0x1517
-/* Color correction coefficients */
-#define CMC_COEF_REG(n)                (0x1530 + (n))
-/* Color correction offset coefficients */
-#define CMC_OFS_REG(n)         (0x1540 + (n))
-/* page 16 - Gamma correction */
-#define GMA_CTL_REG            0x1610
-/* Gamma correction coefficients 0.14 */
-#define GMA_COEF_REG(n)                (0x1630 + (n))
-/* page 20 - Auto Exposure */
-#define AE_CTL1_REG            0x2010
-#define AE_CTL2_REG            0x2011
-#define AE_FRM_CTL_REG         0x2020
-#define AE_FINE_CTL_REG(n)     (0x2028 + (n))
-#define EXP_TIMEH_REG          0x2083
-#define EXP_TIMEM_REG          0x2084
-#define EXP_TIMEL_REG          0x2085
-#define EXP_MMINH_REG          0x2086
-#define EXP_MMINL_REG          0x2087
-#define EXP_MMAXH_REG          0x2088
-#define EXP_MMAXM_REG          0x2089
-#define EXP_MMAXL_REG          0x208A
-/* page 22 - Auto White Balance */
-#define AWB_CTL1_REG           0x2210
-#define AWB_ENABLE             0x80
-#define AWB_CTL2_REG           0x2211
-#define MWB_ENABLE             0x01
-/* RGB gain control (manual WB) when AWB_CTL1[7]=0 */
-#define AWB_RGAIN_REG          0x2280
-#define AWB_GGAIN_REG          0x2281
-#define AWB_BGAIN_REG          0x2282
-#define AWB_RMAX_REG           0x2283
-#define AWB_RMIN_REG           0x2284
-#define AWB_BMAX_REG           0x2285
-#define AWB_BMIN_REG           0x2286
-/* R, B gain range in bright light conditions */
-#define AWB_RMAXB_REG          0x2287
-#define AWB_RMINB_REG          0x2288
-#define AWB_BMAXB_REG          0x2289
-#define AWB_BMINB_REG          0x228A
-/* manual white balance, when AWB_CTL2[0]=1 */
-#define MWB_RGAIN_REG          0x22B2
-#define MWB_BGAIN_REG          0x22B3
-/* the token to mark an array end */
-#define REG_TERM               0xFFFF
-
-/* Minimum and maximum exposure time in ms */
-#define EXPOS_MIN_MS           1
-#define EXPOS_MAX_MS           125
-
-struct sr030pc30_info {
-       struct v4l2_subdev sd;
-       struct v4l2_ctrl_handler hdl;
-       const struct sr030pc30_platform_data *pdata;
-       const struct sr030pc30_format *curr_fmt;
-       const struct sr030pc30_frmsize *curr_win;
-       unsigned int hflip:1;
-       unsigned int vflip:1;
-       unsigned int sleep:1;
-       struct {
-               /* auto whitebalance control cluster */
-               struct v4l2_ctrl *awb;
-               struct v4l2_ctrl *red;
-               struct v4l2_ctrl *blue;
-       };
-       struct {
-               /* auto exposure control cluster */
-               struct v4l2_ctrl *autoexp;
-               struct v4l2_ctrl *exp;
-       };
-       u8 i2c_reg_page;
-};
-
-struct sr030pc30_format {
-       u32 code;
-       enum v4l2_colorspace colorspace;
-       u16 ispctl1_reg;
-};
-
-struct sr030pc30_frmsize {
-       u16 width;
-       u16 height;
-       int vid_ctl1;
-};
-
-struct i2c_regval {
-       u16 addr;
-       u16 val;
-};
-
-/* supported resolutions */
-static const struct sr030pc30_frmsize sr030pc30_sizes[] = {
-       {
-               .width          = 640,
-               .height         = 480,
-               .vid_ctl1       = SUBSAMPL_NONE_VGA,
-       }, {
-               .width          = 320,
-               .height         = 240,
-               .vid_ctl1       = SUBSAMPL_QVGA,
-       }, {
-               .width          = 160,
-               .height         = 120,
-               .vid_ctl1       = SUBSAMPL_QQVGA,
-       },
-};
-
-/* supported pixel formats */
-static const struct sr030pc30_format sr030pc30_formats[] = {
-       {
-               .code           = MEDIA_BUS_FMT_YUYV8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0x03,
-       }, {
-               .code           = MEDIA_BUS_FMT_YVYU8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0x02,
-       }, {
-               .code           = MEDIA_BUS_FMT_VYUY8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0,
-       }, {
-               .code           = MEDIA_BUS_FMT_UYVY8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0x01,
-       }, {
-               .code           = MEDIA_BUS_FMT_RGB565_2X8_BE,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-               .ispctl1_reg    = 0x40,
-       },
-};
-
-static const struct i2c_regval sr030pc30_base_regs[] = {
-       /* Window size and position within pixel matrix */
-       { WIN_ROWH_REG,         0x00 }, { WIN_ROWL_REG,         0x06 },
-       { WIN_COLH_REG,         0x00 }, { WIN_COLL_REG,         0x06 },
-       { WIN_HEIGHTH_REG,      0x01 }, { WIN_HEIGHTL_REG,      0xE0 },
-       { WIN_WIDTHH_REG,       0x02 }, { WIN_WIDTHL_REG,       0x80 },
-       { HBLANKH_REG,          0x01 }, { HBLANKL_REG,          0x50 },
-       { VSYNCH_REG,           0x00 }, { VSYNCL_REG,           0x14 },
-       { SYNC_CTL_REG,         0 },
-       /* Color corection and saturation */
-       { ISP_CTL_REG(0),       0x30 }, { YOFS_REG,             0x80 },
-       { DARK_YOFS_REG,        0x04 }, { AG_ABRTH_REG,         0x78 },
-       { SAT_CTL_REG,          0x1F }, { BSAT_REG,             0x90 },
-       { AG_SAT_TH_REG,        0xF0 }, { 0x1064,               0x80 },
-       { CMC_CTL_REG,          0x03 }, { CMC_OFSGH_REG,        0x3C },
-       { CMC_OFSGL_REG,        0x2C }, { CMC_SIGN_REG,         0x2F },
-       { CMC_COEF_REG(0),      0xCB }, { CMC_OFS_REG(0),       0x87 },
-       { CMC_COEF_REG(1),      0x61 }, { CMC_OFS_REG(1),       0x18 },
-       { CMC_COEF_REG(2),      0x16 }, { CMC_OFS_REG(2),       0x91 },
-       { CMC_COEF_REG(3),      0x23 }, { CMC_OFS_REG(3),       0x94 },
-       { CMC_COEF_REG(4),      0xCE }, { CMC_OFS_REG(4),       0x9f },
-       { CMC_COEF_REG(5),      0x2B }, { CMC_OFS_REG(5),       0x33 },
-       { CMC_COEF_REG(6),      0x01 }, { CMC_OFS_REG(6),       0x00 },
-       { CMC_COEF_REG(7),      0x34 }, { CMC_OFS_REG(7),       0x94 },
-       { CMC_COEF_REG(8),      0x75 }, { CMC_OFS_REG(8),       0x14 },
-       /* Color corection coefficients */
-       { GMA_CTL_REG,          0x03 }, { GMA_COEF_REG(0),      0x00 },
-       { GMA_COEF_REG(1),      0x19 }, { GMA_COEF_REG(2),      0x26 },
-       { GMA_COEF_REG(3),      0x3B }, { GMA_COEF_REG(4),      0x5D },
-       { GMA_COEF_REG(5),      0x79 }, { GMA_COEF_REG(6),      0x8E },
-       { GMA_COEF_REG(7),      0x9F }, { GMA_COEF_REG(8),      0xAF },
-       { GMA_COEF_REG(9),      0xBD }, { GMA_COEF_REG(10),     0xCA },
-       { GMA_COEF_REG(11),     0xDD }, { GMA_COEF_REG(12),     0xEC },
-       { GMA_COEF_REG(13),     0xF7 }, { GMA_COEF_REG(14),     0xFF },
-       /* Noise reduction, Z-LPF, YC-LPF and BLPF filters setup */
-       { ZLPF_CTRL_REG,        0x99 }, { ZLPF_CTRL2_REG,       0x0E },
-       { ZLPF_AGH_THR_REG,     0x29 }, { ZLPF_THR_REG,         0x0F },
-       { ZLPF_DYN_THR_REG,     0x63 }, { YCLPF_CTL1_REG,       0x23 },
-       { YCLPF_CTL2_REG,       0x3B }, { YCLPF_THR_REG,        0x05 },
-       { BLPF_CTL_REG,         0x1D }, { BLPF_THR1_REG,        0x05 },
-       { BLPF_THR2_REG,        0x04 },
-       /* Automatic white balance */
-       { AWB_CTL1_REG,         0xFB }, { AWB_CTL2_REG,         0x26 },
-       { AWB_RMAX_REG,         0x54 }, { AWB_RMIN_REG,         0x2B },
-       { AWB_BMAX_REG,         0x57 }, { AWB_BMIN_REG,         0x29 },
-       { AWB_RMAXB_REG,        0x50 }, { AWB_RMINB_REG,        0x43 },
-       { AWB_BMAXB_REG,        0x30 }, { AWB_BMINB_REG,        0x22 },
-       /* Auto exposure */
-       { AE_CTL1_REG,          0x8C }, { AE_CTL2_REG,          0x04 },
-       { AE_FRM_CTL_REG,       0x01 }, { AE_FINE_CTL_REG(0),   0x3F },
-       { AE_FINE_CTL_REG(1),   0xA3 }, { AE_FINE_CTL_REG(3),   0x34 },
-       /* Lens shading compensation */
-       { LENS_CTRL_REG,        0x01 }, { LENS_XCEN_REG,        0x80 },
-       { LENS_YCEN_REG,        0x70 }, { LENS_R_COMP_REG,      0x53 },
-       { LENS_G_COMP_REG,      0x40 }, { LENS_B_COMP_REG,      0x3e },
-       { REG_TERM,             0 },
-};
-
-static inline struct sr030pc30_info *to_sr030pc30(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct sr030pc30_info, sd);
-}
-
-static inline int set_i2c_page(struct sr030pc30_info *info,
-                              struct i2c_client *client, unsigned int reg)
-{
-       int ret = 0;
-       u32 page = reg >> 8 & 0xFF;
-
-       if (info->i2c_reg_page != page && (reg & 0xFF) != 0x03) {
-               ret = i2c_smbus_write_byte_data(client, PAGEMODE_REG, page);
-               if (!ret)
-                       info->i2c_reg_page = page;
-       }
-       return ret;
-}
-
-static int cam_i2c_read(struct v4l2_subdev *sd, u32 reg_addr)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct sr030pc30_info *info = to_sr030pc30(sd);
-
-       int ret = set_i2c_page(info, client, reg_addr);
-       if (!ret)
-               ret = i2c_smbus_read_byte_data(client, reg_addr & 0xFF);
-       return ret;
-}
-
-static int cam_i2c_write(struct v4l2_subdev *sd, u32 reg_addr, u32 val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct sr030pc30_info *info = to_sr030pc30(sd);
-
-       int ret = set_i2c_page(info, client, reg_addr);
-       if (!ret)
-               ret = i2c_smbus_write_byte_data(
-                       client, reg_addr & 0xFF, val);
-       return ret;
-}
-
-static inline int sr030pc30_bulk_write_reg(struct v4l2_subdev *sd,
-                               const struct i2c_regval *msg)
-{
-       while (msg->addr != REG_TERM) {
-               int ret = cam_i2c_write(sd, msg->addr, msg->val);
-               if (ret)
-                       return ret;
-               msg++;
-       }
-       return 0;
-}
-
-/* Device reset and sleep mode control */
-static int sr030pc30_pwr_ctrl(struct v4l2_subdev *sd,
-                                    bool reset, bool sleep)
-{
-       struct sr030pc30_info *info = to_sr030pc30(sd);
-       u8 reg = sleep ? 0xF1 : 0xF0;
-       int ret = 0;
-
-       if (reset)
-               ret = cam_i2c_write(sd, POWER_CTRL_REG, reg | 0x02);
-       if (!ret) {
-               ret = cam_i2c_write(sd, POWER_CTRL_REG, reg);
-               if (!ret) {
-                       info->sleep = sleep;
-                       if (reset)
-                               info->i2c_reg_page = -1;
-               }
-       }
-       return ret;
-}
-
-static int sr030pc30_set_flip(struct v4l2_subdev *sd)
-{
-       struct sr030pc30_info *info = to_sr030pc30(sd);
-
-       s32 reg = cam_i2c_read(sd, VDO_CTL2_REG);
-       if (reg < 0)
-               return reg;
-
-       reg &= 0x7C;
-       if (info->hflip)
-               reg |= 0x01;
-       if (info->vflip)
-               reg |= 0x02;
-       return cam_i2c_write(sd, VDO_CTL2_REG, reg | 0x80);
-}
-
-/* Configure resolution, color format and image flip */
-static int sr030pc30_set_params(struct v4l2_subdev *sd)
-{
-       struct sr030pc30_info *info = to_sr030pc30(sd);
-       int ret;
-
-       if (!info->curr_win)
-               return -EINVAL;
-
-       /* Configure the resolution through subsampling */
-       ret = cam_i2c_write(sd, VDO_CTL1_REG,
-                           info->curr_win->vid_ctl1);
-
-       if (!ret && info->curr_fmt)
-               ret = cam_i2c_write(sd, ISP_CTL_REG(0),
-                               info->curr_fmt->ispctl1_reg);
-       if (!ret)
-               ret = sr030pc30_set_flip(sd);
-
-       return ret;
-}
-
-/* Find nearest matching image pixel size. */
-static int sr030pc30_try_frame_size(struct v4l2_mbus_framefmt *mf)
-{
-       unsigned int min_err = ~0;
-       int i = ARRAY_SIZE(sr030pc30_sizes);
-       const struct sr030pc30_frmsize *fsize = &sr030pc30_sizes[0],
-                                       *match = NULL;
-       while (i--) {
-               int err = abs(fsize->width - mf->width)
-                               + abs(fsize->height - mf->height);
-               if (err < min_err) {
-                       min_err = err;
-                       match = fsize;
-               }
-               fsize++;
-       }
-       if (match) {
-               mf->width  = match->width;
-               mf->height = match->height;
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static int sr030pc30_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct sr030pc30_info *info =
-               container_of(ctrl->handler, struct sr030pc30_info, hdl);
-       struct v4l2_subdev *sd = &info->sd;
-       int ret = 0;
-
-       v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
-                        __func__, ctrl->id, ctrl->val);
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               if (ctrl->is_new) {
-                       ret = cam_i2c_write(sd, AWB_CTL2_REG,
-                                       ctrl->val ? 0x2E : 0x2F);
-                       if (!ret)
-                               ret = cam_i2c_write(sd, AWB_CTL1_REG,
-                                               ctrl->val ? 0xFB : 0x7B);
-               }
-               if (!ret && info->blue->is_new)
-                       ret = cam_i2c_write(sd, MWB_BGAIN_REG, info->blue->val);
-               if (!ret && info->red->is_new)
-                       ret = cam_i2c_write(sd, MWB_RGAIN_REG, info->red->val);
-               return ret;
-
-       case V4L2_CID_EXPOSURE_AUTO:
-               /* auto anti-flicker is also enabled here */
-               if (ctrl->is_new)
-                       ret = cam_i2c_write(sd, AE_CTL1_REG,
-                               ctrl->val == V4L2_EXPOSURE_AUTO ? 0xDC : 0x0C);
-               if (info->exp->is_new) {
-                       unsigned long expos = info->exp->val;
-
-                       expos = expos * info->pdata->clk_rate / (8 * 1000);
-
-                       if (!ret)
-                               ret = cam_i2c_write(sd, EXP_TIMEH_REG,
-                                               expos >> 16 & 0xFF);
-                       if (!ret)
-                               ret = cam_i2c_write(sd, EXP_TIMEM_REG,
-                                               expos >> 8 & 0xFF);
-                       if (!ret)
-                               ret = cam_i2c_write(sd, EXP_TIMEL_REG,
-                                               expos & 0xFF);
-               }
-               return ret;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int sr030pc30_enum_mbus_code(struct v4l2_subdev *sd,
-               struct v4l2_subdev_state *sd_state,
-               struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (!code || code->pad ||
-           code->index >= ARRAY_SIZE(sr030pc30_formats))
-               return -EINVAL;
-
-       code->code = sr030pc30_formats[code->index].code;
-       return 0;
-}
-
-static int sr030pc30_get_fmt(struct v4l2_subdev *sd,
-               struct v4l2_subdev_state *sd_state,
-               struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *mf;
-       struct sr030pc30_info *info = to_sr030pc30(sd);
-
-       if (!format || format->pad)
-               return -EINVAL;
-
-       mf = &format->format;
-
-       if (!info->curr_win || !info->curr_fmt)
-               return -EINVAL;
-
-       mf->width       = info->curr_win->width;
-       mf->height      = info->curr_win->height;
-       mf->code        = info->curr_fmt->code;
-       mf->colorspace  = info->curr_fmt->colorspace;
-       mf->field       = V4L2_FIELD_NONE;
-
-       return 0;
-}
-
-/* Return nearest media bus frame format. */
-static const struct sr030pc30_format *try_fmt(struct v4l2_subdev *sd,
-                                             struct v4l2_mbus_framefmt *mf)
-{
-       int i;
-
-       sr030pc30_try_frame_size(mf);
-
-       for (i = 0; i < ARRAY_SIZE(sr030pc30_formats); i++) {
-               if (mf->code == sr030pc30_formats[i].code)
-                       break;
-       }
-       if (i == ARRAY_SIZE(sr030pc30_formats))
-               i = 0;
-
-       mf->code = sr030pc30_formats[i].code;
-
-       return &sr030pc30_formats[i];
-}
-
-/* Return nearest media bus frame format. */
-static int sr030pc30_set_fmt(struct v4l2_subdev *sd,
-               struct v4l2_subdev_state *sd_state,
-               struct v4l2_subdev_format *format)
-{
-       struct sr030pc30_info *info = sd ? to_sr030pc30(sd) : NULL;
-       const struct sr030pc30_format *fmt;
-       struct v4l2_mbus_framefmt *mf;
-
-       if (!sd || !format)
-               return -EINVAL;
-
-       mf = &format->format;
-       if (format->pad)
-               return -EINVAL;
-
-       fmt = try_fmt(sd, mf);
-       if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
-               sd_state->pads->try_fmt = *mf;
-               return 0;
-       }
-
-       info->curr_fmt = fmt;
-
-       return sr030pc30_set_params(sd);
-}
-
-static int sr030pc30_base_config(struct v4l2_subdev *sd)
-{
-       struct sr030pc30_info *info = to_sr030pc30(sd);
-       int ret;
-       unsigned long expmin, expmax;
-
-       ret = sr030pc30_bulk_write_reg(sd, sr030pc30_base_regs);
-       if (!ret) {
-               info->curr_fmt = &sr030pc30_formats[0];
-               info->curr_win = &sr030pc30_sizes[0];
-               ret = sr030pc30_set_params(sd);
-       }
-       if (!ret)
-               ret = sr030pc30_pwr_ctrl(sd, false, false);
-
-       if (ret)
-               return ret;
-
-       expmin = EXPOS_MIN_MS * info->pdata->clk_rate / (8 * 1000);
-       expmax = EXPOS_MAX_MS * info->pdata->clk_rate / (8 * 1000);
-
-       v4l2_dbg(1, debug, sd, "%s: expmin= %lx, expmax= %lx", __func__,
-                expmin, expmax);
-
-       /* Setting up manual exposure time range */
-       ret = cam_i2c_write(sd, EXP_MMINH_REG, expmin >> 8 & 0xFF);
-       if (!ret)
-               ret = cam_i2c_write(sd, EXP_MMINL_REG, expmin & 0xFF);
-       if (!ret)
-               ret = cam_i2c_write(sd, EXP_MMAXH_REG, expmax >> 16 & 0xFF);
-       if (!ret)
-               ret = cam_i2c_write(sd, EXP_MMAXM_REG, expmax >> 8 & 0xFF);
-       if (!ret)
-               ret = cam_i2c_write(sd, EXP_MMAXL_REG, expmax & 0xFF);
-
-       return ret;
-}
-
-static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct sr030pc30_info *info = to_sr030pc30(sd);
-       const struct sr030pc30_platform_data *pdata = info->pdata;
-       int ret;
-
-       if (pdata == NULL) {
-               WARN(1, "No platform data!\n");
-               return -EINVAL;
-       }
-
-       /*
-        * Put sensor into power sleep mode before switching off
-        * power and disabling MCLK.
-        */
-       if (!on)
-               sr030pc30_pwr_ctrl(sd, false, true);
-
-       /* set_power controls sensor's power and clock */
-       if (pdata->set_power) {
-               ret = pdata->set_power(&client->dev, on);
-               if (ret)
-                       return ret;
-       }
-
-       if (on) {
-               ret = sr030pc30_base_config(sd);
-       } else {
-               ret = 0;
-               info->curr_win = NULL;
-               info->curr_fmt = NULL;
-       }
-
-       return ret;
-}
-
-static const struct v4l2_ctrl_ops sr030pc30_ctrl_ops = {
-       .s_ctrl = sr030pc30_s_ctrl,
-};
-
-static const struct v4l2_subdev_core_ops sr030pc30_core_ops = {
-       .s_power        = sr030pc30_s_power,
-};
-
-static const struct v4l2_subdev_pad_ops sr030pc30_pad_ops = {
-       .enum_mbus_code = sr030pc30_enum_mbus_code,
-       .get_fmt        = sr030pc30_get_fmt,
-       .set_fmt        = sr030pc30_set_fmt,
-};
-
-static const struct v4l2_subdev_ops sr030pc30_ops = {
-       .core   = &sr030pc30_core_ops,
-       .pad    = &sr030pc30_pad_ops,
-};
-
-/*
- * Detect sensor type. Return 0 if SR030PC30 was detected
- * or -ENODEV otherwise.
- */
-static int sr030pc30_detect(struct i2c_client *client)
-{
-       const struct sr030pc30_platform_data *pdata
-               = client->dev.platform_data;
-       int ret;
-
-       /* Enable sensor's power and clock */
-       if (pdata->set_power) {
-               ret = pdata->set_power(&client->dev, 1);
-               if (ret)
-                       return ret;
-       }
-
-       ret = i2c_smbus_read_byte_data(client, DEVICE_ID_REG);
-
-       if (pdata->set_power)
-               pdata->set_power(&client->dev, 0);
-
-       if (ret < 0) {
-               dev_err(&client->dev, "%s: I2C read failed\n", __func__);
-               return ret;
-       }
-
-       return ret == SR030PC30_ID ? 0 : -ENODEV;
-}
-
-
-static int sr030pc30_probe(struct i2c_client *client)
-{
-       struct sr030pc30_info *info;
-       struct v4l2_subdev *sd;
-       struct v4l2_ctrl_handler *hdl;
-       const struct sr030pc30_platform_data *pdata
-               = client->dev.platform_data;
-       int ret;
-
-       if (!pdata) {
-               dev_err(&client->dev, "No platform data!");
-               return -EIO;
-       }
-
-       ret = sr030pc30_detect(client);
-       if (ret)
-               return ret;
-
-       info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       sd = &info->sd;
-       info->pdata = client->dev.platform_data;
-
-       v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops);
-
-       hdl = &info->hdl;
-       v4l2_ctrl_handler_init(hdl, 6);
-       info->awb = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
-                       V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
-       info->red = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
-                       V4L2_CID_RED_BALANCE, 0, 127, 1, 64);
-       info->blue = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
-                       V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64);
-       info->autoexp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
-                       V4L2_CID_EXPOSURE_AUTO, 0, 1, 1, 1);
-       info->exp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
-                       V4L2_CID_EXPOSURE, EXPOS_MIN_MS, EXPOS_MAX_MS, 1, 30);
-       sd->ctrl_handler = hdl;
-       if (hdl->error) {
-               int err = hdl->error;
-
-               v4l2_ctrl_handler_free(hdl);
-               return err;
-       }
-       v4l2_ctrl_auto_cluster(3, &info->awb, 0, false);
-       v4l2_ctrl_auto_cluster(2, &info->autoexp, V4L2_EXPOSURE_MANUAL, false);
-       v4l2_ctrl_handler_setup(hdl);
-
-       info->i2c_reg_page      = -1;
-       info->hflip             = 1;
-
-       return 0;
-}
-
-static void sr030pc30_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-       v4l2_device_unregister_subdev(sd);
-       v4l2_ctrl_handler_free(sd->ctrl_handler);
-}
-
-static const struct i2c_device_id sr030pc30_id[] = {
-       { MODULE_NAME, 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(i2c, sr030pc30_id);
-
-
-static struct i2c_driver sr030pc30_i2c_driver = {
-       .driver = {
-               .name = MODULE_NAME
-       },
-       .probe_new      = sr030pc30_probe,
-       .remove         = sr030pc30_remove,
-       .id_table       = sr030pc30_id,
-};
-
-module_i2c_driver(sr030pc30_i2c_driver);
-
-MODULE_DESCRIPTION("Siliconfile SR030PC30 camera driver");
-MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
-MODULE_LICENSE("GPL");
index 5dcabee6677d4ef4850644fa0622cf54ac12d1b7..adbd093ad190fc3ae90b569c092fe48066c91aec 100644 (file)
@@ -1334,7 +1334,6 @@ static int vgxy61_init_cfg(struct v4l2_subdev *sd,
        struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
        struct v4l2_subdev_format fmt = { 0 };
 
-       sensor->current_mode = sensor->default_mode;
        vgxy61_fill_framefmt(sensor, sensor->current_mode, &fmt.format,
                             VGXY61_MEDIA_BUS_FMT_DEF);
 
@@ -1549,7 +1548,7 @@ static int vgxy61_tx_from_ep(struct vgxy61_dev *sensor,
        sensor->nb_of_lane = l_nb;
 
        dev_dbg(&client->dev, "tx uses %d lanes", l_nb);
-       for (i = 0; i < 5; i++) {
+       for (i = 0; i < VGXY61_NB_POLARITIES; i++) {
                dev_dbg(&client->dev, "log2phy[%d] = %d\n", i, log2phy[i]);
                dev_dbg(&client->dev, "phy2log[%d] = %d\n", i, phy2log[i]);
                dev_dbg(&client->dev, "polarity[%d] = %d\n", i, polarities[i]);
@@ -1735,6 +1734,12 @@ static int vgxy61_power_on(struct device *dev)
                }
        }
 
+       ret = vgxy61_detect(sensor);
+       if (ret) {
+               dev_err(&client->dev, "sensor detect failed %d\n", ret);
+               goto disable_clock;
+       }
+
        ret = vgxy61_patch(sensor);
        if (ret) {
                dev_err(&client->dev, "sensor patch failed %d\n", ret);
@@ -1861,21 +1866,15 @@ static int vgxy61_probe(struct i2c_client *client)
        if (ret)
                return ret;
 
-       ret = vgxy61_detect(sensor);
-       if (ret) {
-               dev_err(&client->dev, "sensor detect failed %d\n", ret);
-               return ret;
-       }
-
        vgxy61_fill_sensor_param(sensor);
        vgxy61_fill_framefmt(sensor, sensor->current_mode, &sensor->fmt,
                             VGXY61_MEDIA_BUS_FMT_DEF);
 
+       mutex_init(&sensor->lock);
+
        ret = vgxy61_update_hdr(sensor, sensor->hdr);
        if (ret)
-               return ret;
-
-       mutex_init(&sensor->lock);
+               goto error_power_off;
 
        ret = vgxy61_init_controls(sensor);
        if (ret) {
@@ -1914,8 +1913,8 @@ error_pm_runtime:
        media_entity_cleanup(&sensor->sd.entity);
 error_handler_free:
        v4l2_ctrl_handler_free(sensor->sd.ctrl_handler);
-       mutex_destroy(&sensor->lock);
 error_power_off:
+       mutex_destroy(&sensor->lock);
        vgxy61_power_off(dev);
 
        return ret;
index 4063754a67320f5d5d4026ac7e4c0dbe2eafaf04..ec1a193ba161a3594f098c94faff47437b924743 100644 (file)
@@ -854,11 +854,11 @@ static unsigned long tc358746_find_pll_settings(struct tc358746 *tc358746,
                        m_best = mul;
                        min_delta = delta;
                        best_freq = tmp;
-               };
+               }
 
                if (delta == 0)
                        break;
-       };
+       }
 
        if (!best_freq) {
                dev_err(dev, "Failed find PLL frequency\n");
diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c
deleted file mode 100644 (file)
index d35c5ec..0000000
+++ /dev/null
@@ -1,854 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vs6624.c ST VS6624 CMOS image sensor driver
- *
- * Copyright (c) 2011 Analog Devices Inc.
- */
-
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/videodev2.h>
-
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-mediabus.h>
-#include <media/v4l2-image-sizes.h>
-
-#include "vs6624_regs.h"
-
-#define MAX_FRAME_RATE  30
-
-struct vs6624 {
-       struct v4l2_subdev sd;
-       struct v4l2_ctrl_handler hdl;
-       struct v4l2_fract frame_rate;
-       struct v4l2_mbus_framefmt fmt;
-       unsigned ce_pin;
-};
-
-static const struct vs6624_format {
-       u32 mbus_code;
-       enum v4l2_colorspace colorspace;
-} vs6624_formats[] = {
-       {
-               .mbus_code      = MEDIA_BUS_FMT_UYVY8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-       },
-       {
-               .mbus_code      = MEDIA_BUS_FMT_YUYV8_2X8,
-               .colorspace     = V4L2_COLORSPACE_JPEG,
-       },
-       {
-               .mbus_code      = MEDIA_BUS_FMT_RGB565_2X8_LE,
-               .colorspace     = V4L2_COLORSPACE_SRGB,
-       },
-};
-
-static const struct v4l2_mbus_framefmt vs6624_default_fmt = {
-       .width = VGA_WIDTH,
-       .height = VGA_HEIGHT,
-       .code = MEDIA_BUS_FMT_UYVY8_2X8,
-       .field = V4L2_FIELD_NONE,
-       .colorspace = V4L2_COLORSPACE_JPEG,
-};
-
-static const u16 vs6624_p1[] = {
-       0x8104, 0x03,
-       0x8105, 0x01,
-       0xc900, 0x03,
-       0xc904, 0x47,
-       0xc905, 0x10,
-       0xc906, 0x80,
-       0xc907, 0x3a,
-       0x903a, 0x02,
-       0x903b, 0x47,
-       0x903c, 0x15,
-       0xc908, 0x31,
-       0xc909, 0xdc,
-       0xc90a, 0x80,
-       0xc90b, 0x44,
-       0x9044, 0x02,
-       0x9045, 0x31,
-       0x9046, 0xe2,
-       0xc90c, 0x07,
-       0xc90d, 0xe0,
-       0xc90e, 0x80,
-       0xc90f, 0x47,
-       0x9047, 0x90,
-       0x9048, 0x83,
-       0x9049, 0x81,
-       0x904a, 0xe0,
-       0x904b, 0x60,
-       0x904c, 0x08,
-       0x904d, 0x90,
-       0x904e, 0xc0,
-       0x904f, 0x43,
-       0x9050, 0x74,
-       0x9051, 0x01,
-       0x9052, 0xf0,
-       0x9053, 0x80,
-       0x9054, 0x05,
-       0x9055, 0xE4,
-       0x9056, 0x90,
-       0x9057, 0xc0,
-       0x9058, 0x43,
-       0x9059, 0xf0,
-       0x905a, 0x02,
-       0x905b, 0x07,
-       0x905c, 0xec,
-       0xc910, 0x5d,
-       0xc911, 0xca,
-       0xc912, 0x80,
-       0xc913, 0x5d,
-       0x905d, 0xa3,
-       0x905e, 0x04,
-       0x905f, 0xf0,
-       0x9060, 0xa3,
-       0x9061, 0x04,
-       0x9062, 0xf0,
-       0x9063, 0x22,
-       0xc914, 0x72,
-       0xc915, 0x92,
-       0xc916, 0x80,
-       0xc917, 0x64,
-       0x9064, 0x74,
-       0x9065, 0x01,
-       0x9066, 0x02,
-       0x9067, 0x72,
-       0x9068, 0x95,
-       0xc918, 0x47,
-       0xc919, 0xf2,
-       0xc91a, 0x81,
-       0xc91b, 0x69,
-       0x9169, 0x74,
-       0x916a, 0x02,
-       0x916b, 0xf0,
-       0x916c, 0xec,
-       0x916d, 0xb4,
-       0x916e, 0x10,
-       0x916f, 0x0a,
-       0x9170, 0x90,
-       0x9171, 0x80,
-       0x9172, 0x16,
-       0x9173, 0xe0,
-       0x9174, 0x70,
-       0x9175, 0x04,
-       0x9176, 0x90,
-       0x9177, 0xd3,
-       0x9178, 0xc4,
-       0x9179, 0xf0,
-       0x917a, 0x22,
-       0xc91c, 0x0a,
-       0xc91d, 0xbe,
-       0xc91e, 0x80,
-       0xc91f, 0x73,
-       0x9073, 0xfc,
-       0x9074, 0xa3,
-       0x9075, 0xe0,
-       0x9076, 0xf5,
-       0x9077, 0x82,
-       0x9078, 0x8c,
-       0x9079, 0x83,
-       0x907a, 0xa3,
-       0x907b, 0xa3,
-       0x907c, 0xe0,
-       0x907d, 0xfc,
-       0x907e, 0xa3,
-       0x907f, 0xe0,
-       0x9080, 0xc3,
-       0x9081, 0x9f,
-       0x9082, 0xff,
-       0x9083, 0xec,
-       0x9084, 0x9e,
-       0x9085, 0xfe,
-       0x9086, 0x02,
-       0x9087, 0x0a,
-       0x9088, 0xea,
-       0xc920, 0x47,
-       0xc921, 0x38,
-       0xc922, 0x80,
-       0xc923, 0x89,
-       0x9089, 0xec,
-       0x908a, 0xd3,
-       0x908b, 0x94,
-       0x908c, 0x20,
-       0x908d, 0x40,
-       0x908e, 0x01,
-       0x908f, 0x1c,
-       0x9090, 0x90,
-       0x9091, 0xd3,
-       0x9092, 0xd4,
-       0x9093, 0xec,
-       0x9094, 0xf0,
-       0x9095, 0x02,
-       0x9096, 0x47,
-       0x9097, 0x3d,
-       0xc924, 0x45,
-       0xc925, 0xca,
-       0xc926, 0x80,
-       0xc927, 0x98,
-       0x9098, 0x12,
-       0x9099, 0x77,
-       0x909a, 0xd6,
-       0x909b, 0x02,
-       0x909c, 0x45,
-       0x909d, 0xcd,
-       0xc928, 0x20,
-       0xc929, 0xd5,
-       0xc92a, 0x80,
-       0xc92b, 0x9e,
-       0x909e, 0x90,
-       0x909f, 0x82,
-       0x90a0, 0x18,
-       0x90a1, 0xe0,
-       0x90a2, 0xb4,
-       0x90a3, 0x03,
-       0x90a4, 0x0e,
-       0x90a5, 0x90,
-       0x90a6, 0x83,
-       0x90a7, 0xbf,
-       0x90a8, 0xe0,
-       0x90a9, 0x60,
-       0x90aa, 0x08,
-       0x90ab, 0x90,
-       0x90ac, 0x81,
-       0x90ad, 0xfc,
-       0x90ae, 0xe0,
-       0x90af, 0xff,
-       0x90b0, 0xc3,
-       0x90b1, 0x13,
-       0x90b2, 0xf0,
-       0x90b3, 0x90,
-       0x90b4, 0x81,
-       0x90b5, 0xfc,
-       0x90b6, 0xe0,
-       0x90b7, 0xff,
-       0x90b8, 0x02,
-       0x90b9, 0x20,
-       0x90ba, 0xda,
-       0xc92c, 0x70,
-       0xc92d, 0xbc,
-       0xc92e, 0x80,
-       0xc92f, 0xbb,
-       0x90bb, 0x90,
-       0x90bc, 0x82,
-       0x90bd, 0x18,
-       0x90be, 0xe0,
-       0x90bf, 0xb4,
-       0x90c0, 0x03,
-       0x90c1, 0x06,
-       0x90c2, 0x90,
-       0x90c3, 0xc1,
-       0x90c4, 0x06,
-       0x90c5, 0x74,
-       0x90c6, 0x05,
-       0x90c7, 0xf0,
-       0x90c8, 0x90,
-       0x90c9, 0xd3,
-       0x90ca, 0xa0,
-       0x90cb, 0x02,
-       0x90cc, 0x70,
-       0x90cd, 0xbf,
-       0xc930, 0x72,
-       0xc931, 0x21,
-       0xc932, 0x81,
-       0xc933, 0x3b,
-       0x913b, 0x7d,
-       0x913c, 0x02,
-       0x913d, 0x7f,
-       0x913e, 0x7b,
-       0x913f, 0x02,
-       0x9140, 0x72,
-       0x9141, 0x25,
-       0xc934, 0x28,
-       0xc935, 0xae,
-       0xc936, 0x80,
-       0xc937, 0xd2,
-       0x90d2, 0xf0,
-       0x90d3, 0x90,
-       0x90d4, 0xd2,
-       0x90d5, 0x0a,
-       0x90d6, 0x02,
-       0x90d7, 0x28,
-       0x90d8, 0xb4,
-       0xc938, 0x28,
-       0xc939, 0xb1,
-       0xc93a, 0x80,
-       0xc93b, 0xd9,
-       0x90d9, 0x90,
-       0x90da, 0x83,
-       0x90db, 0xba,
-       0x90dc, 0xe0,
-       0x90dd, 0xff,
-       0x90de, 0x90,
-       0x90df, 0xd2,
-       0x90e0, 0x08,
-       0x90e1, 0xe0,
-       0x90e2, 0xe4,
-       0x90e3, 0xef,
-       0x90e4, 0xf0,
-       0x90e5, 0xa3,
-       0x90e6, 0xe0,
-       0x90e7, 0x74,
-       0x90e8, 0xff,
-       0x90e9, 0xf0,
-       0x90ea, 0x90,
-       0x90eb, 0xd2,
-       0x90ec, 0x0a,
-       0x90ed, 0x02,
-       0x90ee, 0x28,
-       0x90ef, 0xb4,
-       0xc93c, 0x29,
-       0xc93d, 0x79,
-       0xc93e, 0x80,
-       0xc93f, 0xf0,
-       0x90f0, 0xf0,
-       0x90f1, 0x90,
-       0x90f2, 0xd2,
-       0x90f3, 0x0e,
-       0x90f4, 0x02,
-       0x90f5, 0x29,
-       0x90f6, 0x7f,
-       0xc940, 0x29,
-       0xc941, 0x7c,
-       0xc942, 0x80,
-       0xc943, 0xf7,
-       0x90f7, 0x90,
-       0x90f8, 0x83,
-       0x90f9, 0xba,
-       0x90fa, 0xe0,
-       0x90fb, 0xff,
-       0x90fc, 0x90,
-       0x90fd, 0xd2,
-       0x90fe, 0x0c,
-       0x90ff, 0xe0,
-       0x9100, 0xe4,
-       0x9101, 0xef,
-       0x9102, 0xf0,
-       0x9103, 0xa3,
-       0x9104, 0xe0,
-       0x9105, 0x74,
-       0x9106, 0xff,
-       0x9107, 0xf0,
-       0x9108, 0x90,
-       0x9109, 0xd2,
-       0x910a, 0x0e,
-       0x910b, 0x02,
-       0x910c, 0x29,
-       0x910d, 0x7f,
-       0xc944, 0x2a,
-       0xc945, 0x42,
-       0xc946, 0x81,
-       0xc947, 0x0e,
-       0x910e, 0xf0,
-       0x910f, 0x90,
-       0x9110, 0xd2,
-       0x9111, 0x12,
-       0x9112, 0x02,
-       0x9113, 0x2a,
-       0x9114, 0x48,
-       0xc948, 0x2a,
-       0xc949, 0x45,
-       0xc94a, 0x81,
-       0xc94b, 0x15,
-       0x9115, 0x90,
-       0x9116, 0x83,
-       0x9117, 0xba,
-       0x9118, 0xe0,
-       0x9119, 0xff,
-       0x911a, 0x90,
-       0x911b, 0xd2,
-       0x911c, 0x10,
-       0x911d, 0xe0,
-       0x911e, 0xe4,
-       0x911f, 0xef,
-       0x9120, 0xf0,
-       0x9121, 0xa3,
-       0x9122, 0xe0,
-       0x9123, 0x74,
-       0x9124, 0xff,
-       0x9125, 0xf0,
-       0x9126, 0x90,
-       0x9127, 0xd2,
-       0x9128, 0x12,
-       0x9129, 0x02,
-       0x912a, 0x2a,
-       0x912b, 0x48,
-       0xc900, 0x01,
-       0x0000, 0x00,
-};
-
-static const u16 vs6624_p2[] = {
-       0x806f, 0x01,
-       0x058c, 0x01,
-       0x0000, 0x00,
-};
-
-static const u16 vs6624_run_setup[] = {
-       0x1d18, 0x00,                           /* Enableconstrainedwhitebalance */
-       VS6624_PEAK_MIN_OUT_G_MSB, 0x3c,        /* Damper PeakGain Output MSB */
-       VS6624_PEAK_MIN_OUT_G_LSB, 0x66,        /* Damper PeakGain Output LSB */
-       VS6624_CM_LOW_THR_MSB, 0x65,            /* Damper Low MSB */
-       VS6624_CM_LOW_THR_LSB, 0xd1,            /* Damper Low LSB */
-       VS6624_CM_HIGH_THR_MSB, 0x66,           /* Damper High MSB */
-       VS6624_CM_HIGH_THR_LSB, 0x62,           /* Damper High LSB */
-       VS6624_CM_MIN_OUT_MSB, 0x00,            /* Damper Min output MSB */
-       VS6624_CM_MIN_OUT_LSB, 0x00,            /* Damper Min output LSB */
-       VS6624_NORA_DISABLE, 0x00,              /* Nora fDisable */
-       VS6624_NORA_USAGE, 0x04,                /* Nora usage */
-       VS6624_NORA_LOW_THR_MSB, 0x63,          /* Damper Low MSB Changed 0x63 to 0x65 */
-       VS6624_NORA_LOW_THR_LSB, 0xd1,          /* Damper Low LSB */
-       VS6624_NORA_HIGH_THR_MSB, 0x68,         /* Damper High MSB */
-       VS6624_NORA_HIGH_THR_LSB, 0xdd,         /* Damper High LSB */
-       VS6624_NORA_MIN_OUT_MSB, 0x3a,          /* Damper Min output MSB */
-       VS6624_NORA_MIN_OUT_LSB, 0x00,          /* Damper Min output LSB */
-       VS6624_F2B_DISABLE, 0x00,               /* Disable */
-       0x1d8a, 0x30,                           /* MAXWeightHigh */
-       0x1d91, 0x62,                           /* fpDamperLowThresholdHigh MSB */
-       0x1d92, 0x4a,                           /* fpDamperLowThresholdHigh LSB */
-       0x1d95, 0x65,                           /* fpDamperHighThresholdHigh MSB */
-       0x1d96, 0x0e,                           /* fpDamperHighThresholdHigh LSB */
-       0x1da1, 0x3a,                           /* fpMinimumDamperOutputLow MSB */
-       0x1da2, 0xb8,                           /* fpMinimumDamperOutputLow LSB */
-       0x1e08, 0x06,                           /* MAXWeightLow */
-       0x1e0a, 0x0a,                           /* MAXWeightHigh */
-       0x1601, 0x3a,                           /* Red A MSB */
-       0x1602, 0x14,                           /* Red A LSB */
-       0x1605, 0x3b,                           /* Blue A MSB */
-       0x1606, 0x85,                           /* BLue A LSB */
-       0x1609, 0x3b,                           /* RED B MSB */
-       0x160a, 0x85,                           /* RED B LSB */
-       0x160d, 0x3a,                           /* Blue B MSB */
-       0x160e, 0x14,                           /* Blue B LSB */
-       0x1611, 0x30,                           /* Max Distance from Locus MSB */
-       0x1612, 0x8f,                           /* Max Distance from Locus MSB */
-       0x1614, 0x01,                           /* Enable constrainer */
-       0x0000, 0x00,
-};
-
-static const u16 vs6624_default[] = {
-       VS6624_CONTRAST0, 0x84,
-       VS6624_SATURATION0, 0x75,
-       VS6624_GAMMA0, 0x11,
-       VS6624_CONTRAST1, 0x84,
-       VS6624_SATURATION1, 0x75,
-       VS6624_GAMMA1, 0x11,
-       VS6624_MAN_RG, 0x80,
-       VS6624_MAN_GG, 0x80,
-       VS6624_MAN_BG, 0x80,
-       VS6624_WB_MODE, 0x1,
-       VS6624_EXPO_COMPENSATION, 0xfe,
-       VS6624_EXPO_METER, 0x0,
-       VS6624_LIGHT_FREQ, 0x64,
-       VS6624_PEAK_GAIN, 0xe,
-       VS6624_PEAK_LOW_THR, 0x28,
-       VS6624_HMIRROR0, 0x0,
-       VS6624_VFLIP0, 0x0,
-       VS6624_ZOOM_HSTEP0_MSB, 0x0,
-       VS6624_ZOOM_HSTEP0_LSB, 0x1,
-       VS6624_ZOOM_VSTEP0_MSB, 0x0,
-       VS6624_ZOOM_VSTEP0_LSB, 0x1,
-       VS6624_PAN_HSTEP0_MSB, 0x0,
-       VS6624_PAN_HSTEP0_LSB, 0xf,
-       VS6624_PAN_VSTEP0_MSB, 0x0,
-       VS6624_PAN_VSTEP0_LSB, 0xf,
-       VS6624_SENSOR_MODE, 0x1,
-       VS6624_SYNC_CODE_SETUP, 0x21,
-       VS6624_DISABLE_FR_DAMPER, 0x0,
-       VS6624_FR_DEN, 0x1,
-       VS6624_FR_NUM_LSB, 0xf,
-       VS6624_INIT_PIPE_SETUP, 0x0,
-       VS6624_IMG_FMT0, 0x0,
-       VS6624_YUV_SETUP, 0x1,
-       VS6624_IMAGE_SIZE0, 0x2,
-       0x0000, 0x00,
-};
-
-static inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct vs6624, sd);
-}
-static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
-{
-       return &container_of(ctrl->handler, struct vs6624, hdl)->sd;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vs6624_read(struct v4l2_subdev *sd, u16 index)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       u8 buf[2];
-
-       buf[0] = index >> 8;
-       buf[1] = index;
-       i2c_master_send(client, buf, 2);
-       i2c_master_recv(client, buf, 1);
-
-       return buf[0];
-}
-#endif
-
-static int vs6624_write(struct v4l2_subdev *sd, u16 index,
-                               u8 value)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       u8 buf[3];
-
-       buf[0] = index >> 8;
-       buf[1] = index;
-       buf[2] = value;
-
-       return i2c_master_send(client, buf, 3);
-}
-
-static int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs)
-{
-       u16 reg;
-       u8 data;
-
-       while (*regs != 0x00) {
-               reg = *regs++;
-               data = *regs++;
-
-               vs6624_write(sd, reg, data);
-       }
-       return 0;
-}
-
-static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct v4l2_subdev *sd = to_sd(ctrl);
-
-       switch (ctrl->id) {
-       case V4L2_CID_CONTRAST:
-               vs6624_write(sd, VS6624_CONTRAST0, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               vs6624_write(sd, VS6624_SATURATION0, ctrl->val);
-               break;
-       case V4L2_CID_HFLIP:
-               vs6624_write(sd, VS6624_HMIRROR0, ctrl->val);
-               break;
-       case V4L2_CID_VFLIP:
-               vs6624_write(sd, VS6624_VFLIP0, ctrl->val);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int vs6624_enum_mbus_code(struct v4l2_subdev *sd,
-               struct v4l2_subdev_state *sd_state,
-               struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (code->pad || code->index >= ARRAY_SIZE(vs6624_formats))
-               return -EINVAL;
-
-       code->code = vs6624_formats[code->index].mbus_code;
-       return 0;
-}
-
-static int vs6624_set_fmt(struct v4l2_subdev *sd,
-               struct v4l2_subdev_state *sd_state,
-               struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *fmt = &format->format;
-       struct vs6624 *sensor = to_vs6624(sd);
-       int index;
-
-       if (format->pad)
-               return -EINVAL;
-
-       for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++)
-               if (vs6624_formats[index].mbus_code == fmt->code)
-                       break;
-       if (index >= ARRAY_SIZE(vs6624_formats)) {
-               /* default to first format */
-               index = 0;
-               fmt->code = vs6624_formats[0].mbus_code;
-       }
-
-       /* sensor mode is VGA */
-       if (fmt->width > VGA_WIDTH)
-               fmt->width = VGA_WIDTH;
-       if (fmt->height > VGA_HEIGHT)
-               fmt->height = VGA_HEIGHT;
-       fmt->width = fmt->width & (~3);
-       fmt->height = fmt->height & (~3);
-       fmt->field = V4L2_FIELD_NONE;
-       fmt->colorspace = vs6624_formats[index].colorspace;
-
-       if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
-               sd_state->pads->try_fmt = *fmt;
-               return 0;
-       }
-
-       /* set image format */
-       switch (fmt->code) {
-       case MEDIA_BUS_FMT_UYVY8_2X8:
-               vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
-               vs6624_write(sd, VS6624_YUV_SETUP, 0x1);
-               break;
-       case MEDIA_BUS_FMT_YUYV8_2X8:
-               vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
-               vs6624_write(sd, VS6624_YUV_SETUP, 0x3);
-               break;
-       case MEDIA_BUS_FMT_RGB565_2X8_LE:
-               vs6624_write(sd, VS6624_IMG_FMT0, 0x4);
-               vs6624_write(sd, VS6624_RGB_SETUP, 0x0);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* set image size */
-       if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT))
-               vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2);
-       else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT))
-               vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4);
-       else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT))
-               vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6);
-       else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT))
-               vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3);
-       else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT))
-               vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5);
-       else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT))
-               vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7);
-       else {
-               vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8);
-               vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8);
-               vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF);
-               vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8);
-               vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF);
-               vs6624_write(sd, VS6624_CROP_CTRL0, 0x1);
-       }
-
-       sensor->fmt = *fmt;
-
-       return 0;
-}
-
-static int vs6624_get_fmt(struct v4l2_subdev *sd,
-               struct v4l2_subdev_state *sd_state,
-               struct v4l2_subdev_format *format)
-{
-       struct vs6624 *sensor = to_vs6624(sd);
-
-       if (format->pad)
-               return -EINVAL;
-
-       format->format = sensor->fmt;
-       return 0;
-}
-
-static int vs6624_g_frame_interval(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_frame_interval *ival)
-{
-       struct vs6624 *sensor = to_vs6624(sd);
-
-       ival->interval.numerator = sensor->frame_rate.denominator;
-       ival->interval.denominator = sensor->frame_rate.numerator;
-       return 0;
-}
-
-static int vs6624_s_frame_interval(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_frame_interval *ival)
-{
-       struct vs6624 *sensor = to_vs6624(sd);
-       struct v4l2_fract *tpf = &ival->interval;
-
-
-       if (tpf->numerator == 0 || tpf->denominator == 0
-               || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) {
-               /* reset to max frame rate */
-               tpf->numerator = 1;
-               tpf->denominator = MAX_FRAME_RATE;
-       }
-       sensor->frame_rate.numerator = tpf->denominator;
-       sensor->frame_rate.denominator = tpf->numerator;
-       vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
-       vs6624_write(sd, VS6624_FR_NUM_MSB,
-                       sensor->frame_rate.numerator >> 8);
-       vs6624_write(sd, VS6624_FR_NUM_LSB,
-                       sensor->frame_rate.numerator & 0xFF);
-       vs6624_write(sd, VS6624_FR_DEN,
-                       sensor->frame_rate.denominator & 0xFF);
-       return 0;
-}
-
-static int vs6624_s_stream(struct v4l2_subdev *sd, int enable)
-{
-       if (enable)
-               vs6624_write(sd, VS6624_USER_CMD, 0x2);
-       else
-               vs6624_write(sd, VS6624_USER_CMD, 0x4);
-       udelay(100);
-       return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
-{
-       reg->val = vs6624_read(sd, reg->reg & 0xffff);
-       reg->size = 1;
-       return 0;
-}
-
-static int vs6624_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
-{
-       vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff);
-       return 0;
-}
-#endif
-
-static const struct v4l2_ctrl_ops vs6624_ctrl_ops = {
-       .s_ctrl = vs6624_s_ctrl,
-};
-
-static const struct v4l2_subdev_core_ops vs6624_core_ops = {
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .g_register = vs6624_g_register,
-       .s_register = vs6624_s_register,
-#endif
-};
-
-static const struct v4l2_subdev_video_ops vs6624_video_ops = {
-       .s_frame_interval = vs6624_s_frame_interval,
-       .g_frame_interval = vs6624_g_frame_interval,
-       .s_stream = vs6624_s_stream,
-};
-
-static const struct v4l2_subdev_pad_ops vs6624_pad_ops = {
-       .enum_mbus_code = vs6624_enum_mbus_code,
-       .get_fmt = vs6624_get_fmt,
-       .set_fmt = vs6624_set_fmt,
-};
-
-static const struct v4l2_subdev_ops vs6624_ops = {
-       .core = &vs6624_core_ops,
-       .video = &vs6624_video_ops,
-       .pad = &vs6624_pad_ops,
-};
-
-static int vs6624_probe(struct i2c_client *client)
-{
-       struct vs6624 *sensor;
-       struct v4l2_subdev *sd;
-       struct v4l2_ctrl_handler *hdl;
-       const unsigned *ce;
-       int ret;
-
-       /* Check if the adapter supports the needed features */
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
-               return -EIO;
-
-       ce = client->dev.platform_data;
-       if (ce == NULL)
-               return -EINVAL;
-
-       ret = devm_gpio_request_one(&client->dev, *ce, GPIOF_OUT_INIT_HIGH,
-                                   "VS6624 Chip Enable");
-       if (ret) {
-               v4l_err(client, "failed to request GPIO %d\n", *ce);
-               return ret;
-       }
-       /* wait 100ms before any further i2c writes are performed */
-       msleep(100);
-
-       sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
-       if (sensor == NULL)
-               return -ENOMEM;
-
-       sd = &sensor->sd;
-       v4l2_i2c_subdev_init(sd, client, &vs6624_ops);
-
-       vs6624_writeregs(sd, vs6624_p1);
-       vs6624_write(sd, VS6624_MICRO_EN, 0x2);
-       vs6624_write(sd, VS6624_DIO_EN, 0x1);
-       usleep_range(10000, 11000);
-       vs6624_writeregs(sd, vs6624_p2);
-
-       vs6624_writeregs(sd, vs6624_default);
-       vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF);
-       vs6624_writeregs(sd, vs6624_run_setup);
-
-       /* set frame rate */
-       sensor->frame_rate.numerator = MAX_FRAME_RATE;
-       sensor->frame_rate.denominator = 1;
-       vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
-       vs6624_write(sd, VS6624_FR_NUM_MSB,
-                       sensor->frame_rate.numerator >> 8);
-       vs6624_write(sd, VS6624_FR_NUM_LSB,
-                       sensor->frame_rate.numerator & 0xFF);
-       vs6624_write(sd, VS6624_FR_DEN,
-                       sensor->frame_rate.denominator & 0xFF);
-
-       sensor->fmt = vs6624_default_fmt;
-       sensor->ce_pin = *ce;
-
-       v4l_info(client, "chip found @ 0x%02x (%s)\n",
-                       client->addr << 1, client->adapter->name);
-
-       hdl = &sensor->hdl;
-       v4l2_ctrl_handler_init(hdl, 4);
-       v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87);
-       v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78);
-       v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
-                       V4L2_CID_HFLIP, 0, 1, 1, 0);
-       v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
-                       V4L2_CID_VFLIP, 0, 1, 1, 0);
-       /* hook the control handler into the driver */
-       sd->ctrl_handler = hdl;
-       if (hdl->error) {
-               int err = hdl->error;
-
-               v4l2_ctrl_handler_free(hdl);
-               return err;
-       }
-
-       /* initialize the hardware to the default control values */
-       ret = v4l2_ctrl_handler_setup(hdl);
-       if (ret)
-               v4l2_ctrl_handler_free(hdl);
-       return ret;
-}
-
-static void vs6624_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-       v4l2_device_unregister_subdev(sd);
-       v4l2_ctrl_handler_free(sd->ctrl_handler);
-}
-
-static const struct i2c_device_id vs6624_id[] = {
-       {"vs6624", 0},
-       {},
-};
-
-MODULE_DEVICE_TABLE(i2c, vs6624_id);
-
-static struct i2c_driver vs6624_driver = {
-       .driver = {
-               .name   = "vs6624",
-       },
-       .probe_new      = vs6624_probe,
-       .remove         = vs6624_remove,
-       .id_table       = vs6624_id,
-};
-
-module_i2c_driver(vs6624_driver);
-
-MODULE_DESCRIPTION("VS6624 sensor driver");
-MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/vs6624_regs.h b/drivers/media/i2c/vs6624_regs.h
deleted file mode 100644 (file)
index 76c9ed0..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vs6624 - ST VS6624 CMOS image sensor registers
- *
- * Copyright (c) 2011 Analog Devices Inc.
- */
-
-#ifndef _VS6624_REGS_H_
-#define _VS6624_REGS_H_
-
-/* low level control registers */
-#define VS6624_MICRO_EN               0xC003 /* power enable for all MCU clock */
-#define VS6624_DIO_EN                 0xC044 /* enable digital I/O */
-/* device parameters */
-#define VS6624_DEV_ID_MSB             0x0001 /* device id MSB */
-#define VS6624_DEV_ID_LSB             0x0002 /* device id LSB */
-#define VS6624_FW_VSN_MAJOR           0x0004 /* firmware version major */
-#define VS6624_FW_VSN_MINOR           0x0006 /* firmware version minor */
-#define VS6624_PATCH_VSN_MAJOR        0x0008 /* patch version major */
-#define VS6624_PATCH_VSN_MINOR        0x000A /* patch version minor */
-/* host interface manager control */
-#define VS6624_USER_CMD               0x0180 /* user level control of operating states */
-/* host interface manager status */
-#define VS6624_STATE                  0x0202 /* current state of the mode manager */
-/* run mode control */
-#define VS6624_METER_ON               0x0280 /* if false AE and AWB are disabled */
-/* mode setup */
-#define VS6624_ACTIVE_PIPE_SETUP      0x0302 /* select the active bank for non view live mode */
-#define VS6624_SENSOR_MODE            0x0308 /* select the different sensor mode */
-/* pipe setup bank0 */
-#define VS6624_IMAGE_SIZE0            0x0380 /* required output dimension */
-#define VS6624_MAN_HSIZE0_MSB         0x0383 /* input required manual H size MSB */
-#define VS6624_MAN_HSIZE0_LSB         0x0384 /* input required manual H size LSB */
-#define VS6624_MAN_VSIZE0_MSB         0x0387 /* input required manual V size MSB */
-#define VS6624_MAN_VSIZE0_LSB         0x0388 /* input required manual V size LSB */
-#define VS6624_ZOOM_HSTEP0_MSB        0x038B /* set the zoom H step MSB */
-#define VS6624_ZOOM_HSTEP0_LSB        0x038C /* set the zoom H step LSB */
-#define VS6624_ZOOM_VSTEP0_MSB        0x038F /* set the zoom V step MSB */
-#define VS6624_ZOOM_VSTEP0_LSB        0x0390 /* set the zoom V step LSB */
-#define VS6624_ZOOM_CTRL0             0x0392 /* control zoon in, out and stop */
-#define VS6624_PAN_HSTEP0_MSB         0x0395 /* set the pan H step MSB */
-#define VS6624_PAN_HSTEP0_LSB         0x0396 /* set the pan H step LSB */
-#define VS6624_PAN_VSTEP0_MSB         0x0399 /* set the pan V step MSB */
-#define VS6624_PAN_VSTEP0_LSB         0x039A /* set the pan V step LSB */
-#define VS6624_PAN_CTRL0              0x039C /* control pan operation */
-#define VS6624_CROP_CTRL0             0x039E /* select cropping mode */
-#define VS6624_CROP_HSTART0_MSB       0x03A1 /* set the cropping H start address MSB */
-#define VS6624_CROP_HSTART0_LSB       0x03A2 /* set the cropping H start address LSB */
-#define VS6624_CROP_HSIZE0_MSB        0x03A5 /* set the cropping H size MSB */
-#define VS6624_CROP_HSIZE0_LSB        0x03A6 /* set the cropping H size LSB */
-#define VS6624_CROP_VSTART0_MSB       0x03A9 /* set the cropping V start address MSB */
-#define VS6624_CROP_VSTART0_LSB       0x03AA /* set the cropping V start address LSB */
-#define VS6624_CROP_VSIZE0_MSB        0x03AD /* set the cropping V size MSB */
-#define VS6624_CROP_VSIZE0_LSB        0x03AE /* set the cropping V size LSB */
-#define VS6624_IMG_FMT0               0x03B0 /* select required output image format */
-#define VS6624_BAYER_OUT_ALIGN0       0x03B2 /* set bayer output alignment */
-#define VS6624_CONTRAST0              0x03B4 /* contrast control for output */
-#define VS6624_SATURATION0            0x03B6 /* saturation control for output */
-#define VS6624_GAMMA0                 0x03B8 /* gamma settings */
-#define VS6624_HMIRROR0               0x03BA /* horizontal image orientation flip */
-#define VS6624_VFLIP0                 0x03BC /* vertical image orientation flip */
-#define VS6624_CHANNEL_ID0            0x03BE /* logical DMA channel number */
-/* pipe setup bank1 */
-#define VS6624_IMAGE_SIZE1            0x0400 /* required output dimension */
-#define VS6624_MAN_HSIZE1_MSB         0x0403 /* input required manual H size MSB */
-#define VS6624_MAN_HSIZE1_LSB         0x0404 /* input required manual H size LSB */
-#define VS6624_MAN_VSIZE1_MSB         0x0407 /* input required manual V size MSB */
-#define VS6624_MAN_VSIZE1_LSB         0x0408 /* input required manual V size LSB */
-#define VS6624_ZOOM_HSTEP1_MSB        0x040B /* set the zoom H step MSB */
-#define VS6624_ZOOM_HSTEP1_LSB        0x040C /* set the zoom H step LSB */
-#define VS6624_ZOOM_VSTEP1_MSB        0x040F /* set the zoom V step MSB */
-#define VS6624_ZOOM_VSTEP1_LSB        0x0410 /* set the zoom V step LSB */
-#define VS6624_ZOOM_CTRL1             0x0412 /* control zoon in, out and stop */
-#define VS6624_PAN_HSTEP1_MSB         0x0415 /* set the pan H step MSB */
-#define VS6624_PAN_HSTEP1_LSB         0x0416 /* set the pan H step LSB */
-#define VS6624_PAN_VSTEP1_MSB         0x0419 /* set the pan V step MSB */
-#define VS6624_PAN_VSTEP1_LSB         0x041A /* set the pan V step LSB */
-#define VS6624_PAN_CTRL1              0x041C /* control pan operation */
-#define VS6624_CROP_CTRL1             0x041E /* select cropping mode */
-#define VS6624_CROP_HSTART1_MSB       0x0421 /* set the cropping H start address MSB */
-#define VS6624_CROP_HSTART1_LSB       0x0422 /* set the cropping H start address LSB */
-#define VS6624_CROP_HSIZE1_MSB        0x0425 /* set the cropping H size MSB */
-#define VS6624_CROP_HSIZE1_LSB        0x0426 /* set the cropping H size LSB */
-#define VS6624_CROP_VSTART1_MSB       0x0429 /* set the cropping V start address MSB */
-#define VS6624_CROP_VSTART1_LSB       0x042A /* set the cropping V start address LSB */
-#define VS6624_CROP_VSIZE1_MSB        0x042D /* set the cropping V size MSB */
-#define VS6624_CROP_VSIZE1_LSB        0x042E /* set the cropping V size LSB */
-#define VS6624_IMG_FMT1               0x0430 /* select required output image format */
-#define VS6624_BAYER_OUT_ALIGN1       0x0432 /* set bayer output alignment */
-#define VS6624_CONTRAST1              0x0434 /* contrast control for output */
-#define VS6624_SATURATION1            0x0436 /* saturation control for output */
-#define VS6624_GAMMA1                 0x0438 /* gamma settings */
-#define VS6624_HMIRROR1               0x043A /* horizontal image orientation flip */
-#define VS6624_VFLIP1                 0x043C /* vertical image orientation flip */
-#define VS6624_CHANNEL_ID1            0x043E /* logical DMA channel number */
-/* view live control */
-#define VS6624_VIEW_LIVE_EN           0x0480 /* enable view live mode */
-#define VS6624_INIT_PIPE_SETUP        0x0482 /* select initial pipe setup bank */
-/* view live status */
-#define VS6624_CUR_PIPE_SETUP         0x0500 /* indicates most recently applied setup bank */
-/* power management */
-#define VS6624_TIME_TO_POWER_DOWN     0x0580 /* automatically transition time to stop mode */
-/* video timing parameter host inputs */
-#define VS6624_EXT_CLK_FREQ_NUM_MSB   0x0605 /* external clock frequency numerator MSB */
-#define VS6624_EXT_CLK_FREQ_NUM_LSB   0x0606 /* external clock frequency numerator LSB */
-#define VS6624_EXT_CLK_FREQ_DEN       0x0608 /* external clock frequency denominator */
-/* video timing control */
-#define VS6624_SYS_CLK_MODE           0x0880 /* decides system clock frequency */
-/* frame dimension parameter host inputs */
-#define VS6624_LIGHT_FREQ             0x0C80 /* AC frequency used for flicker free time */
-#define VS6624_FLICKER_COMPAT         0x0C82 /* flicker compatible frame length */
-/* static frame rate control */
-#define VS6624_FR_NUM_MSB             0x0D81 /* desired frame rate numerator MSB */
-#define VS6624_FR_NUM_LSB             0x0D82 /* desired frame rate numerator LSB */
-#define VS6624_FR_DEN                 0x0D84 /* desired frame rate denominator */
-/* automatic frame rate control */
-#define VS6624_DISABLE_FR_DAMPER      0x0E80 /* defines frame rate mode */
-#define VS6624_MIN_DAMPER_OUT_MSB     0x0E8C /* minimum frame rate MSB */
-#define VS6624_MIN_DAMPER_OUT_LSB     0x0E8A /* minimum frame rate LSB */
-/* exposure controls */
-#define VS6624_EXPO_MODE              0x1180 /* exposure mode */
-#define VS6624_EXPO_METER             0x1182 /* weights to be associated with the zones */
-#define VS6624_EXPO_TIME_NUM          0x1184 /* exposure time numerator */
-#define VS6624_EXPO_TIME_DEN          0x1186 /* exposure time denominator */
-#define VS6624_EXPO_TIME_MSB          0x1189 /* exposure time for the Manual Mode MSB */
-#define VS6624_EXPO_TIME_LSB          0x118A /* exposure time for the Manual Mode LSB */
-#define VS6624_EXPO_COMPENSATION      0x1190 /* exposure compensation */
-#define VS6624_DIRECT_COARSE_MSB      0x1195 /* coarse integration lines for Direct Mode MSB */
-#define VS6624_DIRECT_COARSE_LSB      0x1196 /* coarse integration lines for Direct Mode LSB */
-#define VS6624_DIRECT_FINE_MSB        0x1199 /* fine integration pixels for Direct Mode MSB */
-#define VS6624_DIRECT_FINE_LSB        0x119A /* fine integration pixels for Direct Mode LSB */
-#define VS6624_DIRECT_ANAL_GAIN_MSB   0x119D /* analog gain for Direct Mode MSB */
-#define VS6624_DIRECT_ANAL_GAIN_LSB   0x119E /* analog gain for Direct Mode LSB */
-#define VS6624_DIRECT_DIGI_GAIN_MSB   0x11A1 /* digital gain for Direct Mode MSB */
-#define VS6624_DIRECT_DIGI_GAIN_LSB   0x11A2 /* digital gain for Direct Mode LSB */
-#define VS6624_FLASH_COARSE_MSB       0x11A5 /* coarse integration lines for Flash Gun Mode MSB */
-#define VS6624_FLASH_COARSE_LSB       0x11A6 /* coarse integration lines for Flash Gun Mode LSB */
-#define VS6624_FLASH_FINE_MSB         0x11A9 /* fine integration pixels for Flash Gun Mode MSB */
-#define VS6624_FLASH_FINE_LSB         0x11AA /* fine integration pixels for Flash Gun Mode LSB */
-#define VS6624_FLASH_ANAL_GAIN_MSB    0x11AD /* analog gain for Flash Gun Mode MSB */
-#define VS6624_FLASH_ANAL_GAIN_LSB    0x11AE /* analog gain for Flash Gun Mode LSB */
-#define VS6624_FLASH_DIGI_GAIN_MSB    0x11B1 /* digital gain for Flash Gun Mode MSB */
-#define VS6624_FLASH_DIGI_GAIN_LSB    0x11B2 /* digital gain for Flash Gun Mode LSB */
-#define VS6624_FREEZE_AE              0x11B4 /* freeze auto exposure */
-#define VS6624_MAX_INT_TIME_MSB       0x11B7 /* user maximum integration time MSB */
-#define VS6624_MAX_INT_TIME_LSB       0x11B8 /* user maximum integration time LSB */
-#define VS6624_FLASH_AG_THR_MSB       0x11BB /* recommend flash gun analog gain threshold MSB */
-#define VS6624_FLASH_AG_THR_LSB       0x11BC /* recommend flash gun analog gain threshold LSB */
-#define VS6624_ANTI_FLICKER_MODE      0x11C0 /* anti flicker mode */
-/* white balance control */
-#define VS6624_WB_MODE                0x1480 /* set white balance mode */
-#define VS6624_MAN_RG                 0x1482 /* user setting for red channel gain */
-#define VS6624_MAN_GG                 0x1484 /* user setting for green channel gain */
-#define VS6624_MAN_BG                 0x1486 /* user setting for blue channel gain */
-#define VS6624_FLASH_RG_MSB           0x148B /* red gain for Flash Gun MSB */
-#define VS6624_FLASH_RG_LSB           0x148C /* red gain for Flash Gun LSB */
-#define VS6624_FLASH_GG_MSB           0x148F /* green gain for Flash Gun MSB */
-#define VS6624_FLASH_GG_LSB           0x1490 /* green gain for Flash Gun LSB */
-#define VS6624_FLASH_BG_MSB           0x1493 /* blue gain for Flash Gun MSB */
-#define VS6624_FLASH_BG_LSB           0x1494 /* blue gain for Flash Gun LSB */
-/* sensor setup */
-#define VS6624_BC_OFFSET              0x1990 /* Black Correction Offset */
-/* image stability */
-#define VS6624_STABLE_WB              0x1900 /* white balance stable */
-#define VS6624_STABLE_EXPO            0x1902 /* exposure stable */
-#define VS6624_STABLE                 0x1906 /* system stable */
-/* flash control */
-#define VS6624_FLASH_MODE             0x1A80 /* flash mode */
-#define VS6624_FLASH_OFF_LINE_MSB     0x1A83 /* off line at flash pulse mode MSB */
-#define VS6624_FLASH_OFF_LINE_LSB     0x1A84 /* off line at flash pulse mode LSB */
-/* flash status */
-#define VS6624_FLASH_RECOM            0x1B00 /* flash gun is recommended */
-#define VS6624_FLASH_GRAB_COMPLETE    0x1B02 /* flash gun image has been grabbed */
-/* scythe filter controls */
-#define VS6624_SCYTHE_FILTER          0x1D80 /* disable scythe defect correction */
-/* jack filter controls */
-#define VS6624_JACK_FILTER            0x1E00 /* disable jack defect correction */
-/* demosaic control */
-#define VS6624_ANTI_ALIAS_FILTER      0x1E80 /* anti alias filter suppress */
-/* color matrix dampers */
-#define VS6624_CM_DISABLE             0x1F00 /* disable color matrix damper */
-#define VS6624_CM_LOW_THR_MSB         0x1F03 /* low threshold for exposure MSB */
-#define VS6624_CM_LOW_THR_LSB         0x1F04 /* low threshold for exposure LSB */
-#define VS6624_CM_HIGH_THR_MSB        0x1F07 /* high threshold for exposure MSB */
-#define VS6624_CM_HIGH_THR_LSB        0x1F08 /* high threshold for exposure LSB */
-#define VS6624_CM_MIN_OUT_MSB         0x1F0B /* minimum possible damper output MSB */
-#define VS6624_CM_MIN_OUT_LSB         0x1F0C /* minimum possible damper output LSB */
-/* peaking control */
-#define VS6624_PEAK_GAIN              0x2000 /* controls peaking gain */
-#define VS6624_PEAK_G_DISABLE         0x2002 /* disable peak gain damping */
-#define VS6624_PEAK_LOW_THR_G_MSB     0x2005 /* low threshold for exposure for gain MSB */
-#define VS6624_PEAK_LOW_THR_G_LSB     0x2006 /* low threshold for exposure for gain LSB */
-#define VS6624_PEAK_HIGH_THR_G_MSB    0x2009 /* high threshold for exposure for gain MSB */
-#define VS6624_PEAK_HIGH_THR_G_LSB    0x200A /* high threshold for exposure for gain LSB */
-#define VS6624_PEAK_MIN_OUT_G_MSB     0x200D /* minimum damper output for gain MSB */
-#define VS6624_PEAK_MIN_OUT_G_LSB     0x200E /* minimum damper output for gain LSB */
-#define VS6624_PEAK_LOW_THR           0x2010 /* adjust degree of coring */
-#define VS6624_PEAK_C_DISABLE         0x2012 /* disable coring damping */
-#define VS6624_PEAK_HIGH_THR          0x2014 /* adjust maximum gain */
-#define VS6624_PEAK_LOW_THR_C_MSB     0x2017 /* low threshold for exposure for coring MSB */
-#define VS6624_PEAK_LOW_THR_C_LSB     0x2018 /* low threshold for exposure for coring LSB */
-#define VS6624_PEAK_HIGH_THR_C_MSB    0x201B /* high threshold for exposure for coring MSB */
-#define VS6624_PEAK_HIGH_THR_C_LSB    0x201C /* high threshold for exposure for coring LSB */
-#define VS6624_PEAK_MIN_OUT_C_MSB     0x201F /* minimum damper output for coring MSB */
-#define VS6624_PEAK_MIN_OUT_C_LSB     0x2020 /* minimum damper output for coring LSB */
-/* pipe 0 RGB to YUV matrix manual control */
-#define VS6624_RYM0_MAN_CTRL          0x2180 /* enable manual RGB to YUV matrix */
-#define VS6624_RYM0_W00_MSB           0x2183 /* row 0 column 0 of YUV matrix MSB */
-#define VS6624_RYM0_W00_LSB           0x2184 /* row 0 column 0 of YUV matrix LSB */
-#define VS6624_RYM0_W01_MSB           0x2187 /* row 0 column 1 of YUV matrix MSB */
-#define VS6624_RYM0_W01_LSB           0x2188 /* row 0 column 1 of YUV matrix LSB */
-#define VS6624_RYM0_W02_MSB           0x218C /* row 0 column 2 of YUV matrix MSB */
-#define VS6624_RYM0_W02_LSB           0x218D /* row 0 column 2 of YUV matrix LSB */
-#define VS6624_RYM0_W10_MSB           0x2190 /* row 1 column 0 of YUV matrix MSB */
-#define VS6624_RYM0_W10_LSB           0x218F /* row 1 column 0 of YUV matrix LSB */
-#define VS6624_RYM0_W11_MSB           0x2193 /* row 1 column 1 of YUV matrix MSB */
-#define VS6624_RYM0_W11_LSB           0x2194 /* row 1 column 1 of YUV matrix LSB */
-#define VS6624_RYM0_W12_MSB           0x2197 /* row 1 column 2 of YUV matrix MSB */
-#define VS6624_RYM0_W12_LSB           0x2198 /* row 1 column 2 of YUV matrix LSB */
-#define VS6624_RYM0_W20_MSB           0x219B /* row 2 column 0 of YUV matrix MSB */
-#define VS6624_RYM0_W20_LSB           0x219C /* row 2 column 0 of YUV matrix LSB */
-#define VS6624_RYM0_W21_MSB           0x21A0 /* row 2 column 1 of YUV matrix MSB */
-#define VS6624_RYM0_W21_LSB           0x219F /* row 2 column 1 of YUV matrix LSB */
-#define VS6624_RYM0_W22_MSB           0x21A3 /* row 2 column 2 of YUV matrix MSB */
-#define VS6624_RYM0_W22_LSB           0x21A4 /* row 2 column 2 of YUV matrix LSB */
-#define VS6624_RYM0_YINY_MSB          0x21A7 /* Y in Y MSB */
-#define VS6624_RYM0_YINY_LSB          0x21A8 /* Y in Y LSB */
-#define VS6624_RYM0_YINCB_MSB         0x21AB /* Y in Cb MSB */
-#define VS6624_RYM0_YINCB_LSB         0x21AC /* Y in Cb LSB */
-#define VS6624_RYM0_YINCR_MSB         0x21B0 /* Y in Cr MSB */
-#define VS6624_RYM0_YINCR_LSB         0x21AF /* Y in Cr LSB */
-/* pipe 1 RGB to YUV matrix manual control */
-#define VS6624_RYM1_MAN_CTRL          0x2200 /* enable manual RGB to YUV matrix */
-#define VS6624_RYM1_W00_MSB           0x2203 /* row 0 column 0 of YUV matrix MSB */
-#define VS6624_RYM1_W00_LSB           0x2204 /* row 0 column 0 of YUV matrix LSB */
-#define VS6624_RYM1_W01_MSB           0x2207 /* row 0 column 1 of YUV matrix MSB */
-#define VS6624_RYM1_W01_LSB           0x2208 /* row 0 column 1 of YUV matrix LSB */
-#define VS6624_RYM1_W02_MSB           0x220C /* row 0 column 2 of YUV matrix MSB */
-#define VS6624_RYM1_W02_LSB           0x220D /* row 0 column 2 of YUV matrix LSB */
-#define VS6624_RYM1_W10_MSB           0x2210 /* row 1 column 0 of YUV matrix MSB */
-#define VS6624_RYM1_W10_LSB           0x220F /* row 1 column 0 of YUV matrix LSB */
-#define VS6624_RYM1_W11_MSB           0x2213 /* row 1 column 1 of YUV matrix MSB */
-#define VS6624_RYM1_W11_LSB           0x2214 /* row 1 column 1 of YUV matrix LSB */
-#define VS6624_RYM1_W12_MSB           0x2217 /* row 1 column 2 of YUV matrix MSB */
-#define VS6624_RYM1_W12_LSB           0x2218 /* row 1 column 2 of YUV matrix LSB */
-#define VS6624_RYM1_W20_MSB           0x221B /* row 2 column 0 of YUV matrix MSB */
-#define VS6624_RYM1_W20_LSB           0x221C /* row 2 column 0 of YUV matrix LSB */
-#define VS6624_RYM1_W21_MSB           0x2220 /* row 2 column 1 of YUV matrix MSB */
-#define VS6624_RYM1_W21_LSB           0x221F /* row 2 column 1 of YUV matrix LSB */
-#define VS6624_RYM1_W22_MSB           0x2223 /* row 2 column 2 of YUV matrix MSB */
-#define VS6624_RYM1_W22_LSB           0x2224 /* row 2 column 2 of YUV matrix LSB */
-#define VS6624_RYM1_YINY_MSB          0x2227 /* Y in Y MSB */
-#define VS6624_RYM1_YINY_LSB          0x2228 /* Y in Y LSB */
-#define VS6624_RYM1_YINCB_MSB         0x222B /* Y in Cb MSB */
-#define VS6624_RYM1_YINCB_LSB         0x222C /* Y in Cb LSB */
-#define VS6624_RYM1_YINCR_MSB         0x2220 /* Y in Cr MSB */
-#define VS6624_RYM1_YINCR_LSB         0x222F /* Y in Cr LSB */
-/* pipe 0 gamma manual control */
-#define VS6624_GAMMA_MAN_CTRL0        0x2280 /* enable manual gamma setup */
-#define VS6624_GAMMA_PEAK_R0          0x2282 /* peaked red channel gamma value */
-#define VS6624_GAMMA_PEAK_G0          0x2284 /* peaked green channel gamma value */
-#define VS6624_GAMMA_PEAK_B0          0x2286 /* peaked blue channel gamma value */
-#define VS6624_GAMMA_UNPEAK_R0        0x2288 /* unpeaked red channel gamma value */
-#define VS6624_GAMMA_UNPEAK_G0        0x228A /* unpeaked green channel gamma value */
-#define VS6624_GAMMA_UNPEAK_B0        0x228C /* unpeaked blue channel gamma value */
-/* pipe 1 gamma manual control */
-#define VS6624_GAMMA_MAN_CTRL1        0x2300 /* enable manual gamma setup */
-#define VS6624_GAMMA_PEAK_R1          0x2302 /* peaked red channel gamma value */
-#define VS6624_GAMMA_PEAK_G1          0x2304 /* peaked green channel gamma value */
-#define VS6624_GAMMA_PEAK_B1          0x2306 /* peaked blue channel gamma value */
-#define VS6624_GAMMA_UNPEAK_R1        0x2308 /* unpeaked red channel gamma value */
-#define VS6624_GAMMA_UNPEAK_G1        0x230A /* unpeaked green channel gamma value */
-#define VS6624_GAMMA_UNPEAK_B1        0x230C /* unpeaked blue channel gamma value */
-/* fade to black */
-#define VS6624_F2B_DISABLE            0x2480 /* disable fade to black */
-#define VS6624_F2B_BLACK_VAL_MSB      0x2483 /* black value MSB */
-#define VS6624_F2B_BLACK_VAL_LSB      0x2484 /* black value LSB */
-#define VS6624_F2B_LOW_THR_MSB        0x2487 /* low threshold for exposure MSB */
-#define VS6624_F2B_LOW_THR_LSB        0x2488 /* low threshold for exposure LSB */
-#define VS6624_F2B_HIGH_THR_MSB       0x248B /* high threshold for exposure MSB */
-#define VS6624_F2B_HIGH_THR_LSB       0x248C /* high threshold for exposure LSB */
-#define VS6624_F2B_MIN_OUT_MSB        0x248F /* minimum damper output MSB */
-#define VS6624_F2B_MIN_OUT_LSB        0x2490 /* minimum damper output LSB */
-/* output formatter control */
-#define VS6624_CODE_CK_EN             0x2580 /* code check enable */
-#define VS6624_BLANK_FMT              0x2582 /* blank format */
-#define VS6624_SYNC_CODE_SETUP        0x2584 /* sync code setup */
-#define VS6624_HSYNC_SETUP            0x2586 /* H sync setup */
-#define VS6624_VSYNC_SETUP            0x2588 /* V sync setup */
-#define VS6624_PCLK_SETUP             0x258A /* PCLK setup */
-#define VS6624_PCLK_EN                0x258C /* PCLK enable */
-#define VS6624_OPF_SP_SETUP           0x258E /* output formatter sp setup */
-#define VS6624_BLANK_DATA_MSB         0x2590 /* blank data MSB */
-#define VS6624_BLANK_DATA_LSB         0x2592 /* blank data LSB */
-#define VS6624_RGB_SETUP              0x2594 /* RGB setup */
-#define VS6624_YUV_SETUP              0x2596 /* YUV setup */
-#define VS6624_VSYNC_RIS_COARSE_H     0x2598 /* V sync rising coarse high */
-#define VS6624_VSYNC_RIS_COARSE_L     0x259A /* V sync rising coarse low */
-#define VS6624_VSYNC_RIS_FINE_H       0x259C /* V sync rising fine high */
-#define VS6624_VSYNC_RIS_FINE_L       0x259E /* V sync rising fine low */
-#define VS6624_VSYNC_FALL_COARSE_H    0x25A0 /* V sync falling coarse high */
-#define VS6624_VSYNC_FALL_COARSE_L    0x25A2 /* V sync falling coarse low */
-#define VS6624_VSYNC_FALL_FINE_H      0x25A4 /* V sync falling fine high */
-#define VS6624_VSYNC_FALL_FINE_L      0x25A6 /* V sync falling fine low */
-#define VS6624_HSYNC_RIS_H            0x25A8 /* H sync rising high */
-#define VS6624_HSYNC_RIS_L            0x25AA /* H sync rising low */
-#define VS6624_HSYNC_FALL_H           0x25AC /* H sync falling high */
-#define VS6624_HSYNC_FALL_L           0x25AE /* H sync falling low */
-#define VS6624_OUT_IF                 0x25B0 /* output interface */
-#define VS6624_CCP_EXT_DATA           0x25B2 /* CCP extra data */
-/* NoRA controls */
-#define VS6624_NORA_DISABLE           0x2600 /* NoRA control mode */
-#define VS6624_NORA_USAGE             0x2602 /* usage */
-#define VS6624_NORA_SPLIT_KN          0x2604 /* split kn */
-#define VS6624_NORA_SPLIT_NI          0x2606 /* split ni */
-#define VS6624_NORA_TIGHT_G           0x2608 /* tight green */
-#define VS6624_NORA_DISABLE_NP        0x260A /* disable noro promoting */
-#define VS6624_NORA_LOW_THR_MSB       0x260D /* low threshold for exposure MSB */
-#define VS6624_NORA_LOW_THR_LSB       0x260E /* low threshold for exposure LSB */
-#define VS6624_NORA_HIGH_THR_MSB      0x2611 /* high threshold for exposure MSB */
-#define VS6624_NORA_HIGH_THR_LSB      0x2612 /* high threshold for exposure LSB */
-#define VS6624_NORA_MIN_OUT_MSB       0x2615 /* minimum damper output MSB */
-#define VS6624_NORA_MIN_OUT_LSB       0x2616 /* minimum damper output LSB */
-
-#endif
index 25020d58eb06e85bcd2bfe0afbea3665b3ee0de8..8cee956e38d42174dba763e469df6df796a40bdd 100644 (file)
@@ -756,13 +756,12 @@ int __must_check __media_device_register(struct media_device *mdev,
 }
 EXPORT_SYMBOL_GPL(__media_device_register);
 
-int __must_check media_device_register_entity_notify(struct media_device *mdev,
+void media_device_register_entity_notify(struct media_device *mdev,
                                        struct media_entity_notify *nptr)
 {
        mutex_lock(&mdev->graph_mutex);
        list_add_tail(&nptr->list, &mdev->entity_notify);
        mutex_unlock(&mdev->graph_mutex);
-       return 0;
 }
 EXPORT_SYMBOL_GPL(media_device_register_entity_notify);
 
index 927190281bd540c0355a178725d9d27ed619c291..2d674dc28cec16c793b439f8d03b069fcdb384e6 100644 (file)
@@ -15,7 +15,7 @@ config VIDEO_BT848
        select RADIO_ADAPTERS
        select RADIO_TEA575X
        help
-         Support for BT848 based frame grabber/overlay boards. This includes
+         Support for BT848 based frame grabber boards. This includes
          the Miro, Hauppauge and STB boards. Please read the material in
          <file:Documentation/admin-guide/media/bttv.rst> for more information.
 
index b3179038b900d098292847ce9106572c4ed65f69..0adbf8233e1a371242ee96cbe61eeb23a7df0bc5 100644 (file)
@@ -75,156 +75,3 @@ int btcx_riscmem_alloc(struct pci_dev *pci,
        }
        return 0;
 }
-
-/* ---------------------------------------------------------- */
-/* screen overlay helpers                                     */
-
-int
-btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
-                 struct v4l2_clip *clips, unsigned int n)
-{
-       if (win->left < 0) {
-               /* left */
-               clips[n].c.left = 0;
-               clips[n].c.top = 0;
-               clips[n].c.width  = -win->left;
-               clips[n].c.height = win->height;
-               n++;
-       }
-       if (win->left + win->width > swidth) {
-               /* right */
-               clips[n].c.left   = swidth - win->left;
-               clips[n].c.top    = 0;
-               clips[n].c.width  = win->width - clips[n].c.left;
-               clips[n].c.height = win->height;
-               n++;
-       }
-       if (win->top < 0) {
-               /* top */
-               clips[n].c.left = 0;
-               clips[n].c.top = 0;
-               clips[n].c.width  = win->width;
-               clips[n].c.height = -win->top;
-               n++;
-       }
-       if (win->top + win->height > sheight) {
-               /* bottom */
-               clips[n].c.left = 0;
-               clips[n].c.top = sheight - win->top;
-               clips[n].c.width  = win->width;
-               clips[n].c.height = win->height - clips[n].c.top;
-               n++;
-       }
-       return n;
-}
-
-int
-btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask)
-{
-       s32 nx,nw,dx;
-       unsigned int i;
-
-       /* fixup window */
-       nx = (win->left + mask) & ~mask;
-       nw = (win->width) & ~mask;
-       if (nx + nw > win->left + win->width)
-               nw -= mask+1;
-       dx = nx - win->left;
-       win->left  = nx;
-       win->width = nw;
-       dprintk("btcx: window align %dx%d+%d+%d [dx=%d]\n",
-              win->width, win->height, win->left, win->top, dx);
-
-       /* fixup clips */
-       for (i = 0; i < n; i++) {
-               nx = (clips[i].c.left-dx) & ~mask;
-               nw = (clips[i].c.width) & ~mask;
-               if (nx + nw < clips[i].c.left-dx + clips[i].c.width)
-                       nw += mask+1;
-               clips[i].c.left  = nx;
-               clips[i].c.width = nw;
-               dprintk("btcx:   clip align %dx%d+%d+%d\n",
-                      clips[i].c.width, clips[i].c.height,
-                      clips[i].c.left, clips[i].c.top);
-       }
-       return 0;
-}
-
-void
-btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
-{
-       int i,j,n;
-
-       if (nclips < 2)
-               return;
-       for (i = nclips-2; i >= 0; i--) {
-               for (n = 0, j = 0; j <= i; j++) {
-                       if (clips[j].c.left > clips[j+1].c.left) {
-                               swap(clips[j], clips[j + 1]);
-                               n++;
-                       }
-               }
-               if (0 == n)
-                       break;
-       }
-}
-
-void
-btcx_calc_skips(int line, int width, int *maxy,
-               struct btcx_skiplist *skips, unsigned int *nskips,
-               const struct v4l2_clip *clips, unsigned int nclips)
-{
-       unsigned int clip,skip;
-       int end, maxline;
-
-       skip=0;
-       maxline = 9999;
-       for (clip = 0; clip < nclips; clip++) {
-
-               /* sanity checks */
-               if (clips[clip].c.left + clips[clip].c.width <= 0)
-                       continue;
-               if (clips[clip].c.left > (signed)width)
-                       break;
-
-               /* vertical range */
-               if (line > clips[clip].c.top+clips[clip].c.height-1)
-                       continue;
-               if (line < clips[clip].c.top) {
-                       if (maxline > clips[clip].c.top-1)
-                               maxline = clips[clip].c.top-1;
-                       continue;
-               }
-               if (maxline > clips[clip].c.top+clips[clip].c.height-1)
-                       maxline = clips[clip].c.top+clips[clip].c.height-1;
-
-               /* horizontal range */
-               if (0 == skip || clips[clip].c.left > skips[skip-1].end) {
-                       /* new one */
-                       skips[skip].start = clips[clip].c.left;
-                       if (skips[skip].start < 0)
-                               skips[skip].start = 0;
-                       skips[skip].end = clips[clip].c.left + clips[clip].c.width;
-                       if (skips[skip].end > width)
-                               skips[skip].end = width;
-                       skip++;
-               } else {
-                       /* overlaps -- expand last one */
-                       end = clips[clip].c.left + clips[clip].c.width;
-                       if (skips[skip-1].end < end)
-                               skips[skip-1].end = end;
-                       if (skips[skip-1].end > width)
-                               skips[skip-1].end = width;
-               }
-       }
-       *nskips = skip;
-       *maxy = maxline;
-
-       if (btcx_debug) {
-               dprintk("btcx: skips line %d-%d:", line, maxline);
-               for (skip = 0; skip < *nskips; skip++) {
-                       pr_cont(" %d-%d", skips[skip].start, skips[skip].end);
-               }
-               pr_cont("\n");
-       }
-}
index dc774a64cd1fa35959776c4575ed2ebcd51ee5df..6ac79a15776fefc728abb689e5820e35577ecdbb 100644 (file)
@@ -16,12 +16,3 @@ int  btcx_riscmem_alloc(struct pci_dev *pci,
                        unsigned int size);
 void btcx_riscmem_free(struct pci_dev *pci,
                       struct btcx_riscmem *risc);
-
-int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
-                     struct v4l2_clip *clips, unsigned int n);
-int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
-              unsigned int n, int mask);
-void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
-void btcx_calc_skips(int line, int width, int *maxy,
-                    struct btcx_skiplist *skips, unsigned int *nskips,
-                    const struct v4l2_clip *clips, unsigned int nclips);
index c2b5ab287dd74e51c5680deef844f37b2792d3a9..ec78f7fc5e1b6c50a265a5a9360bdce7bb9077a8 100644 (file)
@@ -81,7 +81,6 @@ static int pvr_boot(struct bttv *btv);
 static unsigned int triton1;
 static unsigned int vsfx;
 static unsigned int latency = UNSET;
-int no_overlay=-1;
 
 static unsigned int card[BTTV_MAX]   = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
 static unsigned int pll[BTTV_MAX]    = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
@@ -99,7 +98,6 @@ static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET };
 /* insmod options */
 module_param(triton1,    int, 0444);
 module_param(vsfx,       int, 0444);
-module_param(no_overlay, int, 0444);
 module_param(latency,    int, 0444);
 module_param(gpiomask,   int, 0444);
 module_param(audioall,   int, 0444);
@@ -127,7 +125,6 @@ MODULE_PARM_DESC(audiodev, "specify audio device:\n"
                "\t\t 2 = tda7432\n"
                "\t\t 3 = tvaudio");
 MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition.");
-MODULE_PARM_DESC(no_overlay, "allow override overlay default (0 disables, 1 enables) [some VIA/SIS chipsets are known to have problem with overlay]");
 
 
 /* I2C addresses list */
@@ -4869,11 +4866,8 @@ static void gv800s_init(struct bttv *btv)
 
 void __init bttv_check_chipset(void)
 {
-       int pcipci_fail = 0;
        struct pci_dev *dev = NULL;
 
-       if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))       /* should check if target is AGP */
-               pcipci_fail = 1;
        if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF))
                triton1 = 1;
        if (pci_pci_problems & PCIPCI_VSFX)
@@ -4889,15 +4883,6 @@ void __init bttv_check_chipset(void)
                pr_info("Host bridge needs ETBF enabled\n");
        if (vsfx)
                pr_info("Host bridge needs VSFX enabled\n");
-       if (pcipci_fail) {
-               pr_info("bttv and your chipset may not work together\n");
-               if (!no_overlay) {
-                       pr_info("overlay will be disabled\n");
-                       no_overlay = 1;
-               } else {
-                       pr_info("overlay forced. Use this option at your own risk.\n");
-               }
-       }
        if (UNSET != latency)
                pr_info("pci latency fixup [%d]\n", latency);
        while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL,
index d40b537f4e98be383fa4ebb513821ec9cea96365..734f02b91aa31ca574afa10f69909e89ccfad61a 100644 (file)
@@ -624,20 +624,14 @@ static const unsigned int FORMATS = ARRAY_SIZE(formats);
                 VIDIOC_QBUF 1)              bttv_release
                 VIDIOCMCAPTURE 1)
 
-   OVERLAY      VIDIOCCAPTURE on            VIDIOCCAPTURE off
-                VIDIOC_OVERLAY on           VIDIOC_OVERLAY off
-                3)                          bttv_release
-
    VBI          VIDIOC_STREAMON             VIDIOC_STREAMOFF
                 VIDIOC_QBUF 1)              bttv_release
-                bttv_read, bttv_poll 1) 4)
+                bttv_read, bttv_poll 1) 3)
 
    1) The resource must be allocated when we enter buffer prepare functions
       and remain allocated while buffers are in the DMA queue.
    2) This is a single frame read.
-   3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
-      RESOURCE_OVERLAY is allocated.
-   4) This is a continuous read, implies VIDIOC_STREAMON.
+   3) This is a continuous read, implies VIDIOC_STREAMON.
 
    Note this driver permits video input and standard changes regardless if
    resources are allocated.
@@ -645,8 +639,7 @@ static const unsigned int FORMATS = ARRAY_SIZE(formats);
 
 #define VBI_RESOURCES (RESOURCE_VBI)
 #define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
-                        RESOURCE_VIDEO_STREAM | \
-                        RESOURCE_OVERLAY)
+                        RESOURCE_VIDEO_STREAM)
 
 static
 int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
@@ -1491,37 +1484,6 @@ format_by_fourcc(int fourcc)
        return NULL;
 }
 
-/* ----------------------------------------------------------------------- */
-/* misc helpers                                                            */
-
-static int
-bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
-                   struct bttv_buffer *new)
-{
-       struct bttv_buffer *old;
-       unsigned long flags;
-
-       dprintk("switch_overlay: enter [new=%p]\n", new);
-       if (new)
-               new->vb.state = VIDEOBUF_DONE;
-       spin_lock_irqsave(&btv->s_lock,flags);
-       old = btv->screen;
-       btv->screen = new;
-       btv->loop_irq |= 1;
-       bttv_set_dma(btv, 0x03);
-       spin_unlock_irqrestore(&btv->s_lock,flags);
-       if (NULL != old) {
-               dprintk("switch_overlay: old=%p state is %d\n",
-                       old, old->vb.state);
-               bttv_dma_free(&fh->cap,btv, old);
-               kfree(old);
-       }
-       if (NULL == new)
-               free_btres_lock(btv,fh,RESOURCE_OVERLAY);
-       dprintk("switch_overlay: done\n");
-       return 0;
-}
-
 /* ----------------------------------------------------------------------- */
 /* video4linux (1) interface                                               */
 
@@ -2045,150 +2007,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
        return rc;
 }
 
-/* Returns an error if the given overlay window dimensions are not
-   possible with the current cropping parameters. If adjust_size is
-   TRUE the function may adjust the window width and/or height
-   instead, however it always rounds the horizontal position and
-   width as btcx_align() does. If adjust_crop is TRUE the function
-   may also adjust the current cropping parameters to get closer
-   to the desired window size. */
-static int
-verify_window_lock(struct bttv_fh *fh, struct v4l2_window *win,
-                        int adjust_size, int adjust_crop)
-{
-       enum v4l2_field field;
-       unsigned int width_mask;
-
-       if (win->w.width < 48)
-               win->w.width = 48;
-       if (win->w.height < 32)
-               win->w.height = 32;
-       if (win->clipcount > 2048)
-               win->clipcount = 2048;
-
-       win->chromakey = 0;
-       win->global_alpha = 0;
-       field = win->field;
-
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-       case V4L2_FIELD_INTERLACED:
-               break;
-       default:
-               field = V4L2_FIELD_ANY;
-               break;
-       }
-       if (V4L2_FIELD_ANY == field) {
-               __s32 height2;
-
-               height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
-               field = (win->w.height > height2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_TOP;
-       }
-       win->field = field;
-
-       if (NULL == fh->ovfmt)
-               return -EINVAL;
-       /* 4-byte alignment. */
-       width_mask = ~0;
-       switch (fh->ovfmt->depth) {
-       case 8:
-       case 24:
-               width_mask = ~3;
-               break;
-       case 16:
-               width_mask = ~1;
-               break;
-       case 32:
-               break;
-       default:
-               BUG();
-       }
-
-       win->w.width -= win->w.left & ~width_mask;
-       win->w.left = (win->w.left - width_mask - 1) & width_mask;
-
-       return limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
-                                     field, width_mask,
-                                     /* width_bias: round down */ 0,
-                                     adjust_size, adjust_crop);
-}
-
-static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
-                       struct v4l2_window *win, int fixup)
-{
-       struct v4l2_clip *clips = NULL;
-       int n,size,retval = 0;
-
-       if (NULL == fh->ovfmt)
-               return -EINVAL;
-       if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
-               return -EINVAL;
-       retval = verify_window_lock(fh, win,
-                              /* adjust_size */ fixup,
-                              /* adjust_crop */ fixup);
-       if (0 != retval)
-               return retval;
-
-       /* copy clips  --  luckily v4l1 + v4l2 are binary
-          compatible here ...*/
-       n = win->clipcount;
-       size = sizeof(*clips)*(n+4);
-       clips = kmalloc(size,GFP_KERNEL);
-       if (NULL == clips)
-               return -ENOMEM;
-       if (n > 0)
-               memcpy(clips, win->clips, sizeof(struct v4l2_clip) * n);
-
-       /* clip against screen */
-       if (NULL != btv->fbuf.base)
-               n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
-                                     &win->w, clips, n);
-       btcx_sort_clips(clips,n);
-
-       /* 4-byte alignments */
-       switch (fh->ovfmt->depth) {
-       case 8:
-       case 24:
-               btcx_align(&win->w, clips, n, 3);
-               break;
-       case 16:
-               btcx_align(&win->w, clips, n, 1);
-               break;
-       case 32:
-               /* no alignment fixups needed */
-               break;
-       default:
-               BUG();
-       }
-
-       kfree(fh->ov.clips);
-       fh->ov.clips    = clips;
-       fh->ov.nclips   = n;
-
-       fh->ov.w        = win->w;
-       fh->ov.field    = win->field;
-       fh->ov.setup_ok = 1;
-
-       btv->init.ov.w.width   = win->w.width;
-       btv->init.ov.w.height  = win->w.height;
-       btv->init.ov.field     = win->field;
-
-       /* update overlay if needed */
-       retval = 0;
-       if (check_btres(fh, RESOURCE_OVERLAY)) {
-               struct bttv_buffer *new;
-
-               new = videobuf_sg_alloc(sizeof(*new));
-               new->crop = btv->crop[!!fh->do_crop].rect;
-               bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
-               retval = bttv_switch_overlay(btv,fh,new);
-       }
-       return retval;
-}
-
 /* ----------------------------------------------------------------------- */
 
 static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
@@ -2270,17 +2088,6 @@ static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct bttv_fh *fh  = priv;
-
-       f->fmt.win.w     = fh->ov.w;
-       f->fmt.win.field = fh->ov.field;
-
-       return 0;
-}
-
 static void bttv_get_width_mask_vid_cap(const struct bttv_format *fmt,
                                        unsigned int *width_mask,
                                        unsigned int *width_bias)
@@ -2352,17 +2159,6 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
-                                               struct v4l2_format *f)
-{
-       struct bttv_fh *fh = priv;
-
-       verify_window_lock(fh, &f->fmt.win,
-                       /* adjust_size */ 1,
-                       /* adjust_crop */ 0);
-       return 0;
-}
-
 static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
@@ -2410,20 +2206,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct bttv_fh *fh = priv;
-       struct bttv *btv = fh->btv;
-
-       if (no_overlay > 0) {
-               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-
-       return setup_window_lock(fh, btv, &f->fmt.win, 1);
-}
-
 static int bttv_querycap(struct file *file, void  *priv,
                                struct v4l2_capability *cap)
 {
@@ -2437,8 +2219,6 @@ static int bttv_querycap(struct file *file, void  *priv,
        strscpy(cap->card, btv->video_dev.name, sizeof(cap->card));
        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
                            V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
-       if (no_overlay <= 0)
-               cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
        if (video_is_registered(&btv->vbi_dev))
                cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
        if (video_is_registered(&btv->radio_dev)) {
@@ -2458,7 +2238,8 @@ static int bttv_querycap(struct file *file, void  *priv,
        return 0;
 }
 
-static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
+static int bttv_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                struct v4l2_fmtdesc *f)
 {
        int index = -1, i;
 
@@ -2473,162 +2254,9 @@ static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
 
        f->pixelformat = formats[i].fourcc;
 
-       return i;
-}
-
-static int bttv_enum_fmt_vid_cap(struct file *file, void  *priv,
-                               struct v4l2_fmtdesc *f)
-{
-       int rc = bttv_enum_fmt_cap_ovr(f);
-
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
-
-static int bttv_enum_fmt_vid_overlay(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       int rc;
-
-       if (no_overlay > 0) {
-               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-
-       rc = bttv_enum_fmt_cap_ovr(f);
-
-       if (rc < 0)
-               return rc;
-
-       if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
-               return -EINVAL;
-
        return 0;
 }
 
-static int bttv_g_fbuf(struct file *file, void *f,
-                               struct v4l2_framebuffer *fb)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-
-       *fb = btv->fbuf;
-       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-       fb->flags = V4L2_FBUF_FLAG_PRIMARY;
-       if (fh->ovfmt)
-               fb->fmt.pixelformat  = fh->ovfmt->fourcc;
-       return 0;
-}
-
-static int bttv_overlay(struct file *file, void *f, unsigned int on)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-       struct bttv_buffer *new;
-       int retval = 0;
-
-       if (on) {
-               /* verify args */
-               if (unlikely(!btv->fbuf.base)) {
-                       return -EINVAL;
-               }
-               if (unlikely(!fh->ov.setup_ok)) {
-                       dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
-                       retval = -EINVAL;
-               }
-               if (retval)
-                       return retval;
-       }
-
-       if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
-               return -EBUSY;
-
-       if (on) {
-               fh->ov.tvnorm = btv->tvnorm;
-               new = videobuf_sg_alloc(sizeof(*new));
-               new->crop = btv->crop[!!fh->do_crop].rect;
-               bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
-       } else {
-               new = NULL;
-       }
-
-       /* switch over */
-       retval = bttv_switch_overlay(btv, fh, new);
-       return retval;
-}
-
-static int bttv_s_fbuf(struct file *file, void *f,
-                               const struct v4l2_framebuffer *fb)
-{
-       struct bttv_fh *fh = f;
-       struct bttv *btv = fh->btv;
-       const struct bttv_format *fmt;
-       int retval;
-
-       if (!capable(CAP_SYS_ADMIN) &&
-               !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       /* check args */
-       fmt = format_by_fourcc(fb->fmt.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-       if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
-               return -EINVAL;
-
-       retval = -EINVAL;
-       if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
-               __s32 width = fb->fmt.width;
-               __s32 height = fb->fmt.height;
-
-               retval = limit_scaled_size_lock(fh, &width, &height,
-                                          V4L2_FIELD_INTERLACED,
-                                          /* width_mask */ ~3,
-                                          /* width_bias */ 2,
-                                          /* adjust_size */ 0,
-                                          /* adjust_crop */ 0);
-               if (0 != retval)
-                       return retval;
-       }
-
-       /* ok, accept it */
-       btv->fbuf.base       = fb->base;
-       btv->fbuf.fmt.width  = fb->fmt.width;
-       btv->fbuf.fmt.height = fb->fmt.height;
-       if (0 != fb->fmt.bytesperline)
-               btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
-       else
-               btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
-
-       retval = 0;
-       fh->ovfmt = fmt;
-       btv->init.ovfmt = fmt;
-       if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
-               fh->ov.w.left   = 0;
-               fh->ov.w.top    = 0;
-               fh->ov.w.width  = fb->fmt.width;
-               fh->ov.w.height = fb->fmt.height;
-               btv->init.ov.w.width  = fb->fmt.width;
-               btv->init.ov.w.height = fb->fmt.height;
-
-               kfree(fh->ov.clips);
-               fh->ov.clips = NULL;
-               fh->ov.nclips = 0;
-
-               if (check_btres(fh, RESOURCE_OVERLAY)) {
-                       struct bttv_buffer *new;
-
-                       new = videobuf_sg_alloc(sizeof(*new));
-                       new->crop = btv->crop[!!fh->do_crop].rect;
-                       bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
-                       retval = bttv_switch_overlay(btv, fh, new);
-               }
-       }
-       return retval;
-}
-
 static int bttv_reqbufs(struct file *file, void *priv,
                                struct v4l2_requestbuffers *p)
 {
@@ -2748,8 +2376,7 @@ static int bttv_g_selection(struct file *file, void *f, struct v4l2_selection *s
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
 
-       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           sel->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
        switch (sel->target) {
@@ -2786,8 +2413,7 @@ static int bttv_s_selection(struct file *file, void *f, struct v4l2_selection *s
        __s32 b_right;
        __s32 b_bottom;
 
-       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           sel->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
        if (sel->target != V4L2_SEL_TGT_CROP)
@@ -2977,7 +2603,6 @@ static int bttv_open(struct file *file)
        v4l2_fh_init(&fh->fh, vdev);
 
        fh->type = type;
-       fh->ov.setup_ok = 0;
 
        videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
                            &btv->c.pci->dev, &btv->s_lock,
@@ -3021,10 +2646,6 @@ static int bttv_release(struct file *file)
        struct bttv_fh *fh = file->private_data;
        struct bttv *btv = fh->btv;
 
-       /* turn off overlay */
-       if (check_btres(fh, RESOURCE_OVERLAY))
-               bttv_switch_overlay(btv,fh,NULL);
-
        /* stop video capture */
        if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
                videobuf_streamoff(&fh->cap);
@@ -3090,10 +2711,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
        .vidioc_g_fmt_vid_cap           = bttv_g_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap         = bttv_try_fmt_vid_cap,
        .vidioc_s_fmt_vid_cap           = bttv_s_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_overlay    = bttv_enum_fmt_vid_overlay,
-       .vidioc_g_fmt_vid_overlay       = bttv_g_fmt_vid_overlay,
-       .vidioc_try_fmt_vid_overlay     = bttv_try_fmt_vid_overlay,
-       .vidioc_s_fmt_vid_overlay       = bttv_s_fmt_vid_overlay,
        .vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
        .vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
        .vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
@@ -3113,9 +2730,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
        .vidioc_s_tuner                 = bttv_s_tuner,
        .vidioc_g_selection             = bttv_g_selection,
        .vidioc_s_selection             = bttv_s_selection,
-       .vidioc_g_fbuf                  = bttv_g_fbuf,
-       .vidioc_s_fbuf                  = bttv_s_fbuf,
-       .vidioc_overlay                 = bttv_overlay,
        .vidioc_g_parm                  = bttv_g_parm,
        .vidioc_g_frequency             = bttv_g_frequency,
        .vidioc_s_frequency             = bttv_s_frequency,
@@ -3385,9 +2999,6 @@ static void bttv_print_riscaddr(struct bttv *btv)
                ? (unsigned long long)btv->curr.top->top.dma : 0,
                btv->curr.bottom
                ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
-       pr_info("  scr : o=%08llx e=%08llx\n",
-               btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
-               btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
        bttv_risc_disasm(btv, &btv->main);
 }
 
@@ -3508,28 +3119,9 @@ bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
                }
        }
 
-       /* screen overlay ? */
-       if (NULL != btv->screen) {
-               if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
-                       if (NULL == set->top && NULL == set->bottom) {
-                               set->top    = btv->screen;
-                               set->bottom = btv->screen;
-                       }
-               } else {
-                       if (V4L2_FIELD_TOP == btv->screen->vb.field &&
-                           NULL == set->top) {
-                               set->top = btv->screen;
-                       }
-                       if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
-                           NULL == set->bottom) {
-                               set->bottom = btv->screen;
-                       }
-               }
-       }
-
-       dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
+       dprintk("%d: next set: top=%p bottom=%p [irq=%d,%d]\n",
                btv->c.nr, set->top, set->bottom,
-               btv->screen, set->frame_irq, set->top_irq);
+               set->frame_irq, set->top_irq);
        return 0;
 }
 
@@ -3883,17 +3475,12 @@ static void bttv_unregister_video(struct bttv *btv)
 /* register video4linux devices */
 static int bttv_register_video(struct bttv *btv)
 {
-       if (no_overlay > 0)
-               pr_notice("Overlay support disabled\n");
-
        /* video */
        vdev_init(btv, &btv->video_dev, &bttv_video_template, "video");
        btv->video_dev.device_caps = V4L2_CAP_VIDEO_CAPTURE |
                                     V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
        if (btv->tuner_type != TUNER_ABSENT)
                btv->video_dev.device_caps |= V4L2_CAP_TUNER;
-       if (no_overlay <= 0)
-               btv->video_dev.device_caps |= V4L2_CAP_VIDEO_OVERLAY;
 
        if (video_register_device(&btv->video_dev, VFL_TYPE_VIDEO,
                                  video_nr[btv->c.nr]) < 0)
@@ -4084,14 +3671,9 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 
        /* fill struct bttv with some useful defaults */
        btv->init.btv         = btv;
-       btv->init.ov.w.width  = 320;
-       btv->init.ov.w.height = 240;
        btv->init.fmt         = format_by_fourcc(V4L2_PIX_FMT_BGR24);
        btv->init.width       = 320;
        btv->init.height      = 240;
-       btv->init.ov.w.width  = 320;
-       btv->init.ov.w.height = 240;
-       btv->init.ov.field    = V4L2_FIELD_INTERLACED;
        btv->input = 0;
 
        v4l2_ctrl_new_std(hdl, &bttv_ctrl_ops,
index 32fa4a7fe76f7468be0f7a072664a5d2cc814bc9..4fa4b9da9634bf3ecf5cb433131fefcf157cb24a 100644 (file)
@@ -231,95 +231,6 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
        return 0;
 }
 
-static int
-bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
-                 const struct bttv_format *fmt, struct bttv_overlay *ov,
-                 int skip_even, int skip_odd)
-{
-       int dwords, rc, line, maxy, start, end;
-       unsigned skip, nskips;
-       struct btcx_skiplist *skips;
-       __le32 *rp;
-       u32 ri,ra;
-       u32 addr;
-
-       /* skip list for window clipping */
-       skips = kmalloc_array(ov->nclips, sizeof(*skips),GFP_KERNEL);
-       if (NULL == skips)
-               return -ENOMEM;
-
-       /* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
-          + sync + jump (all 2 dwords) */
-       dwords  = (3 * ov->nclips + 2) *
-               ((skip_even || skip_odd) ? (ov->w.height+1)>>1 :  ov->w.height);
-       dwords += 4;
-       if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
-               kfree(skips);
-               return rc;
-       }
-
-       /* sync instruction */
-       rp = risc->cpu;
-       *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
-       *(rp++) = cpu_to_le32(0);
-
-       addr  = (unsigned long)btv->fbuf.base;
-       addr += btv->fbuf.fmt.bytesperline * ov->w.top;
-       addr += (fmt->depth >> 3)          * ov->w.left;
-
-       /* scan lines */
-       for (maxy = -1, line = 0; line < ov->w.height;
-            line++, addr += btv->fbuf.fmt.bytesperline) {
-               if ((btv->opt_vcr_hack) &&
-                    (line >= (ov->w.height - VCR_HACK_LINES)))
-                       continue;
-               if ((line%2) == 0  &&  skip_even)
-                       continue;
-               if ((line%2) == 1  &&  skip_odd)
-                       continue;
-
-               /* calculate clipping */
-               if (line > maxy)
-                       btcx_calc_skips(line, ov->w.width, &maxy,
-                                       skips, &nskips, ov->clips, ov->nclips);
-
-               /* write out risc code */
-               for (start = 0, skip = 0; start < ov->w.width; start = end) {
-                       if (skip >= nskips) {
-                               ri  = BT848_RISC_WRITE;
-                               end = ov->w.width;
-                       } else if (start < skips[skip].start) {
-                               ri  = BT848_RISC_WRITE;
-                               end = skips[skip].start;
-                       } else {
-                               ri  = BT848_RISC_SKIP;
-                               end = skips[skip].end;
-                               skip++;
-                       }
-                       if (BT848_RISC_WRITE == ri)
-                               ra = addr + (fmt->depth>>3)*start;
-                       else
-                               ra = 0;
-
-                       if (0 == start)
-                               ri |= BT848_RISC_SOL;
-                       if (ov->w.width == end)
-                               ri |= BT848_RISC_EOL;
-                       ri |= (fmt->depth>>3) * (end-start);
-
-                       *(rp++)=cpu_to_le32(ri);
-                       if (0 != ra)
-                               *(rp++)=cpu_to_le32(ra);
-               }
-       }
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
-       kfree(skips);
-       return 0;
-}
-
 /* ---------------------------------------------------------- */
 
 static void
@@ -848,45 +759,3 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
        buf->btswap   = buf->fmt->btswap;
        return 0;
 }
-
-/* ---------------------------------------------------------- */
-
-/* calculate geometry, build risc code */
-int
-bttv_overlay_risc(struct bttv *btv,
-                 struct bttv_overlay *ov,
-                 const struct bttv_format *fmt,
-                 struct bttv_buffer *buf)
-{
-       /* check interleave, bottom+top fields */
-       dprintk("%d: overlay fields: %s format: 0x%08x  size: %dx%d\n",
-               btv->c.nr, v4l2_field_names[buf->vb.field],
-               fmt->fourcc, ov->w.width, ov->w.height);
-
-       /* calculate geometry */
-       bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
-                     V4L2_FIELD_HAS_BOTH(ov->field),
-                     &bttv_tvnorms[ov->tvnorm],&buf->crop);
-
-       /* build risc code */
-       switch (ov->field) {
-       case V4L2_FIELD_TOP:
-               bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
-               break;
-       case V4L2_FIELD_BOTTOM:
-               bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
-               break;
-       case V4L2_FIELD_INTERLACED:
-               bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
-               bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
-               break;
-       default:
-               BUG();
-       }
-
-       /* copy format info */
-       buf->btformat = fmt->btformat;
-       buf->btswap   = fmt->btswap;
-       buf->vb.field = ov->field;
-       return 0;
-}
index 4abf436578465fcd6194b9d59065989f53097ff7..717f002a41dffa978ec7243f07e414b4086d2a54 100644 (file)
@@ -50,7 +50,6 @@
 #define RISC_SLOT_E_FIELD     12
 #define RISC_SLOT_LOOP        14
 
-#define RESOURCE_OVERLAY       1
 #define RESOURCE_VIDEO_STREAM  2
 #define RESOURCE_VBI           4
 #define RESOURCE_VIDEO_READ    8
@@ -165,15 +164,6 @@ struct bttv_buffer_set {
        unsigned int           frame_irq;
 };
 
-struct bttv_overlay {
-       unsigned int           tvnorm;
-       struct v4l2_rect       w;
-       enum v4l2_field        field;
-       struct v4l2_clip       *clips;
-       int                    nclips;
-       int                    setup_ok;
-};
-
 struct bttv_vbi_fmt {
        struct v4l2_vbi_format fmt;
 
@@ -216,10 +206,6 @@ struct bttv_fh {
        int                      width;
        int                      height;
 
-       /* video overlay */
-       const struct bttv_format *ovfmt;
-       struct bttv_overlay      ov;
-
        /* Application called VIDIOC_S_SELECTION. */
        int                      do_crop;
 
@@ -256,12 +242,6 @@ int bttv_buffer_activate_vbi(struct bttv *btv,
 void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv,
                   struct bttv_buffer *buf);
 
-/* overlay handling */
-int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
-                     const struct bttv_format *fmt,
-                     struct bttv_buffer *buf);
-
-
 /* ---------------------------------------------------------- */
 /* bttv-vbi.c                                                 */
 
@@ -278,11 +258,6 @@ extern struct bus_type bttv_sub_bus_type;
 int bttv_sub_add_device(struct bttv_core *core, char *name);
 int bttv_sub_del_devices(struct bttv_core *core);
 
-/* ---------------------------------------------------------- */
-/* bttv-cards.c                                               */
-
-extern int no_overlay;
-
 /* ---------------------------------------------------------- */
 /* bttv-input.c                                               */
 
@@ -454,7 +429,6 @@ struct bttv {
           - must acquire s_lock before changing these
           - only the irq handler is supported to touch top + bottom + vcurr */
        struct btcx_riscmem     main;
-       struct bttv_buffer      *screen;    /* overlay             */
        struct list_head        capture;    /* video capture queue */
        struct list_head        vcapture;   /* vbi capture queue   */
        struct bttv_buffer_set  curr;       /* active buffers      */
@@ -479,7 +453,7 @@ struct bttv {
        /* used to make dvb-bt8xx autoloadable */
        struct work_struct request_module_wk;
 
-       /* Default (0) and current (1) video capturing and overlay
+       /* Default (0) and current (1) video capturing
           cropping parameters in bttv_tvnorm.cropcap units. Protected
           by bttv.lock. */
        struct bttv_crop crop[2];
index 0ff37496c9ab79017bb29a0bd9738bb0587dc82f..4bfbcca14f60b73728ab67df9cf26aa92c4f8c05 100644 (file)
@@ -708,7 +708,6 @@ static int cobalt_g_fmt_vid_cap(struct file *file, void *priv_fh,
 {
        struct cobalt_stream *s = video_drvdata(file);
        struct v4l2_pix_format *pix = &f->fmt.pix;
-       struct v4l2_subdev_format sd_fmt;
 
        pix->width = s->width;
        pix->height = s->height;
@@ -718,8 +717,11 @@ static int cobalt_g_fmt_vid_cap(struct file *file, void *priv_fh,
        if (s->input == 1) {
                pix->colorspace = V4L2_COLORSPACE_SRGB;
        } else {
-               sd_fmt.pad = s->pad_source;
-               sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+               struct v4l2_subdev_format sd_fmt = {
+                       .pad = s->pad_source,
+                       .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               };
+
                v4l2_subdev_call(s->sd, pad, get_fmt, NULL, &sd_fmt);
                v4l2_fill_pix_format(pix, &sd_fmt.format);
        }
@@ -735,7 +737,6 @@ static int cobalt_try_fmt_vid_cap(struct file *file, void *priv_fh,
 {
        struct cobalt_stream *s = video_drvdata(file);
        struct v4l2_pix_format *pix = &f->fmt.pix;
-       struct v4l2_subdev_format sd_fmt;
 
        /* Check for min (QCIF) and max (Full HD) size */
        if ((pix->width < 176) || (pix->height < 144)) {
@@ -760,8 +761,11 @@ static int cobalt_try_fmt_vid_cap(struct file *file, void *priv_fh,
                pix->height = 1080;
                pix->colorspace = V4L2_COLORSPACE_SRGB;
        } else {
-               sd_fmt.pad = s->pad_source;
-               sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+               struct v4l2_subdev_format sd_fmt = {
+                       .pad = s->pad_source,
+                       .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               };
+
                v4l2_subdev_call(s->sd, pad, get_fmt, NULL, &sd_fmt);
                v4l2_fill_pix_format(pix, &sd_fmt.format);
        }
@@ -906,7 +910,9 @@ static int cobalt_s_fmt_vid_out(struct file *file, void *priv_fh,
 {
        struct cobalt_stream *s = video_drvdata(file);
        struct v4l2_pix_format *pix = &f->fmt.pix;
-       struct v4l2_subdev_format sd_fmt = { 0 };
+       struct v4l2_subdev_format sd_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        u32 code;
 
        if (cobalt_try_fmt_vid_out(file, priv_fh, f))
@@ -937,7 +943,6 @@ static int cobalt_s_fmt_vid_out(struct file *file, void *priv_fh,
        s->xfer_func = pix->xfer_func;
        s->ycbcr_enc = pix->ycbcr_enc;
        s->quantization = pix->quantization;
-       sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        v4l2_fill_mbus_format(&sd_fmt.format, pix, code);
        v4l2_subdev_call(s->sd, pad, set_fmt, NULL, &sd_fmt);
        return 0;
index a4e32fdcfd3d2bf4166a6f54dfda5da5fb8210b9..5c959bb5e233918627926edf5377beb33569bf7b 100644 (file)
@@ -3,7 +3,7 @@ config VIDEO_CX18
        tristate "Conexant cx23418 MPEG encoder support"
        depends on VIDEO_DEV && DVB_CORE && PCI && I2C
        select I2C_ALGOBIT
-       select VIDEOBUF_VMALLOC
+       select VIDEOBUF2_VMALLOC
        depends on RC_CORE
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
index 84260972c3432e07b3f40cea2132700444e8e70c..743fcc9613744bfc1edeffc51e908fe88520405a 100644 (file)
@@ -771,11 +771,11 @@ static void cx18_init_struct2(struct cx18 *cx)
 {
        int i;
 
-       for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS - 1; i++)
+       for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
                if (cx->card->video_inputs[i].video_type == 0)
                        break;
        cx->nof_inputs = i;
-       for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS - 1; i++)
+       for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
                if (cx->card->audio_inputs[i].audio_type == 0)
                        break;
        cx->nof_audio_inputs = i;
index ef545b96121df626563298a4a45412b8641c3dc5..887d2aa364470a711afdd03bbf5ef2ade3271309 100644 (file)
@@ -48,9 +48,8 @@
 #include <media/dvb_net.h>
 #include <media/dvbdev.h>
 
-/* Videobuf / YUV support */
-#include <media/videobuf-core.h>
-#include <media/videobuf-vmalloc.h>
+/* vb2 YUV support */
+#include <media/videobuf2-vmalloc.h>
 
 #ifndef CONFIG_PCI
 #  error "This driver requires kernel PCI support."
@@ -284,6 +283,14 @@ struct cx18_options {
 #define list_entry_is_past_end(pos, head, member) \
        (&pos->member == (head))
 
+struct cx18_vb2_buffer {
+       /* Common video buffer sub-system struct */
+       struct vb2_v4l2_buffer vb;
+       struct list_head list;
+       v4l2_std_id tvnorm; /* selected tv norm */
+       u32 bytes_used;
+};
+
 struct cx18_buffer {
        struct list_head list;
        dma_addr_t dma_handle;
@@ -399,19 +406,12 @@ struct cx18_stream {
        struct list_head vb_capture;    /* video capture queue */
        spinlock_t vb_lock;
        struct timer_list vb_timeout;
+       u32 sequence;
 
-       struct videobuf_queue vbuf_q;
-       spinlock_t vbuf_q_lock; /* Protect vbuf_q */
+       struct vb2_queue vidq;
        enum v4l2_buf_type vb_type;
 };
 
-struct cx18_videobuf_buffer {
-       /* Common video buffer sub-system struct */
-       struct videobuf_buffer vb;
-       v4l2_std_id tvnorm; /* selected tv norm */
-       u32 bytes_used;
-};
-
 struct cx18_open_id {
        struct v4l2_fh fh;
        u32 open_id;
index 4cf5b9ca92e7d4cbfdf8511f88c7211faa909bd6..7e742733391b6f69870f16115768bc5c733da860 100644 (file)
@@ -584,12 +584,6 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
        if (rc)
                return rc;
 
-       if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
-               return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0,
-                       filp->f_flags & O_NONBLOCK);
-       }
-
        return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
 }
 
@@ -618,17 +612,6 @@ __poll_t cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
                CX18_DEBUG_FILE("Encoder poll started capture\n");
        }
 
-       if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
-               __poll_t videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
-
-               if (v4l2_event_pending(&id->fh))
-                       res |= EPOLLPRI;
-               if (eof && videobuf_poll == EPOLLERR)
-                       return res | EPOLLHUP;
-               return res | videobuf_poll;
-       }
-
        /* add stream's waitq to the poll list */
        CX18_DEBUG_HI_FILE("Encoder poll\n");
        if (v4l2_event_pending(&id->fh))
@@ -643,62 +626,20 @@ __poll_t cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
        return res;
 }
 
-int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-       int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
-
-       if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
-
-               /* Start a capture if there is none */
-               if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
-                       int rc;
-
-                       mutex_lock(&cx->serialize_lock);
-                       rc = cx18_start_capture(id);
-                       mutex_unlock(&cx->serialize_lock);
-                       if (rc) {
-                               CX18_DEBUG_INFO(
-                                       "Could not start capture for %s (%d)\n",
-                                       s->name, rc);
-                               return -EINVAL;
-                       }
-                       CX18_DEBUG_FILE("Encoder mmap started capture\n");
-               }
-
-               return videobuf_mmap_mapper(&s->vbuf_q, vma);
-       }
-
-       return -EINVAL;
-}
-
 void cx18_vb_timeout(struct timer_list *t)
 {
        struct cx18_stream *s = from_timer(s, t, vb_timeout);
-       struct cx18_videobuf_buffer *buf;
-       unsigned long flags;
 
-       /* Return all of the buffers in error state, so the vbi/vid inode
+       /*
+        * Return all of the buffers in error state, so the vbi/vid inode
         * can return from blocking.
         */
-       spin_lock_irqsave(&s->vb_lock, flags);
-       while (!list_empty(&s->vb_capture)) {
-               buf = list_entry(s->vb_capture.next,
-                       struct cx18_videobuf_buffer, vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-       }
-       spin_unlock_irqrestore(&s->vb_lock, flags);
+       cx18_clear_queue(s, VB2_BUF_STATE_ERROR);
 }
 
-void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
+void cx18_stop_capture(struct cx18_stream *s, int gop_end)
 {
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
+       struct cx18 *cx = s->cx;
        struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
        struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
 
@@ -709,7 +650,7 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
        /* Stop capturing */
        if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
                CX18_DEBUG_INFO("close stopping capture\n");
-               if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
+               if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
                        /* Stop internal use associated VBI and IDX streams */
                        if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
                            !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
@@ -721,7 +662,7 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
                                cx18_stop_v4l2_encode_stream(s_idx, 0);
                        }
                }
-               if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
+               if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
                    test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
                        /* Also used internally, don't stop capturing */
                        s->id = -1;
@@ -741,13 +682,14 @@ int cx18_v4l2_close(struct file *filp)
        struct cx18_open_id *id = fh2id(fh);
        struct cx18 *cx = id->cx;
        struct cx18_stream *s = &cx->streams[id->type];
+       struct video_device *vdev = &s->video_dev;
 
        CX18_DEBUG_IOCTL("close() of %s\n", s->name);
 
        mutex_lock(&cx->serialize_lock);
        /* Stop radio */
        if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
-                       v4l2_fh_is_singular_file(filp)) {
+           v4l2_fh_is_singular_file(filp)) {
                /* Closing radio device, return to TV mode */
                cx18_mute(cx);
                /* Mark that the radio is no longer in use */
@@ -766,12 +708,17 @@ int cx18_v4l2_close(struct file *filp)
                cx18_unmute(cx);
        }
 
+       if (id->type == CX18_ENC_STREAM_TYPE_YUV &&
+           filp->private_data == vdev->queue->owner) {
+               vb2_queue_release(vdev->queue);
+               vdev->queue->owner = NULL;
+       }
        v4l2_fh_del(fh);
        v4l2_fh_exit(fh);
 
        /* 'Unclaim' this stream */
-       if (s->id == id->open_id)
-               cx18_stop_capture(id, 0);
+       if (id->type != CX18_ENC_STREAM_TYPE_YUV && s->id == id->open_id)
+               cx18_stop_capture(s, 0);
        kfree(id);
        mutex_unlock(&cx->serialize_lock);
        return 0;
index 1985d6422347f333d137b7acf1d904087239a456..943057b83d94849ec8f538842f6c5f999a80bb57 100644 (file)
@@ -16,10 +16,11 @@ ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count,
 int cx18_v4l2_close(struct file *filp);
 __poll_t cx18_v4l2_enc_poll(struct file *filp, poll_table *wait);
 int cx18_start_capture(struct cx18_open_id *id);
-void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
+void cx18_stop_capture(struct cx18_stream *s, int gop_end);
 void cx18_mute(struct cx18 *cx);
 void cx18_unmute(struct cx18 *cx);
 int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma);
+void cx18_clear_queue(struct cx18_stream *s, enum vb2_buffer_state state);
 void cx18_vb_timeout(struct timer_list *t);
 
 /* Shared with cx18-alsa module */
index c8ba7841c72088ea54a632cbc03f54ab4d2186fa..1817b9ed042c5dc64fe14dd4bb5250bed492bb14 100644 (file)
 #include <media/tveeprom.h>
 #include <media/v4l2-event.h>
 
+static const struct v4l2_fmtdesc cx18_formats_yuv[] = {
+       {
+               .index = 0,
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               .pixelformat = V4L2_PIX_FMT_NV12_16L16,
+       },
+       {
+               .index = 1,
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               .pixelformat = V4L2_PIX_FMT_UYVY,
+       },
+};
+
+static const struct v4l2_fmtdesc cx18_formats_mpeg[] = {
+       {
+               .index = 0,
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               .flags = V4L2_FMT_FLAG_COMPRESSED,
+               .pixelformat = V4L2_PIX_FMT_MPEG,
+       },
+};
+
+static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
+                             struct v4l2_format *fmt)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+
+       pixfmt->width = cx->cxhdl.width;
+       pixfmt->height = cx->cxhdl.height;
+       pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       pixfmt->field = V4L2_FIELD_INTERLACED;
+       if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
+               pixfmt->pixelformat = s->pixelformat;
+               pixfmt->sizeimage = s->vb_bytes_per_frame;
+               pixfmt->bytesperline = s->vb_bytes_per_line;
+       } else {
+               pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
+               pixfmt->sizeimage = 128 * 1024;
+               pixfmt->bytesperline = 0;
+       }
+       return 0;
+}
+
+static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+       int w = pixfmt->width;
+       int h = pixfmt->height;
+
+       w = min(w, 720);
+       w = max(w, 720 / 16);
+
+       h = min(h, cx->is_50hz ? 576 : 480);
+       h = max(h, (cx->is_50hz ? 576 : 480) / 8);
+
+       if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
+               if (pixfmt->pixelformat != V4L2_PIX_FMT_NV12_16L16 &&
+                   pixfmt->pixelformat != V4L2_PIX_FMT_UYVY)
+                       pixfmt->pixelformat = V4L2_PIX_FMT_UYVY;
+               /* YUV height must be a multiple of 32 */
+               h = round_up(h, 32);
+               /*
+                * HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+                * UYUV YUV size is (Y=(h*720) + UV=(h*(720)))
+                */
+               if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12_16L16) {
+                       pixfmt->sizeimage = h * 720 * 3 / 2;
+                       pixfmt->bytesperline = 720; /* First plane */
+               } else {
+                       pixfmt->sizeimage = h * 720 * 2;
+                       pixfmt->bytesperline = 1440; /* Packed */
+               }
+       } else {
+               pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
+               pixfmt->sizeimage = 128 * 1024;
+               pixfmt->bytesperline = 0;
+       }
+
+       pixfmt->width = w;
+       pixfmt->height = h;
+       pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       pixfmt->field = V4L2_FIELD_INTERLACED;
+       return 0;
+}
+
+static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
+                             struct v4l2_format *fmt)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       struct v4l2_subdev_format format = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
+       struct cx18_stream *s = &cx->streams[id->type];
+       int ret;
+       int w, h;
+
+       ret = cx18_try_fmt_vid_cap(file, fh, fmt);
+       if (ret)
+               return ret;
+       w = fmt->fmt.pix.width;
+       h = fmt->fmt.pix.height;
+
+       if (cx->cxhdl.width == w && cx->cxhdl.height == h &&
+           s->pixelformat == fmt->fmt.pix.pixelformat)
+               return 0;
+
+       if (atomic_read(&cx->ana_capturing) > 0)
+               return -EBUSY;
+
+       s->pixelformat = fmt->fmt.pix.pixelformat;
+       s->vb_bytes_per_frame = fmt->fmt.pix.sizeimage;
+       s->vb_bytes_per_line = fmt->fmt.pix.bytesperline;
+
+       format.format.width = cx->cxhdl.width = w;
+       format.format.height = cx->cxhdl.height = h;
+       format.format.code = MEDIA_BUS_FMT_FIXED;
+       v4l2_subdev_call(cx->sd_av, pad, set_fmt, NULL, &format);
+       return cx18_g_fmt_vid_cap(file, fh, fmt);
+}
+
 u16 cx18_service2vbi(int type)
 {
        switch (type) {
@@ -131,30 +258,6 @@ u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
        return set;
 }
 
-static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
-                               struct v4l2_format *fmt)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
-
-       pixfmt->width = cx->cxhdl.width;
-       pixfmt->height = cx->cxhdl.height;
-       pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       pixfmt->field = V4L2_FIELD_INTERLACED;
-       if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
-               pixfmt->pixelformat = s->pixelformat;
-               pixfmt->sizeimage = s->vb_bytes_per_frame;
-               pixfmt->bytesperline = s->vb_bytes_per_line;
-       } else {
-               pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
-               pixfmt->sizeimage = 128 * 1024;
-               pixfmt->bytesperline = 0;
-       }
-       return 0;
-}
-
 static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
                                struct v4l2_format *fmt)
 {
@@ -199,30 +302,6 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
        return 0;
 }
 
-static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
-                               struct v4l2_format *fmt)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       int w = fmt->fmt.pix.width;
-       int h = fmt->fmt.pix.height;
-       int min_h = 2;
-
-       w = min(w, 720);
-       w = max(w, 2);
-       if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
-               /* YUV height must be a multiple of 32 */
-               h &= ~0x1f;
-               min_h = 32;
-       }
-       h = min(h, cx->is_50hz ? 576 : 480);
-       h = max(h, min_h);
-
-       fmt->fmt.pix.width = w;
-       fmt->fmt.pix.height = h;
-       return 0;
-}
-
 static int cx18_try_fmt_vbi_cap(struct file *file, void *fh,
                                struct v4l2_format *fmt)
 {
@@ -248,49 +327,6 @@ static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh,
        return 0;
 }
 
-static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
-                               struct v4l2_format *fmt)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       struct v4l2_subdev_format format = {
-               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-       };
-       struct cx18_stream *s = &cx->streams[id->type];
-       int ret;
-       int w, h;
-
-       ret = cx18_try_fmt_vid_cap(file, fh, fmt);
-       if (ret)
-               return ret;
-       w = fmt->fmt.pix.width;
-       h = fmt->fmt.pix.height;
-
-       if (cx->cxhdl.width == w && cx->cxhdl.height == h &&
-           s->pixelformat == fmt->fmt.pix.pixelformat)
-               return 0;
-
-       if (atomic_read(&cx->ana_capturing) > 0)
-               return -EBUSY;
-
-       s->pixelformat = fmt->fmt.pix.pixelformat;
-       /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
-          UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
-       if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16) {
-               s->vb_bytes_per_frame = h * 720 * 3 / 2;
-               s->vb_bytes_per_line = 720; /* First plane */
-       } else {
-               s->vb_bytes_per_frame = h * 720 * 2;
-               s->vb_bytes_per_line = 1440; /* Packed */
-       }
-
-       format.format.width = cx->cxhdl.width = w;
-       format.format.height = cx->cxhdl.height = h;
-       format.format.code = MEDIA_BUS_FMT_FIXED;
-       v4l2_subdev_call(cx->sd_av, pad, set_fmt, NULL, &format);
-       return cx18_g_fmt_vid_cap(file, fh, fmt);
-}
-
 static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
                                struct v4l2_format *fmt)
 {
@@ -463,31 +499,17 @@ static int cx18_g_selection(struct file *file, void *fh,
 static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
                                        struct v4l2_fmtdesc *fmt)
 {
-       static const struct v4l2_fmtdesc formats[] = {
-               {
-                       .index = 0,
-                       .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                       .description = "HM12 (YUV 4:1:1)",
-                       .pixelformat = V4L2_PIX_FMT_NV12_16L16,
-               },
-               {
-                       .index = 1,
-                       .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                       .flags = V4L2_FMT_FLAG_COMPRESSED,
-                       .description = "MPEG",
-                       .pixelformat = V4L2_PIX_FMT_MPEG,
-               },
-               {
-                       .index = 2,
-                       .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                       .description = "UYVY 4:2:2",
-                       .pixelformat = V4L2_PIX_FMT_UYVY,
-               },
-       };
+       struct cx18_open_id *id = fh2id(fh);
 
-       if (fmt->index > ARRAY_SIZE(formats) - 1)
+       if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
+               if (fmt->index >= ARRAY_SIZE(cx18_formats_yuv))
+                       return -EINVAL;
+               *fmt = cx18_formats_yuv[fmt->index];
+               return 0;
+       }
+       if (fmt->index)
                return -EINVAL;
-       *fmt = formats[fmt->index];
+       *fmt = cx18_formats_mpeg[0];
        return 0;
 }
 
@@ -596,6 +618,19 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id std)
        cx2341x_handler_set_50hz(&cx->cxhdl, cx->is_50hz);
        cx->cxhdl.width = 720;
        cx->cxhdl.height = cx->is_50hz ? 576 : 480;
+       /*
+        * HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+        * UYUV YUV size is (Y=(h*720) + UV=(h*(720)))
+        */
+       if (cx->streams[CX18_ENC_STREAM_TYPE_YUV].pixelformat == V4L2_PIX_FMT_NV12_16L16) {
+               cx->streams[CX18_ENC_STREAM_TYPE_YUV].vb_bytes_per_frame =
+                       cx->cxhdl.height * 720 * 3 / 2;
+               cx->streams[CX18_ENC_STREAM_TYPE_YUV].vb_bytes_per_line = 720;
+       } else {
+               cx->streams[CX18_ENC_STREAM_TYPE_YUV].vb_bytes_per_frame =
+                       cx->cxhdl.height * 720 * 2;
+               cx->streams[CX18_ENC_STREAM_TYPE_YUV].vb_bytes_per_line = 1440;
+       }
        cx->vbi.count = cx->is_50hz ? 18 : 12;
        cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
        cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
@@ -803,117 +838,6 @@ static int cx18_g_enc_index(struct file *file, void *fh,
        return 0;
 }
 
-static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id)
-{
-       struct videobuf_queue *q = NULL;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       switch (s->vb_type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               q = &s->vbuf_q;
-               break;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               break;
-       default:
-               break;
-       }
-       return q;
-}
-
-static int cx18_streamon(struct file *file, void *priv,
-       enum v4l2_buf_type type)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       /* Start the hardware only if we're the video device */
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       if (id->type != CX18_ENC_STREAM_TYPE_YUV)
-               return -EINVAL;
-
-       /* Establish a buffer timeout */
-       mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
-
-       return videobuf_streamon(cx18_vb_queue(id));
-}
-
-static int cx18_streamoff(struct file *file, void *priv,
-       enum v4l2_buf_type type)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       /* Start the hardware only if we're the video device */
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       if (id->type != CX18_ENC_STREAM_TYPE_YUV)
-               return -EINVAL;
-
-       return videobuf_streamoff(cx18_vb_queue(id));
-}
-
-static int cx18_reqbufs(struct file *file, void *priv,
-       struct v4l2_requestbuffers *rb)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       return videobuf_reqbufs(cx18_vb_queue(id), rb);
-}
-
-static int cx18_querybuf(struct file *file, void *priv,
-       struct v4l2_buffer *b)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       return videobuf_querybuf(cx18_vb_queue(id), b);
-}
-
-static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       return videobuf_qbuf(cx18_vb_queue(id), b);
-}
-
-static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK);
-}
-
 static int cx18_encoder_cmd(struct file *file, void *fh,
                                struct v4l2_encoder_cmd *enc)
 {
@@ -930,7 +854,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
        case V4L2_ENC_CMD_STOP:
                CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
                enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
-               cx18_stop_capture(id,
+               cx18_stop_capture(&cx->streams[id->type],
                                  enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
                break;
 
@@ -1106,12 +1030,15 @@ static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
        .vidioc_s_register              = cx18_s_register,
 #endif
        .vidioc_default                 = cx18_default,
-       .vidioc_streamon                = cx18_streamon,
-       .vidioc_streamoff               = cx18_streamoff,
-       .vidioc_reqbufs                 = cx18_reqbufs,
-       .vidioc_querybuf                = cx18_querybuf,
-       .vidioc_qbuf                    = cx18_qbuf,
-       .vidioc_dqbuf                   = cx18_dqbuf,
+
+       .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
+       .vidioc_querybuf                = vb2_ioctl_querybuf,
+       .vidioc_qbuf                    = vb2_ioctl_qbuf,
+       .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
+       .vidioc_create_bufs             = vb2_ioctl_create_bufs,
+       .vidioc_streamon                = vb2_ioctl_streamon,
+       .vidioc_streamoff               = vb2_ioctl_streamoff,
+       .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
        .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
        .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
 };
index 162480ec68caf0647f769d142fd3c5885018ad48..3b283f3c672680ee947bb48222527b6d76457048 100644 (file)
@@ -145,36 +145,37 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
        }
 }
 
-static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
-       struct cx18_mdl *mdl)
+static void cx18_mdl_send_to_vb2(struct cx18_stream *s, struct cx18_mdl *mdl)
 {
-       struct cx18_videobuf_buffer *vb_buf;
+       struct cx18_vb2_buffer *vb_buf;
        struct cx18_buffer *buf;
        u8 *p;
        u32 offset = 0;
        int dispatch = 0;
+       unsigned long bsize;
 
        if (mdl->bytesused == 0)
                return;
 
-       /* Acquire a videobuf buffer, clone to and and release it */
+       /* Acquire a vb2 buffer, clone to and release it */
        spin_lock(&s->vb_lock);
        if (list_empty(&s->vb_capture))
                goto out;
 
-       vb_buf = list_first_entry(&s->vb_capture, struct cx18_videobuf_buffer,
-               vb.queue);
+       vb_buf = list_first_entry(&s->vb_capture, struct cx18_vb2_buffer,
+                                 list);
 
-       p = videobuf_to_vmalloc(&vb_buf->vb);
+       p = vb2_plane_vaddr(&vb_buf->vb.vb2_buf, 0);
        if (!p)
                goto out;
 
+       bsize = vb2_get_plane_payload(&vb_buf->vb.vb2_buf, 0);
        offset = vb_buf->bytes_used;
        list_for_each_entry(buf, &mdl->buf_list, list) {
                if (buf->bytesused == 0)
                        break;
 
-               if ((offset + buf->bytesused) <= vb_buf->vb.bsize) {
+               if ((offset + buf->bytesused) <= bsize) {
                        memcpy(p + offset, buf->buf, buf->bytesused);
                        offset += buf->bytesused;
                        vb_buf->bytes_used += buf->bytesused;
@@ -188,10 +189,10 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
        }
 
        if (dispatch) {
-               vb_buf->vb.ts = ktime_get_ns();
-               list_del(&vb_buf->vb.queue);
-               vb_buf->vb.state = VIDEOBUF_DONE;
-               wake_up(&vb_buf->vb.done);
+               vb_buf->vb.vb2_buf.timestamp = ktime_get_ns();
+               vb_buf->vb.sequence = s->sequence++;
+               list_del(&vb_buf->list);
+               vb2_buffer_done(&vb_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
        }
 
        mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
@@ -304,7 +305,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
                                cx18_enqueue(s, mdl, &s->q_full);
                        }
                } else if (s->type == CX18_ENC_STREAM_TYPE_YUV) {
-                       cx18_mdl_send_to_videobuf(s, mdl);
+                       cx18_mdl_send_to_vb2(s, mdl);
                        cx18_enqueue(s, mdl, &s->q_free);
                } else {
                        cx18_enqueue(s, mdl, &s->q_full);
index 87ff554bb2d2372db5c7a5f0e9ddbe9bcf58cc07..597472754c4c586c3282ea071f7606986f627021 100644 (file)
@@ -29,7 +29,16 @@ static const struct v4l2_file_operations cx18_v4l2_enc_fops = {
        .unlocked_ioctl = video_ioctl2,
        .release = cx18_v4l2_close,
        .poll = cx18_v4l2_enc_poll,
-       .mmap = cx18_v4l2_mmap,
+};
+
+static const struct v4l2_file_operations cx18_v4l2_enc_yuv_fops = {
+       .owner = THIS_MODULE,
+       .open = cx18_v4l2_open,
+       .unlocked_ioctl = video_ioctl2,
+       .release = cx18_v4l2_close,
+       .poll = vb2_fop_poll,
+       .read = vb2_fop_read,
+       .mmap = vb2_fop_mmap,
 };
 
 /* offset from 0 to register ts v4l2 minors on */
@@ -70,7 +79,7 @@ static struct {
                VFL_TYPE_VBI, 0,
                DMA_FROM_DEVICE,
                V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE |
-               V4L2_CAP_READWRITE | V4L2_CAP_TUNER
+               V4L2_CAP_READWRITE | V4L2_CAP_AUDIO | V4L2_CAP_TUNER
        },
        {       /* CX18_ENC_STREAM_TYPE_PCM */
                "encoder PCM audio",
@@ -91,156 +100,142 @@ static struct {
        },
 };
 
-
-static void cx18_dma_free(struct videobuf_queue *q,
-       struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
-{
-       videobuf_waiton(q, &buf->vb, 0, 0);
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int cx18_prepare_buffer(struct videobuf_queue *q,
-       struct cx18_stream *s,
-       struct cx18_videobuf_buffer *buf,
-       u32 pixelformat,
-       unsigned int width, unsigned int height,
-       enum v4l2_field field)
+static int cx18_queue_setup(struct vb2_queue *vq,
+                           unsigned int *nbuffers, unsigned int *nplanes,
+                           unsigned int sizes[], struct device *alloc_devs[])
 {
+       struct cx18_stream *s = vb2_get_drv_priv(vq);
        struct cx18 *cx = s->cx;
-       int rc = 0;
-
-       /* check settings */
-       buf->bytes_used = 0;
-
-       if ((width  < 48) || (height < 32))
-               return -EINVAL;
-
-       buf->vb.size = (width * height * 2);
-       if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
-               return -EINVAL;
+       unsigned int szimage;
 
-       /* alloc + fill struct (if changed) */
-       if (buf->vb.width != width || buf->vb.height != height ||
-           buf->vb.field != field || s->pixelformat != pixelformat ||
-           buf->tvnorm != cx->std) {
+       /*
+        * HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+        * UYUV YUV size is (Y=(h*720) + UV=(h*(720)))
+        */
+       if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16)
+               szimage = cx->cxhdl.height * 720 * 3 / 2;
+       else
+               szimage = cx->cxhdl.height * 720 * 2;
 
-               buf->vb.width  = width;
-               buf->vb.height = height;
-               buf->vb.field  = field;
-               buf->tvnorm    = cx->std;
-               s->pixelformat = pixelformat;
+       /*
+        * Let's request at least three buffers: two for the
+        * DMA engine and one for userspace.
+        */
+       if (vq->num_buffers + *nbuffers < 3)
+               *nbuffers = 3 - vq->num_buffers;
 
-               /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
-                  UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
-               if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16)
-                       s->vb_bytes_per_frame = height * 720 * 3 / 2;
-               else
-                       s->vb_bytes_per_frame = height * 720 * 2;
-               cx18_dma_free(q, s, buf);
+       if (*nplanes) {
+               if (*nplanes != 1 || sizes[0] < szimage)
+                       return -EINVAL;
+               return 0;
        }
 
-       if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
-               return -EINVAL;
-
-       if (buf->vb.field == 0)
-               buf->vb.field = V4L2_FIELD_INTERLACED;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               buf->vb.width  = width;
-               buf->vb.height = height;
-               buf->vb.field  = field;
-               buf->tvnorm    = cx->std;
-               s->pixelformat = pixelformat;
-
-               /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
-                  UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
-               if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16)
-                       s->vb_bytes_per_frame = height * 720 * 3 / 2;
-               else
-                       s->vb_bytes_per_frame = height * 720 * 2;
-               rc = videobuf_iolock(q, &buf->vb, NULL);
-               if (rc != 0)
-                       goto fail;
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
+       sizes[0] = szimage;
+       *nplanes = 1;
        return 0;
-
-fail:
-       cx18_dma_free(q, s, buf);
-       return rc;
-
 }
 
-/* VB_MIN_BUFSIZE is lcm(1440 * 480, 1440 * 576)
-   1440 is a single line of 4:2:2 YUV at 720 luma samples wide
-*/
-#define VB_MIN_BUFFERS 32
-#define VB_MIN_BUFSIZE 4147200
+static void cx18_buf_queue(struct vb2_buffer *vb)
+{
+       struct cx18_stream *s = vb2_get_drv_priv(vb->vb2_queue);
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct cx18_vb2_buffer *buf =
+               container_of(vbuf, struct cx18_vb2_buffer, vb);
+       unsigned long flags;
+
+       spin_lock_irqsave(&s->vb_lock, flags);
+       list_add_tail(&buf->list, &s->vb_capture);
+       spin_unlock_irqrestore(&s->vb_lock, flags);
+}
 
-static int buffer_setup(struct videobuf_queue *q,
-       unsigned int *count, unsigned int *size)
+static int cx18_buf_prepare(struct vb2_buffer *vb)
 {
-       struct cx18_stream *s = q->priv_data;
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct cx18_stream *s = vb2_get_drv_priv(vb->vb2_queue);
        struct cx18 *cx = s->cx;
+       unsigned int size;
 
-       *size = 2 * cx->cxhdl.width * cx->cxhdl.height;
-       if (*count == 0)
-               *count = VB_MIN_BUFFERS;
-
-       while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE)
-               (*count)--;
-
-       q->field = V4L2_FIELD_INTERLACED;
-       q->last = V4L2_FIELD_INTERLACED;
+       /*
+        * HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+        * UYUV YUV size is (Y=(h*720) + UV=(h*(720)))
+        */
+       if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16)
+               size = cx->cxhdl.height * 720 * 3 / 2;
+       else
+               size = cx->cxhdl.height * 720 * 2;
 
+       if (vb2_plane_size(vb, 0) < size)
+               return -EINVAL;
+       vb2_set_plane_payload(vb, 0, size);
+       vbuf->field = V4L2_FIELD_INTERLACED;
        return 0;
 }
 
-static int buffer_prepare(struct videobuf_queue *q,
-       struct videobuf_buffer *vb,
-       enum v4l2_field field)
+void cx18_clear_queue(struct cx18_stream *s, enum vb2_buffer_state state)
 {
-       struct cx18_videobuf_buffer *buf =
-               container_of(vb, struct cx18_videobuf_buffer, vb);
-       struct cx18_stream *s = q->priv_data;
-       struct cx18 *cx = s->cx;
+       while (!list_empty(&s->vb_capture)) {
+               struct cx18_vb2_buffer *buf;
 
-       return cx18_prepare_buffer(q, s, buf, s->pixelformat,
-               cx->cxhdl.width, cx->cxhdl.height, field);
+               buf = list_first_entry(&s->vb_capture,
+                                      struct cx18_vb2_buffer, list);
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb.vb2_buf, state);
+       }
 }
 
-static void buffer_release(struct videobuf_queue *q,
-       struct videobuf_buffer *vb)
+static int cx18_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
-       struct cx18_videobuf_buffer *buf =
-               container_of(vb, struct cx18_videobuf_buffer, vb);
-       struct cx18_stream *s = q->priv_data;
+       struct v4l2_fh *owner = vq->owner;
+       struct cx18_stream *s = vb2_get_drv_priv(vq);
+       unsigned long flags;
+       int rc;
+
+       if (WARN_ON(!owner)) {
+               rc = -EIO;
+               goto clear_queue;
+       }
 
-       cx18_dma_free(q, s, buf);
+       s->sequence = 0;
+       rc = cx18_start_capture(fh2id(owner));
+       if (!rc) {
+               /* Establish a buffer timeout */
+               mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
+               return 0;
+       }
+
+clear_queue:
+       spin_lock_irqsave(&s->vb_lock, flags);
+       cx18_clear_queue(s, VB2_BUF_STATE_QUEUED);
+       spin_unlock_irqrestore(&s->vb_lock, flags);
+       return rc;
 }
 
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static void cx18_stop_streaming(struct vb2_queue *vq)
 {
-       struct cx18_videobuf_buffer *buf =
-               container_of(vb, struct cx18_videobuf_buffer, vb);
-       struct cx18_stream *s = q->priv_data;
-
-       buf->vb.state = VIDEOBUF_QUEUED;
-
-       list_add_tail(&buf->vb.queue, &s->vb_capture);
+       struct cx18_stream *s = vb2_get_drv_priv(vq);
+       unsigned long flags;
+
+       cx18_stop_capture(s, 0);
+       timer_delete_sync(&s->vb_timeout);
+       spin_lock_irqsave(&s->vb_lock, flags);
+       cx18_clear_queue(s, VB2_BUF_STATE_ERROR);
+       spin_unlock_irqrestore(&s->vb_lock, flags);
 }
 
-static const struct videobuf_queue_ops cx18_videobuf_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
+static const struct vb2_ops cx18_vb2_qops = {
+       .queue_setup            = cx18_queue_setup,
+       .buf_queue              = cx18_buf_queue,
+       .buf_prepare            = cx18_buf_prepare,
+       .start_streaming        = cx18_start_streaming,
+       .stop_streaming         = cx18_stop_streaming,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
 };
 
-static void cx18_stream_init(struct cx18 *cx, int type)
+static int cx18_stream_init(struct cx18 *cx, int type)
 {
        struct cx18_stream *s = &cx->streams[type];
+       int err = 0;
 
        memset(s, 0, sizeof(*s));
 
@@ -275,22 +270,33 @@ static void cx18_stream_init(struct cx18 *cx, int type)
        INIT_LIST_HEAD(&s->vb_capture);
        timer_setup(&s->vb_timeout, cx18_vb_timeout, 0);
        spin_lock_init(&s->vb_lock);
-       if (type == CX18_ENC_STREAM_TYPE_YUV) {
-               spin_lock_init(&s->vbuf_q_lock);
 
+       if (type == CX18_ENC_STREAM_TYPE_YUV) {
                s->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               videobuf_queue_vmalloc_init(&s->vbuf_q, &cx18_videobuf_qops,
-                       &cx->pci_dev->dev, &s->vbuf_q_lock,
-                       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                       V4L2_FIELD_INTERLACED,
-                       sizeof(struct cx18_videobuf_buffer),
-                       s, &cx->serialize_lock);
 
                /* Assume the previous pixel default */
                s->pixelformat = V4L2_PIX_FMT_NV12_16L16;
                s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
                s->vb_bytes_per_line = 720;
+
+               s->vidq.io_modes = VB2_READ | VB2_MMAP | VB2_DMABUF;
+               s->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               s->vidq.drv_priv = s;
+               s->vidq.buf_struct_size = sizeof(struct cx18_vb2_buffer);
+               s->vidq.ops = &cx18_vb2_qops;
+               s->vidq.mem_ops = &vb2_vmalloc_memops;
+               s->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+               s->vidq.min_buffers_needed = 2;
+               s->vidq.gfp_flags = GFP_DMA32;
+               s->vidq.dev = &cx->pci_dev->dev;
+               s->vidq.lock = &cx->serialize_lock;
+
+               err = vb2_queue_init(&s->vidq);
+               if (err)
+                       v4l2_err(&cx->v4l2_dev, "cannot init vb2 queue\n");
+               s->video_dev.queue = &s->vidq;
        }
+       return err;
 }
 
 static int cx18_prep_dev(struct cx18 *cx, int type)
@@ -299,6 +305,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
        u32 cap = cx->v4l2_cap;
        int num_offset = cx18_stream_info[type].num_offset;
        int num = cx->instance + cx18_first_minor + num_offset;
+       int err;
 
        /*
         * These five fields are always initialized.
@@ -330,7 +337,9 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
                return 0;
        }
 
-       cx18_stream_init(cx, type);
+       err = cx18_stream_init(cx, type);
+       if (err)
+               return err;
 
        /* Allocate the cx18_dvb struct only for the TS on cards with DTV */
        if (type == CX18_ENC_STREAM_TYPE_TS) {
@@ -356,7 +365,10 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
 
        s->video_dev.num = num;
        s->video_dev.v4l2_dev = &cx->v4l2_dev;
-       s->video_dev.fops = &cx18_v4l2_enc_fops;
+       if (type == CX18_ENC_STREAM_TYPE_YUV)
+               s->video_dev.fops = &cx18_v4l2_enc_yuv_fops;
+       else
+               s->video_dev.fops = &cx18_v4l2_enc_fops;
        s->video_dev.release = video_device_release_empty;
        if (cx->card->video_inputs->video_type == CX18_CARD_INPUT_VID_TUNER)
                s->video_dev.tvnorms = cx->tuner_std;
@@ -525,12 +537,12 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
                if (vdev->v4l2_dev == NULL)
                        continue;
 
-               if (type == CX18_ENC_STREAM_TYPE_YUV)
-                       videobuf_mmap_free(&cx->streams[type].vbuf_q);
-
                cx18_stream_free(&cx->streams[type]);
 
-               video_unregister_device(vdev);
+               if (type == CX18_ENC_STREAM_TYPE_YUV)
+                       vb2_video_unregister_device(vdev);
+               else
+                       video_unregister_device(vdev);
        }
 }
 
index 9232a966bcabb2f8b7ec1b472cd59c5ee67a4364..2ce2914576cf2adaf227f7cf9f19f559ee6e0c50 100644 (file)
@@ -1325,7 +1325,9 @@ void cx23885_free_buffer(struct cx23885_dev *dev, struct cx23885_buffer *buf)
 {
        struct cx23885_riscmem *risc = &buf->risc;
 
-       dma_free_coherent(&dev->pci->dev, risc->size, risc->cpu, risc->dma);
+       if (risc->cpu)
+               dma_free_coherent(&dev->pci->dev, risc->size, risc->cpu, risc->dma);
+       memset(risc, 0, sizeof(*risc));
 }
 
 static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
index 3d03f5e95786a9cd1df7d76d4353c719af6c5d49..671fc0588e431bcfdcfb209d68ce093355886e84 100644 (file)
@@ -342,6 +342,7 @@ static int queue_setup(struct vb2_queue *q,
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+       int ret;
        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
        struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
        struct cx23885_buffer *buf =
@@ -358,12 +359,12 @@ static int buffer_prepare(struct vb2_buffer *vb)
 
        switch (dev->field) {
        case V4L2_FIELD_TOP:
-               cx23885_risc_buffer(dev->pci, &buf->risc,
+               ret = cx23885_risc_buffer(dev->pci, &buf->risc,
                                sgt->sgl, 0, UNSET,
                                buf->bpl, 0, dev->height);
                break;
        case V4L2_FIELD_BOTTOM:
-               cx23885_risc_buffer(dev->pci, &buf->risc,
+               ret = cx23885_risc_buffer(dev->pci, &buf->risc,
                                sgt->sgl, UNSET, 0,
                                buf->bpl, 0, dev->height);
                break;
@@ -391,21 +392,21 @@ static int buffer_prepare(struct vb2_buffer *vb)
                        line0_offset = 0;
                        line1_offset = buf->bpl;
                }
-               cx23885_risc_buffer(dev->pci, &buf->risc,
+               ret = cx23885_risc_buffer(dev->pci, &buf->risc,
                                sgt->sgl, line0_offset,
                                line1_offset,
                                buf->bpl, buf->bpl,
                                dev->height >> 1);
                break;
        case V4L2_FIELD_SEQ_TB:
-               cx23885_risc_buffer(dev->pci, &buf->risc,
+               ret = cx23885_risc_buffer(dev->pci, &buf->risc,
                                sgt->sgl,
                                0, buf->bpl * (dev->height >> 1),
                                buf->bpl, 0,
                                dev->height >> 1);
                break;
        case V4L2_FIELD_SEQ_BT:
-               cx23885_risc_buffer(dev->pci, &buf->risc,
+               ret = cx23885_risc_buffer(dev->pci, &buf->risc,
                                sgt->sgl,
                                buf->bpl * (dev->height >> 1), 0,
                                buf->bpl, 0,
@@ -418,7 +419,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
                buf, buf->vb.vb2_buf.index,
                dev->width, dev->height, dev->fmt->depth, dev->fmt->fourcc,
                (unsigned long)buf->risc.dma);
-       return 0;
+       return ret;
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
index 4ac645a56c14eb35ce7609752cbe9dad89383dc9..9e9c7c071acccefa29295549f244f560c88b6a5a 100644 (file)
@@ -1176,6 +1176,7 @@ static void dm1105_remove(struct pci_dev *pdev)
        struct dvb_demux *dvbdemux = &dev->demux;
        struct dmx_demux *dmx = &dvbdemux->dmx;
 
+       cancel_work_sync(&dev->ir.work);
        dm1105_ir_exit(dev);
        dmx->close(dmx);
        dvb_net_release(&dev->dvbnet);
index dfefe0d8aa959e432af958649bdaf33b07ba9ddc..3c2accfe545510ba583ccf4a0219ac2b27586345 100644 (file)
@@ -29,6 +29,14 @@ static const struct cio2_sensor_config cio2_supported_sensors[] = {
        CIO2_SENSOR_CONFIG("INT347E", 1, 319200000),
        /* Omnivision OV2680 */
        CIO2_SENSOR_CONFIG("OVTI2680", 0),
+       /* Omnivision ov8856 */
+       CIO2_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000),
+       /* Omnivision ov2740 */
+       CIO2_SENSOR_CONFIG("INT3474", 1, 360000000),
+       /* Hynix hi556 */
+       CIO2_SENSOR_CONFIG("INT3537", 1, 437000000),
+       /* Omnivision ov13b10 */
+       CIO2_SENSOR_CONFIG("OVTIDB10", 1, 560000000),
 };
 
 static const struct cio2_property_names prop_names = {
@@ -212,6 +220,7 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
                                                  struct cio2_sensor *sensor)
 {
        struct software_node *nodes = sensor->swnodes;
+       char vcm_name[ACPI_ID_LEN + 4];
 
        cio2_bridge_init_swnode_names(sensor);
 
@@ -229,9 +238,13 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
                                                sensor->node_names.endpoint,
                                                &nodes[SWNODE_CIO2_PORT],
                                                sensor->cio2_properties);
-       if (sensor->ssdb.vcmtype)
-               nodes[SWNODE_VCM] =
-                       NODE_VCM(cio2_vcm_types[sensor->ssdb.vcmtype - 1]);
+       if (sensor->ssdb.vcmtype) {
+               /* append ssdb.link to distinguish VCM nodes with same HID */
+               snprintf(vcm_name, sizeof(vcm_name), "%s-%u",
+                        cio2_vcm_types[sensor->ssdb.vcmtype - 1],
+                        sensor->ssdb.link);
+               nodes[SWNODE_VCM] = NODE_VCM(vcm_name);
+       }
 
        cio2_bridge_init_swnode_group(sensor);
 }
@@ -295,7 +308,6 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
                }
 
                sensor = &bridge->sensors[bridge->n_sensors];
-               strscpy(sensor->name, cfg->hid, sizeof(sensor->name));
 
                ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
                                                   &sensor->ssdb,
@@ -303,6 +315,9 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
                if (ret)
                        goto err_put_adev;
 
+               snprintf(sensor->name, sizeof(sensor->name), "%s-%u",
+                        cfg->hid, sensor->ssdb.link);
+
                if (sensor->ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) {
                        dev_warn(&adev->dev, "Unknown VCM type %d\n",
                                 sensor->ssdb.vcmtype);
index b93b749c65bda33b27bb3e8a532baa7f9cfd6359..b76ed8a641e2017de3b506327746b10dc2501fca 100644 (file)
@@ -113,7 +113,8 @@ struct cio2_sensor_config {
 };
 
 struct cio2_sensor {
-       char name[ACPI_ID_LEN];
+       /* append ssdb.link(u8) in "-%u" format as suffix of HID */
+       char name[ACPI_ID_LEN + 4];
        struct acpi_device *adev;
        struct i2c_client *vcm_i2c_client;
 
index 3b76a9d0383a86aaadbe420c28d58f01b5fc04af..3c84cb12163207a076fff56de7813485ca48fb71 100644 (file)
@@ -1305,6 +1305,7 @@ static int cio2_subdev_link_validate_get_format(struct media_pad *pad,
                struct v4l2_subdev *sd =
                        media_entity_to_v4l2_subdev(pad->entity);
 
+               memset(fmt, 0, sizeof(*fmt));
                fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
                fmt->pad = pad->index;
                return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
index 99be59af356057d1c22645489a0e4ca6939ca917..1280696f65f26ba083dc5519a9ede2d959eb4fc7 100644 (file)
@@ -2116,7 +2116,6 @@ struct saa7134_board saa7134_boards[] = {
                - Remote control doesn't initialize properly.
                - Audio volume starts muted,
                then gradually increases after channel change.
-               - Overlay scaling problems (application error?)
                - Composite S-Video untested.
                From: Konrad Rzepecki <hannibal@megapolis.pl>
                */
index cf2871306987ca1550477c63a3e206ee4bc5f11d..ea0585e43abb900ad124728393fdedb06ee8fc44 100644 (file)
@@ -51,10 +51,6 @@ static unsigned int latency = UNSET;
 module_param(latency, int, 0444);
 MODULE_PARM_DESC(latency,"pci latency timer");
 
-int saa7134_no_overlay=-1;
-module_param_named(no_overlay, saa7134_no_overlay, int, 0444);
-MODULE_PARM_DESC(no_overlay, "allow override overlay default (0 disables, 1 enables) [some VIA/SIS chipsets are known to have problem with overlay]");
-
 bool saa7134_userptr;
 module_param(saa7134_userptr, bool, 0644);
 MODULE_PARM_DESC(saa7134_userptr, "enable page-aligned userptr support");
@@ -400,13 +396,6 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
                        SAA7134_MAIN_CTRL_TE5;
        }
 
-       /* screen overlay -- dma 0 + video task B */
-       if (dev->ovenable) {
-               task |= 0x10;
-               ctrl |= SAA7134_MAIN_CTRL_TE1;
-               ov = dev->ovfield;
-       }
-
        /* vbi capture -- dma 0 + vbi task A+B */
        if (dev->vbi_q.curr) {
                task |= 0x22;
@@ -1066,18 +1055,6 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
                        latency = 0x0A;
                }
 #endif
-               if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) {
-                       pr_info("%s: quirk: this driver and your chipset may not work together in overlay mode.\n",
-                               dev->name);
-                       if (!saa7134_no_overlay) {
-                               pr_info("%s: quirk: overlay mode will be disabled.\n",
-                                               dev->name);
-                               saa7134_no_overlay = 1;
-                       } else {
-                               pr_info("%s: quirk: overlay mode will be forced. Use this option at your own risk.\n",
-                                               dev->name);
-                       }
-               }
        }
        if (UNSET != latency) {
                pr_info("%s: setting pci latency timer to %d\n",
@@ -1198,9 +1175,6 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
                saa_call_all(dev, core, s_power, 0);
 
        /* register v4l devices */
-       if (saa7134_no_overlay > 0)
-               pr_info("%s: Overlay support disabled.\n", dev->name);
-
        dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
        dev->video_dev->ctrl_handler = &dev->ctrl_handler;
        dev->video_dev->lock = &dev->lock;
@@ -1210,9 +1184,6 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
        if (dev->tuner_type != TUNER_ABSENT && dev->tuner_type != UNSET)
                dev->video_dev->device_caps |= V4L2_CAP_TUNER;
 
-       if (saa7134_no_overlay <= 0)
-               dev->video_dev->device_caps |= V4L2_CAP_VIDEO_OVERLAY;
-
        err = video_register_device(dev->video_dev,VFL_TYPE_VIDEO,
                                    video_nr[dev->nr]);
        if (err < 0) {
@@ -1403,9 +1374,6 @@ static int __maybe_unused saa7134_suspend(struct device *dev_d)
        struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
        struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
 
-       /* disable overlay - apps should enable it explicitly on resume*/
-       dev->ovenable = 0;
-
        /* Disable interrupts, DMA, and rest of the chip*/
        saa_writel(SAA7134_IRQ1, 0);
        saa_writel(SAA7134_IRQ2, 0);
index aafbb34765b066b7572b02e7a9dbe094bc7f7230..434fa1ee1c33c9756a9ed6d23a8ff7b2e7b177d9 100644 (file)
@@ -139,8 +139,8 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
        struct saa7134_dev *dev = video_drvdata(file);
        struct v4l2_subdev_pad_config pad_cfg;
        struct v4l2_subdev_state pad_state = {
-               .pads = &pad_cfg
-               };
+               .pads = &pad_cfg,
+       };
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
index 6a5053126237f455da079a4fa1ef5a2bc42286c2..437dbe5e75e2975a370a99f14f9aeb9fb5658b96 100644 (file)
@@ -300,6 +300,7 @@ int saa7134_ts_start(struct saa7134_dev *dev)
 
 int saa7134_ts_fini(struct saa7134_dev *dev)
 {
+       del_timer_sync(&dev->ts_q.timeout);
        saa7134_pgtable_free(dev->pci, &dev->ts_q.pt);
        return 0;
 }
index 3f0b0933eed69e9bbffbcc5f822d95b775191965..3e773690468bdb935d0a2ada46ef9a7f9da23e8d 100644 (file)
@@ -185,6 +185,7 @@ int saa7134_vbi_init1(struct saa7134_dev *dev)
 int saa7134_vbi_fini(struct saa7134_dev *dev)
 {
        /* nothing */
+       del_timer_sync(&dev->vbi_q.timeout);
        return 0;
 }
 
index 4d8974c9fcc984d7fb64e6f5facc4c692918453a..56b4481a40e6125fa8534a85e56031186a190e8e 100644 (file)
@@ -571,193 +571,6 @@ static void set_size(struct saa7134_dev *dev, int task,
 
 /* ------------------------------------------------------------------ */
 
-struct cliplist {
-       __u16 position;
-       __u8  enable;
-       __u8  disable;
-};
-
-static void set_cliplist(struct saa7134_dev *dev, int reg,
-                       struct cliplist *cl, int entries, char *name)
-{
-       __u8 winbits = 0;
-       int i;
-
-       for (i = 0; i < entries; i++) {
-               winbits |= cl[i].enable;
-               winbits &= ~cl[i].disable;
-               if (i < 15 && cl[i].position == cl[i+1].position)
-                       continue;
-               saa_writeb(reg + 0, winbits);
-               saa_writeb(reg + 2, cl[i].position & 0xff);
-               saa_writeb(reg + 3, cl[i].position >> 8);
-               video_dbg("clip: %s winbits=%02x pos=%d\n",
-                       name,winbits,cl[i].position);
-               reg += 8;
-       }
-       for (; reg < 0x400; reg += 8) {
-               saa_writeb(reg+ 0, 0);
-               saa_writeb(reg + 1, 0);
-               saa_writeb(reg + 2, 0);
-               saa_writeb(reg + 3, 0);
-       }
-}
-
-static int clip_range(int val)
-{
-       if (val < 0)
-               val = 0;
-       return val;
-}
-
-/* Sort into smallest position first order */
-static int cliplist_cmp(const void *a, const void *b)
-{
-       const struct cliplist *cla = a;
-       const struct cliplist *clb = b;
-       if (cla->position < clb->position)
-               return -1;
-       if (cla->position > clb->position)
-               return 1;
-       return 0;
-}
-
-static int setup_clipping(struct saa7134_dev *dev, struct v4l2_clip *clips,
-                         int nclips, int interlace)
-{
-       struct cliplist col[16], row[16];
-       int cols = 0, rows = 0, i;
-       int div = interlace ? 2 : 1;
-
-       memset(col, 0, sizeof(col));
-       memset(row, 0, sizeof(row));
-       for (i = 0; i < nclips && i < 8; i++) {
-               col[cols].position = clip_range(clips[i].c.left);
-               col[cols].enable   = (1 << i);
-               cols++;
-               col[cols].position = clip_range(clips[i].c.left+clips[i].c.width);
-               col[cols].disable  = (1 << i);
-               cols++;
-               row[rows].position = clip_range(clips[i].c.top / div);
-               row[rows].enable   = (1 << i);
-               rows++;
-               row[rows].position = clip_range((clips[i].c.top + clips[i].c.height)
-                                               / div);
-               row[rows].disable  = (1 << i);
-               rows++;
-       }
-       sort(col, cols, sizeof col[0], cliplist_cmp, NULL);
-       sort(row, rows, sizeof row[0], cliplist_cmp, NULL);
-       set_cliplist(dev,0x380,col,cols,"cols");
-       set_cliplist(dev,0x384,row,rows,"rows");
-       return 0;
-}
-
-static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win, bool try)
-{
-       enum v4l2_field field;
-       int maxw, maxh;
-
-       if (!try && (dev->ovbuf.base == NULL || dev->ovfmt == NULL))
-               return -EINVAL;
-       if (win->w.width < 48)
-               win->w.width = 48;
-       if (win->w.height < 32)
-               win->w.height = 32;
-       if (win->clipcount > 8)
-               win->clipcount = 8;
-
-       win->chromakey = 0;
-       win->global_alpha = 0;
-       field = win->field;
-       maxw  = dev->crop_current.width;
-       maxh  = dev->crop_current.height;
-
-       if (V4L2_FIELD_ANY == field) {
-               field = (win->w.height > maxh/2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_TOP;
-       }
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-               maxh = maxh / 2;
-               break;
-       default:
-               field = V4L2_FIELD_INTERLACED;
-               break;
-       }
-
-       win->field = field;
-       if (win->w.width > maxw)
-               win->w.width = maxw;
-       if (win->w.height > maxh)
-               win->w.height = maxh;
-       return 0;
-}
-
-static int start_preview(struct saa7134_dev *dev)
-{
-       unsigned long base,control,bpl;
-       int err;
-
-       err = verify_preview(dev, &dev->win, false);
-       if (0 != err)
-               return err;
-
-       dev->ovfield = dev->win.field;
-       video_dbg("%s %dx%d+%d+%d 0x%08x field=%s\n", __func__,
-                 dev->win.w.width, dev->win.w.height,
-                 dev->win.w.left, dev->win.w.top,
-                 dev->ovfmt->fourcc, v4l2_field_names[dev->ovfield]);
-
-       /* setup window + clipping */
-       set_size(dev, TASK_B, dev->win.w.width, dev->win.w.height,
-                V4L2_FIELD_HAS_BOTH(dev->ovfield));
-       setup_clipping(dev, dev->clips, dev->nclips,
-                      V4L2_FIELD_HAS_BOTH(dev->ovfield));
-       if (dev->ovfmt->yuv)
-               saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x03);
-       else
-               saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x01);
-       saa_writeb(SAA7134_OFMT_VIDEO_B, dev->ovfmt->pm | 0x20);
-
-       /* dma: setup channel 1 (= Video Task B) */
-       base  = (unsigned long)dev->ovbuf.base;
-       base += dev->ovbuf.fmt.bytesperline * dev->win.w.top;
-       base += dev->ovfmt->depth/8         * dev->win.w.left;
-       bpl   = dev->ovbuf.fmt.bytesperline;
-       control = SAA7134_RS_CONTROL_BURST_16;
-       if (dev->ovfmt->bswap)
-               control |= SAA7134_RS_CONTROL_BSWAP;
-       if (dev->ovfmt->wswap)
-               control |= SAA7134_RS_CONTROL_WSWAP;
-       if (V4L2_FIELD_HAS_BOTH(dev->ovfield)) {
-               saa_writel(SAA7134_RS_BA1(1),base);
-               saa_writel(SAA7134_RS_BA2(1),base+bpl);
-               saa_writel(SAA7134_RS_PITCH(1),bpl*2);
-               saa_writel(SAA7134_RS_CONTROL(1),control);
-       } else {
-               saa_writel(SAA7134_RS_BA1(1),base);
-               saa_writel(SAA7134_RS_BA2(1),base);
-               saa_writel(SAA7134_RS_PITCH(1),bpl);
-               saa_writel(SAA7134_RS_CONTROL(1),control);
-       }
-
-       /* start dma */
-       dev->ovenable = 1;
-       saa7134_set_dmabits(dev);
-
-       return 0;
-}
-
-static int stop_preview(struct saa7134_dev *dev)
-{
-       dev->ovenable = 0;
-       saa7134_set_dmabits(dev);
-       return 0;
-}
-
 /*
  * Media Controller helper functions
  */
@@ -1042,8 +855,6 @@ static const struct vb2_ops vb2_qops = {
 static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct saa7134_dev *dev = container_of(ctrl->handler, struct saa7134_dev, ctrl_handler);
-       unsigned long flags;
-       int restart_overlay = 0;
 
        switch (ctrl->id) {
        case V4L2_CID_BRIGHTNESS:
@@ -1081,15 +892,12 @@ static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl)
                break;
        case V4L2_CID_HFLIP:
                dev->ctl_mirror = ctrl->val;
-               restart_overlay = 1;
                break;
        case V4L2_CID_PRIVATE_Y_EVEN:
                dev->ctl_y_even = ctrl->val;
-               restart_overlay = 1;
                break;
        case V4L2_CID_PRIVATE_Y_ODD:
                dev->ctl_y_odd = ctrl->val;
-               restart_overlay = 1;
                break;
        case V4L2_CID_PRIVATE_AUTOMUTE:
        {
@@ -1112,12 +920,6 @@ static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl)
        default:
                return -EINVAL;
        }
-       if (restart_overlay && dev->overlay_owner) {
-               spin_lock_irqsave(&dev->slock, flags);
-               stop_preview(dev);
-               start_preview(dev);
-               spin_unlock_irqrestore(&dev->slock, flags);
-       }
        return 0;
 }
 
@@ -1150,21 +952,11 @@ static int video_release(struct file *file)
 {
        struct video_device *vdev = video_devdata(file);
        struct saa7134_dev *dev = video_drvdata(file);
-       struct v4l2_fh *fh = file->private_data;
        struct saa6588_command cmd;
-       unsigned long flags;
 
        mutex_lock(&dev->lock);
        saa7134_tvaudio_close(dev);
 
-       /* turn off overlay */
-       if (fh == dev->overlay_owner) {
-               spin_lock_irqsave(&dev->slock,flags);
-               stop_preview(dev);
-               spin_unlock_irqrestore(&dev->slock,flags);
-               dev->overlay_owner = NULL;
-       }
-
        if (vdev->vfl_type == VFL_TYPE_RADIO)
                v4l2_fh_release(file);
        else
@@ -1261,34 +1053,6 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7134_dev *dev = video_drvdata(file);
-       u32 clipcount = f->fmt.win.clipcount;
-       int i;
-
-       if (saa7134_no_overlay > 0) {
-               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-       f->fmt.win = dev->win;
-       if (!f->fmt.win.clips) {
-               f->fmt.win.clipcount = 0;
-               return 0;
-       }
-       if (dev->nclips < clipcount)
-               clipcount = dev->nclips;
-       f->fmt.win.clipcount = clipcount;
-
-       for (i = 0; i < clipcount; i++) {
-               memcpy(&f->fmt.win.clips[i].c, &dev->clips[i].c,
-                      sizeof(struct v4l2_rect));
-       }
-
-       return 0;
-}
-
 static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
                                                struct v4l2_format *f)
 {
@@ -1342,21 +1106,6 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
-                                               struct v4l2_format *f)
-{
-       struct saa7134_dev *dev = video_drvdata(file);
-
-       if (saa7134_no_overlay > 0) {
-               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-
-       if (f->fmt.win.clips == NULL)
-               f->fmt.win.clipcount = 0;
-       return verify_preview(dev, &f->fmt.win, true);
-}
-
 static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
@@ -1374,39 +1123,6 @@ static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct saa7134_dev *dev = video_drvdata(file);
-       int err;
-       unsigned long flags;
-
-       if (saa7134_no_overlay > 0) {
-               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-       if (f->fmt.win.clips == NULL)
-               f->fmt.win.clipcount = 0;
-       err = verify_preview(dev, &f->fmt.win, true);
-       if (0 != err)
-               return err;
-
-       dev->win    = f->fmt.win;
-       dev->nclips = f->fmt.win.clipcount;
-
-       memcpy(dev->clips, f->fmt.win.clips,
-              sizeof(struct v4l2_clip) * dev->nclips);
-
-       if (priv == dev->overlay_owner) {
-               spin_lock_irqsave(&dev->slock, flags);
-               stop_preview(dev);
-               start_preview(dev);
-               spin_unlock_irqrestore(&dev->slock, flags);
-       }
-
-       return 0;
-}
-
 int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i)
 {
        struct saa7134_dev *dev = video_drvdata(file);
@@ -1482,8 +1198,6 @@ int saa7134_querycap(struct file *file, void *priv,
                cap->capabilities |= V4L2_CAP_TUNER;
        if (dev->has_rds)
                cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
-       if (saa7134_no_overlay <= 0)
-               cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
 
        return 0;
 }
@@ -1492,17 +1206,9 @@ EXPORT_SYMBOL_GPL(saa7134_querycap);
 int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
        struct saa7134_dev *dev = video_drvdata(file);
-       struct v4l2_fh *fh = priv;
-       unsigned long flags;
        unsigned int i;
        v4l2_std_id fixup;
 
-       if (is_empress(file) && dev->overlay_owner) {
-               /* Don't change the std from the mpeg device
-                  if overlay is active. */
-               return -EBUSY;
-       }
-
        for (i = 0; i < TVNORMS; i++)
                if (id == tvnorms[i].id)
                        break;
@@ -1534,18 +1240,7 @@ int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)
                        return -EINVAL;
        }
 
-       if (!is_empress(file) && fh == dev->overlay_owner) {
-               spin_lock_irqsave(&dev->slock, flags);
-               stop_preview(dev);
-               spin_unlock_irqrestore(&dev->slock, flags);
-
-               set_tvnorm(dev, &tvnorms[i]);
-
-               spin_lock_irqsave(&dev->slock, flags);
-               start_preview(dev);
-               spin_unlock_irqrestore(&dev->slock, flags);
-       } else
-               set_tvnorm(dev, &tvnorms[i]);
+       set_tvnorm(dev, &tvnorms[i]);
 
        saa7134_tvaudio_do_scan(dev);
        return 0;
@@ -1595,8 +1290,7 @@ static int saa7134_g_pixelaspect(struct file *file, void *priv,
 {
        struct saa7134_dev *dev = video_drvdata(file);
 
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
        if (dev->tvnorm->id & V4L2_STD_525_60) {
@@ -1614,8 +1308,7 @@ static int saa7134_g_selection(struct file *file, void *f, struct v4l2_selection
 {
        struct saa7134_dev *dev = video_drvdata(file);
 
-       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           sel->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
        switch (sel->target) {
@@ -1640,15 +1333,12 @@ static int saa7134_s_selection(struct file *file, void *f, struct v4l2_selection
        struct v4l2_rect *b = &dev->crop_bounds;
        struct v4l2_rect *c = &dev->crop_current;
 
-       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           sel->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
        if (sel->target != V4L2_SEL_TGT_CROP)
                return -EINVAL;
 
-       if (dev->overlay_owner)
-               return -EBUSY;
        if (vb2_is_streaming(&dev->video_vbq))
                return -EBUSY;
 
@@ -1764,85 +1454,6 @@ static int saa7134_enum_fmt_vid_cap(struct file *file, void  *priv,
        return 0;
 }
 
-static int saa7134_enum_fmt_vid_overlay(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (saa7134_no_overlay > 0) {
-               pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-
-       if ((f->index >= FORMATS) || formats[f->index].planar)
-               return -EINVAL;
-
-       f->pixelformat = formats[f->index].fourcc;
-
-       return 0;
-}
-
-static int saa7134_g_fbuf(struct file *file, void *f,
-                               struct v4l2_framebuffer *fb)
-{
-       struct saa7134_dev *dev = video_drvdata(file);
-
-       *fb = dev->ovbuf;
-       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-
-       return 0;
-}
-
-static int saa7134_s_fbuf(struct file *file, void *f,
-                                       const struct v4l2_framebuffer *fb)
-{
-       struct saa7134_dev *dev = video_drvdata(file);
-       struct saa7134_format *fmt;
-
-       if (!capable(CAP_SYS_ADMIN) &&
-          !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       /* check args */
-       fmt = format_by_fourcc(fb->fmt.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-
-       /* ok, accept it */
-       dev->ovbuf = *fb;
-       dev->ovfmt = fmt;
-       if (0 == dev->ovbuf.fmt.bytesperline)
-               dev->ovbuf.fmt.bytesperline =
-                       dev->ovbuf.fmt.width*fmt->depth/8;
-       return 0;
-}
-
-static int saa7134_overlay(struct file *file, void *priv, unsigned int on)
-{
-       struct saa7134_dev *dev = video_drvdata(file);
-       unsigned long flags;
-
-       if (on) {
-               if (saa7134_no_overlay > 0) {
-                       video_dbg("no_overlay\n");
-                       return -EINVAL;
-               }
-
-               if (dev->overlay_owner && priv != dev->overlay_owner)
-                       return -EBUSY;
-               dev->overlay_owner = priv;
-               spin_lock_irqsave(&dev->slock, flags);
-               start_preview(dev);
-               spin_unlock_irqrestore(&dev->slock, flags);
-       } else {
-               if (priv != dev->overlay_owner)
-                       return -EINVAL;
-               spin_lock_irqsave(&dev->slock, flags);
-               stop_preview(dev);
-               spin_unlock_irqrestore(&dev->slock, flags);
-               dev->overlay_owner = NULL;
-       }
-       return 0;
-}
-
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int vidioc_g_register (struct file *file, void *priv,
                              struct v4l2_dbg_register *reg)
@@ -1912,10 +1523,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_g_fmt_vid_cap           = saa7134_g_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap         = saa7134_try_fmt_vid_cap,
        .vidioc_s_fmt_vid_cap           = saa7134_s_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_overlay    = saa7134_enum_fmt_vid_overlay,
-       .vidioc_g_fmt_vid_overlay       = saa7134_g_fmt_vid_overlay,
-       .vidioc_try_fmt_vid_overlay     = saa7134_try_fmt_vid_overlay,
-       .vidioc_s_fmt_vid_overlay       = saa7134_s_fmt_vid_overlay,
        .vidioc_g_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
        .vidioc_try_fmt_vbi_cap         = saa7134_try_get_set_fmt_vbi_cap,
        .vidioc_s_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
@@ -1937,9 +1544,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_s_tuner                 = saa7134_s_tuner,
        .vidioc_g_selection             = saa7134_g_selection,
        .vidioc_s_selection             = saa7134_s_selection,
-       .vidioc_g_fbuf                  = saa7134_g_fbuf,
-       .vidioc_s_fbuf                  = saa7134_s_fbuf,
-       .vidioc_overlay                 = saa7134_overlay,
        .vidioc_g_frequency             = saa7134_g_frequency,
        .vidioc_s_frequency             = saa7134_s_frequency,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -2086,13 +1690,6 @@ int saa7134_video_init1(struct saa7134_dev *dev)
        dev->width    = 720;
        dev->height   = 576;
        dev->field = V4L2_FIELD_INTERLACED;
-       dev->win.w.width = dev->width;
-       dev->win.w.height = dev->height;
-       dev->win.field = V4L2_FIELD_INTERLACED;
-       dev->ovbuf.fmt.width = dev->width;
-       dev->ovbuf.fmt.height = dev->height;
-       dev->ovbuf.fmt.pixelformat = dev->fmt->fourcc;
-       dev->ovbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
        if (saa7134_boards[dev->board].video_out)
                saa7134_videoport_init(dev);
@@ -2146,6 +1743,7 @@ int saa7134_video_init1(struct saa7134_dev *dev)
 
 void saa7134_video_fini(struct saa7134_dev *dev)
 {
+       del_timer_sync(&dev->video_q.timeout);
        /* free stuff */
        saa7134_pgtable_free(dev->pci, &dev->video_q.pt);
        saa7134_pgtable_free(dev->pci, &dev->vbi_q.pt);
index 5c9b2912a9d12a398c4691ed03d2d88b3245d431..9f27e3775c273e1b4738f022399d624b18f695cc 100644 (file)
@@ -429,7 +429,6 @@ struct saa7134_board {
 /* ----------------------------------------------------------- */
 /* device / file handle status                                 */
 
-#define RESOURCE_OVERLAY       1
 #define RESOURCE_VIDEO         2
 #define RESOURCE_VBI           4
 #define RESOURCE_EMPRESS       8
@@ -589,17 +588,6 @@ struct saa7134_dev {
        unsigned char              eedata[256];
        int                        has_rds;
 
-       /* video overlay */
-       struct v4l2_framebuffer    ovbuf;
-       struct saa7134_format      *ovfmt;
-       unsigned int               ovenable;
-       enum v4l2_field            ovfield;
-       struct v4l2_window         win;
-       struct v4l2_clip           clips[8];
-       unsigned int               nclips;
-       struct v4l2_fh             *overlay_owner;
-
-
        /* video+ts+vbi capture */
        struct saa7134_dmaqueue    video_q;
        struct vb2_queue           video_vbq;
@@ -745,7 +733,6 @@ static inline bool is_empress(struct file *file)
 
 extern struct list_head  saa7134_devlist;
 extern struct mutex saa7134_devlist_lock;
-extern int saa7134_no_overlay;
 extern bool saa7134_userptr;
 
 void saa7134_track_gpio(struct saa7134_dev *dev, const char *msg);
index 3947701cd6c7e76835d3d8e58321a5a75c7d9c46..40b35098f3ead1d63378d05beb2ccddf3977a2da 100644 (file)
@@ -27,17 +27,18 @@ static int hexium_num;
 #define HEXIUM_GEMINI                  4
 #define HEXIUM_GEMINI_DUAL             5
 
+#define HEXIUM_STD (V4L2_STD_PAL | V4L2_STD_SECAM | V4L2_STD_NTSC)
 #define HEXIUM_INPUTS  9
 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
-       { 0, "CVBS 1",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 1, "CVBS 2",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 2, "CVBS 3",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 3, "CVBS 4",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 4, "CVBS 5",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 5, "CVBS 6",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 6, "Y/C 1",   V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 7, "Y/C 2",   V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 8, "Y/C 3",   V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
+       { 0, "CVBS 1",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 1, "CVBS 2",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 2, "CVBS 3",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 3, "CVBS 4",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 4, "CVBS 5",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 5, "CVBS 6",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 6, "Y/C 1",   V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 7, "Y/C 2",   V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 8, "Y/C 3",   V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
 };
 
 #define HEXIUM_AUDIOS  0
@@ -215,7 +216,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 
 static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
        *input = hexium->cur_input;
@@ -226,7 +227,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
 
 static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
        DEB_EE("VIDIOC_S_INPUT %d\n", input);
index 2eb4bee16b71f28175854cc636472c903f0f4228..a2076728c6210e9d5442f51fbbc13a87371973e4 100644 (file)
@@ -28,17 +28,18 @@ static int hexium_num;
 #define HEXIUM_ORION_1SVHS_3BNC                2
 #define HEXIUM_ORION_4BNC              3
 
+#define HEXIUM_STD (V4L2_STD_PAL | V4L2_STD_SECAM | V4L2_STD_NTSC)
 #define HEXIUM_INPUTS  9
 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
-       { 0, "CVBS 1",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 1, "CVBS 2",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 2, "CVBS 3",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 3, "CVBS 4",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 4, "CVBS 5",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 5, "CVBS 6",  V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 6, "Y/C 1",   V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 7, "Y/C 2",   V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-       { 8, "Y/C 3",   V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
+       { 0, "CVBS 1",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 1, "CVBS 2",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 2, "CVBS 3",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 3, "CVBS 4",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 4, "CVBS 5",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 5, "CVBS 6",  V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 6, "Y/C 1",   V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 7, "Y/C 2",   V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
+       { 8, "Y/C 3",   V4L2_INPUT_TYPE_CAMERA, 0, 0, HEXIUM_STD, 0, V4L2_IN_CAP_STD },
 };
 
 #define HEXIUM_AUDIOS  0
@@ -326,7 +327,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 
 static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
        *input = hexium->cur_input;
@@ -337,7 +338,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
 
 static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
 
        if (input >= HEXIUM_INPUTS)
@@ -379,6 +380,7 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
        /* the rest */
        hexium->cur_input = 0;
        hexium_init_done(dev);
+       hexium_set_input(hexium, 0);
 
        return 0;
 }
index 7ded8f5b05cb32ca8adbbdc21e00dee5ec155e80..a14b839098b8491b2a2ff3ce0d9d25682309607e 100644 (file)
@@ -48,6 +48,7 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 
+#define MXB_STD (V4L2_STD_PAL_BG | V4L2_STD_PAL_I | V4L2_STD_SECAM | V4L2_STD_NTSC)
 #define MXB_INPUTS 4
 enum { TUNER, AUX1, AUX3, AUX3_YC };
 
@@ -55,11 +56,11 @@ static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
        { TUNER,   "Tuner",          V4L2_INPUT_TYPE_TUNER,  0x3f, 0,
                V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },
        { AUX1,    "AUX1",           V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
-               V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
+               MXB_STD, 0, V4L2_IN_CAP_STD },
        { AUX3,    "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
-               V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
+               MXB_STD, 0, V4L2_IN_CAP_STD },
        { AUX3_YC, "AUX3 S-Video",   V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
-               V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
+               MXB_STD, 0, V4L2_IN_CAP_STD },
 };
 
 /* this array holds the information, which port of the saa7146 each
@@ -456,7 +457,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 
 static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
        *i = mxb->cur_input;
 
@@ -466,7 +467,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
 
 static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
        int err = 0;
        int i = 0;
@@ -512,6 +513,9 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
        if (err)
                return err;
 
+       mxb->video_dev.tvnorms = mxb_inputs[input].std;
+       mxb->vbi_dev.tvnorms = mxb_inputs[input].std;
+
        /* switch video in saa7111a */
        if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
                pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
@@ -528,7 +532,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
 
 static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
        if (t->index) {
@@ -550,7 +554,7 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
 
 static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
        if (t->index) {
@@ -565,14 +569,14 @@ static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *
 
 static int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *norm)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
 
        return call_all(dev, video, querystd, norm);
 }
 
 static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
        if (f->tuner)
@@ -585,9 +589,8 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency
 
 static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
-       struct saa7146_vv *vv = dev->vv_data;
 
        if (f->tuner)
                return -EINVAL;
@@ -604,15 +607,6 @@ static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_fre
        tuner_call(mxb, tuner, g_frequency, &mxb->cur_freq);
        if (mxb->cur_audinput == 0)
                mxb_update_audmode(mxb);
-
-       if (mxb->cur_input)
-               return 0;
-
-       /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
-       spin_lock(&dev->slock);
-       vv->vbi_fieldcount = 0;
-       spin_unlock(&dev->slock);
-
        return 0;
 }
 
@@ -626,7 +620,7 @@ static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
 
 static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
        DEB_EE("VIDIOC_G_AUDIO\n");
@@ -636,7 +630,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
 
 static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
        DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
@@ -656,7 +650,7 @@ static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
 
        if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
                return -EINVAL;
@@ -667,7 +661,7 @@ static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_regist
 
 static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
 
        if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
                return -EINVAL;
@@ -713,6 +707,17 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data
        vv_data.vid_ops.vidioc_g_register = vidioc_g_register;
        vv_data.vid_ops.vidioc_s_register = vidioc_s_register;
 #endif
+       vv_data.vbi_ops.vidioc_enum_input = vidioc_enum_input;
+       vv_data.vbi_ops.vidioc_g_input = vidioc_g_input;
+       vv_data.vbi_ops.vidioc_s_input = vidioc_s_input;
+       vv_data.vbi_ops.vidioc_querystd = vidioc_querystd;
+       vv_data.vbi_ops.vidioc_g_tuner = vidioc_g_tuner;
+       vv_data.vbi_ops.vidioc_s_tuner = vidioc_s_tuner;
+       vv_data.vbi_ops.vidioc_g_frequency = vidioc_g_frequency;
+       vv_data.vbi_ops.vidioc_s_frequency = vidioc_s_frequency;
+       vv_data.vbi_ops.vidioc_enumaudio = vidioc_enumaudio;
+       vv_data.vbi_ops.vidioc_g_audio = vidioc_g_audio;
+       vv_data.vbi_ops.vidioc_s_audio = vidioc_s_audio;
        if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_VIDEO)) {
                ERR("cannot register capture v4l2 device. skipping.\n");
                saa7146_vv_release(dev);
index 3cb83005cf09b6c186a081b144ceb2e3657cfab8..824529f3c74b0bdf2c6fab28295db9722e002dd3 100644 (file)
@@ -31,6 +31,7 @@
 #include "dvb-pll.h"
 #include <media/drv-intf/saa7146_vv.h>
 #include <linux/module.h>
+#include <linux/etherdevice.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -1410,7 +1411,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 
 static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
 
        *i = budget_av->cur_input;
@@ -1421,7 +1422,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
 
 static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
 
        dprintk(1, "VIDIOC_S_INPUT %d\n", input);
index 0cbc5b038073bc3b052d1acf6ba4d3220c99ceeb..773a18702d36967ecd2fd7d6d8b6ab784de329fd 100644 (file)
@@ -437,6 +437,7 @@ static void tw68_buf_queue(struct vb2_buffer *vb)
  */
 static int tw68_buf_prepare(struct vb2_buffer *vb)
 {
+       int ret;
        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
        struct vb2_queue *vq = vb->vb2_queue;
        struct tw68_dev *dev = vb2_get_drv_priv(vq);
@@ -452,30 +453,30 @@ static int tw68_buf_prepare(struct vb2_buffer *vb)
        bpl = (dev->width * dev->fmt->depth) >> 3;
        switch (dev->field) {
        case V4L2_FIELD_TOP:
-               tw68_risc_buffer(dev->pci, buf, dma->sgl,
+               ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
                                 0, UNSET, bpl, 0, dev->height);
                break;
        case V4L2_FIELD_BOTTOM:
-               tw68_risc_buffer(dev->pci, buf, dma->sgl,
+               ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
                                 UNSET, 0, bpl, 0, dev->height);
                break;
        case V4L2_FIELD_SEQ_TB:
-               tw68_risc_buffer(dev->pci, buf, dma->sgl,
+               ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
                                 0, bpl * (dev->height >> 1),
                                 bpl, 0, dev->height >> 1);
                break;
        case V4L2_FIELD_SEQ_BT:
-               tw68_risc_buffer(dev->pci, buf, dma->sgl,
+               ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
                                 bpl * (dev->height >> 1), 0,
                                 bpl, 0, dev->height >> 1);
                break;
        case V4L2_FIELD_INTERLACED:
        default:
-               tw68_risc_buffer(dev->pci, buf, dma->sgl,
+               ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
                                 0, bpl, bpl, bpl, dev->height >> 1);
                break;
        }
-       return 0;
+       return ret;
 }
 
 static void tw68_buf_finish(struct vb2_buffer *vb)
@@ -485,7 +486,8 @@ static void tw68_buf_finish(struct vb2_buffer *vb)
        struct tw68_dev *dev = vb2_get_drv_priv(vq);
        struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb);
 
-       dma_free_coherent(&dev->pci->dev, buf->size, buf->cpu, buf->dma);
+       if (buf->cpu)
+               dma_free_coherent(&dev->pci->dev, buf->size, buf->cpu, buf->dma);
 }
 
 static int tw68_start_streaming(struct vb2_queue *q, unsigned int count)
index 237e830ae72684188be2ae821e2e64d7991fce0b..6d2a526789a504221fb65258835a14fa00924b2e 100644 (file)
@@ -25,8 +25,6 @@ void jpeg_codec_sleep(struct zoran *zr, int sleep);
 int jpeg_codec_reset(struct zoran *zr);
 
 /* zr360x7 access to raw capture */
-void zr36057_overlay(struct zoran *zr, int on);
-void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count);
 void zr36057_set_memgrab(struct zoran *zr, int mode);
 int wait_grab_pending(struct zoran *zr);
 
index 2423714afcb9f28d1dfde5ef7b2d8be0ed933262..ec03e17727d7fda21d22dc87138111423c4efa91 100644 (file)
@@ -3919,7 +3919,7 @@ static int allegro_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int allegro_remove(struct platform_device *pdev)
+static void allegro_remove(struct platform_device *pdev)
 {
        struct allegro_dev *dev = platform_get_drvdata(pdev);
 
@@ -3935,8 +3935,6 @@ static int allegro_remove(struct platform_device *pdev)
        pm_runtime_disable(&dev->plat_dev->dev);
 
        v4l2_device_unregister(&dev->v4l2_dev);
-
-       return 0;
 }
 
 static int allegro_runtime_resume(struct device *device)
@@ -4006,7 +4004,7 @@ static const struct dev_pm_ops allegro_pm_ops = {
 
 static struct platform_driver allegro_driver = {
        .probe = allegro_probe,
-       .remove = allegro_remove,
+       .remove_new = allegro_remove,
        .driver = {
                .name = "allegro",
                .of_match_table = of_match_ptr(allegro_dt_ids),
index 142d421a8d769f8e86369a5f1518396ad3095099..09409908ba5dfb45e3bc766e568a017304104852 100644 (file)
@@ -1024,7 +1024,7 @@ disable_clks:
        return ret;
 }
 
-static int ge2d_remove(struct platform_device *pdev)
+static void ge2d_remove(struct platform_device *pdev)
 {
        struct meson_ge2d *ge2d = platform_get_drvdata(pdev);
 
@@ -1032,8 +1032,6 @@ static int ge2d_remove(struct platform_device *pdev)
        v4l2_m2m_release(ge2d->m2m_dev);
        v4l2_device_unregister(&ge2d->v4l2_dev);
        clk_disable_unprepare(ge2d->clk);
-
-       return 0;
 }
 
 static const struct of_device_id meson_ge2d_match[] = {
@@ -1047,7 +1045,7 @@ MODULE_DEVICE_TABLE(of, meson_ge2d_match);
 
 static struct platform_driver ge2d_drv = {
        .probe = ge2d_probe,
-       .remove = ge2d_remove,
+       .remove_new = ge2d_remove,
        .driver = {
                .name = "meson-ge2d",
                .of_match_table = meson_ge2d_match,
index 87f9f8e90ab138d43ce0bdc9188ca73f663a3815..3fa1a74a2e2047fcc9928bf703385315ee8b7895 100644 (file)
@@ -165,10 +165,55 @@ static const struct vpu_format vdec_formats[] = {
                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED
        },
+       {
+               .pixfmt = V4L2_PIX_FMT_SPK,
+               .mem_planes = 1,
+               .comp_planes = 1,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+               .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_RV30,
+               .mem_planes = 1,
+               .comp_planes = 1,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+               .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_RV40,
+               .mem_planes = 1,
+               .comp_planes = 1,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+               .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED
+       },
        {0, 0, 0, 0},
 };
 
+static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct vpu_inst *inst = ctrl_to_inst(ctrl);
+       struct vdec_t *vdec = inst->priv;
+       int ret = 0;
+
+       vpu_inst_lock(inst);
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:
+               vdec->params.display_delay_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:
+               vdec->params.display_delay = ctrl->val;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       vpu_inst_unlock(inst);
+
+       return ret;
+}
+
 static const struct v4l2_ctrl_ops vdec_ctrl_ops = {
+       .s_ctrl = vdec_op_s_ctrl,
        .g_volatile_ctrl = vpu_helper_g_volatile_ctrl,
 };
 
@@ -181,6 +226,14 @@ static int vdec_ctrl_init(struct vpu_inst *inst)
        if (ret)
                return ret;
 
+       v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
+                         V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,
+                         0, 0, 1, 0);
+
+       v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
+                         V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,
+                         0, 1, 1, 0);
+
        ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
                                 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 2);
        if (ctrl)
index 528a93f08ecd42d724efe5d9aa8d564c0d9e560e..bac6d0d94f8a5f40d675cb58b8613d5a8bd710b0 100644 (file)
@@ -55,7 +55,8 @@ struct vpu_encode_params {
 struct vpu_decode_params {
        u32 codec_format;
        u32 output_format;
-       u32 b_dis_reorder;
+       u32 display_delay_enable;
+       u32 display_delay;
        u32 b_non_frame;
        u32 frame_count;
        u32 end_flag;
index f9ec1753f7c86f365047f9d6913907ddb1533d07..de23627a119a0977fc346ecd1a6431651c0379c3 100644 (file)
@@ -709,7 +709,7 @@ err_runtime_disable:
        return ret;
 }
 
-static int vpu_core_remove(struct platform_device *pdev)
+static void vpu_core_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct vpu_core *core = platform_get_drvdata(pdev);
@@ -728,8 +728,6 @@ static int vpu_core_remove(struct platform_device *pdev)
        memunmap(core->rpc.virt);
        mutex_destroy(&core->lock);
        mutex_destroy(&core->cmd_lock);
-
-       return 0;
 }
 
 static int __maybe_unused vpu_core_runtime_resume(struct device *dev)
@@ -864,7 +862,7 @@ MODULE_DEVICE_TABLE(of, vpu_core_dt_match);
 
 static struct platform_driver amphion_vpu_core_driver = {
        .probe = vpu_core_probe,
-       .remove = vpu_core_remove,
+       .remove_new = vpu_core_remove,
        .driver = {
                .name = "amphion-vpu-core",
                .of_match_table = vpu_core_dt_match,
index f01ce49d27e8048da5c07f187805e8d17360d2a7..4187b2b5562f92a9a7dc6653d74f3cd077ec2921 100644 (file)
@@ -157,7 +157,7 @@ err_vpu_deinit:
        return ret;
 }
 
-static int vpu_remove(struct platform_device *pdev)
+static void vpu_remove(struct platform_device *pdev)
 {
        struct vpu_dev *vpu = platform_get_drvdata(pdev);
        struct device *dev = &pdev->dev;
@@ -173,8 +173,6 @@ static int vpu_remove(struct platform_device *pdev)
        media_device_cleanup(&vpu->mdev);
        v4l2_device_unregister(&vpu->v4l2_dev);
        mutex_destroy(&vpu->lock);
-
-       return 0;
 }
 
 static int __maybe_unused vpu_runtime_resume(struct device *dev)
@@ -229,7 +227,7 @@ MODULE_DEVICE_TABLE(of, vpu_dt_match);
 
 static struct platform_driver amphion_vpu_driver = {
        .probe = vpu_probe,
-       .remove = vpu_remove,
+       .remove_new = vpu_remove,
        .driver = {
                .name = "amphion-vpu",
                .of_match_table = vpu_dt_match,
index 2c9bfc6a5a72e5658e9d24b1ea1365665f2f0cc1..ef44bff9fbaf633fa3bb6db415388786856bbbe4 100644 (file)
@@ -68,6 +68,8 @@
 #define STREAM_CONFIG_NUM_DBE_SET(x, y)                CONFIG_SET(x, y, 30, 0x40000000)
 #define STREAM_CONFIG_FS_CTRL_MODE_SET(x, y)   CONFIG_SET(x, y, 31, 0x80000000)
 
+#define MALONE_DEC_FMT_RV_MASK                 BIT(21)
+
 enum vpu_malone_stream_input_mode {
        INVALID_MODE = 0,
        FRAME_LVL,
@@ -478,6 +480,9 @@ u32 vpu_malone_get_version(struct vpu_shared_addr *shared)
 {
        struct malone_iface *iface = shared->iface;
 
+       vpu_malone_enable_format(V4L2_PIX_FMT_RV30, iface->fw_version & MALONE_DEC_FMT_RV_MASK);
+       vpu_malone_enable_format(V4L2_PIX_FMT_RV40, iface->fw_version & MALONE_DEC_FMT_RV_MASK);
+
        return iface->fw_version;
 }
 
@@ -562,8 +567,23 @@ static struct malone_fmt_mapping fmt_mappings[] = {
        {V4L2_PIX_FMT_H263,        MALONE_FMT_ASP},
        {V4L2_PIX_FMT_JPEG,        MALONE_FMT_JPG},
        {V4L2_PIX_FMT_VP8,         MALONE_FMT_VP8},
+       {V4L2_PIX_FMT_SPK,         MALONE_FMT_SPK},
+       {V4L2_PIX_FMT_RV30,        MALONE_FMT_RV},
+       {V4L2_PIX_FMT_RV40,        MALONE_FMT_RV},
 };
 
+void vpu_malone_enable_format(u32 pixelformat, int enable)
+{
+       u32 i;
+
+       for (i = 0; i < ARRAY_SIZE(fmt_mappings); i++) {
+               if (pixelformat == fmt_mappings[i].pixelformat) {
+                       fmt_mappings[i].is_disabled = enable ? 0 : 1;
+                       return;
+               }
+       }
+}
+
 static enum vpu_malone_format vpu_malone_format_remap(u32 pixelformat)
 {
        u32 i;
@@ -641,7 +661,9 @@ static int vpu_malone_set_params(struct vpu_shared_addr *shared,
                hc->jpg[instance].jpg_mjpeg_interlaced = 0;
        }
 
-       hc->codec_param[instance].disp_imm = params->b_dis_reorder ? 1 : 0;
+       hc->codec_param[instance].disp_imm = params->display_delay_enable ? 1 : 0;
+       if (malone_format != MALONE_FMT_AVC)
+               hc->codec_param[instance].disp_imm = 0;
        hc->codec_param[instance].dbglog_enable = 0;
        iface->dbglog_desc.level = 0;
 
@@ -987,6 +1009,9 @@ static const struct malone_padding_scode padding_scodes[] = {
        {SCODE_PADDING_EOS,      V4L2_PIX_FMT_XVID,        {0xb1010000, 0x0}},
        {SCODE_PADDING_EOS,      V4L2_PIX_FMT_H263,        {0xb1010000, 0x0}},
        {SCODE_PADDING_EOS,      V4L2_PIX_FMT_VP8,         {0x34010000, 0x0}},
+       {SCODE_PADDING_EOS,      V4L2_PIX_FMT_SPK,         {0x34010000, 0x0}},
+       {SCODE_PADDING_EOS,      V4L2_PIX_FMT_RV30,        {0x34010000, 0x0}},
+       {SCODE_PADDING_EOS,      V4L2_PIX_FMT_RV40,        {0x34010000, 0x0}},
        {SCODE_PADDING_EOS,      V4L2_PIX_FMT_JPEG,        {0xefff0000, 0x0}},
        {SCODE_PADDING_ABORT,    V4L2_PIX_FMT_H264,        {0x0B010000, 0}},
        {SCODE_PADDING_ABORT,    V4L2_PIX_FMT_H264_MVC,    {0x0B010000, 0}},
@@ -998,6 +1023,9 @@ static const struct malone_padding_scode padding_scodes[] = {
        {SCODE_PADDING_ABORT,    V4L2_PIX_FMT_XVID,        {0xb1010000, 0x0}},
        {SCODE_PADDING_ABORT,    V4L2_PIX_FMT_H263,        {0xb1010000, 0x0}},
        {SCODE_PADDING_ABORT,    V4L2_PIX_FMT_VP8,         {0x34010000, 0x0}},
+       {SCODE_PADDING_ABORT,    V4L2_PIX_FMT_SPK,         {0x34010000, 0x0}},
+       {SCODE_PADDING_ABORT,    V4L2_PIX_FMT_RV30,        {0x34010000, 0x0}},
+       {SCODE_PADDING_ABORT,    V4L2_PIX_FMT_RV40,        {0x34010000, 0x0}},
        {SCODE_PADDING_EOS,      V4L2_PIX_FMT_JPEG,        {0x0, 0x0}},
        {SCODE_PADDING_BUFFLUSH, V4L2_PIX_FMT_H264,        {0x15010000, 0x0}},
        {SCODE_PADDING_BUFFLUSH, V4L2_PIX_FMT_H264_MVC,    {0x15010000, 0x0}},
@@ -1411,6 +1439,16 @@ static int vpu_malone_insert_scode_vp8_pic(struct malone_scode_t *scode)
        return size;
 }
 
+static int vpu_malone_insert_scode_spk_seq(struct malone_scode_t *scode)
+{
+       return vpu_malone_insert_scode_seq(scode, MALONE_CODEC_ID_SPK, 0);
+}
+
+static int vpu_malone_insert_scode_spk_pic(struct malone_scode_t *scode)
+{
+       return vpu_malone_insert_scode_pic(scode, MALONE_CODEC_ID_SPK, 0);
+}
+
 static const struct malone_scode_handler scode_handlers[] = {
        {
                /* fix me, need to swap return operation after gstreamer swap */
@@ -1427,6 +1465,11 @@ static const struct malone_scode_handler scode_handlers[] = {
                .insert_scode_seq = vpu_malone_insert_scode_vp8_seq,
                .insert_scode_pic = vpu_malone_insert_scode_vp8_pic,
        },
+       {
+               .pixelformat = V4L2_PIX_FMT_SPK,
+               .insert_scode_seq = vpu_malone_insert_scode_spk_seq,
+               .insert_scode_pic = vpu_malone_insert_scode_spk_pic,
+       },
 };
 
 static const struct malone_scode_handler *get_scode_handler(u32 pixelformat)
index 02a9d9530970f62c3c1bb3c6a603f832b699c170..c95b536291995e7658860900f6b247fe2374c07e 100644 (file)
@@ -41,5 +41,6 @@ int vpu_malone_post_cmd(struct vpu_shared_addr *shared, u32 instance);
 int vpu_malone_init_instance(struct vpu_shared_addr *shared, u32 instance);
 u32 vpu_malone_get_max_instance_count(struct vpu_shared_addr *shared);
 bool vpu_malone_check_fmt(enum vpu_core_type type, u32 pixelfmt);
+void vpu_malone_enable_format(u32 pixelformat, int enable);
 
 #endif
index 794d4dc3a6547254a1ffc4dcda517056101575d5..374eb7781936a91bb687917819540984df8dd394 100644 (file)
@@ -2206,7 +2206,7 @@ static int aspeed_video_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int aspeed_video_remove(struct platform_device *pdev)
+static void aspeed_video_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
@@ -2228,8 +2228,6 @@ static int aspeed_video_remove(struct platform_device *pdev)
        aspeed_video_free_buf(video, &video->jpeg);
 
        of_reserved_mem_device_release(dev);
-
-       return 0;
 }
 
 static struct platform_driver aspeed_video_driver = {
@@ -2238,7 +2236,7 @@ static struct platform_driver aspeed_video_driver = {
                .of_match_table = aspeed_video_of_match,
        },
        .probe = aspeed_video_probe,
-       .remove = aspeed_video_remove,
+       .remove_new = aspeed_video_remove,
 };
 
 module_platform_driver(aspeed_video_driver);
index 4d15814e4481c5d442975ed408e7ba696992834c..c29e04864445c11905cad30cafe568a7c7ed495a 100644 (file)
@@ -587,8 +587,8 @@ static int isi_try_fmt(struct atmel_isi *isi, struct v4l2_format *f,
        struct v4l2_pix_format *pixfmt = &f->fmt.pix;
        struct v4l2_subdev_pad_config pad_cfg = {};
        struct v4l2_subdev_state pad_state = {
-               .pads = &pad_cfg
-               };
+               .pads = &pad_cfg,
+       };
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
@@ -1317,7 +1317,7 @@ err_vdev_alloc:
        return ret;
 }
 
-static int atmel_isi_remove(struct platform_device *pdev)
+static void atmel_isi_remove(struct platform_device *pdev)
 {
        struct atmel_isi *isi = platform_get_drvdata(pdev);
 
@@ -1329,8 +1329,6 @@ static int atmel_isi_remove(struct platform_device *pdev)
        v4l2_async_nf_unregister(&isi->notifier);
        v4l2_async_nf_cleanup(&isi->notifier);
        v4l2_device_unregister(&isi->v4l2_dev);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1368,7 +1366,7 @@ static struct platform_driver atmel_isi_driver = {
                .pm     = &atmel_isi_dev_pm_ops,
        },
        .probe          = atmel_isi_probe,
-       .remove         = atmel_isi_remove,
+       .remove_new     = atmel_isi_remove,
 };
 
 module_platform_driver(atmel_isi_driver);
index cc3ebb0d96f66ca18fe637e40d4bf12755c0e36d..9755d1c8ceb9bad32e2d3a35bc0bc22167450a72 100644 (file)
@@ -473,14 +473,12 @@ err_free_priv:
        return ret;
 }
 
-static int csi2rx_remove(struct platform_device *pdev)
+static void csi2rx_remove(struct platform_device *pdev)
 {
        struct csi2rx_priv *csi2rx = platform_get_drvdata(pdev);
 
        v4l2_async_unregister_subdev(&csi2rx->subdev);
        kfree(csi2rx);
-
-       return 0;
 }
 
 static const struct of_device_id csi2rx_of_table[] = {
@@ -491,7 +489,7 @@ MODULE_DEVICE_TABLE(of, csi2rx_of_table);
 
 static struct platform_driver csi2rx_driver = {
        .probe  = csi2rx_probe,
-       .remove = csi2rx_remove,
+       .remove_new = csi2rx_remove,
 
        .driver = {
                .name           = "cdns-csi2rx",
index 58e405b69f67b3b54b4b23f98cc44ef1ca2fca98..1e0400b7803e939dc5266480f49c60a7f3ef7ec5 100644 (file)
@@ -635,19 +635,17 @@ err_free_priv:
        return ret;
 }
 
-static int csi2tx_remove(struct platform_device *pdev)
+static void csi2tx_remove(struct platform_device *pdev)
 {
        struct csi2tx_priv *csi2tx = platform_get_drvdata(pdev);
 
        v4l2_async_unregister_subdev(&csi2tx->subdev);
        kfree(csi2tx);
-
-       return 0;
 }
 
 static struct platform_driver csi2tx_driver = {
        .probe  = csi2tx_probe,
-       .remove = csi2tx_remove,
+       .remove_new = csi2tx_remove,
 
        .driver = {
                .name           = "cdns-csi2tx",
index af71eea04dbd9f21cd7aba410e53e076199ffd2d..d013ea5d9d3d239195d09e2057236d61685958d6 100644 (file)
@@ -3300,7 +3300,7 @@ err_v4l2_register:
        return ret;
 }
 
-static int coda_remove(struct platform_device *pdev)
+static void coda_remove(struct platform_device *pdev)
 {
        struct coda_dev *dev = platform_get_drvdata(pdev);
        int i;
@@ -3322,7 +3322,6 @@ static int coda_remove(struct platform_device *pdev)
        coda_free_aux_buf(dev, &dev->workbuf);
        debugfs_remove_recursive(dev->debugfs_root);
        ida_destroy(&dev->ida);
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -3347,7 +3346,7 @@ static const struct dev_pm_ops coda_pm_ops = {
 
 static struct platform_driver coda_driver = {
        .probe  = coda_probe,
-       .remove = coda_remove,
+       .remove_new = coda_remove,
        .driver = {
                .name   = CODA_NAME,
                .of_match_table = coda_dt_ids,
index 54270d6b6f50fe9128069ff2729f4d7d68795d0a..9ed3c2e063de05f9adabcc3db08600323d814d32 100644 (file)
@@ -1794,8 +1794,8 @@ static int pxac_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
        struct v4l2_pix_format *pix = &f->fmt.pix;
        struct v4l2_subdev_pad_config pad_cfg;
        struct v4l2_subdev_state pad_state = {
-               .pads = &pad_cfg
-               };
+               .pads = &pad_cfg,
+       };
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
@@ -2421,7 +2421,7 @@ exit_free_dma_y:
        return err;
 }
 
-static int pxa_camera_remove(struct platform_device *pdev)
+static void pxa_camera_remove(struct platform_device *pdev)
 {
        struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
 
@@ -2437,8 +2437,6 @@ static int pxa_camera_remove(struct platform_device *pdev)
        v4l2_device_unregister(&pcdev->v4l2_dev);
 
        dev_info(&pdev->dev, "PXA Camera driver unloaded\n");
-
-       return 0;
 }
 
 static const struct dev_pm_ops pxa_camera_pm = {
@@ -2459,7 +2457,7 @@ static struct platform_driver pxa_camera_driver = {
                .of_match_table = of_match_ptr(pxa_camera_of_match),
        },
        .probe          = pxa_camera_probe,
-       .remove         = pxa_camera_remove,
+       .remove_new     = pxa_camera_remove,
 };
 
 module_platform_driver(pxa_camera_driver);
index 1f89e71cdccfc7685ad556a7c631c8418fe2aa6f..96b35a5d61740a25cc1e2013b99ea9b9ba2007f0 100644 (file)
@@ -984,7 +984,7 @@ rel_dma:
        return ret;
 }
 
-static int deinterlace_remove(struct platform_device *pdev)
+static void deinterlace_remove(struct platform_device *pdev)
 {
        struct deinterlace_dev *pcdev = platform_get_drvdata(pdev);
 
@@ -993,13 +993,11 @@ static int deinterlace_remove(struct platform_device *pdev)
        video_unregister_device(&pcdev->vfd);
        v4l2_device_unregister(&pcdev->v4l2_dev);
        dma_release_channel(pcdev->dma_chan);
-
-       return 0;
 }
 
 static struct platform_driver deinterlace_pdrv = {
        .probe          = deinterlace_probe,
-       .remove         = deinterlace_remove,
+       .remove_new     = deinterlace_remove,
        .driver         = {
                .name   = MEM2MEM_NAME,
        },
index ad4a7922d0d74310308045b6f3b7b7843b3f8290..154bdcb3f2cc56c2ff7a38c4aede93da23c74a33 100644 (file)
@@ -1351,8 +1351,8 @@ static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
        struct v4l2_pix_format *pix = &fmt->fmt.pix;
        struct v4l2_subdev_pad_config pad_cfg;
        struct v4l2_subdev_state pad_state = {
-               .pads = &pad_cfg
-               };
+               .pads = &pad_cfg,
+       };
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
index ef22bf8f276ca5a8d68e098d259cc40fee926097..e93feefb447b48ee0d6bf53e0d7512b999f1eb2a 100644 (file)
@@ -287,23 +287,13 @@ out:
        return ret;
 }
 
-
-static int mmpcam_remove(struct mmp_camera *cam)
+static void mmpcam_remove(struct platform_device *pdev)
 {
+       struct mmp_camera *cam = platform_get_drvdata(pdev);
        struct mcam_camera *mcam = &cam->mcam;
 
        mccic_shutdown(mcam);
        pm_runtime_force_suspend(mcam->dev);
-       return 0;
-}
-
-static int mmpcam_platform_remove(struct platform_device *pdev)
-{
-       struct mmp_camera *cam = platform_get_drvdata(pdev);
-
-       if (cam == NULL)
-               return -ENODEV;
-       return mmpcam_remove(cam);
 }
 
 /*
@@ -369,7 +359,7 @@ MODULE_DEVICE_TABLE(of, mmpcam_of_match);
 
 static struct platform_driver mmpcam_driver = {
        .probe          = mmpcam_probe,
-       .remove         = mmpcam_platform_remove,
+       .remove_new     = mmpcam_remove,
        .driver = {
                .name   = "mmp-camera",
                .of_match_table = of_match_ptr(mmpcam_of_match),
index 969516a940ba7600732b9fa938aa147a0ec10f17..6c7c5f3648df81197c3088570c5ada45fa1ee96c 100644 (file)
@@ -1004,8 +1004,8 @@ static void mtk_jpegenc_worker(struct work_struct *work)
 retry_select:
        hw_id = mtk_jpegenc_get_hw(ctx);
        if (hw_id < 0) {
-               ret = wait_event_interruptible(jpeg->enc_hw_wq,
-                                              atomic_read(&jpeg->enchw_rdy) > 0);
+               ret = wait_event_interruptible(jpeg->hw_wq,
+                                              atomic_read(&jpeg->hw_rdy) > 0);
                if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) {
                        dev_err(jpeg->dev, "%s : %d, all HW are busy\n",
                                __func__, __LINE__);
@@ -1016,7 +1016,7 @@ retry_select:
                goto retry_select;
        }
 
-       atomic_dec(&jpeg->enchw_rdy);
+       atomic_dec(&jpeg->hw_rdy);
        src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
        if (!src_buf)
                goto getbuf_fail;
@@ -1025,9 +1025,6 @@ retry_select:
        if (!dst_buf)
                goto getbuf_fail;
 
-       v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-       v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
        v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
 
        mtk_jpegenc_set_hw_param(ctx, hw_id, src_buf, dst_buf);
@@ -1045,6 +1042,9 @@ retry_select:
                goto enc_end;
        }
 
+       v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+       v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
        schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work,
                              msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
 
@@ -1073,7 +1073,7 @@ enc_end:
        v4l2_m2m_buf_done(src_buf, buf_state);
        v4l2_m2m_buf_done(dst_buf, buf_state);
 getbuf_fail:
-       atomic_inc(&jpeg->enchw_rdy);
+       atomic_inc(&jpeg->hw_rdy);
        mtk_jpegenc_put_hw(jpeg, hw_id);
        v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 }
@@ -1198,8 +1198,8 @@ static void mtk_jpegdec_worker(struct work_struct *work)
 retry_select:
        hw_id = mtk_jpegdec_get_hw(ctx);
        if (hw_id < 0) {
-               ret = wait_event_interruptible_timeout(jpeg->dec_hw_wq,
-                                                      atomic_read(&jpeg->dechw_rdy) > 0,
+               ret = wait_event_interruptible_timeout(jpeg->hw_wq,
+                                                      atomic_read(&jpeg->hw_rdy) > 0,
                                                       MTK_JPEG_HW_TIMEOUT_MSEC);
                if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) {
                        dev_err(jpeg->dev, "%s : %d, all HW are busy\n",
@@ -1211,7 +1211,7 @@ retry_select:
                goto retry_select;
        }
 
-       atomic_dec(&jpeg->dechw_rdy);
+       atomic_dec(&jpeg->hw_rdy);
        src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
        if (!src_buf)
                goto getbuf_fail;
@@ -1220,9 +1220,6 @@ retry_select:
        if (!dst_buf)
                goto getbuf_fail;
 
-       v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-       v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
        v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
        jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
        jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
@@ -1231,7 +1228,7 @@ retry_select:
                                             &jpeg_src_buf->dec_param)) {
                mtk_jpeg_queue_src_chg_event(ctx);
                ctx->state = MTK_JPEG_SOURCE_CHANGE;
-               goto dec_end;
+               goto getbuf_fail;
        }
 
        jpeg_src_buf->curr_ctx = ctx;
@@ -1254,6 +1251,9 @@ retry_select:
                goto clk_end;
        }
 
+       v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+       v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
        schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work,
                              msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
 
@@ -1290,7 +1290,7 @@ dec_end:
        v4l2_m2m_buf_done(src_buf, buf_state);
        v4l2_m2m_buf_done(dst_buf, buf_state);
 getbuf_fail:
-       atomic_inc(&jpeg->dechw_rdy);
+       atomic_inc(&jpeg->hw_rdy);
        mtk_jpegdec_put_hw(jpeg, hw_id);
        v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 }
@@ -1575,12 +1575,7 @@ static int mtk_jpeg_open(struct file *file)
                goto free;
        }
 
-       if (jpeg->is_jpgenc_multihw)
-               INIT_WORK(&ctx->jpeg_work, mtk_jpegenc_worker);
-
-       if (jpeg->is_jpgdec_multihw)
-               INIT_WORK(&ctx->jpeg_work, mtk_jpegdec_worker);
-
+       INIT_WORK(&ctx->jpeg_work, jpeg->variant->jpeg_worker);
        INIT_LIST_HEAD(&ctx->dst_done_queue);
        spin_lock_init(&ctx->done_queue_lock);
        v4l2_fh_init(&ctx->fh, vfd);
@@ -1671,10 +1666,52 @@ static void mtk_jpeg_job_timeout_work(struct work_struct *work)
        v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 }
 
+static int mtk_jpeg_single_core_init(struct platform_device *pdev,
+                                    struct mtk_jpeg_dev *jpeg_dev)
+{
+       struct mtk_jpeg_dev *jpeg = jpeg_dev;
+       int jpeg_irq, ret;
+
+       INIT_DELAYED_WORK(&jpeg->job_timeout_work,
+                         mtk_jpeg_job_timeout_work);
+
+       jpeg->reg_base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(jpeg->reg_base)) {
+               ret = PTR_ERR(jpeg->reg_base);
+               return ret;
+       }
+
+       jpeg_irq = platform_get_irq(pdev, 0);
+       if (jpeg_irq < 0)
+               return jpeg_irq;
+
+       ret = devm_request_irq(&pdev->dev,
+                              jpeg_irq,
+                              jpeg->variant->irq_handler,
+                              0,
+                              pdev->name, jpeg);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to request jpeg_irq %d (%d)\n",
+                       jpeg_irq, ret);
+               return ret;
+       }
+
+       ret = devm_clk_bulk_get(jpeg->dev,
+                               jpeg->variant->num_clks,
+                               jpeg->variant->clks);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to init clk\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static int mtk_jpeg_probe(struct platform_device *pdev)
 {
        struct mtk_jpeg_dev *jpeg;
-       int jpeg_irq;
+       struct device_node *child;
+       int num_child = 0;
        int ret;
 
        jpeg = devm_kzalloc(&pdev->dev, sizeof(*jpeg), GFP_KERNEL);
@@ -1692,38 +1729,26 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       if (list_empty(&pdev->dev.devres_head)) {
-               INIT_DELAYED_WORK(&jpeg->job_timeout_work,
-                                 mtk_jpeg_job_timeout_work);
-
-               jpeg->reg_base = devm_platform_ioremap_resource(pdev, 0);
-               if (IS_ERR(jpeg->reg_base)) {
-                       ret = PTR_ERR(jpeg->reg_base);
-                       return ret;
+       if (!jpeg->variant->multi_core) {
+               ret = mtk_jpeg_single_core_init(pdev, jpeg);
+               if (ret) {
+                       v4l2_err(&jpeg->v4l2_dev, "mtk_jpeg_single_core_init failed.");
+                       return -EINVAL;
                }
+       } else {
+               init_waitqueue_head(&jpeg->hw_wq);
 
-               jpeg_irq = platform_get_irq(pdev, 0);
-               if (jpeg_irq < 0)
-                       return jpeg_irq;
+               for_each_child_of_node(pdev->dev.of_node, child)
+                       num_child++;
 
-               ret = devm_request_irq(&pdev->dev,
-                                      jpeg_irq,
-                                      jpeg->variant->irq_handler,
-                                      0,
-                                      pdev->name, jpeg);
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed to request jpeg_irq %d (%d)\n",
-                               jpeg_irq, ret);
-                       return ret;
-               }
+               atomic_set(&jpeg->hw_rdy, num_child);
+               atomic_set(&jpeg->hw_index, 0);
 
-               ret = devm_clk_bulk_get(jpeg->dev,
-                                       jpeg->variant->num_clks,
-                                       jpeg->variant->clks);
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed to init clk\n");
-                       return ret;
-               }
+               jpeg->workqueue = alloc_ordered_workqueue(MTK_JPEG_NAME,
+                                                         WQ_MEM_RECLAIM
+                                                         | WQ_FREEZABLE);
+               if (!jpeg->workqueue)
+                       return -EINVAL;
        }
 
        ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
@@ -1757,7 +1782,7 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
        jpeg->vdev->device_caps = V4L2_CAP_STREAMING |
                                  V4L2_CAP_VIDEO_M2M_MPLANE;
 
-       if (of_get_property(pdev->dev.of_node, "dma-ranges", NULL))
+       if (of_property_present(pdev->dev.of_node, "dma-ranges"))
                dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
 
        ret = video_register_device(jpeg->vdev, VFL_TYPE_VIDEO, -1);
@@ -1790,7 +1815,7 @@ err_m2m_init:
        return ret;
 }
 
-static int mtk_jpeg_remove(struct platform_device *pdev)
+static void mtk_jpeg_remove(struct platform_device *pdev)
 {
        struct mtk_jpeg_dev *jpeg = platform_get_drvdata(pdev);
 
@@ -1798,8 +1823,6 @@ static int mtk_jpeg_remove(struct platform_device *pdev)
        video_unregister_device(jpeg->vdev);
        v4l2_m2m_release(jpeg->m2m_dev);
        v4l2_device_unregister(&jpeg->v4l2_dev);
-
-       return 0;
 }
 
 static __maybe_unused int mtk_jpeg_pm_suspend(struct device *dev)
@@ -1846,6 +1869,7 @@ static const struct dev_pm_ops mtk_jpeg_pm_ops = {
        SET_RUNTIME_PM_OPS(mtk_jpeg_pm_suspend, mtk_jpeg_pm_resume, NULL)
 };
 
+#if defined(CONFIG_OF)
 static const struct mtk_jpeg_variant mt8173_jpeg_drvdata = {
        .clks = mt8173_jpeg_dec_clocks,
        .num_clks = ARRAY_SIZE(mt8173_jpeg_dec_clocks),
@@ -1874,6 +1898,7 @@ static const struct mtk_jpeg_variant mtk_jpeg_drvdata = {
        .ioctl_ops = &mtk_jpeg_enc_ioctl_ops,
        .out_q_default_fourcc = V4L2_PIX_FMT_YUYV,
        .cap_q_default_fourcc = V4L2_PIX_FMT_JPEG,
+       .multi_core = false,
 };
 
 static struct mtk_jpeg_variant mtk8195_jpegenc_drvdata = {
@@ -1885,6 +1910,8 @@ static struct mtk_jpeg_variant mtk8195_jpegenc_drvdata = {
        .ioctl_ops = &mtk_jpeg_enc_ioctl_ops,
        .out_q_default_fourcc = V4L2_PIX_FMT_YUYV,
        .cap_q_default_fourcc = V4L2_PIX_FMT_JPEG,
+       .multi_core = true,
+       .jpeg_worker = mtk_jpegenc_worker,
 };
 
 static const struct mtk_jpeg_variant mtk8195_jpegdec_drvdata = {
@@ -1896,9 +1923,10 @@ static const struct mtk_jpeg_variant mtk8195_jpegdec_drvdata = {
        .ioctl_ops = &mtk_jpeg_dec_ioctl_ops,
        .out_q_default_fourcc = V4L2_PIX_FMT_JPEG,
        .cap_q_default_fourcc = V4L2_PIX_FMT_YUV420M,
+       .multi_core = true,
+       .jpeg_worker = mtk_jpegdec_worker,
 };
 
-#if defined(CONFIG_OF)
 static const struct of_device_id mtk_jpeg_match[] = {
        {
                .compatible = "mediatek,mt8173-jpgdec",
@@ -1928,7 +1956,7 @@ MODULE_DEVICE_TABLE(of, mtk_jpeg_match);
 
 static struct platform_driver mtk_jpeg_driver = {
        .probe = mtk_jpeg_probe,
-       .remove = mtk_jpeg_remove,
+       .remove_new = mtk_jpeg_remove,
        .driver = {
                .name           = MTK_JPEG_NAME,
                .of_match_table = of_match_ptr(mtk_jpeg_match),
index b9126476be8fa0ebe44bd535195a4385ea73eb1d..8ba6e757e11aa93e154c2fa9c7965cd494753765 100644 (file)
@@ -60,6 +60,8 @@ enum mtk_jpeg_ctx_state {
  * @ioctl_ops:                 the callback of jpeg v4l2_ioctl_ops
  * @out_q_default_fourcc:      output queue default fourcc
  * @cap_q_default_fourcc:      capture queue default fourcc
+ * @multi_core:                mark jpeg hw is multi_core or not
+ * @jpeg_worker:               jpeg dec or enc worker
  */
 struct mtk_jpeg_variant {
        struct clk_bulk_data *clks;
@@ -74,6 +76,8 @@ struct mtk_jpeg_variant {
        const struct v4l2_ioctl_ops *ioctl_ops;
        u32 out_q_default_fourcc;
        u32 cap_q_default_fourcc;
+       bool multi_core;
+       void (*jpeg_worker)(struct work_struct *work);
 };
 
 struct mtk_jpeg_src_buf {
@@ -199,16 +203,12 @@ struct mtk_jpegdec_comp_dev {
  * @job_timeout_work:  IRQ timeout structure
  * @variant:           driver variant to be used
  * @reg_encbase:       jpg encode register base addr
- * @enc_hw_dev:                jpg encode hardware device
- * @is_jpgenc_multihw: the flag of multi-hw core
- * @enc_hw_wq:         jpg encode wait queue
- * @enchw_rdy:         jpg encode hw ready flag
+ * @enc_hw_dev:        jpg encode hardware device
+ * @hw_wq:             jpg wait queue
+ * @hw_rdy:            jpg hw ready flag
  * @reg_decbase:       jpg decode register base addr
- * @dec_hw_dev:                jpg decode hardware device
- * @is_jpgdec_multihw: the flag of dec multi-hw core
- * @dec_hw_wq:         jpg decode wait queue
- * @dec_workqueue:     jpg decode work queue
- * @dechw_rdy:         jpg decode hw ready flag
+ * @dec_hw_dev:        jpg decode hardware device
+ * @hw_index:          jpg hw index
  */
 struct mtk_jpeg_dev {
        struct mutex            lock;
@@ -225,16 +225,12 @@ struct mtk_jpeg_dev {
 
        void __iomem *reg_encbase[MTK_JPEGENC_HW_MAX];
        struct mtk_jpegenc_comp_dev *enc_hw_dev[MTK_JPEGENC_HW_MAX];
-       bool is_jpgenc_multihw;
-       wait_queue_head_t enc_hw_wq;
-       atomic_t enchw_rdy;
+       wait_queue_head_t hw_wq;
+       atomic_t hw_rdy;
 
        void __iomem *reg_decbase[MTK_JPEGDEC_HW_MAX];
        struct mtk_jpegdec_comp_dev *dec_hw_dev[MTK_JPEGDEC_HW_MAX];
-       bool is_jpgdec_multihw;
-       wait_queue_head_t dec_hw_wq;
-       struct workqueue_struct *dec_workqueue;
-       atomic_t dechw_rdy;
+       atomic_t hw_index;
 };
 
 /**
index 8c07fa02fd9acdd85df91004a90a138869649a86..869068fac5e2f9ae8cb25e02ce12be285fd6d25d 100644 (file)
@@ -503,8 +503,8 @@ static void mtk_jpegdec_timeout_work(struct work_struct *work)
        clk_disable_unprepare(cjpeg->jdec_clk.clks->clk);
        pm_runtime_put(cjpeg->dev);
        cjpeg->hw_state = MTK_JPEG_HW_IDLE;
-       atomic_inc(&master_jpeg->dechw_rdy);
-       wake_up(&master_jpeg->dec_hw_wq);
+       atomic_inc(&master_jpeg->hw_rdy);
+       wake_up(&master_jpeg->hw_wq);
        v4l2_m2m_buf_done(src_buf, buf_state);
        mtk_jpegdec_put_buf(cjpeg);
 }
@@ -551,8 +551,8 @@ static irqreturn_t mtk_jpegdec_hw_irq_handler(int irq, void *priv)
        clk_disable_unprepare(jpeg->jdec_clk.clks->clk);
 
        jpeg->hw_state = MTK_JPEG_HW_IDLE;
-       wake_up(&master_jpeg->dec_hw_wq);
-       atomic_inc(&master_jpeg->dechw_rdy);
+       wake_up(&master_jpeg->hw_wq);
+       atomic_inc(&master_jpeg->hw_rdy);
 
        return IRQ_HANDLED;
 }
@@ -608,25 +608,12 @@ static int mtk_jpegdec_hw_probe(struct platform_device *pdev)
        dev->plat_dev = pdev;
        dev->dev = &pdev->dev;
 
-       if (!master_dev->is_jpgdec_multihw) {
-               master_dev->is_jpgdec_multihw = true;
-               for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++)
-                       master_dev->dec_hw_dev[i] = NULL;
-
-               init_waitqueue_head(&master_dev->dec_hw_wq);
-               master_dev->workqueue = alloc_ordered_workqueue(MTK_JPEG_NAME,
-                                                               WQ_MEM_RECLAIM
-                                                               | WQ_FREEZABLE);
-               if (!master_dev->workqueue)
-                       return -EINVAL;
-
-               ret = devm_add_action_or_reset(&pdev->dev, mtk_jpegdec_destroy_workqueue,
-                                              master_dev->workqueue);
-               if (ret)
-                       return ret;
-       }
+       ret = devm_add_action_or_reset(&pdev->dev,
+                                      mtk_jpegdec_destroy_workqueue,
+                                      master_dev->workqueue);
+       if (ret)
+               return ret;
 
-       atomic_set(&master_dev->dechw_rdy, MTK_JPEGDEC_HW_MAX);
        spin_lock_init(&dev->hw_lock);
        dev->hw_state = MTK_JPEG_HW_IDLE;
 
@@ -651,14 +638,10 @@ static int mtk_jpegdec_hw_probe(struct platform_device *pdev)
                return dev_err_probe(&pdev->dev, ret,
                                     "Failed to register JPEGDEC irq handler.\n");
 
-       for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) {
-               if (master_dev->dec_hw_dev[i])
-                       continue;
-
-               master_dev->dec_hw_dev[i] = dev;
-               master_dev->reg_decbase[i] = dev->reg_base;
-               dev->master_dev = master_dev;
-       }
+       i = atomic_add_return(1, &master_dev->hw_index) - 1;
+       master_dev->dec_hw_dev[i] = dev;
+       master_dev->reg_decbase[i] = dev->reg_base;
+       dev->master_dev = master_dev;
 
        platform_set_drvdata(pdev, dev);
        pm_runtime_enable(&pdev->dev);
index 1bbb712d78d0e64057e7ac13502958a11b508c24..71e85b4bbf12762ae175dd6af8ecbdc9bc93101b 100644 (file)
@@ -248,8 +248,8 @@ static void mtk_jpegenc_timeout_work(struct work_struct *work)
        clk_disable_unprepare(cjpeg->venc_clk.clks->clk);
        pm_runtime_put(cjpeg->dev);
        cjpeg->hw_state = MTK_JPEG_HW_IDLE;
-       atomic_inc(&master_jpeg->enchw_rdy);
-       wake_up(&master_jpeg->enc_hw_wq);
+       atomic_inc(&master_jpeg->hw_rdy);
+       wake_up(&master_jpeg->hw_wq);
        v4l2_m2m_buf_done(src_buf, buf_state);
        mtk_jpegenc_put_buf(cjpeg);
 }
@@ -286,14 +286,10 @@ static irqreturn_t mtk_jpegenc_hw_irq_handler(int irq, void *priv)
        mtk_jpegenc_put_buf(jpeg);
        pm_runtime_put(ctx->jpeg->dev);
        clk_disable_unprepare(jpeg->venc_clk.clks->clk);
-       if (!list_empty(&ctx->fh.m2m_ctx->out_q_ctx.rdy_queue) ||
-           !list_empty(&ctx->fh.m2m_ctx->cap_q_ctx.rdy_queue)) {
-               queue_work(master_jpeg->workqueue, &ctx->jpeg_work);
-       }
 
        jpeg->hw_state = MTK_JPEG_HW_IDLE;
-       wake_up(&master_jpeg->enc_hw_wq);
-       atomic_inc(&master_jpeg->enchw_rdy);
+       wake_up(&master_jpeg->hw_wq);
+       atomic_inc(&master_jpeg->hw_rdy);
 
        return IRQ_HANDLED;
 }
@@ -344,20 +340,6 @@ static int mtk_jpegenc_hw_probe(struct platform_device *pdev)
        dev->plat_dev = pdev;
        dev->dev = &pdev->dev;
 
-       if (!master_dev->is_jpgenc_multihw) {
-               master_dev->is_jpgenc_multihw = true;
-               for (i = 0; i < MTK_JPEGENC_HW_MAX; i++)
-                       master_dev->enc_hw_dev[i] = NULL;
-
-               init_waitqueue_head(&master_dev->enc_hw_wq);
-               master_dev->workqueue = alloc_ordered_workqueue(MTK_JPEG_NAME,
-                                                               WQ_MEM_RECLAIM
-                                                               | WQ_FREEZABLE);
-               if (!master_dev->workqueue)
-                       return -EINVAL;
-       }
-
-       atomic_set(&master_dev->enchw_rdy, MTK_JPEGENC_HW_MAX);
        spin_lock_init(&dev->hw_lock);
        dev->hw_state = MTK_JPEG_HW_IDLE;
 
@@ -380,14 +362,10 @@ static int mtk_jpegenc_hw_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
-               if (master_dev->enc_hw_dev[i])
-                       continue;
-
-               master_dev->enc_hw_dev[i] = dev;
-               master_dev->reg_encbase[i] = dev->reg_base;
-               dev->master_dev = master_dev;
-       }
+       i = atomic_add_return(1, &master_dev->hw_index) - 1;
+       master_dev->enc_hw_dev[i] = dev;
+       master_dev->reg_encbase[i] = dev->reg_base;
+       dev->master_dev = master_dev;
 
        platform_set_drvdata(pdev, dev);
        pm_runtime_enable(&pdev->dev);
index d83c4964eaf939a4ade52458051dca393ebf8c7f..77e310e588e59c96d37bdba54385360597e4a2e6 100644 (file)
@@ -235,7 +235,7 @@ err_comp:
        return ret;
 }
 
-static int mtk_mdp_remove(struct platform_device *pdev)
+static void mtk_mdp_remove(struct platform_device *pdev)
 {
        struct mtk_mdp_dev *mdp = platform_get_drvdata(pdev);
        struct mtk_mdp_comp *comp, *comp_temp;
@@ -255,7 +255,6 @@ static int mtk_mdp_remove(struct platform_device *pdev)
        }
 
        dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
-       return 0;
 }
 
 static int __maybe_unused mtk_mdp_pm_suspend(struct device *dev)
@@ -299,7 +298,7 @@ static const struct dev_pm_ops mtk_mdp_pm_ops = {
 
 static struct platform_driver mtk_mdp_driver = {
        .probe          = mtk_mdp_probe,
-       .remove         = mtk_mdp_remove,
+       .remove_new     = mtk_mdp_remove,
        .driver = {
                .name   = MTK_MDP_MODULE_NAME,
                .pm     = &mtk_mdp_pm_ops,
index 63e6c87e480b4cc57e5a9850a9f51079e1252c78..2ee24195a2dd70621b52711a63e8a9cb85889a88 100644 (file)
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-mtk-mdp3-y += mtk-mdp3-core.o mtk-mdp3-vpu.o mtk-mdp3-regs.o
+mtk-mdp3-y += mdp_cfg_data.o mtk-mdp3-core.o mtk-mdp3-vpu.o mtk-mdp3-regs.o
 mtk-mdp3-y += mtk-mdp3-m2m.o
 mtk-mdp3-y += mtk-mdp3-comp.o mtk-mdp3-cmdq.o
 
diff --git a/drivers/media/platform/mediatek/mdp3/mdp_cfg_data.c b/drivers/media/platform/mediatek/mdp3/mdp_cfg_data.c
new file mode 100644 (file)
index 0000000..502eeae
--- /dev/null
@@ -0,0 +1,453 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
+ */
+
+#include "mtk-img-ipi.h"
+#include "mtk-mdp3-cfg.h"
+#include "mtk-mdp3-core.h"
+#include "mtk-mdp3-comp.h"
+#include "mtk-mdp3-regs.h"
+
+enum mt8183_mdp_comp_id {
+       /* ISP */
+       MT8183_MDP_COMP_WPEI = 0,
+       MT8183_MDP_COMP_WPEO,           /* 1 */
+       MT8183_MDP_COMP_WPEI2,          /* 2 */
+       MT8183_MDP_COMP_WPEO2,          /* 3 */
+       MT8183_MDP_COMP_ISP_IMGI,       /* 4 */
+       MT8183_MDP_COMP_ISP_IMGO,       /* 5 */
+       MT8183_MDP_COMP_ISP_IMG2O,      /* 6 */
+
+       /* IPU */
+       MT8183_MDP_COMP_IPUI,           /* 7 */
+       MT8183_MDP_COMP_IPUO,           /* 8 */
+
+       /* MDP */
+       MT8183_MDP_COMP_CAMIN,          /* 9 */
+       MT8183_MDP_COMP_CAMIN2,         /* 10 */
+       MT8183_MDP_COMP_RDMA0,          /* 11 */
+       MT8183_MDP_COMP_AAL0,           /* 12 */
+       MT8183_MDP_COMP_CCORR0,         /* 13 */
+       MT8183_MDP_COMP_RSZ0,           /* 14 */
+       MT8183_MDP_COMP_RSZ1,           /* 15 */
+       MT8183_MDP_COMP_TDSHP0,         /* 16 */
+       MT8183_MDP_COMP_COLOR0,         /* 17 */
+       MT8183_MDP_COMP_PATH0_SOUT,     /* 18 */
+       MT8183_MDP_COMP_PATH1_SOUT,     /* 19 */
+       MT8183_MDP_COMP_WROT0,          /* 20 */
+       MT8183_MDP_COMP_WDMA,           /* 21 */
+
+       /* Dummy Engine */
+       MT8183_MDP_COMP_RDMA1,          /* 22 */
+       MT8183_MDP_COMP_RSZ2,           /* 23 */
+       MT8183_MDP_COMP_TDSHP1,         /* 24 */
+       MT8183_MDP_COMP_WROT1,          /* 25 */
+};
+
+static const struct of_device_id mt8183_mdp_probe_infra[MDP_INFRA_MAX] = {
+       [MDP_INFRA_MMSYS] = { .compatible = "mediatek,mt8183-mmsys" },
+       [MDP_INFRA_MUTEX] = { .compatible = "mediatek,mt8183-disp-mutex" },
+       [MDP_INFRA_SCP] = { .compatible = "mediatek,mt8183-scp" }
+};
+
+static const struct mdp_platform_config mt8183_plat_cfg = {
+       .rdma_support_10bit             = true,
+       .rdma_rsz1_sram_sharing         = true,
+       .rdma_upsample_repeat_only      = true,
+       .rsz_disable_dcm_small_sample   = false,
+       .wrot_filter_constraint         = false,
+};
+
+static const u32 mt8183_mutex_idx[MDP_MAX_COMP_COUNT] = {
+       [MDP_COMP_RDMA0] = MUTEX_MOD_IDX_MDP_RDMA0,
+       [MDP_COMP_RSZ0] = MUTEX_MOD_IDX_MDP_RSZ0,
+       [MDP_COMP_RSZ1] = MUTEX_MOD_IDX_MDP_RSZ1,
+       [MDP_COMP_TDSHP0] = MUTEX_MOD_IDX_MDP_TDSHP0,
+       [MDP_COMP_WROT0] = MUTEX_MOD_IDX_MDP_WROT0,
+       [MDP_COMP_WDMA] = MUTEX_MOD_IDX_MDP_WDMA,
+       [MDP_COMP_AAL0] = MUTEX_MOD_IDX_MDP_AAL0,
+       [MDP_COMP_CCORR0] = MUTEX_MOD_IDX_MDP_CCORR0,
+};
+
+static const struct mdp_comp_data mt8183_mdp_comp_data[MDP_MAX_COMP_COUNT] = {
+       [MDP_COMP_WPEI] = {
+               {MDP_COMP_TYPE_WPEI, 0, MT8183_MDP_COMP_WPEI},
+               {0, 0, 0}
+       },
+       [MDP_COMP_WPEO] = {
+               {MDP_COMP_TYPE_EXTO, 2, MT8183_MDP_COMP_WPEO},
+               {0, 0, 0}
+       },
+       [MDP_COMP_WPEI2] = {
+               {MDP_COMP_TYPE_WPEI, 1, MT8183_MDP_COMP_WPEI2},
+               {0, 0, 0}
+       },
+       [MDP_COMP_WPEO2] = {
+               {MDP_COMP_TYPE_EXTO, 3, MT8183_MDP_COMP_WPEO2},
+               {0, 0, 0}
+       },
+       [MDP_COMP_ISP_IMGI] = {
+               {MDP_COMP_TYPE_IMGI, 0, MT8183_MDP_COMP_ISP_IMGI},
+               {0, 0, 4}
+       },
+       [MDP_COMP_ISP_IMGO] = {
+               {MDP_COMP_TYPE_EXTO, 0, MT8183_MDP_COMP_ISP_IMGO},
+               {0, 0, 4}
+       },
+       [MDP_COMP_ISP_IMG2O] = {
+               {MDP_COMP_TYPE_EXTO, 1, MT8183_MDP_COMP_ISP_IMG2O},
+               {0, 0, 0}
+       },
+       [MDP_COMP_CAMIN] = {
+               {MDP_COMP_TYPE_DL_PATH, 0, MT8183_MDP_COMP_CAMIN},
+               {2, 2, 1}
+       },
+       [MDP_COMP_CAMIN2] = {
+               {MDP_COMP_TYPE_DL_PATH, 1, MT8183_MDP_COMP_CAMIN2},
+               {2, 4, 1}
+       },
+       [MDP_COMP_RDMA0] = {
+               {MDP_COMP_TYPE_RDMA, 0, MT8183_MDP_COMP_RDMA0},
+               {2, 0, 0}
+       },
+       [MDP_COMP_CCORR0] = {
+               {MDP_COMP_TYPE_CCORR, 0, MT8183_MDP_COMP_CCORR0},
+               {1, 0, 0}
+       },
+       [MDP_COMP_RSZ0] = {
+               {MDP_COMP_TYPE_RSZ, 0, MT8183_MDP_COMP_RSZ0},
+               {1, 0, 0}
+       },
+       [MDP_COMP_RSZ1] = {
+               {MDP_COMP_TYPE_RSZ, 1, MT8183_MDP_COMP_RSZ1},
+               {1, 0, 0}
+       },
+       [MDP_COMP_TDSHP0] = {
+               {MDP_COMP_TYPE_TDSHP, 0, MT8183_MDP_COMP_TDSHP0},
+               {0, 0, 0}
+       },
+       [MDP_COMP_PATH0_SOUT] = {
+               {MDP_COMP_TYPE_PATH, 0, MT8183_MDP_COMP_PATH0_SOUT},
+               {0, 0, 0}
+       },
+       [MDP_COMP_PATH1_SOUT] = {
+               {MDP_COMP_TYPE_PATH, 1, MT8183_MDP_COMP_PATH1_SOUT},
+               {0, 0, 0}
+       },
+       [MDP_COMP_WROT0] = {
+               {MDP_COMP_TYPE_WROT, 0, MT8183_MDP_COMP_WROT0},
+               {1, 0, 0}
+       },
+       [MDP_COMP_WDMA] = {
+               {MDP_COMP_TYPE_WDMA, 0, MT8183_MDP_COMP_WDMA},
+               {1, 0, 0}
+       },
+};
+
+static const struct of_device_id mt8183_sub_comp_dt_ids[] = {
+       {
+               .compatible = "mediatek,mt8183-mdp3-wdma",
+               .data = (void *)MDP_COMP_TYPE_PATH,
+       }, {
+               .compatible = "mediatek,mt8183-mdp3-wrot",
+               .data = (void *)MDP_COMP_TYPE_PATH,
+       },
+       {}
+};
+
+/*
+ * All 10-bit related formats are not added in the basic format list,
+ * please add the corresponding format settings before use.
+ */
+static const struct mdp_format mt8183_formats[] = {
+       {
+               .pixelformat    = V4L2_PIX_FMT_GREY,
+               .mdp_color      = MDP_COLOR_GREY,
+               .depth          = { 8 },
+               .row_depth      = { 8 },
+               .num_planes     = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_RGB565X,
+               .mdp_color      = MDP_COLOR_BGR565,
+               .depth          = { 16 },
+               .row_depth      = { 16 },
+               .num_planes     = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_RGB565,
+               .mdp_color      = MDP_COLOR_RGB565,
+               .depth          = { 16 },
+               .row_depth      = { 16 },
+               .num_planes     = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_RGB24,
+               .mdp_color      = MDP_COLOR_RGB888,
+               .depth          = { 24 },
+               .row_depth      = { 24 },
+               .num_planes     = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_BGR24,
+               .mdp_color      = MDP_COLOR_BGR888,
+               .depth          = { 24 },
+               .row_depth      = { 24 },
+               .num_planes     = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_ABGR32,
+               .mdp_color      = MDP_COLOR_BGRA8888,
+               .depth          = { 32 },
+               .row_depth      = { 32 },
+               .num_planes     = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_ARGB32,
+               .mdp_color      = MDP_COLOR_ARGB8888,
+               .depth          = { 32 },
+               .row_depth      = { 32 },
+               .num_planes     = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_UYVY,
+               .mdp_color      = MDP_COLOR_UYVY,
+               .depth          = { 16 },
+               .row_depth      = { 16 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_VYUY,
+               .mdp_color      = MDP_COLOR_VYUY,
+               .depth          = { 16 },
+               .row_depth      = { 16 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_YUYV,
+               .mdp_color      = MDP_COLOR_YUYV,
+               .depth          = { 16 },
+               .row_depth      = { 16 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_YVYU,
+               .mdp_color      = MDP_COLOR_YVYU,
+               .depth          = { 16 },
+               .row_depth      = { 16 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_YUV420,
+               .mdp_color      = MDP_COLOR_I420,
+               .depth          = { 12 },
+               .row_depth      = { 8 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .halign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_YVU420,
+               .mdp_color      = MDP_COLOR_YV12,
+               .depth          = { 12 },
+               .row_depth      = { 8 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .halign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV12,
+               .mdp_color      = MDP_COLOR_NV12,
+               .depth          = { 12 },
+               .row_depth      = { 8 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .halign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV21,
+               .mdp_color      = MDP_COLOR_NV21,
+               .depth          = { 12 },
+               .row_depth      = { 8 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .halign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV16,
+               .mdp_color      = MDP_COLOR_NV16,
+               .depth          = { 16 },
+               .row_depth      = { 8 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV61,
+               .mdp_color      = MDP_COLOR_NV61,
+               .depth          = { 16 },
+               .row_depth      = { 8 },
+               .num_planes     = 1,
+               .walign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV24,
+               .mdp_color      = MDP_COLOR_NV24,
+               .depth          = { 24 },
+               .row_depth      = { 8 },
+               .num_planes     = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV42,
+               .mdp_color      = MDP_COLOR_NV42,
+               .depth          = { 24 },
+               .row_depth      = { 8 },
+               .num_planes     = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_MT21C,
+               .mdp_color      = MDP_COLOR_420_BLK_UFO,
+               .depth          = { 8, 4 },
+               .row_depth      = { 8, 8 },
+               .num_planes     = 2,
+               .walign         = 4,
+               .halign         = 5,
+               .flags          = MDP_FMT_FLAG_OUTPUT,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_MM21,
+               .mdp_color      = MDP_COLOR_420_BLK,
+               .depth          = { 8, 4 },
+               .row_depth      = { 8, 8 },
+               .num_planes     = 2,
+               .walign         = 4,
+               .halign         = 5,
+               .flags          = MDP_FMT_FLAG_OUTPUT,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV12M,
+               .mdp_color      = MDP_COLOR_NV12,
+               .depth          = { 8, 4 },
+               .row_depth      = { 8, 8 },
+               .num_planes     = 2,
+               .walign         = 1,
+               .halign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV21M,
+               .mdp_color      = MDP_COLOR_NV21,
+               .depth          = { 8, 4 },
+               .row_depth      = { 8, 8 },
+               .num_planes     = 2,
+               .walign         = 1,
+               .halign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV16M,
+               .mdp_color      = MDP_COLOR_NV16,
+               .depth          = { 8, 8 },
+               .row_depth      = { 8, 8 },
+               .num_planes     = 2,
+               .walign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_NV61M,
+               .mdp_color      = MDP_COLOR_NV61,
+               .depth          = { 8, 8 },
+               .row_depth      = { 8, 8 },
+               .num_planes     = 2,
+               .walign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_YUV420M,
+               .mdp_color      = MDP_COLOR_I420,
+               .depth          = { 8, 2, 2 },
+               .row_depth      = { 8, 4, 4 },
+               .num_planes     = 3,
+               .walign         = 1,
+               .halign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }, {
+               .pixelformat    = V4L2_PIX_FMT_YVU420M,
+               .mdp_color      = MDP_COLOR_YV12,
+               .depth          = { 8, 2, 2 },
+               .row_depth      = { 8, 4, 4 },
+               .num_planes     = 3,
+               .walign         = 1,
+               .halign         = 1,
+               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
+       }
+};
+
+static const struct mdp_limit mt8183_mdp_def_limit = {
+       .out_limit = {
+               .wmin   = 16,
+               .hmin   = 16,
+               .wmax   = 8176,
+               .hmax   = 8176,
+       },
+       .cap_limit = {
+               .wmin   = 2,
+               .hmin   = 2,
+               .wmax   = 8176,
+               .hmax   = 8176,
+       },
+       .h_scale_up_max = 32,
+       .v_scale_up_max = 32,
+       .h_scale_down_max = 20,
+       .v_scale_down_max = 128,
+};
+
+static const struct mdp_pipe_info mt8183_pipe_info[] = {
+       [MDP_PIPE_WPEI] = {MDP_PIPE_WPEI, 0},
+       [MDP_PIPE_WPEI2] = {MDP_PIPE_WPEI2, 1},
+       [MDP_PIPE_IMGI] = {MDP_PIPE_IMGI, 2},
+       [MDP_PIPE_RDMA0] = {MDP_PIPE_RDMA0, 3}
+};
+
+const struct mtk_mdp_driver_data mt8183_mdp_driver_data = {
+       .mdp_plat_id = MT8183,
+       .mdp_probe_infra = mt8183_mdp_probe_infra,
+       .mdp_cfg = &mt8183_plat_cfg,
+       .mdp_mutex_table_idx = mt8183_mutex_idx,
+       .comp_data = mt8183_mdp_comp_data,
+       .comp_data_len = ARRAY_SIZE(mt8183_mdp_comp_data),
+       .mdp_sub_comp_dt_ids = mt8183_sub_comp_dt_ids,
+       .format = mt8183_formats,
+       .format_len = ARRAY_SIZE(mt8183_formats),
+       .def_limit = &mt8183_mdp_def_limit,
+       .pipe_info = mt8183_pipe_info,
+       .pipe_info_len = ARRAY_SIZE(mt8183_pipe_info),
+};
+
+s32 mdp_cfg_get_id_inner(struct mdp_dev *mdp_dev, enum mtk_mdp_comp_id id)
+{
+       if (!mdp_dev)
+               return MDP_COMP_NONE;
+       if (id <= MDP_COMP_NONE || id >= MDP_MAX_COMP_COUNT)
+               return MDP_COMP_NONE;
+
+       return mdp_dev->mdp_data->comp_data[id].match.inner_id;
+}
+
+enum mtk_mdp_comp_id mdp_cfg_get_id_public(struct mdp_dev *mdp_dev, s32 inner_id)
+{
+       enum mtk_mdp_comp_id public_id = MDP_COMP_NONE;
+       u32 i;
+
+       if (IS_ERR(mdp_dev) || !inner_id)
+               goto err_public_id;
+
+       for (i = 0; i < MDP_MAX_COMP_COUNT; i++) {
+               if (mdp_dev->mdp_data->comp_data[i].match.inner_id == inner_id) {
+                       public_id = i;
+                       return public_id;
+               }
+       }
+
+err_public_id:
+       return public_id;
+}
diff --git a/drivers/media/platform/mediatek/mdp3/mdp_sm_mt8183.h b/drivers/media/platform/mediatek/mdp3/mdp_sm_mt8183.h
new file mode 100644 (file)
index 0000000..8563708
--- /dev/null
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
+ */
+
+#ifndef __MDP_SM_MT8183_H__
+#define __MDP_SM_MT8183_H__
+
+#include "mtk-mdp3-type.h"
+
+/*
+ * ISP-MDP generic output information
+ * MD5 of the target SCP prebuild:
+ *     2d995ddb5c3b0cf26e96d6a823481886
+ */
+
+#define IMG_MAX_SUBFRAMES_8183      14
+
+struct img_comp_frame_8183 {
+       u32 output_disable:1;
+       u32 bypass:1;
+       u16 in_width;
+       u16 in_height;
+       u16 out_width;
+       u16 out_height;
+       struct img_crop crop;
+       u16 in_total_width;
+       u16 out_total_width;
+} __packed;
+
+struct img_comp_subfrm_8183 {
+       u32 tile_disable:1;
+       struct img_region in;
+       struct img_region out;
+       struct img_offset luma;
+       struct img_offset chroma;
+       s16 out_vertical; /* Output vertical index */
+       s16 out_horizontal; /* Output horizontal index */
+} __packed;
+
+struct mdp_rdma_subfrm_8183 {
+       u32 offset[IMG_MAX_PLANES];
+       u32 offset_0_p;
+       u32 src;
+       u32 clip;
+       u32 clip_ofst;
+} __packed;
+
+struct mdp_rdma_data_8183 {
+       u32 src_ctrl;
+       u32 control;
+       u32 iova[IMG_MAX_PLANES];
+       u32 iova_end[IMG_MAX_PLANES];
+       u32 mf_bkgd;
+       u32 mf_bkgd_in_pxl;
+       u32 sf_bkgd;
+       u32 ufo_dec_y;
+       u32 ufo_dec_c;
+       u32 transform;
+       struct mdp_rdma_subfrm_8183 subfrms[IMG_MAX_SUBFRAMES_8183];
+} __packed;
+
+struct mdp_rsz_subfrm_8183 {
+       u32 control2;
+       u32 src;
+       u32 clip;
+} __packed;
+
+struct mdp_rsz_data_8183 {
+       u32 coeff_step_x;
+       u32 coeff_step_y;
+       u32 control1;
+       u32 control2;
+       struct mdp_rsz_subfrm_8183 subfrms[IMG_MAX_SUBFRAMES_8183];
+} __packed;
+
+struct mdp_wrot_subfrm_8183 {
+       u32 offset[IMG_MAX_PLANES];
+       u32 src;
+       u32 clip;
+       u32 clip_ofst;
+       u32 main_buf;
+} __packed;
+
+struct mdp_wrot_data_8183 {
+       u32 iova[IMG_MAX_PLANES];
+       u32 control;
+       u32 stride[IMG_MAX_PLANES];
+       u32 mat_ctrl;
+       u32 fifo_test;
+       u32 filter;
+       struct mdp_wrot_subfrm_8183 subfrms[IMG_MAX_SUBFRAMES_8183];
+} __packed;
+
+struct mdp_wdma_subfrm_8183 {
+       u32 offset[IMG_MAX_PLANES];
+       u32 src;
+       u32 clip;
+       u32 clip_ofst;
+} __packed;
+
+struct mdp_wdma_data_8183 {
+       u32 wdma_cfg;
+       u32 iova[IMG_MAX_PLANES];
+       u32 w_in_byte;
+       u32 uv_stride;
+       struct mdp_wdma_subfrm_8183 subfrms[IMG_MAX_SUBFRAMES_8183];
+} __packed;
+
+struct isp_data_8183 {
+       u64 dl_flags; /* 1 << (enum mdp_comp_type) */
+       u32 smxi_iova[4];
+       u32 cq_idx;
+       u32 cq_iova;
+       u32 tpipe_iova[IMG_MAX_SUBFRAMES_8183];
+} __packed;
+
+struct img_compparam_8183 {
+       u16 type; /* enum mdp_comp_id */
+       u16 id; /* engine alias_id */
+       u32 input;
+       u32 outputs[IMG_MAX_HW_OUTPUTS];
+       u32 num_outputs;
+       struct img_comp_frame_8183 frame;
+       struct img_comp_subfrm_8183 subfrms[IMG_MAX_SUBFRAMES_8183];
+       u32 num_subfrms;
+       union {
+               struct mdp_rdma_data_8183 rdma;
+               struct mdp_rsz_data_8183 rsz;
+               struct mdp_wrot_data_8183 wrot;
+               struct mdp_wdma_data_8183 wdma;
+               struct isp_data_8183 isp;
+       };
+} __packed;
+
+struct img_config_8183 {
+       struct img_compparam_8183 components[IMG_MAX_COMPONENTS];
+       u32 num_components;
+       struct img_mmsys_ctrl ctrls[IMG_MAX_SUBFRAMES_8183];
+       u32 num_subfrms;
+} __packed;
+
+#endif  /* __MDP_SM_MT8183_H__ */
index c7f231f8ea3e74ff368e05324f0102c356b2504b..22b8b9a10ef7f5f327484d174fde11e0fb59b4c7 100644 (file)
@@ -8,19 +8,11 @@
 #ifndef __MTK_IMG_IPI_H__
 #define __MTK_IMG_IPI_H__
 
-#include <linux/types.h>
+#include <linux/err.h>
+#include "mdp_sm_mt8183.h"
+#include "mtk-mdp3-type.h"
 
-/*
- * ISP-MDP generic input information
- * MD5 of the target SCP blob:
- *     6da52bdcf4bf76a0983b313e1d4745d6
- */
-
-#define IMG_MAX_HW_INPUTS      3
-
-#define IMG_MAX_HW_OUTPUTS     4
-
-#define IMG_MAX_PLANES         3
+/* ISP-MDP generic input information */
 
 #define IMG_IPI_INIT    1
 #define IMG_IPI_DEINIT  2
@@ -71,17 +63,6 @@ struct img_image_buffer {
 
 #define IMG_SUBPIXEL_SHIFT     20
 
-struct img_crop {
-       s32 left;
-       s32 top;
-       u32 width;
-       u32 height;
-       u32 left_subpix;
-       u32 top_subpix;
-       u32 width_subpix;
-       u32 height_subpix;
-} __packed;
-
 #define IMG_CTRL_FLAG_HFLIP    BIT(0)
 #define IMG_CTRL_FLAG_DITHER   BIT(1)
 #define IMG_CTRL_FLAG_SHARPNESS        BIT(4)
@@ -132,159 +113,37 @@ struct img_frameparam {
        struct img_ipi_frameparam frameparam;
 } __packed;
 
-/* ISP-MDP generic output information */
+/* Platform config indicator */
+#define MT8183 8183
 
-struct img_comp_frame {
-       u32 output_disable;
-       u32 bypass;
-       u32 in_width;
-       u32 in_height;
-       u32 out_width;
-       u32 out_height;
-       struct img_crop crop;
-       u32 in_total_width;
-       u32 out_total_width;
-} __packed;
+#define CFG_CHECK(plat, p_id) ((plat) == (p_id))
 
-struct img_region {
-       s32 left;
-       s32 right;
-       s32 top;
-       s32 bottom;
-} __packed;
+#define _CFG_OFST(plat, cfg, ofst) ((void *)(&((cfg)->config_##plat) + (ofst)))
+#define CFG_OFST(plat, cfg, ofst) \
+       (IS_ERR_OR_NULL(cfg) ? NULL : _CFG_OFST(plat, cfg, ofst))
 
-struct img_offset {
-       s32 left;
-       s32 top;
-       u32 left_subpix;
-       u32 top_subpix;
-} __packed;
-
-struct img_comp_subfrm {
-       u32 tile_disable;
-       struct img_region in;
-       struct img_region out;
-       struct img_offset luma;
-       struct img_offset chroma;
-       s32 out_vertical; /* Output vertical index */
-       s32 out_horizontal; /* Output horizontal index */
-} __packed;
+#define _CFG_ADDR(plat, cfg, mem) (&((cfg)->config_##plat.mem))
+#define CFG_ADDR(plat, cfg, mem) \
+       (IS_ERR_OR_NULL(cfg) ? NULL : _CFG_ADDR(plat, cfg, mem))
 
-#define IMG_MAX_SUBFRAMES      14
+#define _CFG_GET(plat, cfg, mem) ((cfg)->config_##plat.mem)
+#define CFG_GET(plat, cfg, mem) \
+       (IS_ERR_OR_NULL(cfg) ? 0 : _CFG_GET(plat, cfg, mem))
 
-struct mdp_rdma_subfrm {
-       u32 offset[IMG_MAX_PLANES];
-       u32 offset_0_p;
-       u32 src;
-       u32 clip;
-       u32 clip_ofst;
-} __packed;
-
-struct mdp_rdma_data {
-       u32 src_ctrl;
-       u32 control;
-       u32 iova[IMG_MAX_PLANES];
-       u32 iova_end[IMG_MAX_PLANES];
-       u32 mf_bkgd;
-       u32 mf_bkgd_in_pxl;
-       u32 sf_bkgd;
-       u32 ufo_dec_y;
-       u32 ufo_dec_c;
-       u32 transform;
-       struct mdp_rdma_subfrm subfrms[IMG_MAX_SUBFRAMES];
-} __packed;
-
-struct mdp_rsz_subfrm {
-       u32 control2;
-       u32 src;
-       u32 clip;
-} __packed;
-
-struct mdp_rsz_data {
-       u32 coeff_step_x;
-       u32 coeff_step_y;
-       u32 control1;
-       u32 control2;
-       struct mdp_rsz_subfrm subfrms[IMG_MAX_SUBFRAMES];
-} __packed;
+#define _CFG_COMP(plat, comp, mem) ((comp)->comp_##plat.mem)
+#define CFG_COMP(plat, comp, mem) \
+       (IS_ERR_OR_NULL(comp) ? 0 : _CFG_COMP(plat, comp, mem))
 
-struct mdp_wrot_subfrm {
-       u32 offset[IMG_MAX_PLANES];
-       u32 src;
-       u32 clip;
-       u32 clip_ofst;
-       u32 main_buf;
-} __packed;
-
-struct mdp_wrot_data {
-       u32 iova[IMG_MAX_PLANES];
-       u32 control;
-       u32 stride[IMG_MAX_PLANES];
-       u32 mat_ctrl;
-       u32 fifo_test;
-       u32 filter;
-       struct mdp_wrot_subfrm subfrms[IMG_MAX_SUBFRAMES];
-} __packed;
-
-struct mdp_wdma_subfrm {
-       u32 offset[IMG_MAX_PLANES];
-       u32 src;
-       u32 clip;
-       u32 clip_ofst;
-} __packed;
-
-struct mdp_wdma_data {
-       u32 wdma_cfg;
-       u32 iova[IMG_MAX_PLANES];
-       u32 w_in_byte;
-       u32 uv_stride;
-       struct mdp_wdma_subfrm subfrms[IMG_MAX_SUBFRAMES];
-} __packed;
-
-struct isp_data {
-       u64 dl_flags; /* 1 << (enum mdp_comp_type) */
-       u32 smxi_iova[4];
-       u32 cq_idx;
-       u32 cq_iova;
-       u32 tpipe_iova[IMG_MAX_SUBFRAMES];
+struct img_config {
+       union {
+               struct img_config_8183 config_8183;
+       };
 } __packed;
 
 struct img_compparam {
-       u32 type; /* enum mdp_comp_id */
-       u32 id; /* engine alias_id */
-       u32 input;
-       u32 outputs[IMG_MAX_HW_OUTPUTS];
-       u32 num_outputs;
-       struct img_comp_frame frame;
-       struct img_comp_subfrm subfrms[IMG_MAX_SUBFRAMES];
-       u32 num_subfrms;
        union {
-               struct mdp_rdma_data rdma;
-               struct mdp_rsz_data rsz;
-               struct mdp_wrot_data wrot;
-               struct mdp_wdma_data wdma;
-               struct isp_data isp;
+               struct img_compparam_8183 comp_8183;
        };
 } __packed;
 
-#define IMG_MAX_COMPONENTS     20
-
-struct img_mux {
-       u32 reg;
-       u32 value;
-       u32 subsys_id;
-} __packed;
-
-struct img_mmsys_ctrl {
-       struct img_mux sets[IMG_MAX_COMPONENTS * 2];
-       u32 num_sets;
-} __packed;
-
-struct img_config {
-       struct img_compparam components[IMG_MAX_COMPONENTS];
-       u32 num_components;
-       struct img_mmsys_ctrl ctrls[IMG_MAX_SUBFRAMES];
-       u32 num_subfrms;
-} __packed;
-
 #endif  /* __MTK_IMG_IPI_H__ */
diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cfg.h b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cfg.h
new file mode 100644 (file)
index 0000000..dee57cc
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
+ */
+
+#ifndef __MTK_MDP3_CFG_H__
+#define __MTK_MDP3_CFG_H__
+
+#include <linux/types.h>
+
+extern const struct mtk_mdp_driver_data mt8183_mdp_driver_data;
+
+struct mdp_dev;
+enum mtk_mdp_comp_id;
+
+s32 mdp_cfg_get_id_inner(struct mdp_dev *mdp_dev, enum mtk_mdp_comp_id id);
+enum mtk_mdp_comp_id mdp_cfg_get_id_public(struct mdp_dev *mdp_dev, s32 id);
+
+#endif  /* __MTK_MDP3_CFG_H__ */
index 124c1b96e96bd4ef579d82e93086c9f8e3937db3..3177592490bee4f7aab2c1407b513b88879a73ae 100644 (file)
@@ -10,6 +10,7 @@
 #include "mtk-mdp3-comp.h"
 #include "mtk-mdp3-core.h"
 #include "mtk-mdp3-m2m.h"
+#include "mtk-img-ipi.h"
 
 #define MDP_PATH_MAX_COMPS     IMG_MAX_COMPONENTS
 
@@ -28,50 +29,62 @@ struct mdp_path {
  #define call_op(ctx, op, ...) \
        (has_op(ctx, op) ? (ctx)->comp->ops->op(ctx, ##__VA_ARGS__) : 0)
 
-static bool is_output_disabled(const struct img_compparam *param, u32 count)
+static bool is_output_disabled(int p_id, const struct img_compparam *param, u32 count)
 {
-       return (count < param->num_subfrms) ?
-               (param->frame.output_disable ||
-               param->subfrms[count].tile_disable) :
-               true;
+       u32 num = 0;
+       bool dis_output = false;
+       bool dis_tile = false;
+
+       if (CFG_CHECK(MT8183, p_id)) {
+               num = CFG_COMP(MT8183, param, num_subfrms);
+               dis_output = CFG_COMP(MT8183, param, frame.output_disable);
+               dis_tile = CFG_COMP(MT8183, param, frame.output_disable);
+       }
+
+       return (count < num) ? (dis_output || dis_tile) : true;
 }
 
 static int mdp_path_subfrm_require(const struct mdp_path *path,
                                   struct mdp_cmdq_cmd *cmd,
                                   s32 *mutex_id, u32 count)
 {
-       const struct img_config *config = path->config;
+       const int p_id = path->mdp_dev->mdp_data->mdp_plat_id;
        const struct mdp_comp_ctx *ctx;
        const struct mtk_mdp_driver_data *data = path->mdp_dev->mdp_data;
        struct device *dev = &path->mdp_dev->pdev->dev;
        struct mtk_mutex **mutex = path->mdp_dev->mdp_mutex;
        int id, index;
+       u32 num_comp = 0;
+
+       if (CFG_CHECK(MT8183, p_id))
+               num_comp = CFG_GET(MT8183, path->config, num_components);
 
        /* Decide which mutex to use based on the current pipeline */
-       switch (path->comps[0].comp->id) {
+       switch (path->comps[0].comp->public_id) {
        case MDP_COMP_RDMA0:
-               *mutex_id = MDP_PIPE_RDMA0;
+               index = MDP_PIPE_RDMA0;
                break;
        case MDP_COMP_ISP_IMGI:
-               *mutex_id = MDP_PIPE_IMGI;
+               index = MDP_PIPE_IMGI;
                break;
        case MDP_COMP_WPEI:
-               *mutex_id = MDP_PIPE_WPEI;
+               index = MDP_PIPE_WPEI;
                break;
        case MDP_COMP_WPEI2:
-               *mutex_id = MDP_PIPE_WPEI2;
+               index = MDP_PIPE_WPEI2;
                break;
        default:
                dev_err(dev, "Unknown pipeline and no mutex is assigned");
                return -EINVAL;
        }
+       *mutex_id = data->pipe_info[index].mutex_id;
 
        /* Set mutex mod */
-       for (index = 0; index < config->num_components; index++) {
+       for (index = 0; index < num_comp; index++) {
                ctx = &path->comps[index];
-               if (is_output_disabled(ctx->param, count))
+               if (is_output_disabled(p_id, ctx->param, count))
                        continue;
-               id = ctx->comp->id;
+               id = ctx->comp->public_id;
                mtk_mutex_write_mod(mutex[*mutex_id],
                                    data->mdp_mutex_table_idx[id], false);
        }
@@ -86,11 +99,12 @@ static int mdp_path_subfrm_run(const struct mdp_path *path,
                               struct mdp_cmdq_cmd *cmd,
                               s32 *mutex_id, u32 count)
 {
-       const struct img_config *config = path->config;
+       const int p_id = path->mdp_dev->mdp_data->mdp_plat_id;
        const struct mdp_comp_ctx *ctx;
        struct device *dev = &path->mdp_dev->pdev->dev;
        struct mtk_mutex **mutex = path->mdp_dev->mdp_mutex;
        int index;
+       u32 num_comp = 0;
        s32 event;
 
        if (-1 == *mutex_id) {
@@ -98,11 +112,14 @@ static int mdp_path_subfrm_run(const struct mdp_path *path,
                return -EINVAL;
        }
 
+       if (CFG_CHECK(MT8183, p_id))
+               num_comp = CFG_GET(MT8183, path->config, num_components);
+
        /* Wait WROT SRAM shared to DISP RDMA */
        /* Clear SOF event for each engine */
-       for (index = 0; index < config->num_components; index++) {
+       for (index = 0; index < num_comp; index++) {
                ctx = &path->comps[index];
-               if (is_output_disabled(ctx->param, count))
+               if (is_output_disabled(p_id, ctx->param, count))
                        continue;
                event = ctx->comp->gce_event[MDP_GCE_EVENT_SOF];
                if (event != MDP_GCE_NO_EVENT)
@@ -113,9 +130,9 @@ static int mdp_path_subfrm_run(const struct mdp_path *path,
        mtk_mutex_enable_by_cmdq(mutex[*mutex_id], (void *)&cmd->pkt);
 
        /* Wait SOF events and clear mutex modules (optional) */
-       for (index = 0; index < config->num_components; index++) {
+       for (index = 0; index < num_comp; index++) {
                ctx = &path->comps[index];
-               if (is_output_disabled(ctx->param, count))
+               if (is_output_disabled(p_id, ctx->param, count))
                        continue;
                event = ctx->comp->gce_event[MDP_GCE_EVENT_SOF];
                if (event != MDP_GCE_NO_EVENT)
@@ -127,16 +144,22 @@ static int mdp_path_subfrm_run(const struct mdp_path *path,
 
 static int mdp_path_ctx_init(struct mdp_dev *mdp, struct mdp_path *path)
 {
-       const struct img_config *config = path->config;
+       const int p_id = mdp->mdp_data->mdp_plat_id;
+       void *param = NULL;
        int index, ret;
+       u32 num_comp = 0;
 
-       if (config->num_components < 1)
+       if (CFG_CHECK(MT8183, p_id))
+               num_comp = CFG_GET(MT8183, path->config, num_components);
+
+       if (num_comp < 1)
                return -EINVAL;
 
-       for (index = 0; index < config->num_components; index++) {
+       for (index = 0; index < num_comp; index++) {
+               if (CFG_CHECK(MT8183, p_id))
+                       param = (void *)CFG_ADDR(MT8183, path->config, components[index]);
                ret = mdp_comp_ctx_config(mdp, &path->comps[index],
-                                         &config->components[index],
-                                         path->param);
+                                         param, path->param);
                if (ret)
                        return ret;
        }
@@ -147,12 +170,19 @@ static int mdp_path_ctx_init(struct mdp_dev *mdp, struct mdp_path *path)
 static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd,
                                  struct mdp_path *path, u32 count)
 {
-       const struct img_config *config = path->config;
-       const struct img_mmsys_ctrl *ctrl = &config->ctrls[count];
+       const int p_id = path->mdp_dev->mdp_data->mdp_plat_id;
+       const struct img_mmsys_ctrl *ctrl = NULL;
        const struct img_mux *set;
        struct mdp_comp_ctx *ctx;
        s32 mutex_id;
        int index, ret;
+       u32 num_comp = 0;
+
+       if (CFG_CHECK(MT8183, p_id))
+               num_comp = CFG_GET(MT8183, path->config, num_components);
+
+       if (CFG_CHECK(MT8183, p_id))
+               ctrl = CFG_ADDR(MT8183, path->config, ctrls[count]);
 
        /* Acquire components */
        ret = mdp_path_subfrm_require(path, cmd, &mutex_id, count);
@@ -165,9 +195,9 @@ static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd,
                                    set->value, 0xFFFFFFFF);
        }
        /* Config sub-frame information */
-       for (index = (config->num_components - 1); index >= 0; index--) {
+       for (index = (num_comp - 1); index >= 0; index--) {
                ctx = &path->comps[index];
-               if (is_output_disabled(ctx->param, count))
+               if (is_output_disabled(p_id, ctx->param, count))
                        continue;
                ret = call_op(ctx, config_subfrm, cmd, count);
                if (ret)
@@ -178,16 +208,16 @@ static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd,
        if (ret)
                return ret;
        /* Wait components done */
-       for (index = 0; index < config->num_components; index++) {
+       for (index = 0; index < num_comp; index++) {
                ctx = &path->comps[index];
-               if (is_output_disabled(ctx->param, count))
+               if (is_output_disabled(p_id, ctx->param, count))
                        continue;
                ret = call_op(ctx, wait_comp_event, cmd);
                if (ret)
                        return ret;
        }
        /* Advance to the next sub-frame */
-       for (index = 0; index < config->num_components; index++) {
+       for (index = 0; index < num_comp; index++) {
                ctx = &path->comps[index];
                ret = call_op(ctx, advance_subfrm, cmd, count);
                if (ret)
@@ -206,23 +236,35 @@ static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd,
 static int mdp_path_config(struct mdp_dev *mdp, struct mdp_cmdq_cmd *cmd,
                           struct mdp_path *path)
 {
-       const struct img_config *config = path->config;
+       const int p_id = mdp->mdp_data->mdp_plat_id;
        struct mdp_comp_ctx *ctx;
        int index, count, ret;
+       u32 num_comp = 0;
+       u32 num_sub = 0;
+
+       if (CFG_CHECK(MT8183, p_id))
+               num_comp = CFG_GET(MT8183, path->config, num_components);
+
+       if (CFG_CHECK(MT8183, p_id))
+               num_sub = CFG_GET(MT8183, path->config, num_subfrms);
 
        /* Config path frame */
        /* Reset components */
-       for (index = 0; index < config->num_components; index++) {
+       for (index = 0; index < num_comp; index++) {
                ctx = &path->comps[index];
                ret = call_op(ctx, init_comp, cmd);
                if (ret)
                        return ret;
        }
        /* Config frame mode */
-       for (index = 0; index < config->num_components; index++) {
-               const struct v4l2_rect *compose =
-                       path->composes[ctx->param->outputs[0]];
+       for (index = 0; index < num_comp; index++) {
+               const struct v4l2_rect *compose;
+               u32 out = 0;
+
+               if (CFG_CHECK(MT8183, p_id))
+                       out = CFG_COMP(MT8183, ctx->param, outputs[0]);
 
+               compose = path->composes[out];
                ctx = &path->comps[index];
                ret = call_op(ctx, config_frame, cmd, compose);
                if (ret)
@@ -230,13 +272,13 @@ static int mdp_path_config(struct mdp_dev *mdp, struct mdp_cmdq_cmd *cmd,
        }
 
        /* Config path sub-frames */
-       for (count = 0; count < config->num_subfrms; count++) {
+       for (count = 0; count < num_sub; count++) {
                ret = mdp_path_config_subfrm(cmd, path, count);
                if (ret)
                        return ret;
        }
        /* Post processing information */
-       for (index = 0; index < config->num_components; index++) {
+       for (index = 0; index < num_comp; index++) {
                ctx = &path->comps[index];
                ret = call_op(ctx, post_process, cmd);
                if (ret)
@@ -286,11 +328,13 @@ static void mdp_auto_release_work(struct work_struct *work)
 {
        struct mdp_cmdq_cmd *cmd;
        struct mdp_dev *mdp;
+       int id;
 
        cmd = container_of(work, struct mdp_cmdq_cmd, auto_release_work);
        mdp = cmd->mdp;
 
-       mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
+       id = mdp->mdp_data->pipe_info[MDP_PIPE_RDMA0].mutex_id;
+       mtk_mutex_unprepare(mdp->mdp_mutex[id]);
        mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
                            cmd->num_comps);
 
@@ -310,6 +354,7 @@ static void mdp_handle_cmdq_callback(struct mbox_client *cl, void *mssg)
        struct cmdq_cb_data *data;
        struct mdp_dev *mdp;
        struct device *dev;
+       int id;
 
        if (!mssg) {
                pr_info("%s:no callback data\n", __func__);
@@ -335,7 +380,8 @@ static void mdp_handle_cmdq_callback(struct mbox_client *cl, void *mssg)
        INIT_WORK(&cmd->auto_release_work, mdp_auto_release_work);
        if (!queue_work(mdp->clock_wq, &cmd->auto_release_work)) {
                dev_err(dev, "%s:queue_work fail!\n", __func__);
-               mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
+               id = mdp->mdp_data->pipe_info[MDP_PIPE_RDMA0].mutex_id;
+               mtk_mutex_unprepare(mdp->mdp_mutex[id]);
                mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
                                    cmd->num_comps);
 
@@ -356,7 +402,9 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
        struct mdp_cmdq_cmd *cmd = NULL;
        struct mdp_comp *comps = NULL;
        struct device *dev = &mdp->pdev->dev;
+       const int p_id = mdp->mdp_data->mdp_plat_id;
        int i, ret;
+       u32 num_comp = 0;
 
        atomic_inc(&mdp->job_count);
        if (atomic_read(&mdp->suspended)) {
@@ -374,8 +422,13 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
        if (ret)
                goto err_free_cmd;
 
-       comps = kcalloc(param->config->num_components, sizeof(*comps),
-                       GFP_KERNEL);
+       if (CFG_CHECK(MT8183, p_id)) {
+               num_comp = CFG_GET(MT8183, param->config, num_components);
+       } else {
+               ret = -EINVAL;
+               goto err_destroy_pkt;
+       }
+       comps = kcalloc(num_comp, sizeof(*comps), GFP_KERNEL);
        if (!comps) {
                ret = -ENOMEM;
                goto err_destroy_pkt;
@@ -387,7 +440,8 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
                goto err_free_comps;
        }
 
-       ret = mtk_mutex_prepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
+       i = mdp->mdp_data->pipe_info[MDP_PIPE_RDMA0].mutex_id;
+       ret = mtk_mutex_prepare(mdp->mdp_mutex[i]);
        if (ret) {
                dev_err(dev, "Fail to enable mutex clk\n");
                goto err_free_path;
@@ -406,7 +460,6 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
                path->composes[i] = param->composes[i] ?
                        param->composes[i] : &path->bounds[i];
        }
-
        ret = mdp_path_ctx_init(mdp, path);
        if (ret) {
                dev_err(dev, "mdp_path_ctx_init error\n");
@@ -420,7 +473,7 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
        }
        cmdq_pkt_finalize(&cmd->pkt);
 
-       for (i = 0; i < param->config->num_components; i++)
+       for (i = 0; i < num_comp; i++)
                memcpy(&comps[i], path->comps[i].comp,
                       sizeof(struct mdp_comp));
 
@@ -429,7 +482,7 @@ int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
        cmd->user_cmdq_cb = param->cmdq_cb;
        cmd->user_cb_data = param->cb_data;
        cmd->comps = comps;
-       cmd->num_comps = param->config->num_components;
+       cmd->num_comps = num_comp;
        cmd->mdp_ctx = param->mdp_ctx;
 
        ret = mdp_comp_clocks_on(&mdp->pdev->dev, cmd->comps, cmd->num_comps);
@@ -453,7 +506,8 @@ err_clock_off:
        mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
                            cmd->num_comps);
 err_free_path:
-       mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
+       i = mdp->mdp_data->pipe_info[MDP_PIPE_RDMA0].mutex_id;
+       mtk_mutex_unprepare(mdp->mdp_mutex[i]);
        kfree(path);
 err_free_comps:
        kfree(comps);
index 091a68685590425b5f7cf8711d94c2e708525001..75c92e282fa298d9f9367020302c31fba11031c6 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/pm_runtime.h>
+#include "mtk-mdp3-cfg.h"
 #include "mtk-mdp3-comp.h"
 #include "mtk-mdp3-core.h"
 #include "mtk-mdp3-regs.h"
@@ -19,6 +20,7 @@
 #include "mdp_reg_wdma.h"
 
 static u32 mdp_comp_alias_id[MDP_COMP_TYPE_COUNT];
+static int p_id;
 
 static inline const struct mdp_platform_config *
 __get_plat_cfg(const struct mdp_comp_ctx *ctx)
@@ -32,12 +34,18 @@ __get_plat_cfg(const struct mdp_comp_ctx *ctx)
 static s64 get_comp_flag(const struct mdp_comp_ctx *ctx)
 {
        const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
+       u32 rdma0, rsz1;
+
+       rdma0 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RDMA0);
+       rsz1 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RSZ1);
+       if (!rdma0 || !rsz1)
+               return MDP_COMP_NONE;
 
        if (mdp_cfg && mdp_cfg->rdma_rsz1_sram_sharing)
-               if (ctx->comp->id == MDP_COMP_RDMA0)
-                       return BIT(MDP_COMP_RDMA0) | BIT(MDP_COMP_RSZ1);
+               if (ctx->comp->inner_id == rdma0)
+                       return BIT(rdma0) | BIT(rsz1);
 
-       return BIT(ctx->comp->id);
+       return BIT(ctx->comp->inner_id);
 }
 
 static int init_rdma(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
@@ -45,12 +53,17 @@ static int init_rdma(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
        const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       s32 rdma0;
+
+       rdma0 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RDMA0);
+       if (!rdma0)
+               return -EINVAL;
 
        if (mdp_cfg && mdp_cfg->rdma_support_10bit) {
                struct mdp_comp *prz1 = ctx->comp->mdp_dev->comp[MDP_COMP_RSZ1];
 
                /* Disable RSZ1 */
-               if (ctx->comp->id == MDP_COMP_RDMA0 && prz1)
+               if (ctx->comp->inner_id == rdma0 && prz1)
                        MM_REG_WRITE(cmd, subsys_id, prz1->reg_base, PRZ_ENABLE,
                                     0x0, BIT(0));
        }
@@ -66,13 +79,13 @@ static int config_rdma_frame(struct mdp_comp_ctx *ctx,
                             struct mdp_cmdq_cmd *cmd,
                             const struct v4l2_rect *compose)
 {
-       const struct mdp_rdma_data *rdma = &ctx->param->rdma;
        const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
        u32 colorformat = ctx->input->buffer.format.colorformat;
        bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat);
        bool en_ufo = MDP_COLOR_IS_UFP(colorformat);
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       u32 reg = 0;
 
        if (mdp_cfg && mdp_cfg->rdma_support_10bit) {
                if (block10bit)
@@ -90,49 +103,78 @@ static int config_rdma_frame(struct mdp_comp_ctx *ctx,
                     0x00030071);
 
        /* Setup source frame info */
-       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_CON, rdma->src_ctrl,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.src_ctrl);
+       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_CON, reg,
                     0x03C8FE0F);
 
        if (mdp_cfg)
                if (mdp_cfg->rdma_support_10bit && en_ufo) {
                        /* Setup source buffer base */
+                       if (CFG_CHECK(MT8183, p_id))
+                               reg = CFG_COMP(MT8183, ctx->param, rdma.ufo_dec_y);
                        MM_REG_WRITE(cmd, subsys_id,
                                     base, MDP_RDMA_UFO_DEC_LENGTH_BASE_Y,
-                                    rdma->ufo_dec_y, 0xFFFFFFFF);
+                                    reg, 0xFFFFFFFF);
+                       if (CFG_CHECK(MT8183, p_id))
+                               reg = CFG_COMP(MT8183, ctx->param, rdma.ufo_dec_c);
                        MM_REG_WRITE(cmd, subsys_id,
                                     base, MDP_RDMA_UFO_DEC_LENGTH_BASE_C,
-                                    rdma->ufo_dec_c, 0xFFFFFFFF);
+                                    reg, 0xFFFFFFFF);
                        /* Set 10bit source frame pitch */
-                       if (block10bit)
+                       if (block10bit) {
+                               if (CFG_CHECK(MT8183, p_id))
+                                       reg = CFG_COMP(MT8183, ctx->param, rdma.mf_bkgd_in_pxl);
                                MM_REG_WRITE(cmd, subsys_id,
                                             base, MDP_RDMA_MF_BKGD_SIZE_IN_PXL,
-                                            rdma->mf_bkgd_in_pxl, 0x001FFFFF);
+                                            reg, 0x001FFFFF);
+                       }
                }
 
-       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_CON, rdma->control,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.control);
+       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_CON, reg,
                     0x1110);
        /* Setup source buffer base */
-       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_0, rdma->iova[0],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.iova[0]);
+       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_0, reg,
                     0xFFFFFFFF);
-       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_1, rdma->iova[1],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.iova[1]);
+       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_1, reg,
                     0xFFFFFFFF);
-       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_2, rdma->iova[2],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.iova[2]);
+       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_2, reg,
                     0xFFFFFFFF);
        /* Setup source buffer end */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[0]);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_0,
-                    rdma->iova_end[0], 0xFFFFFFFF);
+                    reg, 0xFFFFFFFF);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[1]);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_1,
-                    rdma->iova_end[1], 0xFFFFFFFF);
+                    reg, 0xFFFFFFFF);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[2]);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_2,
-                    rdma->iova_end[2], 0xFFFFFFFF);
+                    reg, 0xFFFFFFFF);
        /* Setup source frame pitch */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.mf_bkgd);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_BKGD_SIZE_IN_BYTE,
-                    rdma->mf_bkgd, 0x001FFFFF);
+                    reg, 0x001FFFFF);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.sf_bkgd);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SF_BKGD_SIZE_IN_BYTE,
-                    rdma->sf_bkgd, 0x001FFFFF);
+                    reg, 0x001FFFFF);
        /* Setup color transform */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.transform);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_TRANSFORM_0,
-                    rdma->transform, 0x0F110000);
+                    reg, 0x0F110000);
 
        return 0;
 }
@@ -140,47 +182,67 @@ static int config_rdma_frame(struct mdp_comp_ctx *ctx,
 static int config_rdma_subfrm(struct mdp_comp_ctx *ctx,
                              struct mdp_cmdq_cmd *cmd, u32 index)
 {
-       const struct mdp_rdma_subfrm *subfrm = &ctx->param->rdma.subfrms[index];
-       const struct img_comp_subfrm *csf = &ctx->param->subfrms[index];
        const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
        u32 colorformat = ctx->input->buffer.format.colorformat;
        bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat);
        bool en_ufo = MDP_COLOR_IS_UFP(colorformat);
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       u32 csf_l = 0, csf_r = 0;
+       u32 reg = 0;
 
        /* Enable RDMA */
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_EN, BIT(0), BIT(0));
 
        /* Set Y pixel offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[0]);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_0,
-                    subfrm->offset[0], 0xFFFFFFFF);
+                    reg, 0xFFFFFFFF);
 
        /* Set 10bit UFO mode */
-       if (mdp_cfg)
-               if (mdp_cfg->rdma_support_10bit && block10bit && en_ufo)
+       if (mdp_cfg) {
+               if (mdp_cfg->rdma_support_10bit && block10bit && en_ufo) {
+                       if (CFG_CHECK(MT8183, p_id))
+                               reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset_0_p);
                        MM_REG_WRITE(cmd, subsys_id, base,
                                     MDP_RDMA_SRC_OFFSET_0_P,
-                                    subfrm->offset_0_p, 0xFFFFFFFF);
+                                    reg, 0xFFFFFFFF);
+               }
+       }
 
        /* Set U pixel offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[1]);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_1,
-                    subfrm->offset[1], 0xFFFFFFFF);
+                    reg, 0xFFFFFFFF);
        /* Set V pixel offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[2]);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_2,
-                    subfrm->offset[2], 0xFFFFFFFF);
+                    reg, 0xFFFFFFFF);
        /* Set source size */
-       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_SRC_SIZE, subfrm->src,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].src);
+       MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_SRC_SIZE, reg,
                     0x1FFF1FFF);
        /* Set target size */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].clip);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_CLIP_SIZE,
-                    subfrm->clip, 0x1FFF1FFF);
+                    reg, 0x1FFF1FFF);
        /* Set crop offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].clip_ofst);
        MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_OFFSET_1,
-                    subfrm->clip_ofst, 0x003F001F);
+                    reg, 0x003F001F);
 
+       if (CFG_CHECK(MT8183, p_id)) {
+               csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
+               csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
+       }
        if (mdp_cfg && mdp_cfg->rdma_upsample_repeat_only)
-               if ((csf->in.right - csf->in.left + 1) > 320)
+               if ((csf_r - csf_l + 1) > 320)
                        MM_REG_WRITE(cmd, subsys_id, base,
                                     MDP_RDMA_RESV_DUMMY_0, BIT(2), BIT(2));
 
@@ -228,63 +290,97 @@ static int config_rsz_frame(struct mdp_comp_ctx *ctx,
                            struct mdp_cmdq_cmd *cmd,
                            const struct v4l2_rect *compose)
 {
-       const struct mdp_rsz_data *rsz = &ctx->param->rsz;
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       bool bypass = FALSE;
+       u32 reg = 0;
 
-       if (ctx->param->frame.bypass) {
+       if (CFG_CHECK(MT8183, p_id))
+               bypass = CFG_COMP(MT8183, ctx->param, frame.bypass);
+
+       if (bypass) {
                /* Disable RSZ */
                MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x0, BIT(0));
                return 0;
        }
 
-       MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, rsz->control1,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rsz.control1);
+       MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, reg,
                     0x03FFFDF3);
-       MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, rsz->control2,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rsz.control2);
+       MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, reg,
                     0x0FFFC290);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rsz.coeff_step_x);
        MM_REG_WRITE(cmd, subsys_id, base, PRZ_HORIZONTAL_COEFF_STEP,
-                    rsz->coeff_step_x, 0x007FFFFF);
+                    reg, 0x007FFFFF);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rsz.coeff_step_y);
        MM_REG_WRITE(cmd, subsys_id, base, PRZ_VERTICAL_COEFF_STEP,
-                    rsz->coeff_step_y, 0x007FFFFF);
+                    reg, 0x007FFFFF);
        return 0;
 }
 
 static int config_rsz_subfrm(struct mdp_comp_ctx *ctx,
                             struct mdp_cmdq_cmd *cmd, u32 index)
 {
-       const struct mdp_rsz_subfrm *subfrm = &ctx->param->rsz.subfrms[index];
-       const struct img_comp_subfrm *csf = &ctx->param->subfrms[index];
        const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       u32 csf_l = 0, csf_r = 0;
+       u32 reg = 0;
 
-       MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, subfrm->control2,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].control2);
+       MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, reg,
                     0x00003800);
-       MM_REG_WRITE(cmd, subsys_id, base, PRZ_INPUT_IMAGE, subfrm->src,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].src);
+       MM_REG_WRITE(cmd, subsys_id, base, PRZ_INPUT_IMAGE, reg,
                     0xFFFFFFFF);
 
+       if (CFG_CHECK(MT8183, p_id)) {
+               csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
+               csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
+       }
        if (mdp_cfg && mdp_cfg->rsz_disable_dcm_small_sample)
-               if ((csf->in.right - csf->in.left + 1) <= 16)
+               if ((csf_r - csf_l + 1) <= 16)
                        MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1,
                                     BIT(27), BIT(27));
 
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.left);
        MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_HORIZONTAL_INTEGER_OFFSET,
-                    csf->luma.left, 0xFFFF);
+                    reg, 0xFFFF);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.left_subpix);
        MM_REG_WRITE(cmd, subsys_id,
                     base, PRZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET,
-                    csf->luma.left_subpix, 0x1FFFFF);
+                    reg, 0x1FFFFF);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.top);
        MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_INTEGER_OFFSET,
-                    csf->luma.top, 0xFFFF);
+                    reg, 0xFFFF);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.top_subpix);
        MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_SUBPIXEL_OFFSET,
-                    csf->luma.top_subpix, 0x1FFFFF);
+                    reg, 0x1FFFFF);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, subfrms[index].chroma.left);
        MM_REG_WRITE(cmd, subsys_id,
                     base, PRZ_CHROMA_HORIZONTAL_INTEGER_OFFSET,
-                    csf->chroma.left, 0xFFFF);
+                    reg, 0xFFFF);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, subfrms[index].chroma.left_subpix);
        MM_REG_WRITE(cmd, subsys_id,
                     base, PRZ_CHROMA_HORIZONTAL_SUBPIXEL_OFFSET,
-                    csf->chroma.left_subpix, 0x1FFFFF);
+                    reg, 0x1FFFFF);
 
-       MM_REG_WRITE(cmd, subsys_id, base, PRZ_OUTPUT_IMAGE, subfrm->clip,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].clip);
+       MM_REG_WRITE(cmd, subsys_id, base, PRZ_OUTPUT_IMAGE, reg,
                     0xFFFFFFFF);
 
        return 0;
@@ -296,11 +392,16 @@ static int advance_rsz_subfrm(struct mdp_comp_ctx *ctx,
        const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
 
        if (mdp_cfg && mdp_cfg->rsz_disable_dcm_small_sample) {
-               const struct img_comp_subfrm *csf = &ctx->param->subfrms[index];
                phys_addr_t base = ctx->comp->reg_base;
                u8 subsys_id = ctx->comp->subsys_id;
+               u32 csf_l = 0, csf_r = 0;
+
+               if (CFG_CHECK(MT8183, p_id)) {
+                       csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
+                       csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
+               }
 
-               if ((csf->in.right - csf->in.left + 1) <= 16)
+               if ((csf_r - csf_l + 1) <= 16)
                        MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, 0x0,
                                     BIT(27));
        }
@@ -333,31 +434,47 @@ static int config_wrot_frame(struct mdp_comp_ctx *ctx,
                             struct mdp_cmdq_cmd *cmd,
                             const struct v4l2_rect *compose)
 {
-       const struct mdp_wrot_data *wrot = &ctx->param->wrot;
        const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       u32 reg = 0;
 
        /* Write frame base address */
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR, wrot->iova[0],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.iova[0]);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR, reg,
                     0xFFFFFFFF);
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_C, wrot->iova[1],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.iova[1]);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_C, reg,
                     0xFFFFFFFF);
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_V, wrot->iova[2],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.iova[2]);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_V, reg,
                     0xFFFFFFFF);
        /* Write frame related registers */
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_CTRL, wrot->control,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.control);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_CTRL, reg,
                     0xF131510F);
        /* Write frame Y pitch */
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE, wrot->stride[0],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.stride[0]);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE, reg,
                     0x0000FFFF);
        /* Write frame UV pitch */
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_C, wrot->stride[1],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.stride[1]);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_C, reg,
                     0xFFFF);
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_V, wrot->stride[2],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.stride[2]);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_V, reg,
                     0xFFFF);
        /* Write matrix control */
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAT_CTRL, wrot->mat_ctrl, 0xF3);
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.mat_ctrl);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAT_CTRL, reg, 0xF3);
 
        /* Set the fixed ALPHA as 0xFF */
        MM_REG_WRITE(cmd, subsys_id, base, VIDO_DITHER, 0xFF000000,
@@ -365,13 +482,18 @@ static int config_wrot_frame(struct mdp_comp_ctx *ctx,
        /* Set VIDO_EOL_SEL */
        MM_REG_WRITE(cmd, subsys_id, base, VIDO_RSV_1, BIT(31), BIT(31));
        /* Set VIDO_FIFO_TEST */
-       if (wrot->fifo_test != 0)
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.fifo_test);
+       if (reg != 0)
                MM_REG_WRITE(cmd, subsys_id, base, VIDO_FIFO_TEST,
-                            wrot->fifo_test, 0xFFF);
+                            reg, 0xFFF);
        /* Filter enable */
-       if (mdp_cfg && mdp_cfg->wrot_filter_constraint)
+       if (mdp_cfg && mdp_cfg->wrot_filter_constraint) {
+               if (CFG_CHECK(MT8183, p_id))
+                       reg = CFG_COMP(MT8183, ctx->param, wrot.filter);
                MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE,
-                            wrot->filter, 0x77);
+                            reg, 0x77);
+       }
 
        return 0;
 }
@@ -379,30 +501,44 @@ static int config_wrot_frame(struct mdp_comp_ctx *ctx,
 static int config_wrot_subfrm(struct mdp_comp_ctx *ctx,
                              struct mdp_cmdq_cmd *cmd, u32 index)
 {
-       const struct mdp_wrot_subfrm *subfrm = &ctx->param->wrot.subfrms[index];
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       u32 reg = 0;
 
        /* Write Y pixel offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[0]);
        MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR,
-                    subfrm->offset[0], 0x0FFFFFFF);
+                    reg, 0x0FFFFFFF);
        /* Write U pixel offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[1]);
        MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR_C,
-                    subfrm->offset[1], 0x0FFFFFFF);
+                    reg, 0x0FFFFFFF);
        /* Write V pixel offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[2]);
        MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR_V,
-                    subfrm->offset[2], 0x0FFFFFFF);
+                    reg, 0x0FFFFFFF);
        /* Write source size */
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_IN_SIZE, subfrm->src,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].src);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_IN_SIZE, reg,
                     0x1FFF1FFF);
        /* Write target size */
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_TAR_SIZE, subfrm->clip,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].clip);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_TAR_SIZE, reg,
                     0x1FFF1FFF);
-       MM_REG_WRITE(cmd, subsys_id, base, VIDO_CROP_OFST, subfrm->clip_ofst,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].clip_ofst);
+       MM_REG_WRITE(cmd, subsys_id, base, VIDO_CROP_OFST, reg,
                     0x1FFF1FFF);
 
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].main_buf);
        MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE,
-                    subfrm->main_buf, 0x1FFF7F00);
+                    reg, 0x1FFF7F00);
 
        /* Enable WROT */
        MM_REG_WRITE(cmd, subsys_id, base, VIDO_ROT_EN, BIT(0), BIT(0));
@@ -456,29 +592,41 @@ static int config_wdma_frame(struct mdp_comp_ctx *ctx,
                             struct mdp_cmdq_cmd *cmd,
                             const struct v4l2_rect *compose)
 {
-       const struct mdp_wdma_data *wdma = &ctx->param->wdma;
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       u32 reg = 0;
 
        MM_REG_WRITE(cmd, subsys_id, base, WDMA_BUF_CON2, 0x10101050,
                     0xFFFFFFFF);
 
        /* Setup frame information */
-       MM_REG_WRITE(cmd, subsys_id, base, WDMA_CFG, wdma->wdma_cfg,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.wdma_cfg);
+       MM_REG_WRITE(cmd, subsys_id, base, WDMA_CFG, reg,
                     0x0F01B8F0);
        /* Setup frame base address */
-       MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR,   wdma->iova[0],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.iova[0]);
+       MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR, reg,
                     0xFFFFFFFF);
-       MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR, wdma->iova[1],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.iova[1]);
+       MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR, reg,
                     0xFFFFFFFF);
-       MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR, wdma->iova[2],
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.iova[2]);
+       MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR, reg,
                     0xFFFFFFFF);
        /* Setup Y pitch */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.w_in_byte);
        MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_W_IN_BYTE,
-                    wdma->w_in_byte, 0x0000FFFF);
+                    reg, 0x0000FFFF);
        /* Setup UV pitch */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.uv_stride);
        MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_UV_PITCH,
-                    wdma->uv_stride, 0x0000FFFF);
+                    reg, 0x0000FFFF);
        /* Set the fixed ALPHA as 0xFF */
        MM_REG_WRITE(cmd, subsys_id, base, WDMA_ALPHA, 0x800000FF,
                     0x800000FF);
@@ -489,27 +637,39 @@ static int config_wdma_frame(struct mdp_comp_ctx *ctx,
 static int config_wdma_subfrm(struct mdp_comp_ctx *ctx,
                              struct mdp_cmdq_cmd *cmd, u32 index)
 {
-       const struct mdp_wdma_subfrm *subfrm = &ctx->param->wdma.subfrms[index];
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       u32 reg = 0;
 
        /* Write Y pixel offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[0]);
        MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR_OFFSET,
-                    subfrm->offset[0], 0x0FFFFFFF);
+                    reg, 0x0FFFFFFF);
        /* Write U pixel offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[1]);
        MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR_OFFSET,
-                    subfrm->offset[1], 0x0FFFFFFF);
+                    reg, 0x0FFFFFFF);
        /* Write V pixel offset */
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[2]);
        MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR_OFFSET,
-                    subfrm->offset[2], 0x0FFFFFFF);
+                    reg, 0x0FFFFFFF);
        /* Write source size */
-       MM_REG_WRITE(cmd, subsys_id, base, WDMA_SRC_SIZE, subfrm->src,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].src);
+       MM_REG_WRITE(cmd, subsys_id, base, WDMA_SRC_SIZE, reg,
                     0x3FFF3FFF);
        /* Write target size */
-       MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_SIZE, subfrm->clip,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].clip);
+       MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_SIZE, reg,
                     0x3FFF3FFF);
        /* Write clip offset */
-       MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_COORD, subfrm->clip_ofst,
+       if (CFG_CHECK(MT8183, p_id))
+               reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].clip_ofst);
+       MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_COORD, reg,
                     0x3FFF3FFF);
 
        /* Enable WDMA */
@@ -552,13 +712,21 @@ static int init_ccorr(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
 static int config_ccorr_subfrm(struct mdp_comp_ctx *ctx,
                               struct mdp_cmdq_cmd *cmd, u32 index)
 {
-       const struct img_comp_subfrm *csf = &ctx->param->subfrms[index];
        phys_addr_t base = ctx->comp->reg_base;
        u8 subsys_id = ctx->comp->subsys_id;
+       u32 csf_l = 0, csf_r = 0;
+       u32 csf_t = 0, csf_b = 0;
        u32 hsize, vsize;
 
-       hsize = csf->in.right - csf->in.left + 1;
-       vsize = csf->in.bottom - csf->in.top + 1;
+       if (CFG_CHECK(MT8183, p_id)) {
+               csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
+               csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
+               csf_t = CFG_COMP(MT8183, ctx->param, subfrms[index].in.top);
+               csf_b = CFG_COMP(MT8183, ctx->param, subfrms[index].in.bottom);
+       }
+
+       hsize = csf_r - csf_l + 1;
+       vsize = csf_b - csf_t + 1;
        MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_SIZE,
                     (hsize << 16) + (vsize <<  0), 0x1FFF1FFF);
        return 0;
@@ -578,32 +746,6 @@ static const struct mdp_comp_ops *mdp_comp_ops[MDP_COMP_TYPE_COUNT] = {
        [MDP_COMP_TYPE_CCORR] =         &ccorr_ops,
 };
 
-struct mdp_comp_match {
-       enum mdp_comp_type      type;
-       u32                     alias_id;
-};
-
-static const struct mdp_comp_match mdp_comp_matches[MDP_MAX_COMP_COUNT] = {
-       [MDP_COMP_WPEI] =       { MDP_COMP_TYPE_WPEI, 0 },
-       [MDP_COMP_WPEO] =       { MDP_COMP_TYPE_EXTO, 2 },
-       [MDP_COMP_WPEI2] =      { MDP_COMP_TYPE_WPEI, 1 },
-       [MDP_COMP_WPEO2] =      { MDP_COMP_TYPE_EXTO, 3 },
-       [MDP_COMP_ISP_IMGI] =   { MDP_COMP_TYPE_IMGI, 0 },
-       [MDP_COMP_ISP_IMGO] =   { MDP_COMP_TYPE_EXTO, 0 },
-       [MDP_COMP_ISP_IMG2O] =  { MDP_COMP_TYPE_EXTO, 1 },
-
-       [MDP_COMP_CAMIN] =      { MDP_COMP_TYPE_DL_PATH, 0 },
-       [MDP_COMP_CAMIN2] =     { MDP_COMP_TYPE_DL_PATH, 1 },
-       [MDP_COMP_RDMA0] =      { MDP_COMP_TYPE_RDMA, 0 },
-       [MDP_COMP_CCORR0] =     { MDP_COMP_TYPE_CCORR, 0 },
-       [MDP_COMP_RSZ0] =       { MDP_COMP_TYPE_RSZ, 0 },
-       [MDP_COMP_RSZ1] =       { MDP_COMP_TYPE_RSZ, 1 },
-       [MDP_COMP_PATH0_SOUT] = { MDP_COMP_TYPE_PATH, 0 },
-       [MDP_COMP_PATH1_SOUT] = { MDP_COMP_TYPE_PATH, 1 },
-       [MDP_COMP_WROT0] =      { MDP_COMP_TYPE_WROT, 0 },
-       [MDP_COMP_WDMA] =       { MDP_COMP_TYPE_WDMA, 0 },
-};
-
 static const struct of_device_id mdp_comp_dt_ids[] = {
        {
                .compatible = "mediatek,mt8183-mdp3-rdma",
@@ -624,32 +766,6 @@ static const struct of_device_id mdp_comp_dt_ids[] = {
        {}
 };
 
-static const struct of_device_id mdp_sub_comp_dt_ids[] = {
-       {
-               .compatible = "mediatek,mt8183-mdp3-wdma",
-               .data = (void *)MDP_COMP_TYPE_PATH,
-       }, {
-               .compatible = "mediatek,mt8183-mdp3-wrot",
-               .data = (void *)MDP_COMP_TYPE_PATH,
-       },
-       {}
-};
-
-/* Used to describe the item order in MDP property */
-struct mdp_comp_info {
-       u32     clk_num;
-       u32     clk_ofst;
-       u32     dts_reg_ofst;
-};
-
-static const struct mdp_comp_info mdp_comp_dt_info[MDP_MAX_COMP_COUNT] = {
-       [MDP_COMP_RDMA0]        = {2, 0, 0},
-       [MDP_COMP_RSZ0]         = {1, 0, 0},
-       [MDP_COMP_WROT0]        = {1, 0, 0},
-       [MDP_COMP_WDMA]         = {1, 0, 0},
-       [MDP_COMP_CCORR0]       = {1, 0, 0},
-};
-
 static inline bool is_dma_capable(const enum mdp_comp_type type)
 {
        return (type == MDP_COMP_TYPE_RDMA ||
@@ -666,13 +782,13 @@ static inline bool is_bypass_gce_event(const enum mdp_comp_type type)
        return (type == MDP_COMP_TYPE_PATH);
 }
 
-static int mdp_comp_get_id(enum mdp_comp_type type, int alias_id)
+static int mdp_comp_get_id(struct mdp_dev *mdp, enum mdp_comp_type type, u32 alias_id)
 {
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(mdp_comp_matches); i++)
-               if (mdp_comp_matches[i].type == type &&
-                   mdp_comp_matches[i].alias_id == alias_id)
+       for (i = 0; i < mdp->mdp_data->comp_data_len; i++)
+               if (mdp->mdp_data->comp_data[i].match.type == type &&
+                   mdp->mdp_data->comp_data[i].match.alias_id == alias_id)
                        return i;
        return -ENODEV;
 }
@@ -681,24 +797,25 @@ int mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp)
 {
        int i, ret;
 
-       if (comp->comp_dev) {
+       /* Only DMA capable components need the pm control */
+       if (comp->comp_dev && is_dma_capable(comp->type)) {
                ret = pm_runtime_resume_and_get(comp->comp_dev);
                if (ret < 0) {
                        dev_err(dev,
                                "Failed to get power, err %d. type:%d id:%d\n",
-                               ret, comp->type, comp->id);
+                               ret, comp->type, comp->inner_id);
                        return ret;
                }
        }
 
-       for (i = 0; i < ARRAY_SIZE(comp->clks); i++) {
+       for (i = 0; i < comp->clk_num; i++) {
                if (IS_ERR_OR_NULL(comp->clks[i]))
                        continue;
                ret = clk_prepare_enable(comp->clks[i]);
                if (ret) {
                        dev_err(dev,
                                "Failed to enable clk %d. type:%d id:%d\n",
-                               i, comp->type, comp->id);
+                               i, comp->type, comp->inner_id);
                        goto err_revert;
                }
        }
@@ -711,7 +828,7 @@ err_revert:
                        continue;
                clk_disable_unprepare(comp->clks[i]);
        }
-       if (comp->comp_dev)
+       if (comp->comp_dev && is_dma_capable(comp->type))
                pm_runtime_put_sync(comp->comp_dev);
 
        return ret;
@@ -721,13 +838,13 @@ void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp)
 {
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(comp->clks); i++) {
+       for (i = 0; i < comp->clk_num; i++) {
                if (IS_ERR_OR_NULL(comp->clks[i]))
                        continue;
                clk_disable_unprepare(comp->clks[i]);
        }
 
-       if (comp->comp_dev)
+       if (comp->comp_dev && is_dma_capable(comp->type))
                pm_runtime_put(comp->comp_dev);
 }
 
@@ -752,8 +869,8 @@ void mdp_comp_clocks_off(struct device *dev, struct mdp_comp *comps, int num)
                mdp_comp_clock_off(dev, &comps[i]);
 }
 
-static int mdp_get_subsys_id(struct device *dev, struct device_node *node,
-                            struct mdp_comp *comp)
+static int mdp_get_subsys_id(struct mdp_dev *mdp, struct device *dev,
+                            struct device_node *node, struct mdp_comp *comp)
 {
        struct platform_device *comp_pdev;
        struct cmdq_client_reg  cmdq_reg;
@@ -766,12 +883,12 @@ static int mdp_get_subsys_id(struct device *dev, struct device_node *node,
        comp_pdev = of_find_device_by_node(node);
 
        if (!comp_pdev) {
-               dev_err(dev, "get comp_pdev fail! comp id=%d type=%d\n",
-                       comp->id, comp->type);
+               dev_err(dev, "get comp_pdev fail! comp public id=%d, inner id=%d, type=%d\n",
+                       comp->public_id, comp->inner_id, comp->type);
                return -ENODEV;
        }
 
-       index = mdp_comp_dt_info[comp->id].dts_reg_ofst;
+       index = mdp->mdp_data->comp_data[comp->public_id].info.dts_reg_ofst;
        ret = cmdq_dev_get_client_reg(&comp_pdev->dev, &cmdq_reg, index);
        if (ret != 0) {
                dev_err(&comp_pdev->dev, "cmdq_dev_get_subsys fail!\n");
@@ -789,8 +906,9 @@ static void __mdp_comp_init(struct mdp_dev *mdp, struct device_node *node,
 {
        struct resource res;
        phys_addr_t base;
-       int index = mdp_comp_dt_info[comp->id].dts_reg_ofst;
+       int index;
 
+       index = mdp->mdp_data->comp_data[comp->public_id].info.dts_reg_ofst;
        if (of_address_to_resource(node, index, &res) < 0)
                base = 0L;
        else
@@ -805,7 +923,7 @@ static int mdp_comp_init(struct mdp_dev *mdp, struct device_node *node,
                         struct mdp_comp *comp, enum mtk_mdp_comp_id id)
 {
        struct device *dev = &mdp->pdev->dev;
-       int clk_num;
+       struct platform_device *pdev_c;
        int clk_ofst;
        int i;
        s32 event;
@@ -815,22 +933,36 @@ static int mdp_comp_init(struct mdp_dev *mdp, struct device_node *node,
                return -EINVAL;
        }
 
-       comp->id = id;
-       comp->type = mdp_comp_matches[id].type;
-       comp->alias_id = mdp_comp_matches[id].alias_id;
+       pdev_c = of_find_device_by_node(node);
+       if (!pdev_c) {
+               dev_warn(dev, "can't find platform device of node:%s\n",
+                        node->name);
+               return -ENODEV;
+       }
+
+       comp->comp_dev = &pdev_c->dev;
+       comp->public_id = id;
+       comp->type = mdp->mdp_data->comp_data[id].match.type;
+       comp->inner_id = mdp->mdp_data->comp_data[id].match.inner_id;
+       comp->alias_id = mdp->mdp_data->comp_data[id].match.alias_id;
        comp->ops = mdp_comp_ops[comp->type];
        __mdp_comp_init(mdp, node, comp);
 
-       clk_num = mdp_comp_dt_info[id].clk_num;
-       clk_ofst = mdp_comp_dt_info[id].clk_ofst;
+       comp->clk_num = mdp->mdp_data->comp_data[id].info.clk_num;
+       comp->clks = devm_kzalloc(dev, sizeof(struct clk *) * comp->clk_num,
+                                 GFP_KERNEL);
+       if (!comp->clks)
+               return -ENOMEM;
 
-       for (i = 0; i < clk_num; i++) {
+       clk_ofst = mdp->mdp_data->comp_data[id].info.clk_ofst;
+
+       for (i = 0; i < comp->clk_num; i++) {
                comp->clks[i] = of_clk_get(node, i + clk_ofst);
                if (IS_ERR(comp->clks[i]))
                        break;
        }
 
-       mdp_get_subsys_id(dev, node, comp);
+       mdp_get_subsys_id(mdp, dev, node, comp);
 
        /* Set GCE SOF event */
        if (is_bypass_gce_event(comp->type) ||
@@ -861,6 +993,11 @@ static void mdp_comp_deinit(struct mdp_comp *comp)
        if (!comp)
                return;
 
+       if (comp->comp_dev && comp->clks) {
+               devm_kfree(&comp->mdp_dev->pdev->dev, comp->clks);
+               comp->clks = NULL;
+       }
+
        if (comp->regs)
                iounmap(comp->regs);
 }
@@ -888,8 +1025,8 @@ static struct mdp_comp *mdp_comp_create(struct mdp_dev *mdp,
        mdp->comp[id] = comp;
        mdp->comp[id]->mdp_dev = mdp;
 
-       dev_dbg(dev, "%s type:%d alias:%d id:%d base:%#x regs:%p\n",
-               dev->of_node->name, comp->type, comp->alias_id, id,
+       dev_dbg(dev, "%s type:%d alias:%d public id:%d inner id:%d base:%#x regs:%p\n",
+               dev->of_node->name, comp->type, comp->alias_id, id, comp->inner_id,
                (u32)comp->reg_base, comp->regs);
        return comp;
 }
@@ -898,6 +1035,7 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp)
 {
        struct device *dev = &mdp->pdev->dev;
        struct device_node *node, *parent;
+       const struct mtk_mdp_driver_data *data = mdp->mdp_data;
 
        parent = dev->of_node->parent;
 
@@ -907,7 +1045,7 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp)
                int id, alias_id;
                struct mdp_comp *comp;
 
-               of_id = of_match_node(mdp_sub_comp_dt_ids, node);
+               of_id = of_match_node(data->mdp_sub_comp_dt_ids, node);
                if (!of_id)
                        continue;
                if (!of_device_is_available(node)) {
@@ -918,7 +1056,7 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp)
 
                type = (enum mdp_comp_type)(uintptr_t)of_id->data;
                alias_id = mdp_comp_alias_id[type];
-               id = mdp_comp_get_id(type, alias_id);
+               id = mdp_comp_get_id(mdp, type, alias_id);
                if (id < 0) {
                        dev_err(dev,
                                "Fail to get sub comp. id: type %d alias %d\n",
@@ -941,7 +1079,8 @@ void mdp_comp_destroy(struct mdp_dev *mdp)
 
        for (i = 0; i < ARRAY_SIZE(mdp->comp); i++) {
                if (mdp->comp[i]) {
-                       pm_runtime_disable(mdp->comp[i]->comp_dev);
+                       if (is_dma_capable(mdp->comp[i]->type))
+                               pm_runtime_disable(mdp->comp[i]->comp_dev);
                        mdp_comp_deinit(mdp->comp[i]);
                        devm_kfree(mdp->comp[i]->comp_dev, mdp->comp[i]);
                        mdp->comp[i] = NULL;
@@ -953,10 +1092,10 @@ int mdp_comp_config(struct mdp_dev *mdp)
 {
        struct device *dev = &mdp->pdev->dev;
        struct device_node *node, *parent;
-       struct platform_device *pdev;
        int ret;
 
        memset(mdp_comp_alias_id, 0, sizeof(mdp_comp_alias_id));
+       p_id = mdp->mdp_data->mdp_plat_id;
 
        parent = dev->of_node->parent;
        /* Iterate over sibling MDP function blocks */
@@ -978,7 +1117,7 @@ int mdp_comp_config(struct mdp_dev *mdp)
 
                type = (enum mdp_comp_type)(uintptr_t)of_id->data;
                alias_id = mdp_comp_alias_id[type];
-               id = mdp_comp_get_id(type, alias_id);
+               id = mdp_comp_get_id(mdp, type, alias_id);
                if (id < 0) {
                        dev_err(dev,
                                "Fail to get component id: type %d alias %d\n",
@@ -994,19 +1133,8 @@ int mdp_comp_config(struct mdp_dev *mdp)
                }
 
                /* Only DMA capable components need the pm control */
-               comp->comp_dev = NULL;
                if (!is_dma_capable(comp->type))
                        continue;
-
-               pdev = of_find_device_by_node(node);
-               if (!pdev) {
-                       dev_warn(dev, "can't find platform device of node:%s\n",
-                                node->name);
-                       ret = -ENODEV;
-                       goto err_init_comps;
-               }
-
-               comp->comp_dev = &pdev->dev;
                pm_runtime_enable(comp->comp_dev);
        }
 
@@ -1026,22 +1154,47 @@ int mdp_comp_ctx_config(struct mdp_dev *mdp, struct mdp_comp_ctx *ctx,
                        const struct img_ipi_frameparam *frame)
 {
        struct device *dev = &mdp->pdev->dev;
-       int i;
+       enum mtk_mdp_comp_id public_id = MDP_COMP_NONE;
+       u32 arg;
+       int i, idx;
 
-       if (param->type < 0 || param->type >= MDP_MAX_COMP_COUNT) {
-               dev_err(dev, "Invalid component id %d", param->type);
+       if (!param) {
+               dev_err(dev, "Invalid component param");
                return -EINVAL;
        }
 
-       ctx->comp = mdp->comp[param->type];
+       if (CFG_CHECK(MT8183, p_id))
+               arg = CFG_COMP(MT8183, param, type);
+       else
+               return -EINVAL;
+       public_id = mdp_cfg_get_id_public(mdp, arg);
+       if (public_id < 0) {
+               dev_err(dev, "Invalid component id %d", public_id);
+               return -EINVAL;
+       }
+
+       ctx->comp = mdp->comp[public_id];
        if (!ctx->comp) {
-               dev_err(dev, "Uninit component id %d", param->type);
+               dev_err(dev, "Uninit component inner id %d", arg);
                return -EINVAL;
        }
 
        ctx->param = param;
-       ctx->input = &frame->inputs[param->input];
-       for (i = 0; i < param->num_outputs; i++)
-               ctx->outputs[i] = &frame->outputs[param->outputs[i]];
+       if (CFG_CHECK(MT8183, p_id))
+               arg = CFG_COMP(MT8183, param, input);
+       else
+               return -EINVAL;
+       ctx->input = &frame->inputs[arg];
+       if (CFG_CHECK(MT8183, p_id))
+               idx = CFG_COMP(MT8183, param, num_outputs);
+       else
+               return -EINVAL;
+       for (i = 0; i < idx; i++) {
+               if (CFG_CHECK(MT8183, p_id))
+                       arg = CFG_COMP(MT8183, param, outputs[i]);
+               else
+                       return -EINVAL;
+               ctx->outputs[i] = &frame->outputs[arg];
+       }
        return 0;
 }
index dc48f55ac4f74aaf442297a60b1bbdab75c20014..20d2bcb77ef93c12762e45dc5fd1949dc2f36e72 100644 (file)
@@ -134,6 +134,24 @@ enum {
        MDP_GCE_EVENT_MAX,
 };
 
+struct mdp_comp_match {
+       enum mdp_comp_type type;
+       u32 alias_id;
+       s32 inner_id;
+};
+
+/* Used to describe the item order in MDP property */
+struct mdp_comp_info {
+       u32 clk_num;
+       u32 clk_ofst;
+       u32 dts_reg_ofst;
+};
+
+struct mdp_comp_data {
+       struct mdp_comp_match match;
+       struct mdp_comp_info info;
+};
+
 struct mdp_comp_ops;
 
 struct mdp_comp {
@@ -141,10 +159,12 @@ struct mdp_comp {
        void __iomem                    *regs;
        phys_addr_t                     reg_base;
        u8                              subsys_id;
-       struct clk                      *clks[6];
+       u8                              clk_num;
+       struct clk                      **clks;
        struct device                   *comp_dev;
        enum mdp_comp_type              type;
-       enum mtk_mdp_comp_id            id;
+       enum mtk_mdp_comp_id            public_id;
+       s32                             inner_id;
        u32                             alias_id;
        s32                             gce_event[MDP_GCE_EVENT_MAX];
        const struct mdp_comp_ops       *ops;
index 97edcd9d1c8173266b82a2d1b134a37a3d5ec37d..aa6c225302f0043f07373ae18274a4d70842293c 100644 (file)
 #include <linux/remoteproc.h>
 #include <linux/remoteproc/mtk_scp.h>
 #include <media/videobuf2-dma-contig.h>
+
 #include "mtk-mdp3-core.h"
+#include "mtk-mdp3-cfg.h"
 #include "mtk-mdp3-m2m.h"
 
-static const struct mdp_platform_config mt8183_plat_cfg = {
-       .rdma_support_10bit             = true,
-       .rdma_rsz1_sram_sharing         = true,
-       .rdma_upsample_repeat_only      = true,
-       .rsz_disable_dcm_small_sample   = false,
-       .wrot_filter_constraint         = false,
-};
-
-static const struct of_device_id mt8183_mdp_probe_infra[MDP_INFRA_MAX] = {
-       [MDP_INFRA_MMSYS] = { .compatible = "mediatek,mt8183-mmsys" },
-       [MDP_INFRA_MUTEX] = { .compatible = "mediatek,mt8183-disp-mutex" },
-       [MDP_INFRA_SCP] = { .compatible = "mediatek,mt8183-scp" }
-};
-
-static const u32 mt8183_mutex_idx[MDP_MAX_COMP_COUNT] = {
-       [MDP_COMP_RDMA0] = MUTEX_MOD_IDX_MDP_RDMA0,
-       [MDP_COMP_RSZ0] = MUTEX_MOD_IDX_MDP_RSZ0,
-       [MDP_COMP_RSZ1] = MUTEX_MOD_IDX_MDP_RSZ1,
-       [MDP_COMP_TDSHP0] = MUTEX_MOD_IDX_MDP_TDSHP0,
-       [MDP_COMP_WROT0] = MUTEX_MOD_IDX_MDP_WROT0,
-       [MDP_COMP_WDMA] = MUTEX_MOD_IDX_MDP_WDMA,
-       [MDP_COMP_AAL0] = MUTEX_MOD_IDX_MDP_AAL0,
-       [MDP_COMP_CCORR0] = MUTEX_MOD_IDX_MDP_CCORR0,
-};
-
-static const struct mtk_mdp_driver_data mt8183_mdp_driver_data = {
-       .mdp_probe_infra = mt8183_mdp_probe_infra,
-       .mdp_cfg = &mt8183_plat_cfg,
-       .mdp_mutex_table_idx = mt8183_mutex_idx,
-};
-
 static const struct of_device_id mdp_of_ids[] = {
        { .compatible = "mediatek,mt8183-mdp3-rdma",
          .data = &mt8183_mdp_driver_data,
@@ -182,7 +153,7 @@ static int mdp_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct mdp_dev *mdp;
        struct platform_device *mm_pdev;
-       int ret, i;
+       int ret, i, mutex_id;
 
        mdp = kzalloc(sizeof(*mdp), GFP_KERNEL);
        if (!mdp) {
@@ -205,10 +176,13 @@ static int mdp_probe(struct platform_device *pdev)
                ret = -ENODEV;
                goto err_destroy_device;
        }
-       for (i = 0; i < MDP_PIPE_MAX; i++) {
-               mdp->mdp_mutex[i] = mtk_mutex_get(&mm_pdev->dev);
-               if (IS_ERR(mdp->mdp_mutex[i])) {
-                       ret = PTR_ERR(mdp->mdp_mutex[i]);
+       for (i = 0; i < mdp->mdp_data->pipe_info_len; i++) {
+               mutex_id = mdp->mdp_data->pipe_info[i].mutex_id;
+               if (!IS_ERR_OR_NULL(mdp->mdp_mutex[mutex_id]))
+                       continue;
+               mdp->mdp_mutex[mutex_id] = mtk_mutex_get(&mm_pdev->dev);
+               if (IS_ERR(mdp->mdp_mutex[mutex_id])) {
+                       ret = PTR_ERR(mdp->mdp_mutex[mutex_id]);
                        goto err_free_mutex;
                }
        }
@@ -288,7 +262,7 @@ err_destroy_job_wq:
 err_deinit_comp:
        mdp_comp_destroy(mdp);
 err_free_mutex:
-       for (i = 0; i < MDP_PIPE_MAX; i++)
+       for (i = 0; i < mdp->mdp_data->pipe_info_len; i++)
                if (!IS_ERR_OR_NULL(mdp->mdp_mutex[i]))
                        mtk_mutex_put(mdp->mdp_mutex[i]);
 err_destroy_device:
@@ -298,14 +272,13 @@ err_return:
        return ret;
 }
 
-static int mdp_remove(struct platform_device *pdev)
+static void mdp_remove(struct platform_device *pdev)
 {
        struct mdp_dev *mdp = platform_get_drvdata(pdev);
 
        v4l2_device_unregister(&mdp->v4l2_dev);
 
        dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
-       return 0;
 }
 
 static int __maybe_unused mdp_suspend(struct device *dev)
@@ -345,7 +318,7 @@ static const struct dev_pm_ops mdp_pm_ops = {
 
 static struct platform_driver mdp_driver = {
        .probe          = mdp_probe,
-       .remove         = mdp_remove,
+       .remove_new     = mdp_remove,
        .driver = {
                .name   = MDP_MODULE_NAME,
                .pm     = &mdp_pm_ops,
index 2ef5fbc4f25a88e62fa963109eb84653642c92af..7e21d226ceb81ee02db09a59205989d0971467ef 100644 (file)
@@ -43,17 +43,26 @@ struct mdp_platform_config {
 
 /* indicate which mutex is used by each pipepline */
 enum mdp_pipe_id {
-       MDP_PIPE_RDMA0,
-       MDP_PIPE_IMGI,
        MDP_PIPE_WPEI,
        MDP_PIPE_WPEI2,
+       MDP_PIPE_IMGI,
+       MDP_PIPE_RDMA0,
        MDP_PIPE_MAX
 };
 
 struct mtk_mdp_driver_data {
+       const int mdp_plat_id;
        const struct of_device_id *mdp_probe_infra;
        const struct mdp_platform_config *mdp_cfg;
        const u32 *mdp_mutex_table_idx;
+       const struct mdp_comp_data *comp_data;
+       unsigned int comp_data_len;
+       const struct of_device_id *mdp_sub_comp_dt_ids;
+       const struct mdp_format *format;
+       unsigned int format_len;
+       const struct mdp_limit *def_limit;
+       const struct mdp_pipe_info *pipe_info;
+       unsigned int pipe_info_len;
 };
 
 struct mdp_dev {
@@ -85,6 +94,11 @@ struct mdp_dev {
        atomic_t                                job_count;
 };
 
+struct mdp_pipe_info {
+       enum mdp_pipe_id pipe_id;
+       u32 mutex_id;
+};
+
 int mdp_vpu_get_locked(struct mdp_dev *mdp);
 void mdp_vpu_put_locked(struct mdp_dev *mdp);
 int mdp_vpu_register(struct mdp_dev *mdp);
index 5f74ea3b7a524800f5f28877fdf02e67388bb3b5..a298c1b15b9ea578427acb4e8b3711552b8efc5f 100644 (file)
@@ -87,14 +87,14 @@ static void mdp_m2m_device_run(void *priv)
        dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
        mdp_set_dst_config(&param.outputs[0], frame, &dst_vb->vb2_buf);
 
-       ret = mdp_vpu_process(&ctx->vpu, &param);
+       ret = mdp_vpu_process(&ctx->mdp_dev->vpu, &param);
        if (ret) {
                dev_err(&ctx->mdp_dev->pdev->dev,
                        "VPU MDP process failed: %d\n", ret);
                goto worker_end;
        }
 
-       task.config = ctx->vpu.config;
+       task.config = ctx->mdp_dev->vpu.config;
        task.param = &param;
        task.composes[0] = &frame->compose;
        task.cmdq_cb = NULL;
@@ -150,11 +150,6 @@ static int mdp_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
 
        if (!mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) {
                ret = mdp_vpu_get_locked(ctx->mdp_dev);
-               if (ret)
-                       return ret;
-
-               ret = mdp_vpu_ctx_init(&ctx->vpu, &ctx->mdp_dev->vpu,
-                                      MDP_DEV_M2M);
                if (ret) {
                        dev_err(&ctx->mdp_dev->pdev->dev,
                                "VPU init failed %d\n", ret);
@@ -277,7 +272,9 @@ static int mdp_m2m_querycap(struct file *file, void *fh,
 static int mdp_m2m_enum_fmt_mplane(struct file *file, void *fh,
                                   struct v4l2_fmtdesc *f)
 {
-       return mdp_enum_fmt_mplane(f);
+       struct mdp_m2m_ctx *ctx = fh_to_ctx(fh);
+
+       return mdp_enum_fmt_mplane(ctx->mdp_dev, f);
 }
 
 static int mdp_m2m_g_fmt_mplane(struct file *file, void *fh,
@@ -307,7 +304,7 @@ static int mdp_m2m_s_fmt_mplane(struct file *file, void *fh,
        const struct mdp_format *fmt;
        struct vb2_queue *vq;
 
-       fmt = mdp_try_fmt_mplane(f, &ctx->curr_param, ctx->id);
+       fmt = mdp_try_fmt_mplane(ctx->mdp_dev, f, &ctx->curr_param, ctx->id);
        if (!fmt)
                return -EINVAL;
 
@@ -346,7 +343,7 @@ static int mdp_m2m_try_fmt_mplane(struct file *file, void *fh,
 {
        struct mdp_m2m_ctx *ctx = fh_to_ctx(fh);
 
-       if (!mdp_try_fmt_mplane(f, &ctx->curr_param, ctx->id))
+       if (!mdp_try_fmt_mplane(ctx->mdp_dev, f, &ctx->curr_param, ctx->id))
                return -EINVAL;
 
        return 0;
@@ -556,6 +553,7 @@ static int mdp_m2m_open(struct file *file)
        struct device *dev = &mdp->pdev->dev;
        int ret;
        struct v4l2_format default_format = {};
+       const struct mdp_limit *limit = mdp->mdp_data->def_limit;
 
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
@@ -566,7 +564,11 @@ static int mdp_m2m_open(struct file *file)
                goto err_free_ctx;
        }
 
-       ctx->id = ida_alloc(&mdp->mdp_ida, GFP_KERNEL);
+       ret = ida_alloc(&mdp->mdp_ida, GFP_KERNEL);
+       if (ret < 0)
+               goto err_unlock_mutex;
+       ctx->id = ret;
+
        ctx->mdp_dev = mdp;
 
        v4l2_fh_init(&ctx->fh, vdev);
@@ -589,7 +591,7 @@ static int mdp_m2m_open(struct file *file)
        ctx->fh.m2m_ctx = ctx->m2m_ctx;
 
        ctx->curr_param.ctx = ctx;
-       ret = mdp_frameparam_init(&ctx->curr_param);
+       ret = mdp_frameparam_init(mdp, &ctx->curr_param);
        if (ret) {
                dev_err(dev, "Failed to initialize mdp parameter\n");
                goto err_release_m2m_ctx;
@@ -599,8 +601,8 @@ static int mdp_m2m_open(struct file *file)
 
        /* Default format */
        default_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-       default_format.fmt.pix_mp.width = 32;
-       default_format.fmt.pix_mp.height = 32;
+       default_format.fmt.pix_mp.width = limit->out_limit.wmin;
+       default_format.fmt.pix_mp.height = limit->out_limit.hmin;
        default_format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M;
        mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format);
        default_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
@@ -617,6 +619,8 @@ err_release_handler:
        v4l2_fh_del(&ctx->fh);
 err_exit_fh:
        v4l2_fh_exit(&ctx->fh);
+       ida_free(&mdp->mdp_ida, ctx->id);
+err_unlock_mutex:
        mutex_unlock(&mdp->m2m_lock);
 err_free_ctx:
        kfree(ctx);
@@ -632,10 +636,8 @@ static int mdp_m2m_release(struct file *file)
 
        mutex_lock(&mdp->m2m_lock);
        v4l2_m2m_ctx_release(ctx->m2m_ctx);
-       if (mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) {
-               mdp_vpu_ctx_deinit(&ctx->vpu);
+       if (mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT))
                mdp_vpu_put_locked(mdp);
-       }
 
        v4l2_ctrl_handler_free(&ctx->ctrl_handler);
        v4l2_fh_del(&ctx->fh);
index 61ddbaf1bf139008b4930ed0cbf72a6b45346f94..dfc59e5b3b87fd45482a90a7a89e1a1d3558e03c 100644 (file)
@@ -33,7 +33,6 @@ struct mdp_m2m_ctx {
        struct v4l2_ctrl_handler        ctrl_handler;
        struct mdp_m2m_ctrls            ctrls;
        struct v4l2_m2m_ctx             *m2m_ctx;
-       struct mdp_vpu_ctx              vpu;
        u32                             frame_count[MDP_M2M_MAX];
 
        struct mdp_frameparam           curr_param;
index 4e84a37ecdfc1a7ce0bbc3ad8d227d8654b819c3..9b436b911d92d75aea563b4bc7c091f781b1b0a8 100644 (file)
@@ -4,6 +4,7 @@
  * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
  */
 
+#include <linux/math64.h>
 #include <media/v4l2-common.h>
 #include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 #include "mtk-mdp3-regs.h"
 #include "mtk-mdp3-m2m.h"
 
-/*
- * All 10-bit related formats are not added in the basic format list,
- * please add the corresponding format settings before use.
- */
-static const struct mdp_format mdp_formats[] = {
-       {
-               .pixelformat    = V4L2_PIX_FMT_GREY,
-               .mdp_color      = MDP_COLOR_GREY,
-               .depth          = { 8 },
-               .row_depth      = { 8 },
-               .num_planes     = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_RGB565X,
-               .mdp_color      = MDP_COLOR_BGR565,
-               .depth          = { 16 },
-               .row_depth      = { 16 },
-               .num_planes     = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_RGB565,
-               .mdp_color      = MDP_COLOR_RGB565,
-               .depth          = { 16 },
-               .row_depth      = { 16 },
-               .num_planes     = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_RGB24,
-               .mdp_color      = MDP_COLOR_RGB888,
-               .depth          = { 24 },
-               .row_depth      = { 24 },
-               .num_planes     = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_BGR24,
-               .mdp_color      = MDP_COLOR_BGR888,
-               .depth          = { 24 },
-               .row_depth      = { 24 },
-               .num_planes     = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_ABGR32,
-               .mdp_color      = MDP_COLOR_BGRA8888,
-               .depth          = { 32 },
-               .row_depth      = { 32 },
-               .num_planes     = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_ARGB32,
-               .mdp_color      = MDP_COLOR_ARGB8888,
-               .depth          = { 32 },
-               .row_depth      = { 32 },
-               .num_planes     = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_UYVY,
-               .mdp_color      = MDP_COLOR_UYVY,
-               .depth          = { 16 },
-               .row_depth      = { 16 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_VYUY,
-               .mdp_color      = MDP_COLOR_VYUY,
-               .depth          = { 16 },
-               .row_depth      = { 16 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_YUYV,
-               .mdp_color      = MDP_COLOR_YUYV,
-               .depth          = { 16 },
-               .row_depth      = { 16 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_YVYU,
-               .mdp_color      = MDP_COLOR_YVYU,
-               .depth          = { 16 },
-               .row_depth      = { 16 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_YUV420,
-               .mdp_color      = MDP_COLOR_I420,
-               .depth          = { 12 },
-               .row_depth      = { 8 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .halign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_YVU420,
-               .mdp_color      = MDP_COLOR_YV12,
-               .depth          = { 12 },
-               .row_depth      = { 8 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .halign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV12,
-               .mdp_color      = MDP_COLOR_NV12,
-               .depth          = { 12 },
-               .row_depth      = { 8 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .halign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV21,
-               .mdp_color      = MDP_COLOR_NV21,
-               .depth          = { 12 },
-               .row_depth      = { 8 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .halign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV16,
-               .mdp_color      = MDP_COLOR_NV16,
-               .depth          = { 16 },
-               .row_depth      = { 8 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV61,
-               .mdp_color      = MDP_COLOR_NV61,
-               .depth          = { 16 },
-               .row_depth      = { 8 },
-               .num_planes     = 1,
-               .walign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV24,
-               .mdp_color      = MDP_COLOR_NV24,
-               .depth          = { 24 },
-               .row_depth      = { 8 },
-               .num_planes     = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV42,
-               .mdp_color      = MDP_COLOR_NV42,
-               .depth          = { 24 },
-               .row_depth      = { 8 },
-               .num_planes     = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_MT21C,
-               .mdp_color      = MDP_COLOR_420_BLK_UFO,
-               .depth          = { 8, 4 },
-               .row_depth      = { 8, 8 },
-               .num_planes     = 2,
-               .walign         = 4,
-               .halign         = 5,
-               .flags          = MDP_FMT_FLAG_OUTPUT,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_MM21,
-               .mdp_color      = MDP_COLOR_420_BLK,
-               .depth          = { 8, 4 },
-               .row_depth      = { 8, 8 },
-               .num_planes     = 2,
-               .walign         = 4,
-               .halign         = 5,
-               .flags          = MDP_FMT_FLAG_OUTPUT,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV12M,
-               .mdp_color      = MDP_COLOR_NV12,
-               .depth          = { 8, 4 },
-               .row_depth      = { 8, 8 },
-               .num_planes     = 2,
-               .walign         = 1,
-               .halign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV21M,
-               .mdp_color      = MDP_COLOR_NV21,
-               .depth          = { 8, 4 },
-               .row_depth      = { 8, 8 },
-               .num_planes     = 2,
-               .walign         = 1,
-               .halign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV16M,
-               .mdp_color      = MDP_COLOR_NV16,
-               .depth          = { 8, 8 },
-               .row_depth      = { 8, 8 },
-               .num_planes     = 2,
-               .walign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_NV61M,
-               .mdp_color      = MDP_COLOR_NV61,
-               .depth          = { 8, 8 },
-               .row_depth      = { 8, 8 },
-               .num_planes     = 2,
-               .walign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_YUV420M,
-               .mdp_color      = MDP_COLOR_I420,
-               .depth          = { 8, 2, 2 },
-               .row_depth      = { 8, 4, 4 },
-               .num_planes     = 3,
-               .walign         = 1,
-               .halign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }, {
-               .pixelformat    = V4L2_PIX_FMT_YVU420M,
-               .mdp_color      = MDP_COLOR_YV12,
-               .depth          = { 8, 2, 2 },
-               .row_depth      = { 8, 4, 4 },
-               .num_planes     = 3,
-               .walign         = 1,
-               .halign         = 1,
-               .flags          = MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
-       }
-};
-
-static const struct mdp_limit mdp_def_limit = {
-       .out_limit = {
-               .wmin   = 16,
-               .hmin   = 16,
-               .wmax   = 8176,
-               .hmax   = 8176,
-       },
-       .cap_limit = {
-               .wmin   = 2,
-               .hmin   = 2,
-               .wmax   = 8176,
-               .hmax   = 8176,
-       },
-       .h_scale_up_max = 32,
-       .v_scale_up_max = 32,
-       .h_scale_down_max = 20,
-       .v_scale_down_max = 128,
-};
-
-static const struct mdp_format *mdp_find_fmt(u32 pixelformat, u32 type)
+static const struct mdp_format *mdp_find_fmt(const struct mtk_mdp_driver_data *mdp_data,
+                                            u32 pixelformat, u32 type)
 {
        u32 i, flag;
 
        flag = V4L2_TYPE_IS_OUTPUT(type) ? MDP_FMT_FLAG_OUTPUT :
                                        MDP_FMT_FLAG_CAPTURE;
-       for (i = 0; i < ARRAY_SIZE(mdp_formats); ++i) {
-               if (!(mdp_formats[i].flags & flag))
+       for (i = 0; i < mdp_data->format_len; ++i) {
+               if (!(mdp_data->format[i].flags & flag))
                        continue;
-               if (mdp_formats[i].pixelformat == pixelformat)
-                       return &mdp_formats[i];
+               if (mdp_data->format[i].pixelformat == pixelformat)
+                       return &mdp_data->format[i];
        }
        return NULL;
 }
 
-static const struct mdp_format *mdp_find_fmt_by_index(u32 index, u32 type)
+static const struct mdp_format *mdp_find_fmt_by_index(const struct mtk_mdp_driver_data *mdp_data,
+                                                     u32 index, u32 type)
 {
        u32 i, flag, num = 0;
 
        flag = V4L2_TYPE_IS_OUTPUT(type) ? MDP_FMT_FLAG_OUTPUT :
                                        MDP_FMT_FLAG_CAPTURE;
-       for (i = 0; i < ARRAY_SIZE(mdp_formats); ++i) {
-               if (!(mdp_formats[i].flags & flag))
+       for (i = 0; i < mdp_data->format_len; ++i) {
+               if (!(mdp_data->format[i].flags & flag))
                        continue;
                if (index == num)
-                       return &mdp_formats[i];
+                       return &mdp_data->format[i];
                num++;
        }
        return NULL;
@@ -354,11 +113,11 @@ static int mdp_clamp_align(s32 *x, int min, int max, unsigned int align)
        return 0;
 }
 
-int mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f)
+int mdp_enum_fmt_mplane(struct mdp_dev *mdp, struct v4l2_fmtdesc *f)
 {
        const struct mdp_format *fmt;
 
-       fmt = mdp_find_fmt_by_index(f->index, f->type);
+       fmt = mdp_find_fmt_by_index(mdp->mdp_data, f->index, f->type);
        if (!fmt)
                return -EINVAL;
 
@@ -366,7 +125,8 @@ int mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f)
        return 0;
 }
 
-const struct mdp_format *mdp_try_fmt_mplane(struct v4l2_format *f,
+const struct mdp_format *mdp_try_fmt_mplane(struct mdp_dev *mdp,
+                                           struct v4l2_format *f,
                                            struct mdp_frameparam *param,
                                            u32 ctx_id)
 {
@@ -378,9 +138,9 @@ const struct mdp_format *mdp_try_fmt_mplane(struct v4l2_format *f,
        u32 org_w, org_h;
        unsigned int i;
 
-       fmt = mdp_find_fmt(pix_mp->pixelformat, f->type);
+       fmt = mdp_find_fmt(mdp->mdp_data, pix_mp->pixelformat, f->type);
        if (!fmt) {
-               fmt = mdp_find_fmt_by_index(0, f->type);
+               fmt = mdp_find_fmt_by_index(mdp->mdp_data, 0, f->type);
                if (!fmt) {
                        dev_dbg(dev, "%d: pixelformat %c%c%c%c invalid", ctx_id,
                                (pix_mp->pixelformat & 0xff),
@@ -428,14 +188,15 @@ const struct mdp_format *mdp_try_fmt_mplane(struct v4l2_format *f,
                u32 bpl = pix_mp->plane_fmt[i].bytesperline;
                u32 min_si, max_si;
                u32 si = pix_mp->plane_fmt[i].sizeimage;
+               u64 di;
 
                bpl = clamp(bpl, min_bpl, max_bpl);
                pix_mp->plane_fmt[i].bytesperline = bpl;
 
-               min_si = (bpl * pix_mp->height * fmt->depth[i]) /
-                        fmt->row_depth[i];
-               max_si = (bpl * s.max_height * fmt->depth[i]) /
-                        fmt->row_depth[i];
+               di = (u64)bpl * pix_mp->height * fmt->depth[i];
+               min_si = (u32)div_u64(di, fmt->row_depth[i]);
+               di = (u64)bpl * s.max_height * fmt->depth[i];
+               max_si = (u32)div_u64(di, fmt->row_depth[i]);
 
                si = clamp(si, min_si, max_si);
                pix_mp->plane_fmt[i].sizeimage = si;
@@ -699,7 +460,7 @@ void mdp_set_dst_config(struct img_output *out,
        mdp_set_orientation(out, frame->rotation, frame->hflip, frame->vflip);
 }
 
-int mdp_frameparam_init(struct mdp_frameparam *param)
+int mdp_frameparam_init(struct mdp_dev *mdp, struct mdp_frameparam *param)
 {
        struct mdp_frame *frame;
 
@@ -707,12 +468,12 @@ int mdp_frameparam_init(struct mdp_frameparam *param)
                return -EINVAL;
 
        INIT_LIST_HEAD(&param->list);
-       param->limit = &mdp_def_limit;
+       param->limit = mdp->mdp_data->def_limit;
        param->type = MDP_STREAM_TYPE_BITBLT;
 
        frame = &param->output;
        frame->format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-       frame->mdp_fmt = mdp_try_fmt_mplane(&frame->format, param, 0);
+       frame->mdp_fmt = mdp_try_fmt_mplane(mdp, &frame->format, param, 0);
        frame->ycbcr_prof =
                mdp_map_ycbcr_prof_mplane(&frame->format,
                                          frame->mdp_fmt->mdp_color);
@@ -721,7 +482,7 @@ int mdp_frameparam_init(struct mdp_frameparam *param)
        param->num_captures = 1;
        frame = &param->captures[0];
        frame->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       frame->mdp_fmt = mdp_try_fmt_mplane(&frame->format, param, 0);
+       frame->mdp_fmt = mdp_try_fmt_mplane(mdp, &frame->format, param, 0);
        frame->ycbcr_prof =
                mdp_map_ycbcr_prof_mplane(&frame->format,
                                          frame->mdp_fmt->mdp_color);
index f995e536d45fd4837118134b8fd4041823a89984..e9ab8ac2c0e871eba89c5df5d68a68bcd69059f5 100644 (file)
  * V-subsample: 0, 1
  * Color group: 0-RGB, 1-YUV, 2-raw
  */
-#define MDP_COLOR(PACKED, LOOSE, VIDEO, PLANE, HF, VF, BITS, GROUP, SWAP, ID)\
-       (((PACKED) << 27) | ((LOOSE) << 26) | ((VIDEO) << 23) |\
+#define MDP_COLOR(COMPRESS, PACKED, LOOSE, VIDEO, PLANE, HF, VF, BITS, GROUP, SWAP, ID)\
+       (((COMPRESS) << 29) | ((PACKED) << 27) | ((LOOSE) << 26) | ((VIDEO) << 23) |\
         ((PLANE) << 21) | ((HF) << 19) | ((VF) << 18) | ((BITS) << 8) |\
         ((GROUP) << 6) | ((SWAP) << 5) | ((ID) << 0))
 
+#define MDP_COLOR_IS_COMPRESS(c)        ((0x20000000 & (c)) >> 29)
 #define MDP_COLOR_IS_10BIT_PACKED(c)   ((0x08000000 & (c)) >> 27)
 #define MDP_COLOR_IS_10BIT_LOOSE(c)    (((0x0c000000 & (c)) >> 26) == 1)
 #define MDP_COLOR_IS_10BIT_TILE(c)     (((0x0c000000 & (c)) >> 26) == 3)
 enum mdp_color {
        MDP_COLOR_UNKNOWN       = 0,
 
-       //MDP_COLOR_FULLG8,
-       MDP_COLOR_FULLG8_RGGB   = MDP_COLOR(0, 0, 0, 1, 0, 0,  8, 2,  0, 21),
-       MDP_COLOR_FULLG8_GRBG   = MDP_COLOR(0, 0, 0, 1, 0, 1,  8, 2,  0, 21),
-       MDP_COLOR_FULLG8_GBRG   = MDP_COLOR(0, 0, 0, 1, 1, 0,  8, 2,  0, 21),
-       MDP_COLOR_FULLG8_BGGR   = MDP_COLOR(0, 0, 0, 1, 1, 1,  8, 2,  0, 21),
+       /* MDP_COLOR_FULLG8 */
+       MDP_COLOR_FULLG8_RGGB   = MDP_COLOR(0, 0, 0, 0, 1, 0, 0,  8, 2,  0, 21),
+       MDP_COLOR_FULLG8_GRBG   = MDP_COLOR(0, 0, 0, 0, 1, 0, 1,  8, 2,  0, 21),
+       MDP_COLOR_FULLG8_GBRG   = MDP_COLOR(0, 0, 0, 0, 1, 1, 0,  8, 2,  0, 21),
+       MDP_COLOR_FULLG8_BGGR   = MDP_COLOR(0, 0, 0, 0, 1, 1, 1,  8, 2,  0, 21),
        MDP_COLOR_FULLG8        = MDP_COLOR_FULLG8_BGGR,
 
-       //MDP_COLOR_FULLG10,
-       MDP_COLOR_FULLG10_RGGB  = MDP_COLOR(0, 0, 0, 1, 0, 0, 10, 2,  0, 21),
-       MDP_COLOR_FULLG10_GRBG  = MDP_COLOR(0, 0, 0, 1, 0, 1, 10, 2,  0, 21),
-       MDP_COLOR_FULLG10_GBRG  = MDP_COLOR(0, 0, 0, 1, 1, 0, 10, 2,  0, 21),
-       MDP_COLOR_FULLG10_BGGR  = MDP_COLOR(0, 0, 0, 1, 1, 1, 10, 2,  0, 21),
+       /* MDP_COLOR_FULLG10 */
+       MDP_COLOR_FULLG10_RGGB  = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 10, 2,  0, 21),
+       MDP_COLOR_FULLG10_GRBG  = MDP_COLOR(0, 0, 0, 0, 1, 0, 1, 10, 2,  0, 21),
+       MDP_COLOR_FULLG10_GBRG  = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 10, 2,  0, 21),
+       MDP_COLOR_FULLG10_BGGR  = MDP_COLOR(0, 0, 0, 0, 1, 1, 1, 10, 2,  0, 21),
        MDP_COLOR_FULLG10       = MDP_COLOR_FULLG10_BGGR,
 
-       //MDP_COLOR_FULLG12,
-       MDP_COLOR_FULLG12_RGGB  = MDP_COLOR(0, 0, 0, 1, 0, 0, 12, 2,  0, 21),
-       MDP_COLOR_FULLG12_GRBG  = MDP_COLOR(0, 0, 0, 1, 0, 1, 12, 2,  0, 21),
-       MDP_COLOR_FULLG12_GBRG  = MDP_COLOR(0, 0, 0, 1, 1, 0, 12, 2,  0, 21),
-       MDP_COLOR_FULLG12_BGGR  = MDP_COLOR(0, 0, 0, 1, 1, 1, 12, 2,  0, 21),
+       /* MDP_COLOR_FULLG12 */
+       MDP_COLOR_FULLG12_RGGB  = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 12, 2,  0, 21),
+       MDP_COLOR_FULLG12_GRBG  = MDP_COLOR(0, 0, 0, 0, 1, 0, 1, 12, 2,  0, 21),
+       MDP_COLOR_FULLG12_GBRG  = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 12, 2,  0, 21),
+       MDP_COLOR_FULLG12_BGGR  = MDP_COLOR(0, 0, 0, 0, 1, 1, 1, 12, 2,  0, 21),
        MDP_COLOR_FULLG12       = MDP_COLOR_FULLG12_BGGR,
 
-       //MDP_COLOR_FULLG14,
-       MDP_COLOR_FULLG14_RGGB  = MDP_COLOR(0, 0, 0, 1, 0, 0, 14, 2,  0, 21),
-       MDP_COLOR_FULLG14_GRBG  = MDP_COLOR(0, 0, 0, 1, 0, 1, 14, 2,  0, 21),
-       MDP_COLOR_FULLG14_GBRG  = MDP_COLOR(0, 0, 0, 1, 1, 0, 14, 2,  0, 21),
-       MDP_COLOR_FULLG14_BGGR  = MDP_COLOR(0, 0, 0, 1, 1, 1, 14, 2,  0, 21),
+       /* MDP_COLOR_FULLG14 */
+       MDP_COLOR_FULLG14_RGGB  = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 14, 2,  0, 21),
+       MDP_COLOR_FULLG14_GRBG  = MDP_COLOR(0, 0, 0, 0, 1, 0, 1, 14, 2,  0, 21),
+       MDP_COLOR_FULLG14_GBRG  = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 14, 2,  0, 21),
+       MDP_COLOR_FULLG14_BGGR  = MDP_COLOR(0, 0, 0, 0, 1, 1, 1, 14, 2,  0, 21),
        MDP_COLOR_FULLG14       = MDP_COLOR_FULLG14_BGGR,
 
-       MDP_COLOR_UFO10         = MDP_COLOR(0, 0, 0, 1, 0, 0, 10, 2,  0, 24),
+       MDP_COLOR_UFO10         = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 10, 2,  0, 24),
 
-       //MDP_COLOR_BAYER8,
-       MDP_COLOR_BAYER8_RGGB   = MDP_COLOR(0, 0, 0, 1, 0, 0,  8, 2,  0, 20),
-       MDP_COLOR_BAYER8_GRBG   = MDP_COLOR(0, 0, 0, 1, 0, 1,  8, 2,  0, 20),
-       MDP_COLOR_BAYER8_GBRG   = MDP_COLOR(0, 0, 0, 1, 1, 0,  8, 2,  0, 20),
-       MDP_COLOR_BAYER8_BGGR   = MDP_COLOR(0, 0, 0, 1, 1, 1,  8, 2,  0, 20),
+       /* MDP_COLOR_BAYER8 */
+       MDP_COLOR_BAYER8_RGGB   = MDP_COLOR(0, 0, 0, 0, 1, 0, 0,  8, 2,  0, 20),
+       MDP_COLOR_BAYER8_GRBG   = MDP_COLOR(0, 0, 0, 0, 1, 0, 1,  8, 2,  0, 20),
+       MDP_COLOR_BAYER8_GBRG   = MDP_COLOR(0, 0, 0, 0, 1, 1, 0,  8, 2,  0, 20),
+       MDP_COLOR_BAYER8_BGGR   = MDP_COLOR(0, 0, 0, 0, 1, 1, 1,  8, 2,  0, 20),
        MDP_COLOR_BAYER8        = MDP_COLOR_BAYER8_BGGR,
 
-       //MDP_COLOR_BAYER10,
-       MDP_COLOR_BAYER10_RGGB  = MDP_COLOR(0, 0, 0, 1, 0, 0, 10, 2,  0, 20),
-       MDP_COLOR_BAYER10_GRBG  = MDP_COLOR(0, 0, 0, 1, 0, 1, 10, 2,  0, 20),
-       MDP_COLOR_BAYER10_GBRG  = MDP_COLOR(0, 0, 0, 1, 1, 0, 10, 2,  0, 20),
-       MDP_COLOR_BAYER10_BGGR  = MDP_COLOR(0, 0, 0, 1, 1, 1, 10, 2,  0, 20),
+       /* MDP_COLOR_BAYER10 */
+       MDP_COLOR_BAYER10_RGGB  = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 10, 2,  0, 20),
+       MDP_COLOR_BAYER10_GRBG  = MDP_COLOR(0, 0, 0, 0, 1, 0, 1, 10, 2,  0, 20),
+       MDP_COLOR_BAYER10_GBRG  = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 10, 2,  0, 20),
+       MDP_COLOR_BAYER10_BGGR  = MDP_COLOR(0, 0, 0, 0, 1, 1, 1, 10, 2,  0, 20),
        MDP_COLOR_BAYER10       = MDP_COLOR_BAYER10_BGGR,
 
-       //MDP_COLOR_BAYER12,
-       MDP_COLOR_BAYER12_RGGB  = MDP_COLOR(0, 0, 0, 1, 0, 0, 12, 2,  0, 20),
-       MDP_COLOR_BAYER12_GRBG  = MDP_COLOR(0, 0, 0, 1, 0, 1, 12, 2,  0, 20),
-       MDP_COLOR_BAYER12_GBRG  = MDP_COLOR(0, 0, 0, 1, 1, 0, 12, 2,  0, 20),
-       MDP_COLOR_BAYER12_BGGR  = MDP_COLOR(0, 0, 0, 1, 1, 1, 12, 2,  0, 20),
+       /* MDP_COLOR_BAYER12 */
+       MDP_COLOR_BAYER12_RGGB  = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 12, 2,  0, 20),
+       MDP_COLOR_BAYER12_GRBG  = MDP_COLOR(0, 0, 0, 0, 1, 0, 1, 12, 2,  0, 20),
+       MDP_COLOR_BAYER12_GBRG  = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 12, 2,  0, 20),
+       MDP_COLOR_BAYER12_BGGR  = MDP_COLOR(0, 0, 0, 0, 1, 1, 1, 12, 2,  0, 20),
        MDP_COLOR_BAYER12       = MDP_COLOR_BAYER12_BGGR,
 
-       //MDP_COLOR_BAYER14,
-       MDP_COLOR_BAYER14_RGGB  = MDP_COLOR(0, 0, 0, 1, 0, 0, 14, 2,  0, 20),
-       MDP_COLOR_BAYER14_GRBG  = MDP_COLOR(0, 0, 0, 1, 0, 1, 14, 2,  0, 20),
-       MDP_COLOR_BAYER14_GBRG  = MDP_COLOR(0, 0, 0, 1, 1, 0, 14, 2,  0, 20),
-       MDP_COLOR_BAYER14_BGGR  = MDP_COLOR(0, 0, 0, 1, 1, 1, 14, 2,  0, 20),
+       /* MDP_COLOR_BAYER14 */
+       MDP_COLOR_BAYER14_RGGB  = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 14, 2,  0, 20),
+       MDP_COLOR_BAYER14_GRBG  = MDP_COLOR(0, 0, 0, 0, 1, 0, 1, 14, 2,  0, 20),
+       MDP_COLOR_BAYER14_GBRG  = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 14, 2,  0, 20),
+       MDP_COLOR_BAYER14_BGGR  = MDP_COLOR(0, 0, 0, 0, 1, 1, 1, 14, 2,  0, 20),
        MDP_COLOR_BAYER14       = MDP_COLOR_BAYER14_BGGR,
 
-       MDP_COLOR_RGB48         = MDP_COLOR(0, 0, 0, 1, 0, 0, 48, 0,  0, 23),
+       MDP_COLOR_RGB48         = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 48, 0,  0, 23),
        /* For bayer+mono raw-16 */
-       MDP_COLOR_RGB565_RAW    = MDP_COLOR(0, 0, 0, 1, 0, 0, 16, 2,  0, 0),
+       MDP_COLOR_RGB565_RAW    = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 16, 2,  0, 0),
 
-       MDP_COLOR_BAYER8_UNPAK  = MDP_COLOR(0, 0, 0, 1, 0, 0,  8, 2,  0, 22),
-       MDP_COLOR_BAYER10_UNPAK = MDP_COLOR(0, 0, 0, 1, 0, 0, 10, 2,  0, 22),
-       MDP_COLOR_BAYER12_UNPAK = MDP_COLOR(0, 0, 0, 1, 0, 0, 12, 2,  0, 22),
-       MDP_COLOR_BAYER14_UNPAK = MDP_COLOR(0, 0, 0, 1, 0, 0, 14, 2,  0, 22),
+       MDP_COLOR_BAYER8_UNPAK  = MDP_COLOR(0, 0, 0, 0, 1, 0, 0,  8, 2,  0, 22),
+       MDP_COLOR_BAYER10_UNPAK = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 10, 2,  0, 22),
+       MDP_COLOR_BAYER12_UNPAK = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 12, 2,  0, 22),
+       MDP_COLOR_BAYER14_UNPAK = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 14, 2,  0, 22),
 
        /* Unified formats */
-       MDP_COLOR_GREY          = MDP_COLOR(0, 0, 0, 1, 0, 0,  8, 1,  0, 7),
-
-       MDP_COLOR_RGB565        = MDP_COLOR(0, 0, 0, 1, 0, 0, 16, 0,  0, 0),
-       MDP_COLOR_BGR565        = MDP_COLOR(0, 0, 0, 1, 0, 0, 16, 0,  1, 0),
-       MDP_COLOR_RGB888        = MDP_COLOR(0, 0, 0, 1, 0, 0, 24, 0,  1, 1),
-       MDP_COLOR_BGR888        = MDP_COLOR(0, 0, 0, 1, 0, 0, 24, 0,  0, 1),
-       MDP_COLOR_RGBA8888      = MDP_COLOR(0, 0, 0, 1, 0, 0, 32, 0,  1, 2),
-       MDP_COLOR_BGRA8888      = MDP_COLOR(0, 0, 0, 1, 0, 0, 32, 0,  0, 2),
-       MDP_COLOR_ARGB8888      = MDP_COLOR(0, 0, 0, 1, 0, 0, 32, 0,  1, 3),
-       MDP_COLOR_ABGR8888      = MDP_COLOR(0, 0, 0, 1, 0, 0, 32, 0,  0, 3),
-
-       MDP_COLOR_UYVY          = MDP_COLOR(0, 0, 0, 1, 1, 0, 16, 1,  0, 4),
-       MDP_COLOR_VYUY          = MDP_COLOR(0, 0, 0, 1, 1, 0, 16, 1,  1, 4),
-       MDP_COLOR_YUYV          = MDP_COLOR(0, 0, 0, 1, 1, 0, 16, 1,  0, 5),
-       MDP_COLOR_YVYU          = MDP_COLOR(0, 0, 0, 1, 1, 0, 16, 1,  1, 5),
-
-       MDP_COLOR_I420          = MDP_COLOR(0, 0, 0, 3, 1, 1,  8, 1,  0, 8),
-       MDP_COLOR_YV12          = MDP_COLOR(0, 0, 0, 3, 1, 1,  8, 1,  1, 8),
-       MDP_COLOR_I422          = MDP_COLOR(0, 0, 0, 3, 1, 0,  8, 1,  0, 9),
-       MDP_COLOR_YV16          = MDP_COLOR(0, 0, 0, 3, 1, 0,  8, 1,  1, 9),
-       MDP_COLOR_I444          = MDP_COLOR(0, 0, 0, 3, 0, 0,  8, 1,  0, 10),
-       MDP_COLOR_YV24          = MDP_COLOR(0, 0, 0, 3, 0, 0,  8, 1,  1, 10),
-
-       MDP_COLOR_NV12          = MDP_COLOR(0, 0, 0, 2, 1, 1,  8, 1,  0, 12),
-       MDP_COLOR_NV21          = MDP_COLOR(0, 0, 0, 2, 1, 1,  8, 1,  1, 12),
-       MDP_COLOR_NV16          = MDP_COLOR(0, 0, 0, 2, 1, 0,  8, 1,  0, 13),
-       MDP_COLOR_NV61          = MDP_COLOR(0, 0, 0, 2, 1, 0,  8, 1,  1, 13),
-       MDP_COLOR_NV24          = MDP_COLOR(0, 0, 0, 2, 0, 0,  8, 1,  0, 14),
-       MDP_COLOR_NV42          = MDP_COLOR(0, 0, 0, 2, 0, 0,  8, 1,  1, 14),
+       MDP_COLOR_GREY          = MDP_COLOR(0, 0, 0, 0, 1, 0, 0,  8, 1,  0, 7),
+
+       MDP_COLOR_RGB565        = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 16, 0,  0, 0),
+       MDP_COLOR_BGR565        = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 16, 0,  1, 0),
+       MDP_COLOR_RGB888        = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 24, 0,  1, 1),
+       MDP_COLOR_BGR888        = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 24, 0,  0, 1),
+       MDP_COLOR_RGBA8888      = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 32, 0,  1, 2),
+       MDP_COLOR_BGRA8888      = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 32, 0,  0, 2),
+       MDP_COLOR_ARGB8888      = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 32, 0,  1, 3),
+       MDP_COLOR_ABGR8888      = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 32, 0,  0, 3),
+
+       MDP_COLOR_UYVY          = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 16, 1,  0, 4),
+       MDP_COLOR_VYUY          = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 16, 1,  1, 4),
+       MDP_COLOR_YUYV          = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 16, 1,  0, 5),
+       MDP_COLOR_YVYU          = MDP_COLOR(0, 0, 0, 0, 1, 1, 0, 16, 1,  1, 5),
+
+       MDP_COLOR_I420          = MDP_COLOR(0, 0, 0, 0, 3, 1, 1,  8, 1,  0, 8),
+       MDP_COLOR_YV12          = MDP_COLOR(0, 0, 0, 0, 3, 1, 1,  8, 1,  1, 8),
+       MDP_COLOR_I422          = MDP_COLOR(0, 0, 0, 0, 3, 1, 0,  8, 1,  0, 9),
+       MDP_COLOR_YV16          = MDP_COLOR(0, 0, 0, 0, 3, 1, 0,  8, 1,  1, 9),
+       MDP_COLOR_I444          = MDP_COLOR(0, 0, 0, 0, 3, 0, 0,  8, 1,  0, 10),
+       MDP_COLOR_YV24          = MDP_COLOR(0, 0, 0, 0, 3, 0, 0,  8, 1,  1, 10),
+
+       MDP_COLOR_NV12          = MDP_COLOR(0, 0, 0, 0, 2, 1, 1,  8, 1,  0, 12),
+       MDP_COLOR_NV21          = MDP_COLOR(0, 0, 0, 0, 2, 1, 1,  8, 1,  1, 12),
+       MDP_COLOR_NV16          = MDP_COLOR(0, 0, 0, 0, 2, 1, 0,  8, 1,  0, 13),
+       MDP_COLOR_NV61          = MDP_COLOR(0, 0, 0, 0, 2, 1, 0,  8, 1,  1, 13),
+       MDP_COLOR_NV24          = MDP_COLOR(0, 0, 0, 0, 2, 0, 0,  8, 1,  0, 14),
+       MDP_COLOR_NV42          = MDP_COLOR(0, 0, 0, 0, 2, 0, 0,  8, 1,  1, 14),
 
        /* MediaTek proprietary formats */
        /* UFO encoded block mode */
-       MDP_COLOR_420_BLK_UFO   = MDP_COLOR(0, 0, 5, 2, 1, 1, 256, 1, 0, 12),
+       MDP_COLOR_420_BLK_UFO   = MDP_COLOR(0, 0, 0, 5, 2, 1, 1, 256, 1, 0, 12),
        /* Block mode */
-       MDP_COLOR_420_BLK       = MDP_COLOR(0, 0, 1, 2, 1, 1, 256, 1, 0, 12),
+       MDP_COLOR_420_BLK       = MDP_COLOR(0, 0, 0, 1, 2, 1, 1, 256, 1, 0, 12),
        /* Block mode + field mode */
-       MDP_COLOR_420_BLKI      = MDP_COLOR(0, 0, 3, 2, 1, 1, 256, 1, 0, 12),
+       MDP_COLOR_420_BLKI      = MDP_COLOR(0, 0, 0, 3, 2, 1, 1, 256, 1, 0, 12),
        /* Block mode */
-       MDP_COLOR_422_BLK       = MDP_COLOR(0, 0, 1, 1, 1, 0, 512, 1, 0, 4),
+       MDP_COLOR_422_BLK       = MDP_COLOR(0, 0, 0, 1, 1, 1, 0, 512, 1, 0, 4),
 
-       MDP_COLOR_IYU2          = MDP_COLOR(0, 0, 0, 1, 0, 0, 24,  1, 0, 25),
-       MDP_COLOR_YUV444        = MDP_COLOR(0, 0, 0, 1, 0, 0, 24,  1, 0, 30),
+       MDP_COLOR_IYU2          = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 24,  1, 0, 25),
+       MDP_COLOR_YUV444        = MDP_COLOR(0, 0, 0, 0, 1, 0, 0, 24,  1, 0, 30),
 
        /* Packed 10-bit formats */
-       MDP_COLOR_RGBA1010102   = MDP_COLOR(1, 0, 0, 1, 0, 0, 32,  0, 1, 2),
-       MDP_COLOR_BGRA1010102   = MDP_COLOR(1, 0, 0, 1, 0, 0, 32,  0, 0, 2),
+       MDP_COLOR_RGBA1010102   = MDP_COLOR(0, 1, 0, 0, 1, 0, 0, 32,  0, 1, 2),
+       MDP_COLOR_BGRA1010102   = MDP_COLOR(0, 1, 0, 0, 1, 0, 0, 32,  0, 0, 2),
        /* Packed 10-bit UYVY */
-       MDP_COLOR_UYVY_10P      = MDP_COLOR(1, 0, 0, 1, 1, 0, 20,  1, 0, 4),
+       MDP_COLOR_UYVY_10P      = MDP_COLOR(0, 1, 0, 0, 1, 1, 0, 20,  1, 0, 4),
        /* Packed 10-bit NV21 */
-       MDP_COLOR_NV21_10P      = MDP_COLOR(1, 0, 0, 2, 1, 1, 10,  1, 1, 12),
+       MDP_COLOR_NV21_10P      = MDP_COLOR(0, 1, 0, 0, 2, 1, 1, 10,  1, 1, 12),
        /* 10-bit block mode */
-       MDP_COLOR_420_BLK_10_H  = MDP_COLOR(1, 0, 1, 2, 1, 1, 320, 1, 0, 12),
+       MDP_COLOR_420_BLK_10_H  = MDP_COLOR(0, 1, 0, 1, 2, 1, 1, 320, 1, 0, 12),
        /* 10-bit HEVC tile mode */
-       MDP_COLOR_420_BLK_10_V  = MDP_COLOR(1, 1, 1, 2, 1, 1, 320, 1, 0, 12),
+       MDP_COLOR_420_BLK_10_V  = MDP_COLOR(0, 1, 1, 1, 2, 1, 1, 320, 1, 0, 12),
        /* UFO encoded 10-bit block mode */
-       MDP_COLOR_420_BLK_U10_H = MDP_COLOR(1, 0, 5, 2, 1, 1, 320, 1, 0, 12),
+       MDP_COLOR_420_BLK_U10_H = MDP_COLOR(0, 1, 0, 5, 2, 1, 1, 320, 1, 0, 12),
        /* UFO encoded 10-bit HEVC tile mode */
-       MDP_COLOR_420_BLK_U10_V = MDP_COLOR(1, 1, 5, 2, 1, 1, 320, 1, 0, 12),
+       MDP_COLOR_420_BLK_U10_V = MDP_COLOR(0, 1, 1, 5, 2, 1, 1, 320, 1, 0, 12),
 
        /* Loose 10-bit formats */
-       MDP_COLOR_UYVY_10L      = MDP_COLOR(0, 1, 0, 1, 1, 0, 20,  1, 0, 4),
-       MDP_COLOR_VYUY_10L      = MDP_COLOR(0, 1, 0, 1, 1, 0, 20,  1, 1, 4),
-       MDP_COLOR_YUYV_10L      = MDP_COLOR(0, 1, 0, 1, 1, 0, 20,  1, 0, 5),
-       MDP_COLOR_YVYU_10L      = MDP_COLOR(0, 1, 0, 1, 1, 0, 20,  1, 1, 5),
-       MDP_COLOR_NV12_10L      = MDP_COLOR(0, 1, 0, 2, 1, 1, 10,  1, 0, 12),
-       MDP_COLOR_NV21_10L      = MDP_COLOR(0, 1, 0, 2, 1, 1, 10,  1, 1, 12),
-       MDP_COLOR_NV16_10L      = MDP_COLOR(0, 1, 0, 2, 1, 0, 10,  1, 0, 13),
-       MDP_COLOR_NV61_10L      = MDP_COLOR(0, 1, 0, 2, 1, 0, 10,  1, 1, 13),
-       MDP_COLOR_YV12_10L      = MDP_COLOR(0, 1, 0, 3, 1, 1, 10,  1, 1, 8),
-       MDP_COLOR_I420_10L      = MDP_COLOR(0, 1, 0, 3, 1, 1, 10,  1, 0, 8),
+       MDP_COLOR_UYVY_10L      = MDP_COLOR(0, 0, 1, 0, 1, 1, 0, 20,  1, 0, 4),
+       MDP_COLOR_VYUY_10L      = MDP_COLOR(0, 0, 1, 0, 1, 1, 0, 20,  1, 1, 4),
+       MDP_COLOR_YUYV_10L      = MDP_COLOR(0, 0, 1, 0, 1, 1, 0, 20,  1, 0, 5),
+       MDP_COLOR_YVYU_10L      = MDP_COLOR(0, 0, 1, 0, 1, 1, 0, 20,  1, 1, 5),
+       MDP_COLOR_NV12_10L      = MDP_COLOR(0, 0, 1, 0, 2, 1, 1, 10,  1, 0, 12),
+       MDP_COLOR_NV21_10L      = MDP_COLOR(0, 0, 1, 0, 2, 1, 1, 10,  1, 1, 12),
+       MDP_COLOR_NV16_10L      = MDP_COLOR(0, 0, 1, 0, 2, 1, 0, 10,  1, 0, 13),
+       MDP_COLOR_NV61_10L      = MDP_COLOR(0, 0, 1, 0, 2, 1, 0, 10,  1, 1, 13),
+       MDP_COLOR_YV12_10L      = MDP_COLOR(0, 0, 1, 0, 3, 1, 1, 10,  1, 1, 8),
+       MDP_COLOR_I420_10L      = MDP_COLOR(0, 0, 1, 0, 3, 1, 1, 10,  1, 0, 8),
 };
 
 static inline bool MDP_COLOR_IS_UV_COPLANE(enum mdp_color c)
@@ -353,8 +354,11 @@ struct mdp_frameparam {
        enum v4l2_quantization          quant;
 };
 
-int mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f);
-const struct mdp_format *mdp_try_fmt_mplane(struct v4l2_format *f,
+struct mdp_dev;
+
+int mdp_enum_fmt_mplane(struct mdp_dev *mdp, struct v4l2_fmtdesc *f);
+const struct mdp_format *mdp_try_fmt_mplane(struct mdp_dev *mdp,
+                                           struct v4l2_format *f,
                                            struct mdp_frameparam *param,
                                            u32 ctx_id);
 enum mdp_ycbcr_profile mdp_map_ycbcr_prof_mplane(struct v4l2_format *f,
@@ -368,6 +372,6 @@ void mdp_set_src_config(struct img_input *in,
                        struct mdp_frame *frame, struct vb2_buffer *vb);
 void mdp_set_dst_config(struct img_output *out,
                        struct mdp_frame *frame, struct vb2_buffer *vb);
-int mdp_frameparam_init(struct mdp_frameparam *param);
+int mdp_frameparam_init(struct mdp_dev *mdp, struct mdp_frameparam *param);
 
 #endif  /* __MTK_MDP3_REGS_H__ */
diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-type.h b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-type.h
new file mode 100644 (file)
index 0000000..ae03968
--- /dev/null
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
+ */
+
+#ifndef __MTK_MDP3_TYPE_H__
+#define __MTK_MDP3_TYPE_H__
+
+#include <linux/types.h>
+
+#define IMG_MAX_HW_INPUTS      3
+#define IMG_MAX_HW_OUTPUTS     4
+#define IMG_MAX_PLANES         3
+#define IMG_MAX_COMPONENTS     20
+
+struct img_crop {
+       s32 left;
+       s32 top;
+       u32 width;
+       u32 height;
+       u32 left_subpix;
+       u32 top_subpix;
+       u32 width_subpix;
+       u32 height_subpix;
+} __packed;
+
+struct img_region {
+       s32 left;
+       s32 right;
+       s32 top;
+       s32 bottom;
+} __packed;
+
+struct img_offset {
+       s32 left;
+       s32 top;
+       u32 left_subpix;
+       u32 top_subpix;
+} __packed;
+
+struct img_mux {
+       u32 reg;
+       u32 value;
+       u32 subsys_id;
+} __packed;
+
+struct img_mmsys_ctrl {
+       struct img_mux sets[IMG_MAX_COMPONENTS * 2];
+       u32 num_sets;
+} __packed;
+
+#endif  /* __MTK_MDP3_TYPE_H__ */
index a72bed927bb64460ebfdf4d73f7ca0e614f3d67e..49fc2e9d45dd51a81722b8b0c219380e3aa0524f 100644 (file)
@@ -10,7 +10,6 @@
 #include "mtk-mdp3-core.h"
 
 #define MDP_VPU_MESSAGE_TIMEOUT 500U
-#define vpu_alloc_size         0x600000
 
 static inline struct mdp_dev *vpu_to_mdp(struct mdp_vpu_dev *vpu)
 {
@@ -19,23 +18,63 @@ static inline struct mdp_dev *vpu_to_mdp(struct mdp_vpu_dev *vpu)
 
 static int mdp_vpu_shared_mem_alloc(struct mdp_vpu_dev *vpu)
 {
-       if (vpu->work && vpu->work_addr)
-               return 0;
+       struct device *dev;
 
-       vpu->work = dma_alloc_coherent(scp_get_device(vpu->scp), vpu_alloc_size,
-                                      &vpu->work_addr, GFP_KERNEL);
+       if (IS_ERR_OR_NULL(vpu))
+               goto err_return;
 
-       if (!vpu->work)
-               return -ENOMEM;
-       else
-               return 0;
+       dev = scp_get_device(vpu->scp);
+
+       if (!vpu->param) {
+               vpu->param = dma_alloc_wc(dev, vpu->param_size,
+                                         &vpu->param_addr, GFP_KERNEL);
+               if (!vpu->param)
+                       goto err_return;
+       }
+
+       if (!vpu->work) {
+               vpu->work = dma_alloc_wc(dev, vpu->work_size,
+                                        &vpu->work_addr, GFP_KERNEL);
+               if (!vpu->work)
+                       goto err_free_param;
+       }
+
+       if (!vpu->config) {
+               vpu->config = dma_alloc_wc(dev, vpu->config_size,
+                                          &vpu->config_addr, GFP_KERNEL);
+               if (!vpu->config)
+                       goto err_free_work;
+       }
+
+       return 0;
+
+err_free_work:
+       dma_free_wc(dev, vpu->work_size, vpu->work, vpu->work_addr);
+       vpu->work = NULL;
+err_free_param:
+       dma_free_wc(dev, vpu->param_size, vpu->param, vpu->param_addr);
+       vpu->param = NULL;
+err_return:
+       return -ENOMEM;
 }
 
 void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu)
 {
+       struct device *dev;
+
+       if (IS_ERR_OR_NULL(vpu))
+               return;
+
+       dev = scp_get_device(vpu->scp);
+
+       if (vpu->param && vpu->param_addr)
+               dma_free_wc(dev, vpu->param_size, vpu->param, vpu->param_addr);
+
        if (vpu->work && vpu->work_addr)
-               dma_free_coherent(scp_get_device(vpu->scp), vpu_alloc_size,
-                                 vpu->work, vpu->work_addr);
+               dma_free_wc(dev, vpu->work_size, vpu->work, vpu->work_addr);
+
+       if (vpu->config && vpu->config_addr)
+               dma_free_wc(dev, vpu->config_size, vpu->config, vpu->config_addr);
 }
 
 static void mdp_vpu_ipi_handle_init_ack(void *data, unsigned int len,
@@ -69,16 +108,16 @@ static void mdp_vpu_ipi_handle_frame_ack(void *data, unsigned int len,
        struct img_sw_addr *addr = (struct img_sw_addr *)data;
        struct img_ipi_frameparam *param =
                (struct img_ipi_frameparam *)(unsigned long)addr->va;
-       struct mdp_vpu_ctx *ctx =
-               (struct mdp_vpu_ctx *)(unsigned long)param->drv_data;
+       struct mdp_vpu_dev *vpu =
+               (struct mdp_vpu_dev *)(unsigned long)param->drv_data;
 
        if (param->state) {
-               struct mdp_dev *mdp = vpu_to_mdp(ctx->vpu_dev);
+               struct mdp_dev *mdp = vpu_to_mdp(vpu);
 
                dev_err(&mdp->pdev->dev, "VPU MDP failure:%d\n", param->state);
        }
-       ctx->vpu_dev->status = param->state;
-       complete(&ctx->vpu_dev->ipi_acked);
+       vpu->status = param->state;
+       complete(&vpu->ipi_acked);
 }
 
 int mdp_vpu_register(struct mdp_dev *mdp)
@@ -157,9 +196,6 @@ int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp,
        struct mdp_ipi_init_msg msg = {
                .drv_data = (unsigned long)vpu,
        };
-       size_t mem_size;
-       phys_addr_t pool;
-       const size_t pool_size = sizeof(struct mdp_config_pool);
        struct mdp_dev *mdp = vpu_to_mdp(vpu);
        int err;
 
@@ -172,34 +208,29 @@ int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp,
                goto err_work_size;
        /* vpu work_size was set in mdp_vpu_ipi_handle_init_ack */
 
-       mem_size = vpu_alloc_size;
+       mutex_lock(vpu->lock);
+       vpu->work_size = ALIGN(vpu->work_size, 64);
+       vpu->param_size = ALIGN(sizeof(struct img_ipi_frameparam), 64);
+       vpu->config_size = ALIGN(sizeof(struct img_config), 64);
        err = mdp_vpu_shared_mem_alloc(vpu);
+       mutex_unlock(vpu->lock);
        if (err) {
                dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
                goto err_mem_alloc;
        }
 
-       pool = ALIGN((uintptr_t)vpu->work + vpu->work_size, 8);
-       if (pool + pool_size - (uintptr_t)vpu->work > mem_size) {
-               dev_err(&mdp->pdev->dev,
-                       "VPU memory insufficient: %zx + %zx > %zx",
-                       vpu->work_size, pool_size, mem_size);
-               err = -ENOMEM;
-               goto err_mem_size;
-       }
-
        dev_dbg(&mdp->pdev->dev,
-               "VPU work:%pK pa:%pad sz:%zx pool:%pa sz:%zx (mem sz:%zx)",
+               "VPU param:%pK pa:%pad sz:%zx, work:%pK pa:%pad sz:%zx, config:%pK pa:%pad sz:%zx",
+               vpu->param, &vpu->param_addr, vpu->param_size,
                vpu->work, &vpu->work_addr, vpu->work_size,
-               &pool, pool_size, mem_size);
-       vpu->pool = (struct mdp_config_pool *)(uintptr_t)pool;
+               vpu->config, &vpu->config_addr, vpu->config_size);
+
        msg.work_addr = vpu->work_addr;
        msg.work_size = vpu->work_size;
        err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg));
        if (err)
                goto err_work_size;
 
-       memset(vpu->pool, 0, sizeof(*vpu->pool));
        return 0;
 
 err_work_size:
@@ -212,7 +243,6 @@ err_work_size:
                break;
        }
        return err;
-err_mem_size:
 err_mem_alloc:
        return err;
 }
@@ -227,88 +257,31 @@ int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu)
        return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_DEINIT, &msg, sizeof(msg));
 }
 
-static struct img_config *mdp_config_get(struct mdp_vpu_dev *vpu,
-                                        enum mdp_config_id id, uint32_t *addr)
+int mdp_vpu_process(struct mdp_vpu_dev *vpu, struct img_ipi_frameparam *param)
 {
-       struct img_config *config;
-
-       if (id < 0 || id >= MDP_CONFIG_POOL_SIZE)
-               return ERR_PTR(-EINVAL);
+       struct mdp_dev *mdp = vpu_to_mdp(vpu);
+       struct img_sw_addr addr;
 
        mutex_lock(vpu->lock);
-       vpu->pool->cfg_count[id]++;
-       config = &vpu->pool->configs[id];
-       *addr = vpu->work_addr + ((uintptr_t)config - (uintptr_t)vpu->work);
-       mutex_unlock(vpu->lock);
-
-       return config;
-}
-
-static int mdp_config_put(struct mdp_vpu_dev *vpu,
-                         enum mdp_config_id id,
-                         const struct img_config *config)
-{
-       int err = 0;
-
-       if (id < 0 || id >= MDP_CONFIG_POOL_SIZE)
-               return -EINVAL;
-       if (vpu->lock)
-               mutex_lock(vpu->lock);
-       if (!vpu->pool->cfg_count[id] || config != &vpu->pool->configs[id])
-               err = -EINVAL;
-       else
-               vpu->pool->cfg_count[id]--;
-       if (vpu->lock)
+       if (mdp_vpu_shared_mem_alloc(vpu)) {
+               dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
                mutex_unlock(vpu->lock);
-       return err;
-}
-
-int mdp_vpu_ctx_init(struct mdp_vpu_ctx *ctx, struct mdp_vpu_dev *vpu,
-                    enum mdp_config_id id)
-{
-       ctx->config = mdp_config_get(vpu, id, &ctx->inst_addr);
-       if (IS_ERR(ctx->config)) {
-               int err = PTR_ERR(ctx->config);
-
-               ctx->config = NULL;
-               return err;
+               return -ENOMEM;
        }
-       ctx->config_id = id;
-       ctx->vpu_dev = vpu;
-       return 0;
-}
 
-int mdp_vpu_ctx_deinit(struct mdp_vpu_ctx *ctx)
-{
-       int err = mdp_config_put(ctx->vpu_dev, ctx->config_id, ctx->config);
+       memset(vpu->param, 0, vpu->param_size);
+       memset(vpu->work, 0, vpu->work_size);
+       memset(vpu->config, 0, vpu->config_size);
 
-       ctx->config_id = 0;
-       ctx->config = NULL;
-       ctx->inst_addr = 0;
-       return err;
-}
+       param->self_data.va = (unsigned long)vpu->work;
+       param->self_data.pa = vpu->work_addr;
+       param->config_data.va = (unsigned long)vpu->config;
+       param->config_data.pa = vpu->config_addr;
+       param->drv_data = (unsigned long)vpu;
+       memcpy(vpu->param, param, sizeof(*param));
 
-int mdp_vpu_process(struct mdp_vpu_ctx *ctx, struct img_ipi_frameparam *param)
-{
-       struct mdp_vpu_dev *vpu = ctx->vpu_dev;
-       struct mdp_dev *mdp = vpu_to_mdp(vpu);
-       struct img_sw_addr addr;
-
-       if (!ctx->vpu_dev->work || !ctx->vpu_dev->work_addr) {
-               if (mdp_vpu_shared_mem_alloc(vpu)) {
-                       dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
-                       return -ENOMEM;
-               }
-       }
-       memset((void *)ctx->vpu_dev->work, 0, ctx->vpu_dev->work_size);
-       memset(ctx->config, 0, sizeof(*ctx->config));
-       param->config_data.va = (unsigned long)ctx->config;
-       param->config_data.pa = ctx->inst_addr;
-       param->drv_data = (unsigned long)ctx;
-
-       memcpy((void *)ctx->vpu_dev->work, param, sizeof(*param));
-       addr.pa = ctx->vpu_dev->work_addr;
-       addr.va = (uintptr_t)ctx->vpu_dev->work;
-       return mdp_vpu_sendmsg(ctx->vpu_dev, SCP_IPI_MDP_FRAME,
-               &addr, sizeof(addr));
+       addr.pa = vpu->param_addr;
+       addr.va = (unsigned long)vpu->param;
+       mutex_unlock(vpu->lock);
+       return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_FRAME, &addr, sizeof(addr));
 }
index 244b3a32d689ec4034301f8b70165781e8ef773e..ad3551bc07305e84fdaa89b050f84c244392e7cf 100644 (file)
@@ -37,42 +37,27 @@ struct mdp_ipi_deinit_msg {
        u32     work_addr;
 } __packed;
 
-enum mdp_config_id {
-       MDP_DEV_M2M = 0,
-       MDP_CONFIG_POOL_SIZE    /* ALWAYS keep at the end */
-};
-
-struct mdp_config_pool {
-       u64                     cfg_count[MDP_CONFIG_POOL_SIZE];
-       struct img_config       configs[MDP_CONFIG_POOL_SIZE];
-};
-
 struct mdp_vpu_dev {
        /* synchronization protect for accessing vpu working buffer info */
        struct mutex            *lock;
        struct mtk_scp          *scp;
        struct completion       ipi_acked;
+       void                    *param;
+       dma_addr_t              param_addr;
+       size_t                  param_size;
        void                    *work;
        dma_addr_t              work_addr;
        size_t                  work_size;
-       struct mdp_config_pool  *pool;
+       void                    *config;
+       dma_addr_t              config_addr;
+       size_t                  config_size;
        u32                     status;
 };
 
-struct mdp_vpu_ctx {
-       struct mdp_vpu_dev      *vpu_dev;
-       u32                     config_id;
-       struct img_config       *config;
-       u32                     inst_addr;
-};
-
 void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu);
 int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp,
                     struct mutex *lock /* for sync */);
 int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu);
-int mdp_vpu_ctx_init(struct mdp_vpu_ctx *ctx, struct mdp_vpu_dev *vpu,
-                    enum mdp_config_id id);
-int mdp_vpu_ctx_deinit(struct mdp_vpu_ctx *ctx);
-int mdp_vpu_process(struct mdp_vpu_ctx *vpu, struct img_ipi_frameparam *param);
+int mdp_vpu_process(struct mdp_vpu_dev *vpu, struct img_ipi_frameparam *param);
 
 #endif  /* __MTK_MDP3_VPU_H__ */
index 641f533c417fd3764d18ec1328b1945b5e4e271b..93fcea821001fb60d9cdd913cbcb3f9a189ea043 100644 (file)
@@ -39,10 +39,9 @@ static bool mtk_vdec_get_cap_fmt(struct mtk_vcodec_ctx *ctx, int format_index)
 {
        const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
        const struct mtk_video_fmt *fmt;
-       struct mtk_q_data *q_data;
        int num_frame_count = 0, i;
-       bool ret = true;
 
+       fmt = &dec_pdata->vdec_formats[format_index];
        for (i = 0; i < *dec_pdata->num_formats; i++) {
                if (dec_pdata->vdec_formats[i].type != MTK_FMT_FRAME)
                        continue;
@@ -50,27 +49,10 @@ static bool mtk_vdec_get_cap_fmt(struct mtk_vcodec_ctx *ctx, int format_index)
                num_frame_count++;
        }
 
-       if (num_frame_count == 1)
+       if (num_frame_count == 1 || fmt->fourcc == V4L2_PIX_FMT_MM21)
                return true;
 
-       fmt = &dec_pdata->vdec_formats[format_index];
-       q_data = &ctx->q_data[MTK_Q_DATA_SRC];
-       switch (q_data->fmt->fourcc) {
-       case V4L2_PIX_FMT_VP8_FRAME:
-               if (fmt->fourcc == V4L2_PIX_FMT_MM21)
-                       ret = true;
-               break;
-       case V4L2_PIX_FMT_H264_SLICE:
-       case V4L2_PIX_FMT_VP9_FRAME:
-               if (fmt->fourcc == V4L2_PIX_FMT_MM21)
-                       ret = false;
-               break;
-       default:
-               ret = true;
-               break;
-       }
-
-       return ret;
+       return false;
 }
 
 static struct mtk_q_data *mtk_vdec_get_q_data(struct mtk_vcodec_ctx *ctx,
@@ -753,6 +735,13 @@ int vb2ops_vdec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
        }
 
        if (*nplanes) {
+               if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+                       if (*nplanes != q_data->fmt->num_planes)
+                               return -EINVAL;
+               } else {
+                       if (*nplanes != 1)
+                               return -EINVAL;
+               }
                for (i = 0; i < *nplanes; i++) {
                        if (sizes[i] < q_data->sizeimage[i])
                                return -EINVAL;
index 174a6eec2f549afd80f7eb7c97d690e2b3f38308..9ba5dc5df648d12abf43fc585caf75d24e5d9599 100644 (file)
@@ -321,7 +321,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
                }
        }
 
-       if (of_get_property(pdev->dev.of_node, "dma-ranges", NULL)) {
+       if (of_property_present(pdev->dev.of_node, "dma-ranges")) {
                ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
                if (ret) {
                        mtk_v4l2_err("Failed to set mask");
@@ -451,7 +451,8 @@ err_core_workq:
        if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch))
                destroy_workqueue(dev->core_workqueue);
 err_res:
-       pm_runtime_disable(dev->pm.dev);
+       if (!dev->vdec_pdata->is_subdev_supported)
+               pm_runtime_disable(dev->pm.dev);
 err_dec_pm:
        mtk_vcodec_fw_release(dev->fw_handler);
        return ret;
@@ -487,7 +488,7 @@ static const struct of_device_id mtk_vcodec_match[] = {
 
 MODULE_DEVICE_TABLE(of, mtk_vcodec_match);
 
-static int mtk_vcodec_dec_remove(struct platform_device *pdev)
+static void mtk_vcodec_dec_remove(struct platform_device *pdev)
 {
        struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev);
 
@@ -509,12 +510,11 @@ static int mtk_vcodec_dec_remove(struct platform_device *pdev)
        if (!dev->vdec_pdata->is_subdev_supported)
                pm_runtime_disable(dev->pm.dev);
        mtk_vcodec_fw_release(dev->fw_handler);
-       return 0;
 }
 
 static struct platform_driver mtk_vcodec_dec_driver = {
        .probe  = mtk_vcodec_probe,
-       .remove = mtk_vcodec_dec_remove,
+       .remove_new = mtk_vcodec_dec_remove,
        .driver = {
                .name   = MTK_VCODEC_DEC_NAME,
                .of_match_table = mtk_vcodec_match,
index 376db0e433d7503e1b70d67ef30ed3f5c12f5e77..b753bf54ebd90854aba8d39ca71047afa0636eb2 100644 (file)
@@ -193,8 +193,16 @@ err:
        return ret;
 }
 
+static int mtk_vdec_hw_remove(struct platform_device *pdev)
+{
+       pm_runtime_disable(&pdev->dev);
+
+       return 0;
+}
+
 static struct platform_driver mtk_vdec_driver = {
        .probe  = mtk_vdec_hw_probe,
+       .remove = mtk_vdec_hw_remove,
        .driver = {
                .name   = "mtk-vdec-comp",
                .of_match_table = mtk_vdec_hw_match,
index 035c86e7809fd77ffcaafe0dada4bf12d2249f05..29991551cf6140671e486490ff648871b0860250 100644 (file)
@@ -11,7 +11,7 @@
 #include "mtk_vcodec_dec_pm.h"
 #include "vdec_drv_if.h"
 
-static const struct mtk_video_fmt mtk_video_formats[] = {
+static struct mtk_video_fmt mtk_video_formats[] = {
        {
                .fourcc = V4L2_PIX_FMT_H264,
                .type = MTK_FMT_DEC,
@@ -580,6 +580,16 @@ static int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx)
 
 static void mtk_init_vdec_params(struct mtk_vcodec_ctx *ctx)
 {
+       unsigned int i;
+
+       if (!(ctx->dev->dec_capability & VCODEC_CAPABILITY_4K_DISABLED)) {
+               for (i = 0; i < num_supported_formats; i++) {
+                       mtk_video_formats[i].frmsize.max_width =
+                               VCODEC_DEC_4K_CODED_WIDTH;
+                       mtk_video_formats[i].frmsize.max_height =
+                               VCODEC_DEC_4K_CODED_HEIGHT;
+               }
+       }
 }
 
 static struct vb2_ops mtk_vdec_frame_vb2_ops = {
index ffbcee04dc26f7959773e26485cee262aaa96dcf..3000db975e5f5fa2b6831ccae60b205809186cd8 100644 (file)
@@ -258,8 +258,10 @@ static void mtk_vdec_worker(struct work_struct *work)
                if (src_buf_req)
                        v4l2_ctrl_request_complete(src_buf_req, &ctx->ctrl_hdl);
        } else {
-               v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-               v4l2_m2m_buf_done(vb2_v4l2_src, state);
+               if (ret != -EAGAIN) {
+                       v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+                       v4l2_m2m_buf_done(vb2_v4l2_src, state);
+               }
                v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
        }
 }
@@ -390,14 +392,14 @@ static void mtk_vcodec_get_supported_formats(struct mtk_vcodec_ctx *ctx)
        if (num_formats)
                return;
 
-       if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_MM21) {
-               mtk_vcodec_add_formats(V4L2_PIX_FMT_MM21, ctx);
-               cap_format_count++;
-       }
        if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_MT21C) {
                mtk_vcodec_add_formats(V4L2_PIX_FMT_MT21C, ctx);
                cap_format_count++;
        }
+       if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_MM21) {
+               mtk_vcodec_add_formats(V4L2_PIX_FMT_MM21, ctx);
+               cap_format_count++;
+       }
        if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_H264_SLICE) {
                mtk_vcodec_add_formats(V4L2_PIX_FMT_H264_SLICE, ctx);
                out_format_count++;
index d65800a3b89d80ea8362e4cb751e10513a73d0fc..db65e77bd37339fd37b5b6478f87a4c415418618 100644 (file)
@@ -943,7 +943,7 @@ err_start_stream:
                 * FIXME: This check is not needed as only active buffers
                 * can be marked as done.
                 */
-               if (buf->state == VB2_BUF_STATE_ACTIVE) {
+               if (buf && buf->state == VB2_BUF_STATE_ACTIVE) {
                        mtk_v4l2_debug(0, "[%d] id=%d, type=%d, %d -> VB2_BUF_STATE_QUEUED",
                                        ctx->id, i, q->type,
                                        (int)buf->state);
index 9095186d549533a1c1b33e162c9641129b2a4c02..755f567b9e54fa50b8a45ca93d1892a1bfa4435c 100644 (file)
@@ -89,16 +89,24 @@ static irqreturn_t mtk_vcodec_enc_irq_handler(int irq, void *priv)
        struct mtk_vcodec_ctx *ctx;
        unsigned long flags;
        void __iomem *addr;
+       int core_id;
 
        spin_lock_irqsave(&dev->irqlock, flags);
        ctx = dev->curr_ctx;
        spin_unlock_irqrestore(&dev->irqlock, flags);
 
-       mtk_v4l2_debug(1, "id=%d coreid:%d", ctx->id, dev->venc_pdata->core_id);
-       addr = dev->reg_base[dev->venc_pdata->core_id] +
-                               MTK_VENC_IRQ_ACK_OFFSET;
+       core_id = dev->venc_pdata->core_id;
+       if (core_id < 0 || core_id >= NUM_MAX_VCODEC_REG_BASE) {
+               mtk_v4l2_err("Invalid core id: %d, ctx id: %d",
+                            core_id, ctx->id);
+               return IRQ_HANDLED;
+       }
+
+       mtk_v4l2_debug(1, "id: %d, core id: %d", ctx->id, core_id);
 
-       ctx->irq_status = readl(dev->reg_base[dev->venc_pdata->core_id] +
+       addr = dev->reg_base[core_id] + MTK_VENC_IRQ_ACK_OFFSET;
+
+       ctx->irq_status = readl(dev->reg_base[core_id] +
                                (MTK_VENC_IRQ_STATUS_OFFSET));
 
        clean_irq_status(ctx->irq_status, addr);
@@ -344,7 +352,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
                goto err_event_workq;
        }
 
-       if (of_get_property(pdev->dev.of_node, "dma-ranges", NULL))
+       if (of_property_present(pdev->dev.of_node, "dma-ranges"))
                dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
 
        ret = video_register_device(vfd_enc, VFL_TYPE_VIDEO, -1);
@@ -451,7 +459,7 @@ static const struct of_device_id mtk_vcodec_enc_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mtk_vcodec_enc_match);
 
-static int mtk_vcodec_enc_remove(struct platform_device *pdev)
+static void mtk_vcodec_enc_remove(struct platform_device *pdev)
 {
        struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev);
 
@@ -466,12 +474,11 @@ static int mtk_vcodec_enc_remove(struct platform_device *pdev)
        v4l2_device_unregister(&dev->v4l2_dev);
        pm_runtime_disable(dev->pm.dev);
        mtk_vcodec_fw_release(dev->fw_handler);
-       return 0;
 }
 
 static struct platform_driver mtk_vcodec_enc_driver = {
        .probe  = mtk_vcodec_probe,
-       .remove = mtk_vcodec_enc_remove,
+       .remove_new = mtk_vcodec_enc_remove,
        .driver = {
                .name   = MTK_VCODEC_ENC_NAME,
                .of_match_table = mtk_vcodec_enc_match,
index 955b2d0c8f53f74ce1c9176745c16171487b66f8..999ce7ee5fdc2027662ea06abfc09eb1a6280c15 100644 (file)
@@ -597,7 +597,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
        lat_buf = vdec_msg_queue_dqbuf(&inst->ctx->msg_queue.lat_ctx);
        if (!lat_buf) {
                mtk_vcodec_err(inst, "failed to get lat buffer");
-               return -EINVAL;
+               return -EAGAIN;
        }
        share_info = lat_buf->private_data;
        src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
index cbb6728b8a40b3a2d2faa5993ff7393d2cfc0d46..cf16cf2807f0728ba46cdaa943a75715f194cbee 100644 (file)
@@ -2070,7 +2070,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
        lat_buf = vdec_msg_queue_dqbuf(&instance->ctx->msg_queue.lat_ctx);
        if (!lat_buf) {
                mtk_vcodec_err(instance, "Failed to get VP9 lat buf\n");
-               return -EBUSY;
+               return -EAGAIN;
        }
        pfc = (struct vdec_vp9_slice_pfc *)lat_buf->private_data;
        if (!pfc) {
index dc2004790a472c86a03cf9c4fa05f7537b8ea210..f3073d1e7f420001f305ce6d94d6d3549e017858 100644 (file)
@@ -52,9 +52,26 @@ static struct list_head *vdec_get_buf_list(int hardware_index, struct vdec_lat_b
        }
 }
 
+static void vdec_msg_queue_inc(struct vdec_msg_queue *msg_queue, int hardware_index)
+{
+       if (hardware_index == MTK_VDEC_CORE)
+               atomic_inc(&msg_queue->core_list_cnt);
+       else
+               atomic_inc(&msg_queue->lat_list_cnt);
+}
+
+static void vdec_msg_queue_dec(struct vdec_msg_queue *msg_queue, int hardware_index)
+{
+       if (hardware_index == MTK_VDEC_CORE)
+               atomic_dec(&msg_queue->core_list_cnt);
+       else
+               atomic_dec(&msg_queue->lat_list_cnt);
+}
+
 int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf *buf)
 {
        struct list_head *head;
+       int status;
 
        head = vdec_get_buf_list(msg_ctx->hardware_index, buf);
        if (!head) {
@@ -66,11 +83,18 @@ int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf
        list_add_tail(head, &msg_ctx->ready_queue);
        msg_ctx->ready_num++;
 
-       if (msg_ctx->hardware_index != MTK_VDEC_CORE)
+       vdec_msg_queue_inc(&buf->ctx->msg_queue, msg_ctx->hardware_index);
+       if (msg_ctx->hardware_index != MTK_VDEC_CORE) {
                wake_up_all(&msg_ctx->ready_to_use);
-       else
-               queue_work(buf->ctx->dev->core_workqueue,
-                          &buf->ctx->msg_queue.core_work);
+       } else {
+               if (buf->ctx->msg_queue.core_work_cnt <
+                       atomic_read(&buf->ctx->msg_queue.core_list_cnt)) {
+                       status = queue_work(buf->ctx->dev->core_workqueue,
+                                           &buf->ctx->msg_queue.core_work);
+                       if (status)
+                               buf->ctx->msg_queue.core_work_cnt++;
+               }
+       }
 
        mtk_v4l2_debug(3, "enqueue buf type: %d addr: 0x%p num: %d",
                       msg_ctx->hardware_index, buf, msg_ctx->ready_num);
@@ -127,6 +151,7 @@ struct vdec_lat_buf *vdec_msg_queue_dqbuf(struct vdec_msg_queue_ctx *msg_ctx)
                return NULL;
        }
        list_del(head);
+       vdec_msg_queue_dec(&buf->ctx->msg_queue, msg_ctx->hardware_index);
 
        msg_ctx->ready_num--;
        mtk_v4l2_debug(3, "dqueue buf type:%d addr: 0x%p num: %d",
@@ -156,11 +181,29 @@ void vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue *msg_queue, uint64_t u
 
 bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
 {
+       struct vdec_lat_buf *buf, *tmp;
+       struct list_head *list_core[3];
+       struct vdec_msg_queue_ctx *core_ctx;
+       int ret, i, in_core_count = 0, count = 0;
        long timeout_jiff;
-       int ret;
+
+       core_ctx = &msg_queue->ctx->dev->msg_queue_core_ctx;
+       spin_lock(&core_ctx->ready_lock);
+       list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) {
+               if (buf && buf->ctx == msg_queue->ctx) {
+                       list_core[in_core_count++] = &buf->core_list;
+                       list_del(&buf->core_list);
+               }
+       }
+
+       for (i = 0; i < in_core_count; i++) {
+               list_add(list_core[in_core_count - (1 + i)], &core_ctx->ready_queue);
+               queue_work(msg_queue->ctx->dev->core_workqueue, &msg_queue->core_work);
+       }
+       spin_unlock(&core_ctx->ready_lock);
 
        timeout_jiff = msecs_to_jiffies(1000 * (NUM_BUFFER_COUNT + 2));
-       ret = wait_event_timeout(msg_queue->lat_ctx.ready_to_use,
+       ret = wait_event_timeout(msg_queue->ctx->msg_queue.core_dec_done,
                                 msg_queue->lat_ctx.ready_num == NUM_BUFFER_COUNT,
                                 timeout_jiff);
        if (ret) {
@@ -168,8 +211,20 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
                               msg_queue->lat_ctx.ready_num);
                return true;
        }
-       mtk_v4l2_err("failed with lat buf isn't full: %d",
-                    msg_queue->lat_ctx.ready_num);
+
+       spin_lock(&core_ctx->ready_lock);
+       list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) {
+               if (buf && buf->ctx == msg_queue->ctx) {
+                       count++;
+                       list_del(&buf->core_list);
+               }
+       }
+       spin_unlock(&core_ctx->ready_lock);
+
+       mtk_v4l2_err("failed with lat buf isn't full: list(%d %d) count:%d",
+                    atomic_read(&msg_queue->lat_list_cnt),
+                    atomic_read(&msg_queue->core_list_cnt), count);
+
        return false;
 }
 
@@ -206,6 +261,7 @@ static void vdec_msg_queue_core_work(struct work_struct *work)
                container_of(msg_queue, struct mtk_vcodec_ctx, msg_queue);
        struct mtk_vcodec_dev *dev = ctx->dev;
        struct vdec_lat_buf *lat_buf;
+       int status;
 
        lat_buf = vdec_msg_queue_dqbuf(&dev->msg_queue_core_ctx);
        if (!lat_buf)
@@ -221,11 +277,18 @@ static void vdec_msg_queue_core_work(struct work_struct *work)
        mtk_vcodec_dec_disable_hardware(ctx, MTK_VDEC_CORE);
        vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);
 
-       if (!list_empty(&dev->msg_queue_core_ctx.ready_queue)) {
-               mtk_v4l2_debug(3, "re-schedule to decode for core: %d",
-                              dev->msg_queue_core_ctx.ready_num);
-               queue_work(dev->core_workqueue, &msg_queue->core_work);
+       wake_up_all(&ctx->msg_queue.core_dec_done);
+       spin_lock(&dev->msg_queue_core_ctx.ready_lock);
+       lat_buf->ctx->msg_queue.core_work_cnt--;
+
+       if (lat_buf->ctx->msg_queue.core_work_cnt <
+               atomic_read(&lat_buf->ctx->msg_queue.core_list_cnt)) {
+               status = queue_work(lat_buf->ctx->dev->core_workqueue,
+                                   &lat_buf->ctx->msg_queue.core_work);
+               if (status)
+                       lat_buf->ctx->msg_queue.core_work_cnt++;
        }
+       spin_unlock(&dev->msg_queue_core_ctx.ready_lock);
 }
 
 int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
@@ -239,12 +302,18 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
        if (msg_queue->wdma_addr.size)
                return 0;
 
+       msg_queue->ctx = ctx;
+       msg_queue->core_work_cnt = 0;
        vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0);
        INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work);
+
+       atomic_set(&msg_queue->lat_list_cnt, 0);
+       atomic_set(&msg_queue->core_list_cnt, 0);
+       init_waitqueue_head(&msg_queue->core_dec_done);
+
        msg_queue->wdma_addr.size =
                vde_msg_queue_get_trans_size(ctx->picinfo.buf_w,
                                             ctx->picinfo.buf_h);
-
        err = mtk_vcodec_mem_alloc(ctx, &msg_queue->wdma_addr);
        if (err) {
                mtk_v4l2_err("failed to allocate wdma_addr buf");
index c43d427f5f544cc87070060342a439a52b4dbe99..a5d44bc97c16b9b6f527f47f447f78b09bbb0bbd 100644 (file)
@@ -72,6 +72,12 @@ struct vdec_lat_buf {
  * @wdma_wptr_addr: ube write point
  * @core_work: core hardware work
  * @lat_ctx: used to store lat buffer list
+ * @ctx: point to mtk_vcodec_ctx
+ *
+ * @lat_list_cnt: used to record each instance lat list count
+ * @core_list_cnt: used to record each instance core list count
+ * @core_dec_done: core work queue decode done event
+ * @core_work_cnt: the number of core work in work queue
  */
 struct vdec_msg_queue {
        struct vdec_lat_buf lat_buf[NUM_BUFFER_COUNT];
@@ -82,6 +88,12 @@ struct vdec_msg_queue {
 
        struct work_struct core_work;
        struct vdec_msg_queue_ctx lat_ctx;
+       struct mtk_vcodec_ctx *ctx;
+
+       atomic_t lat_list_cnt;
+       atomic_t core_list_cnt;
+       wait_queue_head_t core_dec_done;
+       int core_work_cnt;
 };
 
 /**
index 47b684b92f8174d943fc44dc839530b7a8c393fe..5e2bc286f168ea030c7a266dc5cca2450718bc5e 100644 (file)
@@ -953,7 +953,7 @@ static const struct of_device_id mtk_vpu_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mtk_vpu_match);
 
-static int mtk_vpu_remove(struct platform_device *pdev)
+static void mtk_vpu_remove(struct platform_device *pdev)
 {
        struct mtk_vpu *vpu = platform_get_drvdata(pdev);
 
@@ -966,8 +966,6 @@ static int mtk_vpu_remove(struct platform_device *pdev)
        vpu_free_ext_mem(vpu, D_FW);
        mutex_destroy(&vpu->vpu_mutex);
        clk_unprepare(vpu->clk);
-
-       return 0;
 }
 
 static int mtk_vpu_suspend(struct device *dev)
@@ -1040,7 +1038,7 @@ static const struct dev_pm_ops mtk_vpu_pm = {
 
 static struct platform_driver mtk_vpu_driver = {
        .probe  = mtk_vpu_probe,
-       .remove = mtk_vpu_remove,
+       .remove_new = mtk_vpu_remove,
        .driver = {
                .name   = "mtk_vpu",
                .pm = &mtk_vpu_pm,
index d5b359f607ae95df2cccc88853c8be06c82b3ae5..bfb3edcf018a86f4c5692d63888142f401295184 100644 (file)
@@ -741,7 +741,7 @@ csi2dc_probe_cleanup_entity:
        return ret;
 }
 
-static int csi2dc_remove(struct platform_device *pdev)
+static void csi2dc_remove(struct platform_device *pdev)
 {
        struct csi2dc_device *csi2dc = platform_get_drvdata(pdev);
 
@@ -751,8 +751,6 @@ static int csi2dc_remove(struct platform_device *pdev)
        v4l2_async_nf_unregister(&csi2dc->notifier);
        v4l2_async_nf_cleanup(&csi2dc->notifier);
        media_entity_cleanup(&csi2dc->csi2dc_sd.entity);
-
-       return 0;
 }
 
 static int __maybe_unused csi2dc_runtime_suspend(struct device *dev)
@@ -782,7 +780,7 @@ MODULE_DEVICE_TABLE(of, csi2dc_of_match);
 
 static struct platform_driver csi2dc_driver = {
        .probe  = csi2dc_probe,
-       .remove = csi2dc_remove,
+       .remove_new = csi2dc_remove,
        .driver = {
                .name =                 "microchip-csi2dc",
                .pm =                   &csi2dc_dev_pm_ops,
index 71758ee8474bb87922347828b63893d7ddc4ef12..4e657fad33d04e64b7546942d3df7f86d3a100fa 100644 (file)
@@ -858,8 +858,10 @@ static int isc_try_configure_pipeline(struct isc_device *isc)
 static void isc_try_fse(struct isc_device *isc,
                        struct v4l2_subdev_state *sd_state)
 {
+       struct v4l2_subdev_frame_size_enum fse = {
+               .which = V4L2_SUBDEV_FORMAT_TRY,
+       };
        int ret;
-       struct v4l2_subdev_frame_size_enum fse = {};
 
        /*
         * If we do not know yet which format the subdev is using, we cannot
@@ -869,7 +871,6 @@ static void isc_try_fse(struct isc_device *isc,
                return;
 
        fse.code = isc->try_config.sd_format->mbus_code;
-       fse.which = V4L2_SUBDEV_FORMAT_TRY;
 
        ret = v4l2_subdev_call(isc->current_subdev->sd, pad, enum_frame_size,
                               sd_state, &fse);
index ac4715d91de6676b22e628d88414238168f89ea0..746f4a2fa9f6e9b84f4310e0500ef0bcb738ce91 100644 (file)
@@ -608,7 +608,7 @@ unprepare_hclk:
        return ret;
 }
 
-static int microchip_isc_remove(struct platform_device *pdev)
+static void microchip_isc_remove(struct platform_device *pdev)
 {
        struct isc_device *isc = platform_get_drvdata(pdev);
 
@@ -624,8 +624,6 @@ static int microchip_isc_remove(struct platform_device *pdev)
        clk_disable_unprepare(isc->hclock);
 
        microchip_isc_clk_cleanup(isc);
-
-       return 0;
 }
 
 static int __maybe_unused isc_runtime_suspend(struct device *dev)
@@ -668,7 +666,7 @@ MODULE_DEVICE_TABLE(of, microchip_isc_of_match);
 
 static struct platform_driver microchip_isc_driver = {
        .probe  = microchip_isc_probe,
-       .remove = microchip_isc_remove,
+       .remove_new = microchip_isc_remove,
        .driver = {
                .name           = "microchip-sama5d2-isc",
                .pm             = &microchip_isc_dev_pm_ops,
index d583eafe5cc1dfcb7e97bdd9c9ffe09af781e8a6..79ae696764d0813c45cff79c443ad87671cd2ab9 100644 (file)
@@ -577,7 +577,7 @@ unprepare_hclk:
        return ret;
 }
 
-static int microchip_xisc_remove(struct platform_device *pdev)
+static void microchip_xisc_remove(struct platform_device *pdev)
 {
        struct isc_device *isc = platform_get_drvdata(pdev);
 
@@ -592,8 +592,6 @@ static int microchip_xisc_remove(struct platform_device *pdev)
        clk_disable_unprepare(isc->hclock);
 
        microchip_isc_clk_cleanup(isc);
-
-       return 0;
 }
 
 static int __maybe_unused xisc_runtime_suspend(struct device *dev)
@@ -631,7 +629,7 @@ MODULE_DEVICE_TABLE(of, microchip_xisc_of_match);
 
 static struct platform_driver microchip_xisc_driver = {
        .probe  = microchip_xisc_probe,
-       .remove = microchip_xisc_remove,
+       .remove_new = microchip_xisc_remove,
        .driver = {
                .name           = "microchip-sama7g5-xisc",
                .pm             = &microchip_xisc_dev_pm_ops,
index f3e863a94c5a3c308b97c222dd01f6cbaf325c23..7157734a15504606d0a346282f9a19eed3dafe4a 100644 (file)
@@ -378,7 +378,7 @@ err_gen_free:
        return err;
 }
 
-static int tegra_vde_remove(struct platform_device *pdev)
+static void tegra_vde_remove(struct platform_device *pdev)
 {
        struct tegra_vde *vde = platform_get_drvdata(pdev);
        struct device *dev = &pdev->dev;
@@ -407,8 +407,6 @@ static int tegra_vde_remove(struct platform_device *pdev)
 
        gen_pool_free(vde->iram_pool, (unsigned long)vde->iram,
                      gen_pool_size(vde->iram_pool));
-
-       return 0;
 }
 
 static void tegra_vde_shutdown(struct platform_device *pdev)
@@ -536,7 +534,7 @@ MODULE_DEVICE_TABLE(of, tegra_vde_of_match);
 
 static struct platform_driver tegra_vde_driver = {
        .probe          = tegra_vde_probe,
-       .remove         = tegra_vde_remove,
+       .remove_new     = tegra_vde_remove,
        .shutdown       = tegra_vde_shutdown,
        .driver         = {
                .name           = "tegra-vde",
index 730f39971e1cdf6c3f346b91592143d29417ede1..a0ca6b297fb8dd801eedbaf910132a6f9136ca74 100644 (file)
@@ -28,6 +28,8 @@ config VIDEO_IMX_MIPI_CSIS
          Video4Linux2 sub-device driver for the MIPI CSI-2 CSIS receiver
          v3.3/v3.6.3 found on some i.MX7 and i.MX8 SoCs.
 
+source "drivers/media/platform/nxp/imx8-isi/Kconfig"
+
 # mem2mem drivers
 
 config VIDEO_IMX_PXP
index 1a129b58d99eb8fe8ec0f08de2faa7a6d846d96c..b8e672b75fed68ee841197fa291ae65c0348ca73 100644 (file)
@@ -2,6 +2,7 @@
 
 obj-y += dw100/
 obj-y += imx-jpeg/
+obj-y += imx8-isi/
 
 obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_MIPI_CSIS) += imx-mipi-csis.o
index 189d60cd5ed130c14d61b1a13c0ea992f074684a..0024d6175ad9aa0c35f313fe4bfd58b37e5eb042 100644 (file)
@@ -1532,7 +1532,6 @@ static int dw100_probe(struct platform_device *pdev)
 {
        struct dw100_device *dw_dev;
        struct video_device *vfd;
-       struct resource *res;
        int ret, irq;
 
        dw_dev = devm_kzalloc(&pdev->dev, sizeof(*dw_dev), GFP_KERNEL);
@@ -1547,8 +1546,7 @@ static int dw100_probe(struct platform_device *pdev)
        }
        dw_dev->num_clks = ret;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       dw_dev->mmio = devm_ioremap_resource(&pdev->dev, res);
+       dw_dev->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(dw_dev->mmio))
                return PTR_ERR(dw_dev->mmio);
 
@@ -1633,7 +1631,7 @@ err_pm:
        return ret;
 }
 
-static int dw100_remove(struct platform_device *pdev)
+static void dw100_remove(struct platform_device *pdev)
 {
        struct dw100_device *dw_dev = platform_get_drvdata(pdev);
 
@@ -1649,8 +1647,6 @@ static int dw100_remove(struct platform_device *pdev)
        mutex_destroy(dw_dev->vfd.lock);
        v4l2_m2m_release(dw_dev->m2m_dev);
        v4l2_device_unregister(&dw_dev->v4l2_dev);
-
-       return 0;
 }
 
 static int __maybe_unused dw100_runtime_suspend(struct device *dev)
@@ -1692,7 +1688,7 @@ MODULE_DEVICE_TABLE(of, dw100_dt_ids);
 
 static struct platform_driver dw100_driver = {
        .probe          = dw100_probe,
-       .remove         = dw100_remove,
+       .remove_new     = dw100_remove,
        .driver         = {
                .name   = DRV_NAME,
                .pm = &dw100_pm,
index ef28122a5ed4964ea081c005eae5cb05cc386411..9a6e8b332e12ae93a54841140cc7afac386dd16b 100644 (file)
@@ -97,25 +97,31 @@ void mxc_jpeg_sw_reset(void __iomem *reg)
        writel(GLB_CTRL_SFT_RST, reg + GLB_CTRL);
 }
 
-void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg)
+void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg, u8 extseq)
 {
        dev_dbg(dev, "CAST Encoder CONFIG...\n");
        /*
         * "Config_Mode" enabled, "Config_Mode auto clear enabled",
         */
-       writel(0xa0, reg + CAST_MODE);
+       if (extseq)
+               writel(0xb0, reg + CAST_MODE);
+       else
+               writel(0xa0, reg + CAST_MODE);
 
        /* all markers and segments */
        writel(0x3ff, reg + CAST_CFG_MODE);
 }
 
-void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg)
+void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg, u8 extseq)
 {
        dev_dbg(dev, "CAST Encoder GO...\n");
        /*
         * "GO" enabled, "GO bit auto clear" enabled
         */
-       writel(0x140, reg + CAST_MODE);
+       if (extseq)
+               writel(0x150, reg + CAST_MODE);
+       else
+               writel(0x140, reg + CAST_MODE);
 }
 
 void mxc_jpeg_enc_set_quality(struct device *dev, void __iomem *reg, u8 quality)
@@ -178,3 +184,8 @@ void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot)
        writel(desc | MXC_NXT_DESCPT_EN,
               reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
 }
+
+void mxc_jpeg_clr_desc(void __iomem *reg, int slot)
+{
+       writel(0, reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
+}
index ecf3b6562ba26628efe164c6478228b235f43efa..ed15ea348f97b706918aab81d5d9617aa4eec891 100644 (file)
@@ -117,8 +117,8 @@ void print_wrapper_info(struct device *dev, void __iomem *reg);
 void mxc_jpeg_sw_reset(void __iomem *reg);
 int mxc_jpeg_enable(void __iomem *reg);
 void wait_frmdone(struct device *dev, void __iomem *reg);
-void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg);
-void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg);
+void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg, u8 extseq);
+void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg, u8 extseq);
 void mxc_jpeg_enc_set_quality(struct device *dev, void __iomem *reg, u8 quality);
 void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg);
 int mxc_jpeg_get_slot(void __iomem *reg);
@@ -137,6 +137,7 @@ void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc,  u32 bufsize);
 void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h);
 void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch);
 void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot);
+void mxc_jpeg_clr_desc(void __iomem *reg, int slot);
 void mxc_jpeg_set_regs_from_desc(struct mxc_jpeg_desc *desc,
                                 void __iomem *reg);
 #endif
index f085f14d676add98b3b0d3c6ed2dedb8a1b7af42..c0e49be42450ae4da04b701b6682aed94b9db6e5 100644 (file)
@@ -87,6 +87,20 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .precision      = 8,
                .is_rgb         = 1,
        },
+       {
+               .name           = "BGR 12bit", /*12-bit BGR packed format*/
+               .fourcc         = V4L2_PIX_FMT_BGR48_12,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+               .nc             = 3,
+               .depth          = 36,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+               .is_rgb         = 1,
+       },
        {
                .name           = "ABGR", /* ABGR packed format */
                .fourcc         = V4L2_PIX_FMT_ABGR32,
@@ -101,6 +115,20 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .precision      = 8,
                .is_rgb         = 1,
        },
+       {
+               .name           = "ABGR 12bit", /* 12-bit ABGR packed format */
+               .fourcc         = V4L2_PIX_FMT_ABGR64_12,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+               .nc             = 4,
+               .depth          = 48,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+               .is_rgb         = 1,
+       },
        {
                .name           = "YUV420", /* 1st plane = Y, 2nd plane = UV */
                .fourcc         = V4L2_PIX_FMT_NV12M,
@@ -127,6 +155,32 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .flags          = MXC_JPEG_FMT_TYPE_RAW,
                .precision      = 8,
        },
+       {
+               .name           = "YUV420 12bit", /* 1st plane = Y, 2nd plane = UV */
+               .fourcc         = V4L2_PIX_FMT_P012M,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+               .nc             = 3,
+               .depth          = 18, /* 6 x 12 bits (4Y + UV) for 4 pixels */
+               .mem_planes     = 2,
+               .comp_planes    = 2, /* 1 plane Y, 1 plane UV interleaved */
+               .h_align        = 4,
+               .v_align        = 4,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
+       {
+               .name           = "YUV420 12bit", /* 1st plane = Y, 2nd plane = UV */
+               .fourcc         = V4L2_PIX_FMT_P012,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+               .nc             = 3,
+               .depth          = 18, /* 6 x 12 bits (4Y + UV) for 4 pixels */
+               .mem_planes     = 1,
+               .comp_planes    = 2, /* 1 plane Y, 1 plane UV interleaved */
+               .h_align        = 4,
+               .v_align        = 4,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
        {
                .name           = "YUV422", /* YUYV */
                .fourcc         = V4L2_PIX_FMT_YUYV,
@@ -140,6 +194,19 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .flags          = MXC_JPEG_FMT_TYPE_RAW,
                .precision      = 8,
        },
+       {
+               .name           = "YUV422 12bit", /* YUYV */
+               .fourcc         = V4L2_PIX_FMT_Y212,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+               .nc             = 3,
+               .depth          = 24,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 4,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
        {
                .name           = "YUV444", /* YUVYUV */
                .fourcc         = V4L2_PIX_FMT_YUV24,
@@ -153,6 +220,19 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .flags          = MXC_JPEG_FMT_TYPE_RAW,
                .precision      = 8,
        },
+       {
+               .name           = "YUV444 12bit", /* YUVYUV */
+               .fourcc         = V4L2_PIX_FMT_YUV48_12,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+               .nc             = 3,
+               .depth          = 36,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
        {
                .name           = "Gray", /* Gray (Y8/Y12) or Single Comp */
                .fourcc         = V4L2_PIX_FMT_GREY,
@@ -166,6 +246,19 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .flags          = MXC_JPEG_FMT_TYPE_RAW,
                .precision      = 8,
        },
+       {
+               .name           = "Gray 12bit", /* Gray (Y8/Y12) or Single Comp */
+               .fourcc         = V4L2_PIX_FMT_Y012,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
+               .nc             = 1,
+               .depth          = 12,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
 };
 
 #define MXC_JPEG_NUM_FORMATS ARRAY_SIZE(mxc_formats)
@@ -229,6 +322,45 @@ static const unsigned char jpeg_dqt[] = {
        0x63, 0x63, 0x63, 0x63, 0x63, 0x63
 };
 
+static const unsigned char jpeg_dqt_extseq[] = {
+       0xFF, 0xDB,
+       0x01, 0x04,
+       0x10,
+       0x00, 0x80, 0x00, 0x58, 0x00, 0x60, 0x00, 0x70,
+       0x00, 0x60, 0x00, 0x50, 0x00, 0x80, 0x00, 0x70,
+       0x00, 0x68, 0x00, 0x70, 0x00, 0x90, 0x00, 0x88,
+       0x00, 0x80, 0x00, 0x98, 0x00, 0xC0, 0x01, 0x40,
+       0x00, 0xD0, 0x00, 0xC0, 0x00, 0xB0, 0x00, 0xB0,
+       0x00, 0xC0, 0x01, 0x88, 0x01, 0x18, 0x01, 0x28,
+       0x00, 0xE8, 0x01, 0x40, 0x01, 0xD0, 0x01, 0x98,
+       0x01, 0xE8, 0x01, 0xE0, 0x01, 0xC8, 0x01, 0x98,
+       0x01, 0xC0, 0x01, 0xB8, 0x02, 0x00, 0x02, 0x40,
+       0x02, 0xE0, 0x02, 0x70, 0x02, 0x00, 0x02, 0x20,
+       0x02, 0xB8, 0x02, 0x28, 0x01, 0xB8, 0x01, 0xC0,
+       0x02, 0x80, 0x03, 0x68, 0x02, 0x88, 0x02, 0xB8,
+       0x02, 0xF8, 0x03, 0x10, 0x03, 0x38, 0x03, 0x40,
+       0x03, 0x38, 0x01, 0xF0, 0x02, 0x68, 0x03, 0x88,
+       0x03, 0xC8, 0x03, 0x80, 0x03, 0x20, 0x03, 0xC0,
+       0x02, 0xE0, 0x03, 0x28, 0x03, 0x38, 0x03, 0x18,
+       0x11,
+       0x00, 0x88, 0x00, 0x90, 0x00, 0x90, 0x00, 0xC0,
+       0x00, 0xA8, 0x00, 0xC0, 0x01, 0x78, 0x00, 0xD0,
+       0x00, 0xD0, 0x01, 0x78, 0x03, 0x18, 0x02, 0x10,
+       0x01, 0xC0, 0x02, 0x10, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+       0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,
+};
+
 static const unsigned char jpeg_sof_maximal[] = {
        0xFF, 0xC0,
        0x00, 0x14, 0x08, 0x00, 0x40, 0x00, 0x40,
@@ -236,6 +368,13 @@ static const unsigned char jpeg_sof_maximal[] = {
        0x03, 0x11, 0x01, 0x04, 0x11, 0x01
 };
 
+static const unsigned char jpeg_sof_extseq[] = {
+       0xFF, 0xC1,
+       0x00, 0x14, 0x08, 0x00, 0x40, 0x00, 0x40,
+       0x04, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01,
+       0x03, 0x11, 0x01, 0x04, 0x11, 0x01
+};
+
 static const unsigned char jpeg_dht[] = {
        0xFF, 0xC4,
        0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01,
@@ -300,6 +439,90 @@ static const unsigned char jpeg_dht[] = {
        0xF6, 0xF7, 0xF8, 0xF9, 0xFA
 };
 
+static const unsigned char jpeg_dht_extseq[] = {
+       0xFF, 0xC4,
+       0x02, 0x2a, 0x00, 0x00, 0x01, 0x05, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+       0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
+       0x04, 0x03, 0x05, 0x05, 0x02, 0x03, 0x02,
+       0x00, 0x00, 0xbf, 0x01, 0x02, 0x03, 0x00,
+       0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,
+       0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71,
+       0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
+       0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+       0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a,
+       0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26,
+       0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36,
+       0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
+       0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54,
+       0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63,
+       0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
+       0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+       0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+       0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+       0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
+       0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2,
+       0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
+       0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+       0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5,
+       0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+       0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+       0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
+       0xf7, 0xf8, 0xf9, 0xfa, 0x0b, 0x0c, 0x0d,
+       0x0e, 0x1b, 0x1c, 0x1d, 0x1e, 0x2b, 0x2c,
+       0x2d, 0x2e, 0x3b, 0x3c, 0x3d, 0x3e, 0x4b,
+       0x4c, 0x4d, 0x4e, 0x5b, 0x5c, 0x5d, 0x5e,
+       0x6b, 0x6c, 0x6d, 0x6e, 0x7b, 0x7c, 0x7d,
+       0x7e, 0x8b, 0x8c, 0x8d, 0x8e, 0x9b, 0x9c,
+       0x9d, 0x9e, 0xab, 0xac, 0xad, 0xae, 0xbb,
+       0xbc, 0xbd, 0xbe, 0xcb, 0xcc, 0xcd, 0xce,
+       0xdb, 0xdc, 0xdd, 0xde, 0xeb, 0xec, 0xed,
+       0xee, 0xfb, 0xfc, 0xfd, 0xfe, 0x01, 0x00,
+       0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+       0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+       0x0d, 0x0e, 0x0f, 0x11, 0x00, 0x02, 0x01,
+       0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05,
+       0x02, 0x03, 0x02, 0x00, 0x00, 0xbf, 0x01,
+       0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91,
+       0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15,
+       0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72,
+       0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19,
+       0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
+       0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
+       0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+       0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+       0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67,
+       0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
+       0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85,
+       0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
+       0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a,
+       0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+       0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4,
+       0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+       0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
+       0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+       0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
+       0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
+       0x0b, 0x0c, 0x0d, 0x0e, 0x1b, 0x1c, 0x1d,
+       0x1e, 0x2b, 0x2c, 0x2d, 0x2e, 0x3b, 0x3c,
+       0x3d, 0x3e, 0x4b, 0x4c, 0x4d, 0x4e, 0x5b,
+       0x5c, 0x5d, 0x5e, 0x6b, 0x6c, 0x6d, 0x6e,
+       0x7b, 0x7c, 0x7d, 0x7e, 0x8b, 0x8c, 0x8d,
+       0x8e, 0x9b, 0x9c, 0x9d, 0x9e, 0xab, 0xac,
+       0xad, 0xae, 0xbb, 0xbc, 0xbd, 0xbe, 0xcb,
+       0xcc, 0xcd, 0xce, 0xdb, 0xdc, 0xdd, 0xde,
+       0xeb, 0xec, 0xed, 0xee, 0xfb, 0xfc, 0xfd,
+       0xfe,
+};
+
 static const unsigned char jpeg_dri[] = {
        0xFF, 0xDD,
        0x00, 0x04, 0x00, 0x20
@@ -420,8 +643,7 @@ static int enum_fmt(const struct mxc_jpeg_fmt *mxc_formats, int n,
        return 0;
 }
 
-static const struct mxc_jpeg_fmt *mxc_jpeg_find_format(struct mxc_jpeg_ctx *ctx,
-                                                      u32 pixelformat)
+static const struct mxc_jpeg_fmt *mxc_jpeg_find_format(u32 pixelformat)
 {
        unsigned int k;
 
@@ -438,17 +660,24 @@ static enum mxc_jpeg_image_format mxc_jpeg_fourcc_to_imgfmt(u32 fourcc)
 {
        switch (fourcc) {
        case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y012:
                return MXC_JPEG_GRAY;
        case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_Y212:
                return MXC_JPEG_YUV422;
        case V4L2_PIX_FMT_NV12:
        case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_P012:
+       case V4L2_PIX_FMT_P012M:
                return MXC_JPEG_YUV420;
        case V4L2_PIX_FMT_YUV24:
+       case V4L2_PIX_FMT_YUV48_12:
                return MXC_JPEG_YUV444;
        case V4L2_PIX_FMT_BGR24:
+       case V4L2_PIX_FMT_BGR48_12:
                return MXC_JPEG_BGR;
        case V4L2_PIX_FMT_ABGR32:
+       case V4L2_PIX_FMT_ABGR64_12:
                return MXC_JPEG_ABGR;
        default:
                return MXC_JPEG_INVALID;
@@ -484,6 +713,17 @@ static void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc,
                offset;
 }
 
+static bool mxc_jpeg_is_extended_sequential(const struct mxc_jpeg_fmt *fmt)
+{
+       if (!fmt || !(fmt->flags & MXC_JPEG_FMT_TYPE_RAW))
+               return false;
+
+       if (fmt->precision > 8)
+               return true;
+
+       return false;
+}
+
 static void notify_eos(struct mxc_jpeg_ctx *ctx)
 {
        const struct v4l2_event ev = {
@@ -497,10 +737,9 @@ static void notify_eos(struct mxc_jpeg_ctx *ctx)
 static void notify_src_chg(struct mxc_jpeg_ctx *ctx)
 {
        const struct v4l2_event ev = {
-                       .type = V4L2_EVENT_SOURCE_CHANGE,
-                       .u.src_change.changes =
-                       V4L2_EVENT_SRC_CH_RESOLUTION,
-               };
+               .type = V4L2_EVENT_SOURCE_CHANGE,
+               .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+       };
 
        dev_dbg(ctx->mxc_jpeg->dev, "Notify app event SRC_CH_RESOLUTION");
        v4l2_event_queue_fh(&ctx->fh, &ev);
@@ -637,6 +876,11 @@ static u32 mxc_jpeg_get_plane_size(struct mxc_jpeg_q_data *q_data, u32 plane_no)
                return q_data->sizeimage[plane_no];
 
        size = q_data->sizeimage[fmt->mem_planes - 1];
+
+       /* Should be impossible given mxc_formats. */
+       if (WARN_ON_ONCE(fmt->comp_planes > ARRAY_SIZE(q_data->sizeimage)))
+               return size;
+
        for (i = fmt->mem_planes; i < fmt->comp_planes; i++)
                size += q_data->sizeimage[i];
 
@@ -692,7 +936,9 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
        if (dec_ret & SLOT_STATUS_ENC_CONFIG_ERR) {
                u32 ret = readl(reg + CAST_STATUS12);
 
-               dev_err(dev, "Encoder/decoder error, status=0x%08x", ret);
+               dev_err(dev, "Encoder/decoder error, dec_ret = 0x%08x, status=0x%08x",
+                       dec_ret, ret);
+               mxc_jpeg_clr_desc(reg, slot);
                mxc_jpeg_sw_reset(reg);
                buf_state = VB2_BUF_STATE_ERROR;
                goto buffers_done;
@@ -703,10 +949,11 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
 
        if (jpeg->mode == MXC_JPEG_ENCODE &&
            ctx->enc_state == MXC_JPEG_ENC_CONF) {
+               q_data = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
                ctx->enc_state = MXC_JPEG_ENCODING;
                dev_dbg(dev, "Encoder config finished. Start encoding...\n");
                mxc_jpeg_enc_set_quality(dev, reg, ctx->jpeg_quality);
-               mxc_jpeg_enc_mode_go(dev, reg);
+               mxc_jpeg_enc_mode_go(dev, reg, mxc_jpeg_is_extended_sequential(q_data->fmt));
                goto job_unlock;
        }
        if (jpeg->mode == MXC_JPEG_DECODE && jpeg_src_buf->dht_needed) {
@@ -757,8 +1004,12 @@ static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof,
                              u16 w, u16 h)
 {
        int sof_length;
+       const struct mxc_jpeg_fmt *fmt = mxc_jpeg_find_format(fourcc);
 
-       sof->precision = 8; /* TODO allow 8/12 bit precision*/
+       if (fmt)
+               sof->precision = fmt->precision;
+       else
+               sof->precision = 8; /* TODO allow 8/12 bit precision*/
        sof->height = h;
        _bswap16(&sof->height);
        sof->width = w;
@@ -767,24 +1018,31 @@ static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof,
        switch (fourcc) {
        case V4L2_PIX_FMT_NV12:
        case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_P012:
+       case V4L2_PIX_FMT_P012M:
                sof->components_no = 3;
                sof->comp[0].v = 0x2;
                sof->comp[0].h = 0x2;
                break;
        case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_Y212:
                sof->components_no = 3;
                sof->comp[0].v = 0x1;
                sof->comp[0].h = 0x2;
                break;
        case V4L2_PIX_FMT_YUV24:
+       case V4L2_PIX_FMT_YUV48_12:
        case V4L2_PIX_FMT_BGR24:
+       case V4L2_PIX_FMT_BGR48_12:
        default:
                sof->components_no = 3;
                break;
        case V4L2_PIX_FMT_ABGR32:
+       case V4L2_PIX_FMT_ABGR64_12:
                sof->components_no = 4;
                break;
        case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y012:
                sof->components_no = 1;
                break;
        }
@@ -804,20 +1062,27 @@ static int mxc_jpeg_fixup_sos(struct mxc_jpeg_sos *sos,
        switch (fourcc) {
        case V4L2_PIX_FMT_NV12:
        case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_P012:
+       case V4L2_PIX_FMT_P012M:
                sos->components_no = 3;
                break;
        case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_Y212:
                sos->components_no = 3;
                break;
        case V4L2_PIX_FMT_YUV24:
+       case V4L2_PIX_FMT_YUV48_12:
        case V4L2_PIX_FMT_BGR24:
+       case V4L2_PIX_FMT_BGR48_12:
        default:
                sos->components_no = 3;
                break;
        case V4L2_PIX_FMT_ABGR32:
+       case V4L2_PIX_FMT_ABGR64_12:
                sos->components_no = 4;
                break;
        case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y012:
                sos->components_no = 1;
                break;
        }
@@ -847,12 +1112,15 @@ static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,
        u8 *cfg = (u8 *)cfg_stream_vaddr;
        struct mxc_jpeg_sof *sof;
        struct mxc_jpeg_sos *sos;
+       const struct mxc_jpeg_fmt *fmt = mxc_jpeg_find_format(fourcc);
+
+       if (!fmt)
+               return 0;
 
        memcpy(cfg + offset, jpeg_soi, ARRAY_SIZE(jpeg_soi));
        offset += ARRAY_SIZE(jpeg_soi);
 
-       if (fourcc == V4L2_PIX_FMT_BGR24 ||
-           fourcc == V4L2_PIX_FMT_ABGR32) {
+       if (fmt->is_rgb) {
                memcpy(cfg + offset, jpeg_app14, sizeof(jpeg_app14));
                offset += sizeof(jpeg_app14);
        } else {
@@ -860,16 +1128,28 @@ static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,
                offset += sizeof(jpeg_app0);
        }
 
-       memcpy(cfg + offset, jpeg_dqt, sizeof(jpeg_dqt));
-       offset += sizeof(jpeg_dqt);
+       if (mxc_jpeg_is_extended_sequential(fmt)) {
+               memcpy(cfg + offset, jpeg_dqt_extseq, sizeof(jpeg_dqt_extseq));
+               offset += sizeof(jpeg_dqt_extseq);
 
-       memcpy(cfg + offset, jpeg_sof_maximal, sizeof(jpeg_sof_maximal));
+               memcpy(cfg + offset, jpeg_sof_extseq, sizeof(jpeg_sof_extseq));
+       } else {
+               memcpy(cfg + offset, jpeg_dqt, sizeof(jpeg_dqt));
+               offset += sizeof(jpeg_dqt);
+
+               memcpy(cfg + offset, jpeg_sof_maximal, sizeof(jpeg_sof_maximal));
+       }
        offset += 2; /* skip marker ID */
        sof = (struct mxc_jpeg_sof *)(cfg + offset);
        offset += mxc_jpeg_fixup_sof(sof, fourcc, w, h);
 
-       memcpy(cfg + offset, jpeg_dht, sizeof(jpeg_dht));
-       offset += sizeof(jpeg_dht);
+       if (mxc_jpeg_is_extended_sequential(fmt)) {
+               memcpy(cfg + offset, jpeg_dht_extseq, sizeof(jpeg_dht_extseq));
+               offset += sizeof(jpeg_dht_extseq);
+       } else {
+               memcpy(cfg + offset, jpeg_dht, sizeof(jpeg_dht));
+               offset += sizeof(jpeg_dht);
+       }
 
        memcpy(cfg + offset, jpeg_dri, sizeof(jpeg_dri));
        offset += sizeof(jpeg_dri);
@@ -918,6 +1198,10 @@ static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
        desc->stm_ctrl &= ~STM_CTRL_IMAGE_FORMAT(0xF); /* clear image format */
        desc->stm_ctrl |= STM_CTRL_IMAGE_FORMAT(img_fmt);
        desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
+       if (mxc_jpeg_is_extended_sequential(jpeg_src_buf->fmt))
+               desc->stm_ctrl |= STM_CTRL_PIXEL_PRECISION;
+       else
+               desc->stm_ctrl &= ~STM_CTRL_PIXEL_PRECISION;
        desc->line_pitch = q_data_cap->bytesperline[0];
        mxc_jpeg_addrs(desc, dst_buf, src_buf, 0);
        mxc_jpeg_set_bufsize(desc, ALIGN(vb2_plane_size(src_buf, 0), 1024));
@@ -1006,6 +1290,10 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
        desc->stm_ctrl = STM_CTRL_CONFIG_MOD(0) |
                         STM_CTRL_IMAGE_FORMAT(img_fmt);
        desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
+       if (mxc_jpeg_is_extended_sequential(q_data->fmt))
+               desc->stm_ctrl |= STM_CTRL_PIXEL_PRECISION;
+       else
+               desc->stm_ctrl &= ~STM_CTRL_PIXEL_PRECISION;
        mxc_jpeg_addrs(desc, src_buf, dst_buf, 0);
        dev_dbg(jpeg->dev, "cfg_desc:\n");
        print_descriptor_info(jpeg->dev, cfg_desc);
@@ -1206,7 +1494,9 @@ static void mxc_jpeg_device_run(void *priv)
                ctx->enc_state = MXC_JPEG_ENC_CONF;
                mxc_jpeg_config_enc_desc(&dst_buf->vb2_buf, ctx,
                                         &src_buf->vb2_buf, &dst_buf->vb2_buf);
-               mxc_jpeg_enc_mode_conf(dev, reg); /* start config phase */
+               /* start config phase */
+               mxc_jpeg_enc_mode_conf(dev, reg,
+                                      mxc_jpeg_is_extended_sequential(q_data_out->fmt));
        } else {
                dev_dbg(dev, "Decoding on slot %d\n", ctx->slot);
                print_mxc_buf(jpeg, &src_buf->vb2_buf, 0);
@@ -1562,7 +1852,7 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
        if (fourcc == 0)
                return -EINVAL;
 
-       jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
+       jpeg_src_buf->fmt = mxc_jpeg_find_format(fourcc);
        jpeg_src_buf->w = header.frame.width;
        jpeg_src_buf->h = header.frame.height;
        ctx->header_parsed = true;
@@ -1702,11 +1992,11 @@ static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx)
        int i;
 
        if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {
-               out_q->fmt = mxc_jpeg_find_format(ctx, MXC_JPEG_DEFAULT_PFMT);
-               cap_q->fmt = mxc_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG);
+               out_q->fmt = mxc_jpeg_find_format(MXC_JPEG_DEFAULT_PFMT);
+               cap_q->fmt = mxc_jpeg_find_format(V4L2_PIX_FMT_JPEG);
        } else {
-               out_q->fmt = mxc_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG);
-               cap_q->fmt = mxc_jpeg_find_format(ctx, MXC_JPEG_DEFAULT_PFMT);
+               out_q->fmt = mxc_jpeg_find_format(V4L2_PIX_FMT_JPEG);
+               cap_q->fmt = mxc_jpeg_find_format(MXC_JPEG_DEFAULT_PFMT);
        }
 
        for (i = 0; i < 2; i++) {
@@ -1950,7 +2240,7 @@ static int mxc_jpeg_try_fmt(struct v4l2_format *f,
                 pix_mp->height : MXC_JPEG_MAX_HEIGHT;
        int i;
 
-       fmt = mxc_jpeg_find_format(ctx, fourcc);
+       fmt = mxc_jpeg_find_format(fourcc);
        if (!fmt || fmt->flags != mxc_jpeg_get_fmt_type(ctx, f->type)) {
                dev_warn(ctx->mxc_jpeg->dev, "Format not supported: %c%c%c%c, use the default.\n",
                         (fourcc & 0xff),
@@ -1958,7 +2248,7 @@ static int mxc_jpeg_try_fmt(struct v4l2_format *f,
                         (fourcc >> 16) & 0xff,
                         (fourcc >> 24) & 0xff);
                fourcc = mxc_jpeg_get_default_fourcc(ctx, f->type);
-               fmt = mxc_jpeg_find_format(ctx, fourcc);
+               fmt = mxc_jpeg_find_format(fourcc);
                if (!fmt)
                        return -EINVAL;
                f->fmt.pix_mp.pixelformat = fourcc;
@@ -2622,7 +2912,7 @@ static const struct dev_pm_ops    mxc_jpeg_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(mxc_jpeg_suspend, mxc_jpeg_resume)
 };
 
-static int mxc_jpeg_remove(struct platform_device *pdev)
+static void mxc_jpeg_remove(struct platform_device *pdev)
 {
        unsigned int slot;
        struct mxc_jpeg_dev *jpeg = platform_get_drvdata(pdev);
@@ -2635,15 +2925,13 @@ static int mxc_jpeg_remove(struct platform_device *pdev)
        v4l2_m2m_release(jpeg->m2m_dev);
        v4l2_device_unregister(&jpeg->v4l2_dev);
        mxc_jpeg_detach_pm_domains(jpeg);
-
-       return 0;
 }
 
 MODULE_DEVICE_TABLE(of, mxc_jpeg_match);
 
 static struct platform_driver mxc_jpeg_driver = {
        .probe = mxc_jpeg_probe,
-       .remove = mxc_jpeg_remove,
+       .remove_new = mxc_jpeg_remove,
        .driver = {
                .name = "mxc-jpeg",
                .of_match_table = mxc_jpeg_match,
index be2768a479951ea25eb61eb94e3d581a54d6c4a7..05d52762e7926a6d498a409ff1931cf25bac9bda 100644 (file)
@@ -1503,7 +1503,7 @@ err_disable_clock:
        return ret;
 }
 
-static int mipi_csis_remove(struct platform_device *pdev)
+static void mipi_csis_remove(struct platform_device *pdev)
 {
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
@@ -1520,8 +1520,6 @@ static int mipi_csis_remove(struct platform_device *pdev)
        media_entity_cleanup(&csis->sd.entity);
        fwnode_handle_put(csis->sd.fwnode);
        pm_runtime_set_suspended(&pdev->dev);
-
-       return 0;
 }
 
 static const struct of_device_id mipi_csis_of_match[] = {
@@ -1544,7 +1542,7 @@ MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
 
 static struct platform_driver mipi_csis_driver = {
        .probe          = mipi_csis_probe,
-       .remove         = mipi_csis_remove,
+       .remove_new     = mipi_csis_remove,
        .driver         = {
                .of_match_table = mipi_csis_of_match,
                .name           = CSIS_DRIVER_NAME,
index fde3c36e5e1dcbe10f5f9a7bca12811a90f8e392..90f319857c2325ad8eb6f4463e521eda0b724d4b 100644 (file)
@@ -1904,7 +1904,7 @@ err_clk:
        return ret;
 }
 
-static int pxp_remove(struct platform_device *pdev)
+static void pxp_remove(struct platform_device *pdev)
 {
        struct pxp_dev *dev = platform_get_drvdata(pdev);
 
@@ -1922,8 +1922,6 @@ static int pxp_remove(struct platform_device *pdev)
        video_unregister_device(&dev->vfd);
        v4l2_m2m_release(dev->m2m_dev);
        v4l2_device_unregister(&dev->v4l2_dev);
-
-       return 0;
 }
 
 static const struct pxp_pdata pxp_imx6ull_pdata = {
@@ -1943,7 +1941,7 @@ MODULE_DEVICE_TABLE(of, pxp_dt_ids);
 
 static struct platform_driver pxp_driver = {
        .probe          = pxp_probe,
-       .remove         = pxp_remove,
+       .remove_new     = pxp_remove,
        .driver         = {
                .name   = MEM2MEM_NAME,
                .of_match_table = pxp_dt_ids,
index c22bf5c827e7ec88cd413e89c47bee8d4870156c..b701e823436a88ae0f5e1ed904eec5e278f3d96d 100644 (file)
@@ -1214,6 +1214,9 @@ static int imx7_csi_video_g_selection(struct file *file, void *fh,
 {
        struct imx7_csi *csi = video_drvdata(file);
 
+       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
        switch (s->target) {
        case V4L2_SEL_TGT_COMPOSE:
        case V4L2_SEL_TGT_COMPOSE_DEFAULT:
@@ -1610,6 +1613,7 @@ static int imx7_csi_video_init_format(struct imx7_csi *csi)
        format.code = IMX7_CSI_DEF_MBUS_CODE;
        format.width = IMX7_CSI_DEF_PIX_WIDTH;
        format.height = IMX7_CSI_DEF_PIX_HEIGHT;
+       format.field = V4L2_FIELD_NONE;
 
        imx7_csi_mbus_fmt_to_pix_fmt(&csi->vdev_fmt, &format, NULL);
        csi->vdev_compose.width = format.width;
@@ -2107,18 +2111,21 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
 
        ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
                                             FWNODE_GRAPH_ENDPOINT_NEXT);
-       if (ep) {
-               asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep,
-                                                     struct v4l2_async_subdev);
+       if (!ep) {
+               ret = dev_err_probe(csi->dev, -ENOTCONN,
+                                   "Failed to get remote endpoint\n");
+               goto error;
+       }
 
-               fwnode_handle_put(ep);
+       asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep,
+                                             struct v4l2_async_subdev);
 
-               if (IS_ERR(asd)) {
-                       ret = PTR_ERR(asd);
-                       /* OK if asd already exists */
-                       if (ret != -EEXIST)
-                               goto error;
-               }
+       fwnode_handle_put(ep);
+
+       if (IS_ERR(asd)) {
+               ret = dev_err_probe(csi->dev, PTR_ERR(asd),
+                                   "Failed to add remote subdev to notifier\n");
+               goto error;
        }
 
        csi->notifier.ops = &imx7_csi_notify_ops;
@@ -2278,7 +2285,7 @@ err_media_cleanup:
        return ret;
 }
 
-static int imx7_csi_remove(struct platform_device *pdev)
+static void imx7_csi_remove(struct platform_device *pdev)
 {
        struct imx7_csi *csi = platform_get_drvdata(pdev);
 
@@ -2287,8 +2294,6 @@ static int imx7_csi_remove(struct platform_device *pdev)
        v4l2_async_nf_unregister(&csi->notifier);
        v4l2_async_nf_cleanup(&csi->notifier);
        v4l2_async_unregister_subdev(&csi->sd);
-
-       return 0;
 }
 
 static const struct of_device_id imx7_csi_of_match[] = {
@@ -2301,7 +2306,7 @@ MODULE_DEVICE_TABLE(of, imx7_csi_of_match);
 
 static struct platform_driver imx7_csi_driver = {
        .probe = imx7_csi_probe,
-       .remove = imx7_csi_remove,
+       .remove_new = imx7_csi_remove,
        .driver = {
                .of_match_table = imx7_csi_of_match,
                .name = "imx7-csi",
diff --git a/drivers/media/platform/nxp/imx8-isi/Kconfig b/drivers/media/platform/nxp/imx8-isi/Kconfig
new file mode 100644 (file)
index 0000000..fcff33f
--- /dev/null
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config VIDEO_IMX8_ISI
+       tristate "i.MX8 Image Sensor Interface (ISI) driver"
+       depends on ARCH_MXC || COMPILE_TEST
+       depends on HAS_DMA && PM
+       depends on VIDEO_DEV
+       select MEDIA_CONTROLLER
+       select V4L2_FWNODE
+       select V4L2_MEM2MEM_DEV if VIDEO_IMX8_ISI_M2M
+       select VIDEO_V4L2_SUBDEV_API
+       select VIDEOBUF2_DMA_CONTIG
+       help
+         V4L2 driver for the Image Sensor Interface (ISI) found in various
+         i.MX8 SoCs.
+
+config VIDEO_IMX8_ISI_M2M
+       bool "i.MX8 Image Sensor Interface (ISI) memory-to-memory support"
+       depends on VIDEO_IMX8_ISI
+       help
+         Select 'yes' here to enable support for memory-to-memory processing
+         in the ISI driver.
diff --git a/drivers/media/platform/nxp/imx8-isi/Makefile b/drivers/media/platform/nxp/imx8-isi/Makefile
new file mode 100644 (file)
index 0000000..9bff929
--- /dev/null
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+imx8-isi-y := imx8-isi-core.o imx8-isi-crossbar.o imx8-isi-hw.o \
+       imx8-isi-pipe.o imx8-isi-video.o
+imx8-isi-$(CONFIG_DEBUG_FS) += imx8-isi-debug.o
+imx8-isi-$(CONFIG_VIDEO_IMX8_ISI_M2M) += imx8-isi-m2m.o
+
+obj-$(CONFIG_VIDEO_IMX8_ISI) += imx8-isi.o
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
new file mode 100644 (file)
index 0000000..2385216
--- /dev/null
@@ -0,0 +1,539 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019-2020 NXP
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <media/media-device.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mc.h>
+
+#include "imx8-isi-core.h"
+
+/* -----------------------------------------------------------------------------
+ * V4L2 async subdevs
+ */
+
+struct mxc_isi_async_subdev {
+       struct v4l2_async_subdev asd;
+       unsigned int port;
+};
+
+static inline struct mxc_isi_async_subdev *
+asd_to_mxc_isi_async_subdev(struct v4l2_async_subdev *asd)
+{
+       return container_of(asd, struct mxc_isi_async_subdev, asd);
+};
+
+static inline struct mxc_isi_dev *
+notifier_to_mxc_isi_dev(struct v4l2_async_notifier *n)
+{
+       return container_of(n, struct mxc_isi_dev, notifier);
+};
+
+static int mxc_isi_async_notifier_bound(struct v4l2_async_notifier *notifier,
+                                       struct v4l2_subdev *sd,
+                                       struct v4l2_async_subdev *asd)
+{
+       const unsigned int link_flags = MEDIA_LNK_FL_IMMUTABLE
+                                     | MEDIA_LNK_FL_ENABLED;
+       struct mxc_isi_dev *isi = notifier_to_mxc_isi_dev(notifier);
+       struct mxc_isi_async_subdev *masd = asd_to_mxc_isi_async_subdev(asd);
+       struct media_pad *pad = &isi->crossbar.pads[masd->port];
+       struct device_link *link;
+
+       dev_dbg(isi->dev, "Bound subdev %s to crossbar input %u\n", sd->name,
+               masd->port);
+
+       /*
+        * Enforce suspend/resume ordering between the source (supplier) and
+        * the ISI (consumer). The source will be suspended before and resume
+        * after the ISI.
+        */
+       link = device_link_add(isi->dev, sd->dev, DL_FLAG_STATELESS);
+       if (!link) {
+               dev_err(isi->dev,
+                       "Failed to create device link to source %s\n", sd->name);
+               return -EINVAL;
+       }
+
+       return v4l2_create_fwnode_links_to_pad(sd, pad, link_flags);
+}
+
+static int mxc_isi_async_notifier_complete(struct v4l2_async_notifier *notifier)
+{
+       struct mxc_isi_dev *isi = notifier_to_mxc_isi_dev(notifier);
+       int ret;
+
+       dev_dbg(isi->dev, "All subdevs bound\n");
+
+       ret = v4l2_device_register_subdev_nodes(&isi->v4l2_dev);
+       if (ret < 0) {
+               dev_err(isi->dev,
+                       "Failed to register subdev nodes: %d\n", ret);
+               return ret;
+       }
+
+       return media_device_register(&isi->media_dev);
+}
+
+static const struct v4l2_async_notifier_operations mxc_isi_async_notifier_ops = {
+       .bound = mxc_isi_async_notifier_bound,
+       .complete = mxc_isi_async_notifier_complete,
+};
+
+static int mxc_isi_pipe_register(struct mxc_isi_pipe *pipe)
+{
+       int ret;
+
+       ret = v4l2_device_register_subdev(&pipe->isi->v4l2_dev, &pipe->sd);
+       if (ret < 0)
+               return ret;
+
+       return mxc_isi_video_register(pipe, &pipe->isi->v4l2_dev);
+}
+
+static void mxc_isi_pipe_unregister(struct mxc_isi_pipe *pipe)
+{
+       mxc_isi_video_unregister(pipe);
+}
+
+static int mxc_isi_v4l2_init(struct mxc_isi_dev *isi)
+{
+       struct fwnode_handle *node = dev_fwnode(isi->dev);
+       struct media_device *media_dev = &isi->media_dev;
+       struct v4l2_device *v4l2_dev = &isi->v4l2_dev;
+       unsigned int i;
+       int ret;
+
+       /* Initialize the media device. */
+       strscpy(media_dev->model, "FSL Capture Media Device",
+               sizeof(media_dev->model));
+       media_dev->dev = isi->dev;
+
+       media_device_init(media_dev);
+
+       /* Initialize and register the V4L2 device. */
+       v4l2_dev->mdev = media_dev;
+       strscpy(v4l2_dev->name, "mx8-img-md", sizeof(v4l2_dev->name));
+
+       ret = v4l2_device_register(isi->dev, v4l2_dev);
+       if (ret < 0) {
+               dev_err(isi->dev,
+                       "Failed to register V4L2 device: %d\n", ret);
+               goto err_media;
+       }
+
+       /* Register the crossbar switch subdev. */
+       ret = mxc_isi_crossbar_register(&isi->crossbar);
+       if (ret < 0) {
+               dev_err(isi->dev, "Failed to register crossbar: %d\n", ret);
+               goto err_v4l2;
+       }
+
+       /* Register the pipeline subdevs and link them to the crossbar switch. */
+       for (i = 0; i < isi->pdata->num_channels; ++i) {
+               struct mxc_isi_pipe *pipe = &isi->pipes[i];
+
+               ret = mxc_isi_pipe_register(pipe);
+               if (ret < 0) {
+                       dev_err(isi->dev, "Failed to register pipe%u: %d\n", i,
+                               ret);
+                       goto err_v4l2;
+               }
+
+               ret = media_create_pad_link(&isi->crossbar.sd.entity,
+                                           isi->crossbar.num_sinks + i,
+                                           &pipe->sd.entity,
+                                           MXC_ISI_PIPE_PAD_SINK,
+                                           MEDIA_LNK_FL_IMMUTABLE |
+                                           MEDIA_LNK_FL_ENABLED);
+               if (ret < 0)
+                       goto err_v4l2;
+       }
+
+       /* Register the M2M device. */
+       ret = mxc_isi_m2m_register(isi, v4l2_dev);
+       if (ret < 0) {
+               dev_err(isi->dev, "Failed to register M2M device: %d\n", ret);
+               goto err_v4l2;
+       }
+
+       /* Initialize, fill and register the async notifier. */
+       v4l2_async_nf_init(&isi->notifier);
+       isi->notifier.ops = &mxc_isi_async_notifier_ops;
+
+       for (i = 0; i < isi->pdata->num_ports; ++i) {
+               struct mxc_isi_async_subdev *masd;
+               struct fwnode_handle *ep;
+
+               ep = fwnode_graph_get_endpoint_by_id(node, i, 0,
+                                                    FWNODE_GRAPH_ENDPOINT_NEXT);
+
+               if (!ep)
+                       continue;
+
+               masd = v4l2_async_nf_add_fwnode_remote(&isi->notifier, ep,
+                                                      struct mxc_isi_async_subdev);
+               fwnode_handle_put(ep);
+
+               if (IS_ERR(masd)) {
+                       ret = PTR_ERR(masd);
+                       goto err_m2m;
+               }
+
+               masd->port = i;
+       }
+
+       ret = v4l2_async_nf_register(v4l2_dev, &isi->notifier);
+       if (ret < 0) {
+               dev_err(isi->dev,
+                       "Failed to register async notifier: %d\n", ret);
+               goto err_m2m;
+       }
+
+       return 0;
+
+err_m2m:
+       mxc_isi_m2m_unregister(isi);
+       v4l2_async_nf_cleanup(&isi->notifier);
+err_v4l2:
+       v4l2_device_unregister(v4l2_dev);
+err_media:
+       media_device_cleanup(media_dev);
+       return ret;
+}
+
+static void mxc_isi_v4l2_cleanup(struct mxc_isi_dev *isi)
+{
+       unsigned int i;
+
+       v4l2_async_nf_unregister(&isi->notifier);
+       v4l2_async_nf_cleanup(&isi->notifier);
+
+       v4l2_device_unregister(&isi->v4l2_dev);
+       media_device_unregister(&isi->media_dev);
+
+       mxc_isi_m2m_unregister(isi);
+
+       for (i = 0; i < isi->pdata->num_channels; ++i)
+               mxc_isi_pipe_unregister(&isi->pipes[i]);
+
+       mxc_isi_crossbar_unregister(&isi->crossbar);
+
+       media_device_cleanup(&isi->media_dev);
+}
+
+/* -----------------------------------------------------------------------------
+ * Device information
+ */
+
+/* Panic will assert when the buffers are 50% full */
+
+/* For i.MX8QXP C0 and i.MX8MN ISI IER version */
+static const struct mxc_isi_ier_reg mxc_imx8_isi_ier_v1 = {
+       .oflw_y_buf_en = { .offset = 19, .mask = 0x80000  },
+       .oflw_u_buf_en = { .offset = 21, .mask = 0x200000 },
+       .oflw_v_buf_en = { .offset = 23, .mask = 0x800000 },
+
+       .panic_y_buf_en = {.offset = 20, .mask = 0x100000  },
+       .panic_u_buf_en = {.offset = 22, .mask = 0x400000  },
+       .panic_v_buf_en = {.offset = 24, .mask = 0x1000000 },
+};
+
+/* For i.MX8MP ISI IER version */
+static const struct mxc_isi_ier_reg mxc_imx8_isi_ier_v2 = {
+       .oflw_y_buf_en = { .offset = 18, .mask = 0x40000  },
+       .oflw_u_buf_en = { .offset = 20, .mask = 0x100000 },
+       .oflw_v_buf_en = { .offset = 22, .mask = 0x400000 },
+
+       .panic_y_buf_en = {.offset = 19, .mask = 0x80000  },
+       .panic_u_buf_en = {.offset = 21, .mask = 0x200000 },
+       .panic_v_buf_en = {.offset = 23, .mask = 0x800000 },
+};
+
+/* Panic will assert when the buffers are 50% full */
+static const struct mxc_isi_set_thd mxc_imx8_isi_thd_v1 = {
+       .panic_set_thd_y = { .mask = 0x0000f, .offset = 0,  .threshold = 0x7 },
+       .panic_set_thd_u = { .mask = 0x00f00, .offset = 8,  .threshold = 0x7 },
+       .panic_set_thd_v = { .mask = 0xf0000, .offset = 16, .threshold = 0x7 },
+};
+
+static const struct clk_bulk_data mxc_imx8mn_clks[] = {
+       { .id = "axi" },
+       { .id = "apb" },
+};
+
+static const struct mxc_isi_plat_data mxc_imx8mn_data = {
+       .model                  = MXC_ISI_IMX8MN,
+       .num_ports              = 1,
+       .num_channels           = 1,
+       .reg_offset             = 0,
+       .ier_reg                = &mxc_imx8_isi_ier_v1,
+       .set_thd                = &mxc_imx8_isi_thd_v1,
+       .clks                   = mxc_imx8mn_clks,
+       .num_clks               = ARRAY_SIZE(mxc_imx8mn_clks),
+       .buf_active_reverse     = false,
+       .has_gasket             = true,
+       .has_36bit_dma          = false,
+};
+
+static const struct mxc_isi_plat_data mxc_imx8mp_data = {
+       .model                  = MXC_ISI_IMX8MP,
+       .num_ports              = 2,
+       .num_channels           = 2,
+       .reg_offset             = 0x2000,
+       .ier_reg                = &mxc_imx8_isi_ier_v2,
+       .set_thd                = &mxc_imx8_isi_thd_v1,
+       .clks                   = mxc_imx8mn_clks,
+       .num_clks               = ARRAY_SIZE(mxc_imx8mn_clks),
+       .buf_active_reverse     = true,
+       .has_gasket             = true,
+       .has_36bit_dma          = true,
+};
+
+/* -----------------------------------------------------------------------------
+ * Power management
+ */
+
+static int mxc_isi_pm_suspend(struct device *dev)
+{
+       struct mxc_isi_dev *isi = dev_get_drvdata(dev);
+       unsigned int i;
+
+       for (i = 0; i < isi->pdata->num_channels; ++i) {
+               struct mxc_isi_pipe *pipe = &isi->pipes[i];
+
+               mxc_isi_video_suspend(pipe);
+       }
+
+       return pm_runtime_force_suspend(dev);
+}
+
+static int mxc_isi_pm_resume(struct device *dev)
+{
+       struct mxc_isi_dev *isi = dev_get_drvdata(dev);
+       unsigned int i;
+       int err = 0;
+       int ret;
+
+       ret = pm_runtime_force_resume(dev);
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < isi->pdata->num_channels; ++i) {
+               struct mxc_isi_pipe *pipe = &isi->pipes[i];
+
+               ret = mxc_isi_video_resume(pipe);
+               if (ret) {
+                       dev_err(dev, "Failed to resume pipeline %u (%d)\n", i,
+                               ret);
+                       /*
+                        * Record the last error as it's as meaningful as any,
+                        * and continue resuming the other pipelines.
+                        */
+                       err = ret;
+               }
+       }
+
+       return err;
+}
+
+static int mxc_isi_runtime_suspend(struct device *dev)
+{
+       struct mxc_isi_dev *isi = dev_get_drvdata(dev);
+
+       clk_bulk_disable_unprepare(isi->pdata->num_clks, isi->clks);
+
+       return 0;
+}
+
+static int mxc_isi_runtime_resume(struct device *dev)
+{
+       struct mxc_isi_dev *isi = dev_get_drvdata(dev);
+       int ret;
+
+       ret = clk_bulk_prepare_enable(isi->pdata->num_clks, isi->clks);
+       if (ret) {
+               dev_err(dev, "Failed to enable clocks (%d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct dev_pm_ops mxc_isi_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(mxc_isi_pm_suspend, mxc_isi_pm_resume)
+       SET_RUNTIME_PM_OPS(mxc_isi_runtime_suspend, mxc_isi_runtime_resume, NULL)
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe, remove & driver
+ */
+
+static int mxc_isi_clk_get(struct mxc_isi_dev *isi)
+{
+       unsigned int size = isi->pdata->num_clks
+                         * sizeof(*isi->clks);
+       int ret;
+
+       isi->clks = devm_kmalloc(isi->dev, size, GFP_KERNEL);
+       if (!isi->clks)
+               return -ENOMEM;
+
+       memcpy(isi->clks, isi->pdata->clks, size);
+
+       ret = devm_clk_bulk_get(isi->dev, isi->pdata->num_clks,
+                               isi->clks);
+       if (ret < 0) {
+               dev_err(isi->dev, "Failed to acquire clocks: %d\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int mxc_isi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct mxc_isi_dev *isi;
+       unsigned int dma_size;
+       unsigned int i;
+       int ret = 0;
+
+       isi = devm_kzalloc(dev, sizeof(*isi), GFP_KERNEL);
+       if (!isi)
+               return -ENOMEM;
+
+       isi->dev = dev;
+       platform_set_drvdata(pdev, isi);
+
+       isi->pdata = of_device_get_match_data(dev);
+
+       isi->pipes = kcalloc(isi->pdata->num_channels, sizeof(isi->pipes[0]),
+                            GFP_KERNEL);
+       if (!isi->pipes)
+               return -ENOMEM;
+
+       ret = mxc_isi_clk_get(isi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to get clocks\n");
+               return ret;
+       }
+
+       isi->regs = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(isi->regs)) {
+               dev_err(dev, "Failed to get ISI register map\n");
+               return PTR_ERR(isi->regs);
+       }
+
+       if (isi->pdata->has_gasket) {
+               isi->gasket = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                                             "fsl,blk-ctrl");
+               if (IS_ERR(isi->gasket)) {
+                       ret = PTR_ERR(isi->gasket);
+                       dev_err(dev, "failed to get gasket: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       dma_size = isi->pdata->has_36bit_dma ? 36 : 32;
+       ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_size));
+       if (ret) {
+               dev_err(dev, "failed to set DMA mask\n");
+               return ret;
+       }
+
+       pm_runtime_enable(dev);
+
+       ret = mxc_isi_crossbar_init(isi);
+       if (ret) {
+               dev_err(dev, "Failed to initialize crossbar: %d\n", ret);
+               goto err_pm;
+       }
+
+       for (i = 0; i < isi->pdata->num_channels; ++i) {
+               ret = mxc_isi_pipe_init(isi, i);
+               if (ret < 0) {
+                       dev_err(dev, "Failed to initialize pipe%u: %d\n", i,
+                               ret);
+                       goto err_xbar;
+               }
+       }
+
+       ret = mxc_isi_v4l2_init(isi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to initialize V4L2: %d\n", ret);
+               goto err_xbar;
+       }
+
+       mxc_isi_debug_init(isi);
+
+       return 0;
+
+err_xbar:
+       mxc_isi_crossbar_cleanup(&isi->crossbar);
+err_pm:
+       pm_runtime_disable(isi->dev);
+       return ret;
+}
+
+static int mxc_isi_remove(struct platform_device *pdev)
+{
+       struct mxc_isi_dev *isi = platform_get_drvdata(pdev);
+       unsigned int i;
+
+       mxc_isi_debug_cleanup(isi);
+
+       for (i = 0; i < isi->pdata->num_channels; ++i) {
+               struct mxc_isi_pipe *pipe = &isi->pipes[i];
+
+               mxc_isi_pipe_cleanup(pipe);
+       }
+
+       mxc_isi_crossbar_cleanup(&isi->crossbar);
+       mxc_isi_v4l2_cleanup(isi);
+
+       pm_runtime_disable(isi->dev);
+
+       return 0;
+}
+
+static const struct of_device_id mxc_isi_of_match[] = {
+       { .compatible = "fsl,imx8mn-isi", .data = &mxc_imx8mn_data },
+       { .compatible = "fsl,imx8mp-isi", .data = &mxc_imx8mp_data },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mxc_isi_of_match);
+
+static struct platform_driver mxc_isi_driver = {
+       .probe          = mxc_isi_probe,
+       .remove         = mxc_isi_remove,
+       .driver = {
+               .of_match_table = mxc_isi_of_match,
+               .name           = MXC_ISI_DRIVER_NAME,
+               .pm             = &mxc_isi_pm_ops,
+       }
+};
+module_platform_driver(mxc_isi_driver);
+
+MODULE_ALIAS("ISI");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("IMX8 Image Sensing Interface driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h
new file mode 100644 (file)
index 0000000..e469788
--- /dev/null
@@ -0,0 +1,394 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * V4L2 Capture ISI subdev for i.MX8QXP/QM platform
+ *
+ * ISI is a Image Sensor Interface of i.MX8QXP/QM platform, which
+ * used to process image from camera sensor to memory or DC
+ * Copyright 2019-2020 NXP
+ */
+
+#ifndef __MXC_ISI_CORE_H__
+#define __MXC_ISI_CORE_H__
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+
+struct clk_bulk_data;
+struct dentry;
+struct device;
+struct media_intf_devnode;
+struct regmap;
+struct v4l2_m2m_dev;
+
+/* Pipeline pads */
+#define MXC_ISI_PIPE_PAD_SINK          0
+#define MXC_ISI_PIPE_PAD_SOURCE                1
+#define MXC_ISI_PIPE_PADS_NUM          2
+
+#define MXC_ISI_MIN_WIDTH              1U
+#define MXC_ISI_MIN_HEIGHT             1U
+#define MXC_ISI_MAX_WIDTH_UNCHAINED    2048U
+#define MXC_ISI_MAX_WIDTH_CHAINED      4096U
+#define MXC_ISI_MAX_HEIGHT             8191U
+
+#define MXC_ISI_DEF_WIDTH              1920U
+#define MXC_ISI_DEF_HEIGHT             1080U
+#define MXC_ISI_DEF_MBUS_CODE_SINK     MEDIA_BUS_FMT_UYVY8_1X16
+#define MXC_ISI_DEF_MBUS_CODE_SOURCE   MEDIA_BUS_FMT_YUV8_1X24
+#define MXC_ISI_DEF_PIXEL_FORMAT       V4L2_PIX_FMT_YUYV
+#define MXC_ISI_DEF_COLOR_SPACE                V4L2_COLORSPACE_SRGB
+#define MXC_ISI_DEF_YCBCR_ENC          V4L2_YCBCR_ENC_601
+#define MXC_ISI_DEF_QUANTIZATION       V4L2_QUANTIZATION_LIM_RANGE
+#define MXC_ISI_DEF_XFER_FUNC          V4L2_XFER_FUNC_SRGB
+
+#define MXC_ISI_DRIVER_NAME            "mxc-isi"
+#define MXC_ISI_CAPTURE                        "mxc-isi-cap"
+#define MXC_ISI_M2M                    "mxc-isi-m2m"
+#define MXC_MAX_PLANES                 3
+
+struct mxc_isi_dev;
+struct mxc_isi_m2m_ctx;
+
+enum mxc_isi_buf_id {
+       MXC_ISI_BUF1 = 0x0,
+       MXC_ISI_BUF2,
+};
+
+enum mxc_isi_encoding {
+       MXC_ISI_ENC_RAW,
+       MXC_ISI_ENC_RGB,
+       MXC_ISI_ENC_YUV,
+};
+
+enum mxc_isi_input_id {
+       /* Inputs from the crossbar switch range from 0 to 15 */
+       MXC_ISI_INPUT_MEM = 16,
+};
+
+enum mxc_isi_video_type {
+       MXC_ISI_VIDEO_CAP = BIT(0),
+       MXC_ISI_VIDEO_M2M_OUT = BIT(1),
+       MXC_ISI_VIDEO_M2M_CAP = BIT(2),
+};
+
+struct mxc_isi_format_info {
+       u32     mbus_code;
+       u32     fourcc;
+       enum mxc_isi_video_type type;
+       u32     isi_in_format;
+       u32     isi_out_format;
+       u8      mem_planes;
+       u8      color_planes;
+       u8      depth[MXC_MAX_PLANES];
+       u8      hsub;
+       u8      vsub;
+       enum mxc_isi_encoding encoding;
+};
+
+struct mxc_isi_bus_format_info {
+       u32     mbus_code;
+       u32     output;
+       u32     pads;
+       enum mxc_isi_encoding encoding;
+};
+
+struct mxc_isi_buffer {
+       struct vb2_v4l2_buffer  v4l2_buf;
+       struct list_head        list;
+       dma_addr_t              dma_addrs[3];
+       enum mxc_isi_buf_id     id;
+       bool discard;
+};
+
+struct mxc_isi_reg {
+       u32 offset;
+       u32 mask;
+};
+
+struct mxc_isi_ier_reg {
+       /* Overflow Y/U/V trigger enable*/
+       struct mxc_isi_reg oflw_y_buf_en;
+       struct mxc_isi_reg oflw_u_buf_en;
+       struct mxc_isi_reg oflw_v_buf_en;
+
+       /* Excess overflow Y/U/V trigger enable*/
+       struct mxc_isi_reg excs_oflw_y_buf_en;
+       struct mxc_isi_reg excs_oflw_u_buf_en;
+       struct mxc_isi_reg excs_oflw_v_buf_en;
+
+       /* Panic Y/U/V trigger enable*/
+       struct mxc_isi_reg panic_y_buf_en;
+       struct mxc_isi_reg panic_v_buf_en;
+       struct mxc_isi_reg panic_u_buf_en;
+};
+
+struct mxc_isi_panic_thd {
+       u32 mask;
+       u32 offset;
+       u32 threshold;
+};
+
+struct mxc_isi_set_thd {
+       struct mxc_isi_panic_thd panic_set_thd_y;
+       struct mxc_isi_panic_thd panic_set_thd_u;
+       struct mxc_isi_panic_thd panic_set_thd_v;
+};
+
+enum model {
+       MXC_ISI_IMX8MN,
+       MXC_ISI_IMX8MP,
+};
+
+struct mxc_isi_plat_data {
+       enum model model;
+       unsigned int num_ports;
+       unsigned int num_channels;
+       unsigned int reg_offset;
+       const struct mxc_isi_ier_reg  *ier_reg;
+       const struct mxc_isi_set_thd *set_thd;
+       const struct clk_bulk_data *clks;
+       unsigned int num_clks;
+       bool buf_active_reverse;
+       bool has_gasket;
+       bool has_36bit_dma;
+};
+
+struct mxc_isi_dma_buffer {
+       size_t                          size;
+       void                            *addr;
+       dma_addr_t                      dma;
+};
+
+struct mxc_isi_input {
+       unsigned int                    enable_count;
+};
+
+struct mxc_isi_crossbar {
+       struct mxc_isi_dev              *isi;
+
+       unsigned int                    num_sinks;
+       unsigned int                    num_sources;
+       struct mxc_isi_input            *inputs;
+
+       struct v4l2_subdev              sd;
+       struct media_pad                *pads;
+};
+
+struct mxc_isi_video {
+       struct mxc_isi_pipe             *pipe;
+
+       struct video_device             vdev;
+       struct media_pad                pad;
+
+       /* Protects is_streaming, and the vdev and vb2_q operations */
+       struct mutex                    lock;
+       bool                            is_streaming;
+
+       struct v4l2_pix_format_mplane   pix;
+       const struct mxc_isi_format_info *fmtinfo;
+
+       struct {
+               struct v4l2_ctrl_handler handler;
+               unsigned int            alpha;
+               bool                    hflip;
+               bool                    vflip;
+       } ctrls;
+
+       struct vb2_queue                vb2_q;
+       struct mxc_isi_buffer           buf_discard[3];
+       struct list_head                out_pending;
+       struct list_head                out_active;
+       struct list_head                out_discard;
+       u32                             frame_count;
+       /* Protects out_pending, out_active, out_discard and frame_count */
+       spinlock_t                      buf_lock;
+
+       struct mxc_isi_dma_buffer       discard_buffer[MXC_MAX_PLANES];
+};
+
+typedef void(*mxc_isi_pipe_irq_t)(struct mxc_isi_pipe *, u32);
+
+struct mxc_isi_pipe {
+       struct mxc_isi_dev              *isi;
+       u32                             id;
+       void __iomem                    *regs;
+
+       struct media_pipeline           pipe;
+
+       struct v4l2_subdev              sd;
+       struct media_pad                pads[MXC_ISI_PIPE_PADS_NUM];
+
+       struct mxc_isi_video            video;
+
+       /*
+        * Protects use_count, irq_handler, res_available, res_acquired,
+        * chained_res, and the CHNL_CTRL register.
+        */
+       struct mutex                    lock;
+       unsigned int                    use_count;
+       mxc_isi_pipe_irq_t              irq_handler;
+
+#define MXC_ISI_CHANNEL_RES_LINE_BUF   BIT(0)
+#define MXC_ISI_CHANNEL_RES_OUTPUT_BUF BIT(1)
+       u8                              available_res;
+       u8                              acquired_res;
+       u8                              chained_res;
+       bool                            chained;
+};
+
+struct mxc_isi_m2m {
+       struct mxc_isi_dev              *isi;
+       struct mxc_isi_pipe             *pipe;
+
+       struct media_pad                pad;
+       struct video_device             vdev;
+       struct media_intf_devnode       *intf;
+       struct v4l2_m2m_dev             *m2m_dev;
+
+       /* Protects last_ctx, usage_count and chained_count */
+       struct mutex                    lock;
+
+       struct mxc_isi_m2m_ctx          *last_ctx;
+       int                             usage_count;
+       int                             chained_count;
+};
+
+struct mxc_isi_dev {
+       struct device                   *dev;
+
+       const struct mxc_isi_plat_data  *pdata;
+
+       void __iomem                    *regs;
+       struct clk_bulk_data            *clks;
+       struct regmap                   *gasket;
+
+       struct mxc_isi_crossbar         crossbar;
+       struct mxc_isi_pipe             *pipes;
+       struct mxc_isi_m2m              m2m;
+
+       struct media_device             media_dev;
+       struct v4l2_device              v4l2_dev;
+       struct v4l2_async_notifier      notifier;
+
+       struct dentry                   *debugfs_root;
+};
+
+int mxc_isi_crossbar_init(struct mxc_isi_dev *isi);
+void mxc_isi_crossbar_cleanup(struct mxc_isi_crossbar *xbar);
+int mxc_isi_crossbar_register(struct mxc_isi_crossbar *xbar);
+void mxc_isi_crossbar_unregister(struct mxc_isi_crossbar *xbar);
+
+const struct mxc_isi_bus_format_info *
+mxc_isi_bus_format_by_code(u32 code, unsigned int pad);
+const struct mxc_isi_bus_format_info *
+mxc_isi_bus_format_by_index(unsigned int index, unsigned int pad);
+const struct mxc_isi_format_info *
+mxc_isi_format_by_fourcc(u32 fourcc, enum mxc_isi_video_type type);
+const struct mxc_isi_format_info *
+mxc_isi_format_enum(unsigned int index, enum mxc_isi_video_type type);
+const struct mxc_isi_format_info *
+mxc_isi_format_try(struct mxc_isi_pipe *pipe, struct v4l2_pix_format_mplane *pix,
+                  enum mxc_isi_video_type type);
+
+int mxc_isi_pipe_init(struct mxc_isi_dev *isi, unsigned int id);
+void mxc_isi_pipe_cleanup(struct mxc_isi_pipe *pipe);
+int mxc_isi_pipe_acquire(struct mxc_isi_pipe *pipe,
+                        mxc_isi_pipe_irq_t irq_handler);
+void mxc_isi_pipe_release(struct mxc_isi_pipe *pipe);
+int mxc_isi_pipe_enable(struct mxc_isi_pipe *pipe);
+void mxc_isi_pipe_disable(struct mxc_isi_pipe *pipe);
+
+int mxc_isi_video_register(struct mxc_isi_pipe *pipe,
+                          struct v4l2_device *v4l2_dev);
+void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe);
+void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe);
+int mxc_isi_video_resume(struct mxc_isi_pipe *pipe);
+int mxc_isi_video_queue_setup(const struct v4l2_pix_format_mplane *format,
+                             const struct mxc_isi_format_info *info,
+                             unsigned int *num_buffers,
+                             unsigned int *num_planes, unsigned int sizes[]);
+void mxc_isi_video_buffer_init(struct vb2_buffer *vb2, dma_addr_t dma_addrs[3],
+                              const struct mxc_isi_format_info *info,
+                              const struct v4l2_pix_format_mplane *pix);
+int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2,
+                                const struct mxc_isi_format_info *info,
+                                const struct v4l2_pix_format_mplane *pix);
+
+#ifdef CONFIG_VIDEO_IMX8_ISI_M2M
+int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev);
+int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi);
+#else
+static inline int mxc_isi_m2m_register(struct mxc_isi_dev *isi,
+                                      struct v4l2_device *v4l2_dev)
+{
+       return 0;
+}
+static inline int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi)
+{
+       return 0;
+}
+#endif
+
+int mxc_isi_channel_acquire(struct mxc_isi_pipe *pipe,
+                           mxc_isi_pipe_irq_t irq_handler, bool bypass);
+void mxc_isi_channel_release(struct mxc_isi_pipe *pipe);
+void mxc_isi_channel_get(struct mxc_isi_pipe *pipe);
+void mxc_isi_channel_put(struct mxc_isi_pipe *pipe);
+void mxc_isi_channel_enable(struct mxc_isi_pipe *pipe);
+void mxc_isi_channel_disable(struct mxc_isi_pipe *pipe);
+int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe, bool bypass);
+void mxc_isi_channel_unchain(struct mxc_isi_pipe *pipe);
+
+void mxc_isi_channel_config(struct mxc_isi_pipe *pipe,
+                           enum mxc_isi_input_id input,
+                           const struct v4l2_area *in_size,
+                           const struct v4l2_area *scale,
+                           const struct v4l2_rect *crop,
+                           enum mxc_isi_encoding in_encoding,
+                           enum mxc_isi_encoding out_encoding);
+
+void mxc_isi_channel_set_input_format(struct mxc_isi_pipe *pipe,
+                                     const struct mxc_isi_format_info *info,
+                                     const struct v4l2_pix_format_mplane *format);
+void mxc_isi_channel_set_output_format(struct mxc_isi_pipe *pipe,
+                                      const struct mxc_isi_format_info *info,
+                                      struct v4l2_pix_format_mplane *format);
+void mxc_isi_channel_m2m_start(struct mxc_isi_pipe *pipe);
+
+void mxc_isi_channel_set_alpha(struct mxc_isi_pipe *pipe, u8 alpha);
+void mxc_isi_channel_set_flip(struct mxc_isi_pipe *pipe, bool hflip, bool vflip);
+
+void mxc_isi_channel_set_inbuf(struct mxc_isi_pipe *pipe, dma_addr_t dma_addr);
+void mxc_isi_channel_set_outbuf(struct mxc_isi_pipe *pipe,
+                               const dma_addr_t dma_addrs[3],
+                               enum mxc_isi_buf_id buf_id);
+
+u32 mxc_isi_channel_irq_status(struct mxc_isi_pipe *pipe, bool clear);
+void mxc_isi_channel_irq_clear(struct mxc_isi_pipe *pipe);
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+void mxc_isi_debug_init(struct mxc_isi_dev *isi);
+void mxc_isi_debug_cleanup(struct mxc_isi_dev *isi);
+#else
+static inline void mxc_isi_debug_init(struct mxc_isi_dev *isi)
+{
+}
+static inline void mxc_isi_debug_cleanup(struct mxc_isi_dev *isi)
+{
+}
+#endif
+
+#endif /* __MXC_ISI_CORE_H__ */
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
new file mode 100644 (file)
index 0000000..b5ffde4
--- /dev/null
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * i.MX8 ISI - Input crossbar switch
+ *
+ * Copyright (c) 2022 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/minmax.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <media/media-entity.h>
+#include <media/mipi-csi2.h>
+#include <media/v4l2-subdev.h>
+
+#include "imx8-isi-core.h"
+
+static inline struct mxc_isi_crossbar *to_isi_crossbar(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct mxc_isi_crossbar, sd);
+}
+
+/* -----------------------------------------------------------------------------
+ * Media block control (i.MX8MN and i.MX8MP only)
+ */
+#define GASKET_BASE(n)                         (0x0060 + (n) * 0x30)
+
+#define GASKET_CTRL                            0x0000
+#define GASKET_CTRL_DATA_TYPE(dt)              ((dt) << 8)
+#define GASKET_CTRL_DATA_TYPE_MASK             (0x3f << 8)
+#define GASKET_CTRL_DUAL_COMP_ENABLE           BIT(1)
+#define GASKET_CTRL_ENABLE                     BIT(0)
+
+#define GASKET_HSIZE                           0x0004
+#define GASKET_VSIZE                           0x0008
+
+static int mxc_isi_crossbar_gasket_enable(struct mxc_isi_crossbar *xbar,
+                                         struct v4l2_subdev_state *state,
+                                         struct v4l2_subdev *remote_sd,
+                                         u32 remote_pad, unsigned int port)
+{
+       struct mxc_isi_dev *isi = xbar->isi;
+       const struct v4l2_mbus_framefmt *fmt;
+       struct v4l2_mbus_frame_desc fd;
+       u32 val;
+       int ret;
+
+       if (!isi->pdata->has_gasket)
+               return 0;
+
+       /*
+        * Configure and enable the gasket with the frame size and CSI-2 data
+        * type. For YUV422 8-bit, enable dual component mode unconditionally,
+        * to match the configuration of the CSIS.
+        */
+
+       ret = v4l2_subdev_call(remote_sd, pad, get_frame_desc, remote_pad, &fd);
+       if (ret) {
+               dev_err(isi->dev,
+                       "failed to get frame descriptor from '%s':%u: %d\n",
+                       remote_sd->name, remote_pad, ret);
+               return ret;
+       }
+
+       if (fd.num_entries != 1) {
+               dev_err(isi->dev, "invalid frame descriptor for '%s':%u\n",
+                       remote_sd->name, remote_pad);
+               return -EINVAL;
+       }
+
+       fmt = v4l2_subdev_state_get_stream_format(state, port, 0);
+       if (!fmt)
+               return -EINVAL;
+
+       regmap_write(isi->gasket, GASKET_BASE(port) + GASKET_HSIZE, fmt->width);
+       regmap_write(isi->gasket, GASKET_BASE(port) + GASKET_VSIZE, fmt->height);
+
+       val = GASKET_CTRL_DATA_TYPE(fd.entry[0].bus.csi2.dt)
+           | GASKET_CTRL_ENABLE;
+
+       if (fd.entry[0].bus.csi2.dt == MIPI_CSI2_DT_YUV422_8B)
+               val |= GASKET_CTRL_DUAL_COMP_ENABLE;
+
+       regmap_write(isi->gasket, GASKET_BASE(port) + GASKET_CTRL, val);
+
+       return 0;
+}
+
+static void mxc_isi_crossbar_gasket_disable(struct mxc_isi_crossbar *xbar,
+                                           unsigned int port)
+{
+       struct mxc_isi_dev *isi = xbar->isi;
+
+       if (!isi->pdata->has_gasket)
+               return;
+
+       regmap_write(isi->gasket, GASKET_BASE(port) + GASKET_CTRL, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static const struct v4l2_mbus_framefmt mxc_isi_crossbar_default_format = {
+       .code = MXC_ISI_DEF_MBUS_CODE_SINK,
+       .width = MXC_ISI_DEF_WIDTH,
+       .height = MXC_ISI_DEF_HEIGHT,
+       .field = V4L2_FIELD_NONE,
+       .colorspace = MXC_ISI_DEF_COLOR_SPACE,
+       .ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC,
+       .quantization = MXC_ISI_DEF_QUANTIZATION,
+       .xfer_func = MXC_ISI_DEF_XFER_FUNC,
+};
+
+static int __mxc_isi_crossbar_set_routing(struct v4l2_subdev *sd,
+                                         struct v4l2_subdev_state *state,
+                                         struct v4l2_subdev_krouting *routing)
+{
+       struct mxc_isi_crossbar *xbar = to_isi_crossbar(sd);
+       struct v4l2_subdev_route *route;
+       int ret;
+
+       ret = v4l2_subdev_routing_validate(sd, routing,
+                                          V4L2_SUBDEV_ROUTING_NO_N_TO_1);
+       if (ret)
+               return ret;
+
+       /* The memory input can be routed to the first pipeline only. */
+       for_each_active_route(&state->routing, route) {
+               if (route->sink_pad == xbar->num_sinks - 1 &&
+                   route->source_pad != xbar->num_sinks) {
+                       dev_dbg(xbar->isi->dev,
+                               "invalid route from memory input (%u) to pipe %u\n",
+                               route->sink_pad,
+                               route->source_pad - xbar->num_sinks);
+                       return -EINVAL;
+               }
+       }
+
+       return v4l2_subdev_set_routing_with_fmt(sd, state, routing,
+                                               &mxc_isi_crossbar_default_format);
+}
+
+static struct v4l2_subdev *
+mxc_isi_crossbar_xlate_streams(struct mxc_isi_crossbar *xbar,
+                              struct v4l2_subdev_state *state,
+                              u32 source_pad, u64 source_streams,
+                              u32 *__sink_pad, u64 *__sink_streams,
+                              u32 *remote_pad)
+{
+       struct v4l2_subdev_route *route;
+       struct v4l2_subdev *sd;
+       struct media_pad *pad;
+       u64 sink_streams = 0;
+       int sink_pad = -1;
+
+       /*
+        * Translate the source pad and streams to the sink side. The routing
+        * validation forbids stream merging, so all matching entries in the
+        * routing table are guaranteed to have the same sink pad.
+        *
+        * TODO: This is likely worth a helper function, it could perhaps be
+        * supported by v4l2_subdev_state_xlate_streams() with pad1 set to -1.
+        */
+       for_each_active_route(&state->routing, route) {
+               if (route->source_pad != source_pad ||
+                   !(source_streams & BIT(route->source_stream)))
+                       continue;
+
+               sink_streams |= BIT(route->sink_stream);
+               sink_pad = route->sink_pad;
+       }
+
+       if (sink_pad < 0) {
+               dev_dbg(xbar->isi->dev,
+                       "no stream connected to pipeline %u\n",
+                       source_pad - xbar->num_sinks);
+               return ERR_PTR(-EPIPE);
+       }
+
+       pad = media_pad_remote_pad_first(&xbar->pads[sink_pad]);
+       sd = media_entity_to_v4l2_subdev(pad->entity);
+
+       if (!sd) {
+               dev_dbg(xbar->isi->dev,
+                       "no entity connected to crossbar input %u\n",
+                       sink_pad);
+               return ERR_PTR(-EPIPE);
+       }
+
+       *__sink_pad = sink_pad;
+       *__sink_streams = sink_streams;
+       *remote_pad = pad->index;
+
+       return sd;
+}
+
+static int mxc_isi_crossbar_init_cfg(struct v4l2_subdev *sd,
+                                    struct v4l2_subdev_state *state)
+{
+       struct mxc_isi_crossbar *xbar = to_isi_crossbar(sd);
+       struct v4l2_subdev_krouting routing = { };
+       struct v4l2_subdev_route *routes;
+       unsigned int i;
+       int ret;
+
+       /*
+        * Create a 1:1 mapping between pixel link inputs and outputs to
+        * pipelines by default.
+        */
+       routes = kcalloc(xbar->num_sources, sizeof(*routes), GFP_KERNEL);
+       if (!routes)
+               return -ENOMEM;
+
+       for (i = 0; i < xbar->num_sources; ++i) {
+               struct v4l2_subdev_route *route = &routes[i];
+
+               route->sink_pad = i;
+               route->source_pad = i + xbar->num_sinks;
+               route->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE;
+       };
+
+       routing.num_routes = xbar->num_sources;
+       routing.routes = routes;
+
+       ret = __mxc_isi_crossbar_set_routing(sd, state, &routing);
+
+       kfree(routes);
+
+       return ret;
+}
+
+static int mxc_isi_crossbar_enum_mbus_code(struct v4l2_subdev *sd,
+                                          struct v4l2_subdev_state *state,
+                                          struct v4l2_subdev_mbus_code_enum *code)
+{
+       struct mxc_isi_crossbar *xbar = to_isi_crossbar(sd);
+       const struct mxc_isi_bus_format_info *info;
+
+       if (code->pad >= xbar->num_sinks) {
+               const struct v4l2_mbus_framefmt *format;
+
+               /*
+                * The media bus code on source pads is identical to the
+                * connected sink pad.
+                */
+               if (code->index > 0)
+                       return -EINVAL;
+
+               format = v4l2_subdev_state_get_opposite_stream_format(state,
+                                                                     code->pad,
+                                                                     code->stream);
+               if (!format)
+                       return -EINVAL;
+
+               code->code = format->code;
+
+               return 0;
+       }
+
+       info = mxc_isi_bus_format_by_index(code->index, MXC_ISI_PIPE_PAD_SINK);
+       if (!info)
+               return -EINVAL;
+
+       code->code = info->mbus_code;
+
+       return 0;
+}
+
+static int mxc_isi_crossbar_set_fmt(struct v4l2_subdev *sd,
+                                   struct v4l2_subdev_state *state,
+                                   struct v4l2_subdev_format *fmt)
+{
+       struct mxc_isi_crossbar *xbar = to_isi_crossbar(sd);
+       struct v4l2_mbus_framefmt *sink_fmt;
+       struct v4l2_subdev_route *route;
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
+           media_pad_is_streaming(&xbar->pads[fmt->pad]))
+               return -EBUSY;
+
+       /*
+        * The source pad format is always identical to the sink pad format and
+        * can't be modified.
+        */
+       if (fmt->pad >= xbar->num_sinks)
+               return v4l2_subdev_get_fmt(sd, state, fmt);
+
+       /* Validate the requested format. */
+       if (!mxc_isi_bus_format_by_code(fmt->format.code, MXC_ISI_PIPE_PAD_SINK))
+               fmt->format.code = MXC_ISI_DEF_MBUS_CODE_SINK;
+
+       fmt->format.width = clamp_t(unsigned int, fmt->format.width,
+                                   MXC_ISI_MIN_WIDTH, MXC_ISI_MAX_WIDTH_CHAINED);
+       fmt->format.height = clamp_t(unsigned int, fmt->format.height,
+                                    MXC_ISI_MIN_HEIGHT, MXC_ISI_MAX_HEIGHT);
+       fmt->format.field = V4L2_FIELD_NONE;
+
+       /*
+        * Set the format on the sink stream and propagate it to the source
+        * streams.
+        */
+       sink_fmt = v4l2_subdev_state_get_stream_format(state, fmt->pad,
+                                                      fmt->stream);
+       if (!sink_fmt)
+               return -EINVAL;
+
+       *sink_fmt = fmt->format;
+
+       /* TODO: A format propagation helper would be useful. */
+       for_each_active_route(&state->routing, route) {
+               struct v4l2_mbus_framefmt *source_fmt;
+
+               if (route->sink_pad != fmt->pad ||
+                   route->sink_stream != fmt->stream)
+                       continue;
+
+               source_fmt = v4l2_subdev_state_get_stream_format(state, route->source_pad,
+                                                                route->source_stream);
+               if (!source_fmt)
+                       return -EINVAL;
+
+               *source_fmt = fmt->format;
+       }
+
+       return 0;
+}
+
+static int mxc_isi_crossbar_set_routing(struct v4l2_subdev *sd,
+                                       struct v4l2_subdev_state *state,
+                                       enum v4l2_subdev_format_whence which,
+                                       struct v4l2_subdev_krouting *routing)
+{
+       if (which == V4L2_SUBDEV_FORMAT_ACTIVE &&
+           media_entity_is_streaming(&sd->entity))
+               return -EBUSY;
+
+       return __mxc_isi_crossbar_set_routing(sd, state, routing);
+}
+
+static int mxc_isi_crossbar_enable_streams(struct v4l2_subdev *sd,
+                                          struct v4l2_subdev_state *state,
+                                          u32 pad, u64 streams_mask)
+{
+       struct mxc_isi_crossbar *xbar = to_isi_crossbar(sd);
+       struct v4l2_subdev *remote_sd;
+       struct mxc_isi_input *input;
+       u64 sink_streams;
+       u32 sink_pad;
+       u32 remote_pad;
+       int ret;
+
+       remote_sd = mxc_isi_crossbar_xlate_streams(xbar, state, pad, streams_mask,
+                                                  &sink_pad, &sink_streams,
+                                                  &remote_pad);
+       if (IS_ERR(remote_sd))
+               return PTR_ERR(remote_sd);
+
+       input = &xbar->inputs[sink_pad];
+
+       /*
+        * TODO: Track per-stream enable counts to support multiplexed
+        * streams.
+        */
+       if (!input->enable_count) {
+               ret = mxc_isi_crossbar_gasket_enable(xbar, state, remote_sd,
+                                                    remote_pad, sink_pad);
+               if (ret)
+                       return ret;
+
+               ret = v4l2_subdev_enable_streams(remote_sd, remote_pad,
+                                                sink_streams);
+               if (ret) {
+                       dev_err(xbar->isi->dev,
+                               "failed to %s streams 0x%llx on '%s':%u: %d\n",
+                               "enable", sink_streams, remote_sd->name,
+                               remote_pad, ret);
+                       mxc_isi_crossbar_gasket_disable(xbar, sink_pad);
+                       return ret;
+               }
+       }
+
+       input->enable_count++;
+
+       return 0;
+}
+
+static int mxc_isi_crossbar_disable_streams(struct v4l2_subdev *sd,
+                                           struct v4l2_subdev_state *state,
+                                           u32 pad, u64 streams_mask)
+{
+       struct mxc_isi_crossbar *xbar = to_isi_crossbar(sd);
+       struct v4l2_subdev *remote_sd;
+       struct mxc_isi_input *input;
+       u64 sink_streams;
+       u32 sink_pad;
+       u32 remote_pad;
+       int ret = 0;
+
+       remote_sd = mxc_isi_crossbar_xlate_streams(xbar, state, pad, streams_mask,
+                                                  &sink_pad, &sink_streams,
+                                                  &remote_pad);
+       if (IS_ERR(remote_sd))
+               return PTR_ERR(remote_sd);
+
+       input = &xbar->inputs[sink_pad];
+
+       input->enable_count--;
+
+       if (!input->enable_count) {
+               ret = v4l2_subdev_disable_streams(remote_sd, remote_pad,
+                                                 sink_streams);
+               if (ret)
+                       dev_err(xbar->isi->dev,
+                               "failed to %s streams 0x%llx on '%s':%u: %d\n",
+                               "disable", sink_streams, remote_sd->name,
+                               remote_pad, ret);
+
+               mxc_isi_crossbar_gasket_disable(xbar, sink_pad);
+       }
+
+       return ret;
+}
+
+static const struct v4l2_subdev_pad_ops mxc_isi_crossbar_subdev_pad_ops = {
+       .init_cfg = mxc_isi_crossbar_init_cfg,
+       .enum_mbus_code = mxc_isi_crossbar_enum_mbus_code,
+       .get_fmt = v4l2_subdev_get_fmt,
+       .set_fmt = mxc_isi_crossbar_set_fmt,
+       .set_routing = mxc_isi_crossbar_set_routing,
+       .enable_streams = mxc_isi_crossbar_enable_streams,
+       .disable_streams = mxc_isi_crossbar_disable_streams,
+};
+
+static const struct v4l2_subdev_ops mxc_isi_crossbar_subdev_ops = {
+       .pad = &mxc_isi_crossbar_subdev_pad_ops,
+};
+
+static const struct media_entity_operations mxc_isi_cross_entity_ops = {
+       .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
+       .link_validate  = v4l2_subdev_link_validate,
+       .has_pad_interdep = v4l2_subdev_has_pad_interdep,
+};
+
+/* -----------------------------------------------------------------------------
+ * Init & cleanup
+ */
+
+int mxc_isi_crossbar_init(struct mxc_isi_dev *isi)
+{
+       struct mxc_isi_crossbar *xbar = &isi->crossbar;
+       struct v4l2_subdev *sd = &xbar->sd;
+       unsigned int num_pads;
+       unsigned int i;
+       int ret;
+
+       xbar->isi = isi;
+
+       v4l2_subdev_init(sd, &mxc_isi_crossbar_subdev_ops);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
+       strscpy(sd->name, "crossbar", sizeof(sd->name));
+       sd->dev = isi->dev;
+
+       sd->entity.function = MEDIA_ENT_F_VID_MUX;
+       sd->entity.ops = &mxc_isi_cross_entity_ops;
+
+       /*
+        * The subdev has one sink and one source per port, plus one sink for
+        * the memory input.
+        */
+       xbar->num_sinks = isi->pdata->num_ports + 1;
+       xbar->num_sources = isi->pdata->num_ports;
+       num_pads = xbar->num_sinks + xbar->num_sources;
+
+       xbar->pads = kcalloc(num_pads, sizeof(*xbar->pads), GFP_KERNEL);
+       if (!xbar->pads)
+               return -ENOMEM;
+
+       xbar->inputs = kcalloc(xbar->num_sinks, sizeof(*xbar->inputs),
+                              GFP_KERNEL);
+       if (!xbar->pads) {
+               ret = -ENOMEM;
+               goto err_free;
+       }
+
+       for (i = 0; i < xbar->num_sinks; ++i)
+               xbar->pads[i].flags = MEDIA_PAD_FL_SINK;
+       for (i = 0; i < xbar->num_sources; ++i)
+               xbar->pads[i + xbar->num_sinks].flags = MEDIA_PAD_FL_SOURCE;
+
+       ret = media_entity_pads_init(&sd->entity, num_pads, xbar->pads);
+       if (ret)
+               goto err_free;
+
+       ret = v4l2_subdev_init_finalize(sd);
+       if (ret < 0)
+               goto err_entity;
+
+       return 0;
+
+err_entity:
+       media_entity_cleanup(&sd->entity);
+err_free:
+       kfree(xbar->pads);
+       kfree(xbar->inputs);
+
+       return ret;
+}
+
+void mxc_isi_crossbar_cleanup(struct mxc_isi_crossbar *xbar)
+{
+       media_entity_cleanup(&xbar->sd.entity);
+       kfree(xbar->pads);
+       kfree(xbar->inputs);
+}
+
+int mxc_isi_crossbar_register(struct mxc_isi_crossbar *xbar)
+{
+       return v4l2_device_register_subdev(&xbar->isi->v4l2_dev, &xbar->sd);
+}
+
+void mxc_isi_crossbar_unregister(struct mxc_isi_crossbar *xbar)
+{
+}
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-debug.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-debug.c
new file mode 100644 (file)
index 0000000..6709ab7
--- /dev/null
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019-2020 NXP
+ */
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/pm_runtime.h>
+#include <linux/seq_file.h>
+#include <linux/types.h>
+
+#include "imx8-isi-core.h"
+#include "imx8-isi-regs.h"
+
+static inline u32 mxc_isi_read(struct mxc_isi_pipe *pipe, u32 reg)
+{
+       return readl(pipe->regs + reg);
+}
+
+static int mxc_isi_debug_dump_regs_show(struct seq_file *m, void *p)
+{
+#define MXC_ISI_DEBUG_REG(name)                { name, #name }
+       static const struct {
+               u32 offset;
+               const char * const name;
+       } registers[] = {
+               MXC_ISI_DEBUG_REG(CHNL_CTRL),
+               MXC_ISI_DEBUG_REG(CHNL_IMG_CTRL),
+               MXC_ISI_DEBUG_REG(CHNL_OUT_BUF_CTRL),
+               MXC_ISI_DEBUG_REG(CHNL_IMG_CFG),
+               MXC_ISI_DEBUG_REG(CHNL_IER),
+               MXC_ISI_DEBUG_REG(CHNL_STS),
+               MXC_ISI_DEBUG_REG(CHNL_SCALE_FACTOR),
+               MXC_ISI_DEBUG_REG(CHNL_SCALE_OFFSET),
+               MXC_ISI_DEBUG_REG(CHNL_CROP_ULC),
+               MXC_ISI_DEBUG_REG(CHNL_CROP_LRC),
+               MXC_ISI_DEBUG_REG(CHNL_CSC_COEFF0),
+               MXC_ISI_DEBUG_REG(CHNL_CSC_COEFF1),
+               MXC_ISI_DEBUG_REG(CHNL_CSC_COEFF2),
+               MXC_ISI_DEBUG_REG(CHNL_CSC_COEFF3),
+               MXC_ISI_DEBUG_REG(CHNL_CSC_COEFF4),
+               MXC_ISI_DEBUG_REG(CHNL_CSC_COEFF5),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_0_ALPHA),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_0_ULC),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_0_LRC),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_1_ALPHA),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_1_ULC),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_1_LRC),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_2_ALPHA),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_2_ULC),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_2_LRC),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_3_ALPHA),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_3_ULC),
+               MXC_ISI_DEBUG_REG(CHNL_ROI_3_LRC),
+               MXC_ISI_DEBUG_REG(CHNL_OUT_BUF1_ADDR_Y),
+               MXC_ISI_DEBUG_REG(CHNL_OUT_BUF1_ADDR_U),
+               MXC_ISI_DEBUG_REG(CHNL_OUT_BUF1_ADDR_V),
+               MXC_ISI_DEBUG_REG(CHNL_OUT_BUF_PITCH),
+               MXC_ISI_DEBUG_REG(CHNL_IN_BUF_ADDR),
+               MXC_ISI_DEBUG_REG(CHNL_IN_BUF_PITCH),
+               MXC_ISI_DEBUG_REG(CHNL_MEM_RD_CTRL),
+               MXC_ISI_DEBUG_REG(CHNL_OUT_BUF2_ADDR_Y),
+               MXC_ISI_DEBUG_REG(CHNL_OUT_BUF2_ADDR_U),
+               MXC_ISI_DEBUG_REG(CHNL_OUT_BUF2_ADDR_V),
+               MXC_ISI_DEBUG_REG(CHNL_SCL_IMG_CFG),
+               MXC_ISI_DEBUG_REG(CHNL_FLOW_CTRL),
+       };
+
+       struct mxc_isi_pipe *pipe = m->private;
+       unsigned int i;
+
+       if (!pm_runtime_get_if_in_use(pipe->isi->dev))
+               return 0;
+
+       seq_printf(m, "--- ISI pipe %u registers ---\n", pipe->id);
+
+       for (i = 0; i < ARRAY_SIZE(registers); ++i)
+               seq_printf(m, "%20s[0x%02x]: 0x%08x\n",
+                          registers[i].name, registers[i].offset,
+                          mxc_isi_read(pipe, registers[i].offset));
+
+       pm_runtime_put(pipe->isi->dev);
+
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(mxc_isi_debug_dump_regs);
+
+void mxc_isi_debug_init(struct mxc_isi_dev *isi)
+{
+       unsigned int i;
+
+       isi->debugfs_root = debugfs_create_dir(dev_name(isi->dev), NULL);
+
+       for (i = 0; i < isi->pdata->num_channels; ++i) {
+               struct mxc_isi_pipe *pipe = &isi->pipes[i];
+               char name[8];
+
+               sprintf(name, "pipe%u", pipe->id);
+               debugfs_create_file(name, 0444, isi->debugfs_root, pipe,
+                                   &mxc_isi_debug_dump_regs_fops);
+       }
+}
+
+void mxc_isi_debug_cleanup(struct mxc_isi_dev *isi)
+{
+       debugfs_remove_recursive(isi->debugfs_root);
+}
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c
new file mode 100644 (file)
index 0000000..db538f3
--- /dev/null
@@ -0,0 +1,650 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019-2020 NXP
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/types.h>
+
+#include "imx8-isi-core.h"
+#include "imx8-isi-regs.h"
+
+#define        ISI_DOWNSCALE_THRESHOLD         0x4000
+
+static inline u32 mxc_isi_read(struct mxc_isi_pipe *pipe, u32 reg)
+{
+       return readl(pipe->regs + reg);
+}
+
+static inline void mxc_isi_write(struct mxc_isi_pipe *pipe, u32 reg, u32 val)
+{
+       writel(val, pipe->regs + reg);
+}
+
+/* -----------------------------------------------------------------------------
+ * Buffers & M2M operation
+ */
+
+void mxc_isi_channel_set_inbuf(struct mxc_isi_pipe *pipe, dma_addr_t dma_addr)
+{
+       mxc_isi_write(pipe, CHNL_IN_BUF_ADDR, dma_addr);
+#if CONFIG_ARCH_DMA_ADDR_T_64BIT
+       if (pipe->isi->pdata->has_36bit_dma)
+               mxc_isi_write(pipe, CHNL_IN_BUF_XTND_ADDR, dma_addr >> 32);
+#endif
+}
+
+void mxc_isi_channel_set_outbuf(struct mxc_isi_pipe *pipe,
+                               const dma_addr_t dma_addrs[3],
+                               enum mxc_isi_buf_id buf_id)
+{
+       int val;
+
+       val = mxc_isi_read(pipe, CHNL_OUT_BUF_CTRL);
+
+       if (buf_id == MXC_ISI_BUF1) {
+               mxc_isi_write(pipe, CHNL_OUT_BUF1_ADDR_Y, dma_addrs[0]);
+               mxc_isi_write(pipe, CHNL_OUT_BUF1_ADDR_U, dma_addrs[1]);
+               mxc_isi_write(pipe, CHNL_OUT_BUF1_ADDR_V, dma_addrs[2]);
+#if CONFIG_ARCH_DMA_ADDR_T_64BIT
+               if (pipe->isi->pdata->has_36bit_dma) {
+                       mxc_isi_write(pipe, CHNL_Y_BUF1_XTND_ADDR,
+                                     dma_addrs[0] >> 32);
+                       mxc_isi_write(pipe, CHNL_U_BUF1_XTND_ADDR,
+                                     dma_addrs[1] >> 32);
+                       mxc_isi_write(pipe, CHNL_V_BUF1_XTND_ADDR,
+                                     dma_addrs[2] >> 32);
+               }
+#endif
+               val ^= CHNL_OUT_BUF_CTRL_LOAD_BUF1_ADDR;
+       } else  {
+               mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_Y, dma_addrs[0]);
+               mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_U, dma_addrs[1]);
+               mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_V, dma_addrs[2]);
+#if CONFIG_ARCH_DMA_ADDR_T_64BIT
+               if (pipe->isi->pdata->has_36bit_dma) {
+                       mxc_isi_write(pipe, CHNL_Y_BUF2_XTND_ADDR,
+                                     dma_addrs[0] >> 32);
+                       mxc_isi_write(pipe, CHNL_U_BUF2_XTND_ADDR,
+                                     dma_addrs[1] >> 32);
+                       mxc_isi_write(pipe, CHNL_V_BUF2_XTND_ADDR,
+                                     dma_addrs[2] >> 32);
+               }
+#endif
+               val ^= CHNL_OUT_BUF_CTRL_LOAD_BUF2_ADDR;
+       }
+
+       mxc_isi_write(pipe, CHNL_OUT_BUF_CTRL, val);
+}
+
+void mxc_isi_channel_m2m_start(struct mxc_isi_pipe *pipe)
+{
+       u32 val;
+
+       val = mxc_isi_read(pipe, CHNL_MEM_RD_CTRL);
+       val &= ~CHNL_MEM_RD_CTRL_READ_MEM;
+       mxc_isi_write(pipe, CHNL_MEM_RD_CTRL, val);
+
+       fsleep(300);
+
+       val |= CHNL_MEM_RD_CTRL_READ_MEM;
+       mxc_isi_write(pipe, CHNL_MEM_RD_CTRL, val);
+}
+
+/* -----------------------------------------------------------------------------
+ * Pipeline configuration
+ */
+
+static u32 mxc_isi_channel_scaling_ratio(unsigned int from, unsigned int to,
+                                        u32 *dec)
+{
+       unsigned int ratio = from / to;
+
+       if (ratio < 2)
+               *dec = 1;
+       else if (ratio < 4)
+               *dec = 2;
+       else if (ratio < 8)
+               *dec = 4;
+       else
+               *dec = 8;
+
+       return min_t(u32, from * 0x1000 / (to * *dec), ISI_DOWNSCALE_THRESHOLD);
+}
+
+static void mxc_isi_channel_set_scaling(struct mxc_isi_pipe *pipe,
+                                       enum mxc_isi_encoding encoding,
+                                       const struct v4l2_area *in_size,
+                                       const struct v4l2_area *out_size,
+                                       bool *bypass)
+{
+       u32 xscale, yscale;
+       u32 decx, decy;
+       u32 val;
+
+       dev_dbg(pipe->isi->dev, "input %ux%u, output %ux%u\n",
+               in_size->width, in_size->height,
+               out_size->width, out_size->height);
+
+       xscale = mxc_isi_channel_scaling_ratio(in_size->width, out_size->width,
+                                              &decx);
+       yscale = mxc_isi_channel_scaling_ratio(in_size->height, out_size->height,
+                                              &decy);
+
+       val = mxc_isi_read(pipe, CHNL_IMG_CTRL);
+       val &= ~(CHNL_IMG_CTRL_DEC_X_MASK | CHNL_IMG_CTRL_DEC_Y_MASK |
+                CHNL_IMG_CTRL_YCBCR_MODE);
+
+       val |= CHNL_IMG_CTRL_DEC_X(ilog2(decx))
+           |  CHNL_IMG_CTRL_DEC_Y(ilog2(decy));
+
+       /*
+        * Contrary to what the documentation states, YCBCR_MODE does not
+        * control conversion between YCbCr and RGB, but whether the scaler
+        * operates in YUV mode or in RGB mode. It must be set when the scaler
+        * input is YUV.
+        */
+       if (encoding == MXC_ISI_ENC_YUV)
+               val |= CHNL_IMG_CTRL_YCBCR_MODE;
+
+       mxc_isi_write(pipe, CHNL_IMG_CTRL, val);
+
+       mxc_isi_write(pipe, CHNL_SCALE_FACTOR,
+                     CHNL_SCALE_FACTOR_Y_SCALE(yscale) |
+                     CHNL_SCALE_FACTOR_X_SCALE(xscale));
+
+       mxc_isi_write(pipe, CHNL_SCALE_OFFSET, 0);
+
+       mxc_isi_write(pipe, CHNL_SCL_IMG_CFG,
+                     CHNL_SCL_IMG_CFG_HEIGHT(out_size->height) |
+                     CHNL_SCL_IMG_CFG_WIDTH(out_size->width));
+
+       *bypass = in_size->height == out_size->height &&
+                 in_size->width == out_size->width;
+}
+
+static void mxc_isi_channel_set_crop(struct mxc_isi_pipe *pipe,
+                                    const struct v4l2_area *src,
+                                    const struct v4l2_rect *dst)
+{
+       u32 val, val0, val1;
+
+       val = mxc_isi_read(pipe, CHNL_IMG_CTRL);
+       val &= ~CHNL_IMG_CTRL_CROP_EN;
+
+       if (src->height == dst->height && src->width == dst->width) {
+               mxc_isi_write(pipe, CHNL_IMG_CTRL, val);
+               return;
+       }
+
+       val |= CHNL_IMG_CTRL_CROP_EN;
+       val0 = CHNL_CROP_ULC_X(dst->left) | CHNL_CROP_ULC_Y(dst->top);
+       val1 = CHNL_CROP_LRC_X(dst->width) | CHNL_CROP_LRC_Y(dst->height);
+
+       mxc_isi_write(pipe, CHNL_CROP_ULC, val0);
+       mxc_isi_write(pipe, CHNL_CROP_LRC, val1 + val0);
+       mxc_isi_write(pipe, CHNL_IMG_CTRL, val);
+}
+
+/*
+ * A2,A1,      B1, A3,     B3, B2,
+ * C2, C1,     D1, C3,     D3, D2
+ */
+static const u32 mxc_isi_yuv2rgb_coeffs[6] = {
+       /* YUV -> RGB */
+       0x0000012a, 0x012a0198, 0x0730079c,
+       0x0204012a, 0x01f00000, 0x01800180
+};
+
+static const u32 mxc_isi_rgb2yuv_coeffs[6] = {
+       /* RGB->YUV */
+       0x00810041, 0x07db0019, 0x007007b6,
+       0x07a20070, 0x001007ee, 0x00800080
+};
+
+static void mxc_isi_channel_set_csc(struct mxc_isi_pipe *pipe,
+                                   enum mxc_isi_encoding in_encoding,
+                                   enum mxc_isi_encoding out_encoding,
+                                   bool *bypass)
+{
+       static const char * const encodings[] = {
+               [MXC_ISI_ENC_RAW] = "RAW",
+               [MXC_ISI_ENC_RGB] = "RGB",
+               [MXC_ISI_ENC_YUV] = "YUV",
+       };
+       const u32 *coeffs;
+       bool cscen = true;
+       u32 val;
+
+       val = mxc_isi_read(pipe, CHNL_IMG_CTRL);
+       val &= ~(CHNL_IMG_CTRL_CSC_BYPASS | CHNL_IMG_CTRL_CSC_MODE_MASK);
+
+       if (in_encoding == MXC_ISI_ENC_YUV &&
+           out_encoding == MXC_ISI_ENC_RGB) {
+               /* YUV2RGB */
+               coeffs = mxc_isi_yuv2rgb_coeffs;
+               /* YCbCr enable???  */
+               val |= CHNL_IMG_CTRL_CSC_MODE(CHNL_IMG_CTRL_CSC_MODE_YCBCR2RGB);
+       } else if (in_encoding == MXC_ISI_ENC_RGB &&
+                  out_encoding == MXC_ISI_ENC_YUV) {
+               /* RGB2YUV */
+               coeffs = mxc_isi_rgb2yuv_coeffs;
+               val |= CHNL_IMG_CTRL_CSC_MODE(CHNL_IMG_CTRL_CSC_MODE_RGB2YCBCR);
+       } else {
+               /* Bypass CSC */
+               cscen = false;
+               val |= CHNL_IMG_CTRL_CSC_BYPASS;
+       }
+
+       dev_dbg(pipe->isi->dev, "CSC: %s -> %s\n",
+               encodings[in_encoding], encodings[out_encoding]);
+
+       if (cscen) {
+               mxc_isi_write(pipe, CHNL_CSC_COEFF0, coeffs[0]);
+               mxc_isi_write(pipe, CHNL_CSC_COEFF1, coeffs[1]);
+               mxc_isi_write(pipe, CHNL_CSC_COEFF2, coeffs[2]);
+               mxc_isi_write(pipe, CHNL_CSC_COEFF3, coeffs[3]);
+               mxc_isi_write(pipe, CHNL_CSC_COEFF4, coeffs[4]);
+               mxc_isi_write(pipe, CHNL_CSC_COEFF5, coeffs[5]);
+       }
+
+       mxc_isi_write(pipe, CHNL_IMG_CTRL, val);
+
+       *bypass = !cscen;
+}
+
+void mxc_isi_channel_set_alpha(struct mxc_isi_pipe *pipe, u8 alpha)
+{
+       u32 val;
+
+       val = mxc_isi_read(pipe, CHNL_IMG_CTRL);
+       val &= ~CHNL_IMG_CTRL_GBL_ALPHA_VAL_MASK;
+       val |= CHNL_IMG_CTRL_GBL_ALPHA_VAL(alpha) |
+              CHNL_IMG_CTRL_GBL_ALPHA_EN;
+       mxc_isi_write(pipe, CHNL_IMG_CTRL, val);
+}
+
+void mxc_isi_channel_set_flip(struct mxc_isi_pipe *pipe, bool hflip, bool vflip)
+{
+       u32 val;
+
+       val = mxc_isi_read(pipe, CHNL_IMG_CTRL);
+       val &= ~(CHNL_IMG_CTRL_VFLIP_EN | CHNL_IMG_CTRL_HFLIP_EN);
+
+       if (vflip)
+               val |= CHNL_IMG_CTRL_VFLIP_EN;
+       if (hflip)
+               val |= CHNL_IMG_CTRL_HFLIP_EN;
+
+       mxc_isi_write(pipe, CHNL_IMG_CTRL, val);
+}
+
+static void mxc_isi_channel_set_panic_threshold(struct mxc_isi_pipe *pipe)
+{
+       const struct mxc_isi_set_thd *set_thd = pipe->isi->pdata->set_thd;
+       u32 val;
+
+       val = mxc_isi_read(pipe, CHNL_OUT_BUF_CTRL);
+
+       val &= ~(set_thd->panic_set_thd_y.mask);
+       val |= set_thd->panic_set_thd_y.threshold << set_thd->panic_set_thd_y.offset;
+
+       val &= ~(set_thd->panic_set_thd_u.mask);
+       val |= set_thd->panic_set_thd_u.threshold << set_thd->panic_set_thd_u.offset;
+
+       val &= ~(set_thd->panic_set_thd_v.mask);
+       val |= set_thd->panic_set_thd_v.threshold << set_thd->panic_set_thd_v.offset;
+
+       mxc_isi_write(pipe, CHNL_OUT_BUF_CTRL, val);
+}
+
+static void mxc_isi_channel_set_control(struct mxc_isi_pipe *pipe,
+                                       enum mxc_isi_input_id input,
+                                       bool bypass)
+{
+       u32 val;
+
+       mutex_lock(&pipe->lock);
+
+       val = mxc_isi_read(pipe, CHNL_CTRL);
+       val &= ~(CHNL_CTRL_CHNL_BYPASS | CHNL_CTRL_CHAIN_BUF_MASK |
+                CHNL_CTRL_BLANK_PXL_MASK | CHNL_CTRL_SRC_TYPE_MASK |
+                CHNL_CTRL_MIPI_VC_ID_MASK | CHNL_CTRL_SRC_INPUT_MASK);
+
+       /*
+        * If no scaling or color space conversion is needed, bypass the
+        * channel.
+        */
+       if (bypass)
+               val |= CHNL_CTRL_CHNL_BYPASS;
+
+       /* Chain line buffers if needed. */
+       if (pipe->chained)
+               val |= CHNL_CTRL_CHAIN_BUF(CHNL_CTRL_CHAIN_BUF_2_CHAIN);
+
+       val |= CHNL_CTRL_BLANK_PXL(0xff);
+
+       /* Input source (including VC configuration for CSI-2) */
+       if (input == MXC_ISI_INPUT_MEM) {
+               /*
+                * The memory input is connected to the last port of the
+                * crossbar switch, after all pixel link inputs. The SRC_INPUT
+                * field controls the input selection and must be set
+                * accordingly, despite being documented as ignored when using
+                * the memory input in the i.MX8MP reference manual, and
+                * reserved in the i.MX8MN reference manual.
+                */
+               val |= CHNL_CTRL_SRC_TYPE(CHNL_CTRL_SRC_TYPE_MEMORY);
+               val |= CHNL_CTRL_SRC_INPUT(pipe->isi->pdata->num_ports);
+       } else {
+               val |= CHNL_CTRL_SRC_TYPE(CHNL_CTRL_SRC_TYPE_DEVICE);
+               val |= CHNL_CTRL_SRC_INPUT(input);
+               val |= CHNL_CTRL_MIPI_VC_ID(0); /* FIXME: For CSI-2 only */
+       }
+
+       mxc_isi_write(pipe, CHNL_CTRL, val);
+
+       mutex_unlock(&pipe->lock);
+}
+
+void mxc_isi_channel_config(struct mxc_isi_pipe *pipe,
+                           enum mxc_isi_input_id input,
+                           const struct v4l2_area *in_size,
+                           const struct v4l2_area *scale,
+                           const struct v4l2_rect *crop,
+                           enum mxc_isi_encoding in_encoding,
+                           enum mxc_isi_encoding out_encoding)
+{
+       bool csc_bypass;
+       bool scaler_bypass;
+
+       /* Input frame size */
+       mxc_isi_write(pipe, CHNL_IMG_CFG,
+                     CHNL_IMG_CFG_HEIGHT(in_size->height) |
+                     CHNL_IMG_CFG_WIDTH(in_size->width));
+
+       /* Scaling */
+       mxc_isi_channel_set_scaling(pipe, in_encoding, in_size, scale,
+                                   &scaler_bypass);
+       mxc_isi_channel_set_crop(pipe, scale, crop);
+
+       /* CSC */
+       mxc_isi_channel_set_csc(pipe, in_encoding, out_encoding, &csc_bypass);
+
+       /* Output buffer management */
+       mxc_isi_channel_set_panic_threshold(pipe);
+
+       /* Channel control */
+       mxc_isi_channel_set_control(pipe, input, csc_bypass && scaler_bypass);
+}
+
+void mxc_isi_channel_set_input_format(struct mxc_isi_pipe *pipe,
+                                     const struct mxc_isi_format_info *info,
+                                     const struct v4l2_pix_format_mplane *format)
+{
+       unsigned int bpl = format->plane_fmt[0].bytesperline;
+
+       mxc_isi_write(pipe, CHNL_MEM_RD_CTRL,
+                     CHNL_MEM_RD_CTRL_IMG_TYPE(info->isi_in_format));
+       mxc_isi_write(pipe, CHNL_IN_BUF_PITCH,
+                     CHNL_IN_BUF_PITCH_LINE_PITCH(bpl));
+}
+
+void mxc_isi_channel_set_output_format(struct mxc_isi_pipe *pipe,
+                                      const struct mxc_isi_format_info *info,
+                                      struct v4l2_pix_format_mplane *format)
+{
+       u32 val;
+
+       /* set outbuf format */
+       dev_dbg(pipe->isi->dev, "output format %p4cc", &format->pixelformat);
+
+       val = mxc_isi_read(pipe, CHNL_IMG_CTRL);
+       val &= ~CHNL_IMG_CTRL_FORMAT_MASK;
+       val |= CHNL_IMG_CTRL_FORMAT(info->isi_out_format);
+       mxc_isi_write(pipe, CHNL_IMG_CTRL, val);
+
+       /* line pitch */
+       mxc_isi_write(pipe, CHNL_OUT_BUF_PITCH,
+                     format->plane_fmt[0].bytesperline);
+}
+
+/* -----------------------------------------------------------------------------
+ * IRQ
+ */
+
+u32 mxc_isi_channel_irq_status(struct mxc_isi_pipe *pipe, bool clear)
+{
+       u32 status;
+
+       status = mxc_isi_read(pipe, CHNL_STS);
+       if (clear)
+               mxc_isi_write(pipe, CHNL_STS, status);
+
+       return status;
+}
+
+void mxc_isi_channel_irq_clear(struct mxc_isi_pipe *pipe)
+{
+       mxc_isi_write(pipe, CHNL_STS, 0xffffffff);
+}
+
+static void mxc_isi_channel_irq_enable(struct mxc_isi_pipe *pipe)
+{
+       const struct mxc_isi_ier_reg *ier_reg = pipe->isi->pdata->ier_reg;
+       u32 val;
+
+       val = CHNL_IER_FRM_RCVD_EN |
+               CHNL_IER_AXI_WR_ERR_U_EN |
+               CHNL_IER_AXI_WR_ERR_V_EN |
+               CHNL_IER_AXI_WR_ERR_Y_EN;
+
+       /* Y/U/V overflow enable */
+       val |= ier_reg->oflw_y_buf_en.mask |
+              ier_reg->oflw_u_buf_en.mask |
+              ier_reg->oflw_v_buf_en.mask;
+
+       /* Y/U/V excess overflow enable */
+       val |= ier_reg->excs_oflw_y_buf_en.mask |
+              ier_reg->excs_oflw_u_buf_en.mask |
+              ier_reg->excs_oflw_v_buf_en.mask;
+
+       /* Y/U/V panic enable */
+       val |= ier_reg->panic_y_buf_en.mask |
+              ier_reg->panic_u_buf_en.mask |
+              ier_reg->panic_v_buf_en.mask;
+
+       mxc_isi_channel_irq_clear(pipe);
+       mxc_isi_write(pipe, CHNL_IER, val);
+}
+
+static void mxc_isi_channel_irq_disable(struct mxc_isi_pipe *pipe)
+{
+       mxc_isi_write(pipe, CHNL_IER, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Init, deinit, enable, disable
+ */
+
+static void mxc_isi_channel_sw_reset(struct mxc_isi_pipe *pipe, bool enable_clk)
+{
+       mxc_isi_write(pipe, CHNL_CTRL, CHNL_CTRL_SW_RST);
+       mdelay(5);
+       mxc_isi_write(pipe, CHNL_CTRL, enable_clk ? CHNL_CTRL_CLK_EN : 0);
+}
+
+static void __mxc_isi_channel_get(struct mxc_isi_pipe *pipe)
+{
+       if (!pipe->use_count++)
+               mxc_isi_channel_sw_reset(pipe, true);
+}
+
+void mxc_isi_channel_get(struct mxc_isi_pipe *pipe)
+{
+       mutex_lock(&pipe->lock);
+       __mxc_isi_channel_get(pipe);
+       mutex_unlock(&pipe->lock);
+}
+
+static void __mxc_isi_channel_put(struct mxc_isi_pipe *pipe)
+{
+       if (!--pipe->use_count)
+               mxc_isi_channel_sw_reset(pipe, false);
+}
+
+void mxc_isi_channel_put(struct mxc_isi_pipe *pipe)
+{
+       mutex_lock(&pipe->lock);
+       __mxc_isi_channel_put(pipe);
+       mutex_unlock(&pipe->lock);
+}
+
+void mxc_isi_channel_enable(struct mxc_isi_pipe *pipe)
+{
+       u32 val;
+
+       mxc_isi_channel_irq_enable(pipe);
+
+       mutex_lock(&pipe->lock);
+
+       val = mxc_isi_read(pipe, CHNL_CTRL);
+       val |= CHNL_CTRL_CHNL_EN;
+       mxc_isi_write(pipe, CHNL_CTRL, val);
+
+       mutex_unlock(&pipe->lock);
+}
+
+void mxc_isi_channel_disable(struct mxc_isi_pipe *pipe)
+{
+       u32 val;
+
+       mxc_isi_channel_irq_disable(pipe);
+
+       mutex_lock(&pipe->lock);
+
+       val = mxc_isi_read(pipe, CHNL_CTRL);
+       val &= ~CHNL_CTRL_CHNL_EN;
+       mxc_isi_write(pipe, CHNL_CTRL, val);
+
+       mutex_unlock(&pipe->lock);
+}
+
+/* -----------------------------------------------------------------------------
+ * Resource management & chaining
+ */
+int mxc_isi_channel_acquire(struct mxc_isi_pipe *pipe,
+                           mxc_isi_pipe_irq_t irq_handler, bool bypass)
+{
+       u8 resources;
+       int ret = 0;
+
+       mutex_lock(&pipe->lock);
+
+       if (pipe->irq_handler) {
+               ret = -EBUSY;
+               goto unlock;
+       }
+
+       /*
+        * Make sure the resources we need are available. The output buffer is
+        * always needed to operate the channel, the line buffer is needed only
+        * when the channel isn't in bypass mode.
+        */
+       resources = MXC_ISI_CHANNEL_RES_OUTPUT_BUF
+                 | (!bypass ? MXC_ISI_CHANNEL_RES_LINE_BUF : 0);
+       if ((pipe->available_res & resources) != resources) {
+               ret = -EBUSY;
+               goto unlock;
+       }
+
+       /* Acquire the channel resources. */
+       pipe->acquired_res = resources;
+       pipe->available_res &= ~resources;
+       pipe->irq_handler = irq_handler;
+
+unlock:
+       mutex_unlock(&pipe->lock);
+
+       return ret;
+}
+
+void mxc_isi_channel_release(struct mxc_isi_pipe *pipe)
+{
+       mutex_lock(&pipe->lock);
+
+       pipe->irq_handler = NULL;
+       pipe->available_res |= pipe->acquired_res;
+       pipe->acquired_res = 0;
+
+       mutex_unlock(&pipe->lock);
+}
+
+/*
+ * We currently support line buffer chaining only, for handling images with a
+ * width larger than 2048 pixels.
+ *
+ * TODO: Support secondary line buffer for downscaling YUV420 images.
+ */
+int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe, bool bypass)
+{
+       /* Channel chaining requires both line and output buffer. */
+       const u8 resources = MXC_ISI_CHANNEL_RES_OUTPUT_BUF
+                          | MXC_ISI_CHANNEL_RES_LINE_BUF;
+       struct mxc_isi_pipe *chained_pipe = pipe + 1;
+       int ret = 0;
+
+       /*
+        * If buffer chaining is required, make sure this channel is not the
+        * last one, otherwise there's no 'next' channel to chain with. This
+        * should be prevented by checks in the set format handlers, but let's
+        * be defensive.
+        */
+       if (WARN_ON(pipe->id == pipe->isi->pdata->num_channels - 1))
+               return -EINVAL;
+
+       mutex_lock(&chained_pipe->lock);
+
+       /* Safety checks. */
+       if (WARN_ON(pipe->chained || chained_pipe->chained_res)) {
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       if ((chained_pipe->available_res & resources) != resources) {
+               ret = -EBUSY;
+               goto unlock;
+       }
+
+       pipe->chained = true;
+       chained_pipe->chained_res |= resources;
+       chained_pipe->available_res &= ~resources;
+
+       __mxc_isi_channel_get(chained_pipe);
+
+unlock:
+       mutex_unlock(&chained_pipe->lock);
+
+       return ret;
+}
+
+void mxc_isi_channel_unchain(struct mxc_isi_pipe *pipe)
+{
+       struct mxc_isi_pipe *chained_pipe = pipe + 1;
+
+       if (!pipe->chained)
+               return;
+
+       pipe->chained = false;
+
+       mutex_lock(&chained_pipe->lock);
+
+       chained_pipe->available_res |= chained_pipe->chained_res;
+       chained_pipe->chained_res = 0;
+
+       __mxc_isi_channel_put(chained_pipe);
+
+       mutex_unlock(&chained_pipe->lock);
+}
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
new file mode 100644 (file)
index 0000000..9745d62
--- /dev/null
@@ -0,0 +1,858 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ISI V4L2 memory to memory driver for i.MX8QXP/QM platform
+ *
+ * ISI is a Image Sensor Interface of i.MX8QXP/QM platform, which
+ * used to process image from camera sensor or memory to memory or DC
+ *
+ * Copyright (c) 2019 NXP Semiconductor
+ */
+
+#include <linux/container_of.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/limits.h>
+#include <linux/minmax.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "imx8-isi-core.h"
+
+struct mxc_isi_m2m_buffer {
+       struct v4l2_m2m_buffer buf;
+       dma_addr_t dma_addrs[3];
+};
+
+struct mxc_isi_m2m_ctx_queue_data {
+       struct v4l2_pix_format_mplane format;
+       const struct mxc_isi_format_info *info;
+       u32 sequence;
+};
+
+struct mxc_isi_m2m_ctx {
+       struct v4l2_fh fh;
+       struct mxc_isi_m2m *m2m;
+
+       /* Protects the m2m vb2 queues */
+       struct mutex vb2_lock;
+
+       struct {
+               struct mxc_isi_m2m_ctx_queue_data out;
+               struct mxc_isi_m2m_ctx_queue_data cap;
+       } queues;
+
+       struct {
+               struct v4l2_ctrl_handler handler;
+               unsigned int alpha;
+               bool hflip;
+               bool vflip;
+       } ctrls;
+
+       bool chained;
+};
+
+static inline struct mxc_isi_m2m_buffer *
+to_isi_m2m_buffer(struct vb2_v4l2_buffer *buf)
+{
+       return container_of(buf, struct mxc_isi_m2m_buffer, buf.vb);
+}
+
+static inline struct mxc_isi_m2m_ctx *to_isi_m2m_ctx(struct v4l2_fh *fh)
+{
+       return container_of(fh, struct mxc_isi_m2m_ctx, fh);
+}
+
+static inline struct mxc_isi_m2m_ctx_queue_data *
+mxc_isi_m2m_ctx_qdata(struct mxc_isi_m2m_ctx *ctx, enum v4l2_buf_type type)
+{
+       if (V4L2_TYPE_IS_OUTPUT(type))
+               return &ctx->queues.out;
+       else
+               return &ctx->queues.cap;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 M2M device operations
+ */
+
+static void mxc_isi_m2m_frame_write_done(struct mxc_isi_pipe *pipe, u32 status)
+{
+       struct mxc_isi_m2m *m2m = &pipe->isi->m2m;
+       struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf;
+       struct mxc_isi_m2m_ctx *ctx;
+
+       ctx = v4l2_m2m_get_curr_priv(m2m->m2m_dev);
+       if (!ctx) {
+               dev_err(m2m->isi->dev,
+                       "Instance released before the end of transaction\n");
+               return;
+       }
+
+       src_vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+       dst_vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+       v4l2_m2m_buf_copy_metadata(src_vbuf, dst_vbuf, false);
+
+       src_vbuf->sequence = ctx->queues.out.sequence++;
+       dst_vbuf->sequence = ctx->queues.cap.sequence++;
+
+       v4l2_m2m_buf_done(src_vbuf, VB2_BUF_STATE_DONE);
+       v4l2_m2m_buf_done(dst_vbuf, VB2_BUF_STATE_DONE);
+
+       v4l2_m2m_job_finish(m2m->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+static void mxc_isi_m2m_device_run(void *priv)
+{
+       struct mxc_isi_m2m_ctx *ctx = priv;
+       struct mxc_isi_m2m *m2m = ctx->m2m;
+       struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf;
+       struct mxc_isi_m2m_buffer *src_buf, *dst_buf;
+
+       mxc_isi_channel_disable(m2m->pipe);
+
+       mutex_lock(&m2m->lock);
+
+       /* If the context has changed, reconfigure the channel. */
+       if (m2m->last_ctx != ctx) {
+               const struct v4l2_area in_size = {
+                       .width = ctx->queues.out.format.width,
+                       .height = ctx->queues.out.format.height,
+               };
+               const struct v4l2_area scale = {
+                       .width = ctx->queues.cap.format.width,
+                       .height = ctx->queues.cap.format.height,
+               };
+               const struct v4l2_rect crop = {
+                       .width = ctx->queues.cap.format.width,
+                       .height = ctx->queues.cap.format.height,
+               };
+
+               mxc_isi_channel_config(m2m->pipe, MXC_ISI_INPUT_MEM,
+                                      &in_size, &scale, &crop,
+                                      ctx->queues.out.info->encoding,
+                                      ctx->queues.cap.info->encoding);
+               mxc_isi_channel_set_input_format(m2m->pipe,
+                                                ctx->queues.out.info,
+                                                &ctx->queues.out.format);
+               mxc_isi_channel_set_output_format(m2m->pipe,
+                                                 ctx->queues.cap.info,
+                                                 &ctx->queues.cap.format);
+
+               m2m->last_ctx = ctx;
+       }
+
+       mutex_unlock(&m2m->lock);
+
+       mutex_lock(ctx->ctrls.handler.lock);
+       mxc_isi_channel_set_alpha(m2m->pipe, ctx->ctrls.alpha);
+       mxc_isi_channel_set_flip(m2m->pipe, ctx->ctrls.hflip, ctx->ctrls.vflip);
+       mutex_unlock(ctx->ctrls.handler.lock);
+
+       src_vbuf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       dst_vbuf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+       src_buf = to_isi_m2m_buffer(src_vbuf);
+       dst_buf = to_isi_m2m_buffer(dst_vbuf);
+
+       mxc_isi_channel_set_inbuf(m2m->pipe, src_buf->dma_addrs[0]);
+       mxc_isi_channel_set_outbuf(m2m->pipe, dst_buf->dma_addrs, MXC_ISI_BUF1);
+       mxc_isi_channel_set_outbuf(m2m->pipe, dst_buf->dma_addrs, MXC_ISI_BUF2);
+
+       mxc_isi_channel_enable(m2m->pipe);
+
+       mxc_isi_channel_m2m_start(m2m->pipe);
+}
+
+static const struct v4l2_m2m_ops mxc_isi_m2m_ops = {
+       .device_run = mxc_isi_m2m_device_run,
+};
+
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
+ */
+
+static int mxc_isi_m2m_vb2_queue_setup(struct vb2_queue *q,
+                                      unsigned int *num_buffers,
+                                      unsigned int *num_planes,
+                                      unsigned int sizes[],
+                                      struct device *alloc_devs[])
+{
+       struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q);
+       const struct mxc_isi_m2m_ctx_queue_data *qdata =
+               mxc_isi_m2m_ctx_qdata(ctx, q->type);
+
+       return mxc_isi_video_queue_setup(&qdata->format, qdata->info,
+                                        num_buffers, num_planes, sizes);
+}
+
+static int mxc_isi_m2m_vb2_buffer_init(struct vb2_buffer *vb2)
+{
+       struct vb2_queue *vq = vb2->vb2_queue;
+       struct mxc_isi_m2m_buffer *buf = to_isi_m2m_buffer(to_vb2_v4l2_buffer(vb2));
+       struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(vb2->vb2_queue);
+       const struct mxc_isi_m2m_ctx_queue_data *qdata =
+               mxc_isi_m2m_ctx_qdata(ctx, vq->type);
+
+       mxc_isi_video_buffer_init(vb2, buf->dma_addrs, qdata->info,
+                                 &qdata->format);
+
+       return 0;
+}
+
+static int mxc_isi_m2m_vb2_buffer_prepare(struct vb2_buffer *vb2)
+{
+       struct vb2_queue *vq = vb2->vb2_queue;
+       struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(vq);
+       const struct mxc_isi_m2m_ctx_queue_data *qdata =
+               mxc_isi_m2m_ctx_qdata(ctx, vq->type);
+
+       return mxc_isi_video_buffer_prepare(ctx->m2m->isi, vb2, qdata->info,
+                                           &qdata->format);
+}
+
+static void mxc_isi_m2m_vb2_buffer_queue(struct vb2_buffer *vb2)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+       struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(vb2->vb2_queue);
+
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static int mxc_isi_m2m_vb2_start_streaming(struct vb2_queue *q,
+                                          unsigned int count)
+{
+       struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q);
+       struct mxc_isi_m2m_ctx_queue_data *qdata =
+               mxc_isi_m2m_ctx_qdata(ctx, q->type);
+
+       qdata->sequence = 0;
+
+       return 0;
+}
+
+static void mxc_isi_m2m_vb2_stop_streaming(struct vb2_queue *q)
+{
+       struct mxc_isi_m2m_ctx *ctx = vb2_get_drv_priv(q);
+       struct vb2_v4l2_buffer *vbuf;
+
+       for (;;) {
+               if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+                       vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+               else
+                       vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+               if (!vbuf)
+                       break;
+
+               v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+       }
+}
+
+static const struct vb2_ops mxc_isi_m2m_vb2_qops = {
+       .queue_setup            = mxc_isi_m2m_vb2_queue_setup,
+       .buf_init               = mxc_isi_m2m_vb2_buffer_init,
+       .buf_prepare            = mxc_isi_m2m_vb2_buffer_prepare,
+       .buf_queue              = mxc_isi_m2m_vb2_buffer_queue,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+       .start_streaming        = mxc_isi_m2m_vb2_start_streaming,
+       .stop_streaming         = mxc_isi_m2m_vb2_stop_streaming,
+};
+
+static int mxc_isi_m2m_queue_init(void *priv, struct vb2_queue *src_vq,
+                                 struct vb2_queue *dst_vq)
+{
+       struct mxc_isi_m2m_ctx *ctx = priv;
+       struct mxc_isi_m2m *m2m = ctx->m2m;
+       int ret;
+
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+       src_vq->drv_priv = ctx;
+       src_vq->buf_struct_size = sizeof(struct mxc_isi_m2m_buffer);
+       src_vq->ops = &mxc_isi_m2m_vb2_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->lock = &ctx->vb2_lock;
+       src_vq->dev = m2m->isi->dev;
+
+       ret = vb2_queue_init(src_vq);
+       if (ret)
+               return ret;
+
+       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+       dst_vq->drv_priv = ctx;
+       dst_vq->buf_struct_size = sizeof(struct mxc_isi_m2m_buffer);
+       dst_vq->ops = &mxc_isi_m2m_vb2_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+       dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       dst_vq->lock = &ctx->vb2_lock;
+       dst_vq->dev = m2m->isi->dev;
+
+       return vb2_queue_init(dst_vq);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static inline struct mxc_isi_m2m_ctx *
+ctrl_to_mxc_isi_m2m_ctx(struct v4l2_ctrl *ctrl)
+{
+       return container_of(ctrl->handler, struct mxc_isi_m2m_ctx, ctrls.handler);
+}
+
+static int mxc_isi_m2m_ctx_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct mxc_isi_m2m_ctx *ctx = ctrl_to_mxc_isi_m2m_ctx(ctrl);
+
+       switch (ctrl->id) {
+       case V4L2_CID_HFLIP:
+               ctx->ctrls.hflip = ctrl->val;
+               break;
+
+       case V4L2_CID_VFLIP:
+               ctx->ctrls.vflip = ctrl->val;
+               break;
+
+       case V4L2_CID_ALPHA_COMPONENT:
+               ctx->ctrls.alpha = ctrl->val;
+               break;
+       }
+
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops mxc_isi_m2m_ctx_ctrl_ops = {
+       .s_ctrl = mxc_isi_m2m_ctx_s_ctrl,
+};
+
+static int mxc_isi_m2m_ctx_ctrls_create(struct mxc_isi_m2m_ctx *ctx)
+{
+       struct v4l2_ctrl_handler *handler = &ctx->ctrls.handler;
+       int ret;
+
+       v4l2_ctrl_handler_init(handler, 3);
+
+       v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctx_ctrl_ops,
+                         V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
+       v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctx_ctrl_ops,
+                         V4L2_CID_HFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(handler, &mxc_isi_m2m_ctx_ctrl_ops,
+                         V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+       if (handler->error) {
+               ret = handler->error;
+               v4l2_ctrl_handler_free(handler);
+               return ret;
+       }
+
+       ctx->fh.ctrl_handler = handler;
+
+       return 0;
+}
+
+static void mxc_isi_m2m_ctx_ctrls_delete(struct mxc_isi_m2m_ctx *ctx)
+{
+       v4l2_ctrl_handler_free(&ctx->ctrls.handler);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 ioctls
+ */
+
+static int mxc_isi_m2m_querycap(struct file *file, void *fh,
+                               struct v4l2_capability *cap)
+{
+       strscpy(cap->driver, MXC_ISI_DRIVER_NAME, sizeof(cap->driver));
+       strscpy(cap->card, MXC_ISI_M2M, sizeof(cap->card));
+       cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+       return 0;
+}
+
+static int mxc_isi_m2m_enum_fmt_vid(struct file *file, void *fh,
+                                   struct v4l2_fmtdesc *f)
+{
+       const enum mxc_isi_video_type type =
+               f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
+               MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP;
+       const struct mxc_isi_format_info *info;
+
+       info = mxc_isi_format_enum(f->index, type);
+       if (!info)
+               return -EINVAL;
+
+       f->pixelformat = info->fourcc;
+       f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE | V4L2_FMT_FLAG_CSC_YCBCR_ENC
+                |  V4L2_FMT_FLAG_CSC_QUANTIZATION | V4L2_FMT_FLAG_CSC_XFER_FUNC;
+
+       return 0;
+}
+
+static const struct mxc_isi_format_info *
+__mxc_isi_m2m_try_fmt_vid(struct mxc_isi_m2m_ctx *ctx,
+                         struct v4l2_pix_format_mplane *pix,
+                         const enum mxc_isi_video_type type)
+{
+       if (type == MXC_ISI_VIDEO_M2M_CAP) {
+               /* Downscaling only  */
+               pix->width = min(pix->width, ctx->queues.out.format.width);
+               pix->height = min(pix->height, ctx->queues.out.format.height);
+       }
+
+       return mxc_isi_format_try(ctx->m2m->pipe, pix, type);
+}
+
+static int mxc_isi_m2m_try_fmt_vid(struct file *file, void *fh,
+                                  struct v4l2_format *f)
+{
+       const enum mxc_isi_video_type type =
+               f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
+               MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP;
+       struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh);
+
+       __mxc_isi_m2m_try_fmt_vid(ctx, &f->fmt.pix_mp, type);
+
+       return 0;
+}
+
+static int mxc_isi_m2m_g_fmt_vid(struct file *file, void *fh,
+                                struct v4l2_format *f)
+{
+       struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh);
+       const struct mxc_isi_m2m_ctx_queue_data *qdata =
+               mxc_isi_m2m_ctx_qdata(ctx, f->type);
+
+       f->fmt.pix_mp = qdata->format;
+
+       return 0;
+}
+
+static int mxc_isi_m2m_s_fmt_vid(struct file *file, void *fh,
+                                struct v4l2_format *f)
+{
+       const enum mxc_isi_video_type type =
+               f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
+               MXC_ISI_VIDEO_M2M_OUT : MXC_ISI_VIDEO_M2M_CAP;
+       struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh);
+       struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+       const struct mxc_isi_format_info *info;
+       struct vb2_queue *vq;
+
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       if (vb2_is_busy(vq))
+               return -EBUSY;
+
+       info = __mxc_isi_m2m_try_fmt_vid(ctx, pix, type);
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ctx->queues.out.format = *pix;
+               ctx->queues.out.info = info;
+       }
+
+       /*
+        * Always set the format on the capture side, due to either format
+        * propagation or direct setting.
+        */
+       ctx->queues.cap.format = *pix;
+       ctx->queues.cap.info = info;
+
+       return 0;
+}
+
+static int mxc_isi_m2m_streamon(struct file *file, void *fh,
+                               enum v4l2_buf_type type)
+{
+       struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh);
+       const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format;
+       const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format;
+       const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info;
+       const struct mxc_isi_format_info *out_info = ctx->queues.out.info;
+       struct mxc_isi_m2m *m2m = ctx->m2m;
+       bool bypass;
+
+       int ret;
+
+       mutex_lock(&m2m->lock);
+
+       if (m2m->usage_count == INT_MAX) {
+               ret = -EOVERFLOW;
+               goto unlock;
+       }
+
+       bypass = cap_pix->width == out_pix->width &&
+                cap_pix->height == out_pix->height &&
+                cap_info->encoding == out_info->encoding;
+
+       /*
+        * Acquire the pipe and initialize the channel with the first user of
+        * the M2M device.
+        */
+       if (m2m->usage_count == 0) {
+               ret = mxc_isi_channel_acquire(m2m->pipe,
+                                             &mxc_isi_m2m_frame_write_done,
+                                             bypass);
+               if (ret)
+                       goto unlock;
+
+               mxc_isi_channel_get(m2m->pipe);
+       }
+
+       m2m->usage_count++;
+
+       /*
+        * Allocate resources for the channel, counting how many users require
+        * buffer chaining.
+        */
+       if (!ctx->chained && out_pix->width > MXC_ISI_MAX_WIDTH_UNCHAINED) {
+               ret = mxc_isi_channel_chain(m2m->pipe, bypass);
+               if (ret)
+                       goto deinit;
+
+               m2m->chained_count++;
+               ctx->chained = true;
+       }
+
+       /*
+        * Drop the lock to start the stream, as the .device_run() operation
+        * needs to acquire it.
+        */
+       mutex_unlock(&m2m->lock);
+       ret = v4l2_m2m_ioctl_streamon(file, fh, type);
+       if (ret) {
+               /* Reacquire the lock for the cleanup path. */
+               mutex_lock(&m2m->lock);
+               goto unchain;
+       }
+
+       return 0;
+
+unchain:
+       if (ctx->chained && --m2m->chained_count == 0)
+               mxc_isi_channel_unchain(m2m->pipe);
+       ctx->chained = false;
+
+deinit:
+       if (--m2m->usage_count == 0) {
+               mxc_isi_channel_put(m2m->pipe);
+               mxc_isi_channel_release(m2m->pipe);
+       }
+
+unlock:
+       mutex_unlock(&m2m->lock);
+       return ret;
+}
+
+static int mxc_isi_m2m_streamoff(struct file *file, void *fh,
+                                enum v4l2_buf_type type)
+{
+       struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh);
+       struct mxc_isi_m2m *m2m = ctx->m2m;
+
+       v4l2_m2m_ioctl_streamoff(file, fh, type);
+
+       mutex_lock(&m2m->lock);
+
+       /*
+        * If the last context is this one, reset it to make sure the device
+        * will be reconfigured when streaming is restarted.
+        */
+       if (m2m->last_ctx == ctx)
+               m2m->last_ctx = NULL;
+
+       /* Free the channel resources if this is the last chained context. */
+       if (ctx->chained && --m2m->chained_count == 0)
+               mxc_isi_channel_unchain(m2m->pipe);
+       ctx->chained = false;
+
+       /* Turn off the light with the last user. */
+       if (--m2m->usage_count == 0) {
+               mxc_isi_channel_disable(m2m->pipe);
+               mxc_isi_channel_put(m2m->pipe);
+               mxc_isi_channel_release(m2m->pipe);
+       }
+
+       WARN_ON(m2m->usage_count < 0);
+
+       mutex_unlock(&m2m->lock);
+
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops mxc_isi_m2m_ioctl_ops = {
+       .vidioc_querycap                = mxc_isi_m2m_querycap,
+
+       .vidioc_enum_fmt_vid_cap        = mxc_isi_m2m_enum_fmt_vid,
+       .vidioc_enum_fmt_vid_out        = mxc_isi_m2m_enum_fmt_vid,
+       .vidioc_g_fmt_vid_cap_mplane    = mxc_isi_m2m_g_fmt_vid,
+       .vidioc_g_fmt_vid_out_mplane    = mxc_isi_m2m_g_fmt_vid,
+       .vidioc_s_fmt_vid_cap_mplane    = mxc_isi_m2m_s_fmt_vid,
+       .vidioc_s_fmt_vid_out_mplane    = mxc_isi_m2m_s_fmt_vid,
+       .vidioc_try_fmt_vid_cap_mplane  = mxc_isi_m2m_try_fmt_vid,
+       .vidioc_try_fmt_vid_out_mplane  = mxc_isi_m2m_try_fmt_vid,
+
+       .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_expbuf                  = v4l2_m2m_ioctl_expbuf,
+       .vidioc_prepare_buf             = v4l2_m2m_ioctl_prepare_buf,
+       .vidioc_create_bufs             = v4l2_m2m_ioctl_create_bufs,
+
+       .vidioc_streamon                = mxc_isi_m2m_streamon,
+       .vidioc_streamoff               = mxc_isi_m2m_streamoff,
+
+       .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
+};
+
+/* -----------------------------------------------------------------------------
+ * Video device file operations
+ */
+
+static void mxc_isi_m2m_init_format(struct mxc_isi_m2m_ctx *ctx,
+                                   struct mxc_isi_m2m_ctx_queue_data *qdata,
+                                   enum mxc_isi_video_type type)
+{
+       qdata->format.width = MXC_ISI_DEF_WIDTH;
+       qdata->format.height = MXC_ISI_DEF_HEIGHT;
+       qdata->format.pixelformat = MXC_ISI_DEF_PIXEL_FORMAT;
+
+       qdata->info = mxc_isi_format_try(ctx->m2m->pipe, &qdata->format, type);
+}
+
+static int mxc_isi_m2m_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct mxc_isi_m2m *m2m = video_drvdata(file);
+       struct mxc_isi_m2m_ctx *ctx;
+       int ret;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       ctx->m2m = m2m;
+       mutex_init(&ctx->vb2_lock);
+
+       v4l2_fh_init(&ctx->fh, vdev);
+       file->private_data = &ctx->fh;
+
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(m2m->m2m_dev, ctx,
+                                           &mxc_isi_m2m_queue_init);
+       if (IS_ERR(ctx->fh.m2m_ctx)) {
+               ret = PTR_ERR(ctx->fh.m2m_ctx);
+               ctx->fh.m2m_ctx = NULL;
+               goto err_fh;
+       }
+
+       mxc_isi_m2m_init_format(ctx, &ctx->queues.out, MXC_ISI_VIDEO_M2M_OUT);
+       mxc_isi_m2m_init_format(ctx, &ctx->queues.cap, MXC_ISI_VIDEO_M2M_CAP);
+
+       ret = mxc_isi_m2m_ctx_ctrls_create(ctx);
+       if (ret)
+               goto err_ctx;
+
+       ret = pm_runtime_resume_and_get(m2m->isi->dev);
+       if (ret)
+               goto err_ctrls;
+
+       v4l2_fh_add(&ctx->fh);
+
+       return 0;
+
+err_ctrls:
+       mxc_isi_m2m_ctx_ctrls_delete(ctx);
+err_ctx:
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+err_fh:
+       v4l2_fh_exit(&ctx->fh);
+       mutex_destroy(&ctx->vb2_lock);
+       kfree(ctx);
+       return ret;
+}
+
+static int mxc_isi_m2m_release(struct file *file)
+{
+       struct mxc_isi_m2m *m2m = video_drvdata(file);
+       struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(file->private_data);
+
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+       mxc_isi_m2m_ctx_ctrls_delete(ctx);
+
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+
+       mutex_destroy(&ctx->vb2_lock);
+       kfree(ctx);
+
+       pm_runtime_put(m2m->isi->dev);
+
+       return 0;
+}
+
+static const struct v4l2_file_operations mxc_isi_m2m_fops = {
+       .owner          = THIS_MODULE,
+       .open           = mxc_isi_m2m_open,
+       .release        = mxc_isi_m2m_release,
+       .poll           = v4l2_m2m_fop_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = v4l2_m2m_fop_mmap,
+};
+
+/* -----------------------------------------------------------------------------
+ * Registration
+ */
+
+int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev)
+{
+       struct mxc_isi_m2m *m2m = &isi->m2m;
+       struct video_device *vdev = &m2m->vdev;
+       struct media_link *link;
+       int ret;
+
+       m2m->isi = isi;
+       m2m->pipe = &isi->pipes[0];
+
+       mutex_init(&m2m->lock);
+
+       /* Initialize the video device and create controls. */
+       snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.m2m");
+
+       vdev->fops      = &mxc_isi_m2m_fops;
+       vdev->ioctl_ops = &mxc_isi_m2m_ioctl_ops;
+       vdev->v4l2_dev  = v4l2_dev;
+       vdev->minor     = -1;
+       vdev->release   = video_device_release_empty;
+       vdev->vfl_dir   = VFL_DIR_M2M;
+
+       vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
+       video_set_drvdata(vdev, m2m);
+
+       /* Create the M2M device. */
+       m2m->m2m_dev = v4l2_m2m_init(&mxc_isi_m2m_ops);
+       if (IS_ERR(m2m->m2m_dev)) {
+               dev_err(isi->dev, "failed to initialize m2m device\n");
+               ret = PTR_ERR(m2m->m2m_dev);
+               goto err_mutex;
+       }
+
+       /* Register the video device. */
+       ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+       if (ret < 0) {
+               dev_err(isi->dev, "failed to register m2m device\n");
+               goto err_m2m;
+       }
+
+       /*
+        * Populate the media graph. We can't use the mem2mem helper
+        * v4l2_m2m_register_media_controller() as the M2M interface needs to
+        * be connected to the existing entities in the graph, so we have to
+        * wire things up manually:
+        *
+        * - The entity in the video_device, which isn't touched by the V4L2
+        *   core for M2M devices, is used as the source I/O entity in the
+        *   graph, connected to the crossbar switch.
+        *
+        * - The video device at the end of the pipeline provides the sink
+        *   entity, and is already wired up in the graph.
+        *
+        * - A new interface is created, pointing at both entities. The sink
+        *   entity will thus have two interfaces pointing to it.
+        */
+       m2m->pad.flags = MEDIA_PAD_FL_SOURCE;
+       vdev->entity.name = "mxc_isi.output";
+       vdev->entity.function = MEDIA_ENT_F_IO_V4L;
+       ret = media_entity_pads_init(&vdev->entity, 1, &m2m->pad);
+       if (ret)
+               goto err_video;
+
+       ret = media_device_register_entity(v4l2_dev->mdev, &vdev->entity);
+       if (ret)
+               goto err_entity_cleanup;
+
+       ret = media_create_pad_link(&vdev->entity, 0,
+                                   &m2m->isi->crossbar.sd.entity,
+                                   m2m->isi->crossbar.num_sinks - 1,
+                                   MEDIA_LNK_FL_IMMUTABLE |
+                                   MEDIA_LNK_FL_ENABLED);
+       if (ret)
+               goto err_entity_unreg;
+
+       m2m->intf = media_devnode_create(v4l2_dev->mdev, MEDIA_INTF_T_V4L_VIDEO,
+                                        0, VIDEO_MAJOR, vdev->minor);
+       if (!m2m->intf) {
+               ret = -ENOMEM;
+               goto err_entity_unreg;
+       }
+
+       link = media_create_intf_link(&vdev->entity, &m2m->intf->intf,
+                                     MEDIA_LNK_FL_IMMUTABLE |
+                                     MEDIA_LNK_FL_ENABLED);
+       if (!link) {
+               ret = -ENOMEM;
+               goto err_devnode;
+       }
+
+       link = media_create_intf_link(&m2m->pipe->video.vdev.entity,
+                                     &m2m->intf->intf,
+                                     MEDIA_LNK_FL_IMMUTABLE |
+                                     MEDIA_LNK_FL_ENABLED);
+       if (!link) {
+               ret = -ENOMEM;
+               goto err_devnode;
+       }
+
+       return 0;
+
+err_devnode:
+       media_devnode_remove(m2m->intf);
+err_entity_unreg:
+       media_device_unregister_entity(&vdev->entity);
+err_entity_cleanup:
+       media_entity_cleanup(&vdev->entity);
+err_video:
+       video_unregister_device(vdev);
+err_m2m:
+       v4l2_m2m_release(m2m->m2m_dev);
+err_mutex:
+       mutex_destroy(&m2m->lock);
+       return ret;
+}
+
+int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi)
+{
+       struct mxc_isi_m2m *m2m = &isi->m2m;
+       struct video_device *vdev = &m2m->vdev;
+
+       video_unregister_device(vdev);
+
+       v4l2_m2m_release(m2m->m2m_dev);
+       media_devnode_remove(m2m->intf);
+       media_entity_cleanup(&vdev->entity);
+       mutex_destroy(&m2m->lock);
+
+       return 0;
+}
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
new file mode 100644 (file)
index 0000000..c4454aa
--- /dev/null
@@ -0,0 +1,867 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * V4L2 Capture ISI subdev driver for i.MX8QXP/QM platform
+ *
+ * ISI is a Image Sensor Interface of i.MX8QXP/QM platform, which
+ * used to process image from camera sensor to memory or DC
+ *
+ * Copyright (c) 2019 NXP Semiconductor
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/minmax.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-v4l2.h>
+
+#include "imx8-isi-core.h"
+#include "imx8-isi-regs.h"
+
+/*
+ * While the ISI receives data from the gasket on a 3x12-bit bus, the pipeline
+ * subdev conceptually includes the gasket in order to avoid exposing an extra
+ * subdev between the CSIS and the ISI. We thus need to expose media bus codes
+ * corresponding to the CSIS output, which is narrower.
+ */
+static const struct mxc_isi_bus_format_info mxc_isi_bus_formats[] = {
+       /* YUV formats */
+       {
+               .mbus_code      = MEDIA_BUS_FMT_UYVY8_1X16,
+               .output         = MEDIA_BUS_FMT_YUV8_1X24,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK),
+               .encoding       = MXC_ISI_ENC_YUV,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_YUV8_1X24,
+               .output         = MEDIA_BUS_FMT_YUV8_1X24,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_YUV,
+       },
+       /* RGB formats */
+       {
+               .mbus_code      = MEDIA_BUS_FMT_RGB565_1X16,
+               .output         = MEDIA_BUS_FMT_RGB888_1X24,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK),
+               .encoding       = MXC_ISI_ENC_RGB,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_RGB888_1X24,
+               .output         = MEDIA_BUS_FMT_RGB888_1X24,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RGB,
+       },
+       /* RAW formats */
+       {
+               .mbus_code      = MEDIA_BUS_FMT_Y8_1X8,
+               .output         = MEDIA_BUS_FMT_Y8_1X8,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_Y10_1X10,
+               .output         = MEDIA_BUS_FMT_Y10_1X10,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_Y12_1X12,
+               .output         = MEDIA_BUS_FMT_Y12_1X12,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_Y14_1X14,
+               .output         = MEDIA_BUS_FMT_Y14_1X14,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SBGGR8_1X8,
+               .output         = MEDIA_BUS_FMT_SBGGR8_1X8,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGBRG8_1X8,
+               .output         = MEDIA_BUS_FMT_SGBRG8_1X8,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGRBG8_1X8,
+               .output         = MEDIA_BUS_FMT_SGRBG8_1X8,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SRGGB8_1X8,
+               .output         = MEDIA_BUS_FMT_SRGGB8_1X8,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SBGGR10_1X10,
+               .output         = MEDIA_BUS_FMT_SBGGR10_1X10,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGBRG10_1X10,
+               .output         = MEDIA_BUS_FMT_SGBRG10_1X10,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGRBG10_1X10,
+               .output         = MEDIA_BUS_FMT_SGRBG10_1X10,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SRGGB10_1X10,
+               .output         = MEDIA_BUS_FMT_SRGGB10_1X10,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SBGGR12_1X12,
+               .output         = MEDIA_BUS_FMT_SBGGR12_1X12,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGBRG12_1X12,
+               .output         = MEDIA_BUS_FMT_SGBRG12_1X12,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGRBG12_1X12,
+               .output         = MEDIA_BUS_FMT_SGRBG12_1X12,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SRGGB12_1X12,
+               .output         = MEDIA_BUS_FMT_SRGGB12_1X12,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SBGGR14_1X14,
+               .output         = MEDIA_BUS_FMT_SBGGR14_1X14,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGBRG14_1X14,
+               .output         = MEDIA_BUS_FMT_SGBRG14_1X14,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGRBG14_1X14,
+               .output         = MEDIA_BUS_FMT_SGRBG14_1X14,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SRGGB14_1X14,
+               .output         = MEDIA_BUS_FMT_SRGGB14_1X14,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       },
+       /* JPEG */
+       {
+               .mbus_code      = MEDIA_BUS_FMT_JPEG_1X8,
+               .output         = MEDIA_BUS_FMT_JPEG_1X8,
+               .pads           = BIT(MXC_ISI_PIPE_PAD_SINK)
+                               | BIT(MXC_ISI_PIPE_PAD_SOURCE),
+               .encoding       = MXC_ISI_ENC_RAW,
+       }
+};
+
+const struct mxc_isi_bus_format_info *
+mxc_isi_bus_format_by_code(u32 code, unsigned int pad)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(mxc_isi_bus_formats); i++) {
+               const struct mxc_isi_bus_format_info *info =
+                       &mxc_isi_bus_formats[i];
+
+               if (info->mbus_code == code && info->pads & BIT(pad))
+                       return info;
+       }
+
+       return NULL;
+}
+
+const struct mxc_isi_bus_format_info *
+mxc_isi_bus_format_by_index(unsigned int index, unsigned int pad)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(mxc_isi_bus_formats); i++) {
+               const struct mxc_isi_bus_format_info *info =
+                       &mxc_isi_bus_formats[i];
+
+               if (!(info->pads & BIT(pad)))
+                       continue;
+
+               if (!index)
+                       return info;
+
+               index--;
+       }
+
+       return NULL;
+}
+
+static inline struct mxc_isi_pipe *to_isi_pipe(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct mxc_isi_pipe, sd);
+}
+
+int mxc_isi_pipe_enable(struct mxc_isi_pipe *pipe)
+{
+       struct mxc_isi_crossbar *xbar = &pipe->isi->crossbar;
+       const struct mxc_isi_bus_format_info *sink_info;
+       const struct mxc_isi_bus_format_info *src_info;
+       const struct v4l2_mbus_framefmt *sink_fmt;
+       const struct v4l2_mbus_framefmt *src_fmt;
+       const struct v4l2_rect *compose;
+       struct v4l2_subdev_state *state;
+       struct v4l2_subdev *sd = &pipe->sd;
+       struct v4l2_area in_size, scale;
+       struct v4l2_rect crop;
+       u32 input;
+       int ret;
+
+       /*
+        * Find the connected input by inspecting the crossbar switch routing
+        * table.
+        */
+       state = v4l2_subdev_lock_and_get_active_state(&xbar->sd);
+       ret = v4l2_subdev_routing_find_opposite_end(&state->routing,
+                                                   xbar->num_sinks + pipe->id,
+                                                   0, &input, NULL);
+       v4l2_subdev_unlock_state(state);
+
+       if (ret)
+               return -EPIPE;
+
+       /* Configure the pipeline. */
+       state = v4l2_subdev_lock_and_get_active_state(sd);
+
+       sink_fmt = v4l2_subdev_get_try_format(sd, state, MXC_ISI_PIPE_PAD_SINK);
+       src_fmt = v4l2_subdev_get_try_format(sd, state, MXC_ISI_PIPE_PAD_SOURCE);
+       compose = v4l2_subdev_get_try_compose(sd, state, MXC_ISI_PIPE_PAD_SINK);
+       crop = *v4l2_subdev_get_try_crop(sd, state, MXC_ISI_PIPE_PAD_SOURCE);
+
+       sink_info = mxc_isi_bus_format_by_code(sink_fmt->code,
+                                              MXC_ISI_PIPE_PAD_SINK);
+       src_info = mxc_isi_bus_format_by_code(src_fmt->code,
+                                             MXC_ISI_PIPE_PAD_SOURCE);
+
+       in_size.width = sink_fmt->width;
+       in_size.height = sink_fmt->height;
+       scale.width = compose->width;
+       scale.height = compose->height;
+
+       v4l2_subdev_unlock_state(state);
+
+       /* Configure the ISI channel. */
+       mxc_isi_channel_config(pipe, input, &in_size, &scale, &crop,
+                              sink_info->encoding, src_info->encoding);
+
+       mxc_isi_channel_enable(pipe);
+
+       /* Enable streams on the crossbar switch. */
+       ret = v4l2_subdev_enable_streams(&xbar->sd, xbar->num_sinks + pipe->id,
+                                        BIT(0));
+       if (ret) {
+               mxc_isi_channel_disable(pipe);
+               dev_err(pipe->isi->dev, "Failed to enable pipe %u\n",
+                       pipe->id);
+               return ret;
+       }
+
+       return 0;
+}
+
+void mxc_isi_pipe_disable(struct mxc_isi_pipe *pipe)
+{
+       struct mxc_isi_crossbar *xbar = &pipe->isi->crossbar;
+       int ret;
+
+       ret = v4l2_subdev_disable_streams(&xbar->sd, xbar->num_sinks + pipe->id,
+                                         BIT(0));
+       if (ret)
+               dev_err(pipe->isi->dev, "Failed to disable pipe %u\n",
+                       pipe->id);
+
+       mxc_isi_channel_disable(pipe);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static struct v4l2_mbus_framefmt *
+mxc_isi_pipe_get_pad_format(struct mxc_isi_pipe *pipe,
+                           struct v4l2_subdev_state *state,
+                           unsigned int pad)
+{
+       return v4l2_subdev_get_try_format(&pipe->sd, state, pad);
+}
+
+static struct v4l2_rect *
+mxc_isi_pipe_get_pad_crop(struct mxc_isi_pipe *pipe,
+                         struct v4l2_subdev_state *state,
+                         unsigned int pad)
+{
+       return v4l2_subdev_get_try_crop(&pipe->sd, state, pad);
+}
+
+static struct v4l2_rect *
+mxc_isi_pipe_get_pad_compose(struct mxc_isi_pipe *pipe,
+                            struct v4l2_subdev_state *state,
+                            unsigned int pad)
+{
+       return v4l2_subdev_get_try_compose(&pipe->sd, state, pad);
+}
+
+static int mxc_isi_pipe_init_cfg(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_state *state)
+{
+       struct mxc_isi_pipe *pipe = to_isi_pipe(sd);
+       struct v4l2_mbus_framefmt *fmt_source;
+       struct v4l2_mbus_framefmt *fmt_sink;
+       struct v4l2_rect *compose;
+       struct v4l2_rect *crop;
+
+       fmt_sink = mxc_isi_pipe_get_pad_format(pipe, state,
+                                              MXC_ISI_PIPE_PAD_SINK);
+       fmt_source = mxc_isi_pipe_get_pad_format(pipe, state,
+                                                MXC_ISI_PIPE_PAD_SOURCE);
+
+       fmt_sink->width = MXC_ISI_DEF_WIDTH;
+       fmt_sink->height = MXC_ISI_DEF_HEIGHT;
+       fmt_sink->code = MXC_ISI_DEF_MBUS_CODE_SINK;
+       fmt_sink->field = V4L2_FIELD_NONE;
+       fmt_sink->colorspace = V4L2_COLORSPACE_JPEG;
+       fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
+       fmt_sink->quantization =
+               V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
+                                             fmt_sink->ycbcr_enc);
+       fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
+
+       *fmt_source = *fmt_sink;
+       fmt_source->code = MXC_ISI_DEF_MBUS_CODE_SOURCE;
+
+       compose = mxc_isi_pipe_get_pad_compose(pipe, state,
+                                              MXC_ISI_PIPE_PAD_SINK);
+       crop = mxc_isi_pipe_get_pad_crop(pipe, state, MXC_ISI_PIPE_PAD_SOURCE);
+
+       compose->left = 0;
+       compose->top = 0;
+       compose->width = MXC_ISI_DEF_WIDTH;
+       compose->height = MXC_ISI_DEF_HEIGHT;
+
+       *crop = *compose;
+
+       return 0;
+}
+
+static int mxc_isi_pipe_enum_mbus_code(struct v4l2_subdev *sd,
+                                      struct v4l2_subdev_state *state,
+                                      struct v4l2_subdev_mbus_code_enum *code)
+{
+       static const u32 output_codes[] = {
+               MEDIA_BUS_FMT_YUV8_1X24,
+               MEDIA_BUS_FMT_RGB888_1X24,
+       };
+       struct mxc_isi_pipe *pipe = to_isi_pipe(sd);
+       const struct mxc_isi_bus_format_info *info;
+       unsigned int index;
+       unsigned int i;
+
+       if (code->pad == MXC_ISI_PIPE_PAD_SOURCE) {
+               const struct v4l2_mbus_framefmt *format;
+
+               format = mxc_isi_pipe_get_pad_format(pipe, state,
+                                                    MXC_ISI_PIPE_PAD_SINK);
+               info = mxc_isi_bus_format_by_code(format->code,
+                                                 MXC_ISI_PIPE_PAD_SINK);
+
+               if (info->encoding == MXC_ISI_ENC_RAW) {
+                       /*
+                        * For RAW formats, the sink and source media bus codes
+                        * must match.
+                        */
+                       if (code->index)
+                               return -EINVAL;
+
+                       code->code = info->output;
+               } else {
+                       /*
+                        * For RGB or YUV formats, the ISI supports format
+                        * conversion. Either of the two output formats can be
+                        * used regardless of the input.
+                        */
+                       if (code->index > 1)
+                               return -EINVAL;
+
+                       code->code = output_codes[code->index];
+               }
+
+               return 0;
+       }
+
+       index = code->index;
+
+       for (i = 0; i < ARRAY_SIZE(mxc_isi_bus_formats); ++i) {
+               info = &mxc_isi_bus_formats[i];
+
+               if (!(info->pads & BIT(MXC_ISI_PIPE_PAD_SINK)))
+                       continue;
+
+               if (index == 0) {
+                       code->code = info->mbus_code;
+                       return 0;
+               }
+
+               index--;
+       }
+
+       return -EINVAL;
+}
+
+static int mxc_isi_pipe_set_fmt(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_state *state,
+                               struct v4l2_subdev_format *fmt)
+{
+       struct mxc_isi_pipe *pipe = to_isi_pipe(sd);
+       struct v4l2_mbus_framefmt *mf = &fmt->format;
+       const struct mxc_isi_bus_format_info *info;
+       struct v4l2_mbus_framefmt *format;
+       struct v4l2_rect *rect;
+
+       if (vb2_is_busy(&pipe->video.vb2_q))
+               return -EBUSY;
+
+       if (fmt->pad == MXC_ISI_PIPE_PAD_SINK) {
+               unsigned int max_width;
+
+               info = mxc_isi_bus_format_by_code(mf->code,
+                                                 MXC_ISI_PIPE_PAD_SINK);
+               if (!info)
+                       info = mxc_isi_bus_format_by_code(MXC_ISI_DEF_MBUS_CODE_SINK,
+                                                         MXC_ISI_PIPE_PAD_SINK);
+
+               /*
+                * Limit the max line length if there's no adjacent pipe to
+                * chain with.
+                */
+               max_width = pipe->id == pipe->isi->pdata->num_channels - 1
+                         ? MXC_ISI_MAX_WIDTH_UNCHAINED
+                         : MXC_ISI_MAX_WIDTH_CHAINED;
+
+               mf->code = info->mbus_code;
+               mf->width = clamp(mf->width, MXC_ISI_MIN_WIDTH, max_width);
+               mf->height = clamp(mf->height, MXC_ISI_MIN_HEIGHT,
+                                  MXC_ISI_MAX_HEIGHT);
+
+               /* Propagate the format to the source pad. */
+               rect = mxc_isi_pipe_get_pad_compose(pipe, state,
+                                                   MXC_ISI_PIPE_PAD_SINK);
+               rect->width = mf->width;
+               rect->height = mf->height;
+
+               rect = mxc_isi_pipe_get_pad_crop(pipe, state,
+                                                MXC_ISI_PIPE_PAD_SOURCE);
+               rect->left = 0;
+               rect->top = 0;
+               rect->width = mf->width;
+               rect->height = mf->height;
+
+               format = mxc_isi_pipe_get_pad_format(pipe, state,
+                                                    MXC_ISI_PIPE_PAD_SOURCE);
+               format->code = info->output;
+               format->width = mf->width;
+               format->height = mf->height;
+       } else {
+               /*
+                * For RGB or YUV formats, the ISI supports RGB <-> YUV format
+                * conversion. For RAW formats, the sink and source media bus
+                * codes must match.
+                */
+               format = mxc_isi_pipe_get_pad_format(pipe, state,
+                                                    MXC_ISI_PIPE_PAD_SINK);
+               info = mxc_isi_bus_format_by_code(format->code,
+                                                 MXC_ISI_PIPE_PAD_SINK);
+
+               if (info->encoding != MXC_ISI_ENC_RAW) {
+                       if (mf->code != MEDIA_BUS_FMT_YUV8_1X24 &&
+                           mf->code != MEDIA_BUS_FMT_RGB888_1X24)
+                               mf->code = info->output;
+
+                       info = mxc_isi_bus_format_by_code(mf->code,
+                                                         MXC_ISI_PIPE_PAD_SOURCE);
+               }
+
+               mf->code = info->output;
+
+               /*
+                * The width and height on the source can't be changed, they
+                * must match the crop rectangle size.
+                */
+               rect = mxc_isi_pipe_get_pad_crop(pipe, state,
+                                                MXC_ISI_PIPE_PAD_SOURCE);
+
+               mf->width = rect->width;
+               mf->height = rect->height;
+       }
+
+       format = mxc_isi_pipe_get_pad_format(pipe, state, fmt->pad);
+       *format = *mf;
+
+       dev_dbg(pipe->isi->dev, "pad%u: code: 0x%04x, %ux%u",
+               fmt->pad, mf->code, mf->width, mf->height);
+
+       return 0;
+}
+
+static int mxc_isi_pipe_get_selection(struct v4l2_subdev *sd,
+                                     struct v4l2_subdev_state *state,
+                                     struct v4l2_subdev_selection *sel)
+{
+       struct mxc_isi_pipe *pipe = to_isi_pipe(sd);
+       const struct v4l2_mbus_framefmt *format;
+       const struct v4l2_rect *rect;
+
+       switch (sel->target) {
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+               if (sel->pad != MXC_ISI_PIPE_PAD_SINK)
+                       /* No compose rectangle on source pad. */
+                       return -EINVAL;
+
+               /* The sink compose is bound by the sink format. */
+               format = mxc_isi_pipe_get_pad_format(pipe, state,
+                                                    MXC_ISI_PIPE_PAD_SINK);
+               sel->r.left = 0;
+               sel->r.top = 0;
+               sel->r.width = format->width;
+               sel->r.height = format->height;
+               break;
+
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               if (sel->pad != MXC_ISI_PIPE_PAD_SOURCE)
+                       /* No crop rectangle on sink pad. */
+                       return -EINVAL;
+
+               /* The source crop is bound by the sink compose. */
+               rect = mxc_isi_pipe_get_pad_compose(pipe, state,
+                                                   MXC_ISI_PIPE_PAD_SINK);
+               sel->r = *rect;
+               break;
+
+       case V4L2_SEL_TGT_CROP:
+               if (sel->pad != MXC_ISI_PIPE_PAD_SOURCE)
+                       /* No crop rectangle on sink pad. */
+                       return -EINVAL;
+
+               rect = mxc_isi_pipe_get_pad_crop(pipe, state, sel->pad);
+               sel->r = *rect;
+               break;
+
+       case V4L2_SEL_TGT_COMPOSE:
+               if (sel->pad != MXC_ISI_PIPE_PAD_SINK)
+                       /* No compose rectangle on source pad. */
+                       return -EINVAL;
+
+               rect = mxc_isi_pipe_get_pad_compose(pipe, state, sel->pad);
+               sel->r = *rect;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mxc_isi_pipe_set_selection(struct v4l2_subdev *sd,
+                                     struct v4l2_subdev_state *state,
+                                     struct v4l2_subdev_selection *sel)
+{
+       struct mxc_isi_pipe *pipe = to_isi_pipe(sd);
+       struct v4l2_mbus_framefmt *format;
+       struct v4l2_rect *rect;
+
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP:
+               if (sel->pad != MXC_ISI_PIPE_PAD_SOURCE)
+                       /* The pipeline support cropping on the source only. */
+                       return -EINVAL;
+
+               /* The source crop is bound by the sink compose. */
+               rect = mxc_isi_pipe_get_pad_compose(pipe, state,
+                                                   MXC_ISI_PIPE_PAD_SINK);
+               sel->r.left = clamp_t(s32, sel->r.left, 0, rect->width - 1);
+               sel->r.top = clamp_t(s32, sel->r.top, 0, rect->height - 1);
+               sel->r.width = clamp(sel->r.width, MXC_ISI_MIN_WIDTH,
+                                    rect->width - sel->r.left);
+               sel->r.height = clamp(sel->r.height, MXC_ISI_MIN_HEIGHT,
+                                     rect->height - sel->r.top);
+
+               rect = mxc_isi_pipe_get_pad_crop(pipe, state,
+                                                MXC_ISI_PIPE_PAD_SOURCE);
+               *rect = sel->r;
+
+               /* Propagate the crop rectangle to the source pad. */
+               format = mxc_isi_pipe_get_pad_format(pipe, state,
+                                                    MXC_ISI_PIPE_PAD_SOURCE);
+               format->width = sel->r.width;
+               format->height = sel->r.height;
+               break;
+
+       case V4L2_SEL_TGT_COMPOSE:
+               if (sel->pad != MXC_ISI_PIPE_PAD_SINK)
+                       /* Composing is supported on the sink only. */
+                       return -EINVAL;
+
+               /* The sink crop is bound by the sink format downscaling only). */
+               format = mxc_isi_pipe_get_pad_format(pipe, state,
+                                                    MXC_ISI_PIPE_PAD_SINK);
+
+               sel->r.left = 0;
+               sel->r.top = 0;
+               sel->r.width = clamp(sel->r.width, MXC_ISI_MIN_WIDTH,
+                                    format->width);
+               sel->r.height = clamp(sel->r.height, MXC_ISI_MIN_HEIGHT,
+                                     format->height);
+
+               rect = mxc_isi_pipe_get_pad_compose(pipe, state,
+                                                   MXC_ISI_PIPE_PAD_SINK);
+               *rect = sel->r;
+
+               /* Propagate the compose rectangle to the source pad. */
+               rect = mxc_isi_pipe_get_pad_crop(pipe, state,
+                                                MXC_ISI_PIPE_PAD_SOURCE);
+               rect->left = 0;
+               rect->top = 0;
+               rect->width = sel->r.width;
+               rect->height = sel->r.height;
+
+               format = mxc_isi_pipe_get_pad_format(pipe, state,
+                                                    MXC_ISI_PIPE_PAD_SOURCE);
+               format->width = sel->r.width;
+               format->height = sel->r.height;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       dev_dbg(pipe->isi->dev, "%s, target %#x: (%d,%d)/%dx%d", __func__,
+               sel->target, sel->r.left, sel->r.top, sel->r.width,
+               sel->r.height);
+
+       return 0;
+}
+
+static const struct v4l2_subdev_pad_ops mxc_isi_pipe_subdev_pad_ops = {
+       .init_cfg = mxc_isi_pipe_init_cfg,
+       .enum_mbus_code = mxc_isi_pipe_enum_mbus_code,
+       .get_fmt = v4l2_subdev_get_fmt,
+       .set_fmt = mxc_isi_pipe_set_fmt,
+       .get_selection = mxc_isi_pipe_get_selection,
+       .set_selection = mxc_isi_pipe_set_selection,
+};
+
+static const struct v4l2_subdev_ops mxc_isi_pipe_subdev_ops = {
+       .pad = &mxc_isi_pipe_subdev_pad_ops,
+};
+
+/* -----------------------------------------------------------------------------
+ * IRQ handling
+ */
+
+static irqreturn_t mxc_isi_pipe_irq_handler(int irq, void *priv)
+{
+       struct mxc_isi_pipe *pipe = priv;
+       const struct mxc_isi_ier_reg *ier_reg = pipe->isi->pdata->ier_reg;
+       u32 status;
+
+       status = mxc_isi_channel_irq_status(pipe, true);
+
+       if (status & CHNL_STS_FRM_STRD) {
+               if (!WARN_ON(!pipe->irq_handler))
+                       pipe->irq_handler(pipe, status);
+       }
+
+       if (status & (CHNL_STS_AXI_WR_ERR_Y |
+                     CHNL_STS_AXI_WR_ERR_U |
+                     CHNL_STS_AXI_WR_ERR_V))
+               dev_dbg(pipe->isi->dev, "%s: IRQ AXI Error stat=0x%X\n",
+                       __func__, status);
+
+       if (status & (ier_reg->panic_y_buf_en.mask |
+                     ier_reg->panic_u_buf_en.mask |
+                     ier_reg->panic_v_buf_en.mask))
+               dev_dbg(pipe->isi->dev, "%s: IRQ Panic OFLW Error stat=0x%X\n",
+                       __func__, status);
+
+       if (status & (ier_reg->oflw_y_buf_en.mask |
+                     ier_reg->oflw_u_buf_en.mask |
+                     ier_reg->oflw_v_buf_en.mask))
+               dev_dbg(pipe->isi->dev, "%s: IRQ OFLW Error stat=0x%X\n",
+                       __func__, status);
+
+       if (status & (ier_reg->excs_oflw_y_buf_en.mask |
+                     ier_reg->excs_oflw_u_buf_en.mask |
+                     ier_reg->excs_oflw_v_buf_en.mask))
+               dev_dbg(pipe->isi->dev, "%s: IRQ EXCS OFLW Error stat=0x%X\n",
+                       __func__, status);
+
+       return IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * Init & cleanup
+ */
+
+static const struct media_entity_operations mxc_isi_pipe_entity_ops = {
+       .link_validate  = v4l2_subdev_link_validate,
+};
+
+int mxc_isi_pipe_init(struct mxc_isi_dev *isi, unsigned int id)
+{
+       struct mxc_isi_pipe *pipe = &isi->pipes[id];
+       struct v4l2_subdev *sd;
+       int irq;
+       int ret;
+
+       pipe->id = id;
+       pipe->isi = isi;
+       pipe->regs = isi->regs + id * isi->pdata->reg_offset;
+
+       mutex_init(&pipe->lock);
+
+       pipe->available_res = MXC_ISI_CHANNEL_RES_LINE_BUF
+                           | MXC_ISI_CHANNEL_RES_OUTPUT_BUF;
+       pipe->acquired_res = 0;
+       pipe->chained_res = 0;
+       pipe->chained = false;
+
+       sd = &pipe->sd;
+       v4l2_subdev_init(sd, &mxc_isi_pipe_subdev_ops);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       snprintf(sd->name, sizeof(sd->name), "mxc_isi.%d", pipe->id);
+       sd->dev = isi->dev;
+
+       sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
+       sd->entity.ops = &mxc_isi_pipe_entity_ops;
+
+       pipe->pads[MXC_ISI_PIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pipe->pads[MXC_ISI_PIPE_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+       ret = media_entity_pads_init(&sd->entity, MXC_ISI_PIPE_PADS_NUM,
+                                    pipe->pads);
+       if (ret)
+               goto error;
+
+       ret = v4l2_subdev_init_finalize(sd);
+       if (ret < 0)
+               goto error;
+
+       /* Register IRQ handler. */
+       mxc_isi_channel_irq_clear(pipe);
+
+       irq = platform_get_irq(to_platform_device(isi->dev), id);
+       if (irq < 0) {
+               dev_err(pipe->isi->dev, "Failed to get IRQ (%d)\n", irq);
+               ret = irq;
+               goto error;
+       }
+
+       ret = devm_request_irq(isi->dev, irq, mxc_isi_pipe_irq_handler,
+                              0, dev_name(isi->dev), pipe);
+       if (ret < 0) {
+               dev_err(isi->dev, "failed to request IRQ (%d)\n", ret);
+               goto error;
+       }
+
+       return 0;
+
+error:
+       media_entity_cleanup(&sd->entity);
+       mutex_destroy(&pipe->lock);
+
+       return ret;
+}
+
+void mxc_isi_pipe_cleanup(struct mxc_isi_pipe *pipe)
+{
+       struct v4l2_subdev *sd = &pipe->sd;
+
+       media_entity_cleanup(&sd->entity);
+       mutex_destroy(&pipe->lock);
+}
+
+int mxc_isi_pipe_acquire(struct mxc_isi_pipe *pipe,
+                        mxc_isi_pipe_irq_t irq_handler)
+{
+       const struct mxc_isi_bus_format_info *sink_info;
+       const struct mxc_isi_bus_format_info *src_info;
+       struct v4l2_mbus_framefmt *sink_fmt;
+       const struct v4l2_mbus_framefmt *src_fmt;
+       struct v4l2_subdev *sd = &pipe->sd;
+       struct v4l2_subdev_state *state;
+       bool bypass;
+       int ret;
+
+       state = v4l2_subdev_lock_and_get_active_state(sd);
+       sink_fmt = v4l2_subdev_get_try_format(sd, state, MXC_ISI_PIPE_PAD_SINK);
+       src_fmt = v4l2_subdev_get_try_format(sd, state, MXC_ISI_PIPE_PAD_SOURCE);
+       v4l2_subdev_unlock_state(state);
+
+       sink_info = mxc_isi_bus_format_by_code(sink_fmt->code,
+                                              MXC_ISI_PIPE_PAD_SINK);
+       src_info = mxc_isi_bus_format_by_code(src_fmt->code,
+                                             MXC_ISI_PIPE_PAD_SOURCE);
+
+       bypass = sink_fmt->width == src_fmt->width &&
+                sink_fmt->height == src_fmt->height &&
+                sink_info->encoding == src_info->encoding;
+
+       ret = mxc_isi_channel_acquire(pipe, irq_handler, bypass);
+       if (ret)
+               return ret;
+
+       /* Chain the channel if needed for wide resolutions. */
+       if (sink_fmt->width > MXC_ISI_MAX_WIDTH_UNCHAINED) {
+               ret = mxc_isi_channel_chain(pipe, bypass);
+               if (ret)
+                       mxc_isi_channel_release(pipe);
+       }
+
+       return ret;
+}
+
+void mxc_isi_pipe_release(struct mxc_isi_pipe *pipe)
+{
+       mxc_isi_channel_release(pipe);
+       mxc_isi_channel_unchain(pipe);
+}
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-regs.h b/drivers/media/platform/nxp/imx8-isi/imx8-isi-regs.h
new file mode 100644 (file)
index 0000000..1b65ecc
--- /dev/null
@@ -0,0 +1,418 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019-2020 NXP
+ */
+
+#ifndef __IMX8_ISI_REGS_H__
+#define __IMX8_ISI_REGS_H__
+
+#include <linux/bits.h>
+
+/* ISI Registers Define  */
+/* Channel Control Register */
+#define CHNL_CTRL                                              0x0000
+#define CHNL_CTRL_CHNL_EN                                      BIT(31)
+#define CHNL_CTRL_CLK_EN                                       BIT(30)
+#define CHNL_CTRL_CHNL_BYPASS                                  BIT(29)
+#define CHNL_CTRL_CHAIN_BUF(n)                                 ((n) << 25)
+#define CHNL_CTRL_CHAIN_BUF_MASK                               GENMASK(26, 25)
+#define CHNL_CTRL_CHAIN_BUF_NO_CHAIN                           0
+#define CHNL_CTRL_CHAIN_BUF_2_CHAIN                            1
+#define CHNL_CTRL_SW_RST                                       BIT(24)
+#define CHNL_CTRL_BLANK_PXL(n)                                 ((n) << 16)
+#define CHNL_CTRL_BLANK_PXL_MASK                               GENMASK(23, 16)
+#define CHNL_CTRL_MIPI_VC_ID(n)                                        ((n) << 6)
+#define CHNL_CTRL_MIPI_VC_ID_MASK                              GENMASK(7, 6)
+#define CHNL_CTRL_SRC_TYPE(n)                                  ((n) << 4)
+#define CHNL_CTRL_SRC_TYPE_MASK                                        BIT(4)
+#define CHNL_CTRL_SRC_TYPE_DEVICE                              0
+#define CHNL_CTRL_SRC_TYPE_MEMORY                              1
+#define CHNL_CTRL_SRC_INPUT(n)                                 ((n) << 0)
+#define CHNL_CTRL_SRC_INPUT_MASK                               GENMASK(2, 0)
+
+/* Channel Image Control Register */
+#define CHNL_IMG_CTRL                                          0x0004
+#define CHNL_IMG_CTRL_FORMAT(n)                                        ((n) << 24)
+#define CHNL_IMG_CTRL_FORMAT_MASK                              GENMASK(29, 24)
+#define CHNL_IMG_CTRL_FORMAT_RGBA8888                          0x00
+#define CHNL_IMG_CTRL_FORMAT_ABGR8888                          0x01
+#define CHNL_IMG_CTRL_FORMAT_ARGB8888                          0x02
+#define CHNL_IMG_CTRL_FORMAT_RGBX888                           0x03
+#define CHNL_IMG_CTRL_FORMAT_XBGR888                           0x04
+#define CHNL_IMG_CTRL_FORMAT_XRGB888                           0x05
+#define CHNL_IMG_CTRL_FORMAT_RGB888P                           0x06
+#define CHNL_IMG_CTRL_FORMAT_BGR888P                           0x07
+#define CHNL_IMG_CTRL_FORMAT_A2BGR10                           0x08
+#define CHNL_IMG_CTRL_FORMAT_A2RGB10                           0x09
+#define CHNL_IMG_CTRL_FORMAT_RGB565                            0x0a
+#define CHNL_IMG_CTRL_FORMAT_RAW8                              0x0b
+#define CHNL_IMG_CTRL_FORMAT_RAW10                             0x0c
+#define CHNL_IMG_CTRL_FORMAT_RAW10P                            0x0d
+#define CHNL_IMG_CTRL_FORMAT_RAW12                             0x0e
+#define CHNL_IMG_CTRL_FORMAT_RAW16                             0x0f
+#define CHNL_IMG_CTRL_FORMAT_YUV444_1P8P                       0x10
+#define CHNL_IMG_CTRL_FORMAT_YUV444_2P8P                       0x11
+#define CHNL_IMG_CTRL_FORMAT_YUV444_3P8P                       0x12
+#define CHNL_IMG_CTRL_FORMAT_YUV444_1P8                                0x13
+#define CHNL_IMG_CTRL_FORMAT_YUV444_1P10                       0x14
+#define CHNL_IMG_CTRL_FORMAT_YUV444_2P10                       0x15
+#define CHNL_IMG_CTRL_FORMAT_YUV444_3P10                       0x16
+#define CHNL_IMG_CTRL_FORMAT_YUV444_1P10P                      0x18
+#define CHNL_IMG_CTRL_FORMAT_YUV444_2P10P                      0x19
+#define CHNL_IMG_CTRL_FORMAT_YUV444_3P10P                      0x1a
+#define CHNL_IMG_CTRL_FORMAT_YUV444_1P12                       0x1c
+#define CHNL_IMG_CTRL_FORMAT_YUV444_2P12                       0x1d
+#define CHNL_IMG_CTRL_FORMAT_YUV444_3P12                       0x1e
+#define CHNL_IMG_CTRL_FORMAT_YUV422_1P8P                       0x20
+#define CHNL_IMG_CTRL_FORMAT_YUV422_2P8P                       0x21
+#define CHNL_IMG_CTRL_FORMAT_YUV422_3P8P                       0x22
+#define CHNL_IMG_CTRL_FORMAT_YUV422_1P10                       0x24
+#define CHNL_IMG_CTRL_FORMAT_YUV422_2P10                       0x25
+#define CHNL_IMG_CTRL_FORMAT_YUV422_3P10                       0x26
+#define CHNL_IMG_CTRL_FORMAT_YUV422_1P10P                      0x28
+#define CHNL_IMG_CTRL_FORMAT_YUV422_2P10P                      0x29
+#define CHNL_IMG_CTRL_FORMAT_YUV422_3P10P                      0x2a
+#define CHNL_IMG_CTRL_FORMAT_YUV422_1P12                       0x2c
+#define CHNL_IMG_CTRL_FORMAT_YUV422_2P12                       0x2d
+#define CHNL_IMG_CTRL_FORMAT_YUV422_3P12                       0x2e
+#define CHNL_IMG_CTRL_FORMAT_YUV420_2P8P                       0x31
+#define CHNL_IMG_CTRL_FORMAT_YUV420_3P8P                       0x32
+#define CHNL_IMG_CTRL_FORMAT_YUV420_2P10                       0x35
+#define CHNL_IMG_CTRL_FORMAT_YUV420_3P10                       0x36
+#define CHNL_IMG_CTRL_FORMAT_YUV420_2P10P                      0x39
+#define CHNL_IMG_CTRL_FORMAT_YUV420_3P10P                      0x3a
+#define CHNL_IMG_CTRL_FORMAT_YUV420_2P12                       0x3d
+#define CHNL_IMG_CTRL_FORMAT_YUV420_3P12                       0x3e
+#define CHNL_IMG_CTRL_GBL_ALPHA_VAL(n)                         ((n) << 16)
+#define CHNL_IMG_CTRL_GBL_ALPHA_VAL_MASK                       GENMASK(23, 16)
+#define CHNL_IMG_CTRL_GBL_ALPHA_EN                             BIT(15)
+#define CHNL_IMG_CTRL_DEINT(n)                                 ((n) << 12)
+#define CHNL_IMG_CTRL_DEINT_MASK                               GENMASK(14, 12)
+#define CHNL_IMG_CTRL_DEINT_WEAVE_ODD_EVEN                     2
+#define CHNL_IMG_CTRL_DEINT_WEAVE_EVEN_ODD                     3
+#define CHNL_IMG_CTRL_DEINT_BLEND_ODD_EVEN                     4
+#define CHNL_IMG_CTRL_DEINT_BLEND_EVEN_ODD                     5
+#define CHNL_IMG_CTRL_DEINT_LDOUBLE_ODD_EVEN                   6
+#define CHNL_IMG_CTRL_DEINT_LDOUBLE_EVEN_ODD                   7
+#define CHNL_IMG_CTRL_DEC_X(n)                                 ((n) << 10)
+#define CHNL_IMG_CTRL_DEC_X_MASK                               GENMASK(11, 10)
+#define CHNL_IMG_CTRL_DEC_Y(n)                                 ((n) << 8)
+#define CHNL_IMG_CTRL_DEC_Y_MASK                               GENMASK(9, 8)
+#define CHNL_IMG_CTRL_CROP_EN                                  BIT(7)
+#define CHNL_IMG_CTRL_VFLIP_EN                                 BIT(6)
+#define CHNL_IMG_CTRL_HFLIP_EN                                 BIT(5)
+#define CHNL_IMG_CTRL_YCBCR_MODE                               BIT(3)
+#define CHNL_IMG_CTRL_CSC_MODE(n)                              ((n) << 1)
+#define CHNL_IMG_CTRL_CSC_MODE_MASK                            GENMASK(2, 1)
+#define CHNL_IMG_CTRL_CSC_MODE_YUV2RGB                         0
+#define CHNL_IMG_CTRL_CSC_MODE_YCBCR2RGB                       1
+#define CHNL_IMG_CTRL_CSC_MODE_RGB2YUV                         2
+#define CHNL_IMG_CTRL_CSC_MODE_RGB2YCBCR                       3
+#define CHNL_IMG_CTRL_CSC_BYPASS                               BIT(0)
+
+/* Channel Output Buffer Control Register */
+#define CHNL_OUT_BUF_CTRL                                      0x0008
+#define CHNL_OUT_BUF_CTRL_LOAD_BUF2_ADDR                       BIT(15)
+#define CHNL_OUT_BUF_CTRL_LOAD_BUF1_ADDR                       BIT(14)
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V(n)              ((n) << 6)
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_MASK            GENMASK(7, 6)
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_NO_PANIC                0
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_PANIC_25                1
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_PANIC_50                2
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_PANIC_75                3
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U(n)              ((n) << 3)
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_MASK            GENMASK(4, 3)
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_NO_PANIC                0
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_PANIC_25                1
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_PANIC_50                2
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_PANIC_75                3
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y(n)              ((n) << 0)
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_MASK            GENMASK(1, 0)
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_NO_PANIC                0
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_PANIC_25                1
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_PANIC_50                2
+#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_PANIC_75                3
+
+/* Channel Image Configuration */
+#define CHNL_IMG_CFG                                           0x000c
+#define CHNL_IMG_CFG_HEIGHT(n)                                 ((n) << 16)
+#define CHNL_IMG_CFG_HEIGHT_MASK                               GENMASK(28, 16)
+#define CHNL_IMG_CFG_WIDTH(n)                                  ((n) << 0)
+#define CHNL_IMG_CFG_WIDTH_MASK                                        GENMASK(12, 0)
+
+/* Channel Interrupt Enable Register */
+#define CHNL_IER                                               0x0010
+#define CHNL_IER_MEM_RD_DONE_EN                                        BIT(31)
+#define CHNL_IER_LINE_RCVD_EN                                  BIT(30)
+#define CHNL_IER_FRM_RCVD_EN                                   BIT(29)
+#define CHNL_IER_AXI_WR_ERR_V_EN                               BIT(28)
+#define CHNL_IER_AXI_WR_ERR_U_EN                               BIT(27)
+#define CHNL_IER_AXI_WR_ERR_Y_EN                               BIT(26)
+#define CHNL_IER_AXI_RD_ERR_EN                                 BIT(25)
+
+/* Channel Status Register */
+#define CHNL_STS                                               0x0014
+#define CHNL_STS_MEM_RD_DONE                                   BIT(31)
+#define CHNL_STS_LINE_STRD                                     BIT(30)
+#define CHNL_STS_FRM_STRD                                      BIT(29)
+#define CHNL_STS_AXI_WR_ERR_V                                  BIT(28)
+#define CHNL_STS_AXI_WR_ERR_U                                  BIT(27)
+#define CHNL_STS_AXI_WR_ERR_Y                                  BIT(26)
+#define CHNL_STS_AXI_RD_ERR                                    BIT(25)
+#define CHNL_STS_OFLW_PANIC_V_BUF                              BIT(24)
+#define CHNL_STS_EXCS_OFLW_V_BUF                               BIT(23)
+#define CHNL_STS_OFLW_V_BUF                                    BIT(22)
+#define CHNL_STS_OFLW_PANIC_U_BUF                              BIT(21)
+#define CHNL_STS_EXCS_OFLW_U_BUF                               BIT(20)
+#define CHNL_STS_OFLW_U_BUF                                    BIT(19)
+#define CHNL_STS_OFLW_PANIC_Y_BUF                              BIT(18)
+#define CHNL_STS_EXCS_OFLW_Y_BUF                               BIT(17)
+#define CHNL_STS_OFLW_Y_BUF                                    BIT(16)
+#define CHNL_STS_EARLY_VSYNC_ERR                               BIT(15)
+#define CHNL_STS_LATE_VSYNC_ERR                                        BIT(14)
+#define CHNL_STS_MEM_RD_OFLOW                                  BIT(10)
+#define CHNL_STS_BUF2_ACTIVE                                   BIT(9)
+#define CHNL_STS_BUF1_ACTIVE                                   BIT(8)
+#define CHNL_STS_OFLW_BYTES(n)                                 ((n) << 0)
+#define CHNL_STS_OFLW_BYTES_MASK                               GENMASK(7, 0)
+
+/* Channel Scale Factor Register */
+#define CHNL_SCALE_FACTOR                                      0x0018
+#define CHNL_SCALE_FACTOR_Y_SCALE(n)                           ((n) << 16)
+#define CHNL_SCALE_FACTOR_Y_SCALE_MASK                         GENMASK(29, 16)
+#define CHNL_SCALE_FACTOR_X_SCALE(n)                           ((n) << 0)
+#define CHNL_SCALE_FACTOR_X_SCALE_MASK                         GENMASK(13, 0)
+
+/* Channel Scale Offset Register */
+#define CHNL_SCALE_OFFSET                                      0x001c
+#define CHNL_SCALE_OFFSET_Y_SCALE(n)                           ((n) << 16)
+#define CHNL_SCALE_OFFSET_Y_SCALE_MASK                         GENMASK(27, 16)
+#define CHNL_SCALE_OFFSET_X_SCALE(n)                           ((n) << 0)
+#define CHNL_SCALE_OFFSET_X_SCALE_MASK                         GENMASK(11, 0)
+
+/* Channel Crop Upper Left Corner Coordinate Register */
+#define CHNL_CROP_ULC                                          0x0020
+#define CHNL_CROP_ULC_X(n)                                     ((n) << 16)
+#define CHNL_CROP_ULC_X_MASK                                   GENMASK(27, 16)
+#define CHNL_CROP_ULC_Y(n)                                     ((n) << 0)
+#define CHNL_CROP_ULC_Y_MASK                                   GENMASK(11, 0)
+
+/* Channel Crop Lower Right Corner Coordinate Register */
+#define CHNL_CROP_LRC                                          0x0024
+#define CHNL_CROP_LRC_X(n)                                     ((n) << 16)
+#define CHNL_CROP_LRC_X_MASK                                   GENMASK(27, 16)
+#define CHNL_CROP_LRC_Y(n)                                     ((n) << 0)
+#define CHNL_CROP_LRC_Y_MASK                                   GENMASK(11, 0)
+
+/* Channel Color Space Conversion Coefficient Register 0 */
+#define CHNL_CSC_COEFF0                                                0x0028
+#define CHNL_CSC_COEFF0_A2(n)                                  ((n) << 16)
+#define CHNL_CSC_COEFF0_A2_MASK                                        GENMASK(26, 16)
+#define CHNL_CSC_COEFF0_A1(n)                                  ((n) << 0)
+#define CHNL_CSC_COEFF0_A1_MASK                                        GENMASK(10, 0)
+
+/* Channel Color Space Conversion Coefficient Register 1 */
+#define CHNL_CSC_COEFF1                                                0x002c
+#define CHNL_CSC_COEFF1_B1(n)                                  ((n) << 16)
+#define CHNL_CSC_COEFF1_B1_MASK                                        GENMASK(26, 16)
+#define CHNL_CSC_COEFF1_A3(n)                                  ((n) << 0)
+#define CHNL_CSC_COEFF1_A3_MASK                                        GENMASK(10, 0)
+
+/* Channel Color Space Conversion Coefficient Register 2 */
+#define CHNL_CSC_COEFF2                                                0x0030
+#define CHNL_CSC_COEFF2_B3(n)                                  ((n) << 16)
+#define CHNL_CSC_COEFF2_B3_MASK                                        GENMASK(26, 16)
+#define CHNL_CSC_COEFF2_B2(n)                                  ((n) << 0)
+#define CHNL_CSC_COEFF2_B2_MASK                                        GENMASK(10, 0)
+
+/* Channel Color Space Conversion Coefficient Register 3 */
+#define CHNL_CSC_COEFF3                                                0x0034
+#define CHNL_CSC_COEFF3_C2(n)                                  ((n) << 16)
+#define CHNL_CSC_COEFF3_C2_MASK                                        GENMASK(26, 16)
+#define CHNL_CSC_COEFF3_C1(n)                                  ((n) << 0)
+#define CHNL_CSC_COEFF3_C1_MASK                                        GENMASK(10, 0)
+
+/* Channel Color Space Conversion Coefficient Register 4 */
+#define CHNL_CSC_COEFF4                                                0x0038
+#define CHNL_CSC_COEFF4_D1(n)                                  ((n) << 16)
+#define CHNL_CSC_COEFF4_D1_MASK                                        GENMASK(24, 16)
+#define CHNL_CSC_COEFF4_C3(n)                                  ((n) << 0)
+#define CHNL_CSC_COEFF4_C3_MASK                                        GENMASK(10, 0)
+
+/* Channel Color Space Conversion Coefficient Register 5 */
+#define CHNL_CSC_COEFF5                                                0x003c
+#define CHNL_CSC_COEFF5_D3(n)                                  ((n) << 16)
+#define CHNL_CSC_COEFF5_D3_MASK                                        GENMASK(24, 16)
+#define CHNL_CSC_COEFF5_D2(n)                                  ((n) << 0)
+#define CHNL_CSC_COEFF5_D2_MASK                                        GENMASK(8, 0)
+
+/* Channel Alpha Value Register for ROI 0 */
+#define CHNL_ROI_0_ALPHA                                       0x0040
+#define CHNL_ROI_0_ALPHA_VAL(n)                                        ((n) << 24)
+#define CHNL_ROI_0_ALPHA_MASK                                  GENMASK(31, 24)
+#define CHNL_ROI_0_ALPHA_EN                                    BIT(16)
+
+/* Channel Upper Left Coordinate Register for ROI 0 */
+#define CHNL_ROI_0_ULC                                         0x0044
+#define CHNL_ROI_0_ULC_X(n)                                    ((n) << 16)
+#define CHNL_ROI_0_ULC_X_MASK                                  GENMASK(27, 16)
+#define CHNL_ROI_0_ULC_Y(n)                                    ((n) << 0)
+#define CHNL_ROI_0_ULC_Y_MASK                                  GENMASK(11, 0)
+
+/* Channel Lower Right Coordinate Register for ROI 0 */
+#define CHNL_ROI_0_LRC                                         0x0048
+#define CHNL_ROI_0_LRC_X(n)                                    ((n) << 16)
+#define CHNL_ROI_0_LRC_X_MASK                                  GENMASK(27, 16)
+#define CHNL_ROI_0_LRC_Y(n)                                    ((n) << 0)
+#define CHNL_ROI_0_LRC_Y_MASK                                  GENMASK(11, 0)
+
+/* Channel Alpha Value Register for ROI 1 */
+#define CHNL_ROI_1_ALPHA                                       0x004c
+#define CHNL_ROI_1_ALPHA_VAL(n)                                        ((n) << 24)
+#define CHNL_ROI_1_ALPHA_MASK                                  GENMASK(31, 24)
+#define CHNL_ROI_1_ALPHA_EN                                    BIT(16)
+
+/* Channel Upper Left Coordinate Register for ROI 1 */
+#define CHNL_ROI_1_ULC                                         0x0050
+#define CHNL_ROI_1_ULC_X(n)                                    ((n) << 16)
+#define CHNL_ROI_1_ULC_X_MASK                                  GENMASK(27, 16)
+#define CHNL_ROI_1_ULC_Y(n)                                    ((n) << 0)
+#define CHNL_ROI_1_ULC_Y_MASK                                  GENMASK(11, 0)
+
+/* Channel Lower Right Coordinate Register for ROI 1 */
+#define CHNL_ROI_1_LRC                                         0x0054
+#define CHNL_ROI_1_LRC_X(n)                                    ((n) << 16)
+#define CHNL_ROI_1_LRC_X_MASK                                  GENMASK(27, 16)
+#define CHNL_ROI_1_LRC_Y(n)                                    ((n) << 0)
+#define CHNL_ROI_1_LRC_Y_MASK                                  GENMASK(11, 0)
+
+/* Channel Alpha Value Register for ROI 2 */
+#define CHNL_ROI_2_ALPHA                                       0x0058
+#define CHNL_ROI_2_ALPHA_VAL(n)                                        ((n) << 24)
+#define CHNL_ROI_2_ALPHA_MASK                                  GENMASK(31, 24)
+#define CHNL_ROI_2_ALPHA_EN                                    BIT(16)
+
+/* Channel Upper Left Coordinate Register for ROI 2 */
+#define CHNL_ROI_2_ULC                                         0x005c
+#define CHNL_ROI_2_ULC_X(n)                                    ((n) << 16)
+#define CHNL_ROI_2_ULC_X_MASK                                  GENMASK(27, 16)
+#define CHNL_ROI_2_ULC_Y(n)                                    ((n) << 0)
+#define CHNL_ROI_2_ULC_Y_MASK                                  GENMASK(11, 0)
+
+/* Channel Lower Right Coordinate Register for ROI 2 */
+#define CHNL_ROI_2_LRC                                         0x0060
+#define CHNL_ROI_2_LRC_X(n)                                    ((n) << 16)
+#define CHNL_ROI_2_LRC_X_MASK                                  GENMASK(27, 16)
+#define CHNL_ROI_2_LRC_Y(n)                                    ((n) << 0)
+#define CHNL_ROI_2_LRC_Y_MASK                                  GENMASK(11, 0)
+
+/* Channel Alpha Value Register for ROI 3 */
+#define CHNL_ROI_3_ALPHA                                       0x0064
+#define CHNL_ROI_3_ALPHA_VAL(n)                                        ((n) << 24)
+#define CHNL_ROI_3_ALPHA_MASK                                  GENMASK(31, 24)
+#define CHNL_ROI_3_ALPHA_EN                                    BIT(16)
+
+/* Channel Upper Left Coordinate Register for ROI 3 */
+#define CHNL_ROI_3_ULC                                         0x0068
+#define CHNL_ROI_3_ULC_X(n)                                    ((n) << 16)
+#define CHNL_ROI_3_ULC_X_MASK                                  GENMASK(27, 16)
+#define CHNL_ROI_3_ULC_Y(n)                                    ((n) << 0)
+#define CHNL_ROI_3_ULC_Y_MASK                                  GENMASK(11, 0)
+
+/* Channel Lower Right Coordinate Register for ROI 3 */
+#define CHNL_ROI_3_LRC                                         0x006c
+#define CHNL_ROI_3_LRC_X(n)                                    ((n) << 16)
+#define CHNL_ROI_3_LRC_X_MASK                                  GENMASK(27, 16)
+#define CHNL_ROI_3_LRC_Y(n)                                    ((n) << 0)
+#define CHNL_ROI_3_LRC_Y_MASK                                  GENMASK(11, 0)
+/* Channel RGB or Luma (Y) Output Buffer 1 Address */
+#define CHNL_OUT_BUF1_ADDR_Y                                   0x0070
+
+/* Channel Chroma (U/Cb/UV/CbCr) Output Buffer 1 Address */
+#define CHNL_OUT_BUF1_ADDR_U                                   0x0074
+
+/* Channel Chroma (V/Cr) Output Buffer 1 Address */
+#define CHNL_OUT_BUF1_ADDR_V                                   0x0078
+
+/* Channel Output Buffer Pitch */
+#define CHNL_OUT_BUF_PITCH                                     0x007c
+#define CHNL_OUT_BUF_PITCH_LINE_PITCH(n)                       ((n) << 0)
+#define CHNL_OUT_BUF_PITCH_LINE_PITCH_MASK                     GENMASK(15, 0)
+
+/* Channel Input Buffer Address */
+#define CHNL_IN_BUF_ADDR                                       0x0080
+
+/* Channel Input Buffer Pitch */
+#define CHNL_IN_BUF_PITCH                                      0x0084
+#define CHNL_IN_BUF_PITCH_FRM_PITCH(n)                         ((n) << 16)
+#define CHNL_IN_BUF_PITCH_FRM_PITCH_MASK                       GENMASK(31, 16)
+#define CHNL_IN_BUF_PITCH_LINE_PITCH(n)                                ((n) << 0)
+#define CHNL_IN_BUF_PITCH_LINE_PITCH_MASK                      GENMASK(15, 0)
+
+/* Channel Memory Read Control */
+#define CHNL_MEM_RD_CTRL                                       0x0088
+#define CHNL_MEM_RD_CTRL_IMG_TYPE(n)                           ((n) << 28)
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_MASK                         GENMASK(31, 28)
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_BGR8P                                0x00
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_RGB8P                                0x01
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_XRGB8                                0x02
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_RGBX8                                0x03
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_XBGR8                                0x04
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_RGB565                       0x05
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_A2BGR10                      0x06
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_A2RGB10                      0x07
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_YUV444_1P8P                  0x08
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_YUV444_1P10                  0x09
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_YUV444_1P10P                 0x0a
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_YUV444_1P12                  0x0b
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_YUV444_1P8                   0x0c
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_YUV422_1P8P                  0x0d
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_YUV422_1P10                  0x0e
+#define CHNL_MEM_RD_CTRL_IMG_TYPE_YUV422_1P12                  0x0f
+#define CHNL_MEM_RD_CTRL_READ_MEM                              BIT(0)
+
+/* Channel RGB or Luma (Y) Output Buffer 2 Address */
+#define CHNL_OUT_BUF2_ADDR_Y                                   0x008c
+
+/* Channel Chroma (U/Cb/UV/CbCr) Output Buffer 2 Address  */
+#define CHNL_OUT_BUF2_ADDR_U                                   0x0090
+
+/* Channel Chroma (V/Cr) Output Buffer 2 Address   */
+#define CHNL_OUT_BUF2_ADDR_V                                   0x0094
+
+/* Channel scale image config */
+#define CHNL_SCL_IMG_CFG                                       0x0098
+#define CHNL_SCL_IMG_CFG_HEIGHT(n)                             ((n) << 16)
+#define CHNL_SCL_IMG_CFG_HEIGHT_MASK                           GENMASK(28, 16)
+#define CHNL_SCL_IMG_CFG_WIDTH(n)                              ((n) << 0)
+#define CHNL_SCL_IMG_CFG_WIDTH_MASK                            GENMASK(12, 0)
+
+/* Channel Flow Control Register */
+#define CHNL_FLOW_CTRL                                         0x009c
+#define CHNL_FLOW_CTRL_FC_DENOM_MASK                           GENMASK(7, 0)
+#define CHNL_FLOW_CTRL_FC_DENOM(n)                             ((n) << 0)
+#define CHNL_FLOW_CTRL_FC_NUMER_MASK                           GENMASK(23, 16)
+#define CHNL_FLOW_CTRL_FC_NUMER(n)                             ((n) << 0)
+
+/* Channel Output Y-Buffer 1 Extended Address Bits */
+#define CHNL_Y_BUF1_XTND_ADDR                                  0x00a0
+
+/* Channel Output U-Buffer 1 Extended Address Bits */
+#define CHNL_U_BUF1_XTND_ADDR                                  0x00a4
+
+/* Channel Output V-Buffer 1 Extended Address Bits */
+#define CHNL_V_BUF1_XTND_ADDR                                  0x00a8
+
+/* Channel Output Y-Buffer 2 Extended Address Bits */
+#define CHNL_Y_BUF2_XTND_ADDR                                  0x00ac
+
+/* Channel Output U-Buffer 2 Extended Address Bits */
+#define CHNL_U_BUF2_XTND_ADDR                                  0x00b0
+
+/* Channel Output V-Buffer 2 Extended Address Bits */
+#define CHNL_V_BUF2_XTND_ADDR                                  0x00b4
+
+/* Channel Input Buffer Extended Address Bits */
+#define CHNL_IN_BUF_XTND_ADDR                                  0x00b8
+
+#endif /* __IMX8_ISI_REGS_H__ */
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
new file mode 100644 (file)
index 0000000..10840c9
--- /dev/null
@@ -0,0 +1,1512 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * V4L2 Capture ISI subdev driver for i.MX8QXP/QM platform
+ *
+ * ISI is a Image Sensor Interface of i.MX8QXP/QM platform, which
+ * used to process image from camera sensor to memory or DC
+ *
+ * Copyright (c) 2019 NXP Semiconductor
+ */
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/media-bus-format.h>
+#include <linux/minmax.h>
+#include <linux/pm_runtime.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-v4l2.h>
+
+#include "imx8-isi-core.h"
+#include "imx8-isi-regs.h"
+
+/* Keep the first entry matching MXC_ISI_DEF_PIXEL_FORMAT */
+static const struct mxc_isi_format_info mxc_isi_formats[] = {
+       /* YUV formats */
+       {
+               .mbus_code      = MEDIA_BUS_FMT_YUV8_1X24,
+               .fourcc         = V4L2_PIX_FMT_YUYV,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
+                               | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_in_format  = CHNL_MEM_RD_CTRL_IMG_TYPE_YUV422_1P8P,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV422_1P8P,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_YUV,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_YUV8_1X24,
+               .fourcc         = V4L2_PIX_FMT_YUVA32,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV444_1P8,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 32 },
+               .encoding       = MXC_ISI_ENC_YUV,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_YUV8_1X24,
+               .fourcc         = V4L2_PIX_FMT_NV12,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV420_2P8P,
+               .color_planes   = 2,
+               .mem_planes     = 1,
+               .depth          = { 8, 16 },
+               .hsub           = 2,
+               .vsub           = 2,
+               .encoding       = MXC_ISI_ENC_YUV,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_YUV8_1X24,
+               .fourcc         = V4L2_PIX_FMT_NV12M,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV420_2P8P,
+               .mem_planes     = 2,
+               .color_planes   = 2,
+               .depth          = { 8, 16 },
+               .hsub           = 2,
+               .vsub           = 2,
+               .encoding       = MXC_ISI_ENC_YUV,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_YUV8_1X24,
+               .fourcc         = V4L2_PIX_FMT_NV16,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV422_2P8P,
+               .color_planes   = 2,
+               .mem_planes     = 1,
+               .depth          = { 8, 16 },
+               .hsub           = 2,
+               .vsub           = 1,
+               .encoding       = MXC_ISI_ENC_YUV,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_YUV8_1X24,
+               .fourcc         = V4L2_PIX_FMT_NV16M,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV422_2P8P,
+               .mem_planes     = 2,
+               .color_planes   = 2,
+               .depth          = { 8, 16 },
+               .hsub           = 2,
+               .vsub           = 1,
+               .encoding       = MXC_ISI_ENC_YUV,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_YUV8_1X24,
+               .fourcc         = V4L2_PIX_FMT_YUV444M,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV444_3P8P,
+               .mem_planes     = 3,
+               .color_planes   = 3,
+               .depth          = { 8, 8, 8 },
+               .hsub           = 1,
+               .vsub           = 1,
+               .encoding       = MXC_ISI_ENC_YUV,
+       },
+       /* RGB formats */
+       {
+               .mbus_code      = MEDIA_BUS_FMT_RGB888_1X24,
+               .fourcc         = V4L2_PIX_FMT_RGB565,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
+                               | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_in_format  = CHNL_MEM_RD_CTRL_IMG_TYPE_RGB565,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RGB565,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RGB,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_RGB888_1X24,
+               .fourcc         = V4L2_PIX_FMT_RGB24,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
+                               | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_in_format  = CHNL_MEM_RD_CTRL_IMG_TYPE_BGR8P,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_BGR888P,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 24 },
+               .encoding       = MXC_ISI_ENC_RGB,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_RGB888_1X24,
+               .fourcc         = V4L2_PIX_FMT_BGR24,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
+                               | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_in_format  = CHNL_MEM_RD_CTRL_IMG_TYPE_RGB8P,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RGB888P,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 24 },
+               .encoding       = MXC_ISI_ENC_RGB,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_RGB888_1X24,
+               .fourcc         = V4L2_PIX_FMT_XBGR32,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
+                               | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_in_format  = CHNL_MEM_RD_CTRL_IMG_TYPE_XBGR8,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_XRGB888,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 32 },
+               .encoding       = MXC_ISI_ENC_RGB,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_RGB888_1X24,
+               .fourcc         = V4L2_PIX_FMT_ABGR32,
+               .type           = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_ARGB8888,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 32 },
+               .encoding       = MXC_ISI_ENC_RGB,
+       },
+       /*
+        * RAW formats
+        *
+        * The ISI shifts the 10-bit and 12-bit formats left by 6 and 4 bits
+        * when using CHNL_IMG_CTRL_FORMAT_RAW10 or MXC_ISI_OUT_FMT_RAW12
+        * respectively, to align the bits to the left and pad with zeros in
+        * the LSBs. The corresponding V4L2 formats are however right-aligned,
+        * we have to use CHNL_IMG_CTRL_FORMAT_RAW16 to avoid the left shift.
+        */
+       {
+               .mbus_code      = MEDIA_BUS_FMT_Y8_1X8,
+               .fourcc         = V4L2_PIX_FMT_GREY,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 8 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_Y10_1X10,
+               .fourcc         = V4L2_PIX_FMT_Y10,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_Y12_1X12,
+               .fourcc         = V4L2_PIX_FMT_Y12,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_Y14_1X14,
+               .fourcc         = V4L2_PIX_FMT_Y14,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SBGGR8_1X8,
+               .fourcc         = V4L2_PIX_FMT_SBGGR8,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 8 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGBRG8_1X8,
+               .fourcc         = V4L2_PIX_FMT_SGBRG8,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 8 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGRBG8_1X8,
+               .fourcc         = V4L2_PIX_FMT_SGRBG8,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 8 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SRGGB8_1X8,
+               .fourcc         = V4L2_PIX_FMT_SRGGB8,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 8 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SBGGR10_1X10,
+               .fourcc         = V4L2_PIX_FMT_SBGGR10,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGBRG10_1X10,
+               .fourcc         = V4L2_PIX_FMT_SGBRG10,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGRBG10_1X10,
+               .fourcc         = V4L2_PIX_FMT_SGRBG10,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SRGGB10_1X10,
+               .fourcc         = V4L2_PIX_FMT_SRGGB10,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SBGGR12_1X12,
+               .fourcc         = V4L2_PIX_FMT_SBGGR12,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGBRG12_1X12,
+               .fourcc         = V4L2_PIX_FMT_SGBRG12,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGRBG12_1X12,
+               .fourcc         = V4L2_PIX_FMT_SGRBG12,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SRGGB12_1X12,
+               .fourcc         = V4L2_PIX_FMT_SRGGB12,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SBGGR14_1X14,
+               .fourcc         = V4L2_PIX_FMT_SBGGR14,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGBRG14_1X14,
+               .fourcc         = V4L2_PIX_FMT_SGBRG14,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SGRBG14_1X14,
+               .fourcc         = V4L2_PIX_FMT_SGRBG14,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }, {
+               .mbus_code      = MEDIA_BUS_FMT_SRGGB14_1X14,
+               .fourcc         = V4L2_PIX_FMT_SRGGB14,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 16 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       },
+       /* JPEG */
+       {
+               .mbus_code      = MEDIA_BUS_FMT_JPEG_1X8,
+               .fourcc         = V4L2_PIX_FMT_MJPEG,
+               .type           = MXC_ISI_VIDEO_CAP,
+               .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
+               .mem_planes     = 1,
+               .color_planes   = 1,
+               .depth          = { 8 },
+               .encoding       = MXC_ISI_ENC_RAW,
+       }
+};
+
+const struct mxc_isi_format_info *
+mxc_isi_format_by_fourcc(u32 fourcc, enum mxc_isi_video_type type)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
+               const struct mxc_isi_format_info *fmt = &mxc_isi_formats[i];
+
+               if (fmt->fourcc == fourcc && fmt->type & type)
+                       return fmt;
+       }
+
+       return NULL;
+}
+
+const struct mxc_isi_format_info *
+mxc_isi_format_enum(unsigned int index, enum mxc_isi_video_type type)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
+               const struct mxc_isi_format_info *fmt = &mxc_isi_formats[i];
+
+               if (!(fmt->type & type))
+                       continue;
+
+               if (!index)
+                       return fmt;
+
+               index--;
+       }
+
+       return NULL;
+}
+
+const struct mxc_isi_format_info *
+mxc_isi_format_try(struct mxc_isi_pipe *pipe, struct v4l2_pix_format_mplane *pix,
+                  enum mxc_isi_video_type type)
+{
+       const struct mxc_isi_format_info *fmt;
+       unsigned int max_width;
+       unsigned int i;
+
+       max_width = pipe->id == pipe->isi->pdata->num_channels - 1
+                 ? MXC_ISI_MAX_WIDTH_UNCHAINED
+                 : MXC_ISI_MAX_WIDTH_CHAINED;
+
+       fmt = mxc_isi_format_by_fourcc(pix->pixelformat, type);
+       if (!fmt)
+               fmt = &mxc_isi_formats[0];
+
+       pix->width = clamp(pix->width, MXC_ISI_MIN_WIDTH, max_width);
+       pix->height = clamp(pix->height, MXC_ISI_MIN_HEIGHT, MXC_ISI_MAX_HEIGHT);
+       pix->pixelformat = fmt->fourcc;
+       pix->field = V4L2_FIELD_NONE;
+
+       if (pix->colorspace == V4L2_COLORSPACE_DEFAULT) {
+               pix->colorspace = MXC_ISI_DEF_COLOR_SPACE;
+               pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC;
+               pix->quantization = MXC_ISI_DEF_QUANTIZATION;
+               pix->xfer_func = MXC_ISI_DEF_XFER_FUNC;
+       }
+
+       if (pix->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
+               pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
+       if (pix->quantization == V4L2_QUANTIZATION_DEFAULT) {
+               bool is_rgb = fmt->encoding == MXC_ISI_ENC_RGB;
+
+               pix->quantization =
+                       V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, pix->colorspace,
+                                                     pix->ycbcr_enc);
+       }
+       if (pix->xfer_func == V4L2_XFER_FUNC_DEFAULT)
+               pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
+
+       pix->num_planes = fmt->mem_planes;
+
+       for (i = 0; i < fmt->color_planes; ++i) {
+               struct v4l2_plane_pix_format *plane = &pix->plane_fmt[i];
+               unsigned int bpl;
+
+               /* The pitch must be identical for all planes. */
+               if (i == 0)
+                       bpl = clamp(plane->bytesperline,
+                                   pix->width * fmt->depth[0] / 8,
+                                   65535U);
+               else
+                       bpl = pix->plane_fmt[0].bytesperline;
+
+               plane->bytesperline = bpl;
+
+               plane->sizeimage = plane->bytesperline * pix->height;
+               if (i >= 1)
+                       plane->sizeimage /= fmt->vsub;
+       }
+
+       /*
+        * For single-planar pixel formats with multiple color planes,
+        * concatenate the size of all planes and clear all planes but the
+        * first one.
+        */
+       if (fmt->color_planes != fmt->mem_planes) {
+               for (i = 1; i < fmt->color_planes; ++i) {
+                       struct v4l2_plane_pix_format *plane = &pix->plane_fmt[i];
+
+                       pix->plane_fmt[0].sizeimage += plane->sizeimage;
+                       plane->bytesperline = 0;
+                       plane->sizeimage = 0;
+               }
+       }
+
+       return fmt;
+}
+
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
+ */
+
+static void mxc_isi_video_frame_write_done(struct mxc_isi_pipe *pipe,
+                                          u32 status)
+{
+       struct mxc_isi_video *video = &pipe->video;
+       struct device *dev = pipe->isi->dev;
+       struct mxc_isi_buffer *next_buf;
+       struct mxc_isi_buffer *buf;
+       enum mxc_isi_buf_id buf_id;
+
+       spin_lock(&video->buf_lock);
+
+       /*
+        * The ISI hardware handles buffers using a ping-pong mechanism with
+        * two sets of destination addresses (with shadow registers to allow
+        * programming addresses for all planes atomically) named BUF1 and
+        * BUF2. Addresses can be loaded and copied to shadow registers at any
+        * at any time.
+        *
+        * The hardware keeps track of which buffer is being written to and
+        * automatically switches to the other buffer at frame end, copying the
+        * corresponding address to another set of shadow registers that track
+        * the address being written to. The active buffer tracking bits are
+        * accessible through the CHNL_STS register.
+        *
+        *  BUF1        BUF2  |   Event   | Action
+        *                    |           |
+        *                    |           | Program initial buffers
+        *                    |           | B0 in BUF1, B1 in BUF2
+        *                    | Start ISI |
+        * +----+             |           |
+        * | B0 |             |           |
+        * +----+             |           |
+        *             +----+ | FRM IRQ 0 | B0 complete, BUF2 now active
+        *             | B1 | |           | Program B2 in BUF1
+        *             +----+ |           |
+        * +----+             | FRM IRQ 1 | B1 complete, BUF1 now active
+        * | B2 |             |           | Program B3 in BUF2
+        * +----+             |           |
+        *             +----+ | FRM IRQ 2 | B2 complete, BUF2 now active
+        *             | B3 | |           | Program B4 in BUF1
+        *             +----+ |           |
+        * +----+             | FRM IRQ 3 | B3 complete, BUF1 now active
+        * | B4 |             |           | Program B5 in BUF2
+        * +----+             |           |
+        *        ...         |           |
+        *
+        * Races between address programming and buffer switching can be
+        * detected by checking if a frame end interrupt occurred after
+        * programming the addresses.
+        *
+        * As none of the shadow registers are accessible, races can occur
+        * between address programming and buffer switching. It is possible to
+        * detect the race condition by checking if a frame end interrupt
+        * occurred after programming the addresses, but impossible to
+        * determine if the race has been won or lost.
+        *
+        * In addition to this, we need to use discard buffers if no pending
+        * buffers are available. To simplify handling of discard buffer, we
+        * need to allocate three of them, as two can be active concurrently
+        * and we need to still be able to get hold of a next buffer. The logic
+        * could be improved to use two buffers only, but as all discard
+        * buffers share the same memory, an additional buffer is cheap.
+        */
+
+       /* Check which buffer has just completed. */
+       buf_id = pipe->isi->pdata->buf_active_reverse
+              ? (status & CHNL_STS_BUF1_ACTIVE ? MXC_ISI_BUF2 : MXC_ISI_BUF1)
+              : (status & CHNL_STS_BUF1_ACTIVE ? MXC_ISI_BUF1 : MXC_ISI_BUF2);
+
+       buf = list_first_entry_or_null(&video->out_active,
+                                      struct mxc_isi_buffer, list);
+
+       /* Safety check, this should really never happen. */
+       if (!buf) {
+               dev_warn(dev, "trying to access empty active list\n");
+               goto done;
+       }
+
+       /*
+        * If the buffer that has completed doesn't match the buffer on the
+        * front of the active list, it means we have lost one frame end
+        * interrupt (or possibly a large odd number of interrupts, although
+        * quite unlikely).
+        *
+        * For instance, if IRQ1 is lost and we handle IRQ2, both B1 and B2
+        * have been completed, but B3 hasn't been programmed, BUF2 still
+        * addresses B1 and the ISI is now writing in B1 instead of B3. We
+        * can't complete B2 as that would result in out-of-order completion.
+        *
+        * The only option is to ignore this interrupt and try again. When IRQ3
+        * will be handled, we will complete B1 and be in sync again.
+        */
+       if (buf->id != buf_id) {
+               dev_dbg(dev, "buffer ID mismatch (expected %u, got %u), skipping\n",
+                       buf->id, buf_id);
+
+               /*
+                * Increment the frame count by two to account for the missed
+                * and the ignored interrupts.
+                */
+               video->frame_count += 2;
+               goto done;
+       }
+
+       /* Pick the next buffer and queue it to the hardware. */
+       next_buf = list_first_entry_or_null(&video->out_pending,
+                                           struct mxc_isi_buffer, list);
+       if (!next_buf) {
+               next_buf = list_first_entry_or_null(&video->out_discard,
+                                                   struct mxc_isi_buffer, list);
+
+               /* Safety check, this should never happen. */
+               if (!next_buf) {
+                       dev_warn(dev, "trying to access empty discard list\n");
+                       goto done;
+               }
+       }
+
+       mxc_isi_channel_set_outbuf(pipe, next_buf->dma_addrs, buf_id);
+       next_buf->id = buf_id;
+
+       /*
+        * Check if we have raced with the end of frame interrupt. If so, we
+        * can't tell if the ISI has recorded the new address, or is still
+        * using the previous buffer. We must assume the latter as that is the
+        * worst case.
+        *
+        * For instance, if we are handling IRQ1 and now detect the FRM
+        * interrupt, assume B2 has completed and the ISI has switched to BUF2
+        * using B1 just before we programmed B3. Unlike in the previous race
+        * condition, B3 has been programmed and will be written to the next
+        * time the ISI switches to BUF2. We can however handle this exactly as
+        * the first race condition, as we'll program B3 (still at the head of
+        * the pending list) when handling IRQ3.
+        */
+       status = mxc_isi_channel_irq_status(pipe, false);
+       if (status & CHNL_STS_FRM_STRD) {
+               dev_dbg(dev, "raced with frame end interrupt\n");
+               video->frame_count += 2;
+               goto done;
+       }
+
+       /*
+        * The next buffer has been queued successfully, move it to the active
+        * list, and complete the current buffer.
+        */
+       list_move_tail(&next_buf->list, &video->out_active);
+
+       if (!buf->discard) {
+               list_del_init(&buf->list);
+               buf->v4l2_buf.sequence = video->frame_count;
+               buf->v4l2_buf.vb2_buf.timestamp = ktime_get_ns();
+               vb2_buffer_done(&buf->v4l2_buf.vb2_buf, VB2_BUF_STATE_DONE);
+       } else {
+               list_move_tail(&buf->list, &video->out_discard);
+       }
+
+       video->frame_count++;
+
+done:
+       spin_unlock(&video->buf_lock);
+}
+
+static void mxc_isi_video_free_discard_buffers(struct mxc_isi_video *video)
+{
+       unsigned int i;
+
+       for (i = 0; i < video->pix.num_planes; i++) {
+               struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i];
+
+               if (!buf->addr)
+                       continue;
+
+               dma_free_coherent(video->pipe->isi->dev, buf->size, buf->addr,
+                                 buf->dma);
+               buf->addr = NULL;
+       }
+}
+
+static int mxc_isi_video_alloc_discard_buffers(struct mxc_isi_video *video)
+{
+       unsigned int i, j;
+
+       /* Allocate memory for each plane. */
+       for (i = 0; i < video->pix.num_planes; i++) {
+               struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i];
+
+               buf->size = PAGE_ALIGN(video->pix.plane_fmt[i].sizeimage);
+               buf->addr = dma_alloc_coherent(video->pipe->isi->dev, buf->size,
+                                              &buf->dma, GFP_DMA | GFP_KERNEL);
+               if (!buf->addr) {
+                       mxc_isi_video_free_discard_buffers(video);
+                       return -ENOMEM;
+               }
+
+               dev_dbg(video->pipe->isi->dev,
+                       "discard buffer plane %u: %zu bytes @%pad (CPU address %p)\n",
+                       i, buf->size, &buf->dma, buf->addr);
+       }
+
+       /* Fill the DMA addresses in the discard buffers. */
+       for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) {
+               struct mxc_isi_buffer *buf = &video->buf_discard[i];
+
+               buf->discard = true;
+
+               for (j = 0; j < video->pix.num_planes; ++j)
+                       buf->dma_addrs[j] = video->discard_buffer[j].dma;
+       }
+
+       return 0;
+}
+
+static int mxc_isi_video_validate_format(struct mxc_isi_video *video)
+{
+       const struct v4l2_mbus_framefmt *format;
+       const struct mxc_isi_format_info *info;
+       struct v4l2_subdev_state *state;
+       struct v4l2_subdev *sd = &video->pipe->sd;
+       int ret = 0;
+
+       state = v4l2_subdev_lock_and_get_active_state(sd);
+
+       info = mxc_isi_format_by_fourcc(video->pix.pixelformat,
+                                       MXC_ISI_VIDEO_CAP);
+       format = v4l2_subdev_get_try_format(sd, state, MXC_ISI_PIPE_PAD_SOURCE);
+
+       if (format->code != info->mbus_code ||
+           format->width != video->pix.width ||
+           format->height != video->pix.height) {
+               dev_dbg(video->pipe->isi->dev,
+                       "%s: configuration mismatch, 0x%04x/%ux%u != 0x%04x/%ux%u\n",
+                       __func__, format->code, format->width, format->height,
+                       info->mbus_code, video->pix.width, video->pix.height);
+               ret = -EINVAL;
+       }
+
+       v4l2_subdev_unlock_state(state);
+
+       return ret;
+}
+
+static void mxc_isi_video_return_buffers(struct mxc_isi_video *video,
+                                        enum vb2_buffer_state state)
+{
+       struct mxc_isi_buffer *buf;
+
+       spin_lock_irq(&video->buf_lock);
+
+       while (!list_empty(&video->out_active)) {
+               buf = list_first_entry(&video->out_active,
+                                      struct mxc_isi_buffer, list);
+               list_del_init(&buf->list);
+               if (buf->discard)
+                       continue;
+
+               vb2_buffer_done(&buf->v4l2_buf.vb2_buf, state);
+       }
+
+       while (!list_empty(&video->out_pending)) {
+               buf = list_first_entry(&video->out_pending,
+                                      struct mxc_isi_buffer, list);
+               list_del_init(&buf->list);
+               vb2_buffer_done(&buf->v4l2_buf.vb2_buf, state);
+       }
+
+       while (!list_empty(&video->out_discard)) {
+               buf = list_first_entry(&video->out_discard,
+                                      struct mxc_isi_buffer, list);
+               list_del_init(&buf->list);
+       }
+
+       INIT_LIST_HEAD(&video->out_active);
+       INIT_LIST_HEAD(&video->out_pending);
+       INIT_LIST_HEAD(&video->out_discard);
+
+       spin_unlock_irq(&video->buf_lock);
+}
+
+static void mxc_isi_video_queue_first_buffers(struct mxc_isi_video *video)
+{
+       unsigned int discard;
+       unsigned int i;
+
+       lockdep_assert_held(&video->buf_lock);
+
+       /*
+        * Queue two ISI channel output buffers. We are not guaranteed to have
+        * any buffer in the pending list when this function is called from the
+        * system resume handler. Use pending buffers as much as possible, and
+        * use discard buffers to fill the remaining slots.
+        */
+
+       /* How many discard buffers do we need to queue first ? */
+       discard = list_empty(&video->out_pending) ? 2
+               : list_is_singular(&video->out_pending) ? 1
+               : 0;
+
+       for (i = 0; i < 2; ++i) {
+               enum mxc_isi_buf_id buf_id = i == 0 ? MXC_ISI_BUF1
+                                          : MXC_ISI_BUF2;
+               struct mxc_isi_buffer *buf;
+               struct list_head *list;
+
+               list = i < discard ? &video->out_discard : &video->out_pending;
+               buf = list_first_entry(list, struct mxc_isi_buffer, list);
+
+               mxc_isi_channel_set_outbuf(video->pipe, buf->dma_addrs, buf_id);
+               buf->id = buf_id;
+               list_move_tail(&buf->list, &video->out_active);
+       }
+}
+
+static inline struct mxc_isi_buffer *to_isi_buffer(struct vb2_v4l2_buffer *v4l2_buf)
+{
+       return container_of(v4l2_buf, struct mxc_isi_buffer, v4l2_buf);
+}
+
+int mxc_isi_video_queue_setup(const struct v4l2_pix_format_mplane *format,
+                             const struct mxc_isi_format_info *info,
+                             unsigned int *num_buffers,
+                             unsigned int *num_planes, unsigned int sizes[])
+{
+       unsigned int i;
+
+       if (*num_planes) {
+               if (*num_planes != info->mem_planes)
+                       return -EINVAL;
+
+               for (i = 0; i < info->mem_planes; ++i) {
+                       if (sizes[i] < format->plane_fmt[i].sizeimage)
+                               return -EINVAL;
+               }
+
+               return 0;
+       }
+
+       *num_planes = info->mem_planes;
+
+       for (i = 0; i < info->mem_planes; ++i)
+               sizes[i] = format->plane_fmt[i].sizeimage;
+
+       return 0;
+}
+
+void mxc_isi_video_buffer_init(struct vb2_buffer *vb2, dma_addr_t dma_addrs[3],
+                              const struct mxc_isi_format_info *info,
+                              const struct v4l2_pix_format_mplane *pix)
+{
+       unsigned int i;
+
+       for (i = 0; i < info->mem_planes; ++i)
+               dma_addrs[i] = vb2_dma_contig_plane_dma_addr(vb2, i);
+
+       /*
+        * For single-planar pixel formats with multiple color planes, split
+        * the buffer into color planes.
+        */
+       if (info->color_planes != info->mem_planes) {
+               unsigned int size = pix->plane_fmt[0].bytesperline * pix->height;
+
+               for (i = 1; i < info->color_planes; ++i) {
+                       unsigned int vsub = i > 1 ? info->vsub : 1;
+
+                       dma_addrs[i] = dma_addrs[i - 1] + size / vsub;
+               }
+       }
+}
+
+int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2,
+                                const struct mxc_isi_format_info *info,
+                                const struct v4l2_pix_format_mplane *pix)
+{
+       unsigned int i;
+
+       for (i = 0; i < info->mem_planes; i++) {
+               unsigned long size = pix->plane_fmt[i].sizeimage;
+
+               if (vb2_plane_size(vb2, i) < size) {
+                       dev_err(isi->dev, "User buffer too small (%ld < %ld)\n",
+                               vb2_plane_size(vb2, i), size);
+                       return -EINVAL;
+               }
+
+               vb2_set_plane_payload(vb2, i, size);
+       }
+
+       return 0;
+}
+
+static int mxc_isi_vb2_queue_setup(struct vb2_queue *q,
+                                  unsigned int *num_buffers,
+                                  unsigned int *num_planes,
+                                  unsigned int sizes[],
+                                  struct device *alloc_devs[])
+{
+       struct mxc_isi_video *video = vb2_get_drv_priv(q);
+
+       return mxc_isi_video_queue_setup(&video->pix, video->fmtinfo,
+                                        num_buffers, num_planes, sizes);
+}
+
+static int mxc_isi_vb2_buffer_init(struct vb2_buffer *vb2)
+{
+       struct mxc_isi_buffer *buf = to_isi_buffer(to_vb2_v4l2_buffer(vb2));
+       struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
+
+       mxc_isi_video_buffer_init(vb2, buf->dma_addrs, video->fmtinfo,
+                                 &video->pix);
+
+       return 0;
+}
+
+static int mxc_isi_vb2_buffer_prepare(struct vb2_buffer *vb2)
+{
+       struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
+
+       return mxc_isi_video_buffer_prepare(video->pipe->isi, vb2,
+                                           video->fmtinfo, &video->pix);
+}
+
+static void mxc_isi_vb2_buffer_queue(struct vb2_buffer *vb2)
+{
+       struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2);
+       struct mxc_isi_buffer *buf = to_isi_buffer(v4l2_buf);
+       struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
+
+       spin_lock_irq(&video->buf_lock);
+       list_add_tail(&buf->list, &video->out_pending);
+       spin_unlock_irq(&video->buf_lock);
+}
+
+static void mxc_isi_video_init_channel(struct mxc_isi_video *video)
+{
+       struct mxc_isi_pipe *pipe = video->pipe;
+
+       mxc_isi_channel_get(pipe);
+
+       mutex_lock(video->ctrls.handler.lock);
+       mxc_isi_channel_set_alpha(pipe, video->ctrls.alpha);
+       mxc_isi_channel_set_flip(pipe, video->ctrls.hflip, video->ctrls.vflip);
+       mutex_unlock(video->ctrls.handler.lock);
+
+       mxc_isi_channel_set_output_format(pipe, video->fmtinfo, &video->pix);
+}
+
+static int mxc_isi_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct mxc_isi_video *video = vb2_get_drv_priv(q);
+       unsigned int i;
+       int ret;
+
+       /* Initialize the ISI channel. */
+       mxc_isi_video_init_channel(video);
+
+       spin_lock_irq(&video->buf_lock);
+
+       /* Add the discard buffers to the out_discard list. */
+       for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) {
+               struct mxc_isi_buffer *buf = &video->buf_discard[i];
+
+               list_add_tail(&buf->list, &video->out_discard);
+       }
+
+       /* Queue the first buffers. */
+       mxc_isi_video_queue_first_buffers(video);
+
+       /* Clear frame count */
+       video->frame_count = 0;
+
+       spin_unlock_irq(&video->buf_lock);
+
+       ret = mxc_isi_pipe_enable(video->pipe);
+       if (ret)
+               goto error;
+
+       return 0;
+
+error:
+       mxc_isi_channel_put(video->pipe);
+       mxc_isi_video_return_buffers(video, VB2_BUF_STATE_QUEUED);
+       return ret;
+}
+
+static void mxc_isi_vb2_stop_streaming(struct vb2_queue *q)
+{
+       struct mxc_isi_video *video = vb2_get_drv_priv(q);
+
+       mxc_isi_pipe_disable(video->pipe);
+       mxc_isi_channel_put(video->pipe);
+
+       mxc_isi_video_return_buffers(video, VB2_BUF_STATE_ERROR);
+}
+
+static const struct vb2_ops mxc_isi_vb2_qops = {
+       .queue_setup            = mxc_isi_vb2_queue_setup,
+       .buf_init               = mxc_isi_vb2_buffer_init,
+       .buf_prepare            = mxc_isi_vb2_buffer_prepare,
+       .buf_queue              = mxc_isi_vb2_buffer_queue,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+       .start_streaming        = mxc_isi_vb2_start_streaming,
+       .stop_streaming         = mxc_isi_vb2_stop_streaming,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static inline struct mxc_isi_video *ctrl_to_isi_video(struct v4l2_ctrl *ctrl)
+{
+       return container_of(ctrl->handler, struct mxc_isi_video, ctrls.handler);
+}
+
+static int mxc_isi_video_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct mxc_isi_video *video = ctrl_to_isi_video(ctrl);
+
+       switch (ctrl->id) {
+       case V4L2_CID_ALPHA_COMPONENT:
+               video->ctrls.alpha = ctrl->val;
+               break;
+       case V4L2_CID_VFLIP:
+               video->ctrls.vflip = ctrl->val;
+               break;
+       case V4L2_CID_HFLIP:
+               video->ctrls.hflip = ctrl->val;
+               break;
+       }
+
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops mxc_isi_video_ctrl_ops = {
+       .s_ctrl = mxc_isi_video_s_ctrl,
+};
+
+static int mxc_isi_video_ctrls_create(struct mxc_isi_video *video)
+{
+       struct v4l2_ctrl_handler *handler = &video->ctrls.handler;
+       int ret;
+
+       v4l2_ctrl_handler_init(handler, 3);
+
+       v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
+                         V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
+
+       v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
+                         V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+       v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
+                         V4L2_CID_HFLIP, 0, 1, 1, 0);
+
+       if (handler->error) {
+               ret = handler->error;
+               v4l2_ctrl_handler_free(handler);
+               return ret;
+       }
+
+       video->vdev.ctrl_handler = handler;
+
+       return 0;
+}
+
+static void mxc_isi_video_ctrls_delete(struct mxc_isi_video *video)
+{
+       v4l2_ctrl_handler_free(&video->ctrls.handler);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 ioctls
+ */
+
+static int mxc_isi_video_querycap(struct file *file, void *priv,
+                                 struct v4l2_capability *cap)
+{
+       strscpy(cap->driver, MXC_ISI_DRIVER_NAME, sizeof(cap->driver));
+       strscpy(cap->card, MXC_ISI_CAPTURE, sizeof(cap->card));
+
+       return 0;
+}
+
+static int mxc_isi_video_enum_fmt(struct file *file, void *priv,
+                                 struct v4l2_fmtdesc *f)
+{
+       const struct mxc_isi_format_info *fmt;
+       unsigned int index = f->index;
+       unsigned int i;
+
+       if (f->mbus_code) {
+               /*
+                * If a media bus code is specified, only enumerate formats
+                * compatible with it.
+                */
+               for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
+                       fmt = &mxc_isi_formats[i];
+                       if (fmt->mbus_code != f->mbus_code)
+                               continue;
+
+                       if (index == 0)
+                               break;
+
+                       index--;
+               }
+
+               if (i == ARRAY_SIZE(mxc_isi_formats))
+                       return -EINVAL;
+       } else {
+               /* Otherwise, enumerate all formatS. */
+               if (f->index >= ARRAY_SIZE(mxc_isi_formats))
+                       return -EINVAL;
+
+               fmt = &mxc_isi_formats[f->index];
+       }
+
+       f->pixelformat = fmt->fourcc;
+       f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE | V4L2_FMT_FLAG_CSC_YCBCR_ENC
+                |  V4L2_FMT_FLAG_CSC_QUANTIZATION | V4L2_FMT_FLAG_CSC_XFER_FUNC;
+
+       return 0;
+}
+
+static int mxc_isi_video_g_fmt(struct file *file, void *fh,
+                              struct v4l2_format *f)
+{
+       struct mxc_isi_video *video = video_drvdata(file);
+
+       f->fmt.pix_mp = video->pix;
+
+       return 0;
+}
+
+static int mxc_isi_video_try_fmt(struct file *file, void *fh,
+                                struct v4l2_format *f)
+{
+       struct mxc_isi_video *video = video_drvdata(file);
+
+       mxc_isi_format_try(video->pipe, &f->fmt.pix_mp, MXC_ISI_VIDEO_CAP);
+       return 0;
+}
+
+static int mxc_isi_video_s_fmt(struct file *file, void *priv,
+                              struct v4l2_format *f)
+{
+       struct mxc_isi_video *video = video_drvdata(file);
+       struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+
+       if (vb2_is_busy(&video->vb2_q))
+               return -EBUSY;
+
+       video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP);
+       video->pix = *pix;
+
+       return 0;
+}
+
+static int mxc_isi_video_streamon(struct file *file, void *priv,
+                                 enum v4l2_buf_type type)
+{
+       struct mxc_isi_video *video = video_drvdata(file);
+       struct media_device *mdev = &video->pipe->isi->media_dev;
+       struct media_pipeline *pipe;
+       int ret;
+
+       if (vb2_queue_is_busy(&video->vb2_q, file))
+               return -EBUSY;
+
+       /*
+        * Get a pipeline for the video node and start it. This must be done
+        * here and not in the queue .start_streaming() handler, so that
+        * pipeline start errors can be reported from VIDIOC_STREAMON and not
+        * delayed until subsequent VIDIOC_QBUF calls.
+        */
+       mutex_lock(&mdev->graph_mutex);
+
+       ret = mxc_isi_pipe_acquire(video->pipe, &mxc_isi_video_frame_write_done);
+       if (ret) {
+               mutex_unlock(&mdev->graph_mutex);
+               return ret;
+       }
+
+       pipe = media_entity_pipeline(&video->vdev.entity) ? : &video->pipe->pipe;
+
+       ret = __video_device_pipeline_start(&video->vdev, pipe);
+       if (ret) {
+               mutex_unlock(&mdev->graph_mutex);
+               goto err_release;
+       }
+
+       mutex_unlock(&mdev->graph_mutex);
+
+       /* Verify that the video format matches the output of the subdev. */
+       ret = mxc_isi_video_validate_format(video);
+       if (ret)
+               goto err_stop;
+
+       /* Allocate buffers for discard operation. */
+       ret = mxc_isi_video_alloc_discard_buffers(video);
+       if (ret)
+               goto err_stop;
+
+       ret = vb2_streamon(&video->vb2_q, type);
+       if (ret)
+               goto err_free;
+
+       video->is_streaming = true;
+
+       return 0;
+
+err_free:
+       mxc_isi_video_free_discard_buffers(video);
+err_stop:
+       video_device_pipeline_stop(&video->vdev);
+err_release:
+       mxc_isi_pipe_release(video->pipe);
+       return ret;
+}
+
+static void mxc_isi_video_cleanup_streaming(struct mxc_isi_video *video)
+{
+       lockdep_assert_held(&video->lock);
+
+       if (!video->is_streaming)
+               return;
+
+       mxc_isi_video_free_discard_buffers(video);
+       video_device_pipeline_stop(&video->vdev);
+       mxc_isi_pipe_release(video->pipe);
+
+       video->is_streaming = false;
+}
+
+static int mxc_isi_video_streamoff(struct file *file, void *priv,
+                                  enum v4l2_buf_type type)
+{
+       struct mxc_isi_video *video = video_drvdata(file);
+       int ret;
+
+       ret = vb2_ioctl_streamoff(file, priv, type);
+       if (ret)
+               return ret;
+
+       mxc_isi_video_cleanup_streaming(video);
+
+       return 0;
+}
+
+static int mxc_isi_video_enum_framesizes(struct file *file, void *priv,
+                                        struct v4l2_frmsizeenum *fsize)
+{
+       struct mxc_isi_video *video = video_drvdata(file);
+       const struct mxc_isi_format_info *info;
+       unsigned int max_width;
+       unsigned int h_align;
+       unsigned int v_align;
+
+       if (fsize->index)
+               return -EINVAL;
+
+       info = mxc_isi_format_by_fourcc(fsize->pixel_format, MXC_ISI_VIDEO_CAP);
+       if (!info)
+               return -EINVAL;
+
+       h_align = max_t(unsigned int, info->hsub, 1);
+       v_align = max_t(unsigned int, info->vsub, 1);
+
+       max_width = video->pipe->id == video->pipe->isi->pdata->num_channels - 1
+                 ? MXC_ISI_MAX_WIDTH_UNCHAINED
+                 : MXC_ISI_MAX_WIDTH_CHAINED;
+
+       fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+       fsize->stepwise.min_width = ALIGN(MXC_ISI_MIN_WIDTH, h_align);
+       fsize->stepwise.min_height = ALIGN(MXC_ISI_MIN_HEIGHT, v_align);
+       fsize->stepwise.max_width = ALIGN_DOWN(max_width, h_align);
+       fsize->stepwise.max_height = ALIGN_DOWN(MXC_ISI_MAX_HEIGHT, v_align);
+       fsize->stepwise.step_width = h_align;
+       fsize->stepwise.step_height = v_align;
+
+       /*
+        * The width can be further restricted due to line buffer sharing
+        * between pipelines when scaling, but we have no way to know here if
+        * the scaler will be used.
+        */
+
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops mxc_isi_video_ioctl_ops = {
+       .vidioc_querycap                = mxc_isi_video_querycap,
+
+       .vidioc_enum_fmt_vid_cap        = mxc_isi_video_enum_fmt,
+       .vidioc_try_fmt_vid_cap_mplane  = mxc_isi_video_try_fmt,
+       .vidioc_s_fmt_vid_cap_mplane    = mxc_isi_video_s_fmt,
+       .vidioc_g_fmt_vid_cap_mplane    = mxc_isi_video_g_fmt,
+
+       .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
+       .vidioc_querybuf                = vb2_ioctl_querybuf,
+       .vidioc_qbuf                    = vb2_ioctl_qbuf,
+       .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
+       .vidioc_expbuf                  = vb2_ioctl_expbuf,
+       .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
+       .vidioc_create_bufs             = vb2_ioctl_create_bufs,
+
+       .vidioc_streamon                = mxc_isi_video_streamon,
+       .vidioc_streamoff               = mxc_isi_video_streamoff,
+
+       .vidioc_enum_framesizes         = mxc_isi_video_enum_framesizes,
+
+       .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
+};
+
+/* -----------------------------------------------------------------------------
+ * Video device file operations
+ */
+
+static int mxc_isi_video_open(struct file *file)
+{
+       struct mxc_isi_video *video = video_drvdata(file);
+       int ret;
+
+       ret = v4l2_fh_open(file);
+       if (ret)
+               return ret;
+
+       ret = pm_runtime_resume_and_get(video->pipe->isi->dev);
+       if (ret) {
+               v4l2_fh_release(file);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int mxc_isi_video_release(struct file *file)
+{
+       struct mxc_isi_video *video = video_drvdata(file);
+       int ret;
+
+       ret = vb2_fop_release(file);
+       if (ret)
+               dev_err(video->pipe->isi->dev, "%s fail\n", __func__);
+
+       mutex_lock(&video->lock);
+       mxc_isi_video_cleanup_streaming(video);
+       mutex_unlock(&video->lock);
+
+       pm_runtime_put(video->pipe->isi->dev);
+       return ret;
+}
+
+static const struct v4l2_file_operations mxc_isi_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = mxc_isi_video_open,
+       .release        = mxc_isi_video_release,
+       .poll           = vb2_fop_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = vb2_fop_mmap,
+};
+
+/* -----------------------------------------------------------------------------
+ * Suspend & resume
+ */
+
+void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe)
+{
+       struct mxc_isi_video *video = &pipe->video;
+
+       if (!video->is_streaming)
+               return;
+
+       mxc_isi_pipe_disable(pipe);
+       mxc_isi_channel_put(pipe);
+
+       spin_lock_irq(&video->buf_lock);
+
+       /*
+        * Move the active buffers back to the pending or discard list. We must
+        * iterate the active list backward and move the buffers to the head of
+        * the pending list to preserve the buffer queueing order.
+        */
+       while (!list_empty(&video->out_active)) {
+               struct mxc_isi_buffer *buf =
+                       list_last_entry(&video->out_active,
+                                       struct mxc_isi_buffer, list);
+
+               if (buf->discard)
+                       list_move(&buf->list, &video->out_discard);
+               else
+                       list_move(&buf->list, &video->out_pending);
+       }
+
+       spin_unlock_irq(&video->buf_lock);
+}
+
+int mxc_isi_video_resume(struct mxc_isi_pipe *pipe)
+{
+       struct mxc_isi_video *video = &pipe->video;
+
+       if (!video->is_streaming)
+               return 0;
+
+       mxc_isi_video_init_channel(video);
+
+       spin_lock_irq(&video->buf_lock);
+       mxc_isi_video_queue_first_buffers(video);
+       spin_unlock_irq(&video->buf_lock);
+
+       return mxc_isi_pipe_enable(pipe);
+}
+
+/* -----------------------------------------------------------------------------
+ * Registration
+ */
+
+int mxc_isi_video_register(struct mxc_isi_pipe *pipe,
+                          struct v4l2_device *v4l2_dev)
+{
+       struct mxc_isi_video *video = &pipe->video;
+       struct v4l2_pix_format_mplane *pix = &video->pix;
+       struct video_device *vdev = &video->vdev;
+       struct vb2_queue *q = &video->vb2_q;
+       int ret = -ENOMEM;
+
+       video->pipe = pipe;
+
+       mutex_init(&video->lock);
+       spin_lock_init(&video->buf_lock);
+
+       pix->width = MXC_ISI_DEF_WIDTH;
+       pix->height = MXC_ISI_DEF_HEIGHT;
+       pix->pixelformat = MXC_ISI_DEF_PIXEL_FORMAT;
+       pix->colorspace = MXC_ISI_DEF_COLOR_SPACE;
+       pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC;
+       pix->quantization = MXC_ISI_DEF_QUANTIZATION;
+       pix->xfer_func = MXC_ISI_DEF_XFER_FUNC;
+       video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP);
+
+       memset(vdev, 0, sizeof(*vdev));
+       snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.%d.capture", pipe->id);
+
+       vdev->fops      = &mxc_isi_video_fops;
+       vdev->ioctl_ops = &mxc_isi_video_ioctl_ops;
+       vdev->v4l2_dev  = v4l2_dev;
+       vdev->minor     = -1;
+       vdev->release   = video_device_release_empty;
+       vdev->queue     = q;
+       vdev->lock      = &video->lock;
+
+       vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE
+                         | V4L2_CAP_IO_MC;
+       video_set_drvdata(vdev, video);
+
+       INIT_LIST_HEAD(&video->out_pending);
+       INIT_LIST_HEAD(&video->out_active);
+       INIT_LIST_HEAD(&video->out_discard);
+
+       memset(q, 0, sizeof(*q));
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       q->io_modes = VB2_MMAP | VB2_DMABUF;
+       q->drv_priv = video;
+       q->ops = &mxc_isi_vb2_qops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->buf_struct_size = sizeof(struct mxc_isi_buffer);
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       q->min_buffers_needed = 2;
+       q->lock = &video->lock;
+       q->dev = pipe->isi->dev;
+
+       ret = vb2_queue_init(q);
+       if (ret)
+               goto err_free_ctx;
+
+       video->pad.flags = MEDIA_PAD_FL_SINK;
+       vdev->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
+       ret = media_entity_pads_init(&vdev->entity, 1, &video->pad);
+       if (ret)
+               goto err_free_ctx;
+
+       ret = mxc_isi_video_ctrls_create(video);
+       if (ret)
+               goto err_me_cleanup;
+
+       ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+       if (ret)
+               goto err_ctrl_free;
+
+       ret = media_create_pad_link(&pipe->sd.entity,
+                                   MXC_ISI_PIPE_PAD_SOURCE,
+                                   &vdev->entity, 0,
+                                   MEDIA_LNK_FL_IMMUTABLE |
+                                   MEDIA_LNK_FL_ENABLED);
+       if (ret)
+               goto err_video_unreg;
+
+       return 0;
+
+err_video_unreg:
+       video_unregister_device(vdev);
+err_ctrl_free:
+       mxc_isi_video_ctrls_delete(video);
+err_me_cleanup:
+       media_entity_cleanup(&vdev->entity);
+err_free_ctx:
+       return ret;
+}
+
+void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe)
+{
+       struct mxc_isi_video *video = &pipe->video;
+       struct video_device *vdev = &video->vdev;
+
+       mutex_lock(&video->lock);
+
+       if (video_is_registered(vdev)) {
+               video_unregister_device(vdev);
+               mxc_isi_video_ctrls_delete(video);
+               media_entity_cleanup(&vdev->entity);
+       }
+
+       mutex_unlock(&video->lock);
+}
index 3ce84d0f078cdae4b1bb342262ab539fb4cd9576..023ed40c6b08362499ab57fb257edc88cbfa8124 100644 (file)
@@ -888,7 +888,7 @@ unreg_dev:
        return ret;
 }
 
-static int emmaprp_remove(struct platform_device *pdev)
+static void emmaprp_remove(struct platform_device *pdev)
 {
        struct emmaprp_dev *pcdev = platform_get_drvdata(pdev);
 
@@ -898,13 +898,11 @@ static int emmaprp_remove(struct platform_device *pdev)
        v4l2_m2m_release(pcdev->m2m_dev);
        v4l2_device_unregister(&pcdev->v4l2_dev);
        mutex_destroy(&pcdev->dev_mutex);
-
-       return 0;
 }
 
 static struct platform_driver emmaprp_pdrv = {
        .probe          = emmaprp_probe,
-       .remove         = emmaprp_remove,
+       .remove_new     = emmaprp_remove,
        .driver         = {
                .name   = MEM2MEM_NAME,
        },
index 2031bde13a939027a96b09354f3ad7536018f894..0f8ac29d038db8562fcefb953113b023c593c69e 100644 (file)
@@ -334,13 +334,14 @@ static const struct csid_format csid_formats[] = {
        },
 };
 
-static void csid_configure_stream(struct csid_device *csid, u8 enable)
+static void __csid_configure_stream(struct csid_device *csid, u8 enable, u8 vc)
 {
        struct csid_testgen_config *tg = &csid->testgen;
        u32 val;
        u32 phy_sel = 0;
        u8 lane_cnt = csid->phy.lane_cnt;
-       struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_SRC];
+       /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
+       struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
        const struct csid_format *format = csid_get_fmt_entry(csid->formats, csid->nformats,
                                                              input_format->code);
 
@@ -351,8 +352,7 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable)
                phy_sel = csid->phy.csiphy_id;
 
        if (enable) {
-               u8 vc = 0; /* Virtual Channel 0 */
-               u8 dt_id = vc * 4;
+               u8 dt_id = vc;
 
                if (tg->enabled) {
                        /* Config Test Generator */
@@ -395,42 +395,42 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable)
                val |= format->data_type << RDI_CFG0_DATA_TYPE;
                val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
                val |= dt_id << RDI_CFG0_DT_ID;
-               writel_relaxed(val, csid->base + CSID_RDI_CFG0(0));
+               writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
 
                /* CSID_TIMESTAMP_STB_POST_IRQ */
                val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
-               writel_relaxed(val, csid->base + CSID_RDI_CFG1(0));
+               writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc));
 
                val = 1;
-               writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(0));
+               writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
 
                val = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(0));
+               writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc));
 
                val = 1;
-               writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(0));
+               writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
 
                val = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(0));
+               writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
 
                val = 1;
-               writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(0));
+               writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc));
 
                val = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(0));
+               writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc));
 
                val = 1;
-               writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(0));
+               writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc));
 
                val = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(0));
+               writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc));
 
                val = 0;
-               writel_relaxed(val, csid->base + CSID_RDI_CTRL(0));
+               writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
 
-               val = readl_relaxed(csid->base + CSID_RDI_CFG0(0));
+               val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc));
                val |=  1 << RDI_CFG0_ENABLE;
-               writel_relaxed(val, csid->base + CSID_RDI_CFG0(0));
+               writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
        }
 
        if (tg->enabled) {
@@ -456,7 +456,16 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable)
                val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
        else
                val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
-       writel_relaxed(val, csid->base + CSID_RDI_CTRL(0));
+       writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
+}
+
+static void csid_configure_stream(struct csid_device *csid, u8 enable)
+{
+       u8 i;
+       /* Loop through all enabled VCs and configure stream for each */
+       for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
+               if (csid->phy.en_vc & BIT(i))
+                       __csid_configure_stream(csid, enable, i);
 }
 
 static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
@@ -502,6 +511,7 @@ static irqreturn_t csid_isr(int irq, void *dev)
        struct csid_device *csid = dev;
        u32 val;
        u8 reset_done;
+       int i;
 
        val = readl_relaxed(csid->base + CSID_TOP_IRQ_STATUS);
        writel_relaxed(val, csid->base + CSID_TOP_IRQ_CLEAR);
@@ -510,8 +520,12 @@ static irqreturn_t csid_isr(int irq, void *dev)
        val = readl_relaxed(csid->base + CSID_CSI2_RX_IRQ_STATUS);
        writel_relaxed(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);
 
-       val = readl_relaxed(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(0));
-       writel_relaxed(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(0));
+       /* Read and clear IRQ status for each enabled RDI channel */
+       for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
+               if (csid->phy.en_vc & BIT(i)) {
+                       val = readl_relaxed(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i));
+                       writel_relaxed(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i));
+               }
 
        val = 1 << IRQ_CMD_CLEAR;
        writel_relaxed(val, csid->base + CSID_IRQ_CMD);
index 88f188e0f7501be50bcd372f3cc5a9c1693bc504..6360314f04a636f1addd249d84f986f0b73fe703 100644 (file)
@@ -196,6 +196,8 @@ static int csid_set_power(struct v4l2_subdev *sd, int on)
                        return ret;
                }
 
+               csid->phy.need_vc_update = true;
+
                enable_irq(csid->irq);
 
                ret = csid->ops->reset(csid);
@@ -249,7 +251,10 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable)
                        return -ENOLINK;
        }
 
-       csid->ops->configure_stream(csid, enable);
+       if (csid->phy.need_vc_update) {
+               csid->ops->configure_stream(csid, enable);
+               csid->phy.need_vc_update = false;
+       }
 
        return 0;
 }
@@ -460,6 +465,7 @@ static int csid_set_format(struct v4l2_subdev *sd,
 {
        struct csid_device *csid = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
+       int i;
 
        format = __csid_get_format(csid, sd_state, fmt->pad, fmt->which);
        if (format == NULL)
@@ -468,14 +474,14 @@ static int csid_set_format(struct v4l2_subdev *sd,
        csid_try_format(csid, sd_state, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
-       /* Propagate the format from sink to source */
+       /* Propagate the format from sink to source pads */
        if (fmt->pad == MSM_CSID_PAD_SINK) {
-               format = __csid_get_format(csid, sd_state, MSM_CSID_PAD_SRC,
-                                          fmt->which);
+               for (i = MSM_CSID_PAD_FIRST_SRC; i < MSM_CSID_PADS_NUM; ++i) {
+                       format = __csid_get_format(csid, sd_state, i, fmt->which);
 
-               *format = fmt->format;
-               csid_try_format(csid, sd_state, MSM_CSID_PAD_SRC, format,
-                               fmt->which);
+                       *format = fmt->format;
+                       csid_try_format(csid, sd_state, i, format, fmt->which);
+               }
        }
 
        return 0;
@@ -738,7 +744,6 @@ static int csid_link_setup(struct media_entity *entity,
                struct csid_device *csid;
                struct csiphy_device *csiphy;
                struct csiphy_lanes_cfg *lane_cfg;
-               struct v4l2_subdev_format format = { 0 };
 
                sd = media_entity_to_v4l2_subdev(entity);
                csid = v4l2_get_subdevdata(sd);
@@ -761,11 +766,22 @@ static int csid_link_setup(struct media_entity *entity,
                lane_cfg = &csiphy->cfg.csi2->lane_cfg;
                csid->phy.lane_cnt = lane_cfg->num_data;
                csid->phy.lane_assign = csid_get_lane_assign(lane_cfg);
+       }
+       /* Decide which virtual channels to enable based on which source pads are enabled */
+       if (local->flags & MEDIA_PAD_FL_SOURCE) {
+               struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+               struct csid_device *csid = v4l2_get_subdevdata(sd);
+               struct device *dev = csid->camss->dev;
+
+               if (flags & MEDIA_LNK_FL_ENABLED)
+                       csid->phy.en_vc |= BIT(local->index - 1);
+               else
+                       csid->phy.en_vc &= ~BIT(local->index - 1);
 
-               /* Reset format on source pad to sink pad format */
-               format.pad = MSM_CSID_PAD_SRC;
-               format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-               csid_set_format(&csid->subdev, NULL, &format);
+               csid->phy.need_vc_update = true;
+
+               dev_dbg(dev, "%s: Enabled CSID virtual channels mask 0x%x\n",
+                       __func__, csid->phy.en_vc);
        }
 
        return 0;
@@ -816,6 +832,7 @@ int msm_csid_register_entity(struct csid_device *csid,
        struct v4l2_subdev *sd = &csid->subdev;
        struct media_pad *pads = csid->pads;
        struct device *dev = csid->camss->dev;
+       int i;
        int ret;
 
        v4l2_subdev_init(sd, &csid_v4l2_ops);
@@ -852,7 +869,8 @@ int msm_csid_register_entity(struct csid_device *csid,
        }
 
        pads[MSM_CSID_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-       pads[MSM_CSID_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
+       for (i = MSM_CSID_PAD_FIRST_SRC; i < MSM_CSID_PADS_NUM; ++i)
+               pads[i].flags = MEDIA_PAD_FL_SOURCE;
 
        sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
        sd->entity.ops = &csid_media_ops;
index f06040e44c515e14bd0fec6592985c5d207eb2f9..d4b48432a0973b2e2eda671871ce2a4fd03182e9 100644 (file)
 #include <media/v4l2-subdev.h>
 
 #define MSM_CSID_PAD_SINK 0
-#define MSM_CSID_PAD_SRC 1
-#define MSM_CSID_PADS_NUM 2
+#define MSM_CSID_PAD_FIRST_SRC 1
+#define MSM_CSID_PADS_NUM 5
+
+#define MSM_CSID_PAD_SRC (MSM_CSID_PAD_FIRST_SRC)
+
+/* CSID hardware can demultiplex up to 4 outputs */
+#define MSM_CSID_MAX_SRC_STREAMS       4
 
 #define DATA_TYPE_EMBEDDED_DATA_8BIT   0x12
 #define DATA_TYPE_YUV420_8BIT          0x18
@@ -81,6 +86,8 @@ struct csid_phy_config {
        u8 csiphy_id;
        u8 lane_cnt;
        u32 lane_assign;
+       u32 en_vc;
+       u8 need_vc_update;
 };
 
 struct csid_device;
index 8e506a805d11917811ca40e72210f21359cb4970..02494c89da91c8db750df58f95f24050eec15238 100644 (file)
@@ -409,7 +409,7 @@ static int vfe_get_output(struct vfe_line *line)
        spin_lock_irqsave(&vfe->output_lock, flags);
 
        output = &line->output;
-       if (output->state != VFE_OUTPUT_OFF) {
+       if (output->state > VFE_OUTPUT_RESERVED) {
                dev_err(vfe->camss->dev, "Output is running\n");
                goto error;
        }
@@ -462,7 +462,7 @@ static int vfe_enable_output(struct vfe_line *line)
 
        ops->reg_update_clear(vfe, line->id);
 
-       if (output->state != VFE_OUTPUT_OFF) {
+       if (output->state > VFE_OUTPUT_RESERVED) {
                dev_err(vfe->camss->dev, "Output is not in reserved state %d\n",
                        output->state);
                spin_unlock_irqrestore(&vfe->output_lock, flags);
index 3aa962b5663bc49925c5bb8a949127b147df85cd..f70aad2e8c2378fb7e07b1e8e374a941c3e6a1b7 100644 (file)
@@ -94,6 +94,8 @@ static inline int bus_irq_mask_0_comp_done(struct vfe_device *vfe, int n)
 #define RDI_WM(n)                      ((IS_LITE ? 0 : 23) + (n))
 #define RDI_COMP_GROUP(n)              ((IS_LITE ? 0 : 11) + (n))
 
+#define MAX_VFE_OUTPUT_LINES   4
+
 static u32 vfe_hw_version(struct vfe_device *vfe)
 {
        u32 hw_version = readl_relaxed(vfe->base + VFE_HW_VERSION);
@@ -171,12 +173,26 @@ static inline void vfe_reg_update_clear(struct vfe_device *vfe,
 
 static void vfe_enable_irq_common(struct vfe_device *vfe)
 {
-       /* enable only the IRQs used: rup and comp_done irqs for RDI0 */
+       /* enable reset ack IRQ and top BUS status IRQ */
        writel_relaxed(IRQ_MASK_0_RESET_ACK | IRQ_MASK_0_BUS_TOP_IRQ,
                       vfe->base + VFE_IRQ_MASK(0));
-       writel_relaxed(BUS_IRQ_MASK_0_RDI_RUP(vfe, 0) |
-                      BUS_IRQ_MASK_0_COMP_DONE(vfe, RDI_COMP_GROUP(0)),
-                      vfe->base + VFE_BUS_IRQ_MASK(0));
+}
+
+static void vfe_enable_lines_irq(struct vfe_device *vfe)
+{
+       int i;
+       u32 bus_irq_mask = 0;
+
+       for (i = 0; i < MAX_VFE_OUTPUT_LINES; i++) {
+               /* Enable IRQ for newly added lines, but also keep already running lines's IRQ */
+               if (vfe->line[i].output.state == VFE_OUTPUT_RESERVED ||
+                   vfe->line[i].output.state == VFE_OUTPUT_ON) {
+                       bus_irq_mask |= BUS_IRQ_MASK_0_RDI_RUP(vfe, i)
+                                       | BUS_IRQ_MASK_0_COMP_DONE(vfe, RDI_COMP_GROUP(i));
+                       }
+       }
+
+       writel_relaxed(bus_irq_mask, vfe->base + VFE_BUS_IRQ_MASK(0));
 }
 
 static void vfe_isr_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id);
@@ -193,6 +209,7 @@ static irqreturn_t vfe_isr(int irq, void *dev)
 {
        struct vfe_device *vfe = dev;
        u32 status;
+       int i;
 
        status = readl_relaxed(vfe->base + VFE_IRQ_STATUS(0));
        writel_relaxed(status, vfe->base + VFE_IRQ_CLEAR(0));
@@ -207,11 +224,14 @@ static irqreturn_t vfe_isr(int irq, void *dev)
                writel_relaxed(status, vfe->base + VFE_BUS_IRQ_CLEAR(0));
                writel_relaxed(1, vfe->base + VFE_BUS_IRQ_CLEAR_GLOBAL);
 
-               if (status & BUS_IRQ_MASK_0_RDI_RUP(vfe, 0))
-                       vfe_isr_reg_update(vfe, 0);
+               /* Loop through all WMs IRQs */
+               for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++) {
+                       if (status & BUS_IRQ_MASK_0_RDI_RUP(vfe, i))
+                               vfe_isr_reg_update(vfe, i);
 
-               if (status & BUS_IRQ_MASK_0_COMP_DONE(vfe, RDI_COMP_GROUP(0)))
-                       vfe_isr_wm_done(vfe, 0);
+                       if (status & BUS_IRQ_MASK_0_COMP_DONE(vfe, RDI_COMP_GROUP(i)))
+                               vfe_isr_wm_done(vfe, i);
+               }
        }
 
        return IRQ_HANDLED;
@@ -234,24 +254,23 @@ static int vfe_get_output(struct vfe_line *line)
        struct vfe_device *vfe = to_vfe(line);
        struct vfe_output *output;
        unsigned long flags;
-       int wm_idx;
 
        spin_lock_irqsave(&vfe->output_lock, flags);
 
        output = &line->output;
-       if (output->state != VFE_OUTPUT_OFF) {
+       if (output->state > VFE_OUTPUT_RESERVED) {
                dev_err(vfe->camss->dev, "Output is running\n");
                goto error;
        }
 
        output->wm_num = 1;
 
-       wm_idx = vfe_reserve_wm(vfe, line->id);
-       if (wm_idx < 0) {
-               dev_err(vfe->camss->dev, "Can not reserve wm\n");
-               goto error_get_wm;
-       }
-       output->wm_idx[0] = wm_idx;
+       /* Correspondence between VFE line number and WM number.
+        * line 0 -> RDI 0, line 1 -> RDI1, line 2 -> RDI2, line 3 -> PIX/RDI3
+        * Note this 1:1 mapping will not work for PIX streams.
+        */
+       output->wm_idx[0] = line->id;
+       vfe->wm_output_map[line->id] = line->id;
 
        output->drop_update_idx = 0;
 
@@ -259,11 +278,9 @@ static int vfe_get_output(struct vfe_line *line)
 
        return 0;
 
-error_get_wm:
-       vfe_release_wm(vfe, output->wm_idx[0]);
-       output->state = VFE_OUTPUT_OFF;
 error:
        spin_unlock_irqrestore(&vfe->output_lock, flags);
+       output->state = VFE_OUTPUT_OFF;
 
        return -EINVAL;
 }
@@ -279,7 +296,7 @@ static int vfe_enable_output(struct vfe_line *line)
 
        vfe_reg_update_clear(vfe, line->id);
 
-       if (output->state != VFE_OUTPUT_OFF) {
+       if (output->state > VFE_OUTPUT_RESERVED) {
                dev_err(vfe->camss->dev, "Output is not in reserved state %d\n",
                        output->state);
                spin_unlock_irqrestore(&vfe->output_lock, flags);
@@ -360,6 +377,8 @@ static int vfe_enable(struct vfe_line *line)
 
        vfe->stream_count++;
 
+       vfe_enable_lines_irq(vfe);
+
        mutex_unlock(&vfe->stream_lock);
 
        ret = vfe_get_output(line);
@@ -566,7 +585,7 @@ static const struct camss_video_ops vfe_video_ops_480 = {
 static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe)
 {
        vfe->video_ops = vfe_video_ops_480;
-       vfe->line_num = 1;
+       vfe->line_num = MAX_VFE_OUTPUT_LINES;
 }
 
 const struct vfe_hw_ops vfe_ops_480 = {
index 4fd265d01883468f1d1d6525c7b391b357c8b6d2..239d3d4ac66612a462f013a9306bdb0490b2f7f1 100644 (file)
@@ -194,7 +194,7 @@ static int vfe_enable_output(struct vfe_line *line)
 
        ops->reg_update_clear(vfe, line->id);
 
-       if (output->state != VFE_OUTPUT_RESERVED) {
+       if (output->state > VFE_OUTPUT_RESERVED) {
                dev_err(vfe->camss->dev, "Output is not in reserved state %d\n", output->state);
                spin_unlock_irqrestore(&vfe->output_lock, flags);
                return -EINVAL;
@@ -289,7 +289,7 @@ static int vfe_get_output(struct vfe_line *line)
        spin_lock_irqsave(&vfe->output_lock, flags);
 
        output = &line->output;
-       if (output->state != VFE_OUTPUT_OFF) {
+       if (output->state > VFE_OUTPUT_RESERVED) {
                dev_err(vfe->camss->dev, "Output is running\n");
                goto error;
        }
index a26e4a5d87b6bb7d03340994cbcac38ec5c68c21..e0832f3f4f25c046049e51b9fdfde932ad30d0db 100644 (file)
@@ -740,6 +740,7 @@ static int vfe_set_stream(struct v4l2_subdev *sd, int enable)
        int ret;
 
        if (enable) {
+               line->output.state = VFE_OUTPUT_RESERVED;
                ret = vfe->ops->vfe_enable(line);
                if (ret < 0)
                        dev_err(vfe->camss->dev,
index 41deda232e4a105e07bd48c5354cb803e683a95d..898f32177b12a5cc2b6aa6a65b9c7f1b8719bd45 100644 (file)
@@ -342,7 +342,9 @@ static struct v4l2_subdev *video_remote_subdev(struct camss_video *video,
 static int video_get_subdev_format(struct camss_video *video,
                                   struct v4l2_format *format)
 {
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        u32 pad;
        int ret;
@@ -351,8 +353,8 @@ static int video_get_subdev_format(struct camss_video *video,
        if (subdev == NULL)
                return -EPIPE;
 
+       memset(&fmt, 0, sizeof(fmt));
        fmt.pad = pad;
-       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        if (ret)
@@ -493,9 +495,11 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count)
        struct v4l2_subdev *subdev;
        int ret;
 
-       ret = video_device_pipeline_start(vdev, &video->pipe);
-       if (ret < 0)
+       ret = video_device_pipeline_alloc_start(vdev);
+       if (ret < 0) {
+               dev_err(video->camss->dev, "Failed to start media pipeline: %d\n", ret);
                goto flush_buffers;
+       }
 
        ret = video_check_format(video);
        if (ret < 0)
@@ -537,6 +541,7 @@ static void video_stop_streaming(struct vb2_queue *q)
        struct media_entity *entity;
        struct media_pad *pad;
        struct v4l2_subdev *subdev;
+       int ret;
 
        entity = &vdev->entity;
        while (1) {
@@ -551,7 +556,18 @@ static void video_stop_streaming(struct vb2_queue *q)
                entity = pad->entity;
                subdev = media_entity_to_v4l2_subdev(entity);
 
-               v4l2_subdev_call(subdev, video, s_stream, 0);
+               ret = v4l2_subdev_call(subdev, video, s_stream, 0);
+
+               if (entity->use_count > 1) {
+                       /* Don't stop if other instances of the pipeline are still running */
+                       dev_dbg(video->camss->dev, "Video pipeline still used, don't stop streaming.\n");
+                       return;
+               }
+
+               if (ret) {
+                       dev_err(video->camss->dev, "Video pipeline stop failed: %d\n", ret);
+                       return;
+               }
        }
 
        video_device_pipeline_stop(vdev);
index 9cda284f1e71f0c99311e81bf1b665c964594d22..1ef26aea3eae629f52ed862cef722ead6e0e80a3 100644 (file)
@@ -1320,7 +1320,7 @@ static int camss_register_entities(struct camss *camss)
                                        struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev;
 
                                        ret = media_create_pad_link(&csid->entity,
-                                                                   MSM_CSID_PAD_SRC,
+                                                                   MSM_CSID_PAD_FIRST_SRC + j,
                                                                    &vfe->entity,
                                                                    MSM_VFE_PAD_SINK,
                                                                    0);
@@ -1725,7 +1725,7 @@ void camss_delete(struct camss *camss)
  *
  * Always returns 0.
  */
-static int camss_remove(struct platform_device *pdev)
+static void camss_remove(struct platform_device *pdev)
 {
        struct camss *camss = platform_get_drvdata(pdev);
 
@@ -1735,8 +1735,6 @@ static int camss_remove(struct platform_device *pdev)
 
        if (atomic_read(&camss->ref_count) == 0)
                camss_delete(camss);
-
-       return 0;
 }
 
 static const struct of_device_id camss_dt_match[] = {
@@ -1798,7 +1796,7 @@ static const struct dev_pm_ops camss_pm_ops = {
 
 static struct platform_driver qcom_camss_driver = {
        .probe = camss_probe,
-       .remove = camss_remove,
+       .remove_new = camss_remove,
        .driver = {
                .name = "qcom-camss",
                .of_match_table = camss_dt_match,
index 990a1519f968df9b93ea7a1ba6a5f0234ee05775..2ae867cb4c48bc83bb969e4ce9660212cba3d468 100644 (file)
@@ -416,7 +416,7 @@ err_core_put:
        return ret;
 }
 
-static int venus_remove(struct platform_device *pdev)
+static void venus_remove(struct platform_device *pdev)
 {
        struct venus_core *core = platform_get_drvdata(pdev);
        const struct venus_pm_ops *pm_ops = core->pm_ops;
@@ -447,8 +447,6 @@ static int venus_remove(struct platform_device *pdev)
        mutex_destroy(&core->pm_lock);
        mutex_destroy(&core->lock);
        venus_dbgfs_deinit(core);
-
-       return ret;
 }
 
 static void venus_core_shutdown(struct platform_device *pdev)
@@ -891,7 +889,7 @@ MODULE_DEVICE_TABLE(of, venus_dt_match);
 
 static struct platform_driver qcom_venus_driver = {
        .probe = venus_probe,
-       .remove = venus_remove,
+       .remove_new = venus_remove,
        .driver = {
                .name = "qcom-venus",
                .of_match_table = venus_dt_match,
index 32551c2602a98b5886bc42a4c1897b2dda2f35da..4f81669986ba7f3ff0a6a09079f619311629ae20 100644 (file)
@@ -107,7 +107,6 @@ struct venus_format {
  * @vcodec1_clks: an array of vcodec1 struct clk pointers
  * @video_path: an interconnect handle to video to/from memory path
  * @cpucfg_path: an interconnect handle to cpu configuration path
- * @opp_table: an device OPP table handle
  * @has_opp_table: does OPP table exist
  * @pmdomains: an array of pmdomains struct device pointers
  * @opp_dl_venus: an device-link for device OPP
@@ -317,6 +316,14 @@ enum venus_dec_state {
        VENUS_DEC_STATE_DRC             = 7,
 };
 
+enum venus_enc_state {
+       VENUS_ENC_STATE_DEINIT          = 0,
+       VENUS_ENC_STATE_INIT            = 1,
+       VENUS_ENC_STATE_ENCODING        = 2,
+       VENUS_ENC_STATE_STOPPED         = 3,
+       VENUS_ENC_STATE_DRAIN           = 4,
+};
+
 struct venus_ts_metadata {
        bool used;
        u64 ts_ns;
@@ -428,6 +435,7 @@ struct venus_inst {
        u8 quantization;
        u8 xfer_func;
        enum venus_dec_state codec_state;
+       enum venus_enc_state enc_state;
        wait_queue_head_t reconf_wait;
        unsigned int subscriptions;
        int buf_count;
index ab6a29ffc81e2d79b8e96fd8ec9c83ba6d209149..a2ceab7f9ddbfc8f076b75d6cdaa2da790b0797b 100644 (file)
@@ -988,8 +988,8 @@ static u32 get_framesize_raw_p010(u32 width, u32 height)
 {
        u32 y_plane, uv_plane, y_stride, uv_stride, y_sclines, uv_sclines;
 
-       y_stride = ALIGN(width * 2, 256);
-       uv_stride = ALIGN(width * 2, 256);
+       y_stride = ALIGN(width * 2, 128);
+       uv_stride = ALIGN(width * 2, 128);
        y_sclines = ALIGN(height, 32);
        uv_sclines = ALIGN((height + 1) >> 1, 16);
        y_plane = y_stride * y_sclines;
index 930b743f225e80661f849d3c3d4c086420f10c43..bc3f8ff058403ca3d7ac1df1bcf86b85faa88a74 100644 (file)
@@ -1257,7 +1257,30 @@ pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt,
                pkt->shdr.hdr.size += sizeof(u32) + sizeof(*tm);
                break;
        }
+       case HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2: {
+               struct hfi_quantization_range_v2 *in = pdata, *range = prop_data;
+               u32 min_qp, max_qp;
+
+               min_qp = in->min_qp.qp_packed;
+               max_qp = in->max_qp.qp_packed;
 
+               /* We'll be packing in the qp, so make sure we
+                * won't be losing data when masking
+                */
+               if (min_qp > 0xff || max_qp > 0xff)
+                       return -ERANGE;
+
+               range->min_qp.layer_id = 0xFF;
+               range->max_qp.layer_id = 0xFF;
+               range->min_qp.qp_packed = (min_qp & 0xFF) | ((min_qp & 0xFF) << 8) |
+                       ((min_qp & 0xFF) << 16);
+               range->max_qp.qp_packed = (max_qp & 0xFF) | ((max_qp & 0xFF) << 8) |
+                       ((max_qp & 0xFF) << 16);
+               range->min_qp.enable = 7;
+               range->max_qp.enable = 7;
+               pkt->shdr.hdr.size += sizeof(u32) + sizeof(*range);
+               break;
+       }
        case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE:
        case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
        case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE:
index d2d6719a2ba4130f4ea0ef6e386dbfdef20aaa6c..105792a680609a0ffe9f7c6ec6a9258da07355a4 100644 (file)
 #define HFI_PROPERTY_PARAM_VENC_SESSION_QP                     0x2005006
 #define HFI_PROPERTY_PARAM_VENC_MPEG4_AC_PREDICTION            0x2005007
 #define HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE               0x2005008
+/*
+ * Note: HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2 is
+ * specific to HFI_VERSION_6XX and HFI_VERSION_4XX only
+ */
+#define HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2            0x2005009
 #define HFI_PROPERTY_PARAM_VENC_MPEG4_TIME_RESOLUTION          0x2005009
 #define HFI_PROPERTY_PARAM_VENC_MPEG4_SHORT_HEADER             0x200500a
 #define HFI_PROPERTY_PARAM_VENC_MPEG4_HEADER_EXTENSION         0x200500b
@@ -827,6 +832,19 @@ struct hfi_quantization_range {
        u32 layer_id;
 };
 
+struct hfi_quantization_v2 {
+       u32 qp_packed;
+       u32 layer_id;
+       u32 enable;
+       u32 reserved[3];
+};
+
+struct hfi_quantization_range_v2 {
+       struct hfi_quantization_v2 min_qp;
+       struct hfi_quantization_v2 max_qp;
+       u32 reserved[4];
+};
+
 #define HFI_LTR_MODE_DISABLE   0x0
 #define HFI_LTR_MODE_MANUAL    0x1
 #define HFI_LTR_MODE_PERIODIC  0x2
index ea25c451222bcd9764db927bc3ab5920602432fe..a9be31ec6927038336ff504718bd95c92f523ac9 100644 (file)
@@ -93,7 +93,7 @@
 #define LCU_MIN_SIZE_PELS              16
 #define SIZE_SEI_USERDATA              4096
 
-#define H265D_MAX_SLICE                        600
+#define H265D_MAX_SLICE                        3600
 #define SIZE_H265D_HW_PIC_T            SIZE_H264D_HW_PIC_T
 #define SIZE_H265D_BSE_CMD_PER_BUF     (16 * sizeof(u32))
 #define SIZE_H265D_VPP_CMD_PER_BUF     256
@@ -1021,7 +1021,7 @@ static u32 h264d_persist1_size(void)
 static u32 h265d_persist1_size(void)
 {
        return ALIGN((SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265 + H265_NUM_TILE
-                       * sizeof(u32)), HFI_DMA_ALIGNMENT);
+                       * sizeof(u32) + NUM_HW_PIC_BUF * SIZE_SEI_USERDATA), HFI_DMA_ALIGNMENT);
 }
 
 static u32 vp8d_persist1_size(void)
index 4ceaba37e2e573928874afee6172e28446312e4f..51a53bf82bd39effbf8d9802eaf266e86b5fba66 100644 (file)
  */
 static const struct venus_format vdec_formats[] = {
        {
-               .pixfmt = V4L2_PIX_FMT_QC08C,
+               .pixfmt = V4L2_PIX_FMT_NV12,
                .num_planes = 1,
                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
        }, {
-               .pixfmt = V4L2_PIX_FMT_QC10C,
+               .pixfmt = V4L2_PIX_FMT_QC08C,
                .num_planes = 1,
                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
-       },{
-               .pixfmt = V4L2_PIX_FMT_NV12,
+       }, {
+               .pixfmt = V4L2_PIX_FMT_QC10C,
                .num_planes = 1,
                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
        }, {
@@ -204,8 +204,13 @@ vdec_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
                                           pixmp->height);
 
        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               unsigned int stride = pixmp->width;
+
+               if (pixmp->pixelformat == V4L2_PIX_FMT_P010)
+                       stride *= 2;
+
                pfmt[0].sizeimage = szimage;
-               pfmt[0].bytesperline = ALIGN(pixmp->width, 128);
+               pfmt[0].bytesperline = ALIGN(stride, 128);
        } else {
                pfmt[0].sizeimage = clamp_t(u32, pfmt[0].sizeimage, 0, SZ_8M);
                pfmt[0].sizeimage = max(pfmt[0].sizeimage, szimage);
@@ -526,6 +531,7 @@ static int
 vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
 {
        struct venus_inst *inst = to_inst(file);
+       struct vb2_queue *dst_vq;
        struct hfi_frame_data fdata = {0};
        int ret;
 
@@ -556,6 +562,13 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
                        inst->codec_state = VENUS_DEC_STATE_DRAIN;
                        inst->drain_active = true;
                }
+       } else if (cmd->cmd == V4L2_DEC_CMD_START &&
+                  inst->codec_state == VENUS_DEC_STATE_STOPPED) {
+               dst_vq = v4l2_m2m_get_vq(inst->fh.m2m_ctx,
+                                        V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+               vb2_clear_last_buffer_dequeued(dst_vq);
+
+               inst->codec_state = VENUS_DEC_STATE_DECODING;
        }
 
 unlock:
@@ -1774,7 +1787,7 @@ err_vdev_release:
        return ret;
 }
 
-static int vdec_remove(struct platform_device *pdev)
+static void vdec_remove(struct platform_device *pdev)
 {
        struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
 
@@ -1783,8 +1796,6 @@ static int vdec_remove(struct platform_device *pdev)
 
        if (core->pm_ops->vdec_put)
                core->pm_ops->vdec_put(core->dev_dec);
-
-       return 0;
 }
 
 static __maybe_unused int vdec_runtime_suspend(struct device *dev)
@@ -1825,7 +1836,7 @@ MODULE_DEVICE_TABLE(of, vdec_dt_match);
 
 static struct platform_driver qcom_venus_dec_driver = {
        .probe = vdec_probe,
-       .remove = vdec_remove,
+       .remove_new = vdec_remove,
        .driver = {
                .name = "qcom-venus-decoder",
                .of_match_table = vdec_dt_match,
index cdb12546c4fa6f5e6915dc6adee5cd3c78317d13..4666f42feea3d60c6c0f856d124e8b62184e99a8 100644 (file)
@@ -520,6 +520,51 @@ static int venc_subscribe_event(struct v4l2_fh *fh,
        }
 }
 
+static int
+venc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *cmd)
+{
+       struct venus_inst *inst = to_inst(file);
+       struct hfi_frame_data fdata = {0};
+       int ret = 0;
+
+       ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd);
+       if (ret)
+               return ret;
+
+       mutex_lock(&inst->lock);
+
+       if (cmd->cmd == V4L2_ENC_CMD_STOP &&
+           inst->enc_state == VENUS_ENC_STATE_ENCODING) {
+               /*
+                * Implement V4L2_ENC_CMD_STOP by enqueue an empty buffer on
+                * encoder input to signal EOS.
+                */
+               if (!(inst->streamon_out && inst->streamon_cap))
+                       goto unlock;
+
+               fdata.buffer_type = HFI_BUFFER_INPUT;
+               fdata.flags |= HFI_BUFFERFLAG_EOS;
+               fdata.device_addr = 0xdeadb000;
+
+               ret = hfi_session_process_buf(inst, &fdata);
+
+               inst->enc_state = VENUS_ENC_STATE_DRAIN;
+       } else if (cmd->cmd == V4L2_ENC_CMD_START) {
+               if (inst->enc_state == VENUS_ENC_STATE_DRAIN) {
+                       ret = -EBUSY;
+                       goto unlock;
+               }
+               if (inst->enc_state == VENUS_ENC_STATE_STOPPED) {
+                       vb2_clear_last_buffer_dequeued(&inst->fh.m2m_ctx->cap_q_ctx.q);
+                       inst->enc_state = VENUS_ENC_STATE_ENCODING;
+               }
+       }
+
+unlock:
+       mutex_unlock(&inst->lock);
+       return ret;
+}
+
 static const struct v4l2_ioctl_ops venc_ioctl_ops = {
        .vidioc_querycap = venc_querycap,
        .vidioc_enum_fmt_vid_cap = venc_enum_fmt,
@@ -548,6 +593,7 @@ static const struct v4l2_ioctl_ops venc_ioctl_ops = {
        .vidioc_subscribe_event = venc_subscribe_event,
        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
        .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
+       .vidioc_encoder_cmd = venc_encoder_cmd,
 };
 
 static int venc_pm_get(struct venus_inst *inst)
@@ -617,6 +663,7 @@ static int venc_set_properties(struct venus_inst *inst)
        struct hfi_idr_period idrp;
        struct hfi_quantization quant;
        struct hfi_quantization_range quant_range;
+       struct hfi_quantization_range_v2 quant_range_v2;
        struct hfi_enable en;
        struct hfi_ltr_mode ltr_mode;
        struct hfi_intra_refresh intra_refresh = {};
@@ -825,16 +872,40 @@ static int venc_set_properties(struct venus_inst *inst)
        if (ret)
                return ret;
 
-       ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE;
-       if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
-               quant_range.min_qp = ctr->hevc_min_qp;
-               quant_range.max_qp = ctr->hevc_max_qp;
+       if (inst->core->res->hfi_version == HFI_VERSION_4XX ||
+           inst->core->res->hfi_version == HFI_VERSION_6XX) {
+               ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2;
+
+               if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
+                       quant_range_v2.min_qp.qp_packed = ctr->hevc_min_qp;
+                       quant_range_v2.max_qp.qp_packed = ctr->hevc_max_qp;
+               } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_VP8) {
+                       quant_range_v2.min_qp.qp_packed = ctr->vp8_min_qp;
+                       quant_range_v2.max_qp.qp_packed = ctr->vp8_max_qp;
+               } else {
+                       quant_range_v2.min_qp.qp_packed = ctr->h264_min_qp;
+                       quant_range_v2.max_qp.qp_packed = ctr->h264_max_qp;
+               }
+
+               ret = hfi_session_set_property(inst, ptype, &quant_range_v2);
        } else {
-               quant_range.min_qp = ctr->h264_min_qp;
-               quant_range.max_qp = ctr->h264_max_qp;
+               ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE;
+
+               if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
+                       quant_range.min_qp = ctr->hevc_min_qp;
+                       quant_range.max_qp = ctr->hevc_max_qp;
+               } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_VP8) {
+                       quant_range.min_qp = ctr->vp8_min_qp;
+                       quant_range.max_qp = ctr->vp8_max_qp;
+               } else {
+                       quant_range.min_qp = ctr->h264_min_qp;
+                       quant_range.max_qp = ctr->h264_max_qp;
+               }
+
+               quant_range.layer_id = 0;
+               ret = hfi_session_set_property(inst, ptype, &quant_range);
        }
-       quant_range.layer_id = 0;
-       ret = hfi_session_set_property(inst, ptype, &quant_range);
+
        if (ret)
                return ret;
 
@@ -1196,6 +1267,8 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
        if (ret)
                goto error;
 
+       inst->enc_state = VENUS_ENC_STATE_ENCODING;
+
        mutex_unlock(&inst->lock);
 
        return 0;
@@ -1215,10 +1288,21 @@ error:
 static void venc_vb2_buf_queue(struct vb2_buffer *vb)
 {
        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 
        venc_pm_get_put(inst);
 
        mutex_lock(&inst->lock);
+
+       if (inst->enc_state == VENUS_ENC_STATE_STOPPED) {
+               vbuf->sequence = inst->sequence_cap++;
+               vbuf->field = V4L2_FIELD_NONE;
+               vb2_set_plane_payload(vb, 0, 0);
+               v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
+               mutex_unlock(&inst->lock);
+               return;
+       }
+
        venus_helper_vb2_buf_queue(vb);
        mutex_unlock(&inst->lock);
 }
@@ -1260,6 +1344,10 @@ static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
                vb->planes[0].data_offset = data_offset;
                vb->timestamp = timestamp_us * NSEC_PER_USEC;
                vbuf->sequence = inst->sequence_cap++;
+               if ((vbuf->flags & V4L2_BUF_FLAG_LAST) &&
+                   inst->enc_state == VENUS_ENC_STATE_DRAIN) {
+                       inst->enc_state = VENUS_ENC_STATE_STOPPED;
+               }
        } else {
                vbuf->sequence = inst->sequence_out++;
        }
@@ -1362,6 +1450,9 @@ static int venc_open(struct file *file)
        inst->core_acquired = false;
        inst->nonblock = file->f_flags & O_NONBLOCK;
 
+       if (inst->enc_state == VENUS_ENC_STATE_DEINIT)
+               inst->enc_state = VENUS_ENC_STATE_INIT;
+
        venus_helper_init_instance(inst);
 
        ret = venc_ctrl_init(inst);
@@ -1424,6 +1515,8 @@ static int venc_close(struct file *file)
        v4l2_fh_del(&inst->fh);
        v4l2_fh_exit(&inst->fh);
 
+       inst->enc_state = VENUS_ENC_STATE_DEINIT;
+
        venc_pm_put(inst, false);
 
        kfree(inst);
@@ -1492,7 +1585,7 @@ err_vdev_release:
        return ret;
 }
 
-static int venc_remove(struct platform_device *pdev)
+static void venc_remove(struct platform_device *pdev)
 {
        struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
 
@@ -1501,8 +1594,6 @@ static int venc_remove(struct platform_device *pdev)
 
        if (core->pm_ops->venc_put)
                core->pm_ops->venc_put(core->dev_enc);
-
-       return 0;
 }
 
 static __maybe_unused int venc_runtime_suspend(struct device *dev)
@@ -1543,7 +1634,7 @@ MODULE_DEVICE_TABLE(of, venc_dt_match);
 
 static struct platform_driver qcom_venus_enc_driver = {
        .probe = venc_probe,
-       .remove = venc_remove,
+       .remove_new = venc_remove,
        .driver = {
                .name = "qcom-venus-encoder",
                .of_match_table = venc_dt_match,
index eb59a3ba6d0fe925620290956aa6413d4b0a9ae2..bcef7b87da7c129062249d52a365ac710a94ee87 100644 (file)
@@ -144,7 +144,7 @@ static int rcar_fcp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int rcar_fcp_remove(struct platform_device *pdev)
+static void rcar_fcp_remove(struct platform_device *pdev)
 {
        struct rcar_fcp_device *fcp = platform_get_drvdata(pdev);
 
@@ -153,8 +153,6 @@ static int rcar_fcp_remove(struct platform_device *pdev)
        mutex_unlock(&fcp_lock);
 
        pm_runtime_disable(&pdev->dev);
-
-       return 0;
 }
 
 static const struct of_device_id rcar_fcp_of_match[] = {
@@ -166,7 +164,7 @@ MODULE_DEVICE_TABLE(of, rcar_fcp_of_match);
 
 static struct platform_driver rcar_fcp_platform_driver = {
        .probe          = rcar_fcp_probe,
-       .remove         = rcar_fcp_remove,
+       .remove_new     = rcar_fcp_remove,
        .driver         = {
                .name   = "rcar-fcp",
                .of_match_table = rcar_fcp_of_match,
index 10b3474f93a42585fd1c24ce249b4411fad97453..f666b621338d08b8dd098e6de1ca9109a9b75ec0 100644 (file)
@@ -419,10 +419,7 @@ static const struct media_entity_operations risp_entity_ops = {
 static int risp_probe_resources(struct rcar_isp *isp,
                                struct platform_device *pdev)
 {
-       struct resource *res;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       isp->base = devm_ioremap_resource(&pdev->dev, res);
+       isp->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(isp->base))
                return PTR_ERR(isp->base);
 
@@ -503,7 +500,7 @@ error_mutex:
        return ret;
 }
 
-static int risp_remove(struct platform_device *pdev)
+static void risp_remove(struct platform_device *pdev)
 {
        struct rcar_isp *isp = platform_get_drvdata(pdev);
 
@@ -515,8 +512,6 @@ static int risp_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
 
        mutex_destroy(&isp->lock);
-
-       return 0;
 }
 
 static struct platform_driver rcar_isp_driver = {
@@ -525,7 +520,7 @@ static struct platform_driver rcar_isp_driver = {
                .of_match_table = risp_of_id_table,
        },
        .probe = risp_probe,
-       .remove = risp_remove,
+       .remove_new = risp_remove,
 };
 
 module_platform_driver(rcar_isp_driver);
index 5e53d6b7036c03857d8c918fef5886ae1a508348..ff4bde9cc0e30dd1f6aa47cf7e2a5150408eae1a 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
-#include <linux/sys_soc.h>
 
 #include <media/v4l2-async.h>
 #include <media/v4l2-fwnode.h>
@@ -1183,24 +1182,6 @@ static const struct rvin_info rcar_info_r8a7795 = {
        .scaler = rvin_scaler_gen3,
 };
 
-static const struct rvin_group_route rcar_info_r8a7795es1_routes[] = {
-       { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 },
-       { .master = 0, .csi = RVIN_CSI21, .chsel = 0x05 },
-       { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 },
-       { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 },
-       { .master = 4, .csi = RVIN_CSI21, .chsel = 0x05 },
-       { .master = 4, .csi = RVIN_CSI41, .chsel = 0x03 },
-       { /* Sentinel */ }
-};
-
-static const struct rvin_info rcar_info_r8a7795es1 = {
-       .model = RCAR_GEN3,
-       .use_mc = true,
-       .max_width = 4096,
-       .max_height = 4096,
-       .routes = rcar_info_r8a7795es1_routes,
-};
-
 static const struct rvin_group_route rcar_info_r8a7796_routes[] = {
        { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 },
        { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 },
@@ -1372,17 +1353,8 @@ static const struct of_device_id rvin_of_id_table[] = {
 };
 MODULE_DEVICE_TABLE(of, rvin_of_id_table);
 
-static const struct soc_device_attribute r8a7795es1[] = {
-       {
-               .soc_id = "r8a7795", .revision = "ES1.*",
-               .data = &rcar_info_r8a7795es1,
-       },
-       { /* Sentinel */ }
-};
-
 static int rcar_vin_probe(struct platform_device *pdev)
 {
-       const struct soc_device_attribute *attr;
        struct rvin_dev *vin;
        int irq, ret;
 
@@ -1394,14 +1366,6 @@ static int rcar_vin_probe(struct platform_device *pdev)
        vin->info = of_device_get_match_data(&pdev->dev);
        vin->alpha = 0xff;
 
-       /*
-        * Special care is needed on r8a7795 ES1.x since it
-        * uses different routing than r8a7795 ES2.0.
-        */
-       attr = soc_device_match(r8a7795es1);
-       if (attr)
-               vin->info = attr->data;
-
        vin->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(vin->base))
                return PTR_ERR(vin->base);
@@ -1442,7 +1406,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int rcar_vin_remove(struct platform_device *pdev)
+static void rcar_vin_remove(struct platform_device *pdev)
 {
        struct rvin_dev *vin = platform_get_drvdata(pdev);
 
@@ -1458,8 +1422,6 @@ static int rcar_vin_remove(struct platform_device *pdev)
                rvin_parallel_cleanup(vin);
 
        rvin_dma_unregister(vin);
-
-       return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(rvin_pm_ops, rvin_suspend, rvin_resume);
@@ -1472,7 +1434,7 @@ static struct platform_driver rcar_vin_driver = {
                .of_match_table = rvin_of_id_table,
        },
        .probe = rcar_vin_probe,
-       .remove = rcar_vin_remove,
+       .remove_new = rcar_vin_remove,
 };
 
 module_platform_driver(rcar_vin_driver);
index 174aa6176f540c27f7a0161ab6b68d94664ccdc6..e34060c2b039567cf318fbb65814a2a4bac7de11 100644 (file)
@@ -345,7 +345,7 @@ static const struct rcsi2_mbps_reg hsfreqrange_h3_v3h_m3n[] = {
        { /* sentinel */ },
 };
 
-static const struct rcsi2_mbps_reg hsfreqrange_m3w_h3es1[] = {
+static const struct rcsi2_mbps_reg hsfreqrange_m3w[] = {
        { .mbps =   80, .reg = 0x00 },
        { .mbps =   90, .reg = 0x10 },
        { .mbps =  100, .reg = 0x20 },
@@ -1369,11 +1369,6 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = {
        .clear_ulps = true,
 };
 
-static const struct rcar_csi2_info rcar_csi2_info_r8a7795es1 = {
-       .hsfreqrange = hsfreqrange_m3w_h3es1,
-       .num_channels = 4,
-};
-
 static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = {
        .init_phtw = rcsi2_init_phtw_h3es2,
        .hsfreqrange = hsfreqrange_h3_v3h_m3n,
@@ -1383,12 +1378,12 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = {
 };
 
 static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = {
-       .hsfreqrange = hsfreqrange_m3w_h3es1,
+       .hsfreqrange = hsfreqrange_m3w,
        .num_channels = 4,
 };
 
 static const struct rcar_csi2_info rcar_csi2_info_r8a77961 = {
-       .hsfreqrange = hsfreqrange_m3w_h3es1,
+       .hsfreqrange = hsfreqrange_m3w,
        .num_channels = 4,
 };
 
@@ -1481,10 +1476,6 @@ static const struct of_device_id rcar_csi2_of_table[] = {
 MODULE_DEVICE_TABLE(of, rcar_csi2_of_table);
 
 static const struct soc_device_attribute r8a7795[] = {
-       {
-               .soc_id = "r8a7795", .revision = "ES1.*",
-               .data = &rcar_csi2_info_r8a7795es1,
-       },
        {
                .soc_id = "r8a7795", .revision = "ES2.*",
                .data = &rcar_csi2_info_r8a7795es2,
@@ -1574,7 +1565,7 @@ error_mutex:
        return ret;
 }
 
-static int rcsi2_remove(struct platform_device *pdev)
+static void rcsi2_remove(struct platform_device *pdev)
 {
        struct rcar_csi2 *priv = platform_get_drvdata(pdev);
 
@@ -1585,12 +1576,10 @@ static int rcsi2_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
 
        mutex_destroy(&priv->lock);
-
-       return 0;
 }
 
 static struct platform_driver rcar_csi2_pdrv = {
-       .remove = rcsi2_remove,
+       .remove_new = rcsi2_remove,
        .probe  = rcsi2_probe,
        .driver = {
                .name   = "rcar-csi2",
index 3fec41f6e964557ac68ac5d476e6b71043e89597..3a92f4535c18bccde7a84a167f56dbc17f715c8b 100644 (file)
@@ -1433,19 +1433,17 @@ static int rcar_drif_probe(struct platform_device *pdev)
 }
 
 /* DRIF channel remove */
-static int rcar_drif_remove(struct platform_device *pdev)
+static void rcar_drif_remove(struct platform_device *pdev)
 {
        struct rcar_drif *ch = platform_get_drvdata(pdev);
        struct rcar_drif_sdr *sdr = ch->sdr;
 
        /* Channel 0 will be the SDR instance */
        if (ch->num)
-               return 0;
+               return;
 
        /* SDR instance */
        rcar_drif_sdr_remove(sdr);
-
-       return 0;
 }
 
 /* FIXME: Implement suspend/resume support */
@@ -1476,7 +1474,7 @@ static struct platform_driver rcar_drif_driver = {
                .pm = &rcar_drif_pm_ops,
                },
        .probe = rcar_drif_probe,
-       .remove = rcar_drif_remove,
+       .remove_new = rcar_drif_remove,
 };
 
 module_platform_driver(rcar_drif_driver);
index 37ecf489d112e67ee2b6738ac2e11da53c1c118d..f43e458590b8cadaa1a821010b1dddef1ae89aed 100644 (file)
@@ -254,7 +254,6 @@ MODULE_PARM_DESC(debug, "activate debug info");
 
 /* Internal Data (HW Version) */
 #define FD1_IP_INTDATA                 0x0800
-#define FD1_IP_H3_ES1                  0x02010101
 #define FD1_IP_M3W                     0x02010202
 #define FD1_IP_H3                      0x02010203
 #define FD1_IP_M3N                     0x02010204
@@ -2313,8 +2312,10 @@ static int fdp1_probe(struct platform_device *pdev)
 
        /* Determine our clock rate */
        clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               goto put_dev;
+       }
 
        fdp1->clk_rate = clk_get_rate(clk);
        clk_put(clk);
@@ -2323,7 +2324,7 @@ static int fdp1_probe(struct platform_device *pdev)
        ret = v4l2_device_register(&pdev->dev, &fdp1->v4l2_dev);
        if (ret) {
                v4l2_err(&fdp1->v4l2_dev, "Failed to register video device\n");
-               return ret;
+               goto put_dev;
        }
 
        /* M2M registration */
@@ -2359,9 +2360,6 @@ static int fdp1_probe(struct platform_device *pdev)
 
        hw_version = fdp1_read(fdp1, FD1_IP_INTDATA);
        switch (hw_version) {
-       case FD1_IP_H3_ES1:
-               dprintk(fdp1, "FDP1 Version R-Car H3 ES1\n");
-               break;
        case FD1_IP_M3W:
                dprintk(fdp1, "FDP1 Version R-Car M3-W\n");
                break;
@@ -2393,10 +2391,12 @@ release_m2m:
 unreg_dev:
        v4l2_device_unregister(&fdp1->v4l2_dev);
 
+put_dev:
+       rcar_fcp_put(fdp1->fcp);
        return ret;
 }
 
-static int fdp1_remove(struct platform_device *pdev)
+static void fdp1_remove(struct platform_device *pdev)
 {
        struct fdp1_dev *fdp1 = platform_get_drvdata(pdev);
 
@@ -2404,8 +2404,7 @@ static int fdp1_remove(struct platform_device *pdev)
        video_unregister_device(&fdp1->vfd);
        v4l2_device_unregister(&fdp1->v4l2_dev);
        pm_runtime_disable(&pdev->dev);
-
-       return 0;
+       rcar_fcp_put(fdp1->fcp);
 }
 
 static int __maybe_unused fdp1_pm_runtime_suspend(struct device *dev)
@@ -2441,7 +2440,7 @@ MODULE_DEVICE_TABLE(of, fdp1_dt_ids);
 
 static struct platform_driver fdp1_pdrv = {
        .probe          = fdp1_probe,
-       .remove         = fdp1_remove,
+       .remove_new     = fdp1_remove,
        .driver         = {
                .name   = DRIVER_NAME,
                .of_match_table = fdp1_dt_ids,
index 2f4377cfbb420b8cd980fdbec4d20d969f2b7694..e7f60480782538fade47feca0eb6da689c5abd23 100644 (file)
@@ -1702,7 +1702,7 @@ device_register_rollback:
        return ret;
 }
 
-static int jpu_remove(struct platform_device *pdev)
+static void jpu_remove(struct platform_device *pdev)
 {
        struct jpu *jpu = platform_get_drvdata(pdev);
 
@@ -1710,8 +1710,6 @@ static int jpu_remove(struct platform_device *pdev)
        video_unregister_device(&jpu->vfd_encoder);
        v4l2_m2m_release(jpu->m2m_dev);
        v4l2_device_unregister(&jpu->v4l2_dev);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1746,7 +1744,7 @@ static const struct dev_pm_ops jpu_pm_ops = {
 
 static struct platform_driver jpu_driver = {
        .probe = jpu_probe,
-       .remove = jpu_remove,
+       .remove_new = jpu_remove,
        .driver = {
                .of_match_table = jpu_dt_ids,
                .name = DRV_NAME,
index f70f91b006b7db4994dfa08d865abc4ea776549a..56b9c59cfda8246aa9b4c4f23e104ac5765cf5d5 100644 (file)
@@ -795,8 +795,8 @@ static int __ceu_try_fmt(struct ceu_device *ceudev, struct v4l2_format *v4l2_fmt
        struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;
        struct v4l2_subdev_pad_config pad_cfg;
        struct v4l2_subdev_state pad_state = {
-               .pads = &pad_cfg
-               };
+               .pads = &pad_cfg,
+       };
        const struct ceu_fmt *ceu_fmt;
        u32 mbus_code_old;
        u32 mbus_code;
@@ -1709,7 +1709,7 @@ error_free_ceudev:
        return ret;
 }
 
-static int ceu_remove(struct platform_device *pdev)
+static void ceu_remove(struct platform_device *pdev)
 {
        struct ceu_device *ceudev = platform_get_drvdata(pdev);
 
@@ -1722,8 +1722,6 @@ static int ceu_remove(struct platform_device *pdev)
        v4l2_device_unregister(&ceudev->v4l2_dev);
 
        video_unregister_device(&ceudev->vdev);
-
-       return 0;
 }
 
 static const struct dev_pm_ops ceu_pm_ops = {
@@ -1739,7 +1737,7 @@ static struct platform_driver ceu_driver = {
                .of_match_table = of_match_ptr(ceu_of_match),
        },
        .probe          = ceu_probe,
-       .remove         = ceu_remove,
+       .remove_new     = ceu_remove,
 };
 
 module_platform_driver(ceu_driver);
index 5939f5165a5e1b0e9399f024b3da842048ed2e67..7a71370fcc32c79f65347eb9e74488dfce3775a6 100644 (file)
@@ -298,7 +298,7 @@ error_dma_unregister:
        return ret;
 }
 
-static int rzg2l_cru_remove(struct platform_device *pdev)
+static void rzg2l_cru_remove(struct platform_device *pdev)
 {
        struct rzg2l_cru_dev *cru = platform_get_drvdata(pdev);
 
@@ -312,8 +312,6 @@ static int rzg2l_cru_remove(struct platform_device *pdev)
        mutex_destroy(&cru->mdev_lock);
 
        rzg2l_cru_dma_unregister(cru);
-
-       return 0;
 }
 
 static const struct of_device_id rzg2l_cru_of_id_table[] = {
@@ -328,7 +326,7 @@ static struct platform_driver rzg2l_cru_driver = {
                .of_match_table = rzg2l_cru_of_id_table,
        },
        .probe = rzg2l_cru_probe,
-       .remove = rzg2l_cru_remove,
+       .remove_new = rzg2l_cru_remove,
 };
 
 module_platform_driver(rzg2l_cru_driver);
index 384fb54e219ab50e0ccec7c0d5a0dc68d197972f..30dad7383654c36c301158d690c79ceb5182bf92 100644 (file)
@@ -819,7 +819,7 @@ error_pm:
        return ret;
 }
 
-static int rzg2l_csi2_remove(struct platform_device *pdev)
+static void rzg2l_csi2_remove(struct platform_device *pdev)
 {
        struct rzg2l_csi2 *csi2 = platform_get_drvdata(pdev);
 
@@ -829,8 +829,6 @@ static int rzg2l_csi2_remove(struct platform_device *pdev)
        v4l2_subdev_cleanup(&csi2->subdev);
        media_entity_cleanup(&csi2->subdev.entity);
        pm_runtime_disable(&pdev->dev);
-
-       return 0;
 }
 
 static int __maybe_unused rzg2l_csi2_pm_runtime_suspend(struct device *dev)
@@ -859,7 +857,7 @@ static const struct of_device_id rzg2l_csi2_of_table[] = {
 };
 
 static struct platform_driver rzg2l_csi2_pdrv = {
-       .remove = rzg2l_csi2_remove,
+       .remove_new = rzg2l_csi2_remove,
        .probe  = rzg2l_csi2_probe,
        .driver = {
                .name = "rzg2l-csi2",
index ca4310e26c49eeed12ecb67a17c06ae7bde19917..8fe3272a541f61805c4413fc21f35129cd27d7b4 100644 (file)
@@ -1343,7 +1343,7 @@ ei2cgadap:
        return ret;
 }
 
-static int sh_vou_remove(struct platform_device *pdev)
+static void sh_vou_remove(struct platform_device *pdev)
 {
        struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
        struct sh_vou_device *vou_dev = container_of(v4l2_dev,
@@ -1356,11 +1356,10 @@ static int sh_vou_remove(struct platform_device *pdev)
        video_unregister_device(&vou_dev->vdev);
        i2c_put_adapter(client->adapter);
        v4l2_device_unregister(&vou_dev->v4l2_dev);
-       return 0;
 }
 
 static struct platform_driver sh_vou = {
-       .remove  = sh_vou_remove,
+       .remove_new = sh_vou_remove,
        .driver  = {
                .name   = "sh-vou",
        },
index c6f25200982c8525eb91bf907797379572691402..9b087bd8df7d8c6ee4b341c0a99b3d7daaf194ef 100644 (file)
@@ -66,7 +66,9 @@ static int vsp1_du_insert_uif(struct vsp1_device *vsp1,
                              struct vsp1_entity *prev, unsigned int prev_pad,
                              struct vsp1_entity *next, unsigned int next_pad)
 {
-       struct v4l2_subdev_format format;
+       struct v4l2_subdev_format format = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
        if (!uif) {
@@ -82,8 +84,6 @@ static int vsp1_du_insert_uif(struct vsp1_device *vsp1,
        prev->sink = uif;
        prev->sink_pad = UIF_PAD_SINK;
 
-       memset(&format, 0, sizeof(format));
-       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        format.pad = prev_pad;
 
        ret = v4l2_subdev_call(&prev->subdev, pad, get_fmt, NULL, &format);
@@ -118,8 +118,12 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
                                      struct vsp1_entity *uif,
                                      unsigned int brx_input)
 {
-       struct v4l2_subdev_selection sel;
-       struct v4l2_subdev_format format;
+       struct v4l2_subdev_selection sel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
+       struct v4l2_subdev_format format = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        const struct v4l2_rect *crop;
        int ret;
 
@@ -129,8 +133,6 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
         */
        crop = &vsp1->drm->inputs[rpf->entity.index].crop;
 
-       memset(&format, 0, sizeof(format));
-       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        format.pad = RWPF_PAD_SINK;
        format.format.width = crop->width + crop->left;
        format.format.height = crop->height + crop->top;
@@ -147,8 +149,6 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
                __func__, format.format.width, format.format.height,
                format.format.code, rpf->entity.index);
 
-       memset(&sel, 0, sizeof(sel));
-       sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        sel.pad = RWPF_PAD_SINK;
        sel.target = V4L2_SEL_TGT_CROP;
        sel.r = *crop;
@@ -481,10 +481,11 @@ static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
                                         struct vsp1_pipeline *pipe)
 {
        struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
-       struct v4l2_subdev_format format = { 0, };
+       struct v4l2_subdev_format format = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
-       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        format.pad = RWPF_PAD_SINK;
        format.format.width = drm_pipe->width;
        format.format.height = drm_pipe->height;
@@ -710,6 +711,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
                return 0;
        }
 
+       /* Reset the underrun counter */
+       pipe->underrun_count = 0;
+
        drm_pipe->width = cfg->width;
        drm_pipe->height = cfg->height;
        pipe->interlaced = cfg->interlaced;
index 5710152d6511202533b85618bc1152b708d3aaae..a9db84be48220fecab7f22a4b8c0bda6a0b3e027 100644 (file)
@@ -45,7 +45,8 @@
 
 static irqreturn_t vsp1_irq_handler(int irq, void *data)
 {
-       u32 mask = VI6_WPF_IRQ_STA_DFE | VI6_WPF_IRQ_STA_FRE;
+       u32 mask = VI6_WPF_IRQ_STA_DFE | VI6_WPF_IRQ_STA_FRE |
+                  VI6_WPF_IRQ_STA_UND;
        struct vsp1_device *vsp1 = data;
        irqreturn_t ret = IRQ_NONE;
        unsigned int i;
@@ -60,6 +61,14 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
                status = vsp1_read(vsp1, VI6_WPF_IRQ_STA(i));
                vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask);
 
+               if ((status & VI6_WPF_IRQ_STA_UND) && wpf->entity.pipe) {
+                       wpf->entity.pipe->underrun_count++;
+
+                       dev_warn_ratelimited(vsp1->dev,
+                               "Underrun occurred at WPF%u (total underruns %u)\n",
+                               i, wpf->entity.pipe->underrun_count);
+               }
+
                if (status & VI6_WPF_IRQ_STA_DFE) {
                        vsp1_pipeline_frame_end(wpf->entity.pipe);
                        ret = IRQ_HANDLED;
@@ -977,7 +986,7 @@ done:
        return ret;
 }
 
-static int vsp1_remove(struct platform_device *pdev)
+static void vsp1_remove(struct platform_device *pdev)
 {
        struct vsp1_device *vsp1 = platform_get_drvdata(pdev);
 
@@ -985,8 +994,6 @@ static int vsp1_remove(struct platform_device *pdev)
        rcar_fcp_put(vsp1->fcp);
 
        pm_runtime_disable(&pdev->dev);
-
-       return 0;
 }
 
 static const struct of_device_id vsp1_of_match[] = {
@@ -999,7 +1006,7 @@ MODULE_DEVICE_TABLE(of, vsp1_of_match);
 
 static struct platform_driver vsp1_platform_driver = {
        .probe          = vsp1_probe,
-       .remove         = vsp1_remove,
+       .remove_new     = vsp1_remove,
        .driver         = {
                .name   = "vsp1",
                .pm     = &vsp1_pm_ops,
index 4c3bd2b1ca287896a7499add4cf8dae1665737f8..c31f05a80bb5679a80e27ac84dc1b11bf952aad1 100644 (file)
@@ -184,15 +184,14 @@ vsp1_entity_get_pad_selection(struct vsp1_entity *entity,
 int vsp1_entity_init_cfg(struct v4l2_subdev *subdev,
                         struct v4l2_subdev_state *sd_state)
 {
-       struct v4l2_subdev_format format;
        unsigned int pad;
 
        for (pad = 0; pad < subdev->entity.num_pads - 1; ++pad) {
-               memset(&format, 0, sizeof(format));
-
-               format.pad = pad;
-               format.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY
-                            : V4L2_SUBDEV_FORMAT_ACTIVE;
+               struct v4l2_subdev_format format = {
+                       .pad = pad,
+                       .which = sd_state ? V4L2_SUBDEV_FORMAT_TRY
+                              : V4L2_SUBDEV_FORMAT_ACTIVE,
+               };
 
                v4l2_subdev_call(subdev, pad, set_fmt, sd_state, &format);
        }
index f22724439cdcb6e8518fb656f06b4d2d1a3a02c3..17f98a6a972e3cece90e676152cc6c1fb5f783f6 100644 (file)
@@ -130,8 +130,6 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
                     const struct v4l2_subdev_ops *ops, u32 function);
 void vsp1_entity_destroy(struct vsp1_entity *entity);
 
-extern const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops;
-
 int vsp1_entity_link_setup(struct media_entity *entity,
                           const struct media_pad *local,
                           const struct media_pad *remote, u32 flags);
index ae646c9ef337317ad1b7c1b589f3bfd080af363e..674b5748d929e2ad95e221423d909f7705b9a0db 100644 (file)
@@ -148,6 +148,8 @@ struct vsp1_pipeline {
        unsigned int partitions;
        struct vsp1_partition *partition;
        struct vsp1_partition *part_table;
+
+       u32 underrun_count;
 };
 
 void vsp1_pipeline_reset(struct vsp1_pipeline *pipe);
index d94343ae57a1a97d23408035a9548410fbd78cc8..7eca82e0ba7ec5e02a5f3b9a30ccdcb48db39ed2 100644 (file)
 #define VI6_STATUS_SYS_ACT(n)          BIT((n) + 8)
 
 #define VI6_WPF_IRQ_ENB(n)             (0x0048 + (n) * 12)
+#define VI6_WPF_IRQ_ENB_UNDE           BIT(16)
 #define VI6_WPF_IRQ_ENB_DFEE           BIT(1)
 #define VI6_WPF_IRQ_ENB_FREE           BIT(0)
 
 #define VI6_WPF_IRQ_STA(n)             (0x004c + (n) * 12)
+#define VI6_WPF_IRQ_STA_UND            BIT(16)
 #define VI6_WPF_IRQ_STA_DFE            BIT(1)
 #define VI6_WPF_IRQ_STA_FRE            BIT(0)
 
index 544012fd1fe933c8e8a956307d7643a211d33a68..e9d5027761bbc76bb7b851921ce8d2070b24f4c7 100644 (file)
@@ -62,7 +62,9 @@ vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 
 static int vsp1_video_verify_format(struct vsp1_video *video)
 {
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        int ret;
 
@@ -70,7 +72,6 @@ static int vsp1_video_verify_format(struct vsp1_video *video)
        if (subdev == NULL)
                return -EINVAL;
 
-       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        if (ret < 0)
                return ret == -ENOIOCTLCMD ? -EINVAL : ret;
@@ -776,7 +777,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
        video->rwpf->mem = buf->mem;
        pipe->buffers_ready |= 1 << video->pipe_index;
 
-       if (vb2_is_streaming(&video->queue) &&
+       if (vb2_start_streaming_called(&video->queue) &&
            vsp1_pipeline_ready(pipe))
                vsp1_video_pipeline_run(pipe);
 
index 61b25fcf826e92a38a56dfde1449ed6677e033dc..67dcf22e5ba3101ed41d84242e51148cbe08274e 100644 (file)
@@ -930,7 +930,7 @@ err_put_clk:
        return ret;
 }
 
-static int rga_remove(struct platform_device *pdev)
+static void rga_remove(struct platform_device *pdev)
 {
        struct rockchip_rga *rga = platform_get_drvdata(pdev);
 
@@ -947,8 +947,6 @@ static int rga_remove(struct platform_device *pdev)
        v4l2_device_unregister(&rga->v4l2_dev);
 
        pm_runtime_disable(rga->dev);
-
-       return 0;
 }
 
 static int __maybe_unused rga_runtime_suspend(struct device *dev)
@@ -986,7 +984,7 @@ MODULE_DEVICE_TABLE(of, rockchip_rga_match);
 
 static struct platform_driver rga_pdrv = {
        .probe = rga_probe,
-       .remove = rga_remove,
+       .remove_new = rga_remove,
        .driver = {
                .name = RGA_NAME,
                .pm = &rga_pm,
index d1d1fdce03e3978e684ac1f979ae679fd3935d73..8f3cba319762341a9a35167488ccc667fc0862e9 100644 (file)
@@ -110,6 +110,16 @@ static const struct rkisp1_capture_fmt_cfg rkisp1_mp_fmts[] = {
                .uv_swap = 1,
                .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+       }, {
+               .fourcc = V4L2_PIX_FMT_NV16M,
+               .uv_swap = 0,
+               .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+       }, {
+               .fourcc = V4L2_PIX_FMT_NV61M,
+               .uv_swap = 1,
+               .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+               .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        }, {
                .fourcc = V4L2_PIX_FMT_YVU422M,
                .uv_swap = 1,
@@ -237,6 +247,18 @@ static const struct rkisp1_capture_fmt_cfg rkisp1_sp_fmts[] = {
                .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA,
                .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
                .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+       }, {
+               .fourcc = V4L2_PIX_FMT_NV16M,
+               .uv_swap = 0,
+               .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA,
+               .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
+               .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+       }, {
+               .fourcc = V4L2_PIX_FMT_NV61M,
+               .uv_swap = 1,
+               .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA,
+               .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
+               .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
        }, {
                .fourcc = V4L2_PIX_FMT_YVU422M,
                .uv_swap = 1,
@@ -1212,6 +1234,35 @@ static int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
        return -EINVAL;
 }
 
+static int rkisp1_enum_framesizes(struct file *file, void *fh,
+                                 struct v4l2_frmsizeenum *fsize)
+{
+       static const unsigned int max_widths[] = {
+               RKISP1_RSZ_MP_SRC_MAX_WIDTH,
+               RKISP1_RSZ_SP_SRC_MAX_WIDTH,
+       };
+       static const unsigned int max_heights[] = {
+               RKISP1_RSZ_MP_SRC_MAX_HEIGHT,
+               RKISP1_RSZ_SP_SRC_MAX_HEIGHT,
+       };
+       struct rkisp1_capture *cap = video_drvdata(file);
+
+       if (fsize->index != 0)
+               return -EINVAL;
+
+       fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+
+       fsize->stepwise.min_width = RKISP1_RSZ_SRC_MIN_WIDTH;
+       fsize->stepwise.max_width = max_widths[cap->id];
+       fsize->stepwise.step_width = 2;
+
+       fsize->stepwise.min_height = RKISP1_RSZ_SRC_MIN_HEIGHT;
+       fsize->stepwise.max_height = max_heights[cap->id];
+       fsize->stepwise.step_height = 2;
+
+       return 0;
+}
+
 static int rkisp1_s_fmt_vid_cap_mplane(struct file *file,
                                       void *priv, struct v4l2_format *f)
 {
@@ -1261,6 +1312,7 @@ static const struct v4l2_ioctl_ops rkisp1_v4l2_ioctl_ops = {
        .vidioc_s_fmt_vid_cap_mplane = rkisp1_s_fmt_vid_cap_mplane,
        .vidioc_g_fmt_vid_cap_mplane = rkisp1_g_fmt_vid_cap_mplane,
        .vidioc_enum_fmt_vid_cap = rkisp1_enum_fmt_vid_cap_mplane,
+       .vidioc_enum_framesizes = rkisp1_enum_framesizes,
        .vidioc_querycap = rkisp1_querycap,
        .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
index f2475c6235ea7cd0d5250c1ad9cd508e5b4a726d..4762cb32353dec2a09691525d789998b8a963838 100644 (file)
@@ -622,7 +622,7 @@ err_pm_runtime_disable:
        return ret;
 }
 
-static int rkisp1_remove(struct platform_device *pdev)
+static void rkisp1_remove(struct platform_device *pdev)
 {
        struct rkisp1_device *rkisp1 = platform_get_drvdata(pdev);
 
@@ -638,8 +638,6 @@ static int rkisp1_remove(struct platform_device *pdev)
        v4l2_device_unregister(&rkisp1->v4l2_dev);
 
        pm_runtime_disable(&pdev->dev);
-
-       return 0;
 }
 
 static struct platform_driver rkisp1_drv = {
@@ -649,7 +647,7 @@ static struct platform_driver rkisp1_drv = {
                .pm = &rkisp1_pm_ops,
        },
        .probe = rkisp1_probe,
-       .remove = rkisp1_remove,
+       .remove_new = rkisp1_remove,
 };
 
 module_platform_driver(rkisp1_drv);
index f76afd8112b21ae1d61994546ebdd6235372f622..c15ae0218118c01e42cd73974c8e65f0e3d3394e 100644 (file)
@@ -123,8 +123,8 @@ rkisp1_rsz_get_pad_fmt(struct rkisp1_resizer *rsz,
                       unsigned int pad, u32 which)
 {
        struct v4l2_subdev_state state = {
-               .pads = rsz->pad_cfg
-               };
+               .pads = rsz->pad_cfg,
+       };
        if (which == V4L2_SUBDEV_FORMAT_TRY)
                return v4l2_subdev_get_try_format(&rsz->sd, sd_state, pad);
        else
@@ -137,8 +137,8 @@ rkisp1_rsz_get_pad_crop(struct rkisp1_resizer *rsz,
                        unsigned int pad, u32 which)
 {
        struct v4l2_subdev_state state = {
-               .pads = rsz->pad_cfg
-               };
+               .pads = rsz->pad_cfg,
+       };
        if (which == V4L2_SUBDEV_FORMAT_TRY)
                return v4l2_subdev_get_try_crop(&rsz->sd, sd_state, pad);
        else
@@ -366,7 +366,7 @@ static int rkisp1_rsz_enum_mbus_code(struct v4l2_subdev *sd,
        struct v4l2_subdev_pad_config dummy_cfg;
        struct v4l2_subdev_state pad_state = {
                .pads = &dummy_cfg
-               };
+       };
        u32 pad = code->pad;
        int ret;
 
@@ -733,8 +733,8 @@ static void rkisp1_rsz_unregister(struct rkisp1_resizer *rsz)
 static int rkisp1_rsz_register(struct rkisp1_resizer *rsz)
 {
        struct v4l2_subdev_state state = {
-               .pads = rsz->pad_cfg
-               };
+               .pads = rsz->pad_cfg,
+       };
        static const char * const dev_names[] = {
                RKISP1_RSZ_MP_DEV_NAME,
                RKISP1_RSZ_SP_DEV_NAME
index b147c645ae0bbd161bc86d03c9a1f91550e0aa58..1fb34de706496cd457f6519cb1162347a02b0721 100644 (file)
@@ -1201,7 +1201,7 @@ err_clk:
        return ret;
 }
 
-static int gsc_remove(struct platform_device *pdev)
+static void gsc_remove(struct platform_device *pdev)
 {
        struct gsc_dev *gsc = platform_get_drvdata(pdev);
        int i;
@@ -1220,7 +1220,6 @@ static int gsc_remove(struct platform_device *pdev)
        pm_runtime_set_suspended(&pdev->dev);
 
        dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1311,7 +1310,7 @@ static const struct dev_pm_ops gsc_pm_ops = {
 
 static struct platform_driver gsc_driver = {
        .probe          = gsc_probe,
-       .remove         = gsc_remove,
+       .remove_new     = gsc_remove,
        .driver = {
                .name   = GSC_MODULE_NAME,
                .pm     = &gsc_pm_ops,
index e3b95a2b7e0403fa06cdd47cdcc8f040d989f05b..a0d43bf892e67735cbd62e799bb218aef0ed4199 100644 (file)
@@ -763,7 +763,10 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
        struct fimc_dev *fimc = ctx->fimc_dev;
        struct fimc_pipeline *p = to_fimc_pipeline(fimc->vid_cap.ve.pipe);
        struct v4l2_subdev *sd = p->subdevs[IDX_SENSOR];
-       struct v4l2_subdev_format sfmt;
+       struct v4l2_subdev_format sfmt = {
+               .which = set ? V4L2_SUBDEV_FORMAT_ACTIVE
+                      : V4L2_SUBDEV_FORMAT_TRY,
+       };
        struct v4l2_mbus_framefmt *mf = &sfmt.format;
        struct media_entity *me;
        struct fimc_fmt *ffmt;
@@ -774,9 +777,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
        if (WARN_ON(!sd || !tfmt))
                return -EINVAL;
 
-       memset(&sfmt, 0, sizeof(sfmt));
        sfmt.format = *tfmt;
-       sfmt.which = set ? V4L2_SUBDEV_FORMAT_ACTIVE : V4L2_SUBDEV_FORMAT_TRY;
 
        me = fimc_pipeline_get_head(&sd->entity);
 
@@ -854,7 +855,7 @@ static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor,
                                      struct v4l2_plane_pix_format *plane_fmt,
                                      unsigned int num_planes, bool try)
 {
-       struct v4l2_mbus_frame_desc fd;
+       struct v4l2_mbus_frame_desc fd = { };
        int i, ret;
        int pad;
 
@@ -1095,7 +1096,12 @@ static int fimc_cap_g_input(struct file *file, void *priv, unsigned int *i)
  */
 static int fimc_pipeline_validate(struct fimc_dev *fimc)
 {
-       struct v4l2_subdev_format sink_fmt, src_fmt;
+       struct v4l2_subdev_format sink_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
+       struct v4l2_subdev_format src_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct fimc_vid_cap *vc = &fimc->vid_cap;
        struct v4l2_subdev *sd = &vc->subdev;
        struct fimc_pipeline *p = to_fimc_pipeline(vc->ve.pipe);
@@ -1132,7 +1138,6 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
                        sink_fmt.format.code = ff->fmt ? ff->fmt->mbus_code : 0;
                } else {
                        sink_fmt.pad = sink_pad->index;
-                       sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                        ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sink_fmt);
                        if (ret < 0 && ret != -ENOIOCTLCMD)
                                return -EPIPE;
@@ -1141,7 +1146,6 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
                /* Retrieve format at the source pad */
                sd = media_entity_to_v4l2_subdev(src_pad->entity);
                src_fmt.pad = src_pad->index;
-               src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
                if (ret < 0 && ret != -ENOIOCTLCMD)
                        return -EPIPE;
index 1791100b6935340ca58bbc2d6ea201036e97f10c..a2034ade8b9e23390a598f5706898281b97217e8 100644 (file)
@@ -1092,7 +1092,7 @@ static int fimc_suspend(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-static int fimc_remove(struct platform_device *pdev)
+static void fimc_remove(struct platform_device *pdev)
 {
        struct fimc_dev *fimc = platform_get_drvdata(pdev);
 
@@ -1108,7 +1108,6 @@ static int fimc_remove(struct platform_device *pdev)
        fimc_clk_put(fimc);
 
        dev_info(&pdev->dev, "driver unloaded\n");
-       return 0;
 }
 
 /* S5PV210, S5PC110 */
@@ -1160,7 +1159,7 @@ static const struct dev_pm_ops fimc_pm_ops = {
 
 static struct platform_driver fimc_driver = {
        .probe          = fimc_probe,
-       .remove         = fimc_remove,
+       .remove_new     = fimc_remove,
        .driver = {
                .of_match_table = fimc_of_match,
                .name           = FIMC_DRIVER_NAME,
index 5d9f4c1cdc5ed4ded73d8214a83c4f520f4c4a50..7a48fad1df161c67f927fa61541c2dfebc0080f9 100644 (file)
@@ -54,7 +54,7 @@ const char *fimc_is_param_strerr(unsigned int error)
        case ERROR_DMA_INPUT_ORDER:
                return "ERROR_DMA_INPUT_ORDER: Invalid order(DRC: YYCbCr,YCbYCr,FD:NO,YYCbCr,YCbYCr,CbCr,CrCb)";
        case ERROR_DMA_INPUT_PLANE:
-               return "ERROR_DMA_INPUT_PLANE: Invalid palne (DRC: 3, FD: 1, 2, 3)";
+               return "ERROR_DMA_INPUT_PLANE: Invalid plane (DRC: 3, FD: 1, 2, 3)";
        case ERROR_OTF_OUTPUT_WIDTH:
                return "ERROR_OTF_OUTPUT_WIDTH: Invalid width (DRC: 128~8192)";
        case ERROR_OTF_OUTPUT_HEIGHT:
index 9dcbb9853ac0ba44aaf2ae40f2374fdc56df74e4..809e117331c0bc74360572bb017ca2d60db8f715 100644 (file)
@@ -156,7 +156,7 @@ enum fimc_is_error {
        ERROR_DMA_INPUT_BIT_WIDTH       = 34,
        /* invalid order(DRC: YYCbCrorYCbYCr, FD:NO,YYCbCr,YCbYCr,CbCr,CrCb) */
        ERROR_DMA_INPUT_ORDER           = 35,
-       /* invalid palne (DRC: 3, FD: 1, 2, 3) */
+       /* invalid plane (DRC: 3, FD: 1, 2, 3) */
        ERROR_DMA_INPUT_PLANE           = 36,
 
        ERROR_OTF_OUTPUT_NONE           = ERROR_COMMON_NONE,
index 83a28ef8e099e72f2aeba3a2ba34b37f106930fd..bef6e9b4a25ea9e234a9114700fb2411947a0cb2 100644 (file)
@@ -82,14 +82,12 @@ err_pm_dis:
        return ret;
 }
 
-static int fimc_is_i2c_remove(struct platform_device *pdev)
+static void fimc_is_i2c_remove(struct platform_device *pdev)
 {
        struct fimc_is_i2c *isp_i2c = platform_get_drvdata(pdev);
 
        pm_runtime_disable(&pdev->dev);
        i2c_del_adapter(&isp_i2c->adapter);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -140,7 +138,7 @@ static const struct of_device_id fimc_is_i2c_of_match[] = {
 
 static struct platform_driver fimc_is_i2c_driver = {
        .probe          = fimc_is_i2c_probe,
-       .remove         = fimc_is_i2c_remove,
+       .remove_new     = fimc_is_i2c_remove,
        .driver = {
                .of_match_table = fimc_is_i2c_of_match,
                .name           = "fimc-isp-i2c",
index a7704ff069d6c4c7fb2c5936b9f903da2f50d40d..530a148fe4d3825312af1f4b1e45ef3d61e8b490 100644 (file)
@@ -915,7 +915,7 @@ static int fimc_is_suspend(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-static int fimc_is_remove(struct platform_device *pdev)
+static void fimc_is_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct fimc_is *is = dev_get_drvdata(dev);
@@ -932,8 +932,6 @@ static int fimc_is_remove(struct platform_device *pdev)
        fimc_is_debugfs_remove(is);
        release_firmware(is->fw.f_w);
        fimc_is_free_cpu_memory(is);
-
-       return 0;
 }
 
 static const struct of_device_id fimc_is_of_match[] = {
@@ -950,7 +948,7 @@ static const struct dev_pm_ops fimc_is_pm_ops = {
 
 static struct platform_driver fimc_is_driver = {
        .probe          = fimc_is_probe,
-       .remove         = fimc_is_remove,
+       .remove_new     = fimc_is_remove,
        .driver = {
                .of_match_table = fimc_is_of_match,
                .name           = FIMC_IS_DRV_NAME,
index f6a302fa8d3774abdff523db35ff813e1f49f80e..8fa26969c4111ecdb97b1174f579187df6520add 100644 (file)
@@ -449,17 +449,22 @@ static int isp_video_s_fmt_mplane(struct file *file, void *priv,
 static int isp_video_pipeline_validate(struct fimc_isp *isp)
 {
        struct v4l2_subdev *sd = &isp->subdev;
-       struct v4l2_subdev_format sink_fmt, src_fmt;
        struct media_pad *pad;
        int ret;
 
        while (1) {
+               struct v4l2_subdev_format sink_fmt = {
+                       .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               };
+               struct v4l2_subdev_format src_fmt = {
+                       .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               };
+
                /* Retrieve format at the sink pad */
                pad = &sd->entity.pads[0];
                if (!(pad->flags & MEDIA_PAD_FL_SINK))
                        break;
                sink_fmt.pad = pad->index;
-               sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sink_fmt);
                if (ret < 0 && ret != -ENOIOCTLCMD)
                        return -EPIPE;
@@ -471,7 +476,6 @@ static int isp_video_pipeline_validate(struct fimc_isp *isp)
 
                sd = media_entity_to_v4l2_subdev(pad->entity);
                src_fmt.pad = pad->index;
-               src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
                if (ret < 0 && ret != -ENOIOCTLCMD)
                        return -EPIPE;
index e185a40305a8f492febdcdfcb4e043a324bf57f1..24b3dda26714b97f7492b81a3dfcbc1bcd19ade5 100644 (file)
@@ -765,7 +765,12 @@ static int fimc_lite_s_fmt_mplane(struct file *file, void *priv,
 static int fimc_pipeline_validate(struct fimc_lite *fimc)
 {
        struct v4l2_subdev *sd = &fimc->subdev;
-       struct v4l2_subdev_format sink_fmt, src_fmt;
+       struct v4l2_subdev_format sink_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
+       struct v4l2_subdev_format src_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct media_pad *pad;
        int ret;
 
@@ -782,7 +787,6 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
                        sink_fmt.format.code = fimc->inp_frame.fmt->mbus_code;
                } else {
                        sink_fmt.pad = pad->index;
-                       sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                        ret = v4l2_subdev_call(sd, pad, get_fmt, NULL,
                                               &sink_fmt);
                        if (ret < 0 && ret != -ENOIOCTLCMD)
@@ -795,7 +799,6 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc)
 
                sd = media_entity_to_v4l2_subdev(pad->entity);
                src_fmt.pad = pad->index;
-               src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
                if (ret < 0 && ret != -ENOIOCTLCMD)
                        return -EPIPE;
@@ -1595,7 +1598,7 @@ static int fimc_lite_suspend(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-static int fimc_lite_remove(struct platform_device *pdev)
+static void fimc_lite_remove(struct platform_device *pdev)
 {
        struct fimc_lite *fimc = platform_get_drvdata(pdev);
        struct device *dev = &pdev->dev;
@@ -1610,7 +1613,6 @@ static int fimc_lite_remove(struct platform_device *pdev)
        fimc_lite_clk_put(fimc);
 
        dev_info(dev, "Driver unloaded\n");
-       return 0;
 }
 
 static const struct dev_pm_ops fimc_lite_pm_ops = {
@@ -1656,7 +1658,7 @@ MODULE_DEVICE_TABLE(of, flite_of_match);
 
 static struct platform_driver fimc_lite_driver = {
        .probe          = fimc_lite_probe,
-       .remove         = fimc_lite_remove,
+       .remove_new     = fimc_lite_remove,
        .driver = {
                .of_match_table = flite_of_match,
                .name           = FIMC_LITE_DRV_NAME,
index 98a60f01129d41bbaba43c23fc19493b9c3e45a1..c9cb9a216fae1edde03a1075a8651b07fc99d732 100644 (file)
@@ -1440,6 +1440,10 @@ static int fimc_md_probe(struct platform_device *pdev)
        if (!fmd)
                return -ENOMEM;
 
+       ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+       if (ret < 0)
+               return -ENOMEM;
+
        spin_lock_init(&fmd->slock);
        INIT_LIST_HEAD(&fmd->pipelines);
        fmd->pdev = pdev;
@@ -1470,10 +1474,8 @@ static int fimc_md_probe(struct platform_device *pdev)
                goto err_v4l2dev;
 
        pinctrl = devm_pinctrl_get(dev);
-       if (IS_ERR(pinctrl)) {
-               ret = dev_err_probe(dev, PTR_ERR(pinctrl), "Failed to get pinctrl\n");
-               goto err_clk;
-       }
+       if (IS_ERR(pinctrl))
+               dev_dbg(dev, "Failed to get pinctrl: %pe\n", pinctrl);
 
        platform_set_drvdata(pdev, fmd);
 
@@ -1530,12 +1532,12 @@ err_md:
        return ret;
 }
 
-static int fimc_md_remove(struct platform_device *pdev)
+static void fimc_md_remove(struct platform_device *pdev)
 {
        struct fimc_md *fmd = platform_get_drvdata(pdev);
 
        if (!fmd)
-               return 0;
+               return;
 
        fimc_md_unregister_clk_provider(fmd);
        v4l2_async_nf_unregister(&fmd->subdev_notifier);
@@ -1548,8 +1550,6 @@ static int fimc_md_remove(struct platform_device *pdev)
        media_device_unregister(&fmd->media_dev);
        media_device_cleanup(&fmd->media_dev);
        fimc_md_put_clocks(fmd);
-
-       return 0;
 }
 
 static const struct platform_device_id fimc_driver_ids[] __always_unused = {
@@ -1566,7 +1566,7 @@ MODULE_DEVICE_TABLE(of, fimc_md_of_match);
 
 static struct platform_driver fimc_md_driver = {
        .probe          = fimc_md_probe,
-       .remove         = fimc_md_remove,
+       .remove_new     = fimc_md_remove,
        .driver = {
                .of_match_table = of_match_ptr(fimc_md_of_match),
                .name           = "s5p-fimc-md",
index 6a0d35f33e8c6d84655a47c743154c5f07d201b0..686ca8753ba22aaf17e333c9abe1c44685cdddc4 100644 (file)
@@ -975,7 +975,7 @@ static int s5pcsis_runtime_resume(struct device *dev)
 }
 #endif
 
-static int s5pcsis_remove(struct platform_device *pdev)
+static void s5pcsis_remove(struct platform_device *pdev)
 {
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct csis_state *state = sd_to_csis_state(sd);
@@ -987,8 +987,6 @@ static int s5pcsis_remove(struct platform_device *pdev)
        s5pcsis_clk_put(state);
 
        media_entity_cleanup(&state->sd.entity);
-
-       return 0;
 }
 
 static const struct dev_pm_ops s5pcsis_pm_ops = {
@@ -1022,7 +1020,7 @@ MODULE_DEVICE_TABLE(of, s5pcsis_of_match);
 
 static struct platform_driver s5pcsis_driver = {
        .probe          = s5pcsis_probe,
-       .remove         = s5pcsis_remove,
+       .remove_new     = s5pcsis_remove,
        .driver         = {
                .of_match_table = s5pcsis_of_match,
                .name           = CSIS_DRIVER_NAME,
index db106ebdf870a4c70ec1f23eff139c9d09a605f1..76634d242b10305b7e02cb16a4886e39d5b2afb6 100644 (file)
@@ -806,7 +806,9 @@ static int s3c_camif_vidioc_s_fmt(struct file *file, void *priv,
 /* Only check pixel formats at the sensor and the camif subdev pads */
 static int camif_pipeline_validate(struct camif_dev *camif)
 {
-       struct v4l2_subdev_format src_fmt;
+       struct v4l2_subdev_format src_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct media_pad *pad;
        int ret;
 
@@ -816,7 +818,6 @@ static int camif_pipeline_validate(struct camif_dev *camif)
                return -EPIPE;
 
        src_fmt.pad = pad->index;
-       src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(camif->sensor.sd, pad, get_fmt, NULL, &src_fmt);
        if (ret < 0 && ret != -ENOIOCTLCMD)
                return -EPIPE;
index 6e8ef86566b78d50bba39a2e8cae6540c6a9ae01..afe1fcc37354b7f0ac505321b633c7d00c4c29b7 100644 (file)
@@ -190,7 +190,9 @@ static int camif_register_sensor(struct camif_dev *camif)
        struct s3c_camif_sensor_info *sensor = &camif->pdata.sensor;
        struct v4l2_device *v4l2_dev = &camif->v4l2_dev;
        struct i2c_adapter *adapter;
-       struct v4l2_subdev_format format;
+       struct v4l2_subdev_format format = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *sd;
        int ret;
 
@@ -220,7 +222,6 @@ static int camif_register_sensor(struct camif_dev *camif)
 
        /* Get initial pixel format and set it at the camif sink pad */
        format.pad = 0;
-       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &format);
 
        if (ret < 0)
@@ -507,7 +508,7 @@ err_sd:
        return ret;
 }
 
-static int s3c_camif_remove(struct platform_device *pdev)
+static void s3c_camif_remove(struct platform_device *pdev)
 {
        struct camif_dev *camif = platform_get_drvdata(pdev);
        struct s3c_camif_plat_data *pdata = &camif->pdata;
@@ -521,8 +522,6 @@ static int s3c_camif_remove(struct platform_device *pdev)
        camif_clk_put(camif);
        s3c_camif_unregister_subdev(camif);
        pdata->gpio_put();
-
-       return 0;
 }
 
 static int s3c_camif_runtime_resume(struct device *dev)
@@ -623,7 +622,7 @@ static const struct dev_pm_ops s3c_camif_pm_ops = {
 
 static struct platform_driver s3c_camif_driver = {
        .probe          = s3c_camif_probe,
-       .remove         = s3c_camif_remove,
+       .remove_new     = s3c_camif_remove,
        .id_table       = s3c_camif_driver_ids,
        .driver = {
                .name   = S3C_CAMIF_DRIVER_NAME,
index dd8864779a7cbffaaa6a3c525f1aff44580d8636..89aeba47ed079ea15342b55e543747f836122d08 100644 (file)
@@ -740,7 +740,7 @@ put_clk:
        return ret;
 }
 
-static int g2d_remove(struct platform_device *pdev)
+static void g2d_remove(struct platform_device *pdev)
 {
        struct g2d_dev *dev = platform_get_drvdata(pdev);
 
@@ -753,7 +753,6 @@ static int g2d_remove(struct platform_device *pdev)
        clk_put(dev->gate);
        clk_unprepare(dev->clk);
        clk_put(dev->clk);
-       return 0;
 }
 
 static struct g2d_variant g2d_drvdata_v3x = {
@@ -778,7 +777,7 @@ MODULE_DEVICE_TABLE(of, exynos_g2d_match);
 
 static struct platform_driver g2d_pdrv = {
        .probe          = g2d_probe,
-       .remove         = g2d_remove,
+       .remove_new     = g2d_remove,
        .driver         = {
                .name = G2D_NAME,
                .of_match_table = exynos_g2d_match,
index 55814041b8d8f3f6578c9a25bce1f588d94af184..c3c7e48f1b6eaea78602146903c96582a3bee360 100644 (file)
@@ -2991,7 +2991,7 @@ device_register_rollback:
        return ret;
 }
 
-static int s5p_jpeg_remove(struct platform_device *pdev)
+static void s5p_jpeg_remove(struct platform_device *pdev)
 {
        struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
        int i;
@@ -3008,8 +3008,6 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
                for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
                        clk_disable_unprepare(jpeg->clocks[i]);
        }
-
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -3164,7 +3162,7 @@ static void *jpeg_get_drv_data(struct device *dev)
 
 static struct platform_driver s5p_jpeg_driver = {
        .probe = s5p_jpeg_probe,
-       .remove = s5p_jpeg_remove,
+       .remove_new = s5p_jpeg_remove,
        .driver = {
                .of_match_table = of_match_ptr(samsung_jpeg_match),
                .name           = S5P_JPEG_M2M_NAME,
index 9d2cce124a34c8bef397adf091b9aeacde1f6c6b..e30e54935d79a9f10bda2b11d192256c4d11e9f5 100644 (file)
@@ -1431,7 +1431,7 @@ err_dma:
 }
 
 /* Remove the driver */
-static int s5p_mfc_remove(struct platform_device *pdev)
+static void s5p_mfc_remove(struct platform_device *pdev)
 {
        struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
        struct s5p_mfc_ctx *ctx;
@@ -1463,7 +1463,6 @@ static int s5p_mfc_remove(struct platform_device *pdev)
        s5p_mfc_unconfigure_dma_memory(dev);
 
        s5p_mfc_final_pm(dev);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1690,7 +1689,7 @@ MODULE_DEVICE_TABLE(of, exynos_mfc_match);
 
 static struct platform_driver s5p_mfc_driver = {
        .probe          = s5p_mfc_probe,
-       .remove         = s5p_mfc_remove,
+       .remove_new     = s5p_mfc_remove,
        .driver = {
                .name   = S5P_MFC_NAME,
                .pm     = &s5p_mfc_pm_ops,
index dd74cc43920d3ce5a469bfa862c83d19b65d62d7..1328b4eb6b9ff8e8ddcb47ba21eee6bc9f6ed935 100644 (file)
@@ -1257,7 +1257,7 @@ static const struct dev_pm_ops bdisp_pm_ops = {
        .runtime_resume         = bdisp_runtime_resume,
 };
 
-static int bdisp_remove(struct platform_device *pdev)
+static void bdisp_remove(struct platform_device *pdev)
 {
        struct bdisp_dev *bdisp = platform_get_drvdata(pdev);
 
@@ -1277,8 +1277,6 @@ static int bdisp_remove(struct platform_device *pdev)
        destroy_workqueue(bdisp->work_queue);
 
        dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
-
-       return 0;
 }
 
 static int bdisp_probe(struct platform_device *pdev)
@@ -1309,6 +1307,8 @@ static int bdisp_probe(struct platform_device *pdev)
        init_waitqueue_head(&bdisp->irq_queue);
        INIT_DELAYED_WORK(&bdisp->timeout_work, bdisp_irq_timeout);
        bdisp->work_queue = create_workqueue(BDISP_NAME);
+       if (!bdisp->work_queue)
+               return -ENOMEM;
 
        spin_lock_init(&bdisp->slock);
        mutex_init(&bdisp->lock);
@@ -1411,7 +1411,7 @@ MODULE_DEVICE_TABLE(of, bdisp_match_types);
 
 static struct platform_driver bdisp_driver = {
        .probe          = bdisp_probe,
-       .remove         = bdisp_remove,
+       .remove_new     = bdisp_remove,
        .driver         = {
                .name           = BDISP_NAME,
                .of_match_table = bdisp_match_types,
index c38b62d4f1aee8cec36954246ada4194abe34d92..45ade7210d26fccbccb29aa38152ff01e052d201 100644 (file)
@@ -878,7 +878,7 @@ err_clk_disable:
        return ret;
 }
 
-static int c8sectpfe_remove(struct platform_device *pdev)
+static void c8sectpfe_remove(struct platform_device *pdev)
 {
        struct c8sectpfei *fei = platform_get_drvdata(pdev);
        struct channel_info *channel;
@@ -910,8 +910,6 @@ static int c8sectpfe_remove(struct platform_device *pdev)
                writel(0, fei->io + SYS_OTHER_CLKEN);
 
        clk_disable_unprepare(fei->c8sectpfeclk);
-
-       return 0;
 }
 
 
@@ -1178,7 +1176,7 @@ static struct platform_driver c8sectpfe_driver = {
                .of_match_table = of_match_ptr(c8sectpfe_match),
        },
        .probe  = c8sectpfe_probe,
-       .remove = c8sectpfe_remove,
+       .remove_new = c8sectpfe_remove,
 };
 
 module_platform_driver(c8sectpfe_driver);
index 03eaee6d15da01a080670cae231c39e261b74b01..da402d1e9171a0b0925d4fd41e7743620063aa7e 100644 (file)
@@ -1900,7 +1900,7 @@ err:
        return ret;
 }
 
-static int delta_remove(struct platform_device *pdev)
+static void delta_remove(struct platform_device *pdev)
 {
        struct delta_dev *delta = platform_get_drvdata(pdev);
 
@@ -1914,8 +1914,6 @@ static int delta_remove(struct platform_device *pdev)
        pm_runtime_disable(delta->dev);
 
        v4l2_device_unregister(&delta->v4l2_dev);
-
-       return 0;
 }
 
 static int delta_runtime_suspend(struct device *dev)
@@ -1956,7 +1954,7 @@ MODULE_DEVICE_TABLE(of, delta_match_types);
 
 static struct platform_driver delta_driver = {
        .probe = delta_probe,
-       .remove = delta_remove,
+       .remove_new = delta_remove,
        .driver = {
                   .name = DELTA_NAME,
                   .of_match_table = delta_match_types,
index bb34d6997d99158d86d077bdc7331a593d63749a..3a848ca32a0ef26fec271cf1790bfc16a066bd3a 100644 (file)
@@ -1422,7 +1422,7 @@ err:
        return ret;
 }
 
-static int hva_remove(struct platform_device *pdev)
+static void hva_remove(struct platform_device *pdev)
 {
        struct hva_dev *hva = platform_get_drvdata(pdev);
        struct device *dev = hva_to_dev(hva);
@@ -1440,8 +1440,6 @@ static int hva_remove(struct platform_device *pdev)
        v4l2_device_unregister(&hva->v4l2_dev);
 
        dev_info(dev, "%s %s removed\n", HVA_PREFIX, pdev->name);
-
-       return 0;
 }
 
 /* PM ops */
@@ -1461,7 +1459,7 @@ MODULE_DEVICE_TABLE(of, hva_match_types);
 
 static struct platform_driver hva_driver = {
        .probe  = hva_probe,
-       .remove = hva_remove,
+       .remove_new = hva_remove,
        .driver = {
                .name           = HVA_NAME,
                .of_match_table = hva_match_types,
index 9706aa41b5d2836fce6580536ceca608e330b41f..92f1edee58f8992136461b76d97081a02877e2ae 100644 (file)
@@ -603,7 +603,6 @@ static int dma2d_probe(struct platform_device *pdev)
 {
        struct dma2d_dev *dev;
        struct video_device *vfd;
-       struct resource *res;
        int ret = 0;
 
        dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -614,9 +613,7 @@ static int dma2d_probe(struct platform_device *pdev)
        mutex_init(&dev->mutex);
        atomic_set(&dev->num_inst, 0);
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       dev->regs = devm_ioremap_resource(&pdev->dev, res);
+       dev->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(dev->regs))
                return PTR_ERR(dev->regs);
 
@@ -696,7 +693,7 @@ put_clk_gate:
        return ret;
 }
 
-static int dma2d_remove(struct platform_device *pdev)
+static void dma2d_remove(struct platform_device *pdev)
 {
        struct dma2d_dev *dev = platform_get_drvdata(pdev);
 
@@ -707,8 +704,6 @@ static int dma2d_remove(struct platform_device *pdev)
        vb2_dma_contig_clear_max_seg_size(&pdev->dev);
        clk_unprepare(dev->gate);
        clk_put(dev->gate);
-
-       return 0;
 }
 
 static const struct of_device_id stm32_dma2d_match[] = {
@@ -722,7 +717,7 @@ MODULE_DEVICE_TABLE(of, stm32_dma2d_match);
 
 static struct platform_driver dma2d_pdrv = {
        .probe          = dma2d_probe,
-       .remove         = dma2d_remove,
+       .remove_new     = dma2d_remove,
        .driver         = {
                .name = DMA2D_NAME,
                .of_match_table = stm32_dma2d_match,
index 3f03a7ca9ee31cbf7e9d251d02fd2b9d5828fd8a..af12739fc774664e14ddc275b71bd063e75b10df 100644 (file)
@@ -90,8 +90,6 @@ struct dma2d_ctx {
        struct dma2d_frame      cap;
        struct dma2d_frame      out;
        struct dma2d_frame      bg;
-       /* fb_buf always point to bg address */
-       struct v4l2_framebuffer fb_buf;
        /*
         * MODE[17:16] of DMA2D_CR
         */
index ad8e9742e1ae7809885af2b8c8dffaedeaeaf536..dad6e22e4ce42c3030787b05745c8938cacfd018 100644 (file)
@@ -2084,6 +2084,7 @@ static int dcmi_probe(struct platform_device *pdev)
        q->mem_ops = &vb2_dma_contig_memops;
        q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        q->min_buffers_needed = 2;
+       q->allow_cache_hints = 1;
        q->dev = &pdev->dev;
 
        ret = vb2_queue_init(q);
@@ -2134,7 +2135,7 @@ err_media_device_cleanup:
        return ret;
 }
 
-static int dcmi_remove(struct platform_device *pdev)
+static void dcmi_remove(struct platform_device *pdev)
 {
        struct stm32_dcmi *dcmi = platform_get_drvdata(pdev);
 
@@ -2147,8 +2148,6 @@ static int dcmi_remove(struct platform_device *pdev)
        media_device_cleanup(&dcmi->mdev);
 
        dma_release_channel(dcmi->dma_chan);
-
-       return 0;
 }
 
 static __maybe_unused int dcmi_runtime_suspend(struct device *dev)
@@ -2202,7 +2201,7 @@ static const struct dev_pm_ops dcmi_pm_ops = {
 
 static struct platform_driver stm32_dcmi_driver = {
        .probe          = dcmi_probe,
-       .remove         = dcmi_remove,
+       .remove_new     = dcmi_remove,
        .driver         = {
                .name = DRV_NAME,
                .of_match_table = of_match_ptr(stm32_dcmi_of_match),
index 86c5235a0c7aa6d7515ad2d94d37d4ee6a39de8f..d6e7d1b360836579ae0f0073e4edf9af7f2f08dd 100644 (file)
@@ -260,7 +260,7 @@ err_clean_pad:
        return ret;
 }
 
-static int sun4i_csi_remove(struct platform_device *pdev)
+static void sun4i_csi_remove(struct platform_device *pdev)
 {
        struct sun4i_csi *csi = platform_get_drvdata(pdev);
 
@@ -271,8 +271,6 @@ static int sun4i_csi_remove(struct platform_device *pdev)
        media_device_unregister(&csi->mdev);
        sun4i_csi_dma_unregister(csi);
        media_device_cleanup(&csi->mdev);
-
-       return 0;
 }
 
 static const struct sun4i_csi_traits sun4i_a10_csi1_traits = {
@@ -330,7 +328,7 @@ static const struct dev_pm_ops sun4i_csi_pm_ops = {
 
 static struct platform_driver sun4i_csi_driver = {
        .probe  = sun4i_csi_probe,
-       .remove = sun4i_csi_remove,
+       .remove_new = sun4i_csi_remove,
        .driver = {
                .name           = "sun4i-csi",
                .of_match_table = sun4i_csi_of_match,
index e3e6650181c88849552773e1c0fb6354407eba6a..e2723cfa4515bf1dc702fdd84c1fb509755795e2 100644 (file)
@@ -375,7 +375,7 @@ error_resources:
        return ret;
 }
 
-static int sun6i_csi_remove(struct platform_device *pdev)
+static void sun6i_csi_remove(struct platform_device *pdev)
 {
        struct sun6i_csi_device *csi_dev = platform_get_drvdata(pdev);
 
@@ -386,8 +386,6 @@ static int sun6i_csi_remove(struct platform_device *pdev)
                sun6i_csi_v4l2_cleanup(csi_dev);
 
        sun6i_csi_resources_cleanup(csi_dev);
-
-       return 0;
 }
 
 static const struct sun6i_csi_variant sun6i_a31_csi_variant = {
@@ -426,7 +424,7 @@ MODULE_DEVICE_TABLE(of, sun6i_csi_of_match);
 
 static struct platform_driver sun6i_csi_platform_driver = {
        .probe  = sun6i_csi_probe,
-       .remove = sun6i_csi_remove,
+       .remove_new = sun6i_csi_remove,
        .driver = {
                .name           = SUN6I_CSI_NAME,
                .of_match_table = of_match_ptr(sun6i_csi_of_match),
index a220ce849b4136cc99cf4b763a009a536b498d36..dce130b4c9f6f1ff459ee2d6588b150aca483b67 100644 (file)
@@ -737,15 +737,13 @@ error_resources:
        return ret;
 }
 
-static int sun6i_mipi_csi2_remove(struct platform_device *platform_dev)
+static void sun6i_mipi_csi2_remove(struct platform_device *platform_dev)
 {
        struct sun6i_mipi_csi2_device *csi2_dev =
                platform_get_drvdata(platform_dev);
 
        sun6i_mipi_csi2_bridge_cleanup(csi2_dev);
        sun6i_mipi_csi2_resources_cleanup(csi2_dev);
-
-       return 0;
 }
 
 static const struct of_device_id sun6i_mipi_csi2_of_match[] = {
@@ -756,7 +754,7 @@ MODULE_DEVICE_TABLE(of, sun6i_mipi_csi2_of_match);
 
 static struct platform_driver sun6i_mipi_csi2_platform_driver = {
        .probe  = sun6i_mipi_csi2_probe,
-       .remove = sun6i_mipi_csi2_remove,
+       .remove_new = sun6i_mipi_csi2_remove,
        .driver = {
                .name           = SUN6I_MIPI_CSI2_NAME,
                .of_match_table = of_match_ptr(sun6i_mipi_csi2_of_match),
index cd2e92ae22933acdca99b8563e6f173160e7be5f..23d32e198aaae45c515a96b1656a15286cae35d0 100644 (file)
@@ -804,15 +804,13 @@ error_resources:
        return ret;
 }
 
-static int sun8i_a83t_mipi_csi2_remove(struct platform_device *platform_dev)
+static void sun8i_a83t_mipi_csi2_remove(struct platform_device *platform_dev)
 {
        struct sun8i_a83t_mipi_csi2_device *csi2_dev =
                platform_get_drvdata(platform_dev);
 
        sun8i_a83t_mipi_csi2_bridge_cleanup(csi2_dev);
        sun8i_a83t_mipi_csi2_resources_cleanup(csi2_dev);
-
-       return 0;
 }
 
 static const struct of_device_id sun8i_a83t_mipi_csi2_of_match[] = {
@@ -823,7 +821,7 @@ MODULE_DEVICE_TABLE(of, sun8i_a83t_mipi_csi2_of_match);
 
 static struct platform_driver sun8i_a83t_mipi_csi2_platform_driver = {
        .probe  = sun8i_a83t_mipi_csi2_probe,
-       .remove = sun8i_a83t_mipi_csi2_remove,
+       .remove_new = sun8i_a83t_mipi_csi2_remove,
        .driver = {
                .name           = SUN8I_A83T_MIPI_CSI2_NAME,
                .of_match_table = of_match_ptr(sun8i_a83t_mipi_csi2_of_match),
index aa65d70b6270a70ced67d3a880e43ec65a17d71b..e4b0fd793f55827979a86de214283277a395c0bb 100644 (file)
@@ -906,7 +906,7 @@ err_v4l2:
        return ret;
 }
 
-static int deinterlace_remove(struct platform_device *pdev)
+static void deinterlace_remove(struct platform_device *pdev)
 {
        struct deinterlace_dev *dev = platform_get_drvdata(pdev);
 
@@ -915,8 +915,6 @@ static int deinterlace_remove(struct platform_device *pdev)
        v4l2_device_unregister(&dev->v4l2_dev);
 
        pm_runtime_force_suspend(&pdev->dev);
-
-       return 0;
 }
 
 static int deinterlace_runtime_resume(struct device *device)
@@ -1002,7 +1000,7 @@ static const struct dev_pm_ops deinterlace_pm_ops = {
 
 static struct platform_driver deinterlace_driver = {
        .probe          = deinterlace_probe,
-       .remove         = deinterlace_remove,
+       .remove_new     = deinterlace_remove,
        .driver         = {
                .name           = DEINTERLACE_NAME,
                .of_match_table = deinterlace_dt_match,
index fbcca59a0517ce2b2a9b9dcdbd44f0fae7b0678c..bd0c4257bbff7fe25e918a0eee8fc1f24adb3f81 100644 (file)
@@ -833,7 +833,7 @@ err_v4l2:
        return ret;
 }
 
-static int rotate_remove(struct platform_device *pdev)
+static void rotate_remove(struct platform_device *pdev)
 {
        struct rotate_dev *dev = platform_get_drvdata(pdev);
 
@@ -842,8 +842,6 @@ static int rotate_remove(struct platform_device *pdev)
        v4l2_device_unregister(&dev->v4l2_dev);
 
        pm_runtime_force_suspend(&pdev->dev);
-
-       return 0;
 }
 
 static int rotate_runtime_resume(struct device *device)
@@ -907,7 +905,7 @@ static const struct dev_pm_ops rotate_pm_ops = {
 
 static struct platform_driver rotate_driver = {
        .probe          = rotate_probe,
-       .remove         = rotate_remove,
+       .remove_new     = rotate_remove,
        .driver         = {
                .name           = ROTATE_NAME,
                .of_match_table = rotate_dt_match,
index 2dfae9bc0bba8a547b50ba5abfbae6c0c702e338..ffe1887cc429b67f739b6e3c519fcb5f455c2775 100644 (file)
@@ -1285,13 +1285,13 @@ static int __subdev_get_format(struct vpfe_device *vpfe,
                               struct v4l2_mbus_framefmt *fmt)
 {
        struct v4l2_subdev *sd = vpfe->current_subdev->sd;
-       struct v4l2_subdev_format sd_fmt;
+       struct v4l2_subdev_format sd_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .pad = 0,
+       };
        struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
        int ret;
 
-       sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-       sd_fmt.pad = 0;
-
        ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt);
        if (ret)
                return ret;
@@ -1309,12 +1309,13 @@ static int __subdev_set_format(struct vpfe_device *vpfe,
                               struct v4l2_mbus_framefmt *fmt)
 {
        struct v4l2_subdev *sd = vpfe->current_subdev->sd;
-       struct v4l2_subdev_format sd_fmt;
+       struct v4l2_subdev_format sd_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .pad = 0,
+       };
        struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
        int ret;
 
-       sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-       sd_fmt.pad = 0;
        *mbus_fmt = *fmt;
 
        ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sd_fmt);
@@ -1393,7 +1394,9 @@ static int vpfe_try_fmt(struct file *file, void *priv,
        struct vpfe_device *vpfe = video_drvdata(file);
        struct v4l2_subdev *sd = vpfe->current_subdev->sd;
        const struct vpfe_fmt *fmt;
-       struct v4l2_subdev_frame_size_enum fse;
+       struct v4l2_subdev_frame_size_enum fse = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret, found;
 
        fmt = find_format_by_pix(vpfe, f->fmt.pix.pixelformat);
@@ -1412,7 +1415,6 @@ static int vpfe_try_fmt(struct file *file, void *priv,
        found = false;
        fse.pad = 0;
        fse.code = fmt->code;
-       fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        for (fse.index = 0; ; fse.index++) {
                ret = v4l2_subdev_call(sd, pad, enum_frame_size,
                                       NULL, &fse);
@@ -1499,7 +1501,9 @@ static int vpfe_enum_size(struct file *file, void  *priv,
                          struct v4l2_frmsizeenum *fsize)
 {
        struct vpfe_device *vpfe = video_drvdata(file);
-       struct v4l2_subdev_frame_size_enum fse;
+       struct v4l2_subdev_frame_size_enum fse = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *sd = vpfe->current_subdev->sd;
        struct vpfe_fmt *fmt;
        int ret;
@@ -1514,11 +1518,9 @@ static int vpfe_enum_size(struct file *file, void  *priv,
 
        memset(fsize->reserved, 0x0, sizeof(fsize->reserved));
 
-       memset(&fse, 0x0, sizeof(fse));
        fse.index = fsize->index;
        fse.pad = 0;
        fse.code = fmt->code;
-       fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(sd, pad, enum_frame_size, NULL, &fse);
        if (ret)
                return ret;
@@ -2146,7 +2148,6 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
 {
        struct vpfe_device *vpfe = container_of(notifier->v4l2_dev,
                                               struct vpfe_device, v4l2_dev);
-       struct v4l2_subdev_mbus_code_enum mbus_code;
        struct vpfe_subdev_info *sdinfo;
        struct vpfe_fmt *fmt;
        int ret = 0;
@@ -2173,9 +2174,11 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
 
        vpfe->num_active_fmt = 0;
        for (j = 0, i = 0; (ret != -EINVAL); ++j) {
-               memset(&mbus_code, 0, sizeof(mbus_code));
-               mbus_code.index = j;
-               mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+               struct v4l2_subdev_mbus_code_enum mbus_code = {
+                       .index = j,
+                       .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               };
+
                ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
                                       NULL, &mbus_code);
                if (ret)
@@ -2483,7 +2486,7 @@ probe_out_cleanup:
 /*
  * vpfe_remove : It un-register device from V4L2 driver
  */
-static int vpfe_remove(struct platform_device *pdev)
+static void vpfe_remove(struct platform_device *pdev)
 {
        struct vpfe_device *vpfe = platform_get_drvdata(pdev);
 
@@ -2493,8 +2496,6 @@ static int vpfe_remove(struct platform_device *pdev)
        v4l2_async_nf_cleanup(&vpfe->notifier);
        v4l2_device_unregister(&vpfe->v4l2_dev);
        video_unregister_device(&vpfe->video_dev);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -2625,7 +2626,7 @@ MODULE_DEVICE_TABLE(of, vpfe_of_match);
 
 static struct platform_driver vpfe_driver = {
        .probe          = vpfe_probe,
-       .remove         = vpfe_remove,
+       .remove_new     = vpfe_remove,
        .driver = {
                .name   = VPFE_MODULE_NAME,
                .pm     = &vpfe_pm_ops,
index 4eade409d5d36ee79ac28f030b496761e71fd415..ca906a9e42229feb4170dd7a7fec540771965c20 100644 (file)
@@ -117,13 +117,13 @@ static int cal_legacy_enum_fmt_vid_cap(struct file *file, void *priv,
 static int __subdev_get_format(struct cal_ctx *ctx,
                               struct v4l2_mbus_framefmt *fmt)
 {
-       struct v4l2_subdev_format sd_fmt;
+       struct v4l2_subdev_format sd_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .pad = 0,
+       };
        struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
        int ret;
 
-       sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-       sd_fmt.pad = 0;
-
        ret = v4l2_subdev_call(ctx->phy->source, pad, get_fmt, NULL, &sd_fmt);
        if (ret)
                return ret;
@@ -139,12 +139,13 @@ static int __subdev_get_format(struct cal_ctx *ctx,
 static int __subdev_set_format(struct cal_ctx *ctx,
                               struct v4l2_mbus_framefmt *fmt)
 {
-       struct v4l2_subdev_format sd_fmt;
+       struct v4l2_subdev_format sd_fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .pad = 0,
+       };
        struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
        int ret;
 
-       sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-       sd_fmt.pad = 0;
        *mbus_fmt = *fmt;
 
        ret = v4l2_subdev_call(ctx->phy->source, pad, set_fmt, NULL, &sd_fmt);
@@ -190,7 +191,9 @@ static int cal_legacy_try_fmt_vid_cap(struct file *file, void *priv,
 {
        struct cal_ctx *ctx = video_drvdata(file);
        const struct cal_format_info *fmtinfo;
-       struct v4l2_subdev_frame_size_enum fse;
+       struct v4l2_subdev_frame_size_enum fse = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int found;
 
        fmtinfo = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
@@ -209,7 +212,6 @@ static int cal_legacy_try_fmt_vid_cap(struct file *file, void *priv,
        found = false;
        fse.pad = 0;
        fse.code = fmtinfo->code;
-       fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        for (fse.index = 0; ; fse.index++) {
                int ret;
 
@@ -302,7 +304,11 @@ static int cal_legacy_enum_framesizes(struct file *file, void *fh,
 {
        struct cal_ctx *ctx = video_drvdata(file);
        const struct cal_format_info *fmtinfo;
-       struct v4l2_subdev_frame_size_enum fse;
+       struct v4l2_subdev_frame_size_enum fse = {
+               .index = fsize->index,
+               .pad = 0,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
        /* check for valid format */
@@ -313,10 +319,7 @@ static int cal_legacy_enum_framesizes(struct file *file, void *fh,
                return -EINVAL;
        }
 
-       fse.index = fsize->index;
-       fse.pad = 0;
        fse.code = fmtinfo->code;
-       fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 
        ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size, NULL,
                               &fse);
@@ -811,7 +814,6 @@ static const struct v4l2_file_operations cal_fops = {
 
 static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 {
-       struct v4l2_subdev_mbus_code_enum mbus_code;
        struct v4l2_mbus_framefmt mbus_fmt;
        const struct cal_format_info *fmtinfo;
        unsigned int i, j, k;
@@ -826,10 +828,11 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
        ctx->num_active_fmt = 0;
 
        for (j = 0, i = 0; ; ++j) {
+               struct v4l2_subdev_mbus_code_enum mbus_code = {
+                       .index = j,
+                       .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               };
 
-               memset(&mbus_code, 0, sizeof(mbus_code));
-               mbus_code.index = j;
-               mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                ret = v4l2_subdev_call(ctx->phy->source, pad, enum_mbus_code,
                                       NULL, &mbus_code);
                if (ret == -EINVAL)
index 1236215ec70ebc9d04e35734d5e84ef6cbe2bed1..9c5105223d6bff7ae0f69216f16e648a6453c991 100644 (file)
@@ -1293,7 +1293,7 @@ error_pm_runtime:
        return ret;
 }
 
-static int cal_remove(struct platform_device *pdev)
+static void cal_remove(struct platform_device *pdev)
 {
        struct cal_dev *cal = platform_get_drvdata(pdev);
        unsigned int i;
@@ -1319,8 +1319,6 @@ static int cal_remove(struct platform_device *pdev)
        if (ret >= 0)
                pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
-
-       return 0;
 }
 
 static int cal_runtime_resume(struct device *dev)
@@ -1364,7 +1362,7 @@ static const struct dev_pm_ops cal_pm_ops = {
 
 static struct platform_driver cal_pdrv = {
        .probe          = cal_probe,
-       .remove         = cal_remove,
+       .remove_new     = cal_remove,
        .driver         = {
                .name   = CAL_MODULE_NAME,
                .pm     = &cal_pm_ops,
index 832489822706ad508c1d6e3e80171c7c17b2199a..63cdfed37bc9bcbff5492aa4f0b5a631c451759b 100644 (file)
@@ -538,7 +538,7 @@ err_put_rpm:
        return ret;
 }
 
-static int vpif_remove(struct platform_device *pdev)
+static void vpif_remove(struct platform_device *pdev)
 {
        struct vpif_data *data = platform_get_drvdata(pdev);
 
@@ -551,8 +551,6 @@ static int vpif_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
 
        kfree(data);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -592,7 +590,7 @@ static struct platform_driver vpif_driver = {
                .name   = VPIF_DRIVER_NAME,
                .pm     = vpif_pm_ops,
        },
-       .remove = vpif_remove,
+       .remove_new = vpif_remove,
        .probe = vpif_probe,
 };
 
index 580723333fccb5516e7e78093cc9190df7b7ad34..44d269d6038c5fc82f1484a690d504b9aaca4a1b 100644 (file)
@@ -1714,7 +1714,7 @@ cleanup:
  *
  * The vidoe device is unregistered
  */
-static int vpif_remove(struct platform_device *device)
+static void vpif_remove(struct platform_device *device)
 {
        struct channel_obj *ch;
        int i;
@@ -1732,7 +1732,6 @@ static int vpif_remove(struct platform_device *device)
                video_unregister_device(&ch->video_dev);
                kfree(vpif_obj.dev[i]);
        }
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1815,7 +1814,7 @@ static __refdata struct platform_driver vpif_driver = {
                .pm     = &vpif_pm_ops,
        },
        .probe = vpif_probe,
-       .remove = vpif_remove,
+       .remove_new = vpif_remove,
 };
 
 module_platform_driver(vpif_driver);
index b2df81603f623210b5cc7db403e169973ee47a1c..f8ec2991c667488b4c264e10376b6714a77167d3 100644 (file)
@@ -1305,7 +1305,7 @@ vpif_free:
 /*
  * vpif_remove: It un-register channels from V4L2 driver
  */
-static int vpif_remove(struct platform_device *device)
+static void vpif_remove(struct platform_device *device)
 {
        struct channel_obj *ch;
        int i;
@@ -1321,8 +1321,6 @@ static int vpif_remove(struct platform_device *device)
                video_unregister_device(&ch->video_dev);
        }
        free_vpif_objs();
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1399,7 +1397,7 @@ static __refdata struct platform_driver vpif_driver = {
                        .pm     = &vpif_pm_ops,
        },
        .probe  = vpif_probe,
-       .remove = vpif_remove,
+       .remove_new = vpif_remove,
 };
 
 module_platform_driver(vpif_driver);
index 3e0d9af7ffec9fc077f9067895c3b0ead73e76b1..4143274089c34dd6810ad9c77ed1a0aed08cfad2 100644 (file)
@@ -1569,7 +1569,7 @@ static void omap_vout_cleanup_device(struct omap_vout_device *vout)
        kfree(vout);
 }
 
-static int omap_vout_remove(struct platform_device *pdev)
+static void omap_vout_remove(struct platform_device *pdev)
 {
        int k;
        struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
@@ -1587,7 +1587,6 @@ static int omap_vout_remove(struct platform_device *pdev)
                omap_dss_put_device(vid_dev->displays[k]);
        }
        kfree(vid_dev);
-       return 0;
 }
 
 static int __init omap_vout_probe(struct platform_device *pdev)
@@ -1721,7 +1720,7 @@ static struct platform_driver omap_vout_driver = {
        .driver = {
                .name = VOUT_NAME,
        },
-       .remove = omap_vout_remove,
+       .remove_new = omap_vout_remove,
 };
 
 static int __init omap_vout_init(void)
index e7327e38482de89ce2423a984b957ade3304499b..f3aaa9e76492e840be0beed609298bf3d26fe182 100644 (file)
@@ -1997,7 +1997,7 @@ error:
  *
  * Always returns 0.
  */
-static int isp_remove(struct platform_device *pdev)
+static void isp_remove(struct platform_device *pdev)
 {
        struct isp_device *isp = platform_get_drvdata(pdev);
 
@@ -2014,8 +2014,6 @@ static int isp_remove(struct platform_device *pdev)
        v4l2_async_nf_cleanup(&isp->notifier);
 
        kfree(isp);
-
-       return 0;
 }
 
 enum isp_of_phy {
@@ -2476,7 +2474,7 @@ MODULE_DEVICE_TABLE(of, omap3isp_of_table);
 
 static struct platform_driver omap3isp_driver = {
        .probe = isp_probe,
-       .remove = isp_remove,
+       .remove_new = isp_remove,
        .id_table = omap3isp_id_table,
        .driver = {
                .name = "omap3isp",
index 11afb8aec29214d7fac2a9a26105acb9b2ce4ae2..fdcdffe5fecb5bb8f9541c9fd2ec71610527648a 100644 (file)
@@ -1118,7 +1118,9 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
        struct v4l2_mbus_framefmt *format;
        const struct v4l2_rect *crop;
        const struct isp_format_info *fmt_info;
-       struct v4l2_subdev_format fmt_src;
+       struct v4l2_subdev_format fmt_src = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        unsigned int depth_out;
        unsigned int depth_in = 0;
        struct media_pad *pad;
@@ -1150,7 +1152,6 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
         * input format is a non-BT.656 YUV variant.
         */
        fmt_src.pad = pad->index;
-       fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
                fmt_info = omap3isp_video_format_info(fmt_src.format.code);
                depth_in = fmt_info->width;
index ddc7d08d4f96b7b278a23b64d37aee1dec9cbb29..daca689dc08254d6e7185d7f34307146d3f87f64 100644 (file)
@@ -268,7 +268,9 @@ static int isp_video_get_graph_data(struct isp_video *video,
 static int
 __isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
 {
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        u32 pad;
        int ret;
@@ -278,7 +280,6 @@ __isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
                return -EINVAL;
 
        fmt.pad = pad;
-       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 
        mutex_lock(&video->mutex);
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
@@ -731,7 +732,9 @@ static int
 isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
 {
        struct isp_video *video = video_drvdata(file);
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        u32 pad;
        int ret;
@@ -746,7 +749,6 @@ isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
        isp_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
 
        fmt.pad = pad;
-       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        if (ret)
                return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
@@ -759,7 +761,9 @@ static int
 isp_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel)
 {
        struct isp_video *video = video_drvdata(file);
-       struct v4l2_subdev_format format;
+       struct v4l2_subdev_format format = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        struct v4l2_subdev_selection sdsel = {
                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -799,7 +803,6 @@ isp_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel)
                return ret;
 
        format.pad = pad;
-       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
        if (ret < 0)
                return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
@@ -957,7 +960,9 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
        struct media_pad *source_pad;
        struct media_entity *source = NULL;
        struct media_entity *sink;
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_ext_controls ctrls;
        struct v4l2_ext_control ctrl;
        unsigned int i;
@@ -993,7 +998,6 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
        pipe->external = media_entity_to_v4l2_subdev(source);
 
        fmt.pad = source_pad->index;
-       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(sink),
                               pad, get_fmt, NULL, &fmt);
        if (unlikely(ret < 0)) {
index 5b1c5d96a4079907a1cb526c80a65f3596bc5ab5..6848cbc82f5288a4ded6e4596b91c07b988e2781 100644 (file)
@@ -2622,7 +2622,7 @@ v4l2_dev_unreg:
        return ret;
 }
 
-static int vpe_remove(struct platform_device *pdev)
+static void vpe_remove(struct platform_device *pdev)
 {
        struct vpe_dev *dev = platform_get_drvdata(pdev);
 
@@ -2635,8 +2635,6 @@ static int vpe_remove(struct platform_device *pdev)
        vpe_set_clock_enable(dev, 0);
        vpe_runtime_put(pdev);
        pm_runtime_disable(&pdev->dev);
-
-       return 0;
 }
 
 #if defined(CONFIG_OF)
@@ -2651,7 +2649,7 @@ MODULE_DEVICE_TABLE(of, vpe_of_match);
 
 static struct platform_driver vpe_pdrv = {
        .probe          = vpe_probe,
-       .remove         = vpe_remove,
+       .remove_new     = vpe_remove,
        .driver         = {
                .name   = VPE_MODULE_NAME,
                .of_match_table = of_match_ptr(vpe_of_match),
index b0aeedae7b65bca938bf20d0ac1f95d32996ebdc..09c74a573ddb50e72e826b982eb167fd1b963fc6 100644 (file)
@@ -251,11 +251,6 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
 
 static int hantro_try_ctrl(struct v4l2_ctrl *ctrl)
 {
-       struct hantro_ctx *ctx;
-
-       ctx = container_of(ctrl->handler,
-                          struct hantro_ctx, ctrl_handler);
-
        if (ctrl->id == V4L2_CID_STATELESS_H264_SPS) {
                const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
 
@@ -274,8 +269,6 @@ static int hantro_try_ctrl(struct v4l2_ctrl *ctrl)
                if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2)
                        /* Only 8-bit and 10-bit are supported */
                        return -EINVAL;
-
-               ctx->bit_depth = sps->bit_depth_luma_minus8 + 8;
        } else if (ctrl->id == V4L2_CID_STATELESS_VP9_FRAME) {
                const struct v4l2_ctrl_vp9_frame *dec_params = ctrl->p_new.p_vp9_frame;
 
@@ -314,9 +307,38 @@ static int hantro_vp9_s_ctrl(struct v4l2_ctrl *ctrl)
                           struct hantro_ctx, ctrl_handler);
 
        switch (ctrl->id) {
-       case V4L2_CID_STATELESS_VP9_FRAME:
-               ctx->bit_depth = ctrl->p_new.p_vp9_frame->bit_depth;
-               break;
+       case V4L2_CID_STATELESS_VP9_FRAME: {
+               int bit_depth = ctrl->p_new.p_vp9_frame->bit_depth;
+
+               if (ctx->bit_depth == bit_depth)
+                       return 0;
+
+               return hantro_reset_raw_fmt(ctx, bit_depth);
+       }
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int hantro_hevc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct hantro_ctx *ctx;
+
+       ctx = container_of(ctrl->handler,
+                          struct hantro_ctx, ctrl_handler);
+
+       switch (ctrl->id) {
+       case V4L2_CID_STATELESS_HEVC_SPS: {
+               const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps;
+               int bit_depth = sps->bit_depth_luma_minus8 + 8;
+
+               if (ctx->bit_depth == bit_depth)
+                       return 0;
+
+               return hantro_reset_raw_fmt(ctx, bit_depth);
+       }
        default:
                return -EINVAL;
        }
@@ -336,6 +358,11 @@ static const struct v4l2_ctrl_ops hantro_vp9_ctrl_ops = {
        .s_ctrl = hantro_vp9_s_ctrl,
 };
 
+static const struct v4l2_ctrl_ops hantro_hevc_ctrl_ops = {
+       .try_ctrl = hantro_try_ctrl,
+       .s_ctrl = hantro_hevc_s_ctrl,
+};
+
 #define HANTRO_JPEG_ACTIVE_MARKERS     (V4L2_JPEG_ACTIVE_MARKER_APP0 | \
                                         V4L2_JPEG_ACTIVE_MARKER_COM | \
                                         V4L2_JPEG_ACTIVE_MARKER_DQT | \
@@ -470,7 +497,7 @@ static const struct hantro_ctrl controls[] = {
                .codec = HANTRO_HEVC_DECODER,
                .cfg = {
                        .id = V4L2_CID_STATELESS_HEVC_SPS,
-                       .ops = &hantro_ctrl_ops,
+                       .ops = &hantro_hevc_ctrl_ops,
                },
        }, {
                .codec = HANTRO_HEVC_DECODER,
@@ -945,7 +972,7 @@ static int hantro_probe(struct platform_device *pdev)
                        return PTR_ERR(vpu->clocks[0].clk);
        }
 
-       vpu->resets = devm_reset_control_array_get(&pdev->dev, false, true);
+       vpu->resets = devm_reset_control_array_get_optional_exclusive(&pdev->dev);
        if (IS_ERR(vpu->resets))
                return PTR_ERR(vpu->resets);
 
@@ -1093,7 +1120,7 @@ err_pm_disable:
        return ret;
 }
 
-static int hantro_remove(struct platform_device *pdev)
+static void hantro_remove(struct platform_device *pdev)
 {
        struct hantro_dev *vpu = platform_get_drvdata(pdev);
 
@@ -1109,7 +1136,6 @@ static int hantro_remove(struct platform_device *pdev)
        reset_control_assert(vpu->resets);
        pm_runtime_dont_use_autosuspend(vpu->dev);
        pm_runtime_disable(vpu->dev);
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1132,7 +1158,7 @@ static const struct dev_pm_ops hantro_pm_ops = {
 
 static struct platform_driver hantro_driver = {
        .probe = hantro_probe,
-       .remove = hantro_remove,
+       .remove_new = hantro_remove,
        .driver = {
                   .name = DRIVER_NAME,
                   .of_match_table = of_match_ptr(of_hantro_match),
index 09d8cf9426895419a726a7b5896e66cd63bb99f8..6437423ccf3a9e973d0adf51729351e72029bd4c 100644 (file)
@@ -197,7 +197,7 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx)
        unsigned int i, buf_size;
 
        /* this should always pick native format */
-       fmt = hantro_get_default_fmt(ctx, false);
+       fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth);
        if (!fmt)
                return -EINVAL;
        v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width,
index c0d427956210c6d7071784037302facdbb946c12..835518534e3b94dc6f352cf3a8fe0330db4d79c5 100644 (file)
@@ -28,6 +28,8 @@
 #include "hantro_hw.h"
 #include "hantro_v4l2.h"
 
+#define  HANTRO_DEFAULT_BIT_DEPTH 8
+
 static int hantro_set_fmt_out(struct hantro_ctx *ctx,
                              struct v4l2_pix_format_mplane *pix_mp);
 static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
@@ -76,18 +78,13 @@ int hantro_get_format_depth(u32 fourcc)
 }
 
 static bool
-hantro_check_depth_match(const struct hantro_ctx *ctx,
-                        const struct hantro_fmt *fmt)
+hantro_check_depth_match(const struct hantro_fmt *fmt, int bit_depth)
 {
-       int fmt_depth, ctx_depth = 8;
+       int fmt_depth;
 
        if (!fmt->match_depth && !fmt->postprocessed)
                return true;
 
-       /* 0 means default depth, which is 8 */
-       if (ctx->bit_depth)
-               ctx_depth = ctx->bit_depth;
-
        fmt_depth = hantro_get_format_depth(fmt->fourcc);
 
        /*
@@ -95,9 +92,9 @@ hantro_check_depth_match(const struct hantro_ctx *ctx,
         * It may be possible to relax that on some HW.
         */
        if (!fmt->match_depth)
-               return fmt_depth <= ctx_depth;
+               return fmt_depth <= bit_depth;
 
-       return fmt_depth == ctx_depth;
+       return fmt_depth == bit_depth;
 }
 
 static const struct hantro_fmt *
@@ -119,7 +116,7 @@ hantro_find_format(const struct hantro_ctx *ctx, u32 fourcc)
 }
 
 const struct hantro_fmt *
-hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream)
+hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, int bit_depth)
 {
        const struct hantro_fmt *formats;
        unsigned int i, num_fmts;
@@ -128,7 +125,7 @@ hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream)
        for (i = 0; i < num_fmts; i++) {
                if (bitstream == (formats[i].codec_mode !=
                                  HANTRO_MODE_NONE) &&
-                   hantro_check_depth_match(ctx, &formats[i]))
+                   hantro_check_depth_match(&formats[i], bit_depth))
                        return &formats[i];
        }
        return NULL;
@@ -204,7 +201,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv,
 
                if (skip_mode_none == mode_none)
                        continue;
-               if (!hantro_check_depth_match(ctx, fmt))
+               if (!hantro_check_depth_match(fmt, ctx->bit_depth))
                        continue;
                if (j == f->index) {
                        f->pixelformat = fmt->fourcc;
@@ -224,7 +221,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv,
        for (i = 0; i < num_fmts; i++) {
                fmt = &formats[i];
 
-               if (!hantro_check_depth_match(ctx, fmt))
+               if (!hantro_check_depth_match(fmt, ctx->bit_depth))
                        continue;
                if (j == f->index) {
                        f->pixelformat = fmt->fourcc;
@@ -278,7 +275,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx,
                          struct v4l2_pix_format_mplane *pix_mp,
                          enum v4l2_buf_type type)
 {
-       const struct hantro_fmt *fmt, *vpu_fmt;
+       const struct hantro_fmt *fmt;
        bool capture = V4L2_TYPE_IS_CAPTURE(type);
        bool coded;
 
@@ -292,17 +289,13 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx,
 
        fmt = hantro_find_format(ctx, pix_mp->pixelformat);
        if (!fmt) {
-               fmt = hantro_get_default_fmt(ctx, coded);
+               fmt = hantro_get_default_fmt(ctx, coded, HANTRO_DEFAULT_BIT_DEPTH);
                pix_mp->pixelformat = fmt->fourcc;
        }
 
        if (coded) {
                pix_mp->num_planes = 1;
-               vpu_fmt = fmt;
-       } else if (ctx->is_encoder) {
-               vpu_fmt = ctx->vpu_dst_fmt;
-       } else {
-               vpu_fmt = fmt;
+       } else if (!ctx->is_encoder) {
                /*
                 * Width/height on the CAPTURE end of a decoder are ignored and
                 * replaced by the OUTPUT ones.
@@ -314,7 +307,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx,
        pix_mp->field = V4L2_FIELD_NONE;
 
        v4l2_apply_frmsize_constraints(&pix_mp->width, &pix_mp->height,
-                                      &vpu_fmt->frmsize);
+                                      &fmt->frmsize);
 
        if (!coded) {
                /* Fill remaining fields */
@@ -378,58 +371,55 @@ static void
 hantro_reset_encoded_fmt(struct hantro_ctx *ctx)
 {
        const struct hantro_fmt *vpu_fmt;
-       struct v4l2_pix_format_mplane *fmt;
-
-       vpu_fmt = hantro_get_default_fmt(ctx, true);
+       struct v4l2_pix_format_mplane fmt;
 
-       if (ctx->is_encoder) {
-               ctx->vpu_dst_fmt = vpu_fmt;
-               fmt = &ctx->dst_fmt;
-       } else {
-               ctx->vpu_src_fmt = vpu_fmt;
-               fmt = &ctx->src_fmt;
-       }
+       vpu_fmt = hantro_get_default_fmt(ctx, true, HANTRO_DEFAULT_BIT_DEPTH);
+       if (!vpu_fmt)
+               return;
 
-       hantro_reset_fmt(fmt, vpu_fmt);
-       fmt->width = vpu_fmt->frmsize.min_width;
-       fmt->height = vpu_fmt->frmsize.min_height;
+       hantro_reset_fmt(&fmt, vpu_fmt);
+       fmt.width = vpu_fmt->frmsize.min_width;
+       fmt.height = vpu_fmt->frmsize.min_height;
        if (ctx->is_encoder)
-               hantro_set_fmt_cap(ctx, fmt);
+               hantro_set_fmt_cap(ctx, &fmt);
        else
-               hantro_set_fmt_out(ctx, fmt);
+               hantro_set_fmt_out(ctx, &fmt);
 }
 
-static void
-hantro_reset_raw_fmt(struct hantro_ctx *ctx)
+int
+hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth)
 {
        const struct hantro_fmt *raw_vpu_fmt;
-       struct v4l2_pix_format_mplane *raw_fmt, *encoded_fmt;
+       struct v4l2_pix_format_mplane raw_fmt, *encoded_fmt;
+       int ret;
 
-       raw_vpu_fmt = hantro_get_default_fmt(ctx, false);
+       raw_vpu_fmt = hantro_get_default_fmt(ctx, false, bit_depth);
+       if (!raw_vpu_fmt)
+               return -EINVAL;
 
-       if (ctx->is_encoder) {
-               ctx->vpu_src_fmt = raw_vpu_fmt;
-               raw_fmt = &ctx->src_fmt;
+       if (ctx->is_encoder)
                encoded_fmt = &ctx->dst_fmt;
-       } else {
-               ctx->vpu_dst_fmt = raw_vpu_fmt;
-               raw_fmt = &ctx->dst_fmt;
+       else
                encoded_fmt = &ctx->src_fmt;
-       }
 
-       hantro_reset_fmt(raw_fmt, raw_vpu_fmt);
-       raw_fmt->width = encoded_fmt->width;
-       raw_fmt->height = encoded_fmt->height;
+       hantro_reset_fmt(&raw_fmt, raw_vpu_fmt);
+       raw_fmt.width = encoded_fmt->width;
+       raw_fmt.height = encoded_fmt->height;
        if (ctx->is_encoder)
-               hantro_set_fmt_out(ctx, raw_fmt);
+               ret = hantro_set_fmt_out(ctx, &raw_fmt);
        else
-               hantro_set_fmt_cap(ctx, raw_fmt);
+               ret = hantro_set_fmt_cap(ctx, &raw_fmt);
+
+       if (!ret)
+               ctx->bit_depth = bit_depth;
+
+       return ret;
 }
 
 void hantro_reset_fmts(struct hantro_ctx *ctx)
 {
        hantro_reset_encoded_fmt(ctx);
-       hantro_reset_raw_fmt(ctx);
+       hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH);
 }
 
 static void
@@ -529,7 +519,7 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx,
         * changes to the raw format.
         */
        if (!ctx->is_encoder)
-               hantro_reset_raw_fmt(ctx);
+               hantro_reset_raw_fmt(ctx, hantro_get_format_depth(pix_mp->pixelformat));
 
        /* Colorimetry information are always propagated. */
        ctx->dst_fmt.colorspace = pix_mp->colorspace;
@@ -592,7 +582,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx,
         * changes to the raw format.
         */
        if (ctx->is_encoder)
-               hantro_reset_raw_fmt(ctx);
+               hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH);
 
        /* Colorimetry information are always propagated. */
        ctx->src_fmt.colorspace = pix_mp->colorspace;
index 64f6f57e9d7a0397707e5bfcabca310e93f2e203..9ea2fef57dcd99ede930428339bd373d1aa27062 100644 (file)
 extern const struct v4l2_ioctl_ops hantro_ioctl_ops;
 extern const struct vb2_ops hantro_queue_ops;
 
+int hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth);
 void hantro_reset_fmts(struct hantro_ctx *ctx);
 int hantro_get_format_depth(u32 fourcc);
 const struct hantro_fmt *
-hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream);
+hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, int bit_depth);
 
 #endif /* HANTRO_V4L2_H_ */
index b390228fd3b4afb0666798c3cbf705897c74e122..f850d8bddef6bc5426e96aa49803f7de37f83908 100644 (file)
@@ -152,6 +152,7 @@ static const struct hantro_fmt imx8m_vpu_g2_postproc_fmts[] = {
        {
                .fourcc = V4L2_PIX_FMT_NV12,
                .codec_mode = HANTRO_MODE_NONE,
+               .match_depth = true,
                .postprocessed = true,
                .frmsize = {
                        .min_width = FMT_MIN_WIDTH,
@@ -165,6 +166,7 @@ static const struct hantro_fmt imx8m_vpu_g2_postproc_fmts[] = {
        {
                .fourcc = V4L2_PIX_FMT_P010,
                .codec_mode = HANTRO_MODE_NONE,
+               .match_depth = true,
                .postprocessed = true,
                .frmsize = {
                        .min_width = FMT_MIN_WIDTH,
index 95483c84c3f252c316e138f9d83163d78adcfb68..450254403fa8914a80c244b897fdd1ab7ca22ed5 100644 (file)
@@ -845,8 +845,8 @@ static int viacam_do_try_fmt(struct via_camera *cam,
        int ret;
        struct v4l2_subdev_pad_config pad_cfg;
        struct v4l2_subdev_state pad_state = {
-               .pads = &pad_cfg
-               };
+               .pads = &pad_cfg,
+       };
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
@@ -1208,7 +1208,9 @@ static int viacam_probe(struct platform_device *pdev)
         * Convince the system that we can do DMA.
         */
        pdev->dev.dma_mask = &viadev->pdev->dma_mask;
-       dma_set_mask(&pdev->dev, 0xffffffff);
+       ret = dma_set_mask(&pdev->dev, 0xffffffff);
+       if (ret)
+               goto out_ctrl_hdl_free;
        /*
         * Fire up the capture port.  The write to 0x78 looks purely
         * OLPCish; any system will need to tweak 0x1e.
@@ -1294,7 +1296,7 @@ out_free:
        return ret;
 }
 
-static int viacam_remove(struct platform_device *pdev)
+static void viacam_remove(struct platform_device *pdev)
 {
        struct via_camera *cam = via_cam_info;
        struct viafb_dev *viadev = pdev->dev.platform_data;
@@ -1309,7 +1311,6 @@ static int viacam_remove(struct platform_device *pdev)
        v4l2_ctrl_handler_free(&cam->ctrl_handler);
        kfree(cam);
        via_cam_info = NULL;
-       return 0;
 }
 
 static struct platform_driver viacam_driver = {
@@ -1317,7 +1318,7 @@ static struct platform_driver viacam_driver = {
                .name = "viafb-camera",
        },
        .probe = viacam_probe,
-       .remove = viacam_remove,
+       .remove_new = viacam_remove,
 };
 
 module_platform_driver(viacam_driver);
index 71d97042a470ba0b93c3df4740aebc3257152a57..1d9f32e5a91716a10bbbd470e9d49e0608f89c18 100644 (file)
@@ -481,7 +481,7 @@ static int video_mux_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int video_mux_remove(struct platform_device *pdev)
+static void video_mux_remove(struct platform_device *pdev)
 {
        struct video_mux *vmux = platform_get_drvdata(pdev);
        struct v4l2_subdev *sd = &vmux->subdev;
@@ -490,8 +490,6 @@ static int video_mux_remove(struct platform_device *pdev)
        v4l2_async_nf_cleanup(&vmux->notifier);
        v4l2_async_unregister_subdev(sd);
        media_entity_cleanup(&sd->entity);
-
-       return 0;
 }
 
 static const struct of_device_id video_mux_dt_ids[] = {
@@ -502,7 +500,7 @@ MODULE_DEVICE_TABLE(of, video_mux_dt_ids);
 
 static struct platform_driver video_mux_driver = {
        .probe          = video_mux_probe,
-       .remove         = video_mux_remove,
+       .remove_new     = video_mux_remove,
        .driver         = {
                .of_match_table = video_mux_dt_ids,
                .name = "video-mux",
index d8a23f18cfbce56b2cec0efe8a324fbc66598e18..5b53745fe44eb87d035707d4febcf8a16bde063b 100644 (file)
@@ -1059,7 +1059,7 @@ err_clk_put:
        return ret;
 }
 
-static int xcsi2rxss_remove(struct platform_device *pdev)
+static void xcsi2rxss_remove(struct platform_device *pdev)
 {
        struct xcsi2rxss_state *xcsi2rxss = platform_get_drvdata(pdev);
        struct v4l2_subdev *subdev = &xcsi2rxss->subdev;
@@ -1070,8 +1070,6 @@ static int xcsi2rxss_remove(struct platform_device *pdev)
        mutex_destroy(&xcsi2rxss->lock);
        clk_bulk_disable_unprepare(num_clks, xcsi2rxss->clks);
        clk_bulk_put(num_clks, xcsi2rxss->clks);
-
-       return 0;
 }
 
 static const struct of_device_id xcsi2rxss_of_id_table[] = {
@@ -1086,7 +1084,7 @@ static struct platform_driver xcsi2rxss_driver = {
                .of_match_table = xcsi2rxss_of_id_table,
        },
        .probe                  = xcsi2rxss_probe,
-       .remove                 = xcsi2rxss_remove,
+       .remove_new             = xcsi2rxss_remove,
 };
 
 module_platform_driver(xcsi2rxss_driver);
index fee02c8c85fd477ad3fc168f96e771af44226737..80d6f5b072ea648e029b2fad447664a067159622 100644 (file)
@@ -56,7 +56,9 @@ xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
 
 static int xvip_dma_verify_format(struct xvip_dma *dma)
 {
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        int ret;
 
@@ -64,7 +66,6 @@ static int xvip_dma_verify_format(struct xvip_dma *dma)
        if (subdev == NULL)
                return -EPIPE;
 
-       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        if (ret < 0)
                return ret == -ENOIOCTLCMD ? -EINVAL : ret;
index 0f2d5a0edf0c3486a4bb652207b817e850785c4d..80353ca44402a524cbbd92c2593563c42681dafd 100644 (file)
@@ -894,7 +894,7 @@ error_resource:
        return ret;
 }
 
-static int xtpg_remove(struct platform_device *pdev)
+static void xtpg_remove(struct platform_device *pdev)
 {
        struct xtpg_device *xtpg = platform_get_drvdata(pdev);
        struct v4l2_subdev *subdev = &xtpg->xvip.subdev;
@@ -904,8 +904,6 @@ static int xtpg_remove(struct platform_device *pdev)
        media_entity_cleanup(&subdev->entity);
 
        xvip_cleanup_resources(&xtpg->xvip);
-
-       return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(xtpg_pm_ops, xtpg_pm_suspend, xtpg_pm_resume);
@@ -923,7 +921,7 @@ static struct platform_driver xtpg_driver = {
                .of_match_table = xtpg_of_id_table,
        },
        .probe                  = xtpg_probe,
-       .remove                 = xtpg_remove,
+       .remove_new             = xtpg_remove,
 };
 
 module_platform_driver(xtpg_driver);
index 0a16c218a50a7cba9477bdcbbdb395fec1152b93..3123216b3f70e1290a1fbbb49eb3e79744d9368f 100644 (file)
@@ -617,14 +617,12 @@ error:
        return ret;
 }
 
-static int xvip_composite_remove(struct platform_device *pdev)
+static void xvip_composite_remove(struct platform_device *pdev)
 {
        struct xvip_composite_device *xdev = platform_get_drvdata(pdev);
 
        xvip_graph_cleanup(xdev);
        xvip_composite_v4l2_cleanup(xdev);
-
-       return 0;
 }
 
 static const struct of_device_id xvip_composite_of_id_table[] = {
@@ -639,7 +637,7 @@ static struct platform_driver xvip_composite_driver = {
                .of_match_table = xvip_composite_of_id_table,
        },
        .probe = xvip_composite_probe,
-       .remove = xvip_composite_remove,
+       .remove_new = xvip_composite_remove,
 };
 
 module_platform_driver(xvip_composite_driver);
index 0ae0208d75296b5d58614a606fc82b0a73f892a1..dda70719f0045a9b84f48475066d0c6b343bac1e 100644 (file)
@@ -254,7 +254,7 @@ struct xvtc_device *xvtc_of_get(struct device_node *np)
        struct xvtc_device *found = NULL;
        struct xvtc_device *xvtc;
 
-       if (!of_find_property(np, "xlnx,vtc", NULL))
+       if (!of_property_present(np, "xlnx,vtc"))
                return NULL;
 
        xvtc_node = of_parse_phandle(np, "xlnx,vtc", 0);
@@ -344,15 +344,13 @@ static int xvtc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int xvtc_remove(struct platform_device *pdev)
+static void xvtc_remove(struct platform_device *pdev)
 {
        struct xvtc_device *xvtc = platform_get_drvdata(pdev);
 
        xvtc_unregister_device(xvtc);
 
        xvip_cleanup_resources(&xvtc->xvip);
-
-       return 0;
 }
 
 static const struct of_device_id xvtc_of_id_table[] = {
@@ -367,7 +365,7 @@ static struct platform_driver xvtc_driver = {
                .of_match_table = xvtc_of_id_table,
        },
        .probe = xvtc_probe,
-       .remove = xvtc_remove,
+       .remove_new = xvtc_remove,
 };
 
 module_platform_driver(xvtc_driver);
index 171f9cc9ee5ea43f992a1d3f32053dbaa6bdf10d..6061506159f1b4f30e3f61dd37f26364d2dc93eb 100644 (file)
@@ -1498,7 +1498,7 @@ exit:
        return rval;
 }
 
-static int si476x_radio_remove(struct platform_device *pdev)
+static void si476x_radio_remove(struct platform_device *pdev)
 {
        struct si476x_radio *radio = platform_get_drvdata(pdev);
 
@@ -1506,8 +1506,6 @@ static int si476x_radio_remove(struct platform_device *pdev)
        video_unregister_device(&radio->videodev);
        v4l2_device_unregister(&radio->v4l2dev);
        debugfs_remove_recursive(radio->debugfs);
-
-       return 0;
 }
 
 MODULE_ALIAS("platform:si476x-radio");
@@ -1517,7 +1515,7 @@ static struct platform_driver si476x_radio_driver = {
                .name   = DRIVER_NAME,
        },
        .probe          = si476x_radio_probe,
-       .remove         = si476x_radio_remove,
+       .remove_new     = si476x_radio_remove,
 };
 module_platform_driver(si476x_radio_driver);
 
index 948ee3eec9144070689b262a42e443bf94b94b24..04daa9c358c27f8bc482a40c2928858cbc456e24 100644 (file)
@@ -151,13 +151,12 @@ err:
        return err;
 }
 
-static int timbradio_remove(struct platform_device *pdev)
+static void timbradio_remove(struct platform_device *pdev)
 {
        struct timbradio *tr = platform_get_drvdata(pdev);
 
        video_unregister_device(&tr->video_dev);
        v4l2_device_unregister(&tr->v4l2_dev);
-       return 0;
 }
 
 static struct platform_driver timbradio_platform_driver = {
@@ -165,7 +164,7 @@ static struct platform_driver timbradio_platform_driver = {
                .name   = DRIVER_NAME,
        },
        .probe          = timbradio_probe,
-       .remove         = timbradio_remove,
+       .remove_new     = timbradio_remove,
 };
 
 module_platform_driver(timbradio_platform_driver);
index 484046471c03f8c1b1defe24006793e538221e4d..e8166eac9efe8da2208e47875e1d89d0543d2040 100644 (file)
@@ -1977,7 +1977,7 @@ static const struct video_device wl1273_viddev_template = {
                                  V4L2_CAP_RDS_OUTPUT,
 };
 
-static int wl1273_fm_radio_remove(struct platform_device *pdev)
+static void wl1273_fm_radio_remove(struct platform_device *pdev)
 {
        struct wl1273_device *radio = platform_get_drvdata(pdev);
        struct wl1273_core *core = radio->core;
@@ -1990,8 +1990,6 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev)
        v4l2_ctrl_handler_free(&radio->ctrl_handler);
        video_unregister_device(&radio->videodev);
        v4l2_device_unregister(&radio->v4l2dev);
-
-       return 0;
 }
 
 static int wl1273_fm_radio_probe(struct platform_device *pdev)
@@ -2147,7 +2145,7 @@ pdata_err:
 
 static struct platform_driver wl1273_fm_radio_driver = {
        .probe          = wl1273_fm_radio_probe,
-       .remove         = wl1273_fm_radio_remove,
+       .remove_new     = wl1273_fm_radio_remove,
        .driver         = {
                .name   = "wl1273_fm_radio",
        },
index 433f9642786dd97a3d084a954b7ff426533b6506..9fdaed68a962ef0bff1e55f5d99ede2024126248 100644 (file)
@@ -190,7 +190,7 @@ exit:
 }
 
 /* radio_si4713_pdriver_remove - remove the device */
-static int radio_si4713_pdriver_remove(struct platform_device *pdev)
+static void radio_si4713_pdriver_remove(struct platform_device *pdev)
 {
        struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
        struct radio_si4713_device *rsdev;
@@ -198,8 +198,6 @@ static int radio_si4713_pdriver_remove(struct platform_device *pdev)
        rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev);
        video_unregister_device(&rsdev->radio_dev);
        v4l2_device_unregister(&rsdev->v4l2_dev);
-
-       return 0;
 }
 
 static struct platform_driver radio_si4713_pdriver = {
@@ -207,7 +205,7 @@ static struct platform_driver radio_si4713_pdriver = {
                .name   = "radio-si4713",
        },
        .probe          = radio_si4713_pdriver_probe,
-       .remove         = radio_si4713_pdriver_remove,
+       .remove_new     = radio_si4713_pdriver_remove,
 };
 
 module_platform_driver(radio_si4713_pdriver);
index 8dbe780dae4e78f852322512bcb0b42c143a1439..27f55ea966c651fc054054758d5824916a4b73f3 100644 (file)
@@ -103,6 +103,8 @@ static int gpio_ir_recv_probe(struct platform_device *pdev)
                rcdev->map_name = RC_MAP_EMPTY;
 
        gpio_dev->rcdev = rcdev;
+       if (of_property_read_bool(np, "wakeup-source"))
+               device_init_wakeup(dev, true);
 
        rc = devm_rc_register_device(dev, rcdev);
        if (rc < 0) {
@@ -126,7 +128,7 @@ static int gpio_ir_recv_probe(struct platform_device *pdev)
                                "gpio-ir-recv-irq", gpio_dev);
 }
 
-static int gpio_ir_recv_remove(struct platform_device *pdev)
+static void gpio_ir_recv_remove(struct platform_device *pdev)
 {
        struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
        struct device *pmdev = gpio_dev->pmdev;
@@ -139,8 +141,6 @@ static int gpio_ir_recv_remove(struct platform_device *pdev)
                pm_runtime_put_noidle(pmdev);
                pm_runtime_set_suspended(pmdev);
        }
-
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -202,7 +202,7 @@ MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match);
 
 static struct platform_driver gpio_ir_recv_driver = {
        .probe  = gpio_ir_recv_probe,
-       .remove = gpio_ir_recv_remove,
+       .remove_new = gpio_ir_recv_remove,
        .driver = {
                .name   = KBUILD_MODNAME,
                .of_match_table = of_match_ptr(gpio_ir_recv_of_match),
index 6f84648720337b26b364e826badc8ae493b3d3f0..d87d8e14c5568179c6b475f76aa136eb69eecce6 100644 (file)
@@ -152,7 +152,7 @@ err_probe:
        return error;
 }
 
-static int img_ir_remove(struct platform_device *pdev)
+static void img_ir_remove(struct platform_device *pdev)
 {
        struct img_ir_priv *priv = platform_get_drvdata(pdev);
 
@@ -164,7 +164,6 @@ static int img_ir_remove(struct platform_device *pdev)
                clk_disable_unprepare(priv->clk);
        if (!IS_ERR(priv->sys_clk))
                clk_disable_unprepare(priv->sys_clk);
-       return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(img_ir_pmops, img_ir_suspend, img_ir_resume);
@@ -182,7 +181,7 @@ static struct platform_driver img_ir_driver = {
                .pm = &img_ir_pmops,
        },
        .probe = img_ir_probe,
-       .remove = img_ir_remove,
+       .remove_new = img_ir_remove,
 };
 
 module_platform_driver(img_ir_driver);
index 4ff954b11dc777ce7ebd118cc13b92372fb6fb09..0034f615b4660ea2b43abdf2b088a1e000cd2255 100644 (file)
@@ -340,13 +340,12 @@ err:
        return ret;
 }
 
-static int hix5hd2_ir_remove(struct platform_device *pdev)
+static void hix5hd2_ir_remove(struct platform_device *pdev)
 {
        struct hix5hd2_ir_priv *priv = platform_get_drvdata(pdev);
 
        clk_disable_unprepare(priv->clock);
        rc_unregister_device(priv->rdev);
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -395,7 +394,7 @@ static struct platform_driver hix5hd2_ir_driver = {
                .pm     = &hix5hd2_ir_pm_ops,
        },
        .probe = hix5hd2_ir_probe,
-       .remove = hix5hd2_ir_remove,
+       .remove_new = hix5hd2_ir_remove,
 };
 
 module_platform_driver(hix5hd2_ir_driver);
index f513ff5caf4e9f64a102f9ba48ca2c482ed58134..f19558fdab0ca9d1ccb4c7d7b0ed664535cb4fed 100644 (file)
@@ -22,6 +22,7 @@ obj-$(CONFIG_RC_MAP) += \
                        rc-avertv-303.o \
                        rc-azurewave-ad-tu700.o \
                        rc-beelink-gs1.o \
+                       rc-beelink-mxiii.o \
                        rc-behold-columbus.o \
                        rc-behold.o \
                        rc-budget-ci-old.o \
@@ -37,6 +38,7 @@ obj-$(CONFIG_RC_MAP) += \
                        rc-dm1105-nec.o \
                        rc-dntv-live-dvb-t.o \
                        rc-dntv-live-dvbt-pro.o \
+                       rc-dreambox.o \
                        rc-dtt200u.o \
                        rc-dvbsky.o \
                        rc-dvico-mce.o \
diff --git a/drivers/media/rc/keymaps/rc-beelink-mxiii.c b/drivers/media/rc/keymaps/rc-beelink-mxiii.c
new file mode 100644 (file)
index 0000000..01180cd
--- /dev/null
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Christian Hewitt <christianshewitt@gmail.com>
+ *
+ */
+
+#include <media/rc-map.h>
+#include <linux/module.h>
+
+/*
+ * Keytable for the Beelink Mini MXIII remote control
+ *
+ */
+
+static struct rc_map_table beelink_mxiii[] = {
+       { 0xb2dc, KEY_POWER },
+
+       { 0xb288, KEY_MUTE },
+       { 0xb282, KEY_HOME },
+
+       { 0xb2ca, KEY_UP },
+       { 0xb299, KEY_LEFT },
+       { 0xb2ce, KEY_OK },
+       { 0xb2c1, KEY_RIGHT },
+       { 0xb2d2, KEY_DOWN },
+
+       { 0xb2c5, KEY_MENU },
+       { 0xb29a, KEY_BACK },
+
+       { 0xb281, KEY_VOLUMEDOWN },
+       { 0xb280, KEY_VOLUMEUP },
+};
+
+static struct rc_map_list beelink_mxiii_map = {
+       .map = {
+               .scan     = beelink_mxiii,
+               .size     = ARRAY_SIZE(beelink_mxiii),
+               .rc_proto = RC_PROTO_NEC,
+               .name     = RC_MAP_BEELINK_MXIII,
+       }
+};
+
+static int __init init_rc_map_beelink_mxiii(void)
+{
+       return rc_map_register(&beelink_mxiii_map);
+}
+
+static void __exit exit_rc_map_beelink_mxiii(void)
+{
+       rc_map_unregister(&beelink_mxiii_map);
+}
+
+module_init(init_rc_map_beelink_mxiii)
+module_exit(exit_rc_map_beelink_mxiii)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hewitt <christianshewitt@gmail.com");
diff --git a/drivers/media/rc/keymaps/rc-dreambox.c b/drivers/media/rc/keymaps/rc-dreambox.c
new file mode 100644 (file)
index 0000000..dea024f
--- /dev/null
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021 Emanuel Strobel <emanuel.strobel@yahoo.com>
+ */
+
+#include <media/rc-map.h>
+#include <linux/module.h>
+
+/*
+ * Keytable for Dreambox RC10/RC0 and RC20/RC-BT remote controls
+ *
+ * Keys that are not IR addressable:
+ *
+ * // DREAM switches to STB control mode
+ * // TV switches to TV control mode
+ * // MODE toggles STB/TV/BT control modes
+ *
+ */
+
+static struct rc_map_table dreambox[] = {
+       /* Dreambox RC10/RC0/RCU-BT remote */
+       { 0x3200, KEY_POWER },
+
+       // DREAM
+       { 0x3290, KEY_HELP },
+       // TV
+
+       { 0x3201, KEY_1 },
+       { 0x3202, KEY_2 },
+       { 0x3203, KEY_3 },
+       { 0x3204, KEY_4 },
+       { 0x3205, KEY_5 },
+       { 0x3206, KEY_6 },
+       { 0x3207, KEY_7 },
+       { 0x3208, KEY_8 },
+       { 0x3209, KEY_9 },
+       { 0x320a, KEY_PREVIOUS },
+       { 0x320b, KEY_0 },
+       { 0x320c, KEY_NEXT },
+
+       { 0x321f, KEY_RED },
+       { 0x3220, KEY_GREEN },
+       { 0x3221, KEY_YELLOW },
+       { 0x3222, KEY_BLUE },
+
+       { 0x3210, KEY_INFO },
+       { 0x3212, KEY_MENU },
+       { 0x320e, KEY_AUDIO },
+       { 0x3218, KEY_PVR },
+
+       { 0x3213, KEY_LEFT },
+       { 0x3211, KEY_UP },
+       { 0x3215, KEY_RIGHT },
+       { 0x3217, KEY_DOWN },
+       { 0x3214, KEY_OK },
+
+       { 0x3219, KEY_VOLUMEUP },
+       { 0x321c, KEY_VOLUMEDOWN },
+
+       { 0x321d, KEY_ESC }, // EXIT
+       { 0x321a, KEY_MUTE },
+
+       { 0x321b, KEY_PAGEUP },
+       { 0x321e, KEY_PAGEDOWN },
+
+       { 0x3223, KEY_PREVIOUSSONG },
+       { 0x3224, KEY_PLAYPAUSE },
+       { 0x3225, KEY_STOP },
+       { 0x3226, KEY_NEXTSONG },
+
+       { 0x3227, KEY_TV },
+       { 0x3228, KEY_RADIO },
+       { 0x3229, KEY_TEXT },
+       { 0x322a, KEY_RECORD },
+
+       /* Dreambox RC20/RC-BT */
+       { 0x3407, KEY_MUTE },
+       // MODE
+       { 0x3401, KEY_POWER },
+
+       { 0x3432, KEY_PREVIOUSSONG },
+       { 0x3433, KEY_PLAYPAUSE },
+       { 0x3435, KEY_NEXTSONG },
+
+       { 0x3436, KEY_RECORD },
+       { 0x3434, KEY_STOP },
+       { 0x3425, KEY_TEXT },
+
+       { 0x341f, KEY_RED },
+       { 0x3420, KEY_GREEN },
+       { 0x3421, KEY_YELLOW },
+       { 0x3422, KEY_BLUE },
+
+       { 0x341b, KEY_INFO },
+       { 0x341c, KEY_MENU },
+       { 0x3430, KEY_AUDIO },
+       { 0x3431, KEY_PVR },
+
+       { 0x3414, KEY_LEFT },
+       { 0x3411, KEY_UP },
+       { 0x3416, KEY_RIGHT },
+       { 0x3419, KEY_DOWN },
+       { 0x3415, KEY_OK },
+
+       { 0x3413, KEY_VOLUMEUP },
+       { 0x3418, KEY_VOLUMEDOWN },
+
+       { 0x3412, KEY_ESC }, // EXIT
+       { 0x3426, KEY_HELP }, // MIC
+
+       { 0x3417, KEY_PAGEUP },
+       { 0x341a, KEY_PAGEDOWN },
+
+       { 0x3404, KEY_1 },
+       { 0x3405, KEY_2 },
+       { 0x3406, KEY_3 },
+       { 0x3408, KEY_4 },
+       { 0x3409, KEY_5 },
+       { 0x340a, KEY_6 },
+       { 0x340c, KEY_7 },
+       { 0x340d, KEY_8 },
+       { 0x340e, KEY_9 },
+       { 0x340b, KEY_PREVIOUS },
+       { 0x3410, KEY_0 },
+       { 0x340f, KEY_NEXT },
+};
+
+static struct rc_map_list dreambox_map = {
+       .map = {
+               .scan     = dreambox,
+               .size     = ARRAY_SIZE(dreambox),
+               .rc_proto = RC_PROTO_NEC,
+               .name     = RC_MAP_DREAMBOX,
+       }
+};
+
+static int __init init_rc_map_dreambox(void)
+{
+       return rc_map_register(&dreambox_map);
+}
+
+static void __exit exit_rc_map_dreambox(void)
+{
+       rc_map_unregister(&dreambox_map);
+}
+
+module_init(init_rc_map_dreambox)
+module_exit(exit_rc_map_dreambox)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Emanuel Strobel <emanuel.strobel@yahoo.com>");
index abdb62b16e980b5c5de81a962ec90ce275e1358a..6355b79893fb258d08452110de78576c49d3df94 100644 (file)
@@ -372,13 +372,11 @@ static int __init meson_irtx_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int meson_irtx_remove(struct platform_device *pdev)
+static void meson_irtx_remove(struct platform_device *pdev)
 {
        struct rc_dev *rc = platform_get_drvdata(pdev);
 
        rc_unregister_device(rc);
-
-       return 0;
 }
 
 static const struct of_device_id meson_irtx_dt_match[] = {
@@ -390,7 +388,7 @@ static const struct of_device_id meson_irtx_dt_match[] = {
 MODULE_DEVICE_TABLE(of, meson_irtx_dt_match);
 
 static struct platform_driver meson_irtx_pd = {
-       .remove = meson_irtx_remove,
+       .remove_new = meson_irtx_remove,
        .driver = {
                .name = DRIVER_NAME,
                .of_match_table = meson_irtx_dt_match,
index 4b769111f78e347464daaf40526ff0d0934192ef..49aa309d1a8c03b1724b4f4bf1733bfd80dd408b 100644 (file)
@@ -177,7 +177,7 @@ static int meson_ir_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int meson_ir_remove(struct platform_device *pdev)
+static void meson_ir_remove(struct platform_device *pdev)
 {
        struct meson_ir *ir = platform_get_drvdata(pdev);
        unsigned long flags;
@@ -186,8 +186,6 @@ static int meson_ir_remove(struct platform_device *pdev)
        spin_lock_irqsave(&ir->lock, flags);
        meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, 0);
        spin_unlock_irqrestore(&ir->lock, flags);
-
-       return 0;
 }
 
 static void meson_ir_shutdown(struct platform_device *pdev)
@@ -226,7 +224,7 @@ MODULE_DEVICE_TABLE(of, meson_ir_match);
 
 static struct platform_driver meson_ir_driver = {
        .probe          = meson_ir_probe,
-       .remove         = meson_ir_remove,
+       .remove_new     = meson_ir_remove,
        .shutdown       = meson_ir_shutdown,
        .driver = {
                .name           = DRIVER_NAME,
index 27b7412d02a56b9656da044d9bb5cf034bf984ef..df9349330a931c6a25b228bdc7db90ced6f07fff 100644 (file)
@@ -420,7 +420,7 @@ exit_clkdisable_clk:
        return ret;
 }
 
-static int mtk_ir_remove(struct platform_device *pdev)
+static void mtk_ir_remove(struct platform_device *pdev)
 {
        struct mtk_ir *ir = platform_get_drvdata(pdev);
 
@@ -434,13 +434,11 @@ static int mtk_ir_remove(struct platform_device *pdev)
 
        clk_disable_unprepare(ir->bus);
        clk_disable_unprepare(ir->clk);
-
-       return 0;
 }
 
 static struct platform_driver mtk_ir_driver = {
        .probe          = mtk_ir_probe,
-       .remove         = mtk_ir_remove,
+       .remove_new     = mtk_ir_remove,
        .driver = {
                .name = MTK_IR_DEV,
                .of_match_table = mtk_ir_match,
index 19e987a048ccb9080933cbc1addfcef5f28ad32e..28477aa955635dd3d432aee1756f7023b060be7a 100644 (file)
@@ -194,7 +194,7 @@ static int st_rc_hardware_init(struct st_rc_device *dev)
        return 0;
 }
 
-static int st_rc_remove(struct platform_device *pdev)
+static void st_rc_remove(struct platform_device *pdev)
 {
        struct st_rc_device *rc_dev = platform_get_drvdata(pdev);
 
@@ -202,7 +202,6 @@ static int st_rc_remove(struct platform_device *pdev)
        device_init_wakeup(&pdev->dev, false);
        clk_disable_unprepare(rc_dev->sys_clock);
        rc_unregister_device(rc_dev->rdev);
-       return 0;
 }
 
 static int st_rc_open(struct rc_dev *rdev)
@@ -408,7 +407,7 @@ static struct platform_driver st_rc_driver = {
                .pm     = &st_rc_pm_ops,
        },
        .probe = st_rc_probe,
-       .remove = st_rc_remove,
+       .remove_new = st_rc_remove,
 };
 
 module_platform_driver(st_rc_driver);
index b631a81e58bb1eea338587288212dc96175ed6ed..75b7aed1579c9fc33424adb37faad14744e29318 100644 (file)
@@ -364,14 +364,12 @@ exit_free_dev:
        return ret;
 }
 
-static int sunxi_ir_remove(struct platform_device *pdev)
+static void sunxi_ir_remove(struct platform_device *pdev)
 {
        struct sunxi_ir *ir = platform_get_drvdata(pdev);
 
        rc_unregister_device(ir->rc);
        sunxi_ir_hw_exit(&pdev->dev);
-
-       return 0;
 }
 
 static void sunxi_ir_shutdown(struct platform_device *pdev)
@@ -413,7 +411,7 @@ MODULE_DEVICE_TABLE(of, sunxi_ir_match);
 
 static struct platform_driver sunxi_ir_driver = {
        .probe          = sunxi_ir_probe,
-       .remove         = sunxi_ir_remove,
+       .remove_new     = sunxi_ir_remove,
        .shutdown       = sunxi_ir_shutdown,
        .driver = {
                .name = SUNXI_IR_DEV,
index 1d1bee11173264c83a89819d88dea57678292ac9..6f0e20df74e91795fdb5a8525986de6331ea698f 100644 (file)
@@ -2179,7 +2179,7 @@ free_dev:
        return ret;
 }
 
-static int vicodec_remove(struct platform_device *pdev)
+static void vicodec_remove(struct platform_device *pdev)
 {
        struct vicodec_dev *dev = platform_get_drvdata(pdev);
 
@@ -2196,13 +2196,11 @@ static int vicodec_remove(struct platform_device *pdev)
        video_unregister_device(&dev->stateful_dec.vfd);
        video_unregister_device(&dev->stateless_dec.vfd);
        v4l2_device_put(&dev->v4l2_dev);
-
-       return 0;
 }
 
 static struct platform_driver vicodec_pdrv = {
        .probe          = vicodec_probe,
-       .remove         = vicodec_remove,
+       .remove_new     = vicodec_remove,
        .driver         = {
                .name   = VICODEC_NAME,
        },
index dff7265a42ca2073d3229567718f732608ee8f92..8b04e12af286cc7ff4d0dccea1e9cc8e7ff3a35a 100644 (file)
@@ -528,7 +528,7 @@ err_dvb:
        return ret;
 }
 
-static int vidtv_bridge_remove(struct platform_device *pdev)
+static void vidtv_bridge_remove(struct platform_device *pdev)
 {
        struct vidtv_dvb *dvb;
        u32 i;
@@ -552,8 +552,6 @@ static int vidtv_bridge_remove(struct platform_device *pdev)
        dvb_dmx_release(&dvb->demux);
        dvb_unregister_adapter(&dvb->adapter);
        dev_info(&pdev->dev, "Successfully removed vidtv\n");
-
-       return 0;
 }
 
 static void vidtv_bridge_dev_release(struct device *dev)
@@ -574,7 +572,7 @@ static struct platform_driver vidtv_bridge_driver = {
                .name = VIDTV_PDEV_NAME,
        },
        .probe    = vidtv_bridge_probe,
-       .remove   = vidtv_bridge_remove,
+       .remove_new = vidtv_bridge_remove,
 };
 
 static void __exit vidtv_bridge_exit(void)
index 7964426bf2f77674aee8601b4c136dc918b79a02..3e3b424b4860580f8b670c75e84240a0f23d9ac3 100644 (file)
@@ -1379,7 +1379,7 @@ error_free:
        return ret;
 }
 
-static int vim2m_remove(struct platform_device *pdev)
+static void vim2m_remove(struct platform_device *pdev)
 {
        struct vim2m_dev *dev = platform_get_drvdata(pdev);
 
@@ -1390,13 +1390,11 @@ static int vim2m_remove(struct platform_device *pdev)
        v4l2_m2m_unregister_media_controller(dev->m2m_dev);
 #endif
        video_unregister_device(&dev->vfd);
-
-       return 0;
 }
 
 static struct platform_driver vim2m_pdrv = {
        .probe          = vim2m_probe,
-       .remove         = vim2m_remove,
+       .remove_new     = vim2m_remove,
        .driver         = {
                .name   = MEM2MEM_NAME,
        },
index 7b27153c0728bd33b4612bb4e59277d8aae3216e..2e72974e35b485582af0708493aab038f5b4695a 100644 (file)
@@ -241,13 +241,13 @@ static int vimc_get_pix_format(struct media_pad *pad,
        if (is_media_entity_v4l2_subdev(pad->entity)) {
                struct v4l2_subdev *sd =
                        media_entity_to_v4l2_subdev(pad->entity);
-               struct v4l2_subdev_format sd_fmt;
+               struct v4l2_subdev_format sd_fmt = {
+                       .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+                       .pad = pad->index,
+               };
                const struct vimc_pix_map *pix_map;
                int ret;
 
-               sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-               sd_fmt.pad = pad->index;
-
                ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt);
                if (ret)
                        return ret;
index e82cfa5ffbf47e2f4222ccb499ff7db9d51d0245..af127476e920e6991740cbc4c7b92dd9b178c93f 100644 (file)
@@ -387,7 +387,7 @@ static int vimc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int vimc_remove(struct platform_device *pdev)
+static void vimc_remove(struct platform_device *pdev)
 {
        struct vimc_device *vimc = platform_get_drvdata(pdev);
 
@@ -397,8 +397,6 @@ static int vimc_remove(struct platform_device *pdev)
        media_device_unregister(&vimc->mdev);
        v4l2_device_unregister(&vimc->v4l2_dev);
        v4l2_device_put(&vimc->v4l2_dev);
-
-       return 0;
 }
 
 static void vimc_dev_release(struct device *dev)
@@ -412,7 +410,7 @@ static struct platform_device vimc_pdev = {
 
 static struct platform_driver vimc_pdrv = {
        .probe          = vimc_probe,
-       .remove         = vimc_remove,
+       .remove_new     = vimc_remove,
        .driver         = {
                .name   = VIMC_PDEV_NAME,
        },
index 9cb60ab653bf5990f81fb54bb541c8f977d65382..9970dc739ca56c85609ed756b7c0c23f4cd646d5 100644 (file)
@@ -480,7 +480,7 @@ error_visl_dev:
        return ret;
 }
 
-static int visl_remove(struct platform_device *pdev)
+static void visl_remove(struct platform_device *pdev)
 {
        struct visl_dev *dev = platform_get_drvdata(pdev);
 
@@ -493,13 +493,11 @@ static int visl_remove(struct platform_device *pdev)
        }
 #endif
        video_unregister_device(&dev->vfd);
-
-       return 0;
 }
 
 static struct platform_driver visl_pdrv = {
        .probe          = visl_probe,
-       .remove         = visl_remove,
+       .remove_new     = visl_remove,
        .driver         = {
                .name   = VISL_NAME,
        },
index f28440e6c9f891711fa9d0625c5f4042a87437c8..c2167ccfd222b3f5be7e7268f0b1a8589e26186d 100644 (file)
@@ -126,7 +126,7 @@ MODULE_PARM_DESC(node_types, " node types, default is 0xe1d3d. Bitmask with the
                             "\t\t    bit 8: Video Output node\n"
                             "\t\t    bit 10-11: VBI Output node: 0 = none, 1 = raw vbi, 2 = sliced vbi, 3 = both\n"
                             "\t\t    bit 12: Radio Transmitter node\n"
-                            "\t\t    bit 16: Framebuffer for testing overlays\n"
+                            "\t\t    bit 16: Framebuffer for testing output overlays\n"
                             "\t\t    bit 17: Metadata Capture node\n"
                             "\t\t    bit 18: Metadata Output node\n"
                             "\t\t    bit 19: Touch Capture node\n");
@@ -326,7 +326,7 @@ static int vidioc_overlay(struct file *file, void *fh, unsigned i)
        struct video_device *vdev = video_devdata(file);
 
        if (vdev->vfl_dir == VFL_DIR_RX)
-               return vivid_vid_cap_overlay(file, fh, i);
+               return -ENOTTY;
        return vivid_vid_out_overlay(file, fh, i);
 }
 
@@ -335,38 +335,16 @@ static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a
        struct video_device *vdev = video_devdata(file);
 
        if (vdev->vfl_dir == VFL_DIR_RX)
-               return vivid_vid_cap_g_fbuf(file, fh, a);
+               return -ENOTTY;
        return vivid_vid_out_g_fbuf(file, fh, a);
 }
 
-/*
- * Only support the framebuffer of one of the vivid instances.
- * Anything else is rejected.
- */
-bool vivid_validate_fb(const struct v4l2_framebuffer *a)
-{
-       struct vivid_dev *dev;
-       int i;
-
-       for (i = 0; i < n_devs; i++) {
-               dev = vivid_devs[i];
-               if (!dev || !dev->video_pbase)
-                       continue;
-               if ((unsigned long)a->base == dev->video_pbase &&
-                   a->fmt.width <= dev->display_width &&
-                   a->fmt.height <= dev->display_height &&
-                   a->fmt.bytesperline <= dev->display_byte_stride)
-                       return true;
-       }
-       return false;
-}
-
 static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a)
 {
        struct video_device *vdev = video_devdata(file);
 
        if (vdev->vfl_dir == VFL_DIR_RX)
-               return vivid_vid_cap_s_fbuf(file, fh, a);
+               return -ENOTTY;
        return vivid_vid_out_s_fbuf(file, fh, a);
 }
 
@@ -651,8 +629,6 @@ static int vivid_fop_release(struct file *file)
                vivid_reconnect(dev);
        }
        mutex_unlock(&dev->mutex);
-       if (file->private_data == dev->overlay_cap_owner)
-               dev->overlay_cap_owner = NULL;
        if (file->private_data == dev->radio_rx_rds_owner) {
                dev->radio_rx_rds_last_block = 0;
                dev->radio_rx_rds_owner = NULL;
@@ -778,10 +754,6 @@ static const struct v4l2_ioctl_ops vivid_ioctl_ops = {
        .vidioc_g_parm                  = vidioc_g_parm,
        .vidioc_s_parm                  = vidioc_s_parm,
 
-       .vidioc_enum_fmt_vid_overlay    = vidioc_enum_fmt_vid_overlay,
-       .vidioc_g_fmt_vid_overlay       = vidioc_g_fmt_vid_overlay,
-       .vidioc_try_fmt_vid_overlay     = vidioc_try_fmt_vid_overlay,
-       .vidioc_s_fmt_vid_overlay       = vidioc_s_fmt_vid_overlay,
        .vidioc_g_fmt_vid_out_overlay   = vidioc_g_fmt_vid_out_overlay,
        .vidioc_try_fmt_vid_out_overlay = vidioc_try_fmt_vid_out_overlay,
        .vidioc_s_fmt_vid_out_overlay   = vidioc_s_fmt_vid_out_overlay,
@@ -862,8 +834,6 @@ static void vivid_dev_release(struct v4l2_device *v4l2_dev)
        vfree(dev->scaled_line);
        vfree(dev->blended_line);
        vfree(dev->edid);
-       vfree(dev->bitmap_cap);
-       vfree(dev->bitmap_out);
        tpg_free(&dev->tpg);
        kfree(dev->query_dv_timings_qmenu);
        kfree(dev->query_dv_timings_qmenu_strings);
@@ -1107,7 +1077,7 @@ static void vivid_set_capabilities(struct vivid_dev *dev)
                /* set up the capabilities of the video capture device */
                dev->vid_cap_caps = dev->multiplanar ?
                        V4L2_CAP_VIDEO_CAPTURE_MPLANE :
-                       V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY;
+                       V4L2_CAP_VIDEO_CAPTURE;
                dev->vid_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
                if (dev->has_audio_inputs)
                        dev->vid_cap_caps |= V4L2_CAP_AUDIO;
@@ -1396,7 +1366,7 @@ static int vivid_create_queues(struct vivid_dev *dev)
        }
 
        if (dev->has_fb) {
-               /* Create framebuffer for testing capture/output overlay */
+               /* Create framebuffer for testing output overlay */
                ret = vivid_fb_init(dev);
                if (ret)
                        return ret;
@@ -1892,13 +1862,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
        vivid_update_format_cap(dev, false);
        vivid_update_format_out(dev);
 
-       /* initialize overlay */
-       dev->fb_cap.fmt.width = dev->src_rect.width;
-       dev->fb_cap.fmt.height = dev->src_rect.height;
-       dev->fb_cap.fmt.pixelformat = dev->fmt_cap->fourcc;
-       dev->fb_cap.fmt.bytesperline = dev->src_rect.width * tpg_g_twopixelsize(&dev->tpg, 0) / 2;
-       dev->fb_cap.fmt.sizeimage = dev->src_rect.height * dev->fb_cap.fmt.bytesperline;
-
        /* update touch configuration */
        dev->timeperframe_tch_cap.numerator = 1;
        dev->timeperframe_tch_cap.denominator = 10;
@@ -2058,7 +2021,7 @@ static int vivid_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int vivid_remove(struct platform_device *pdev)
+static void vivid_remove(struct platform_device *pdev)
 {
        struct vivid_dev *dev;
        unsigned int i, j;
@@ -2138,7 +2101,6 @@ static int vivid_remove(struct platform_device *pdev)
                v4l2_device_put(&dev->v4l2_dev);
                vivid_devs[i] = NULL;
        }
-       return 0;
 }
 
 static void vivid_pdev_release(struct device *dev)
@@ -2152,7 +2114,7 @@ static struct platform_device vivid_pdev = {
 
 static struct platform_driver vivid_pdrv = {
        .probe          = vivid_probe,
-       .remove         = vivid_remove,
+       .remove_new     = vivid_remove,
        .driver         = {
                .name   = "vivid",
        },
index 473f3598db5af5198a50e92f2a0688ecb4afb0fe..cfb8e66083f6eda63fbd1bf50800822e146c106e 100644 (file)
@@ -22,8 +22,6 @@
 #define dprintk(dev, level, fmt, arg...) \
        v4l2_dbg(level, vivid_debug, &dev->v4l2_dev, fmt, ## arg)
 
-/* The maximum number of clip rectangles */
-#define MAX_CLIPS  16
 /* The maximum number of inputs */
 #define MAX_INPUTS 16
 /* The maximum number of outputs */
@@ -345,17 +343,6 @@ struct vivid_dev {
 
        u32                             power_present;
 
-       /* Capture Overlay */
-       struct v4l2_framebuffer         fb_cap;
-       struct v4l2_fh                  *overlay_cap_owner;
-       void                            *fb_vbase_cap;
-       int                             overlay_cap_top, overlay_cap_left;
-       enum v4l2_field                 overlay_cap_field;
-       void                            *bitmap_cap;
-       struct v4l2_clip                clips_cap[MAX_CLIPS];
-       struct v4l2_clip                try_clips_cap[MAX_CLIPS];
-       unsigned                        clipcount_cap;
-
        /* Output */
        unsigned                        output;
        v4l2_std_id                     std_out;
@@ -383,10 +370,6 @@ struct vivid_dev {
        void                            *fb_vbase_out;
        bool                            overlay_out_enabled;
        int                             overlay_out_top, overlay_out_left;
-       void                            *bitmap_out;
-       struct v4l2_clip                clips_out[MAX_CLIPS];
-       struct v4l2_clip                try_clips_out[MAX_CLIPS];
-       unsigned                        clipcount_out;
        unsigned                        fbuf_out_flags;
        u32                             chromakey_out;
        u8                              global_alpha_out;
@@ -613,6 +596,4 @@ static inline bool vivid_is_hdmi_out(const struct vivid_dev *dev)
        return dev->output_type[dev->output] == HDMI;
 }
 
-bool vivid_validate_fb(const struct v4l2_framebuffer *a);
-
 #endif
index ee65d20314d3df2d50a3ea16b1e2b4f668136857..42048727d7ff359bdf7769cfba549b72f47b6283 100644 (file)
@@ -53,31 +53,10 @@ static void copy_pix(struct vivid_dev *dev, int win_y, int win_x,
                        u16 *cap, const u16 *osd)
 {
        u16 out;
-       int left = dev->overlay_out_left;
-       int top = dev->overlay_out_top;
-       int fb_x = win_x + left;
-       int fb_y = win_y + top;
-       int i;
 
        out = *cap;
        *cap = *osd;
-       if (dev->bitmap_out) {
-               const u8 *p = dev->bitmap_out;
-               unsigned stride = (dev->compose_out.width + 7) / 8;
 
-               win_x -= dev->compose_out.left;
-               win_y -= dev->compose_out.top;
-               if (!(p[stride * win_y + win_x / 8] & (1 << (win_x & 7))))
-                       return;
-       }
-
-       for (i = 0; i < dev->clipcount_out; i++) {
-               struct v4l2_rect *r = &dev->clips_out[i].c;
-
-               if (fb_y >= r->top && fb_y < r->top + r->height &&
-                   fb_x >= r->left && fb_x < r->left + r->width)
-                       return;
-       }
        if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_CHROMAKEY) &&
            *osd != dev->chromakey_out)
                return;
@@ -251,7 +230,7 @@ static noinline_for_stack int vivid_copy_buffer(struct vivid_dev *dev, unsigned
        u8 *voutbuf;
        u8 *vosdbuf = NULL;
        unsigned y;
-       bool blend = dev->bitmap_out || dev->clipcount_out || dev->fbuf_out_flags;
+       bool blend = dev->fbuf_out_flags;
        /* Coarse scaling with Bresenham */
        unsigned vid_out_int_part;
        unsigned vid_out_fract_part;
@@ -554,109 +533,6 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
        }
 }
 
-/*
- * Return true if this pixel coordinate is a valid video pixel.
- */
-static bool valid_pix(struct vivid_dev *dev, int win_y, int win_x, int fb_y, int fb_x)
-{
-       int i;
-
-       if (dev->bitmap_cap) {
-               /*
-                * Only if the corresponding bit in the bitmap is set can
-                * the video pixel be shown. Coordinates are relative to
-                * the overlay window set by VIDIOC_S_FMT.
-                */
-               const u8 *p = dev->bitmap_cap;
-               unsigned stride = (dev->compose_cap.width + 7) / 8;
-
-               if (!(p[stride * win_y + win_x / 8] & (1 << (win_x & 7))))
-                       return false;
-       }
-
-       for (i = 0; i < dev->clipcount_cap; i++) {
-               /*
-                * Only if the framebuffer coordinate is not in any of the
-                * clip rectangles will be video pixel be shown.
-                */
-               struct v4l2_rect *r = &dev->clips_cap[i].c;
-
-               if (fb_y >= r->top && fb_y < r->top + r->height &&
-                   fb_x >= r->left && fb_x < r->left + r->width)
-                       return false;
-       }
-       return true;
-}
-
-/*
- * Draw the image into the overlay buffer.
- * Note that the combination of overlay and multiplanar is not supported.
- */
-static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
-{
-       struct tpg_data *tpg = &dev->tpg;
-       unsigned pixsize = tpg_g_twopixelsize(tpg, 0) / 2;
-       void *vbase = dev->fb_vbase_cap;
-       void *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
-       unsigned img_width = dev->compose_cap.width;
-       unsigned img_height = dev->compose_cap.height;
-       unsigned stride = tpg->bytesperline[0];
-       /* if quick is true, then valid_pix() doesn't have to be called */
-       bool quick = dev->bitmap_cap == NULL && dev->clipcount_cap == 0;
-       int x, y, w, out_x = 0;
-
-       /*
-        * Overlay support is only supported for formats that have a twopixelsize
-        * that's >= 2. Warn and bail out if that's not the case.
-        */
-       if (WARN_ON(pixsize == 0))
-               return;
-       if ((dev->overlay_cap_field == V4L2_FIELD_TOP ||
-            dev->overlay_cap_field == V4L2_FIELD_BOTTOM) &&
-           dev->overlay_cap_field != buf->vb.field)
-               return;
-
-       vbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride;
-       x = dev->overlay_cap_left;
-       w = img_width;
-       if (x < 0) {
-               out_x = -x;
-               w = w - out_x;
-               x = 0;
-       } else {
-               w = dev->fb_cap.fmt.width - x;
-               if (w > img_width)
-                       w = img_width;
-       }
-       if (w <= 0)
-               return;
-       if (dev->overlay_cap_top >= 0)
-               vbase += dev->overlay_cap_top * dev->fb_cap.fmt.bytesperline;
-       for (y = dev->overlay_cap_top;
-            y < dev->overlay_cap_top + (int)img_height;
-            y++, vbuf += stride) {
-               int px;
-
-               if (y < 0 || y > dev->fb_cap.fmt.height)
-                       continue;
-               if (quick) {
-                       memcpy(vbase + x * pixsize,
-                              vbuf + out_x * pixsize, w * pixsize);
-                       vbase += dev->fb_cap.fmt.bytesperline;
-                       continue;
-               }
-               for (px = 0; px < w; px++) {
-                       if (!valid_pix(dev, y - dev->overlay_cap_top,
-                                      px + out_x, y, px + x))
-                               continue;
-                       memcpy(vbase + (px + x) * pixsize,
-                              vbuf + (px + out_x) * pixsize,
-                              pixsize);
-               }
-               vbase += dev->fb_cap.fmt.bytesperline;
-       }
-}
-
 static void vivid_cap_update_frame_period(struct vivid_dev *dev)
 {
        u64 f_period;
@@ -730,11 +606,6 @@ static noinline_for_stack void vivid_thread_vid_cap_tick(struct vivid_dev *dev,
                dprintk(dev, 1, "filled buffer %d\n",
                        vid_cap_buf->vb.vb2_buf.index);
 
-               /* Handle overlay */
-               if (dev->overlay_cap_owner && dev->fb_cap.base &&
-                       dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc)
-                       vivid_overlay(dev, vid_cap_buf);
-
                v4l2_ctrl_request_complete(vid_cap_buf->vb.vb2_buf.req_obj.req,
                                           &dev->ctrl_hdl_vid_cap);
                vb2_buffer_done(&vid_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
index c0999581c599bcdedd96200481e27d3ca87e7646..801286dc1448032b963ed5b1548fefab1f7b52fa 100644 (file)
 #include "vivid-kthread-cap.h"
 #include "vivid-vid-cap.h"
 
-static const struct vivid_fmt formats_ovl[] = {
-       {
-               .fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
-               .vdownsampling = { 1 },
-               .bit_depth = { 16 },
-               .planes   = 1,
-               .buffers = 1,
-       },
-       {
-               .fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb arrrrrgg */
-               .vdownsampling = { 1 },
-               .bit_depth = { 16 },
-               .planes   = 1,
-               .buffers = 1,
-       },
-       {
-               .fourcc   = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
-               .vdownsampling = { 1 },
-               .bit_depth = { 16 },
-               .planes   = 1,
-               .buffers = 1,
-       },
-};
-
 /* The number of discrete webcam framesizes */
 #define VIVID_WEBCAM_SIZES 6
 /* The number of discrete webcam frameintervals */
@@ -447,18 +423,10 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
                tpg_s_rgb_range(&dev->tpg, v4l2_ctrl_g_ctrl(dev->rgb_range_cap));
                break;
        }
-       vfree(dev->bitmap_cap);
-       dev->bitmap_cap = NULL;
        vivid_update_quality(dev);
        tpg_reset_source(&dev->tpg, dev->src_rect.width, dev->src_rect.height, dev->field_cap);
        dev->crop_cap = dev->src_rect;
        dev->crop_bounds_cap = dev->src_rect;
-       if (dev->bitmap_cap &&
-           (dev->compose_cap.width != dev->crop_cap.width ||
-            dev->compose_cap.height != dev->crop_cap.height)) {
-               vfree(dev->bitmap_cap);
-               dev->bitmap_cap = NULL;
-       }
        dev->compose_cap = dev->crop_cap;
        if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap))
                dev->compose_cap.height /= 2;
@@ -701,11 +669,6 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
                return -EBUSY;
        }
 
-       if (dev->overlay_cap_owner && dev->fb_cap.fmt.pixelformat != mp->pixelformat) {
-               dprintk(dev, 1, "overlay is active, can't change pixelformat\n");
-               return -EBUSY;
-       }
-
        dev->fmt_cap = vivid_get_format(dev, mp->pixelformat);
        if (V4L2_FIELD_HAS_T_OR_B(mp->field))
                factor = 2;
@@ -927,8 +890,6 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
        struct vivid_dev *dev = video_drvdata(file);
        struct v4l2_rect *crop = &dev->crop_cap;
        struct v4l2_rect *compose = &dev->compose_cap;
-       unsigned orig_compose_w = compose->width;
-       unsigned orig_compose_h = compose->height;
        unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
        int ret;
 
@@ -1052,11 +1013,6 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
                return -EINVAL;
        }
 
-       if (dev->bitmap_cap && (compose->width != orig_compose_w ||
-                               compose->height != orig_compose_h)) {
-               vfree(dev->bitmap_cap);
-               dev->bitmap_cap = NULL;
-       }
        tpg_s_crop_compose(&dev->tpg, crop, compose);
        return 0;
 }
@@ -1084,234 +1040,6 @@ int vivid_vid_cap_g_pixelaspect(struct file *file, void *priv,
        return 0;
 }
 
-int vidioc_enum_fmt_vid_overlay(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       struct vivid_dev *dev = video_drvdata(file);
-       const struct vivid_fmt *fmt;
-
-       if (dev->multiplanar)
-               return -ENOTTY;
-
-       if (f->index >= ARRAY_SIZE(formats_ovl))
-               return -EINVAL;
-
-       fmt = &formats_ovl[f->index];
-
-       f->pixelformat = fmt->fourcc;
-       return 0;
-}
-
-int vidioc_g_fmt_vid_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct vivid_dev *dev = video_drvdata(file);
-       const struct v4l2_rect *compose = &dev->compose_cap;
-       struct v4l2_window *win = &f->fmt.win;
-       unsigned clipcount = win->clipcount;
-
-       if (dev->multiplanar)
-               return -ENOTTY;
-
-       win->w.top = dev->overlay_cap_top;
-       win->w.left = dev->overlay_cap_left;
-       win->w.width = compose->width;
-       win->w.height = compose->height;
-       win->field = dev->overlay_cap_field;
-       win->clipcount = dev->clipcount_cap;
-       if (clipcount > dev->clipcount_cap)
-               clipcount = dev->clipcount_cap;
-       if (dev->bitmap_cap == NULL)
-               win->bitmap = NULL;
-       else if (win->bitmap) {
-               if (copy_to_user(win->bitmap, dev->bitmap_cap,
-                   ((compose->width + 7) / 8) * compose->height))
-                       return -EFAULT;
-       }
-       if (clipcount && win->clips)
-               memcpy(win->clips, dev->clips_cap,
-                      clipcount * sizeof(dev->clips_cap[0]));
-       return 0;
-}
-
-int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct vivid_dev *dev = video_drvdata(file);
-       const struct v4l2_rect *compose = &dev->compose_cap;
-       struct v4l2_window *win = &f->fmt.win;
-       int i, j;
-
-       if (dev->multiplanar)
-               return -ENOTTY;
-
-       win->w.left = clamp_t(int, win->w.left,
-                             -dev->fb_cap.fmt.width, dev->fb_cap.fmt.width);
-       win->w.top = clamp_t(int, win->w.top,
-                            -dev->fb_cap.fmt.height, dev->fb_cap.fmt.height);
-       win->w.width = compose->width;
-       win->w.height = compose->height;
-       if (win->field != V4L2_FIELD_BOTTOM && win->field != V4L2_FIELD_TOP)
-               win->field = V4L2_FIELD_ANY;
-       win->chromakey = 0;
-       win->global_alpha = 0;
-       if (win->clipcount && !win->clips)
-               win->clipcount = 0;
-       if (win->clipcount > MAX_CLIPS)
-               win->clipcount = MAX_CLIPS;
-       if (win->clipcount) {
-               memcpy(dev->try_clips_cap, win->clips,
-                      win->clipcount * sizeof(dev->clips_cap[0]));
-               for (i = 0; i < win->clipcount; i++) {
-                       struct v4l2_rect *r = &dev->try_clips_cap[i].c;
-
-                       r->top = clamp_t(s32, r->top, 0, dev->fb_cap.fmt.height - 1);
-                       r->height = clamp_t(s32, r->height, 1, dev->fb_cap.fmt.height - r->top);
-                       r->left = clamp_t(u32, r->left, 0, dev->fb_cap.fmt.width - 1);
-                       r->width = clamp_t(u32, r->width, 1, dev->fb_cap.fmt.width - r->left);
-               }
-               /*
-                * Yeah, so sue me, it's an O(n^2) algorithm. But n is a small
-                * number and it's typically a one-time deal.
-                */
-               for (i = 0; i < win->clipcount - 1; i++) {
-                       struct v4l2_rect *r1 = &dev->try_clips_cap[i].c;
-
-                       for (j = i + 1; j < win->clipcount; j++) {
-                               struct v4l2_rect *r2 = &dev->try_clips_cap[j].c;
-
-                               if (v4l2_rect_overlap(r1, r2))
-                                       return -EINVAL;
-                       }
-               }
-               memcpy(win->clips, dev->try_clips_cap,
-                      win->clipcount * sizeof(dev->clips_cap[0]));
-       }
-       return 0;
-}
-
-int vidioc_s_fmt_vid_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct vivid_dev *dev = video_drvdata(file);
-       const struct v4l2_rect *compose = &dev->compose_cap;
-       struct v4l2_window *win = &f->fmt.win;
-       int ret = vidioc_try_fmt_vid_overlay(file, priv, f);
-       unsigned bitmap_size = ((compose->width + 7) / 8) * compose->height;
-       unsigned clips_size = win->clipcount * sizeof(dev->clips_cap[0]);
-       void *new_bitmap = NULL;
-
-       if (ret)
-               return ret;
-
-       if (win->bitmap) {
-               new_bitmap = vzalloc(bitmap_size);
-
-               if (new_bitmap == NULL)
-                       return -ENOMEM;
-               if (copy_from_user(new_bitmap, win->bitmap, bitmap_size)) {
-                       vfree(new_bitmap);
-                       return -EFAULT;
-               }
-       }
-
-       dev->overlay_cap_top = win->w.top;
-       dev->overlay_cap_left = win->w.left;
-       dev->overlay_cap_field = win->field;
-       vfree(dev->bitmap_cap);
-       dev->bitmap_cap = new_bitmap;
-       dev->clipcount_cap = win->clipcount;
-       if (dev->clipcount_cap)
-               memcpy(dev->clips_cap, dev->try_clips_cap, clips_size);
-       return 0;
-}
-
-int vivid_vid_cap_overlay(struct file *file, void *fh, unsigned i)
-{
-       struct vivid_dev *dev = video_drvdata(file);
-
-       if (dev->multiplanar)
-               return -ENOTTY;
-
-       if (i && dev->fb_vbase_cap == NULL)
-               return -EINVAL;
-
-       if (i && dev->fb_cap.fmt.pixelformat != dev->fmt_cap->fourcc) {
-               dprintk(dev, 1, "mismatch between overlay and video capture pixelformats\n");
-               return -EINVAL;
-       }
-
-       if (dev->overlay_cap_owner && dev->overlay_cap_owner != fh)
-               return -EBUSY;
-       dev->overlay_cap_owner = i ? fh : NULL;
-       return 0;
-}
-
-int vivid_vid_cap_g_fbuf(struct file *file, void *fh,
-                               struct v4l2_framebuffer *a)
-{
-       struct vivid_dev *dev = video_drvdata(file);
-
-       if (dev->multiplanar)
-               return -ENOTTY;
-
-       *a = dev->fb_cap;
-       a->capability = V4L2_FBUF_CAP_BITMAP_CLIPPING |
-                       V4L2_FBUF_CAP_LIST_CLIPPING;
-       a->flags = V4L2_FBUF_FLAG_PRIMARY;
-       a->fmt.field = V4L2_FIELD_NONE;
-       a->fmt.colorspace = V4L2_COLORSPACE_SRGB;
-       a->fmt.priv = 0;
-       return 0;
-}
-
-int vivid_vid_cap_s_fbuf(struct file *file, void *fh,
-                               const struct v4l2_framebuffer *a)
-{
-       struct vivid_dev *dev = video_drvdata(file);
-       const struct vivid_fmt *fmt;
-
-       if (dev->multiplanar)
-               return -ENOTTY;
-
-       if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       if (dev->overlay_cap_owner)
-               return -EBUSY;
-
-       if (a->base == NULL) {
-               dev->fb_cap.base = NULL;
-               dev->fb_vbase_cap = NULL;
-               return 0;
-       }
-
-       if (a->fmt.width < 48 || a->fmt.height < 32)
-               return -EINVAL;
-       fmt = vivid_get_format(dev, a->fmt.pixelformat);
-       if (!fmt || !fmt->can_do_overlay)
-               return -EINVAL;
-       if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8)
-               return -EINVAL;
-       if (a->fmt.bytesperline > a->fmt.sizeimage / a->fmt.height)
-               return -EINVAL;
-
-       /*
-        * Only support the framebuffer of one of the vivid instances.
-        * Anything else is rejected.
-        */
-       if (!vivid_validate_fb(a))
-               return -EINVAL;
-
-       dev->fb_vbase_cap = phys_to_virt((unsigned long)a->base);
-       dev->fb_cap = *a;
-       dev->overlay_cap_left = clamp_t(int, dev->overlay_cap_left,
-                                   -dev->fb_cap.fmt.width, dev->fb_cap.fmt.width);
-       dev->overlay_cap_top = clamp_t(int, dev->overlay_cap_top,
-                                  -dev->fb_cap.fmt.height, dev->fb_cap.fmt.height);
-       return 0;
-}
-
 static const struct v4l2_audio vivid_audio_inputs[] = {
        { 0, "TV", V4L2_AUDCAP_STEREO },
        { 1, "Line-In", V4L2_AUDCAP_STEREO },
index 1e422a59eeabf1629f4bea408c5be9fed605f46f..949768652d38222f3dea13592ffa34a52ef6e7ea 100644 (file)
@@ -33,9 +33,6 @@ int vidioc_enum_fmt_vid_overlay(struct file *file, void  *priv, struct v4l2_fmtd
 int vidioc_g_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f);
 int vidioc_try_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f);
 int vidioc_s_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_vid_cap_overlay(struct file *file, void *fh, unsigned i);
-int vivid_vid_cap_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a);
-int vivid_vid_cap_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a);
 int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp);
 int vidioc_g_input(struct file *file, void *priv, unsigned *i);
 int vidioc_s_input(struct file *file, void *priv, unsigned i);
index 9f731f085179e87a3cdf4fa3911e8555f6f8be94..184a6df2c29fe20d58f46b2de8da8b01221a9844 100644 (file)
@@ -793,11 +793,6 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection
                }
                s->r.top *= factor;
                s->r.height *= factor;
-               if (dev->bitmap_out && (compose->width != s->r.width ||
-                                       compose->height != s->r.height)) {
-                       vfree(dev->bitmap_out);
-                       dev->bitmap_out = NULL;
-               }
                *compose = s->r;
                break;
        default:
@@ -836,7 +831,6 @@ int vidioc_g_fmt_vid_out_overlay(struct file *file, void *priv,
        struct vivid_dev *dev = video_drvdata(file);
        const struct v4l2_rect *compose = &dev->compose_out;
        struct v4l2_window *win = &f->fmt.win;
-       unsigned clipcount = win->clipcount;
 
        if (!dev->has_fb)
                return -EINVAL;
@@ -844,22 +838,9 @@ int vidioc_g_fmt_vid_out_overlay(struct file *file, void *priv,
        win->w.left = dev->overlay_out_left;
        win->w.width = compose->width;
        win->w.height = compose->height;
-       win->clipcount = dev->clipcount_out;
        win->field = V4L2_FIELD_ANY;
        win->chromakey = dev->chromakey_out;
        win->global_alpha = dev->global_alpha_out;
-       if (clipcount > dev->clipcount_out)
-               clipcount = dev->clipcount_out;
-       if (dev->bitmap_out == NULL)
-               win->bitmap = NULL;
-       else if (win->bitmap) {
-               if (copy_to_user(win->bitmap, dev->bitmap_out,
-                   ((dev->compose_out.width + 7) / 8) * dev->compose_out.height))
-                       return -EFAULT;
-       }
-       if (clipcount && win->clips)
-               memcpy(win->clips, dev->clips_out,
-                      clipcount * sizeof(dev->clips_out[0]));
        return 0;
 }
 
@@ -869,7 +850,6 @@ int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv,
        struct vivid_dev *dev = video_drvdata(file);
        const struct v4l2_rect *compose = &dev->compose_out;
        struct v4l2_window *win = &f->fmt.win;
-       int i, j;
 
        if (!dev->has_fb)
                return -EINVAL;
@@ -884,38 +864,6 @@ int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv,
         * so always set this to ANY.
         */
        win->field = V4L2_FIELD_ANY;
-       if (win->clipcount && !win->clips)
-               win->clipcount = 0;
-       if (win->clipcount > MAX_CLIPS)
-               win->clipcount = MAX_CLIPS;
-       if (win->clipcount) {
-               memcpy(dev->try_clips_out, win->clips,
-                      win->clipcount * sizeof(dev->clips_out[0]));
-               for (i = 0; i < win->clipcount; i++) {
-                       struct v4l2_rect *r = &dev->try_clips_out[i].c;
-
-                       r->top = clamp_t(s32, r->top, 0, dev->display_height - 1);
-                       r->height = clamp_t(s32, r->height, 1, dev->display_height - r->top);
-                       r->left = clamp_t(u32, r->left, 0, dev->display_width - 1);
-                       r->width = clamp_t(u32, r->width, 1, dev->display_width - r->left);
-               }
-               /*
-                * Yeah, so sue me, it's an O(n^2) algorithm. But n is a small
-                * number and it's typically a one-time deal.
-                */
-               for (i = 0; i < win->clipcount - 1; i++) {
-                       struct v4l2_rect *r1 = &dev->try_clips_out[i].c;
-
-                       for (j = i + 1; j < win->clipcount; j++) {
-                               struct v4l2_rect *r2 = &dev->try_clips_out[j].c;
-
-                               if (v4l2_rect_overlap(r1, r2))
-                                       return -EINVAL;
-                       }
-               }
-               memcpy(win->clips, dev->try_clips_out,
-                      win->clipcount * sizeof(dev->clips_out[0]));
-       }
        return 0;
 }
 
@@ -923,34 +871,14 @@ int vidioc_s_fmt_vid_out_overlay(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
        struct vivid_dev *dev = video_drvdata(file);
-       const struct v4l2_rect *compose = &dev->compose_out;
        struct v4l2_window *win = &f->fmt.win;
        int ret = vidioc_try_fmt_vid_out_overlay(file, priv, f);
-       unsigned bitmap_size = ((compose->width + 7) / 8) * compose->height;
-       unsigned clips_size = win->clipcount * sizeof(dev->clips_out[0]);
-       void *new_bitmap = NULL;
 
        if (ret)
                return ret;
 
-       if (win->bitmap) {
-               new_bitmap = vzalloc(bitmap_size);
-
-               if (!new_bitmap)
-                       return -ENOMEM;
-               if (copy_from_user(new_bitmap, win->bitmap, bitmap_size)) {
-                       vfree(new_bitmap);
-                       return -EFAULT;
-               }
-       }
-
        dev->overlay_out_top = win->w.top;
        dev->overlay_out_left = win->w.left;
-       vfree(dev->bitmap_out);
-       dev->bitmap_out = new_bitmap;
-       dev->clipcount_out = win->clipcount;
-       if (dev->clipcount_out)
-               memcpy(dev->clips_out, dev->try_clips_out, clips_size);
        dev->chromakey_out = win->chromakey;
        dev->global_alpha_out = win->global_alpha;
        return ret;
@@ -975,8 +903,6 @@ int vivid_vid_out_g_fbuf(struct file *file, void *fh,
        struct vivid_dev *dev = video_drvdata(file);
 
        a->capability = V4L2_FBUF_CAP_EXTERNOVERLAY |
-                       V4L2_FBUF_CAP_BITMAP_CLIPPING |
-                       V4L2_FBUF_CAP_LIST_CLIPPING |
                        V4L2_FBUF_CAP_CHROMAKEY |
                        V4L2_FBUF_CAP_SRC_CHROMAKEY |
                        V4L2_FBUF_CAP_GLOBAL_ALPHA |
index 7696a28fe4073dfe9540c92d80ab0e202f1c4e60..4d5b1c878028d2c0a62a714174006517e1eac008 100644 (file)
@@ -419,7 +419,7 @@ err:
        return ret;
 }
 
-static int it913x_remove(struct platform_device *pdev)
+static void it913x_remove(struct platform_device *pdev)
 {
        struct it913x_dev *dev = platform_get_drvdata(pdev);
        struct dvb_frontend *fe = dev->fe;
@@ -429,8 +429,6 @@ static int it913x_remove(struct platform_device *pdev)
        memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
        fe->tuner_priv = NULL;
        kfree(dev);
-
-       return 0;
 }
 
 static const struct platform_device_id it913x_id_table[] = {
@@ -446,7 +444,7 @@ static struct platform_driver it913x_driver = {
                .suppress_bind_attrs    = true,
        },
        .probe          = it913x_probe,
-       .remove         = it913x_remove,
+       .remove_new     = it913x_remove,
        .id_table       = it913x_id_table,
 };
 
index 3a509038c8dfbb36e8871968633d5fc0627e4615..06dfab9fb8cbcdde93ca4d1a9036b7f81d10f0f2 100644 (file)
@@ -3423,9 +3423,11 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
 
                        if (controlNum == state->Init_Ctrl[i].Ctrl_Num) {
 
-                               highLimit = 1 << state->Init_Ctrl[i].size;
+                               u16 size = min_t(u16, state->Init_Ctrl[i].size,
+                                              ARRAY_SIZE(state->Init_Ctrl[i].val));
+                               highLimit = 1 << size;
                                if (value < highLimit) {
-                                       for (j = 0; j < state->Init_Ctrl[i].size; j++) {
+                                       for (j = 0; j < size; j++) {
                                                state->Init_Ctrl[i].val[j] = (u8)((value >> j) & 0x01);
                                                MXL_RegWriteBit(fe, (u8)(state->Init_Ctrl[i].addr[j]),
                                                        (u8)(state->Init_Ctrl[i].bit[j]),
@@ -3442,9 +3444,11 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
 
                        if (controlNum == state->CH_Ctrl[i].Ctrl_Num) {
 
-                               highLimit = 1 << state->CH_Ctrl[i].size;
+                               u16 size = min_t(u16, state->CH_Ctrl[i].size,
+                                              ARRAY_SIZE(state->CH_Ctrl[i].val));
+                               highLimit = 1 << size;
                                if (value < highLimit) {
-                                       for (j = 0; j < state->CH_Ctrl[i].size; j++) {
+                                       for (j = 0; j < size; j++) {
                                                state->CH_Ctrl[i].val[j] = (u8)((value >> j) & 0x01);
                                                MXL_RegWriteBit(fe, (u8)(state->CH_Ctrl[i].addr[j]),
                                                        (u8)(state->CH_Ctrl[i].bit[j]),
index 877e85a451cbeb01e47eac282723eb93c1207b35..b3a09d3ac7d24068fad97af44ebf4e6cdd9aa093 100644 (file)
@@ -211,7 +211,7 @@ static int au0828_media_device_init(struct au0828_dev *dev,
 static void au0828_media_graph_notify(struct media_entity *new,
                                      void *notify_data)
 {
-       struct au0828_dev *dev = (struct au0828_dev *) notify_data;
+       struct au0828_dev *dev = notify_data;
        int ret;
        struct media_entity *entity, *mixer = NULL, *decoder = NULL;
 
@@ -627,14 +627,9 @@ static int au0828_media_device_register(struct au0828_dev *dev,
        /* register entity_notify callback */
        dev->entity_notify.notify_data = (void *) dev;
        dev->entity_notify.notify = (void *) au0828_media_graph_notify;
-       ret = media_device_register_entity_notify(dev->media_dev,
+       media_device_register_entity_notify(dev->media_dev,
                                                  &dev->entity_notify);
-       if (ret) {
-               dev_err(&udev->dev,
-                       "Media Device register entity_notify Error: %d\n",
-                       ret);
-               return ret;
-       }
+
        /* set enable_source */
        mutex_lock(&dev->media_dev->graph_mutex);
        dev->media_dev->source_priv = (void *) dev;
index 2a8691a0d7fae25a34e8cb0674ae8998ce1459f5..09f9948c6f8e65f79e683642b326f5d2de2c5f79 100644 (file)
@@ -273,7 +273,7 @@ static void au0828_stop_transport(struct au0828_dev *dev, int full_stop)
 static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
 {
        struct dvb_demux *demux = feed->demux;
-       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+       struct au0828_dev *dev = demux->priv;
        struct au0828_dvb *dvb = &dev->dvb;
        int ret = 0;
 
@@ -305,7 +305,7 @@ static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
 static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
 {
        struct dvb_demux *demux = feed->demux;
-       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+       struct au0828_dev *dev = demux->priv;
        struct au0828_dvb *dvb = &dev->dvb;
        int ret = 0;
 
index e93183ddd7975d84975d147bcf2d804157db2545..deba5224cb8dfd9105c196e769ab13d59e4ce0e3 100644 (file)
@@ -1014,7 +1014,10 @@ static int cxusb_medion_try_s_fmt_vid_cap(struct file *file,
 {
        struct dvb_usb_device *dvbdev = video_drvdata(file);
        struct cxusb_medion_dev *cxdev = dvbdev->priv;
-       struct v4l2_subdev_format subfmt;
+       struct v4l2_subdev_format subfmt = {
+               .which = isset ? V4L2_SUBDEV_FORMAT_ACTIVE :
+                        V4L2_SUBDEV_FORMAT_TRY,
+       };
        u32 field;
        int ret;
 
@@ -1024,9 +1027,6 @@ static int cxusb_medion_try_s_fmt_vid_cap(struct file *file,
        field = vb2_start_streaming_called(&cxdev->videoqueue) ?
                cxdev->field_order : cxusb_medion_field_order(cxdev);
 
-       memset(&subfmt, 0, sizeof(subfmt));
-       subfmt.which = isset ? V4L2_SUBDEV_FORMAT_ACTIVE :
-               V4L2_SUBDEV_FORMAT_TRY;
        subfmt.format.width = f->fmt.pix.width & ~1;
        subfmt.format.height = f->fmt.pix.height & ~1;
        subfmt.format.code = MEDIA_BUS_FMT_FIXED;
@@ -1464,7 +1464,9 @@ int cxusb_medion_analog_init(struct dvb_usb_device *dvbdev)
                                            .buf = tuner_analog_msg_data,
                                            .len =
                                            sizeof(tuner_analog_msg_data) };
-       struct v4l2_subdev_format subfmt;
+       struct v4l2_subdev_format subfmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
        /* switch tuner to analog mode so IF demod will become accessible */
@@ -1507,8 +1509,6 @@ int cxusb_medion_analog_init(struct dvb_usb_device *dvbdev)
        v4l2_subdev_call(cxdev->tuner, video, s_std, cxdev->norm);
        v4l2_subdev_call(cxdev->cx25840, video, s_std, cxdev->norm);
 
-       memset(&subfmt, 0, sizeof(subfmt));
-       subfmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        subfmt.format.width = cxdev->width;
        subfmt.format.height = cxdev->height;
        subfmt.format.code = MEDIA_BUS_FMT_FIXED;
index f0794c68c622e2b261025330eda17e81ca54a84b..da42c989e0719ee72d3c2388dd741db0cf922ddf 100644 (file)
@@ -26,6 +26,8 @@
 #include <media/dvb_ca_en50221.h>
 #include "ttpci-eeprom.h"
 
+#include <linux/etherdevice.h>
+
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
index f2b64e49c5a209e39a8c15842d7da26862191f34..9501b10b31aa57d1683f7ace1a0c05ebc7c604e8 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config VIDEO_PVRUSB2
        tristate "Hauppauge WinTV-PVR USB2 support"
-       depends on VIDEO_DEV && I2C
+       depends on VIDEO_DEV && I2C && DVB_CORE
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_CX2341X
index 2308c0b4f5e7eeb48151475a75d013cddab48740..1f7620cd2996d9ddfb4668dbdb7c2117252147e8 100644 (file)
@@ -47,7 +47,7 @@
 int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
 {
        int ret;
-       int pipe = usb_rcvctrlpipe(usbtv->udev, 0);
+       int pipe = usb_sndctrlpipe(usbtv->udev, 0);
        int i;
 
        for (i = 0; i < size; i++) {
index d7e9ffc7aa237f8bb3d53caee1a9e4b7b2155893..b16b5f4cb91e202f5827ab9c4ab0b818022dd9d3 100644 (file)
@@ -416,7 +416,8 @@ static void v4l2_async_cleanup(struct v4l2_subdev *sd)
 
 /* Unbind all sub-devices in the notifier tree. */
 static void
-v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
+v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
+                                bool readd)
 {
        struct v4l2_subdev *sd, *tmp;
 
@@ -425,9 +426,11 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
                        v4l2_async_find_subdev_notifier(sd);
 
                if (subdev_notifier)
-                       v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
+                       v4l2_async_nf_unbind_all_subdevs(subdev_notifier, true);
 
                v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
+               if (readd)
+                       list_add_tail(&sd->asd->list, &notifier->waiting);
                v4l2_async_cleanup(sd);
 
                list_move(&sd->async_list, &subdev_list);
@@ -559,7 +562,7 @@ err_unbind:
        /*
         * On failure, unbind all sub-devices registered through this notifier.
         */
-       v4l2_async_nf_unbind_all_subdevs(notifier);
+       v4l2_async_nf_unbind_all_subdevs(notifier, false);
 
 err_unlock:
        mutex_unlock(&list_lock);
@@ -609,7 +612,7 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
        if (!notifier || (!notifier->v4l2_dev && !notifier->sd))
                return;
 
-       v4l2_async_nf_unbind_all_subdevs(notifier);
+       v4l2_async_nf_unbind_all_subdevs(notifier, false);
 
        notifier->sd = NULL;
        notifier->v4l2_dev = NULL;
@@ -807,7 +810,7 @@ err_unbind:
         */
        subdev_notifier = v4l2_async_find_subdev_notifier(sd);
        if (subdev_notifier)
-               v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
+               v4l2_async_nf_unbind_all_subdevs(subdev_notifier, false);
 
        if (sd->asd)
                v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
index 40f56e044640d75ae9d41475c39b6b7c8cf0e9ae..3c5ab5ecd67895d3fa7b1c2e766394843ff757c8 100644 (file)
@@ -252,12 +252,16 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
                { .format = V4L2_PIX_FMT_RGB565,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
                { .format = V4L2_PIX_FMT_RGB555,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
                { .format = V4L2_PIX_FMT_BGR666,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
+               { .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
+               { .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
 
                /* YUV packed formats */
                { .format = V4L2_PIX_FMT_YUYV,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
                { .format = V4L2_PIX_FMT_YVYU,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
                { .format = V4L2_PIX_FMT_UYVY,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
                { .format = V4L2_PIX_FMT_VYUY,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
+               { .format = V4L2_PIX_FMT_Y212,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 },
+               { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
 
                /* YUV planar formats */
                { .format = V4L2_PIX_FMT_NV12,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
@@ -267,6 +271,7 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
                { .format = V4L2_PIX_FMT_NV24,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
                { .format = V4L2_PIX_FMT_NV42,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 },
                { .format = V4L2_PIX_FMT_P010,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
+               { .format = V4L2_PIX_FMT_P012,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 },
 
                { .format = V4L2_PIX_FMT_YUV410,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
                { .format = V4L2_PIX_FMT_YVU410,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 },
@@ -292,6 +297,7 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
                { .format = V4L2_PIX_FMT_NV21M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 },
                { .format = V4L2_PIX_FMT_NV16M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
                { .format = V4L2_PIX_FMT_NV61M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 },
+               { .format = V4L2_PIX_FMT_P012M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 },
 
                /* Bayer RGB formats */
                { .format = V4L2_PIX_FMT_SBGGR8,        .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 },
index 55c26e7d370e9292fa5f81f06dad0654c66f5b42..f3bed37859a2115ecf58f5981e97c09f39473e83 100644 (file)
  * data to the routine.
  */
 
-struct v4l2_clip32 {
-       struct v4l2_rect        c;
-       compat_caddr_t          next;
-};
-
 struct v4l2_window32 {
        struct v4l2_rect        w;
        __u32                   field;  /* enum v4l2_field */
        __u32                   chromakey;
-       compat_caddr_t          clips; /* actually struct v4l2_clip32 * */
-       __u32                   clipcount;
-       compat_caddr_t          bitmap;
+       compat_caddr_t          clips; /* always NULL */
+       __u32                   clipcount; /* always 0 */
+       compat_caddr_t          bitmap; /* always NULL */
        __u8                    global_alpha;
 };
 
@@ -65,17 +60,12 @@ static int get_v4l2_window32(struct v4l2_window *p64,
                .w              = w32.w,
                .field          = w32.field,
                .chromakey      = w32.chromakey,
-               .clips          = (void __force *)compat_ptr(w32.clips),
-               .clipcount      = w32.clipcount,
-               .bitmap         = compat_ptr(w32.bitmap),
+               .clips          = NULL,
+               .clipcount      = 0,
+               .bitmap         = NULL,
                .global_alpha   = w32.global_alpha,
        };
 
-       if (p64->clipcount > 2048)
-               return -EINVAL;
-       if (!p64->clipcount)
-               p64->clips = NULL;
-
        return 0;
 }
 
@@ -89,16 +79,13 @@ static int put_v4l2_window32(struct v4l2_window *p64,
                .w              = p64->w,
                .field          = p64->field,
                .chromakey      = p64->chromakey,
-               .clips          = (uintptr_t)p64->clips,
-               .clipcount      = p64->clipcount,
-               .bitmap         = ptr_to_compat(p64->bitmap),
+               .clips          = 0,
+               .clipcount      = 0,
+               .bitmap         = 0,
                .global_alpha   = p64->global_alpha,
        };
 
-       /* copy everything except the clips pointer */
-       if (copy_to_user(p32, &w32, offsetof(struct v4l2_window32, clips)) ||
-           copy_to_user(&p32->clipcount, &w32.clipcount,
-                        sizeof(w32) - offsetof(struct v4l2_window32, clipcount)))
+       if (copy_to_user(p32, &w32, sizeof(w32)))
                return -EFAULT;
 
        return 0;
@@ -600,14 +587,11 @@ struct v4l2_framebuffer32 {
 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
                                  struct v4l2_framebuffer32 __user *p32)
 {
-       compat_caddr_t tmp;
-
-       if (get_user(tmp, &p32->base) ||
-           get_user(p64->capability, &p32->capability) ||
+       if (get_user(p64->capability, &p32->capability) ||
            get_user(p64->flags, &p32->flags) ||
            copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
                return -EFAULT;
-       p64->base = (void __force *)compat_ptr(tmp);
+       p64->base = NULL;
 
        return 0;
 }
@@ -1043,29 +1027,6 @@ int v4l2_compat_get_array_args(struct file *file, void *mbuf,
        memset(mbuf, 0, array_size);
 
        switch (cmd) {
-       case VIDIOC_G_FMT32:
-       case VIDIOC_S_FMT32:
-       case VIDIOC_TRY_FMT32: {
-               struct v4l2_format *f64 = arg;
-               struct v4l2_clip *c64 = mbuf;
-               struct v4l2_clip32 __user *c32 = user_ptr;
-               u32 clipcount = f64->fmt.win.clipcount;
-
-               if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
-                    f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
-                   clipcount == 0)
-                       return 0;
-               if (clipcount > 2048)
-                       return -EINVAL;
-               while (clipcount--) {
-                       if (copy_from_user(c64, c32, sizeof(c64->c)))
-                               return -EFAULT;
-                       c64->next = NULL;
-                       c64++;
-                       c32++;
-               }
-               break;
-       }
 #ifdef CONFIG_COMPAT_32BIT_TIME
        case VIDIOC_QUERYBUF32_TIME32:
        case VIDIOC_QBUF32_TIME32:
@@ -1136,28 +1097,6 @@ int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
        int err = 0;
 
        switch (cmd) {
-       case VIDIOC_G_FMT32:
-       case VIDIOC_S_FMT32:
-       case VIDIOC_TRY_FMT32: {
-               struct v4l2_format *f64 = arg;
-               struct v4l2_clip *c64 = mbuf;
-               struct v4l2_clip32 __user *c32 = user_ptr;
-               u32 clipcount = f64->fmt.win.clipcount;
-
-               if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
-                    f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
-                   clipcount == 0)
-                       return 0;
-               if (clipcount > 2048)
-                       return -EINVAL;
-               while (clipcount--) {
-                       if (copy_to_user(c32, c64, sizeof(c64->c)))
-                               return -EFAULT;
-                       c64++;
-                       c32++;
-               }
-               break;
-       }
 #ifdef CONFIG_COMPAT_32BIT_TIME
        case VIDIOC_QUERYBUF32_TIME32:
        case VIDIOC_QBUF32_TIME32:
index 397d553177fa70b0cb880af9724cedbe52ce486b..f8127949268229fd852eaa1ea2e50b874c376e97 100644 (file)
@@ -556,6 +556,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
        bool is_rx = vdev->vfl_dir != VFL_DIR_TX;
        bool is_tx = vdev->vfl_dir != VFL_DIR_RX;
        bool is_io_mc = vdev->device_caps & V4L2_CAP_IO_MC;
+       bool has_streaming = vdev->device_caps & V4L2_CAP_STREAMING;
 
        bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE);
 
@@ -708,8 +709,8 @@ static void determine_valid_ioctls(struct video_device *vdev)
                SET_VALID_IOCTL(ops, VIDIOC_TRY_FMT, vidioc_try_fmt_sdr_out);
        }
 
-       if (is_vid || is_vbi || is_sdr || is_tch || is_meta) {
-               /* ioctls valid for video, vbi, sdr, touch and metadata */
+       if (has_streaming) {
+               /* ioctls valid for streaming I/O */
                SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
                SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
                SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
index 87f163a89c80503a9d28c45cce499302d84a6f8a..a858acea65477d7003f26bec8d2c2713912bb560 100644 (file)
@@ -310,14 +310,10 @@ static void v4l_print_format(const void *arg, bool write_only)
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                win = &p->fmt.win;
-               /* Note: we can't print the clip list here since the clips
-                * pointer is a userspace pointer, not a kernelspace
-                * pointer. */
-               pr_cont(", wxh=%dx%d, x,y=%d,%d, field=%s, chromakey=0x%08x, clipcount=%u, clips=%p, bitmap=%p, global_alpha=0x%02x\n",
+               pr_cont(", wxh=%dx%d, x,y=%d,%d, field=%s, chromakey=0x%08x, global_alpha=0x%02x\n",
                        win->w.width, win->w.height, win->w.left, win->w.top,
                        prt_names(win->field, v4l2_field_names),
-                       win->chromakey, win->clipcount, win->clips,
-                       win->bitmap, win->global_alpha);
+                       win->chromakey, win->global_alpha);
                break;
        case V4L2_BUF_TYPE_VBI_CAPTURE:
        case V4L2_BUF_TYPE_VBI_OUTPUT:
@@ -1302,11 +1298,14 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
        case V4L2_PIX_FMT_RGBX1010102:  descr = "32-bit RGBX 10-10-10-2"; break;
        case V4L2_PIX_FMT_RGBA1010102:  descr = "32-bit RGBA 10-10-10-2"; break;
        case V4L2_PIX_FMT_ARGB2101010:  descr = "32-bit ARGB 2-10-10-10"; break;
+       case V4L2_PIX_FMT_BGR48_12:     descr = "12-bit Depth BGR"; break;
+       case V4L2_PIX_FMT_ABGR64_12:    descr = "12-bit Depth BGRA"; break;
        case V4L2_PIX_FMT_GREY:         descr = "8-bit Greyscale"; break;
        case V4L2_PIX_FMT_Y4:           descr = "4-bit Greyscale"; break;
        case V4L2_PIX_FMT_Y6:           descr = "6-bit Greyscale"; break;
        case V4L2_PIX_FMT_Y10:          descr = "10-bit Greyscale"; break;
        case V4L2_PIX_FMT_Y12:          descr = "12-bit Greyscale"; break;
+       case V4L2_PIX_FMT_Y012:         descr = "12-bit Greyscale (bits 15-4)"; break;
        case V4L2_PIX_FMT_Y14:          descr = "14-bit Greyscale"; break;
        case V4L2_PIX_FMT_Y16:          descr = "16-bit Greyscale"; break;
        case V4L2_PIX_FMT_Y16_BE:       descr = "16-bit Greyscale BE"; break;
@@ -1345,6 +1344,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
        case V4L2_PIX_FMT_YUV420:       descr = "Planar YUV 4:2:0"; break;
        case V4L2_PIX_FMT_HI240:        descr = "8-bit Dithered RGB (BTTV)"; break;
        case V4L2_PIX_FMT_M420:         descr = "YUV 4:2:0 (M420)"; break;
+       case V4L2_PIX_FMT_YUV48_12:     descr = "12-bit YUV 4:4:4 Packed"; break;
        case V4L2_PIX_FMT_NV12:         descr = "Y/UV 4:2:0"; break;
        case V4L2_PIX_FMT_NV21:         descr = "Y/VU 4:2:0"; break;
        case V4L2_PIX_FMT_NV16:         descr = "Y/UV 4:2:2"; break;
@@ -1352,6 +1352,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
        case V4L2_PIX_FMT_NV24:         descr = "Y/UV 4:4:4"; break;
        case V4L2_PIX_FMT_NV42:         descr = "Y/VU 4:4:4"; break;
        case V4L2_PIX_FMT_P010:         descr = "10-bit Y/UV 4:2:0"; break;
+       case V4L2_PIX_FMT_P012:         descr = "12-bit Y/UV 4:2:0"; break;
        case V4L2_PIX_FMT_NV12_4L4:     descr = "Y/UV 4:2:0 (4x4 Linear)"; break;
        case V4L2_PIX_FMT_NV12_16L16:   descr = "Y/UV 4:2:0 (16x16 Linear)"; break;
        case V4L2_PIX_FMT_NV12_32L32:   descr = "Y/UV 4:2:0 (32x32 Linear)"; break;
@@ -1362,6 +1363,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
        case V4L2_PIX_FMT_NV61M:        descr = "Y/VU 4:2:2 (N-C)"; break;
        case V4L2_PIX_FMT_NV12MT:       descr = "Y/UV 4:2:0 (64x32 MB, N-C)"; break;
        case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/UV 4:2:0 (16x16 MB, N-C)"; break;
+       case V4L2_PIX_FMT_P012M:        descr = "12-bit Y/UV 4:2:0 (N-C)"; break;
        case V4L2_PIX_FMT_YUV420M:      descr = "Planar YUV 4:2:0 (N-C)"; break;
        case V4L2_PIX_FMT_YVU420M:      descr = "Planar YVU 4:2:0 (N-C)"; break;
        case V4L2_PIX_FMT_YUV422M:      descr = "Planar YUV 4:2:2 (N-C)"; break;
@@ -1479,6 +1481,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
                case V4L2_PIX_FMT_HEVC_SLICE:   descr = "HEVC Parsed Slice Data"; break;
                case V4L2_PIX_FMT_FWHT:         descr = "FWHT"; break; /* used in vicodec */
                case V4L2_PIX_FMT_FWHT_STATELESS:       descr = "FWHT Stateless"; break; /* used in vicodec */
+               case V4L2_PIX_FMT_SPK:          descr = "Sorenson Spark"; break;
+               case V4L2_PIX_FMT_RV30:         descr = "RealVideo 8"; break;
+               case V4L2_PIX_FMT_RV40:         descr = "RealVideo 9 & 10"; break;
                case V4L2_PIX_FMT_CPIA1:        descr = "GSPCA CPiA YUV"; break;
                case V4L2_PIX_FMT_WNVA:         descr = "WNVA"; break;
                case V4L2_PIX_FMT_SN9C10X:      descr = "GSPCA SN9C10X"; break;
@@ -1618,29 +1623,7 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
        if (ret)
                return ret;
 
-       /*
-        * fmt can't be cleared for these overlay types due to the 'clips'
-        * 'clipcount' and 'bitmap' pointers in struct v4l2_window.
-        * Those are provided by the user. So handle these two overlay types
-        * first, and then just do a simple memset for the other types.
-        */
-       switch (p->type) {
-       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
-               struct v4l2_clip *clips = p->fmt.win.clips;
-               u32 clipcount = p->fmt.win.clipcount;
-               void __user *bitmap = p->fmt.win.bitmap;
-
-               memset(&p->fmt, 0, sizeof(p->fmt));
-               p->fmt.win.clips = clips;
-               p->fmt.win.clipcount = clipcount;
-               p->fmt.win.bitmap = bitmap;
-               break;
-       }
-       default:
-               memset(&p->fmt, 0, sizeof(p->fmt));
-               break;
-       }
+       memset(&p->fmt, 0, sizeof(p->fmt));
 
        switch (p->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -1728,6 +1711,9 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_s_fmt_vid_overlay))
                        break;
                memset_after(p, 0, fmt.win);
+               p->fmt.win.clips = NULL;
+               p->fmt.win.clipcount = 0;
+               p->fmt.win.bitmap = NULL;
                return ops->vidioc_s_fmt_vid_overlay(file, fh, arg);
        case V4L2_BUF_TYPE_VBI_CAPTURE:
                if (unlikely(!ops->vidioc_s_fmt_vbi_cap))
@@ -1759,6 +1745,9 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay))
                        break;
                memset_after(p, 0, fmt.win);
+               p->fmt.win.clips = NULL;
+               p->fmt.win.clipcount = 0;
+               p->fmt.win.bitmap = NULL;
                return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg);
        case V4L2_BUF_TYPE_VBI_OUTPUT:
                if (unlikely(!ops->vidioc_s_fmt_vbi_out))
@@ -1830,6 +1819,9 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_try_fmt_vid_overlay))
                        break;
                memset_after(p, 0, fmt.win);
+               p->fmt.win.clips = NULL;
+               p->fmt.win.clipcount = 0;
+               p->fmt.win.bitmap = NULL;
                return ops->vidioc_try_fmt_vid_overlay(file, fh, arg);
        case V4L2_BUF_TYPE_VBI_CAPTURE:
                if (unlikely(!ops->vidioc_try_fmt_vbi_cap))
@@ -1861,6 +1853,9 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay))
                        break;
                memset_after(p, 0, fmt.win);
+               p->fmt.win.clips = NULL;
+               p->fmt.win.clipcount = 0;
+               p->fmt.win.bitmap = NULL;
                return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg);
        case V4L2_BUF_TYPE_VBI_OUTPUT:
                if (unlikely(!ops->vidioc_try_fmt_vbi_out))
@@ -2074,6 +2069,15 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
        return ops->vidioc_s_hw_freq_seek(file, fh, p);
 }
 
+static int v4l_s_fbuf(const struct v4l2_ioctl_ops *ops,
+                     struct file *file, void *fh, void *arg)
+{
+       struct v4l2_framebuffer *p = arg;
+
+       p->base = NULL;
+       return ops->vidioc_s_fbuf(file, fh, p);
+}
+
 static int v4l_overlay(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
@@ -2793,7 +2797,6 @@ struct v4l2_ioctl_info {
        }
 
 DEFINE_V4L_STUB_FUNC(g_fbuf)
-DEFINE_V4L_STUB_FUNC(s_fbuf)
 DEFINE_V4L_STUB_FUNC(expbuf)
 DEFINE_V4L_STUB_FUNC(g_std)
 DEFINE_V4L_STUB_FUNC(g_audio)
@@ -2827,7 +2830,7 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] = {
        IOCTL_INFO(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE),
        IOCTL_INFO(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)),
        IOCTL_INFO(VIDIOC_G_FBUF, v4l_stub_g_fbuf, v4l_print_framebuffer, 0),
-       IOCTL_INFO(VIDIOC_S_FBUF, v4l_stub_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
+       IOCTL_INFO(VIDIOC_S_FBUF, v4l_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
        IOCTL_INFO(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO),
        IOCTL_INFO(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
        IOCTL_INFO(VIDIOC_EXPBUF, v4l_stub_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)),
@@ -3134,27 +3137,6 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
                }
                break;
        }
-       case VIDIOC_G_FMT:
-       case VIDIOC_S_FMT:
-       case VIDIOC_TRY_FMT: {
-               struct v4l2_format *fmt = parg;
-
-               if (fmt->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
-                   fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY)
-                       break;
-               if (fmt->fmt.win.clipcount > 2048)
-                       return -EINVAL;
-               if (!fmt->fmt.win.clipcount)
-                       break;
-
-               *user_ptr = (void __user *)fmt->fmt.win.clips;
-               *kernel_ptr = (void **)&fmt->fmt.win.clips;
-               *array_size = sizeof(struct v4l2_clip)
-                               * fmt->fmt.win.clipcount;
-
-               ret = 1;
-               break;
-       }
 
        case VIDIOC_SUBDEV_G_ROUTING:
        case VIDIOC_SUBDEV_S_ROUTING: {
index b01474717dca923ab65aa412dc0e148bdb12d1a6..bf0c18100664f56366a188ee22a1f354184d3b39 100644 (file)
@@ -313,14 +313,11 @@ int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
                                    struct media_pad *sink, u32 flags)
 {
        struct fwnode_handle *endpoint;
-       struct v4l2_subdev *sink_sd;
 
        if (!(sink->flags & MEDIA_PAD_FL_SINK) ||
            !is_media_entity_v4l2_subdev(sink->entity))
                return -EINVAL;
 
-       sink_sd = media_entity_to_v4l2_subdev(sink->entity);
-
        fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) {
                struct fwnode_handle *remote_ep;
                int src_idx, sink_idx, ret;
@@ -340,7 +337,7 @@ int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
                 * ask the sink to verify it owns the remote endpoint,
                 * and translate to a sink pad.
                 */
-               sink_idx = media_entity_get_fwnode_pad(&sink_sd->entity,
+               sink_idx = media_entity_get_fwnode_pad(sink->entity,
                                                       remote_ep,
                                                       MEDIA_PAD_FL_SINK);
                fwnode_handle_put(remote_ep);
@@ -362,17 +359,17 @@ int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
                if (media_entity_find_link(src, sink))
                        continue;
 
-               dev_dbg(sink_sd->dev, "creating link %s:%d -> %s:%d\n",
+               dev_dbg(src_sd->dev, "creating link %s:%d -> %s:%d\n",
                        src_sd->entity.name, src_idx,
-                       sink_sd->entity.name, sink_idx);
+                       sink->entity->name, sink_idx);
 
                ret = media_create_pad_link(&src_sd->entity, src_idx,
-                                           &sink_sd->entity, sink_idx, flags);
+                                           sink->entity, sink_idx, flags);
                if (ret) {
-                       dev_err(sink_sd->dev,
+                       dev_err(src_sd->dev,
                                "link %s:%d -> %s:%d failed with %d\n",
                                src_sd->entity.name, src_idx,
-                               sink_sd->entity.name, sink_idx, ret);
+                               sink->entity->name, sink_idx, ret);
 
                        fwnode_handle_put(endpoint);
                        return ret;
index b10045c02f4343250f98ec668fd9d6cb4f9cd087..2ec179cd126436cbda57e6ce60b65fd96d14a822 100644 (file)
@@ -510,8 +510,11 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
        struct video_device *vdev = video_devdata(file);
        struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
        struct v4l2_fh *vfh = file->private_data;
+       struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
        bool ro_subdev = test_bit(V4L2_FL_SUBDEV_RO_DEVNODE, &vdev->flags);
        bool streams_subdev = sd->flags & V4L2_SUBDEV_FL_STREAMS;
+       bool client_supports_streams = subdev_fh->client_caps &
+                                      V4L2_SUBDEV_CLIENT_CAP_STREAMS;
        int rval;
 
        switch (cmd) {
@@ -636,6 +639,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
        case VIDIOC_SUBDEV_G_FMT: {
                struct v4l2_subdev_format *format = arg;
 
+               if (!client_supports_streams)
+                       format->stream = 0;
+
                memset(format->reserved, 0, sizeof(format->reserved));
                memset(format->format.reserved, 0, sizeof(format->format.reserved));
                return v4l2_subdev_call(sd, pad, get_fmt, state, format);
@@ -647,6 +653,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
                if (format->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev)
                        return -EPERM;
 
+               if (!client_supports_streams)
+                       format->stream = 0;
+
                memset(format->reserved, 0, sizeof(format->reserved));
                memset(format->format.reserved, 0, sizeof(format->format.reserved));
                return v4l2_subdev_call(sd, pad, set_fmt, state, format);
@@ -656,6 +665,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
                struct v4l2_subdev_crop *crop = arg;
                struct v4l2_subdev_selection sel;
 
+               if (!client_supports_streams)
+                       crop->stream = 0;
+
                memset(crop->reserved, 0, sizeof(crop->reserved));
                memset(&sel, 0, sizeof(sel));
                sel.which = crop->which;
@@ -677,6 +689,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
                if (crop->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev)
                        return -EPERM;
 
+               if (!client_supports_streams)
+                       crop->stream = 0;
+
                memset(crop->reserved, 0, sizeof(crop->reserved));
                memset(&sel, 0, sizeof(sel));
                sel.which = crop->which;
@@ -695,6 +710,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
        case VIDIOC_SUBDEV_ENUM_MBUS_CODE: {
                struct v4l2_subdev_mbus_code_enum *code = arg;
 
+               if (!client_supports_streams)
+                       code->stream = 0;
+
                memset(code->reserved, 0, sizeof(code->reserved));
                return v4l2_subdev_call(sd, pad, enum_mbus_code, state,
                                        code);
@@ -703,6 +721,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
        case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: {
                struct v4l2_subdev_frame_size_enum *fse = arg;
 
+               if (!client_supports_streams)
+                       fse->stream = 0;
+
                memset(fse->reserved, 0, sizeof(fse->reserved));
                return v4l2_subdev_call(sd, pad, enum_frame_size, state,
                                        fse);
@@ -711,6 +732,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
        case VIDIOC_SUBDEV_G_FRAME_INTERVAL: {
                struct v4l2_subdev_frame_interval *fi = arg;
 
+               if (!client_supports_streams)
+                       fi->stream = 0;
+
                memset(fi->reserved, 0, sizeof(fi->reserved));
                return v4l2_subdev_call(sd, video, g_frame_interval, arg);
        }
@@ -721,6 +745,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
                if (ro_subdev)
                        return -EPERM;
 
+               if (!client_supports_streams)
+                       fi->stream = 0;
+
                memset(fi->reserved, 0, sizeof(fi->reserved));
                return v4l2_subdev_call(sd, video, s_frame_interval, arg);
        }
@@ -728,6 +755,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
        case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: {
                struct v4l2_subdev_frame_interval_enum *fie = arg;
 
+               if (!client_supports_streams)
+                       fie->stream = 0;
+
                memset(fie->reserved, 0, sizeof(fie->reserved));
                return v4l2_subdev_call(sd, pad, enum_frame_interval, state,
                                        fie);
@@ -736,6 +766,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
        case VIDIOC_SUBDEV_G_SELECTION: {
                struct v4l2_subdev_selection *sel = arg;
 
+               if (!client_supports_streams)
+                       sel->stream = 0;
+
                memset(sel->reserved, 0, sizeof(sel->reserved));
                return v4l2_subdev_call(
                        sd, pad, get_selection, state, sel);
@@ -747,6 +780,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
                if (sel->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev)
                        return -EPERM;
 
+               if (!client_supports_streams)
+                       sel->stream = 0;
+
                memset(sel->reserved, 0, sizeof(sel->reserved));
                return v4l2_subdev_call(
                        sd, pad, set_selection, state, sel);
@@ -888,6 +924,33 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
                                        routing->which, &krouting);
        }
 
+       case VIDIOC_SUBDEV_G_CLIENT_CAP: {
+               struct v4l2_subdev_client_capability *client_cap = arg;
+
+               client_cap->capabilities = subdev_fh->client_caps;
+
+               return 0;
+       }
+
+       case VIDIOC_SUBDEV_S_CLIENT_CAP: {
+               struct v4l2_subdev_client_capability *client_cap = arg;
+
+               /*
+                * Clear V4L2_SUBDEV_CLIENT_CAP_STREAMS if streams API is not
+                * enabled. Remove this when streams API is no longer
+                * experimental.
+                */
+               if (!v4l2_subdev_enable_streams_api)
+                       client_cap->capabilities &= ~V4L2_SUBDEV_CLIENT_CAP_STREAMS;
+
+               /* Filter out unsupported capabilities */
+               client_cap->capabilities &= V4L2_SUBDEV_CLIENT_CAP_STREAMS;
+
+               subdev_fh->client_caps = client_cap->capabilities;
+
+               return 0;
+       }
+
        default:
                return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
        }
@@ -1069,32 +1132,45 @@ EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default);
 
 static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
-                                    struct v4l2_subdev_format *fmt)
+                                    struct v4l2_subdev_format *fmt,
+                                    bool states_locked)
 {
-       if (is_media_entity_v4l2_subdev(pad->entity)) {
-               struct v4l2_subdev *sd =
-                       media_entity_to_v4l2_subdev(pad->entity);
+       struct v4l2_subdev_state *state;
+       struct v4l2_subdev *sd;
+       int ret;
 
-               fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
-               fmt->pad = pad->index;
-               fmt->stream = stream;
+       if (!is_media_entity_v4l2_subdev(pad->entity)) {
+               WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L,
+                    "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
+                    pad->entity->function, pad->entity->name);
 
-               return v4l2_subdev_call(sd, pad, get_fmt,
-                                       v4l2_subdev_get_locked_active_state(sd),
-                                       fmt);
+               return -EINVAL;
        }
 
-       WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L,
-            "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
-            pad->entity->function, pad->entity->name);
+       sd = media_entity_to_v4l2_subdev(pad->entity);
 
-       return -EINVAL;
+       fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       fmt->pad = pad->index;
+       fmt->stream = stream;
+
+       if (states_locked)
+               state = v4l2_subdev_get_locked_active_state(sd);
+       else
+               state = v4l2_subdev_lock_and_get_active_state(sd);
+
+       ret = v4l2_subdev_call(sd, pad, get_fmt, state, fmt);
+
+       if (!states_locked && state)
+               v4l2_subdev_unlock_state(state);
+
+       return ret;
 }
 
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 
 static void __v4l2_link_validate_get_streams(struct media_pad *pad,
-                                            u64 *streams_mask)
+                                            u64 *streams_mask,
+                                            bool states_locked)
 {
        struct v4l2_subdev_route *route;
        struct v4l2_subdev_state *state;
@@ -1104,7 +1180,11 @@ static void __v4l2_link_validate_get_streams(struct media_pad *pad,
 
        *streams_mask = 0;
 
-       state = v4l2_subdev_get_locked_active_state(subdev);
+       if (states_locked)
+               state = v4l2_subdev_get_locked_active_state(subdev);
+       else
+               state = v4l2_subdev_lock_and_get_active_state(subdev);
+
        if (WARN_ON(!state))
                return;
 
@@ -1125,12 +1205,16 @@ static void __v4l2_link_validate_get_streams(struct media_pad *pad,
 
                *streams_mask |= BIT_ULL(route_stream);
        }
+
+       if (!states_locked)
+               v4l2_subdev_unlock_state(state);
 }
 
 #endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
 
 static void v4l2_link_validate_get_streams(struct media_pad *pad,
-                                          u64 *streams_mask)
+                                          u64 *streams_mask,
+                                          bool states_locked)
 {
        struct v4l2_subdev *subdev = media_entity_to_v4l2_subdev(pad->entity);
 
@@ -1141,14 +1225,14 @@ static void v4l2_link_validate_get_streams(struct media_pad *pad,
        }
 
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
-       __v4l2_link_validate_get_streams(pad, streams_mask);
+       __v4l2_link_validate_get_streams(pad, streams_mask, states_locked);
 #else
        /* This shouldn't happen */
        *streams_mask = 0;
 #endif
 }
 
-static int v4l2_subdev_link_validate_locked(struct media_link *link)
+static int v4l2_subdev_link_validate_locked(struct media_link *link, bool states_locked)
 {
        struct v4l2_subdev *sink_subdev =
                media_entity_to_v4l2_subdev(link->sink->entity);
@@ -1163,8 +1247,8 @@ static int v4l2_subdev_link_validate_locked(struct media_link *link)
                link->source->entity->name, link->source->index,
                link->sink->entity->name, link->sink->index);
 
-       v4l2_link_validate_get_streams(link->source, &source_streams_mask);
-       v4l2_link_validate_get_streams(link->sink, &sink_streams_mask);
+       v4l2_link_validate_get_streams(link->source, &source_streams_mask, states_locked);
+       v4l2_link_validate_get_streams(link->sink, &sink_streams_mask, states_locked);
 
        /*
         * It is ok to have more source streams than sink streams as extra
@@ -1192,7 +1276,7 @@ static int v4l2_subdev_link_validate_locked(struct media_link *link)
                        link->sink->entity->name, link->sink->index, stream);
 
                ret = v4l2_subdev_link_validate_get_format(link->source, stream,
-                                                          &source_fmt);
+                                                          &source_fmt, states_locked);
                if (ret < 0) {
                        dev_dbg(dev,
                                "Failed to get format for \"%s\":%u:%u (but that's ok)\n",
@@ -1202,7 +1286,7 @@ static int v4l2_subdev_link_validate_locked(struct media_link *link)
                }
 
                ret = v4l2_subdev_link_validate_get_format(link->sink, stream,
-                                                          &sink_fmt);
+                                                          &sink_fmt, states_locked);
                if (ret < 0) {
                        dev_dbg(dev,
                                "Failed to get format for \"%s\":%u:%u (but that's ok)\n",
@@ -1234,27 +1318,38 @@ int v4l2_subdev_link_validate(struct media_link *link)
 {
        struct v4l2_subdev *source_sd, *sink_sd;
        struct v4l2_subdev_state *source_state, *sink_state;
+       bool states_locked;
        int ret;
 
+       if (!is_media_entity_v4l2_subdev(link->sink->entity) ||
+           !is_media_entity_v4l2_subdev(link->source->entity)) {
+               pr_warn_once("%s of link '%s':%u->'%s':%u is not a V4L2 sub-device, driver bug!\n",
+                            !is_media_entity_v4l2_subdev(link->sink->entity) ?
+                            "sink" : "source",
+                            link->source->entity->name, link->source->index,
+                            link->sink->entity->name, link->sink->index);
+               return 0;
+       }
+
        sink_sd = media_entity_to_v4l2_subdev(link->sink->entity);
        source_sd = media_entity_to_v4l2_subdev(link->source->entity);
 
        sink_state = v4l2_subdev_get_unlocked_active_state(sink_sd);
        source_state = v4l2_subdev_get_unlocked_active_state(source_sd);
 
-       if (sink_state)
-               v4l2_subdev_lock_state(sink_state);
+       states_locked = sink_state && source_state;
 
-       if (source_state)
+       if (states_locked) {
+               v4l2_subdev_lock_state(sink_state);
                v4l2_subdev_lock_state(source_state);
+       }
 
-       ret = v4l2_subdev_link_validate_locked(link);
+       ret = v4l2_subdev_link_validate_locked(link, states_locked);
 
-       if (sink_state)
+       if (states_locked) {
                v4l2_subdev_unlock_state(sink_state);
-
-       if (source_state)
                v4l2_subdev_unlock_state(source_state);
+       }
 
        return ret;
 }
@@ -1676,7 +1771,8 @@ int v4l2_subdev_routing_validate(struct v4l2_subdev *sd,
        unsigned int i, j;
        int ret = -EINVAL;
 
-       if (disallow & V4L2_SUBDEV_ROUTING_NO_STREAM_MIX) {
+       if (disallow & (V4L2_SUBDEV_ROUTING_NO_STREAM_MIX |
+                       V4L2_SUBDEV_ROUTING_NO_MULTIPLEXING)) {
                remote_pads = kcalloc(sd->entity.num_pads, sizeof(*remote_pads),
                                      GFP_KERNEL);
                if (!remote_pads)
@@ -1705,10 +1801,10 @@ int v4l2_subdev_routing_validate(struct v4l2_subdev *sd,
                }
 
                /*
-                * V4L2_SUBDEV_ROUTING_NO_STREAM_MIX: Streams on the same pad
-                * may not be routed to streams on different pads.
+                * V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX: all streams from a
+                * sink pad must be routed to a single source pad.
                 */
-               if (disallow & V4L2_SUBDEV_ROUTING_NO_STREAM_MIX) {
+               if (disallow & V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX) {
                        if (remote_pads[route->sink_pad] != U32_MAX &&
                            remote_pads[route->sink_pad] != route->source_pad) {
                                dev_dbg(sd->dev,
@@ -1716,7 +1812,13 @@ int v4l2_subdev_routing_validate(struct v4l2_subdev *sd,
                                        i, "sink");
                                goto out;
                        }
+               }
 
+               /*
+                * V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX: all streams on a
+                * source pad must originate from a single sink pad.
+                */
+               if (disallow & V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX) {
                        if (remote_pads[route->source_pad] != U32_MAX &&
                            remote_pads[route->source_pad] != route->sink_pad) {
                                dev_dbg(sd->dev,
@@ -1724,7 +1826,37 @@ int v4l2_subdev_routing_validate(struct v4l2_subdev *sd,
                                        i, "source");
                                goto out;
                        }
+               }
+
+               /*
+                * V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING: Pads on the sink
+                * side can not do stream multiplexing, i.e. there can be only
+                * a single stream in a sink pad.
+                */
+               if (disallow & V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING) {
+                       if (remote_pads[route->sink_pad] != U32_MAX) {
+                               dev_dbg(sd->dev,
+                                       "route %u attempts to multiplex on %s pad %u\n",
+                                       i, "sink", route->sink_pad);
+                               goto out;
+                       }
+               }
+
+               /*
+                * V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING: Pads on the
+                * source side can not do stream multiplexing, i.e. there can
+                * be only a single stream in a source pad.
+                */
+               if (disallow & V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING) {
+                       if (remote_pads[route->source_pad] != U32_MAX) {
+                               dev_dbg(sd->dev,
+                                       "route %u attempts to multiplex on %s pad %u\n",
+                                       i, "source", route->source_pad);
+                               goto out;
+                       }
+               }
 
+               if (remote_pads) {
                        remote_pads[route->sink_pad] = route->source_pad;
                        remote_pads[route->source_pad] = route->sink_pad;
                }
index 0d90683ed227d82a6f204ece872b7a0dbe837684..273155308fe36fb0fca8158b21fc0cd06a64a9c7 100644 (file)
@@ -3,6 +3,7 @@
  * Support for GalaxyCore GC0310 VGA camera sensor.
  *
  * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
+ * Copyright (c) 2023 Hans de Goede <hdegoede@redhat.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
 #include <linux/i2c.h>
 #include <linux/moduleparam.h>
+#include <linux/pm_runtime.h>
 #include <media/v4l2-device.h>
 #include <linux/io.h>
 #include "../include/linux/atomisp_gmin_platform.h"
 
 #include "gc0310.h"
 
-/* i2c read/write stuff */
-static int gc0310_read_reg(struct i2c_client *client,
-                          u16 data_length, u8 reg, u8 *val)
-{
-       int err;
-       struct i2c_msg msg[2];
-       unsigned char data[1];
-
-       if (!client->adapter) {
-               dev_err(&client->dev, "%s error, no client->adapter\n",
-                       __func__);
-               return -ENODEV;
-       }
-
-       if (data_length != GC0310_8BIT) {
-               dev_err(&client->dev, "%s error, invalid data length\n",
-                       __func__);
-               return -EINVAL;
-       }
-
-       memset(msg, 0, sizeof(msg));
-
-       msg[0].addr = client->addr;
-       msg[0].flags = 0;
-       msg[0].len = I2C_MSG_LENGTH;
-       msg[0].buf = data;
-
-       /* high byte goes out first */
-       data[0] = (u8)(reg & 0xff);
-
-       msg[1].addr = client->addr;
-       msg[1].len = data_length;
-       msg[1].flags = I2C_M_RD;
-       msg[1].buf = data;
-
-       err = i2c_transfer(client->adapter, msg, 2);
-       if (err != 2) {
-               if (err >= 0)
-                       err = -EIO;
-               dev_err(&client->dev,
-                       "read from offset 0x%x error %d", reg, err);
-               return err;
-       }
-
-       *val = 0;
-       /* high byte comes first */
-       if (data_length == GC0310_8BIT)
-               *val = (u8)data[0];
-
-       return 0;
-}
-
-static int gc0310_i2c_write(struct i2c_client *client, u16 len, u8 *data)
-{
-       struct i2c_msg msg;
-       const int num_msg = 1;
-       int ret;
-
-       msg.addr = client->addr;
-       msg.flags = 0;
-       msg.len = len;
-       msg.buf = data;
-       ret = i2c_transfer(client->adapter, &msg, 1);
-
-       return ret == num_msg ? 0 : -EIO;
-}
-
-static int gc0310_write_reg(struct i2c_client *client, u16 data_length,
-                           u8 reg, u8 val)
-{
-       int ret;
-       unsigned char data[2] = {0};
-       u8 *wreg = (u8 *)data;
-       const u16 len = data_length + sizeof(u8); /* 8-bit address + data */
-
-       if (data_length != GC0310_8BIT) {
-               dev_err(&client->dev,
-                       "%s error, invalid data_length\n", __func__);
-               return -EINVAL;
-       }
-
-       /* high byte goes out first */
-       *wreg = (u8)(reg & 0xff);
-
-       if (data_length == GC0310_8BIT)
-               data[1] = (u8)(val);
-
-       ret = gc0310_i2c_write(client, len, data);
-       if (ret)
-               dev_err(&client->dev,
-                       "write error: wrote 0x%x to offset 0x%x error %d",
-                       val, reg, ret);
-
-       return ret;
-}
-
 /*
  * gc0310_write_reg_array - Initializes a list of GC0310 registers
  * @client: i2c driver client structure
  * @reglist: list of registers to be written
- *
- * This function initializes a list of registers. When consecutive addresses
- * are found in a row on the list, this function creates a buffer and sends
- * consecutive data in a single i2c_transfer().
- *
- * __gc0310_flush_reg_array, __gc0310_buf_reg_array() and
- * __gc0310_write_reg_is_consecutive() are internal functions to
- * gc0310_write_reg_array_fast() and should be not used anywhere else.
- *
+ * @count: number of register, value pairs in the list
  */
-
-static int __gc0310_flush_reg_array(struct i2c_client *client,
-                                   struct gc0310_write_ctrl *ctrl)
-{
-       u16 size;
-
-       if (ctrl->index == 0)
-               return 0;
-
-       size = sizeof(u8) + ctrl->index; /* 8-bit address + data */
-       ctrl->buffer.addr = (u8)(ctrl->buffer.addr);
-       ctrl->index = 0;
-
-       return gc0310_i2c_write(client, size, (u8 *)&ctrl->buffer);
-}
-
-static int __gc0310_buf_reg_array(struct i2c_client *client,
-                                 struct gc0310_write_ctrl *ctrl,
-                                 const struct gc0310_reg *next)
+static int gc0310_write_reg_array(struct i2c_client *client,
+                                 const struct gc0310_reg *reglist, int count)
 {
-       int size;
+       int i, err;
 
-       switch (next->type) {
-       case GC0310_8BIT:
-               size = 1;
-               ctrl->buffer.data[ctrl->index] = (u8)next->val;
-               break;
-       default:
-               return -EINVAL;
+       for (i = 0; i < count; i++) {
+               err = i2c_smbus_write_byte_data(client, reglist[i].reg, reglist[i].val);
+               if (err) {
+                       dev_err(&client->dev, "write error: wrote 0x%x to offset 0x%x error %d",
+                               reglist[i].val, reglist[i].reg, err);
+                       return err;
+               }
        }
 
-       /* When first item is added, we need to store its starting address */
-       if (ctrl->index == 0)
-               ctrl->buffer.addr = next->reg;
-
-       ctrl->index += size;
-
-       /*
-        * Buffer cannot guarantee free space for u32? Better flush it to avoid
-        * possible lack of memory for next item.
-        */
-       if (ctrl->index + sizeof(u8) >= GC0310_MAX_WRITE_BUF_SIZE)
-               return __gc0310_flush_reg_array(client, ctrl);
-
        return 0;
 }
 
-static int __gc0310_write_reg_is_consecutive(struct i2c_client *client,
-                                            struct gc0310_write_ctrl *ctrl,
-                                            const struct gc0310_reg *next)
+static int gc0310_exposure_set(struct gc0310_device *dev, u32 exp)
 {
-       if (ctrl->index == 0)
-               return 1;
-
-       return ctrl->buffer.addr + ctrl->index == next->reg;
-}
-
-static int gc0310_write_reg_array(struct i2c_client *client,
-                                 const struct gc0310_reg *reglist)
-{
-       const struct gc0310_reg *next = reglist;
-       struct gc0310_write_ctrl ctrl;
-       int err;
-
-       ctrl.index = 0;
-       for (; next->type != GC0310_TOK_TERM; next++) {
-               switch (next->type & GC0310_TOK_MASK) {
-               case GC0310_TOK_DELAY:
-                       err = __gc0310_flush_reg_array(client, &ctrl);
-                       if (err)
-                               return err;
-                       msleep(next->val);
-                       break;
-               default:
-                       /*
-                        * If next address is not consecutive, data needs to be
-                        * flushed before proceed.
-                        */
-                       if (!__gc0310_write_reg_is_consecutive(client, &ctrl,
-                                                              next)) {
-                               err = __gc0310_flush_reg_array(client, &ctrl);
-                               if (err)
-                                       return err;
-                       }
-                       err = __gc0310_buf_reg_array(client, &ctrl, next);
-                       if (err) {
-                               dev_err(&client->dev, "%s: write error, aborted\n",
-                                       __func__);
-                               return err;
-                       }
-                       break;
-               }
-       }
+       struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
 
-       return __gc0310_flush_reg_array(client, &ctrl);
+       return i2c_smbus_write_word_swapped(client, GC0310_AEC_PK_EXPO_H, exp);
 }
 
-static int gc0310_set_gain(struct v4l2_subdev *sd, int gain)
-
+static int gc0310_gain_set(struct gc0310_device *dev, u32 gain)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret;
+       struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
        u8 again, dgain;
+       int ret;
 
-       if (gain < 0x20)
-               gain = 0x20;
-       if (gain > 0x80)
-               gain = 0x80;
+       /* Taken from original driver, this never sets dgain lower then 32? */
 
-       if (gain >= 0x20 && gain < 0x40) {
+       /* Change 0 - 95 to 32 - 127 */
+       gain += 32;
+
+       if (gain < 64) {
                again = 0x0; /* sqrt(2) */
                dgain = gain;
        } else {
@@ -261,507 +87,109 @@ static int gc0310_set_gain(struct v4l2_subdev *sd, int gain)
                dgain = gain / 2;
        }
 
-       dev_dbg(&client->dev, "gain=0x%x again=0x%x dgain=0x%x\n", gain, again, dgain);
-
-       /* set analog gain */
-       ret = gc0310_write_reg(client, GC0310_8BIT,
-                              GC0310_AGC_ADJ, again);
-       if (ret)
-               return ret;
-
-       /* set digital gain */
-       ret = gc0310_write_reg(client, GC0310_8BIT,
-                              GC0310_DGC_ADJ, dgain);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static int __gc0310_set_exposure(struct v4l2_subdev *sd, int coarse_itg,
-                                int gain, int digitgain)
-
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret;
-
-       dev_dbg(&client->dev, "coarse_itg=%d gain=%d digitgain=%d\n", coarse_itg, gain, digitgain);
-
-       /* set exposure */
-       ret = gc0310_write_reg(client, GC0310_8BIT,
-                              GC0310_AEC_PK_EXPO_L,
-                              coarse_itg & 0xff);
+       ret = i2c_smbus_write_byte_data(client, GC0310_AGC_ADJ, again);
        if (ret)
                return ret;
 
-       ret = gc0310_write_reg(client, GC0310_8BIT,
-                              GC0310_AEC_PK_EXPO_H,
-                              (coarse_itg >> 8) & 0x0f);
-       if (ret)
-               return ret;
-
-       ret = gc0310_set_gain(sd, gain);
-       if (ret)
-               return ret;
-
-       return ret;
-}
-
-static int gc0310_set_exposure(struct v4l2_subdev *sd, int exposure,
-                              int gain, int digitgain)
-{
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-       int ret;
-
-       mutex_lock(&dev->input_lock);
-       ret = __gc0310_set_exposure(sd, exposure, gain, digitgain);
-       mutex_unlock(&dev->input_lock);
-
-       return ret;
-}
-
-static long gc0310_s_exposure(struct v4l2_subdev *sd,
-                             struct atomisp_exposure *exposure)
-{
-       int exp = exposure->integration_time[0];
-       int gain = exposure->gain[0];
-       int digitgain = exposure->gain[1];
-
-       /* we should not accept the invalid value below. */
-       if (gain == 0) {
-               struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-               v4l2_err(client, "%s: invalid value\n", __func__);
-               return -EINVAL;
-       }
-
-       return gc0310_set_exposure(sd, exp, gain, digitgain);
-}
-
-/* TO DO */
-static int gc0310_v_flip(struct v4l2_subdev *sd, s32 value)
-{
-       return 0;
-}
-
-/* TO DO */
-static int gc0310_h_flip(struct v4l2_subdev *sd, s32 value)
-{
-       return 0;
-}
-
-static long gc0310_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
-{
-       switch (cmd) {
-       case ATOMISP_IOC_S_EXPOSURE:
-               return gc0310_s_exposure(sd, arg);
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/* This returns the exposure time being used. This should only be used
- * for filling in EXIF data, not for actual image processing.
- */
-static int gc0310_q_exposure(struct v4l2_subdev *sd, s32 *value)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       u8 reg_v;
-       int ret;
-
-       /* get exposure */
-       ret = gc0310_read_reg(client, GC0310_8BIT,
-                             GC0310_AEC_PK_EXPO_L,
-                             &reg_v);
-       if (ret)
-               goto err;
-
-       *value = reg_v;
-       ret = gc0310_read_reg(client, GC0310_8BIT,
-                             GC0310_AEC_PK_EXPO_H,
-                             &reg_v);
-       if (ret)
-               goto err;
-
-       *value = *value + (reg_v << 8);
-err:
-       return ret;
+       return i2c_smbus_write_byte_data(client, GC0310_DGC_ADJ, dgain);
 }
 
 static int gc0310_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct gc0310_device *dev =
-           container_of(ctrl->handler, struct gc0310_device, ctrl_handler);
-       struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
-       int ret = 0;
+               container_of(ctrl->handler, struct gc0310_device, ctrls.handler);
+       int ret;
+
+       /* Only apply changes to the controls if the device is powered up */
+       if (!pm_runtime_get_if_in_use(dev->sd.dev))
+               return 0;
 
        switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               dev_dbg(&client->dev, "%s: CID_VFLIP:%d.\n",
-                       __func__, ctrl->val);
-               ret = gc0310_v_flip(&dev->sd, ctrl->val);
+       case V4L2_CID_EXPOSURE:
+               ret = gc0310_exposure_set(dev, ctrl->val);
                break;
-       case V4L2_CID_HFLIP:
-               dev_dbg(&client->dev, "%s: CID_HFLIP:%d.\n",
-                       __func__, ctrl->val);
-               ret = gc0310_h_flip(&dev->sd, ctrl->val);
+       case V4L2_CID_GAIN:
+               ret = gc0310_gain_set(dev, ctrl->val);
                break;
        default:
                ret = -EINVAL;
-       }
-       return ret;
-}
-
-static int gc0310_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gc0310_device *dev =
-           container_of(ctrl->handler, struct gc0310_device, ctrl_handler);
-       int ret = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE_ABSOLUTE:
-               ret = gc0310_q_exposure(&dev->sd, &ctrl->val);
                break;
-       default:
-               ret = -EINVAL;
        }
 
+       pm_runtime_put(dev->sd.dev);
        return ret;
 }
 
 static const struct v4l2_ctrl_ops ctrl_ops = {
        .s_ctrl = gc0310_s_ctrl,
-       .g_volatile_ctrl = gc0310_g_volatile_ctrl
 };
 
-static const struct v4l2_ctrl_config gc0310_controls[] = {
-       {
-               .ops = &ctrl_ops,
-               .id = V4L2_CID_EXPOSURE_ABSOLUTE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "exposure",
-               .min = 0x0,
-               .max = 0xffff,
-               .step = 0x01,
-               .def = 0x00,
-               .flags = 0,
-       },
-       {
-               .ops = &ctrl_ops,
-               .id = V4L2_CID_VFLIP,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Flip",
-               .min = 0,
-               .max = 1,
-               .step = 1,
-               .def = 0,
-       },
-       {
-               .ops = &ctrl_ops,
-               .id = V4L2_CID_HFLIP,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Mirror",
-               .min = 0,
-               .max = 1,
-               .step = 1,
-               .def = 0,
-       },
-};
-
-static int gc0310_init(struct v4l2_subdev *sd)
-{
-       int ret;
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-
-       mutex_lock(&dev->input_lock);
-
-       /* set initial registers */
-       ret  = gc0310_write_reg_array(client, gc0310_reset_register);
-
-       /* restore settings */
-       gc0310_res = gc0310_res_preview;
-       N_RES = N_RES_PREVIEW;
-
-       mutex_unlock(&dev->input_lock);
-
-       return ret;
-}
-
-static int power_ctrl(struct v4l2_subdev *sd, bool flag)
-{
-       int ret = 0;
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-
-       if (!dev || !dev->platform_data)
-               return -ENODEV;
-
-       if (flag) {
-               /* The upstream module driver (written to Crystal
-                * Cove) had this logic to pulse the rails low first.
-                * This appears to break things on the MRD7 with the
-                * X-Powers PMIC...
-                *
-                *     ret = dev->platform_data->v1p8_ctrl(sd, 0);
-                *     ret |= dev->platform_data->v2p8_ctrl(sd, 0);
-                *     mdelay(50);
-                */
-               ret |= dev->platform_data->v1p8_ctrl(sd, 1);
-               ret |= dev->platform_data->v2p8_ctrl(sd, 1);
-               usleep_range(10000, 15000);
-       }
-
-       if (!flag || ret) {
-               ret |= dev->platform_data->v1p8_ctrl(sd, 0);
-               ret |= dev->platform_data->v2p8_ctrl(sd, 0);
-       }
-       return ret;
-}
-
-static int gpio_ctrl(struct v4l2_subdev *sd, bool flag)
-{
-       int ret;
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-
-       if (!dev || !dev->platform_data)
-               return -ENODEV;
-
-       /* GPIO0 == "reset" (active low), GPIO1 == "power down" */
-       if (flag) {
-               /* Pulse reset, then release power down */
-               ret = dev->platform_data->gpio0_ctrl(sd, 0);
-               usleep_range(5000, 10000);
-               ret |= dev->platform_data->gpio0_ctrl(sd, 1);
-               usleep_range(10000, 15000);
-               ret |= dev->platform_data->gpio1_ctrl(sd, 0);
-               usleep_range(10000, 15000);
-       } else {
-               ret = dev->platform_data->gpio1_ctrl(sd, 1);
-               ret |= dev->platform_data->gpio0_ctrl(sd, 0);
-       }
-       return ret;
-}
-
-static int power_up(struct v4l2_subdev *sd)
-{
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret;
-
-       if (!dev->platform_data) {
-               dev_err(&client->dev,
-                       "no camera_sensor_platform_data");
-               return -ENODEV;
-       }
-
-       if (dev->power_on)
-               return 0; /* Already on */
-
-       /* power control */
-       ret = power_ctrl(sd, 1);
-       if (ret)
-               goto fail_power;
-
-       /* flis clock control */
-       ret = dev->platform_data->flisclk_ctrl(sd, 1);
-       if (ret)
-               goto fail_clk;
-
-       /* gpio ctrl */
-       ret = gpio_ctrl(sd, 1);
-       if (ret) {
-               ret = gpio_ctrl(sd, 1);
-               if (ret)
-                       goto fail_gpio;
-       }
-
-       msleep(100);
-
-       dev->power_on = true;
-       return 0;
-
-fail_gpio:
-       dev->platform_data->flisclk_ctrl(sd, 0);
-fail_clk:
-       power_ctrl(sd, 0);
-fail_power:
-       dev_err(&client->dev, "sensor power-up failed\n");
-
-       return ret;
-}
-
-static int power_down(struct v4l2_subdev *sd)
-{
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret = 0;
-
-       if (!dev->platform_data) {
-               dev_err(&client->dev,
-                       "no camera_sensor_platform_data");
-               return -ENODEV;
-       }
-
-       if (!dev->power_on)
-               return 0; /* Already off */
-
-       /* gpio ctrl */
-       ret = gpio_ctrl(sd, 0);
-       if (ret) {
-               ret = gpio_ctrl(sd, 0);
-               if (ret)
-                       dev_err(&client->dev, "gpio failed 2\n");
-       }
-
-       ret = dev->platform_data->flisclk_ctrl(sd, 0);
-       if (ret)
-               dev_err(&client->dev, "flisclk failed\n");
-
-       /* power control */
-       ret = power_ctrl(sd, 0);
-       if (ret)
-               dev_err(&client->dev, "vprog failed.\n");
-
-       dev->power_on = false;
-       return ret;
-}
-
-static int gc0310_s_power(struct v4l2_subdev *sd, int on)
+static struct v4l2_mbus_framefmt *
+gc0310_get_pad_format(struct gc0310_device *dev,
+                     struct v4l2_subdev_state *state,
+                     unsigned int pad, enum v4l2_subdev_format_whence which)
 {
-       int ret;
-
-       if (on == 0)
-               return power_down(sd);
-
-       ret = power_up(sd);
-       if (ret)
-               return ret;
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(&dev->sd, state, pad);
 
-       return gc0310_init(sd);
+       return &dev->mode.fmt;
 }
 
-/* TODO: remove it. */
-static int startup(struct v4l2_subdev *sd)
+/* The GC0310 currently only supports 1 fixed fmt */
+static void gc0310_fill_format(struct v4l2_mbus_framefmt *fmt)
 {
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret = 0;
-
-       ret = gc0310_write_reg_array(client, dev->res->regs);
-       if (ret) {
-               dev_err(&client->dev, "gc0310 write register err.\n");
-               return ret;
-       }
-
-       return ret;
+       memset(fmt, 0, sizeof(*fmt));
+       fmt->width = GC0310_NATIVE_WIDTH;
+       fmt->height = GC0310_NATIVE_HEIGHT;
+       fmt->field = V4L2_FIELD_NONE;
+       fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
 }
 
 static int gc0310_set_fmt(struct v4l2_subdev *sd,
                          struct v4l2_subdev_state *sd_state,
                          struct v4l2_subdev_format *format)
 {
-       struct v4l2_mbus_framefmt *fmt = &format->format;
        struct gc0310_device *dev = to_gc0310_sensor(sd);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct camera_mipi_info *gc0310_info = NULL;
-       struct gc0310_resolution *res;
-       int ret = 0;
-
-       if (format->pad)
-               return -EINVAL;
+       struct v4l2_mbus_framefmt *fmt;
 
-       if (!fmt)
-               return -EINVAL;
-
-       gc0310_info = v4l2_get_subdev_hostdata(sd);
-       if (!gc0310_info)
-               return -EINVAL;
-
-       mutex_lock(&dev->input_lock);
-
-       res = v4l2_find_nearest_size(gc0310_res_preview,
-                                    ARRAY_SIZE(gc0310_res_preview), width,
-                                    height, fmt->width, fmt->height);
-       if (!res)
-               res = &gc0310_res_preview[N_RES - 1];
-
-       fmt->width = res->width;
-       fmt->height = res->height;
-       dev->res = res;
-
-       fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
-
-       if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
-               sd_state->pads->try_fmt = *fmt;
-               mutex_unlock(&dev->input_lock);
-               return 0;
-       }
-
-       /* s_power has not been called yet for std v4l2 clients (camorama) */
-       power_up(sd);
-
-       dev_dbg(&client->dev, "%s: before gc0310_write_reg_array %s\n",
-               __func__, dev->res->desc);
-       ret = startup(sd);
-       if (ret) {
-               dev_err(&client->dev, "gc0310 startup err\n");
-               goto err;
-       }
+       fmt = gc0310_get_pad_format(dev, sd_state, format->pad, format->which);
+       gc0310_fill_format(fmt);
 
-err:
-       mutex_unlock(&dev->input_lock);
-       return ret;
+       format->format = *fmt;
+       return 0;
 }
 
 static int gc0310_get_fmt(struct v4l2_subdev *sd,
                          struct v4l2_subdev_state *sd_state,
                          struct v4l2_subdev_format *format)
 {
-       struct v4l2_mbus_framefmt *fmt = &format->format;
        struct gc0310_device *dev = to_gc0310_sensor(sd);
+       struct v4l2_mbus_framefmt *fmt;
 
-       if (format->pad)
-               return -EINVAL;
-
-       if (!fmt)
-               return -EINVAL;
-
-       fmt->width = dev->res->width;
-       fmt->height = dev->res->height;
-       fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
-
+       fmt = gc0310_get_pad_format(dev, sd_state, format->pad, format->which);
+       format->format = *fmt;
        return 0;
 }
 
 static int gc0310_detect(struct i2c_client *client)
 {
        struct i2c_adapter *adapter = client->adapter;
-       u8 high, low;
        int ret;
-       u16 id;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
                return -ENODEV;
 
-       ret = gc0310_read_reg(client, GC0310_8BIT,
-                             GC0310_SC_CMMN_CHIP_ID_H, &high);
-       if (ret) {
-               dev_err(&client->dev, "read sensor_id_high failed\n");
+       ret = i2c_smbus_read_word_swapped(client, GC0310_SC_CMMN_CHIP_ID_H);
+       if (ret < 0) {
+               dev_err(&client->dev, "read sensor_id failed: %d\n", ret);
                return -ENODEV;
        }
-       ret = gc0310_read_reg(client, GC0310_8BIT,
-                             GC0310_SC_CMMN_CHIP_ID_L, &low);
-       if (ret) {
-               dev_err(&client->dev, "read sensor_id_low failed\n");
-               return -ENODEV;
-       }
-       id = ((((u16)high) << 8) | (u16)low);
-       dev_dbg(&client->dev, "sensor ID = 0x%x\n", id);
 
-       if (id != GC0310_ID) {
-               dev_err(&client->dev, "sensor ID error, read id = 0x%x, target id = 0x%x\n", id,
-                       GC0310_ID);
+       dev_dbg(&client->dev, "sensor ID = 0x%x\n", ret);
+
+       if (ret != GC0310_ID) {
+               dev_err(&client->dev, "sensor ID error, read id = 0x%x, target id = 0x%x\n",
+                       ret, GC0310_ID);
                return -ENODEV;
        }
 
@@ -774,116 +202,90 @@ static int gc0310_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct gc0310_device *dev = to_gc0310_sensor(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret;
+       int ret = 0;
 
        dev_dbg(&client->dev, "%s S enable=%d\n", __func__, enable);
        mutex_lock(&dev->input_lock);
 
-       if (enable) {
-               /* enable per frame MIPI and sensor ctrl reset  */
-               ret = gc0310_write_reg(client, GC0310_8BIT,
-                                      0xFE, 0x30);
-               if (ret) {
-                       mutex_unlock(&dev->input_lock);
-                       return ret;
-               }
-       }
-
-       ret = gc0310_write_reg(client, GC0310_8BIT,
-                              GC0310_RESET_RELATED, GC0310_REGISTER_PAGE_3);
-       if (ret) {
-               mutex_unlock(&dev->input_lock);
-               return ret;
+       if (dev->is_streaming == enable) {
+               dev_warn(&client->dev, "stream already %s\n", enable ? "started" : "stopped");
+               goto error_unlock;
        }
 
-       ret = gc0310_write_reg(client, GC0310_8BIT, GC0310_SW_STREAM,
-                              enable ? GC0310_START_STREAMING :
-                              GC0310_STOP_STREAMING);
-       if (ret) {
-               mutex_unlock(&dev->input_lock);
-               return ret;
-       }
+       if (enable) {
+               ret = pm_runtime_get_sync(&client->dev);
+               if (ret < 0)
+                       goto error_power_down;
 
-       ret = gc0310_write_reg(client, GC0310_8BIT,
-                              GC0310_RESET_RELATED, GC0310_REGISTER_PAGE_0);
-       if (ret) {
-               mutex_unlock(&dev->input_lock);
-               return ret;
-       }
+               msleep(100);
 
-       mutex_unlock(&dev->input_lock);
-       return ret;
-}
-
-static int gc0310_s_config(struct v4l2_subdev *sd,
-                          int irq, void *platform_data)
-{
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       int ret = 0;
+               ret = gc0310_write_reg_array(client, gc0310_reset_register,
+                                            ARRAY_SIZE(gc0310_reset_register));
+               if (ret)
+                       goto error_power_down;
 
-       if (!platform_data)
-               return -ENODEV;
+               ret = gc0310_write_reg_array(client, gc0310_VGA_30fps,
+                                            ARRAY_SIZE(gc0310_VGA_30fps));
+               if (ret)
+                       goto error_power_down;
 
-       dev->platform_data =
-           (struct camera_sensor_platform_data *)platform_data;
+               /* restore value of all ctrls */
+               ret = __v4l2_ctrl_handler_setup(&dev->ctrls.handler);
+               if (ret)
+                       goto error_power_down;
 
-       mutex_lock(&dev->input_lock);
-       /* power off the module, then power on it in future
-        * as first power on by board may not fulfill the
-        * power on sequqence needed by the module
-        */
-       dev->power_on = true; /* force power_down() to run */
-       ret = power_down(sd);
-       if (ret) {
-               dev_err(&client->dev, "gc0310 power-off err.\n");
-               goto fail_power_off;
+               /* enable per frame MIPI and sensor ctrl reset  */
+               ret = i2c_smbus_write_byte_data(client, 0xFE, 0x30);
+               if (ret)
+                       goto error_power_down;
        }
 
-       ret = power_up(sd);
-       if (ret) {
-               dev_err(&client->dev, "gc0310 power-up err.\n");
-               goto fail_power_on;
-       }
+       ret = i2c_smbus_write_byte_data(client, GC0310_RESET_RELATED, GC0310_REGISTER_PAGE_3);
+       if (ret)
+               goto error_power_down;
 
-       ret = dev->platform_data->csi_cfg(sd, 1);
+       ret = i2c_smbus_write_byte_data(client, GC0310_SW_STREAM,
+                                       enable ? GC0310_START_STREAMING : GC0310_STOP_STREAMING);
        if (ret)
-               goto fail_csi_cfg;
+               goto error_power_down;
 
-       /* config & detect sensor */
-       ret = gc0310_detect(client);
-       if (ret) {
-               dev_err(&client->dev, "gc0310_detect err s_config.\n");
-               goto fail_csi_cfg;
-       }
+       ret = i2c_smbus_write_byte_data(client, GC0310_RESET_RELATED, GC0310_REGISTER_PAGE_0);
+       if (ret)
+               goto error_power_down;
 
-       /* turn off sensor, after probed */
-       ret = power_down(sd);
-       if (ret) {
-               dev_err(&client->dev, "gc0310 power-off err.\n");
-               goto fail_csi_cfg;
-       }
-       mutex_unlock(&dev->input_lock);
+       if (!enable)
+               pm_runtime_put(&client->dev);
 
+       dev->is_streaming = enable;
+       mutex_unlock(&dev->input_lock);
        return 0;
 
-fail_csi_cfg:
-       dev->platform_data->csi_cfg(sd, 0);
-fail_power_on:
-       power_down(sd);
-       dev_err(&client->dev, "sensor power-gating failed\n");
-fail_power_off:
+error_power_down:
+       pm_runtime_put(&client->dev);
+       dev->is_streaming = false;
+error_unlock:
        mutex_unlock(&dev->input_lock);
        return ret;
 }
 
+static int gc0310_s_config(struct v4l2_subdev *sd)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int ret;
+
+       ret = pm_runtime_get_sync(&client->dev);
+       if (ret >= 0)
+               ret = gc0310_detect(client);
+
+       pm_runtime_put(&client->dev);
+       return ret;
+}
+
 static int gc0310_g_frame_interval(struct v4l2_subdev *sd,
                                   struct v4l2_subdev_frame_interval *interval)
 {
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-
        interval->interval.numerator = 1;
-       interval->interval.denominator = dev->res->fps;
+       interval->interval.denominator = GC0310_FPS;
 
        return 0;
 }
@@ -892,7 +294,8 @@ static int gc0310_enum_mbus_code(struct v4l2_subdev *sd,
                                 struct v4l2_subdev_state *sd_state,
                                 struct v4l2_subdev_mbus_code_enum *code)
 {
-       if (code->index >= MAX_FMTS)
+       /* We support only a single format */
+       if (code->index)
                return -EINVAL;
 
        code->code = MEDIA_BUS_FMT_SGRBG8_1X8;
@@ -903,27 +306,21 @@ static int gc0310_enum_frame_size(struct v4l2_subdev *sd,
                                  struct v4l2_subdev_state *sd_state,
                                  struct v4l2_subdev_frame_size_enum *fse)
 {
-       int index = fse->index;
-
-       if (index >= N_RES)
+       /* We support only a single resolution */
+       if (fse->index)
                return -EINVAL;
 
-       fse->min_width = gc0310_res[index].width;
-       fse->min_height = gc0310_res[index].height;
-       fse->max_width = gc0310_res[index].width;
-       fse->max_height = gc0310_res[index].height;
+       fse->min_width = GC0310_NATIVE_WIDTH;
+       fse->max_width = GC0310_NATIVE_WIDTH;
+       fse->min_height = GC0310_NATIVE_HEIGHT;
+       fse->max_height = GC0310_NATIVE_HEIGHT;
 
        return 0;
 }
 
 static int gc0310_g_skip_frames(struct v4l2_subdev *sd, u32 *frames)
 {
-       struct gc0310_device *dev = to_gc0310_sensor(sd);
-
-       mutex_lock(&dev->input_lock);
-       *frames = dev->res->skip_frames;
-       mutex_unlock(&dev->input_lock);
-
+       *frames = GC0310_SKIP_FRAMES;
        return 0;
 }
 
@@ -936,11 +333,6 @@ static const struct v4l2_subdev_video_ops gc0310_video_ops = {
        .g_frame_interval = gc0310_g_frame_interval,
 };
 
-static const struct v4l2_subdev_core_ops gc0310_core_ops = {
-       .s_power = gc0310_s_power,
-       .ioctl = gc0310_ioctl,
-};
-
 static const struct v4l2_subdev_pad_ops gc0310_pad_ops = {
        .enum_mbus_code = gc0310_enum_mbus_code,
        .enum_frame_size = gc0310_enum_frame_size,
@@ -949,12 +341,31 @@ static const struct v4l2_subdev_pad_ops gc0310_pad_ops = {
 };
 
 static const struct v4l2_subdev_ops gc0310_ops = {
-       .core = &gc0310_core_ops,
        .video = &gc0310_video_ops,
        .pad = &gc0310_pad_ops,
        .sensor = &gc0310_sensor_ops,
 };
 
+static int gc0310_init_controls(struct gc0310_device *dev)
+{
+       struct v4l2_ctrl_handler *hdl = &dev->ctrls.handler;
+
+       v4l2_ctrl_handler_init(hdl, 2);
+
+       /* Use the same lock for controls as for everything else */
+       hdl->lock = &dev->input_lock;
+       dev->sd.ctrl_handler = hdl;
+
+       dev->ctrls.exposure =
+               v4l2_ctrl_new_std(hdl, &ctrl_ops, V4L2_CID_EXPOSURE, 0, 4095, 1, 1023);
+
+       /* 32 steps at base gain 1 + 64 half steps at base gain 2 */
+       dev->ctrls.gain =
+               v4l2_ctrl_new_std(hdl, &ctrl_ops, V4L2_CID_GAIN, 0, 95, 1, 31);
+
+       return hdl->error;
+}
+
 static void gc0310_remove(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
@@ -962,11 +373,11 @@ static void gc0310_remove(struct i2c_client *client)
 
        dev_dbg(&client->dev, "gc0310_remove...\n");
 
-       dev->platform_data->csi_cfg(sd, 0);
-
+       atomisp_unregister_subdev(sd);
        v4l2_device_unregister_subdev(sd);
        media_entity_cleanup(&dev->sd.entity);
-       v4l2_ctrl_handler_free(&dev->ctrl_handler);
+       v4l2_ctrl_handler_free(&dev->ctrls.handler);
+       pm_runtime_disable(&client->dev);
        kfree(dev);
 }
 
@@ -974,70 +385,91 @@ static int gc0310_probe(struct i2c_client *client)
 {
        struct gc0310_device *dev;
        int ret;
-       void *pdata;
-       unsigned int i;
 
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return -ENOMEM;
 
-       mutex_init(&dev->input_lock);
+       ret = v4l2_get_acpi_sensor_info(&client->dev, NULL);
+       if (ret)
+               return ret;
 
-       dev->res = &gc0310_res_preview[0];
-       v4l2_i2c_subdev_init(&dev->sd, client, &gc0310_ops);
+       dev->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(dev->reset))
+               return dev_err_probe(&client->dev, PTR_ERR(dev->reset),
+                                    "getting reset GPIO\n");
 
-       pdata = gmin_camera_platform_data(&dev->sd,
-                                         ATOMISP_INPUT_FORMAT_RAW_8,
-                                         atomisp_bayer_order_grbg);
-       if (!pdata) {
-               ret = -EINVAL;
-               goto out_free;
-       }
+       dev->powerdown = devm_gpiod_get(&client->dev, "powerdown", GPIOD_OUT_HIGH);
+       if (IS_ERR(dev->powerdown))
+               return dev_err_probe(&client->dev, PTR_ERR(dev->powerdown),
+                                    "getting powerdown GPIO\n");
 
-       ret = gc0310_s_config(&dev->sd, client->irq, pdata);
-       if (ret)
-               goto out_free;
+       mutex_init(&dev->input_lock);
+       v4l2_i2c_subdev_init(&dev->sd, client, &gc0310_ops);
+       gc0310_fill_format(&dev->mode.fmt);
 
-       ret = atomisp_register_i2c_module(&dev->sd, pdata, RAW_CAMERA);
-       if (ret)
-               goto out_free;
+       pm_runtime_set_suspended(&client->dev);
+       pm_runtime_enable(&client->dev);
+       pm_runtime_set_autosuspend_delay(&client->dev, 1000);
+       pm_runtime_use_autosuspend(&client->dev);
+
+       ret = gc0310_s_config(&dev->sd);
+       if (ret) {
+               gc0310_remove(client);
+               return ret;
+       }
 
        dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
        dev->pad.flags = MEDIA_PAD_FL_SOURCE;
-       dev->format.code = MEDIA_BUS_FMT_SGRBG8_1X8;
        dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-       ret =
-           v4l2_ctrl_handler_init(&dev->ctrl_handler,
-                                  ARRAY_SIZE(gc0310_controls));
+
+       ret = gc0310_init_controls(dev);
        if (ret) {
                gc0310_remove(client);
                return ret;
        }
 
-       for (i = 0; i < ARRAY_SIZE(gc0310_controls); i++)
-               v4l2_ctrl_new_custom(&dev->ctrl_handler, &gc0310_controls[i],
-                                    NULL);
+       ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
+       if (ret) {
+               gc0310_remove(client);
+               return ret;
+       }
 
-       if (dev->ctrl_handler.error) {
+       ret = atomisp_register_sensor_no_gmin(&dev->sd, 1, ATOMISP_INPUT_FORMAT_RAW_8,
+                                             atomisp_bayer_order_grbg);
+       if (ret) {
                gc0310_remove(client);
-               return dev->ctrl_handler.error;
+               return ret;
        }
 
-       /* Use same lock for controls as for everything else. */
-       dev->ctrl_handler.lock = &dev->input_lock;
-       dev->sd.ctrl_handler = &dev->ctrl_handler;
+       return 0;
+}
 
-       ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
-       if (ret)
-               gc0310_remove(client);
+static int gc0310_suspend(struct device *dev)
+{
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+       struct gc0310_device *gc0310_dev = to_gc0310_sensor(sd);
 
-       return ret;
-out_free:
-       v4l2_device_unregister_subdev(&dev->sd);
-       kfree(dev);
-       return ret;
+       gpiod_set_value_cansleep(gc0310_dev->powerdown, 1);
+       gpiod_set_value_cansleep(gc0310_dev->reset, 1);
+       return 0;
+}
+
+static int gc0310_resume(struct device *dev)
+{
+       struct v4l2_subdev *sd = dev_get_drvdata(dev);
+       struct gc0310_device *gc0310_dev = to_gc0310_sensor(sd);
+
+       usleep_range(10000, 15000);
+       gpiod_set_value_cansleep(gc0310_dev->reset, 0);
+       usleep_range(10000, 15000);
+       gpiod_set_value_cansleep(gc0310_dev->powerdown, 0);
+
+       return 0;
 }
 
+static DEFINE_RUNTIME_DEV_PM_OPS(gc0310_pm_ops, gc0310_suspend, gc0310_resume, NULL);
+
 static const struct acpi_device_id gc0310_acpi_match[] = {
        {"XXGC0310"},
        {"INT0310"},
@@ -1048,6 +480,7 @@ MODULE_DEVICE_TABLE(acpi, gc0310_acpi_match);
 static struct i2c_driver gc0310_driver = {
        .driver = {
                .name = "gc0310",
+               .pm = pm_sleep_ptr(&gc0310_pm_ops),
                .acpi_match_table = gc0310_acpi_match,
        },
        .probe_new = gc0310_probe,
index aeb38599fe134986a70111f35811f9dbda744f31..63de214916f59ad7ceb27a2ac7761ae4aa6862a6 100644 (file)
@@ -3,6 +3,7 @@
  * Support for OmniVision OV2680 1080p HD camera sensor.
  *
  * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
+ * Copyright (c) 2023 Hans de Goede <hdegoede@redhat.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version
@@ -418,7 +419,7 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
        if (enable) {
                ret = pm_runtime_get_sync(sensor->sd.dev);
                if (ret < 0)
-                       goto error_unlock;
+                       goto error_power_down;
 
                ret = ov2680_set_mode(sensor);
                if (ret)
@@ -446,6 +447,7 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
 
 error_power_down:
        pm_runtime_put(sensor->sd.dev);
+       sensor->is_streaming = false;
 error_unlock:
        mutex_unlock(&sensor->input_lock);
        return ret;
@@ -614,21 +616,6 @@ static void ov2680_remove(struct i2c_client *client)
        pm_runtime_disable(&client->dev);
 }
 
-/*
- * Unlike other sensors which have both a rest and powerdown input pins,
- * the OV2680 only has a powerdown input. But some ACPI tables still list
- * 2 GPIOs for the OV2680 and it is unclear which to use. So try to get
- * up to 2 GPIOs (1 mandatory, 1 optional) and control them in sync.
- */
-static const struct acpi_gpio_params ov2680_first_gpio = { 0, 0, true };
-static const struct acpi_gpio_params ov2680_second_gpio = { 1, 0, true };
-
-static const struct acpi_gpio_mapping ov2680_gpio_mapping[] = {
-       { "powerdown-gpios", &ov2680_first_gpio, 1 },
-       { "powerdown-alt-gpios", &ov2680_second_gpio, 1 },
-       { },
-};
-
 static int ov2680_probe(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
@@ -644,26 +631,24 @@ static int ov2680_probe(struct i2c_client *client)
        sensor->client = client;
        v4l2_i2c_subdev_init(&sensor->sd, client, &ov2680_ops);
 
-       ret = devm_acpi_dev_add_driver_gpios(&client->dev, ov2680_gpio_mapping);
+       ret = v4l2_get_acpi_sensor_info(dev, NULL);
        if (ret)
                return ret;
 
-       sensor->powerdown = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_HIGH);
+       sensor->powerdown = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH);
        if (IS_ERR(sensor->powerdown))
                return dev_err_probe(dev, PTR_ERR(sensor->powerdown), "getting powerdown GPIO\n");
 
-       sensor->powerdown_alt = devm_gpiod_get_optional(dev, "powerdown-alt", GPIOD_OUT_HIGH);
-       if (IS_ERR(sensor->powerdown_alt))
-               return dev_err_probe(dev, PTR_ERR(sensor->powerdown_alt), "getting powerdown-alt GPIO\n");
-
        pm_runtime_set_suspended(dev);
        pm_runtime_enable(dev);
        pm_runtime_set_autosuspend_delay(dev, 1000);
        pm_runtime_use_autosuspend(dev);
 
        ret = ov2680_s_config(&sensor->sd);
-       if (ret)
+       if (ret) {
+               ov2680_remove(client);
                return ret;
+       }
 
        sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
        sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
@@ -699,7 +684,6 @@ static int ov2680_suspend(struct device *dev)
        struct ov2680_device *sensor = to_ov2680_sensor(sd);
 
        gpiod_set_value_cansleep(sensor->powerdown, 1);
-       gpiod_set_value_cansleep(sensor->powerdown_alt, 1);
        return 0;
 }
 
@@ -712,7 +696,6 @@ static int ov2680_resume(struct device *dev)
        usleep_range(5000, 6000);
 
        gpiod_set_value_cansleep(sensor->powerdown, 0);
-       gpiod_set_value_cansleep(sensor->powerdown_alt, 0);
 
        /* according to DS, 20ms is needed between PWDN and i2c access */
        msleep(20);
index cae480ae6fba490d9599763e620bb9c3bbec5776..d404062895987ff327275ba4c269a972c552ffa6 100644 (file)
 
 #include "../include/linux/atomisp_platform.h"
 
-/* Defines for register writes and register array processing */
-#define I2C_MSG_LENGTH         1
-#define I2C_RETRY_COUNT                5
+#define GC0310_NATIVE_WIDTH                    656
+#define GC0310_NATIVE_HEIGHT                   496
 
-#define GC0310_FOCAL_LENGTH_NUM        278     /*2.78mm*/
+#define GC0310_FPS                             30
+#define GC0310_SKIP_FRAMES                     3
 
-#define MAX_FMTS               1
+#define GC0310_FOCAL_LENGTH_NUM                        278 /* 2.78mm */
 
-/*
- * focal length bits definition:
- * bits 31-16: numerator, bits 15-0: denominator
- */
-#define GC0310_FOCAL_LENGTH_DEFAULT 0x1160064
-
-/*
- * current f-number bits definition:
- * bits 31-16: numerator, bits 15-0: denominator
- */
-#define GC0310_F_NUMBER_DEFAULT 0x1a000a
-
-/*
- * f-number range bits definition:
- * bits 31-24: max f-number numerator
- * bits 23-16: max f-number denominator
- * bits 15-8: min f-number numerator
- * bits 7-0: min f-number denominator
- */
-#define GC0310_F_NUMBER_RANGE 0x1a0a1a0a
 #define GC0310_ID      0xa310
 
 #define GC0310_RESET_RELATED           0xFE
 #define GC0310_START_STREAMING                 0x94 /* 8-bit enable */
 #define GC0310_STOP_STREAMING                  0x0 /* 8-bit disable */
 
-#define GC0310_BIN_FACTOR_MAX                  3
-
-struct regval_list {
-       u16 reg_num;
-       u8 value;
-};
-
-struct gc0310_resolution {
-       u8 *desc;
-       const struct gc0310_reg *regs;
-       int res;
-       int width;
-       int height;
-       int fps;
-       int pix_clk_freq;
-       u32 skip_frames;
-       u16 pixels_per_line;
-       u16 lines_per_frame;
-       bool used;
-};
-
-struct gc0310_format {
-       u8 *desc;
-       u32 pixelformat;
-       struct gc0310_reg *regs;
-};
-
 /*
  * gc0310 device structure.
  */
 struct gc0310_device {
        struct v4l2_subdev sd;
        struct media_pad pad;
-       struct v4l2_mbus_framefmt format;
        struct mutex input_lock;
-       struct v4l2_ctrl_handler ctrl_handler;
+       bool is_streaming;
 
-       struct camera_sensor_platform_data *platform_data;
-       struct gc0310_resolution *res;
-       u8 type;
-       bool power_on;
-};
+       struct gpio_desc *reset;
+       struct gpio_desc *powerdown;
 
-enum gc0310_tok_type {
-       GC0310_8BIT  = 0x0001,
-       GC0310_TOK_TERM   = 0xf000,     /* terminating token for reg list */
-       GC0310_TOK_DELAY  = 0xfe00,     /* delay token for reg list */
-       GC0310_TOK_MASK = 0xfff0
+       struct gc0310_mode {
+               struct v4l2_mbus_framefmt fmt;
+       } mode;
+
+       struct gc0310_ctrls {
+               struct v4l2_ctrl_handler handler;
+               struct v4l2_ctrl *exposure;
+               struct v4l2_ctrl *gain;
+       } ctrls;
 };
 
 /**
  * struct gc0310_reg - MI sensor  register format
- * @type: type of the register
  * @reg: 16-bit offset to register
  * @val: 8/16/32-bit register value
  *
  * Define a structure for sensor register initialization values
  */
 struct gc0310_reg {
-       enum gc0310_tok_type type;
        u8 reg;
        u8 val; /* @set value for read/mod/write, @mask */
 };
 
 #define to_gc0310_sensor(x) container_of(x, struct gc0310_device, sd)
 
-#define GC0310_MAX_WRITE_BUF_SIZE      30
-
-struct gc0310_write_buffer {
-       u8 addr;
-       u8 data[GC0310_MAX_WRITE_BUF_SIZE];
-};
-
-struct gc0310_write_ctrl {
-       int index;
-       struct gc0310_write_buffer buffer;
-};
-
 /*
  * Register settings for various resolution
  */
@@ -190,206 +129,181 @@ static const struct gc0310_reg gc0310_reset_register[] = {
 /////////////////////////////////////////////////
 /////////////////      system reg      /////////////////
 /////////////////////////////////////////////////
-       {GC0310_8BIT, 0xfe, 0xf0},
-       {GC0310_8BIT, 0xfe, 0xf0},
-       {GC0310_8BIT, 0xfe, 0x00},
-
-       {GC0310_8BIT, 0xfc, 0x0e}, //4e
-       {GC0310_8BIT, 0xfc, 0x0e}, //16//4e // [0]apwd [6]regf_clk_gate
-       {GC0310_8BIT, 0xf2, 0x80}, //sync output
-       {GC0310_8BIT, 0xf3, 0x00}, //1f//01 data output
-       {GC0310_8BIT, 0xf7, 0x33}, //f9
-       {GC0310_8BIT, 0xf8, 0x05}, //00
-       {GC0310_8BIT, 0xf9, 0x0e}, // 0x8e //0f
-       {GC0310_8BIT, 0xfa, 0x11},
+       { 0xfe, 0xf0 },
+       { 0xfe, 0xf0 },
+       { 0xfe, 0x00 },
+
+       { 0xfc, 0x0e }, /* 4e */
+       { 0xfc, 0x0e }, /* 16//4e // [0]apwd [6]regf_clk_gate */
+       { 0xf2, 0x80 }, /* sync output */
+       { 0xf3, 0x00 }, /* 1f//01 data output */
+       { 0xf7, 0x33 }, /* f9 */
+       { 0xf8, 0x05 }, /* 00 */
+       { 0xf9, 0x0e }, /* 0x8e //0f */
+       { 0xfa, 0x11 },
 
 /////////////////////////////////////////////////
 ///////////////////   MIPI      ////////////////////
 /////////////////////////////////////////////////
-       {GC0310_8BIT, 0xfe, 0x03},
-       {GC0310_8BIT, 0x01, 0x03}, ///mipi 1lane
-       {GC0310_8BIT, 0x02, 0x22}, // 0x33
-       {GC0310_8BIT, 0x03, 0x94},
-       {GC0310_8BIT, 0x04, 0x01}, // fifo_prog
-       {GC0310_8BIT, 0x05, 0x00}, //fifo_prog
-       {GC0310_8BIT, 0x06, 0x80}, //b0  //YUV ISP data
-       {GC0310_8BIT, 0x11, 0x2a},//1e //LDI set YUV422
-       {GC0310_8BIT, 0x12, 0x90},//00 //04 //00 //04//00 //LWC[7:0]  //
-       {GC0310_8BIT, 0x13, 0x02},//05 //05 //LWC[15:8]
-       {GC0310_8BIT, 0x15, 0x12}, // 0x10 //DPHYY_MODE read_ready
-       {GC0310_8BIT, 0x17, 0x01},
-       {GC0310_8BIT, 0x40, 0x08},
-       {GC0310_8BIT, 0x41, 0x00},
-       {GC0310_8BIT, 0x42, 0x00},
-       {GC0310_8BIT, 0x43, 0x00},
-       {GC0310_8BIT, 0x21, 0x02}, // 0x01
-       {GC0310_8BIT, 0x22, 0x02}, // 0x01
-       {GC0310_8BIT, 0x23, 0x01}, // 0x05 //Nor:0x05 DOU:0x06
-       {GC0310_8BIT, 0x29, 0x00},
-       {GC0310_8BIT, 0x2A, 0x25}, // 0x05 //data zero 0x7a de
-       {GC0310_8BIT, 0x2B, 0x02},
-
-       {GC0310_8BIT, 0xfe, 0x00},
+       { 0xfe, 0x03 },
+       { 0x01, 0x03 }, /* mipi 1lane */
+       { 0x02, 0x22 }, /* 0x33 */
+       { 0x03, 0x94 },
+       { 0x04, 0x01 }, /* fifo_prog */
+       { 0x05, 0x00 }, /* fifo_prog */
+       { 0x06, 0x80 }, /* b0  //YUV ISP data */
+       { 0x11, 0x2a }, /* 1e //LDI set YUV422 */
+       { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */
+       { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */
+       { 0x15, 0x12 }, /* 0x10 //DPHYY_MODE read_ready */
+       { 0x17, 0x01 },
+       { 0x40, 0x08 },
+       { 0x41, 0x00 },
+       { 0x42, 0x00 },
+       { 0x43, 0x00 },
+       { 0x21, 0x02 }, /* 0x01 */
+       { 0x22, 0x02 }, /* 0x01 */
+       { 0x23, 0x01 }, /* 0x05 //Nor:0x05 DOU:0x06 */
+       { 0x29, 0x00 },
+       { 0x2A, 0x25 }, /* 0x05 //data zero 0x7a de */
+       { 0x2B, 0x02 },
+
+       { 0xfe, 0x00 },
 
 /////////////////////////////////////////////////
 /////////////////      CISCTL reg      /////////////////
 /////////////////////////////////////////////////
-       {GC0310_8BIT, 0x00, 0x2f}, //2f//0f//02//01
-       {GC0310_8BIT, 0x01, 0x0f}, //06
-       {GC0310_8BIT, 0x02, 0x04},
-       {GC0310_8BIT, 0x4f, 0x00}, //AEC 0FF
-       {GC0310_8BIT, 0x03, 0x01}, // 0x03 //04
-       {GC0310_8BIT, 0x04, 0xc0}, // 0xe8 //58
-       {GC0310_8BIT, 0x05, 0x00},
-       {GC0310_8BIT, 0x06, 0xb2}, // 0x0a //HB
-       {GC0310_8BIT, 0x07, 0x00},
-       {GC0310_8BIT, 0x08, 0x0c}, // 0x89 //VB
-       {GC0310_8BIT, 0x09, 0x00}, //row start
-       {GC0310_8BIT, 0x0a, 0x00}, //
-       {GC0310_8BIT, 0x0b, 0x00}, //col start
-       {GC0310_8BIT, 0x0c, 0x00},
-       {GC0310_8BIT, 0x0d, 0x01}, //height
-       {GC0310_8BIT, 0x0e, 0xf2}, // 0xf7 //height
-       {GC0310_8BIT, 0x0f, 0x02}, //width
-       {GC0310_8BIT, 0x10, 0x94}, // 0xa0 //height
-       {GC0310_8BIT, 0x17, 0x14},
-       {GC0310_8BIT, 0x18, 0x1a}, //0a//[4]double reset
-       {GC0310_8BIT, 0x19, 0x14}, //AD pipeline
-       {GC0310_8BIT, 0x1b, 0x48},
-       {GC0310_8BIT, 0x1e, 0x6b}, //3b//col bias
-       {GC0310_8BIT, 0x1f, 0x28}, //20//00//08//txlow
-       {GC0310_8BIT, 0x20, 0x89}, //88//0c//[3:2]DA15
-       {GC0310_8BIT, 0x21, 0x49}, //48//[3] txhigh
-       {GC0310_8BIT, 0x22, 0xb0},
-       {GC0310_8BIT, 0x23, 0x04}, //[1:0]vcm_r
-       {GC0310_8BIT, 0x24, 0x16}, //15
-       {GC0310_8BIT, 0x34, 0x20}, //[6:4] rsg high//range
+       { 0x00, 0x2f }, /* 2f//0f//02//01 */
+       { 0x01, 0x0f }, /* 06 */
+       { 0x02, 0x04 },
+       { 0x4f, 0x00 }, /* AEC 0FF */
+       { 0x03, 0x01 }, /* 0x03 //04 */
+       { 0x04, 0xc0 }, /* 0xe8 //58 */
+       { 0x05, 0x00 },
+       { 0x06, 0xb2 }, /* 0x0a //HB */
+       { 0x07, 0x00 },
+       { 0x08, 0x0c }, /* 0x89 //VB */
+       { 0x09, 0x00 }, /* row start */
+       { 0x0a, 0x00 },
+       { 0x0b, 0x00 }, /* col start */
+       { 0x0c, 0x00 },
+       { 0x0d, 0x01 }, /* height */
+       { 0x0e, 0xf2 }, /* 0xf7 //height */
+       { 0x0f, 0x02 }, /* width */
+       { 0x10, 0x94 }, /* 0xa0 //height */
+       { 0x17, 0x14 },
+       { 0x18, 0x1a }, /* 0a//[4]double reset */
+       { 0x19, 0x14 }, /* AD pipeline */
+       { 0x1b, 0x48 },
+       { 0x1e, 0x6b }, /* 3b//col bias */
+       { 0x1f, 0x28 }, /* 20//00//08//txlow */
+       { 0x20, 0x89 }, /* 88//0c//[3:2]DA15 */
+       { 0x21, 0x49 }, /* 48//[3] txhigh */
+       { 0x22, 0xb0 },
+       { 0x23, 0x04 }, /* [1:0]vcm_r */
+       { 0x24, 0x16 }, /* 15 */
+       { 0x34, 0x20 }, /* [6:4] rsg high//range */
 
 /////////////////////////////////////////////////
 ////////////////////   BLK      ////////////////////
 /////////////////////////////////////////////////
-       {GC0310_8BIT, 0x26, 0x23}, //[1]dark_current_en [0]offset_en
-       {GC0310_8BIT, 0x28, 0xff}, //BLK_limie_value
-       {GC0310_8BIT, 0x29, 0x00}, //global offset
-       {GC0310_8BIT, 0x33, 0x18}, //offset_ratio
-       {GC0310_8BIT, 0x37, 0x20}, //dark_current_ratio
-       {GC0310_8BIT, 0x2a, 0x00},
-       {GC0310_8BIT, 0x2b, 0x00},
-       {GC0310_8BIT, 0x2c, 0x00},
-       {GC0310_8BIT, 0x2d, 0x00},
-       {GC0310_8BIT, 0x2e, 0x00},
-       {GC0310_8BIT, 0x2f, 0x00},
-       {GC0310_8BIT, 0x30, 0x00},
-       {GC0310_8BIT, 0x31, 0x00},
-       {GC0310_8BIT, 0x47, 0x80}, //a7
-       {GC0310_8BIT, 0x4e, 0x66}, //select_row
-       {GC0310_8BIT, 0xa8, 0x02}, //win_width_dark, same with crop_win_width
-       {GC0310_8BIT, 0xa9, 0x80},
+       { 0x26, 0x23 }, /* [1]dark_current_en [0]offset_en */
+       { 0x28, 0xff }, /* BLK_limie_value */
+       { 0x29, 0x00 }, /* global offset */
+       { 0x33, 0x18 }, /* offset_ratio */
+       { 0x37, 0x20 }, /* dark_current_ratio */
+       { 0x2a, 0x00 },
+       { 0x2b, 0x00 },
+       { 0x2c, 0x00 },
+       { 0x2d, 0x00 },
+       { 0x2e, 0x00 },
+       { 0x2f, 0x00 },
+       { 0x30, 0x00 },
+       { 0x31, 0x00 },
+       { 0x47, 0x80 }, /* a7 */
+       { 0x4e, 0x66 }, /* select_row */
+       { 0xa8, 0x02 }, /* win_width_dark, same with crop_win_width */
+       { 0xa9, 0x80 },
 
 /////////////////////////////////////////////////
 //////////////////      ISP reg  ///////////////////
 /////////////////////////////////////////////////
-       {GC0310_8BIT, 0x40, 0x06}, // 0xff //ff //48
-       {GC0310_8BIT, 0x41, 0x00}, // 0x21 //00//[0]curve_en
-       {GC0310_8BIT, 0x42, 0x04}, // 0xcf //0a//[1]awn_en
-       {GC0310_8BIT, 0x44, 0x18}, // 0x18 //02
-       {GC0310_8BIT, 0x46, 0x02}, // 0x03 //sync
-       {GC0310_8BIT, 0x49, 0x03},
-       {GC0310_8BIT, 0x4c, 0x20}, //00[5]pretect exp
-       {GC0310_8BIT, 0x50, 0x01}, //crop enable
-       {GC0310_8BIT, 0x51, 0x00},
-       {GC0310_8BIT, 0x52, 0x00},
-       {GC0310_8BIT, 0x53, 0x00},
-       {GC0310_8BIT, 0x54, 0x01},
-       {GC0310_8BIT, 0x55, 0x01}, //crop window height
-       {GC0310_8BIT, 0x56, 0xf0},
-       {GC0310_8BIT, 0x57, 0x02}, //crop window width
-       {GC0310_8BIT, 0x58, 0x90},
+       { 0x40, 0x06 }, /* 0xff //ff //48 */
+       { 0x41, 0x00 }, /* 0x21 //00//[0]curve_en */
+       { 0x42, 0x04 }, /* 0xcf //0a//[1]awn_en */
+       { 0x44, 0x18 }, /* 0x18 //02 */
+       { 0x46, 0x02 }, /* 0x03 //sync */
+       { 0x49, 0x03 },
+       { 0x4c, 0x20 }, /* 00[5]pretect exp */
+       { 0x50, 0x01 }, /* crop enable */
+       { 0x51, 0x00 },
+       { 0x52, 0x00 },
+       { 0x53, 0x00 },
+       { 0x54, 0x01 },
+       { 0x55, 0x01 }, /* crop window height */
+       { 0x56, 0xf0 },
+       { 0x57, 0x02 }, /* crop window width */
+       { 0x58, 0x90 },
 
 /////////////////////////////////////////////////
 ///////////////////   GAIN      ////////////////////
 /////////////////////////////////////////////////
-       {GC0310_8BIT, 0x70, 0x70}, //70 //80//global gain
-       {GC0310_8BIT, 0x71, 0x20}, // pregain gain
-       {GC0310_8BIT, 0x72, 0x40}, // post gain
-       {GC0310_8BIT, 0x5a, 0x84}, //84//analog gain 0
-       {GC0310_8BIT, 0x5b, 0xc9}, //c9
-       {GC0310_8BIT, 0x5c, 0xed}, //ed//not use pga gain highest level
-       {GC0310_8BIT, 0x77, 0x40}, // R gain 0x74 //awb gain
-       {GC0310_8BIT, 0x78, 0x40}, // G gain
-       {GC0310_8BIT, 0x79, 0x40}, // B gain 0x5f
-
-       {GC0310_8BIT, 0x48, 0x00},
-       {GC0310_8BIT, 0xfe, 0x01},
-       {GC0310_8BIT, 0x0a, 0x45}, //[7]col gain mode
-
-       {GC0310_8BIT, 0x3e, 0x40},
-       {GC0310_8BIT, 0x3f, 0x5c},
-       {GC0310_8BIT, 0x40, 0x7b},
-       {GC0310_8BIT, 0x41, 0xbd},
-       {GC0310_8BIT, 0x42, 0xf6},
-       {GC0310_8BIT, 0x43, 0x63},
-       {GC0310_8BIT, 0x03, 0x60},
-       {GC0310_8BIT, 0x44, 0x03},
+       { 0x70, 0x70 }, /* 70 //80//global gain */
+       { 0x71, 0x20 }, /* pregain gain */
+       { 0x72, 0x40 }, /* post gain */
+       { 0x5a, 0x84 }, /* 84//analog gain 0  */
+       { 0x5b, 0xc9 }, /* c9 */
+       { 0x5c, 0xed }, /* ed//not use pga gain highest level */
+       { 0x77, 0x40 }, /* R gain 0x74 //awb gain */
+       { 0x78, 0x40 }, /* G gain */
+       { 0x79, 0x40 }, /* B gain 0x5f */
+
+       { 0x48, 0x00 },
+       { 0xfe, 0x01 },
+       { 0x0a, 0x45 }, /* [7]col gain mode */
+
+       { 0x3e, 0x40 },
+       { 0x3f, 0x5c },
+       { 0x40, 0x7b },
+       { 0x41, 0xbd },
+       { 0x42, 0xf6 },
+       { 0x43, 0x63 },
+       { 0x03, 0x60 },
+       { 0x44, 0x03 },
 
 /////////////////////////////////////////////////
 /////////////////      dark sun   //////////////////
 /////////////////////////////////////////////////
-       {GC0310_8BIT, 0xfe, 0x01},
-       {GC0310_8BIT, 0x45, 0xa4}, // 0xf7
-       {GC0310_8BIT, 0x46, 0xf0}, // 0xff //f0//sun value th
-       {GC0310_8BIT, 0x48, 0x03}, //sun mode
-       {GC0310_8BIT, 0x4f, 0x60}, //sun_clamp
-       {GC0310_8BIT, 0xfe, 0x00},
-
-       {GC0310_TOK_TERM, 0, 0},
+       { 0xfe, 0x01 },
+       { 0x45, 0xa4 }, /* 0xf7 */
+       { 0x46, 0xf0 }, /* 0xff //f0//sun value th */
+       { 0x48, 0x03 }, /* sun mode */
+       { 0x4f, 0x60 }, /* sun_clamp */
+       { 0xfe, 0x00 },
 };
 
 static struct gc0310_reg const gc0310_VGA_30fps[] = {
-       {GC0310_8BIT, 0xfe, 0x00},
-       {GC0310_8BIT, 0x0d, 0x01}, //height
-       {GC0310_8BIT, 0x0e, 0xf2}, // 0xf7 //height
-       {GC0310_8BIT, 0x0f, 0x02}, //width
-       {GC0310_8BIT, 0x10, 0x94}, // 0xa0 //height
-
-       {GC0310_8BIT, 0x50, 0x01}, //crop enable
-       {GC0310_8BIT, 0x51, 0x00},
-       {GC0310_8BIT, 0x52, 0x00},
-       {GC0310_8BIT, 0x53, 0x00},
-       {GC0310_8BIT, 0x54, 0x01},
-       {GC0310_8BIT, 0x55, 0x01}, //crop window height
-       {GC0310_8BIT, 0x56, 0xf0},
-       {GC0310_8BIT, 0x57, 0x02}, //crop window width
-       {GC0310_8BIT, 0x58, 0x90},
-
-       {GC0310_8BIT, 0xfe, 0x03},
-       {GC0310_8BIT, 0x12, 0x90},//00 //04 //00 //04//00 //LWC[7:0]  //
-       {GC0310_8BIT, 0x13, 0x02},//05 //05 //LWC[15:8]
-
-       {GC0310_8BIT, 0xfe, 0x00},
-
-       {GC0310_TOK_TERM, 0, 0},
-};
-
-static struct gc0310_resolution gc0310_res_preview[] = {
-       {
-               .desc = "gc0310_VGA_30fps",
-               .width = 656, // 648,
-               .height = 496, // 488,
-               .fps = 30,
-               //.pix_clk_freq = 73,
-               .used = 0,
-#if 0
-               .pixels_per_line = 0x0314,
-               .lines_per_frame = 0x0213,
-#endif
-               .skip_frames = 2,
-               .regs = gc0310_VGA_30fps,
-       },
+       { 0xfe, 0x00 },
+       { 0x0d, 0x01 }, /* height */
+       { 0x0e, 0xf2 }, /* 0xf7 //height */
+       { 0x0f, 0x02 }, /* width */
+       { 0x10, 0x94 }, /* 0xa0 //height */
+
+       { 0x50, 0x01 }, /* crop enable */
+       { 0x51, 0x00 },
+       { 0x52, 0x00 },
+       { 0x53, 0x00 },
+       { 0x54, 0x01 },
+       { 0x55, 0x01 }, /* crop window height */
+       { 0x56, 0xf0 },
+       { 0x57, 0x02 }, /* crop window width */
+       { 0x58, 0x90 },
+
+       { 0xfe, 0x03 },
+       { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0]  */
+       { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */
+
+       { 0xfe, 0x00 },
 };
 
-#define N_RES_PREVIEW (ARRAY_SIZE(gc0310_res_preview))
-
-static struct gc0310_resolution *gc0310_res = gc0310_res_preview;
-static unsigned long N_RES = N_RES_PREVIEW;
 #endif
index a37af0a74a53219b9bc450ccf868d6ed22480b4b..baf49eb0659e31ee749c22acad088a3396c0406a 100644 (file)
@@ -114,7 +114,6 @@ struct ov2680_device {
        struct mutex input_lock;
        struct i2c_client *client;
        struct gpio_desc *powerdown;
-       struct gpio_desc *powerdown_alt;
        bool is_streaming;
 
        struct ov2680_mode {
index 63b1bcd35399bc82611f56ccd3a41853534501b0..c7ec56a1c06404a0981c9f56f0cede08c7797fea 100644 (file)
@@ -299,26 +299,6 @@ struct atomisp_3a_statistics {
        u32 isp_config_id; /* isp config ID */
 };
 
-/**
- * struct atomisp_cont_capture_conf - continuous capture parameters
- * @num_captures: number of still images to capture
- * @skip_frames: number of frames to skip between 2 captures
- * @offset: offset in ring buffer to start capture
- *
- * For example, to capture 1 frame from past, current, and 1 from future
- * and skip one frame between each capture, parameters would be:
- * num_captures:3
- * skip_frames:1
- * offset:-2
- */
-
-struct atomisp_cont_capture_conf {
-       int num_captures;
-       unsigned int skip_frames;
-       int offset;
-       __u32 reserved[5];
-};
-
 struct atomisp_ae_window {
        int x_left;
        int x_right;
@@ -958,9 +938,6 @@ struct atomisp_sensor_ae_bracketing_lut {
 #define ATOMISP_IOC_S_PARAMETERS \
        _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_parameters)
 
-#define ATOMISP_IOC_S_CONT_CAPTURE_CONFIG \
-       _IOWR('v', BASE_VIDIOC_PRIVATE + 33, struct atomisp_cont_capture_conf)
-
 #define ATOMISP_IOC_G_METADATA \
        _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata)
 
@@ -1079,8 +1056,6 @@ struct atomisp_sensor_ae_bracketing_lut {
 #define V4L2_2A_STATUS_AE_READY            BIT(0)
 #define V4L2_2A_STATUS_AWB_READY           BIT(1)
 
-#define V4L2_CID_FMT_AUTO                      (V4L2_CID_CAMERA_LASTP1 + 19)
-
 #define V4L2_CID_RUN_MODE                      (V4L2_CID_CAMERA_LASTP1 + 20)
 #define ATOMISP_RUN_MODE_VIDEO                 1
 #define ATOMISP_RUN_MODE_STILL_CAPTURE         2
@@ -1107,8 +1082,6 @@ struct atomisp_sensor_ae_bracketing_lut {
 /* Lock and unlock raw buffer */
 #define V4L2_CID_ENABLE_RAW_BUFFER_LOCK (V4L2_CID_CAMERA_LASTP1 + 29)
 
-#define V4L2_CID_DEPTH_MODE            (V4L2_CID_CAMERA_LASTP1 + 30)
-
 #define V4L2_CID_EXPOSURE_ZONE_NUM     (V4L2_CID_CAMERA_LASTP1 + 31)
 /* Disable digital zoom */
 #define V4L2_CID_DISABLE_DZ            (V4L2_CID_CAMERA_LASTP1 + 32)
@@ -1127,7 +1100,6 @@ struct atomisp_sensor_ae_bracketing_lut {
 
 #define V4L2_EVENT_ATOMISP_3A_STATS_READY   (V4L2_EVENT_PRIVATE_START + 1)
 #define V4L2_EVENT_ATOMISP_METADATA_READY   (V4L2_EVENT_PRIVATE_START + 2)
-#define V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE   (V4L2_EVENT_PRIVATE_START + 3)
 #define V4L2_EVENT_ATOMISP_ACC_COMPLETE     (V4L2_EVENT_PRIVATE_START + 4)
 #define V4L2_EVENT_ATOMISP_PAUSE_BUFFER            (V4L2_EVENT_PRIVATE_START + 5)
 #define V4L2_EVENT_ATOMISP_CSS_RESET       (V4L2_EVENT_PRIVATE_START + 6)
index 539b21d39d3be6d99cd127c9ede87fdeb19639b6..e8e965f73fc8f97e50be3258e89d625802802b64 100644 (file)
@@ -111,12 +111,9 @@ enum atomisp_input_format {
 
 enum intel_v4l2_subdev_type {
        RAW_CAMERA = 1,
-       SOC_CAMERA = 2,
-       CAMERA_MOTOR = 3,
-       LED_FLASH = 4,
-       XENON_FLASH = 5,
-       FILE_INPUT = 6,
-       TEST_PATTERN = 7,
+       CAMERA_MOTOR = 2,
+       LED_FLASH = 3,
+       TEST_PATTERN = 4,
 };
 
 struct intel_v4l2_subdev_id {
@@ -216,6 +213,8 @@ int atomisp_register_sensor_no_gmin(struct v4l2_subdev *subdev, u32 lanes,
                                    enum atomisp_bayer_order bayer_order);
 void atomisp_unregister_subdev(struct v4l2_subdev *subdev);
 
+int v4l2_get_acpi_sensor_info(struct device *dev, char **module_id_str);
+
 /* API from old platform_camera.h, new CPUID implementation */
 #define __IS_SOC(x) (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && \
                     boot_cpu_data.x86 == 6 &&                       \
index 47f18ac5e40e140cf38cd8f746a17be21c840653..aa790ae746f3742dcaad0627bbce5e772db6c0f8 100644 (file)
@@ -79,8 +79,6 @@ union host {
        } ptr;
 };
 
-static int atomisp_set_raw_buffer_bitmap(struct atomisp_sub_device *asd, int exp_id);
-
 /*
  * get sensor:dis71430/ov2720 related info from v4l2_subdev->priv data field.
  * subdev->priv is set in mrst.c
@@ -198,19 +196,12 @@ int atomisp_freq_scaling(struct atomisp_device *isp,
                         enum atomisp_dfs_mode mode,
                         bool force)
 {
-       struct pci_dev *pdev = to_pci_dev(isp->dev);
-       /* FIXME! Only use subdev[0] status yet */
-       struct atomisp_sub_device *asd = &isp->asd[0];
        const struct atomisp_dfs_config *dfs;
        unsigned int new_freq;
        struct atomisp_freq_scaling_rule curr_rules;
        int i, ret;
        unsigned short fps = 0;
 
-       if ((pdev->device & ATOMISP_PCI_DEVICE_SOC_MASK) ==
-           ATOMISP_PCI_DEVICE_SOC_CHT && ATOMISP_USE_YUVPP(asd))
-               isp->dfs = &dfs_config_cht_soc;
-
        dfs = isp->dfs;
 
        if (dfs->lowest_freq == 0 || dfs->max_freq_at_vmin == 0 ||
@@ -230,7 +221,7 @@ int atomisp_freq_scaling(struct atomisp_device *isp,
                goto done;
        }
 
-       fps = atomisp_get_sensor_fps(asd);
+       fps = atomisp_get_sensor_fps(&isp->asd);
        if (fps == 0) {
                dev_info(isp->dev,
                         "Sensor didn't report FPS. Using DFS max mode.\n");
@@ -238,22 +229,10 @@ int atomisp_freq_scaling(struct atomisp_device *isp,
                goto done;
        }
 
-       curr_rules.width = asd->fmt[asd->capture_pad].fmt.width;
-       curr_rules.height = asd->fmt[asd->capture_pad].fmt.height;
+       curr_rules.width = isp->asd.fmt[isp->asd.capture_pad].fmt.width;
+       curr_rules.height = isp->asd.fmt[isp->asd.capture_pad].fmt.height;
        curr_rules.fps = fps;
-       curr_rules.run_mode = asd->run_mode->val;
-       /*
-        * For continuous mode, we need to make the capture setting applied
-        * since preview mode, because there is no chance to do this when
-        * starting image capture.
-        */
-       if (asd->continuous_mode->val) {
-               if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
-                       curr_rules.run_mode = ATOMISP_RUN_MODE_SDV;
-               else
-                       curr_rules.run_mode =
-                           ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE;
-       }
+       curr_rules.run_mode = isp->asd.run_mode->val;
 
        /* search for the target frequency by looping freq rules*/
        for (i = 0; i < dfs->dfs_table_size; i++) {
@@ -470,37 +449,13 @@ static void clear_irq_reg(struct atomisp_device *isp)
        pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg_ret);
 }
 
-static struct atomisp_sub_device *
-__get_asd_from_port(struct atomisp_device *isp, enum mipi_port_id port)
-{
-       int i;
-
-       /* Check which isp subdev to send eof */
-       for (i = 0; i < isp->num_of_streams; i++) {
-               struct atomisp_sub_device *asd = &isp->asd[i];
-               struct camera_mipi_info *mipi_info;
-
-               mipi_info = atomisp_to_sensor_mipi_info(
-                               isp->inputs[asd->input_curr].camera);
-
-               if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED &&
-                   __get_mipi_port(isp, mipi_info->port) == port) {
-                       return asd;
-               }
-       }
-
-       return NULL;
-}
-
 /* interrupt handling function*/
 irqreturn_t atomisp_isr(int irq, void *dev)
 {
        struct atomisp_device *isp = (struct atomisp_device *)dev;
-       struct atomisp_sub_device *asd;
        struct atomisp_css_event eof_event;
        unsigned int irq_infos = 0;
        unsigned long flags;
-       unsigned int i;
        int err;
 
        spin_lock_irqsave(&isp->lock, flags);
@@ -520,18 +475,10 @@ irqreturn_t atomisp_isr(int irq, void *dev)
        if (!atomisp_streaming_count(isp))
                goto out_nowake;
 
-       for (i = 0; i < isp->num_of_streams; i++) {
-               asd = &isp->asd[i];
-
-               if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
-                       continue;
-               /*
-                * Current SOF only support one stream, so the SOF only valid
-                * either solely one stream is running
-                */
+       if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED) {
                if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) {
-                       atomic_inc(&asd->sof_count);
-                       atomisp_sof_event(asd);
+                       atomic_inc(&isp->asd.sof_count);
+                       atomisp_sof_event(&isp->asd);
 
                        /* If sequence_temp and sequence are the same
                         * there where no frames lost so we can increase
@@ -541,14 +488,14 @@ irqreturn_t atomisp_isr(int irq, void *dev)
                         * NOTE: There is assumption here that ISP will not
                         * start processing next frame from sensor before old
                         * one is completely done. */
-                       if (atomic_read(&asd->sequence) == atomic_read(
-                               &asd->sequence_temp))
-                               atomic_set(&asd->sequence_temp,
-                                          atomic_read(&asd->sof_count));
+                       if (atomic_read(&isp->asd.sequence) ==
+                           atomic_read(&isp->asd.sequence_temp))
+                               atomic_set(&isp->asd.sequence_temp,
+                                          atomic_read(&isp->asd.sof_count));
                }
                if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY)
-                       atomic_set(&asd->sequence,
-                                  atomic_read(&asd->sequence_temp));
+                       atomic_set(&isp->asd.sequence,
+                                  atomic_read(&isp->asd.sequence_temp));
        }
 
        if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) {
@@ -573,21 +520,10 @@ irqreturn_t atomisp_isr(int irq, void *dev)
        }
 
        if (irq_infos & IA_CSS_IRQ_INFO_ISYS_EVENTS_READY) {
-               while (ia_css_dequeue_isys_event(&eof_event.event) ==
-                      0) {
-                       /* EOF Event does not have the css_pipe returned */
-                       asd = __get_asd_from_port(isp, eof_event.event.port);
-                       if (!asd) {
-                               dev_err(isp->dev, "%s: ISYS event, but no subdev.event:%d",
-                                       __func__, eof_event.event.type);
-                               continue;
-                       }
-
-                       atomisp_eof_event(asd, eof_event.event.exp_id);
-                       dev_dbg_ratelimited(isp->dev,
-                                           "%s ISYS event: EOF exp_id %d, asd %d\n",
-                                           __func__, eof_event.event.exp_id,
-                                           asd->index);
+               while (ia_css_dequeue_isys_event(&eof_event.event) == 0) {
+                       atomisp_eof_event(&isp->asd, eof_event.event.exp_id);
+                       dev_dbg_ratelimited(isp->dev, "ISYS event: EOF exp_id %d\n",
+                                           eof_event.event.exp_id);
                }
 
                irq_infos &= ~IA_CSS_IRQ_INFO_ISYS_EVENTS_READY;
@@ -742,19 +678,6 @@ static void atomisp_recover_params_queue(struct atomisp_video_pipe *pipe)
        atomisp_handle_parameter_and_buffer(pipe);
 }
 
-enum atomisp_metadata_type
-atomisp_get_metadata_type(struct atomisp_sub_device *asd,
-                         enum ia_css_pipe_id pipe_id)
-{
-       if (!asd->continuous_mode->val)
-               return ATOMISP_MAIN_METADATA;
-
-       if (pipe_id == IA_CSS_PIPE_ID_CAPTURE) /* online capture pipe */
-               return ATOMISP_SEC_METADATA;
-       else
-               return ATOMISP_MAIN_METADATA;
-}
-
 void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
                      enum ia_css_buffer_type buf_type,
                      enum ia_css_pipe_id css_pipe_id,
@@ -826,7 +749,7 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
                if (error)
                        break;
 
-               md_type = atomisp_get_metadata_type(asd, css_pipe_id);
+               md_type = ATOMISP_MAIN_METADATA;
                list_for_each_entry_safe(md_iter, _md_buf_tmp,
                                         &asd->metadata_in_css[md_type], list) {
                        if (md_iter->metadata ==
@@ -883,15 +806,6 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
 
                pipe = vb_to_pipe(&frame->vb.vb2_buf);
 
-               /* FIXME:
-                * YUVPP doesn't set postview exp_id correctlly in SDV mode.
-                * This is a WORKAROUND to set exp_id. see HSDES-1503911606.
-                */
-               if (IS_BYT && buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME &&
-                   asd->continuous_mode->val && ATOMISP_USE_YUVPP(asd))
-                       frame->exp_id = (asd->postview_exp_id++) %
-                                       (ATOMISP_MAX_EXP_ID + 1);
-
                dev_dbg(isp->dev, "%s: vf frame with exp_id %d is ready\n",
                        __func__, frame->exp_id);
                if (asd->params.flash_state == ATOMISP_FLASH_ONGOING) {
@@ -908,18 +822,6 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
                                        __func__);
                }
                pipe->frame_config_id[frame->vb.vb2_buf.index] = frame->isp_config_id;
-               if (css_pipe_id == IA_CSS_PIPE_ID_CAPTURE &&
-                   asd->pending_capture_request > 0) {
-                       err = atomisp_css_offline_capture_configure(asd,
-                               asd->params.offline_parm.num_captures,
-                               asd->params.offline_parm.skip_frames,
-                               asd->params.offline_parm.offset);
-
-                       asd->pending_capture_request--;
-
-                       dev_dbg(isp->dev, "Trigger capture again for new buffer. err=%d\n",
-                               err);
-               }
                break;
        case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
        case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
@@ -934,15 +836,6 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
 
                pipe = vb_to_pipe(&frame->vb.vb2_buf);
 
-               /* FIXME:
-                * YUVPP doesn't set preview exp_id correctlly in ZSL mode.
-                * This is a WORKAROUND to set exp_id. see HSDES-1503911606.
-                */
-               if (IS_BYT && buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME &&
-                   asd->continuous_mode->val && ATOMISP_USE_YUVPP(asd))
-                       frame->exp_id = (asd->preview_exp_id++) %
-                                       (ATOMISP_MAX_EXP_ID + 1);
-
                dev_dbg(isp->dev, "%s: main frame with exp_id %d is ready\n",
                        __func__, frame->exp_id);
 
@@ -993,35 +886,6 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
 
                asd->params.last_frame_status = asd->frame_status[i];
 
-               if (asd->continuous_mode->val) {
-                       if (css_pipe_id == IA_CSS_PIPE_ID_PREVIEW ||
-                           css_pipe_id == IA_CSS_PIPE_ID_VIDEO) {
-                               asd->latest_preview_exp_id = frame->exp_id;
-                       } else if (css_pipe_id ==
-                                  IA_CSS_PIPE_ID_CAPTURE) {
-                               if (asd->run_mode->val ==
-                                   ATOMISP_RUN_MODE_VIDEO)
-                                       dev_dbg(isp->dev, "SDV capture raw buffer id: %u\n",
-                                               frame->exp_id);
-                               else
-                                       dev_dbg(isp->dev, "ZSL capture raw buffer id: %u\n",
-                                               frame->exp_id);
-                       }
-               }
-               /*
-                * Only after enabled the raw buffer lock
-                * and in continuous mode.
-                * in preview/video pipe, each buffer will
-                * be locked automatically, so record it here.
-                */
-               if (((css_pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
-                    (css_pipe_id == IA_CSS_PIPE_ID_VIDEO)) &&
-                   asd->enable_raw_buffer_lock->val &&
-                   asd->continuous_mode->val) {
-                       atomisp_set_raw_buffer_bitmap(asd, frame->exp_id);
-                       WARN_ON(frame->exp_id > ATOMISP_MAX_EXP_ID);
-               }
-
                if (asd->params.css_update_params_needed) {
                        atomisp_apply_css_parameters(asd,
                                                     &asd->params.css_param);
@@ -1080,43 +944,13 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error,
                atomisp_qbuffers_to_css(asd);
 }
 
-void atomisp_delayed_init_work(struct work_struct *work)
-{
-       struct atomisp_sub_device *asd = container_of(work,
-                                        struct atomisp_sub_device,
-                                        delayed_init_work);
-       /*
-        * to SOC camera, use yuvpp pipe and no support continuous mode.
-        */
-       if (!ATOMISP_USE_YUVPP(asd)) {
-               struct v4l2_event event = {0};
-               struct ia_css_stream *stream;
-
-               stream = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream;
-
-
-               if (ia_css_alloc_continuous_frame_remain(stream))
-                       return;
-
-               ia_css_update_continuous_frames(stream);
-
-               event.type = V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE;
-               v4l2_event_queue(asd->subdev.devnode, &event);
-       }
-
-       /* signal streamon after delayed init is done */
-       asd->delayed_init = ATOMISP_DELAYED_INIT_DONE;
-       complete(&asd->init_done);
-}
-
 static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
 {
        struct pci_dev *pdev = to_pci_dev(isp->dev);
        enum ia_css_pipe_id css_pipe_id;
-       bool stream_restart[MAX_STREAM_NUM] = {0};
-       bool depth_mode = false;
-       int i, ret, depth_cnt = 0;
+       bool stream_restart = false;
        unsigned long flags;
+       int ret;
 
        lockdep_assert_held(&isp->mutex);
 
@@ -1125,52 +959,37 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
 
        atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false);
 
-       BUG_ON(isp->num_of_streams > MAX_STREAM_NUM);
-
-       for (i = 0; i < isp->num_of_streams; i++) {
-               struct atomisp_sub_device *asd = &isp->asd[i];
-
-               if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED &&
-                   !asd->stream_prepared)
-                       continue;
-
-               depth_cnt++;
-
-               if (asd->delayed_init == ATOMISP_DELAYED_INIT_QUEUED)
-                       cancel_work_sync(&asd->delayed_init_work);
-
-               complete(&asd->init_done);
-               asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
-
-               stream_restart[asd->index] = true;
+       if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED ||
+           isp->asd.stream_prepared) {
+               stream_restart = true;
 
                spin_lock_irqsave(&isp->lock, flags);
-               asd->streaming = ATOMISP_DEVICE_STREAMING_STOPPING;
+               isp->asd.streaming = ATOMISP_DEVICE_STREAMING_STOPPING;
                spin_unlock_irqrestore(&isp->lock, flags);
 
                /* stream off sensor */
                ret = v4l2_subdev_call(
-                         isp->inputs[asd->input_curr].
+                         isp->inputs[isp->asd.input_curr].
                          camera, video, s_stream, 0);
                if (ret)
                        dev_warn(isp->dev,
                                 "can't stop streaming on sensor!\n");
 
-               atomisp_clear_css_buffer_counters(asd);
+               atomisp_clear_css_buffer_counters(&isp->asd);
 
-               css_pipe_id = atomisp_get_css_pipe_id(asd);
-               atomisp_css_stop(asd, css_pipe_id, true);
+               css_pipe_id = atomisp_get_css_pipe_id(&isp->asd);
+               atomisp_css_stop(&isp->asd, css_pipe_id, true);
 
                spin_lock_irqsave(&isp->lock, flags);
-               asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
+               isp->asd.streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
                spin_unlock_irqrestore(&isp->lock, flags);
 
-               asd->preview_exp_id = 1;
-               asd->postview_exp_id = 1;
+               isp->asd.preview_exp_id = 1;
+               isp->asd.postview_exp_id = 1;
                /* notify HAL the CSS reset */
                dev_dbg(isp->dev,
-                       "send reset event to %s\n", asd->subdev.devnode->name);
-               atomisp_reset_event(asd);
+                       "send reset event to %s\n", isp->asd.subdev.devnode->name);
+               atomisp_reset_event(&isp->asd);
        }
 
        /* clear irq */
@@ -1186,34 +1005,20 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
        atomisp_reset(isp);
        isp->isp_timeout = false;
 
-       if (!isp_timeout) {
-               for (i = 0; i < isp->num_of_streams; i++) {
-                       if (isp->asd[i].depth_mode->val)
-                               return;
-               }
-       }
-
-       for (i = 0; i < isp->num_of_streams; i++) {
-               struct atomisp_sub_device *asd = &isp->asd[i];
+       if (stream_restart) {
+               atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
 
-               if (!stream_restart[i])
-                       continue;
-
-               if (isp->inputs[asd->input_curr].type != FILE_INPUT)
-                       atomisp_css_input_set_mode(asd,
-                                                  IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
-
-               css_pipe_id = atomisp_get_css_pipe_id(asd);
-               if (atomisp_css_start(asd, css_pipe_id, true)) {
+               css_pipe_id = atomisp_get_css_pipe_id(&isp->asd);
+               if (atomisp_css_start(&isp->asd, css_pipe_id, true)) {
                        dev_warn(isp->dev,
                                 "start SP failed, so do not set streaming to be enable!\n");
                } else {
                        spin_lock_irqsave(&isp->lock, flags);
-                       asd->streaming = ATOMISP_DEVICE_STREAMING_ENABLED;
+                       isp->asd.streaming = ATOMISP_DEVICE_STREAMING_ENABLED;
                        spin_unlock_irqrestore(&isp->lock, flags);
                }
 
-               atomisp_csi2_configure(asd);
+               atomisp_csi2_configure(&isp->asd);
        }
 
        atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF,
@@ -1222,51 +1027,25 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
        if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, true) < 0)
                dev_dbg(isp->dev, "DFS auto failed while recovering!\n");
 
-       for (i = 0; i < isp->num_of_streams; i++) {
-               struct atomisp_sub_device *asd;
-
-               asd = &isp->asd[i];
-
-               if (!stream_restart[i])
-                       continue;
-
-               if (asd->continuous_mode->val &&
-                   asd->delayed_init == ATOMISP_DELAYED_INIT_NOT_QUEUED) {
-                       reinit_completion(&asd->init_done);
-                       asd->delayed_init = ATOMISP_DELAYED_INIT_QUEUED;
-                       queue_work(asd->delayed_init_workq,
-                                  &asd->delayed_init_work);
-               }
+       if (stream_restart) {
                /*
                 * dequeueing buffers is not needed. CSS will recycle
                 * buffers that it has.
                 */
-               atomisp_flush_bufs_and_wakeup(asd);
+               atomisp_flush_bufs_and_wakeup(&isp->asd);
 
                /* Requeue unprocessed per-frame parameters. */
-               atomisp_recover_params_queue(&asd->video_out_capture);
-               atomisp_recover_params_queue(&asd->video_out_preview);
-               atomisp_recover_params_queue(&asd->video_out_video_capture);
-
-               if ((asd->depth_mode->val) &&
-                   (depth_cnt == ATOMISP_DEPTH_SENSOR_STREAMON_COUNT)) {
-                       depth_mode = true;
-                       continue;
-               }
+               atomisp_recover_params_queue(&isp->asd.video_out_capture);
+               atomisp_recover_params_queue(&isp->asd.video_out_preview);
+               atomisp_recover_params_queue(&isp->asd.video_out_video_capture);
 
                ret = v4l2_subdev_call(
-                         isp->inputs[asd->input_curr].camera, video,
+                         isp->inputs[isp->asd.input_curr].camera, video,
                          s_stream, 1);
                if (ret)
                        dev_warn(isp->dev,
                                 "can't start streaming on sensor!\n");
        }
-
-       if (depth_mode) {
-               if (atomisp_stream_on_master_slave_sensor(isp, true))
-                       dev_warn(isp->dev,
-                                "master slave sensor stream on failed!\n");
-       }
 }
 
 void atomisp_assert_recovery_work(struct work_struct *work)
@@ -1321,10 +1100,6 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr)
 {
        struct atomisp_device *isp = isp_ptr;
        unsigned long flags;
-       bool frame_done_found[MAX_STREAM_NUM] = {0};
-       bool css_pipe_done[MAX_STREAM_NUM] = {0};
-       unsigned int i;
-       struct atomisp_sub_device *asd;
 
        dev_dbg(isp->dev, ">%s\n", __func__);
 
@@ -1363,15 +1138,11 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr)
         * time, instead, dequue one and process one, then another
         */
        mutex_lock(&isp->mutex);
-       if (atomisp_css_isr_thread(isp, frame_done_found, css_pipe_done))
+       if (atomisp_css_isr_thread(isp))
                goto out;
 
-       for (i = 0; i < isp->num_of_streams; i++) {
-               asd = &isp->asd[i];
-               if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
-                       continue;
-               atomisp_setup_flash(asd);
-       }
+       if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED)
+               atomisp_setup_flash(&isp->asd);
 out:
        mutex_unlock(&isp->mutex);
        dev_dbg(isp->dev, "<%s\n", __func__);
@@ -1779,11 +1550,6 @@ int atomisp_formats(struct atomisp_sub_device *asd, int flag,
 void atomisp_free_internal_buffers(struct atomisp_sub_device *asd)
 {
        atomisp_free_css_parameters(&asd->params.css_param);
-
-       if (asd->raw_output_frame) {
-               ia_css_frame_free(asd->raw_output_frame);
-               asd->raw_output_frame = NULL;
-       }
 }
 
 static void atomisp_update_grid_info(struct atomisp_sub_device *asd,
@@ -2023,8 +1789,6 @@ int atomisp_get_dvs2_bq_resolutions(struct atomisp_sub_device *asd,
                                    struct atomisp_dvs2_bq_resolutions *bq_res)
 {
        struct ia_css_pipe_config *pipe_cfg = NULL;
-       struct ia_css_stream_config *stream_cfg = NULL;
-       struct ia_css_stream_input_config *input_config = NULL;
 
        struct ia_css_stream *stream =
                    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream;
@@ -2035,9 +1799,6 @@ int atomisp_get_dvs2_bq_resolutions(struct atomisp_sub_device *asd,
 
        pipe_cfg = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
                   .pipe_configs[IA_CSS_PIPE_ID_VIDEO];
-       stream_cfg = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
-                    .stream_config;
-       input_config = &stream_cfg->input_config;
 
        if (!bq_res)
                return -EINVAL;
@@ -2049,132 +1810,27 @@ int atomisp_get_dvs2_bq_resolutions(struct atomisp_sub_device *asd,
        bq_res->envelope_bq.width_bq = 0;
        bq_res->envelope_bq.height_bq = 0;
        /* the GDC input resolution */
-       if (!asd->continuous_mode->val) {
-               bq_res->source_bq.width_bq = bq_res->output_bq.width_bq +
-                                            pipe_cfg->dvs_envelope.width / 2;
-               bq_res->source_bq.height_bq = bq_res->output_bq.height_bq +
-                                             pipe_cfg->dvs_envelope.height / 2;
-               /*
-                * Bad pixels caused by spatial filter processing
-                * ISP filter resolution should be given by CSS/FW, but for now
-                * there is not such API to query, and it is fixed value, so
-                * hardcoded here.
-                */
-               bq_res->ispfilter_bq.width_bq = 12 / 2;
-               bq_res->ispfilter_bq.height_bq = 12 / 2;
-               /* spatial filter shift, always 4 pixels */
-               bq_res->gdc_shift_bq.width_bq = 4 / 2;
-               bq_res->gdc_shift_bq.height_bq = 4 / 2;
-
-               if (asd->params.video_dis_en) {
-                       bq_res->envelope_bq.width_bq = pipe_cfg->dvs_envelope.width
-                                                      / 2 - bq_res->ispfilter_bq.width_bq;
-                       bq_res->envelope_bq.height_bq = pipe_cfg->dvs_envelope.height
-                                                       / 2 - bq_res->ispfilter_bq.height_bq;
-               }
-       } else {
-               unsigned int w_padding;
-               unsigned int gdc_effective_input = 0;
-
-               /* For GDC:
-                * gdc_effective_input = effective_input + envelope
-                *
-                * From the comment and formula in BZ1786,
-                * we see the source_bq should be:
-                * effective_input / bayer_ds_ratio
-                */
-               bq_res->source_bq.width_bq =
-                   (input_config->effective_res.width *
-                    pipe_cfg->bayer_ds_out_res.width /
-                    input_config->effective_res.width + 1) / 2;
-               bq_res->source_bq.height_bq =
-                   (input_config->effective_res.height *
-                    pipe_cfg->bayer_ds_out_res.height /
-                    input_config->effective_res.height + 1) / 2;
-
-               if (!asd->params.video_dis_en) {
-                       /*
-                        * We adjust the ispfilter_bq to:
-                        * ispfilter_bq = 128/BDS
-                        * we still need firmware team to provide an offical
-                        * formula for SDV.
-                        */
-                       bq_res->ispfilter_bq.width_bq = 128 *
-                                                       pipe_cfg->bayer_ds_out_res.width /
-                                                       input_config->effective_res.width / 2;
-                       bq_res->ispfilter_bq.height_bq = 128 *
-                                                        pipe_cfg->bayer_ds_out_res.width /
-                                                        input_config->effective_res.width / 2;
-
-                       if (IS_HWREVISION(asd->isp, ATOMISP_HW_REVISION_ISP2401)) {
-                               /* No additional left padding for ISYS2401 */
-                               bq_res->gdc_shift_bq.width_bq = 4 / 2;
-                               bq_res->gdc_shift_bq.height_bq = 4 / 2;
-                       } else {
-                               /*
-                                * For the w_padding and gdc_shift_bq cacluation
-                                * Please see the BZ 1786 and 4358 for more info.
-                                * Just test that this formula can work now,
-                                * but we still have no offical formula.
-                                *
-                                * w_padding = ceiling(gdc_effective_input
-                                *             /128, 1) * 128 - effective_width
-                                * gdc_shift_bq = w_padding/BDS/2 + ispfilter_bq/2
-                                */
-                               gdc_effective_input =
-                                   input_config->effective_res.width +
-                                   pipe_cfg->dvs_envelope.width;
-                               w_padding = roundup(gdc_effective_input, 128) -
-                                           input_config->effective_res.width;
-                               w_padding = w_padding *
-                                           pipe_cfg->bayer_ds_out_res.width /
-                                           input_config->effective_res.width + 1;
-                               w_padding = roundup(w_padding / 2, 1);
-
-                               bq_res->gdc_shift_bq.width_bq = bq_res->ispfilter_bq.width_bq / 2
-                                                               + w_padding;
-                               bq_res->gdc_shift_bq.height_bq = 4 / 2;
-                       }
-               } else {
-                       unsigned int dvs_w, dvs_h, dvs_w_max, dvs_h_max;
-
-                       bq_res->ispfilter_bq.width_bq = 8 / 2;
-                       bq_res->ispfilter_bq.height_bq = 8 / 2;
-
-                       if (IS_HWREVISION(asd->isp, ATOMISP_HW_REVISION_ISP2401)) {
-                               /* No additional left padding for ISYS2401 */
-                               bq_res->gdc_shift_bq.width_bq = 4 / 2;
-                               bq_res->gdc_shift_bq.height_bq = 4 / 2;
-                       } else {
-                               w_padding =
-                                   roundup(input_config->effective_res.width, 128) -
-                                   input_config->effective_res.width;
-                               if (w_padding < 12)
-                                       w_padding = 12;
-                               bq_res->gdc_shift_bq.width_bq = 4 / 2 +
-                                                               ((w_padding - 12) *
-                                                                pipe_cfg->bayer_ds_out_res.width /
-                                                                input_config->effective_res.width + 1) / 2;
-                               bq_res->gdc_shift_bq.height_bq = 4 / 2;
-                       }
+       bq_res->source_bq.width_bq = bq_res->output_bq.width_bq +
+                                    pipe_cfg->dvs_envelope.width / 2;
+       bq_res->source_bq.height_bq = bq_res->output_bq.height_bq +
+                                     pipe_cfg->dvs_envelope.height / 2;
+       /*
+        * Bad pixels caused by spatial filter processing
+        * ISP filter resolution should be given by CSS/FW, but for now
+        * there is not such API to query, and it is fixed value, so
+        * hardcoded here.
+        */
+       bq_res->ispfilter_bq.width_bq = 12 / 2;
+       bq_res->ispfilter_bq.height_bq = 12 / 2;
+       /* spatial filter shift, always 4 pixels */
+       bq_res->gdc_shift_bq.width_bq = 4 / 2;
+       bq_res->gdc_shift_bq.height_bq = 4 / 2;
 
-                       dvs_w = pipe_cfg->bayer_ds_out_res.width -
-                               pipe_cfg->output_info[0].res.width;
-                       dvs_h = pipe_cfg->bayer_ds_out_res.height -
-                               pipe_cfg->output_info[0].res.height;
-                       dvs_w_max = rounddown(
-                                       pipe_cfg->output_info[0].res.width / 5,
-                                       ATOM_ISP_STEP_WIDTH);
-                       dvs_h_max = rounddown(
-                                       pipe_cfg->output_info[0].res.height / 5,
-                                       ATOM_ISP_STEP_HEIGHT);
-                       bq_res->envelope_bq.width_bq =
-                           min((dvs_w / 2), (dvs_w_max / 2)) -
-                           bq_res->ispfilter_bq.width_bq;
-                       bq_res->envelope_bq.height_bq =
-                           min((dvs_h / 2), (dvs_h_max / 2)) -
-                           bq_res->ispfilter_bq.height_bq;
-               }
+       if (asd->params.video_dis_en) {
+               bq_res->envelope_bq.width_bq = pipe_cfg->dvs_envelope.width / 2 -
+                                              bq_res->ispfilter_bq.width_bq;
+               bq_res->envelope_bq.height_bq = pipe_cfg->dvs_envelope.height / 2 -
+                                               bq_res->ispfilter_bq.height_bq;
        }
 
        dev_dbg(asd->isp->dev,
@@ -3640,10 +3296,8 @@ int atomisp_set_parameters(struct video_device *vdev,
                return -EINVAL;
        }
 
-       dev_dbg(asd->isp->dev,
-               "%s: set parameter(per_frame_setting %d) for asd%d with isp_config_id %d of %s\n",
-               __func__, arg->per_frame_setting, asd->index,
-               arg->isp_config_id, vdev->name);
+       dev_dbg(asd->isp->dev, "set parameter(per_frame_setting %d) isp_config_id %d of %s\n",
+               arg->per_frame_setting, arg->isp_config_id, vdev->name);
 
        if (IS_ISP2401) {
                if (atomisp_is_vf_pipe(pipe) && arg->per_frame_setting) {
@@ -3751,28 +3405,8 @@ int atomisp_param(struct atomisp_sub_device *asd, int flag,
                }
 
                /* update dvs envelop info */
-               if (!asd->continuous_mode->val) {
-                       config->dvs_envelop.width = vp_cfg->dvs_envelope.width;
-                       config->dvs_envelop.height =
-                           vp_cfg->dvs_envelope.height;
-               } else {
-                       unsigned int dvs_w, dvs_h, dvs_w_max, dvs_h_max;
-
-                       dvs_w = vp_cfg->bayer_ds_out_res.width -
-                               vp_cfg->output_info[0].res.width;
-                       dvs_h = vp_cfg->bayer_ds_out_res.height -
-                               vp_cfg->output_info[0].res.height;
-                       dvs_w_max = rounddown(
-                                       vp_cfg->output_info[0].res.width / 5,
-                                       ATOM_ISP_STEP_WIDTH);
-                       dvs_h_max = rounddown(
-                                       vp_cfg->output_info[0].res.height / 5,
-                                       ATOM_ISP_STEP_HEIGHT);
-
-                       config->dvs_envelop.width = min(dvs_w, dvs_w_max);
-                       config->dvs_envelop.height = min(dvs_h, dvs_h_max);
-               }
-
+               config->dvs_envelop.width = vp_cfg->dvs_envelope.width;
+               config->dvs_envelop.height = vp_cfg->dvs_envelope.height;
                return 0;
        }
 
@@ -4254,16 +3888,12 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
        struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
        struct v4l2_subdev_pad_config pad_cfg;
        struct v4l2_subdev_state pad_state = {
-               .pads = &pad_cfg
-               };
+               .pads = &pad_cfg,
+       };
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
-
-       struct v4l2_mbus_framefmt *snr_mbus_fmt = &format.format;
        const struct atomisp_format_bridge *fmt;
-       struct atomisp_input_stream_info *stream_info =
-           (struct atomisp_input_stream_info *)snr_mbus_fmt->reserved;
        int ret;
 
        if (!asd) {
@@ -4284,14 +3914,15 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
        if (f->width <= 0 || f->height <= 0)
                return -EINVAL;
 
-       snr_mbus_fmt->code = fmt->mbus_code;
-       snr_mbus_fmt->width = f->width;
-       snr_mbus_fmt->height = f->height;
+       format.format.code = fmt->mbus_code;
+       format.format.width = f->width;
+       format.format.height = f->height;
 
-       __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, stream_info);
+       __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL,
+                                  (struct atomisp_input_stream_info *)format.format.reserved);
 
        dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n",
-               snr_mbus_fmt->width, snr_mbus_fmt->height);
+               format.format.width, format.format.height);
 
        ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
                               pad, set_fmt, &pad_state, &format);
@@ -4299,12 +3930,12 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
                return ret;
 
        dev_dbg(isp->dev, "try_mbus_fmt: got %ux%u\n",
-               snr_mbus_fmt->width, snr_mbus_fmt->height);
+               format.format.width, format.format.height);
 
-       fmt = atomisp_get_format_bridge_from_mbus(snr_mbus_fmt->code);
+       fmt = atomisp_get_format_bridge_from_mbus(format.format.code);
        if (!fmt) {
                dev_err(isp->dev, "unknown sensor format 0x%8.8x\n",
-                       snr_mbus_fmt->code);
+                       format.format.code);
                return -EINVAL;
        }
 
@@ -4318,15 +3949,15 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
         */
        if (f->pixelformat == V4L2_PIX_FMT_JPEG ||
            f->pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) {
-               f->width = snr_mbus_fmt->width;
-               f->height = snr_mbus_fmt->height;
+               f->width = format.format.width;
+               f->height = format.format.height;
                return 0;
        }
 
-       if (!res_overflow || (snr_mbus_fmt->width < f->width &&
-                             snr_mbus_fmt->height < f->height)) {
-               f->width = snr_mbus_fmt->width;
-               f->height = snr_mbus_fmt->height;
+       if (!res_overflow || (format.format.width < f->width &&
+                             format.format.height < f->height)) {
+               f->width = format.format.width;
+               f->height = format.format.height;
                /* Set the flag when resolution requested is
                 * beyond the max value supported by sensor
                 */
@@ -4439,43 +4070,6 @@ static inline int atomisp_set_sensor_mipi_to_isp(
        return 0;
 }
 
-static int __enable_continuous_mode(struct atomisp_sub_device *asd,
-                                   bool enable)
-{
-       struct atomisp_device *isp = asd->isp;
-
-       dev_dbg(isp->dev,
-               "continuous mode %d, raw buffers %d, stop preview %d\n",
-               enable, asd->continuous_raw_buffer_size->val,
-               !asd->continuous_viewfinder->val);
-
-       if (!IS_ISP2401)
-               atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_PRIMARY);
-       else
-               atomisp_update_capture_mode(asd);
-
-       /* in case of ANR, force capture pipe to offline mode */
-       atomisp_css_capture_enable_online(asd, ATOMISP_INPUT_STREAM_GENERAL,
-                                         asd->params.low_light ? false : !enable);
-       atomisp_css_preview_enable_online(asd, ATOMISP_INPUT_STREAM_GENERAL,
-                                         !enable);
-       atomisp_css_enable_continuous(asd, enable);
-       atomisp_css_enable_cvf(asd, asd->continuous_viewfinder->val);
-
-       atomisp_css_continuous_set_num_raw_frames(asd,
-               asd->continuous_raw_buffer_size->val);
-
-       if (!enable) {
-               atomisp_css_enable_raw_binning(asd, false);
-               atomisp_css_input_set_two_pixels_per_clock(asd, false);
-       }
-
-       if (isp->inputs[asd->input_curr].type != FILE_INPUT)
-               atomisp_css_input_set_mode(asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
-
-       return atomisp_update_run_mode(asd);
-}
-
 static int configure_pp_input_nop(struct atomisp_sub_device *asd,
                                  unsigned int width, unsigned int height)
 {
@@ -4517,17 +4111,6 @@ static int css_input_resolution_changed(struct atomisp_sub_device *asd,
        else
                atomisp_css_input_set_two_pixels_per_clock(asd, true);
 
-       if (asd->continuous_mode->val) {
-               /* Note for all checks: ffmt includes pad_w+pad_h */
-               if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO ||
-                   (ffmt->width >= 2048 || ffmt->height >= 1536)) {
-                       /*
-                        * For preview pipe, enable only if resolution
-                        * is >= 3M for ISP2400.
-                        */
-                       atomisp_css_enable_raw_binning(asd, true);
-               }
-       }
        /*
         * If sensor input changed, which means metadata resolution changed
         * together. Release all metadata buffers here to let it re-allocated
@@ -4551,7 +4134,6 @@ static int css_input_resolution_changed(struct atomisp_sub_device *asd,
 
 static int atomisp_set_fmt_to_isp(struct video_device *vdev,
                                  struct ia_css_frame_info *output_info,
-                                 struct ia_css_frame_info *raw_output_info,
                                  struct v4l2_pix_format *pix,
                                  unsigned int source_pad)
 {
@@ -4592,8 +4174,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
        if (!format)
                return -EINVAL;
 
-       if (isp->inputs[asd->input_curr].type != TEST_PATTERN &&
-           isp->inputs[asd->input_curr].type != FILE_INPUT) {
+       if (isp->inputs[asd->input_curr].type != TEST_PATTERN) {
                mipi_info = atomisp_to_sensor_mipi_info(
                                isp->inputs[asd->input_curr].camera);
                if (!mipi_info) {
@@ -4622,8 +4203,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
         * Configure viewfinder also when vfpp is disabled: the
         * CSS still requires viewfinder configuration.
         */
-       if (asd->fmt_auto->val ||
-           asd->vfpp->val != ATOMISP_VFPP_ENABLE) {
+       {
                struct v4l2_rect vf_size = {0};
                struct v4l2_mbus_framefmt vf_ffmt = {0};
 
@@ -4670,12 +4250,6 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
                }
        }
 
-       if (asd->continuous_mode->val) {
-               ret = __enable_continuous_mode(asd, true);
-               if (ret)
-                       return -EINVAL;
-       }
-
        atomisp_css_input_set_mode(asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
 
        for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
@@ -4691,49 +4265,15 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
                get_frame_info = atomisp_css_video_get_output_frame_info;
                pipe_id = IA_CSS_PIPE_ID_VIDEO;
        } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
-               if (!asd->continuous_mode->val) {
-                       configure_output = atomisp_css_video_configure_output;
-                       get_frame_info =
-                           atomisp_css_video_get_output_frame_info;
-                       pipe_id = IA_CSS_PIPE_ID_VIDEO;
-               } else {
-                       if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW ||
-                           source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) {
-                               configure_output =
-                                   atomisp_css_video_configure_output;
-                               get_frame_info =
-                                   atomisp_css_video_get_output_frame_info;
-                               configure_pp_input =
-                                   atomisp_css_video_configure_pp_input;
-                               pipe_id = IA_CSS_PIPE_ID_VIDEO;
-                       } else {
-                               configure_output =
-                                   atomisp_css_capture_configure_output;
-                               get_frame_info =
-                                   atomisp_css_capture_get_output_frame_info;
-                               configure_pp_input =
-                                   atomisp_css_capture_configure_pp_input;
-                               pipe_id = IA_CSS_PIPE_ID_CAPTURE;
-
-                               atomisp_update_capture_mode(asd);
-                               atomisp_css_capture_enable_online(asd,
-                                                                 ATOMISP_INPUT_STREAM_GENERAL,
-                                                                 false);
-                       }
-               }
+               configure_output = atomisp_css_video_configure_output;
+               get_frame_info = atomisp_css_video_get_output_frame_info;
+               pipe_id = IA_CSS_PIPE_ID_VIDEO;
        } else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) {
                configure_output = atomisp_css_preview_configure_output;
                get_frame_info = atomisp_css_preview_get_output_frame_info;
                configure_pp_input = atomisp_css_preview_configure_pp_input;
                pipe_id = IA_CSS_PIPE_ID_PREVIEW;
        } else {
-               /* CSS doesn't support low light mode on SOC cameras, so disable
-                * it. FIXME: if this is done elsewhere, it gives corrupted
-                * colors into thumbnail image.
-                */
-               if (isp->inputs[asd->input_curr].type == SOC_CAMERA)
-                       asd->params.low_light = false;
-
                if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
                        atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_RAW);
                        atomisp_css_enable_dz(asd, false);
@@ -4741,38 +4281,22 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
                        atomisp_update_capture_mode(asd);
                }
 
-               if (!asd->continuous_mode->val)
-                       /* in case of ANR, force capture pipe to offline mode */
-                       atomisp_css_capture_enable_online(asd, ATOMISP_INPUT_STREAM_GENERAL,
-                                                         asd->params.low_light ?
-                                                         false : asd->params.online_process);
+               /* in case of ANR, force capture pipe to offline mode */
+               atomisp_css_capture_enable_online(asd, ATOMISP_INPUT_STREAM_GENERAL,
+                                                 !asd->params.low_light);
 
                configure_output = atomisp_css_capture_configure_output;
                get_frame_info = atomisp_css_capture_get_output_frame_info;
                configure_pp_input = atomisp_css_capture_configure_pp_input;
                pipe_id = IA_CSS_PIPE_ID_CAPTURE;
 
-               if (!asd->params.online_process &&
-                   !asd->continuous_mode->val) {
-                       ret = atomisp_css_capture_get_output_raw_frame_info(asd,
-                               raw_output_info);
-                       if (ret)
-                               return ret;
-               }
-               if (!asd->continuous_mode->val && asd->run_mode->val
-                   != ATOMISP_RUN_MODE_STILL_CAPTURE) {
+               if (asd->run_mode->val != ATOMISP_RUN_MODE_STILL_CAPTURE) {
                        dev_err(isp->dev,
                                "Need to set the running mode first\n");
                        asd->run_mode->val = ATOMISP_RUN_MODE_STILL_CAPTURE;
                }
        }
 
-       /*
-        * to SOC camera, use yuvpp pipe.
-        */
-       if (ATOMISP_USE_YUVPP(asd))
-               pipe_id = IA_CSS_PIPE_ID_YUVPP;
-
        if (asd->copy_mode)
                ret = atomisp_css_copy_configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL,
                                                        pix->width, pix->height,
@@ -4810,16 +4334,6 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev,
        }
 
        atomisp_update_grid_info(asd, pipe_id, source_pad);
-
-       /* Free the raw_dump buffer first */
-       ia_css_frame_free(asd->raw_output_frame);
-       asd->raw_output_frame = NULL;
-
-       if (!asd->continuous_mode->val && !asd->params.online_process &&
-           ia_css_frame_allocate_from_info(&asd->raw_output_frame,
-                   raw_output_info))
-               return -ENOMEM;
-
        return 0;
 }
 
@@ -4827,12 +4341,6 @@ static void atomisp_get_dis_envelop(struct atomisp_sub_device *asd,
                                    unsigned int width, unsigned int height,
                                    unsigned int *dvs_env_w, unsigned int *dvs_env_h)
 {
-       struct atomisp_device *isp = asd->isp;
-
-       /* if subdev type is SOC camera,we do not need to set DVS */
-       if (isp->inputs[asd->input_curr].type == SOC_CAMERA)
-               asd->params.video_dis_en = false;
-
        if (asd->params.video_dis_en &&
            asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
                /* envelope is 20% of the output resolution */
@@ -4849,7 +4357,7 @@ static void atomisp_get_dis_envelop(struct atomisp_sub_device *asd,
 }
 
 static void atomisp_check_copy_mode(struct atomisp_sub_device *asd,
-                                   int source_pad, struct v4l2_pix_format *f)
+                                   int source_pad, const struct v4l2_pix_format *f)
 {
        struct v4l2_mbus_framefmt *sink, *src;
 
@@ -4872,8 +4380,7 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd,
        dev_dbg(asd->isp->dev, "copy_mode: %d\n", asd->copy_mode);
 }
 
-static int atomisp_set_fmt_to_snr(struct video_device *vdev,
-                                 struct v4l2_pix_format *f, unsigned int pixelformat,
+static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_pix_format *f,
                                  unsigned int padding_w, unsigned int padding_h,
                                  unsigned int dvs_env_w, unsigned int dvs_env_h)
 {
@@ -4882,8 +4389,8 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev,
        const struct atomisp_format_bridge *format;
        struct v4l2_subdev_pad_config pad_cfg;
        struct v4l2_subdev_state pad_state = {
-               .pads = &pad_cfg
-               };
+               .pads = &pad_cfg,
+       };
        struct v4l2_subdev_format vformat = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
@@ -4906,7 +4413,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev,
 
        v4l2_fh_init(&fh.vfh, vdev);
 
-       format = atomisp_get_format_bridge(pixelformat);
+       format = atomisp_get_format_bridge(f->pixelformat);
        if (!format)
                return -EINVAL;
 
@@ -4981,13 +4488,9 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
        struct atomisp_sub_device *asd = pipe->asd;
        const struct atomisp_format_bridge *format_bridge;
        const struct atomisp_format_bridge *snr_format_bridge;
-       struct ia_css_frame_info output_info, raw_output_info;
-       struct v4l2_pix_format snr_fmt;
-       struct v4l2_pix_format backup_fmt, s_fmt;
+       struct ia_css_frame_info output_info;
        unsigned int dvs_env_w = 0, dvs_env_h = 0;
        unsigned int padding_w = pad_w, padding_h = pad_h;
-       bool res_overflow = false, crop_needs_override = false;
-       struct v4l2_mbus_framefmt *isp_sink_fmt;
        struct v4l2_mbus_framefmt isp_source_fmt = {0};
        struct v4l2_subdev_format vformat = {
                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -5005,9 +4508,8 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
                return -EINVAL;
 
        dev_dbg(isp->dev,
-               "setting resolution %ux%u on pad %u for asd%d, bytesperline %u\n",
-               f->fmt.pix.width, f->fmt.pix.height, source_pad,
-               asd->index, f->fmt.pix.bytesperline);
+               "setting resolution %ux%u on pad %u bytesperline %u\n",
+               f->fmt.pix.width, f->fmt.pix.height, source_pad, f->fmt.pix.bytesperline);
 
        v4l2_fh_init(&fh.vfh, vdev);
 
@@ -5042,105 +4544,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
        f->fmt.pix.width = vformat.format.width - padding_w;
        f->fmt.pix.height = vformat.format.height - padding_h;
 
-       snr_fmt = f->fmt.pix;
-       backup_fmt = snr_fmt;
-
-       /**********************************************************************/
-
-       if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VF ||
-           (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
-            && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)) {
-               if (asd->fmt_auto->val) {
-                       struct v4l2_rect *capture_comp;
-                       struct v4l2_rect r = {0};
-
-                       r.width = f->fmt.pix.width;
-                       r.height = f->fmt.pix.height;
-
-                       if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
-                               capture_comp = atomisp_subdev_get_rect(
-                                                  &asd->subdev, NULL,
-                                                  V4L2_SUBDEV_FORMAT_ACTIVE,
-                                                  ATOMISP_SUBDEV_PAD_SOURCE_VIDEO,
-                                                  V4L2_SEL_TGT_COMPOSE);
-                       else
-                               capture_comp = atomisp_subdev_get_rect(
-                                                  &asd->subdev, NULL,
-                                                  V4L2_SUBDEV_FORMAT_ACTIVE,
-                                                  ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
-                                                  V4L2_SEL_TGT_COMPOSE);
-
-                       if (capture_comp->width < r.width
-                           || capture_comp->height < r.height) {
-                               r.width = capture_comp->width;
-                               r.height = capture_comp->height;
-                       }
-
-                       atomisp_subdev_set_selection(
-                           &asd->subdev, fh.state,
-                           V4L2_SUBDEV_FORMAT_ACTIVE, source_pad,
-                           V4L2_SEL_TGT_COMPOSE, 0, &r);
-
-                       f->fmt.pix.width = r.width;
-                       f->fmt.pix.height = r.height;
-               }
-
-               if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) {
-                       atomisp_css_video_configure_viewfinder(asd,
-                                                              f->fmt.pix.width, f->fmt.pix.height,
-                                                              format_bridge->planar ? f->fmt.pix.bytesperline
-                                                              : f->fmt.pix.bytesperline * 8
-                                                              / format_bridge->depth,  format_bridge->sh_fmt);
-                       atomisp_css_video_get_viewfinder_frame_info(asd,
-                               &output_info);
-                       asd->copy_mode = false;
-               } else {
-                       atomisp_css_capture_configure_viewfinder(asd,
-                               f->fmt.pix.width, f->fmt.pix.height,
-                               format_bridge->planar ? f->fmt.pix.bytesperline
-                               : f->fmt.pix.bytesperline * 8
-                               / format_bridge->depth, format_bridge->sh_fmt);
-                       atomisp_css_capture_get_viewfinder_frame_info(asd,
-                               &output_info);
-                       asd->copy_mode = false;
-               }
-
-               goto done;
-       }
-       /*
-        * Check whether main resolution configured smaller
-        * than snapshot resolution. If so, force main resolution
-        * to be the same as snapshot resolution
-        */
-       if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE) {
-               struct v4l2_rect *r;
-
-               r = atomisp_subdev_get_rect(
-                       &asd->subdev, NULL,
-                       V4L2_SUBDEV_FORMAT_ACTIVE,
-                       ATOMISP_SUBDEV_PAD_SOURCE_VF, V4L2_SEL_TGT_COMPOSE);
-
-               if (r->width && r->height
-                   && (r->width > f->fmt.pix.width
-                       || r->height > f->fmt.pix.height))
-                       dev_warn(isp->dev,
-                                "Main Resolution config smaller then Vf Resolution. Force to be equal with Vf Resolution.");
-       }
-
-       /* Pipeline configuration done through subdevs. Bail out now. */
-       if (!asd->fmt_auto->val)
-               goto set_fmt_to_isp;
-
-       /* get sensor resolution and format */
-       ret = atomisp_try_fmt(vdev, &snr_fmt, &res_overflow);
-       if (ret) {
-               dev_warn(isp->dev, "Try format failed with error %d\n", ret);
-               return ret;
-       }
-       f->fmt.pix.width = snr_fmt.width;
-       f->fmt.pix.height = snr_fmt.height;
-
-       snr_format_bridge = atomisp_get_format_bridge(snr_fmt.pixelformat);
+       snr_format_bridge = atomisp_get_format_bridge_from_mbus(vformat.format.code);
        if (!snr_format_bridge) {
                dev_warn(isp->dev, "Can't find bridge format\n");
                return -EINVAL;
@@ -5151,10 +4555,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
                                ATOMISP_SUBDEV_PAD_SINK)->code =
                                    snr_format_bridge->mbus_code;
 
-       isp_sink_fmt = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
-                                               V4L2_SUBDEV_FORMAT_ACTIVE,
-                                               ATOMISP_SUBDEV_PAD_SINK);
-
        isp_source_fmt.code = format_bridge->mbus_code;
        atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
                                V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -5165,80 +4565,22 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
                padding_h = 0;
        }
 
-       /* construct resolution supported by isp */
-       if (res_overflow && !asd->continuous_mode->val) {
-               f->fmt.pix.width = rounddown(
-                                      clamp_t(u32, f->fmt.pix.width - padding_w,
-                                              ATOM_ISP_MIN_WIDTH,
-                                              ATOM_ISP_MAX_WIDTH), ATOM_ISP_STEP_WIDTH);
-               f->fmt.pix.height = rounddown(
-                                       clamp_t(u32, f->fmt.pix.height - padding_h,
-                                               ATOM_ISP_MIN_HEIGHT,
-                                               ATOM_ISP_MAX_HEIGHT), ATOM_ISP_STEP_HEIGHT);
-       }
-
        atomisp_get_dis_envelop(asd, f->fmt.pix.width, f->fmt.pix.height,
                                &dvs_env_w, &dvs_env_h);
 
-       if (asd->continuous_mode->val) {
-               struct v4l2_rect *r;
+       asd->capture_pad = source_pad;
 
-               r = atomisp_subdev_get_rect(
-                       &asd->subdev, NULL,
-                       V4L2_SUBDEV_FORMAT_ACTIVE,
-                       ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
-                       V4L2_SEL_TGT_COMPOSE);
-               /*
-                * The ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE should get resolutions
-                * properly set otherwise, it should not be the capture_pad.
-                */
-               if (r->width && r->height)
-                       asd->capture_pad = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE;
-               else
-                       asd->capture_pad = source_pad;
-       } else {
-               asd->capture_pad = source_pad;
+       ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix,
+                                    padding_w, padding_h, dvs_env_w, dvs_env_h);
+       if (ret) {
+               dev_warn(isp->dev,
+                        "Set format to sensor failed with %d\n", ret);
+               return -EINVAL;
        }
-       /*
-        * set format info to sensor
-        * In continuous mode, resolution is set only if it is higher than
-        * existing value. This because preview pipe will be configured after
-        * capture pipe and usually has lower resolution than capture pipe.
-        */
-       if (!asd->continuous_mode->val ||
-           isp_sink_fmt->width < (f->fmt.pix.width + padding_w + dvs_env_w) ||
-           isp_sink_fmt->height < (f->fmt.pix.height + padding_h +
-                                   dvs_env_h)) {
-               /*
-                * For jpeg or custom raw format the sensor will return constant
-                * width and height. Because we already had quried try_mbus_fmt,
-                * f->fmt.pix.width and f->fmt.pix.height has been changed to
-                * this fixed width and height. So we cannot select the correct
-                * resolution with that information. So use the original width
-                * and height while set_mbus_fmt() so actual resolutions are
-                * being used in while set media bus format.
-                */
-               s_fmt = f->fmt.pix;
-               if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG ||
-                   f->fmt.pix.pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) {
-                       s_fmt.width = backup_fmt.width;
-                       s_fmt.height = backup_fmt.height;
-               }
-               ret = atomisp_set_fmt_to_snr(vdev, &s_fmt,
-                                            f->fmt.pix.pixelformat, padding_w,
-                                            padding_h, dvs_env_w, dvs_env_h);
-               if (ret) {
-                       dev_warn(isp->dev,
-                                "Set format to sensor failed with %d\n", ret);
-                       return -EINVAL;
-               }
 
-               atomisp_csi_lane_config(isp);
-               crop_needs_override = true;
-       }
+       atomisp_csi_lane_config(isp);
 
-       atomisp_check_copy_mode(asd, source_pad, &backup_fmt);
-       asd->yuvpp_mode = false;                        /* Reset variable */
+       atomisp_check_copy_mode(asd, source_pad, &f->fmt.pix);
 
        isp_sink_crop = *atomisp_subdev_get_rect(&asd->subdev, NULL,
                        V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -5250,27 +4592,10 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
        if (isp_sink_crop.width * 9 / 10 < f->fmt.pix.width ||
            isp_sink_crop.height * 9 / 10 < f->fmt.pix.height ||
            (atomisp_subdev_format_conversion(asd, source_pad) &&
-            ((asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
-              !asd->continuous_mode->val) ||
+            (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO ||
              asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER))) {
-               /* for continuous mode, preview size might be smaller than
-                * still capture size. if preview size still needs crop,
-                * pick the larger one between crop size of preview and
-                * still capture.
-                */
-               if (asd->continuous_mode->val
-                   && source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
-                   && !crop_needs_override) {
-                       isp_sink_crop.width =
-                           max_t(unsigned int, f->fmt.pix.width,
-                                 isp_sink_crop.width);
-                       isp_sink_crop.height =
-                           max_t(unsigned int, f->fmt.pix.height,
-                                 isp_sink_crop.height);
-               } else {
-                       isp_sink_crop.width = f->fmt.pix.width;
-                       isp_sink_crop.height = f->fmt.pix.height;
-               }
+               isp_sink_crop.width = f->fmt.pix.width;
+               isp_sink_crop.height = f->fmt.pix.height;
 
                atomisp_subdev_set_selection(&asd->subdev, fh.state,
                                             V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -5314,30 +4639,27 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
                 * which appears to be related by a hardware
                 * performance limitation.  It's unclear why this
                 * particular code triggers the issue. */
-               if (crop_needs_override) {
-                       if (isp_sink_crop.width * main_compose.height >
-                           isp_sink_crop.height * main_compose.width) {
-                               sink_crop.height = isp_sink_crop.height;
-                               sink_crop.width = DIV_NEAREST_STEP(
-                                                     sink_crop.height *
-                                                     f->fmt.pix.width,
-                                                     f->fmt.pix.height,
-                                                     ATOM_ISP_STEP_WIDTH);
-                       } else {
-                               sink_crop.width = isp_sink_crop.width;
-                               sink_crop.height = DIV_NEAREST_STEP(
-                                                      sink_crop.width *
-                                                      f->fmt.pix.height,
-                                                      f->fmt.pix.width,
-                                                      ATOM_ISP_STEP_HEIGHT);
-                       }
-                       atomisp_subdev_set_selection(&asd->subdev, fh.state,
-                                                    V4L2_SUBDEV_FORMAT_ACTIVE,
-                                                    ATOMISP_SUBDEV_PAD_SINK,
-                                                    V4L2_SEL_TGT_CROP,
-                                                    V4L2_SEL_FLAG_KEEP_CONFIG,
-                                                    &sink_crop);
+               if (isp_sink_crop.width * main_compose.height >
+                   isp_sink_crop.height * main_compose.width) {
+                       sink_crop.height = isp_sink_crop.height;
+                       sink_crop.width =
+                               DIV_NEAREST_STEP(sink_crop.height * f->fmt.pix.width,
+                                                f->fmt.pix.height,
+                                                ATOM_ISP_STEP_WIDTH);
+               } else {
+                       sink_crop.width = isp_sink_crop.width;
+                       sink_crop.height =
+                               DIV_NEAREST_STEP(sink_crop.width * f->fmt.pix.height,
+                                                f->fmt.pix.width,
+                                                ATOM_ISP_STEP_HEIGHT);
                }
+               atomisp_subdev_set_selection(&asd->subdev, fh.state,
+                                            V4L2_SUBDEV_FORMAT_ACTIVE,
+                                            ATOMISP_SUBDEV_PAD_SINK,
+                                            V4L2_SEL_TGT_CROP,
+                                            V4L2_SEL_FLAG_KEEP_CONFIG,
+                                            &sink_crop);
+
                atomisp_subdev_set_selection(&asd->subdev, fh.state,
                                             V4L2_SUBDEV_FORMAT_ACTIVE,
                                             source_pad,
@@ -5345,14 +4667,12 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
                                             &main_compose);
        }
 
-set_fmt_to_isp:
-       ret = atomisp_set_fmt_to_isp(vdev, &output_info, &raw_output_info,
-                                    &f->fmt.pix, source_pad);
+       ret = atomisp_set_fmt_to_isp(vdev, &output_info, &f->fmt.pix, source_pad);
        if (ret) {
                dev_warn(isp->dev, "Can't set format on ISP. Error %d\n", ret);
                return -EINVAL;
        }
-done:
+
        pipe->pix.width = f->fmt.pix.width;
        pipe->pix.height = f->fmt.pix.height;
        pipe->pix.pixelformat = f->fmt.pix.pixelformat;
@@ -5470,71 +4790,6 @@ out:
        return ret;
 }
 
-int atomisp_offline_capture_configure(struct atomisp_sub_device *asd,
-                                     struct atomisp_cont_capture_conf *cvf_config)
-{
-       struct v4l2_ctrl *c;
-
-       lockdep_assert_held(&asd->isp->mutex);
-
-       /*
-       * In case of M10MO ZSL capture case, we need to issue a separate
-       * capture request to M10MO which will output captured jpeg image
-       */
-       c = v4l2_ctrl_find(
-               asd->isp->inputs[asd->input_curr].camera->ctrl_handler,
-               V4L2_CID_START_ZSL_CAPTURE);
-       if (c) {
-               int ret;
-
-               dev_dbg(asd->isp->dev, "%s trigger ZSL capture request\n",
-                       __func__);
-               /* TODO: use the cvf_config */
-               ret = v4l2_ctrl_s_ctrl(c, 1);
-               if (ret)
-                       return ret;
-
-               return v4l2_ctrl_s_ctrl(c, 0);
-       }
-
-       asd->params.offline_parm = *cvf_config;
-
-       if (asd->params.offline_parm.num_captures) {
-               if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED) {
-                       unsigned int init_raw_num;
-
-                       if (asd->enable_raw_buffer_lock->val) {
-                               init_raw_num =
-                                   ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
-                               if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
-                                   asd->params.video_dis_en)
-                                       init_raw_num +=
-                                           ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
-                       } else {
-                               init_raw_num =
-                                   ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
-                       }
-
-                       /* TODO: this can be removed once user-space
-                        *       has been updated to use control API */
-                       asd->continuous_raw_buffer_size->val =
-                           max_t(int,
-                                 asd->continuous_raw_buffer_size->val,
-                                 asd->params.offline_parm.
-                                 num_captures + init_raw_num);
-                       asd->continuous_raw_buffer_size->val =
-                           min_t(int, ATOMISP_CONT_RAW_FRAMES,
-                                 asd->continuous_raw_buffer_size->val);
-               }
-               asd->continuous_mode->val = true;
-       } else {
-               asd->continuous_mode->val = false;
-               __enable_continuous_mode(asd, false);
-       }
-
-       return 0;
-}
-
 /*
  * set auto exposure metering window to camera sensor
  */
@@ -5631,53 +4886,6 @@ void atomisp_init_raw_buffer_bitmap(struct atomisp_sub_device *asd)
        spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags);
 }
 
-static int atomisp_set_raw_buffer_bitmap(struct atomisp_sub_device *asd, int exp_id)
-{
-       int *bitmap, bit;
-       unsigned long flags;
-
-       if (__checking_exp_id(asd, exp_id))
-               return -EINVAL;
-
-       bitmap = asd->raw_buffer_bitmap + exp_id / 32;
-       bit = exp_id % 32;
-       spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags);
-       (*bitmap) |= (1 << bit);
-       asd->raw_buffer_locked_count++;
-       spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags);
-
-       dev_dbg(asd->isp->dev, "%s: exp_id %d,  raw_buffer_locked_count %d\n",
-               __func__, exp_id, asd->raw_buffer_locked_count);
-
-       /* Check if the raw buffer after next is still locked!!! */
-       exp_id += 2;
-       if (exp_id > ATOMISP_MAX_EXP_ID)
-               exp_id -= ATOMISP_MAX_EXP_ID;
-       bitmap = asd->raw_buffer_bitmap + exp_id / 32;
-       bit = exp_id % 32;
-       if ((*bitmap) & (1 << bit)) {
-               int ret;
-
-               /* WORKAROUND unlock the raw buffer compulsively */
-               ret = atomisp_css_exp_id_unlock(asd, exp_id);
-               if (ret) {
-                       dev_err(asd->isp->dev,
-                               "%s exp_id is wrapping back to %d but force unlock failed, err %d.\n",
-                               __func__, exp_id, ret);
-                       return ret;
-               }
-
-               spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags);
-               (*bitmap) &= ~(1 << bit);
-               asd->raw_buffer_locked_count--;
-               spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags);
-               dev_warn(asd->isp->dev,
-                        "%s exp_id is wrapping back to %d but it is still locked so force unlock it, raw_buffer_locked_count %d\n",
-                        __func__, exp_id, asd->raw_buffer_locked_count);
-       }
-       return 0;
-}
-
 static int __is_raw_buffer_locked(struct atomisp_sub_device *asd, int exp_id)
 {
        int *bitmap, bit;
@@ -5816,9 +5024,7 @@ static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe)
                return -EINVAL;
        }
 
-       if (ATOMISP_USE_YUVPP(asd)) {
-               return IA_CSS_PIPE_ID_YUVPP;
-       } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
+       if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
                return IA_CSS_PIPE_ID_VIDEO;
        } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
                return IA_CSS_PIPE_ID_CAPTURE;
index 733b9f8cd06f299a6fb56b8122ae220d790d3de0..399b549bcf831d4774ed44ec073574fa537b5693 100644 (file)
@@ -72,7 +72,6 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr);
 const struct atomisp_format_bridge *get_atomisp_format_bridge_from_mbus(
     u32 mbus_code);
 bool atomisp_is_mbuscode_raw(uint32_t code);
-void atomisp_delayed_init_work(struct work_struct *work);
 
 /* Get internal fmt according to V4L2 fmt */
 bool atomisp_is_viewfinder_support(struct atomisp_device *isp);
@@ -268,9 +267,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f);
 int atomisp_set_shading_table(struct atomisp_sub_device *asd,
                              struct atomisp_shading_table *shading_table);
 
-int atomisp_offline_capture_configure(struct atomisp_sub_device *asd,
-                                     struct atomisp_cont_capture_conf *cvf_config);
-
 void atomisp_free_internal_buffers(struct atomisp_sub_device *asd);
 
 int atomisp_s_ae_window(struct atomisp_sub_device *asd,
@@ -317,11 +313,6 @@ void atomisp_init_raw_buffer_bitmap(struct atomisp_sub_device *asd);
 int atomisp_enable_dz_capt_pipe(struct atomisp_sub_device *asd,
                                unsigned int *enable);
 
-/* Function to get metadata type bu pipe id */
-enum atomisp_metadata_type
-atomisp_get_metadata_type(struct atomisp_sub_device *asd,
-                         enum ia_css_pipe_id pipe_id);
-
 u32 atomisp_get_pixel_depth(u32 pixelformat);
 
 /* Function for HAL to inject a fake event to wake up poll thread */
index 7316eb9f974a8eaf40d71be1e839688596b65928..218e8ac276c89234e831760e92c4491711e48c15 100644 (file)
@@ -196,9 +196,6 @@ void atomisp_css_input_set_two_pixels_per_clock(
     struct atomisp_sub_device *asd,
     bool two_ppc);
 
-void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
-                                   bool enable);
-
 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable);
 
 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
@@ -306,10 +303,6 @@ int atomisp_css_copy_get_output_frame_info(
     unsigned int stream_index,
     struct ia_css_frame_info *info);
 
-int atomisp_css_capture_get_output_raw_frame_info(
-    struct atomisp_sub_device *asd,
-    struct ia_css_frame_info *info);
-
 int atomisp_css_preview_get_output_frame_info(
     struct atomisp_sub_device *asd,
     struct ia_css_frame_info *info);
@@ -423,9 +416,7 @@ int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
 
 int atomisp_css_update_stream(struct atomisp_sub_device *asd);
 
-int atomisp_css_isr_thread(struct atomisp_device *isp,
-                          bool *frame_done_found,
-                          bool *css_pipe_done);
+int atomisp_css_isr_thread(struct atomisp_device *isp);
 
 bool atomisp_css_valid_sof(struct atomisp_device *isp);
 
index 61e2e63a0ef1ca6ebc88324617c57efe6c2bc726..1dae2a7cfdd9b419365caf47862dba5ccebe7337 100644 (file)
@@ -158,13 +158,6 @@ static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
        spin_unlock_irqrestore(&mmio_lock, flags);
 }
 
-static int  __printf(1, 0) atomisp_css2_dbg_ftrace_print(const char *fmt,
-                                                        va_list args)
-{
-       ftrace_vprintk(fmt, args);
-       return 0;
-}
-
 static int  __printf(1, 0) atomisp_vprintk(const char *fmt, va_list args)
 {
        vprintk(fmt, args);
@@ -597,8 +590,6 @@ static void __apply_additional_pipe_config(
                .enable_reduced_pipe = true;
                stream_env->pipe_configs[pipe_id]
                .enable_dz = false;
-               if (ATOMISP_SOC_CAMERA(asd))
-                       stream_env->pipe_configs[pipe_id].enable_dz = true;
 
                if (asd->params.video_dis_en) {
                        stream_env->pipe_extra_configs[pipe_id]
@@ -612,10 +603,7 @@ static void __apply_additional_pipe_config(
                break;
        case IA_CSS_PIPE_ID_YUVPP:
        case IA_CSS_PIPE_ID_COPY:
-               if (ATOMISP_SOC_CAMERA(asd))
-                       stream_env->pipe_configs[pipe_id].enable_dz = true;
-               else
-                       stream_env->pipe_configs[pipe_id].enable_dz = false;
+               stream_env->pipe_configs[pipe_id].enable_dz = false;
                break;
        default:
                break;
@@ -658,13 +646,10 @@ static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
 
                return false;
        case ATOMISP_RUN_MODE_PREVIEW:
-               if (!asd->continuous_mode->val) {
-                       if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
-                               return true;
+               if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
+                       return true;
 
-                       return false;
-               }
-               fallthrough;
+               return false;
        case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
                if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
                    pipe_id == IA_CSS_PIPE_ID_PREVIEW)
@@ -672,14 +657,10 @@ static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
 
                return false;
        case ATOMISP_RUN_MODE_VIDEO:
-               if (!asd->continuous_mode->val) {
-                       if (pipe_id == IA_CSS_PIPE_ID_VIDEO ||
-                           pipe_id == IA_CSS_PIPE_ID_YUVPP)
-                               return true;
-                       else
-                               return false;
-               }
-               fallthrough;
+               if (pipe_id == IA_CSS_PIPE_ID_VIDEO || pipe_id == IA_CSS_PIPE_ID_YUVPP)
+                       return true;
+
+               return false;
        case ATOMISP_RUN_MODE_SDV:
                if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
                    pipe_id == IA_CSS_PIPE_ID_VIDEO)
@@ -813,9 +794,6 @@ static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
        if (opt == 0)
                isp->css_env.isp_css_env.print_env.debug_print = NULL;
        else if (opt == 1)
-               isp->css_env.isp_css_env.print_env.debug_print =
-                   atomisp_css2_dbg_ftrace_print;
-       else if (opt == 2)
                isp->css_env.isp_css_env.print_env.debug_print = atomisp_vprintk;
        else
                ret = -EINVAL;
@@ -1745,25 +1723,6 @@ void atomisp_css_input_set_two_pixels_per_clock(
                .update_pipe[i] = true;
 }
 
-void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
-                                   bool enable)
-{
-       struct atomisp_stream_env *stream_env =
-                   &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
-       unsigned int pipe;
-
-       if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
-               pipe = IA_CSS_PIPE_ID_VIDEO;
-       else
-               pipe = IA_CSS_PIPE_ID_PREVIEW;
-
-       stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable;
-       stream_env->update_pipe[pipe] = true;
-       if (enable)
-               stream_env->pipe_configs[pipe].output_info[0].padded_width =
-                   stream_env->stream_config.input_config.effective_res.width;
-}
-
 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
 {
        int i;
@@ -1894,17 +1853,6 @@ void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
                    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
        int i;
 
-       /*
-        * To SOC camera, there is only one YUVPP pipe in any case
-        * including ZSL/SDV/continuous viewfinder, so always set
-        * stream_config.continuous to 0.
-        */
-       if (ATOMISP_USE_YUVPP(asd)) {
-               stream_env->stream_config.continuous = 0;
-               stream_env->stream_config.online = 1;
-               return;
-       }
-
        if (stream_env->stream_config.continuous != !!enable) {
                stream_env->stream_config.continuous = !!enable;
                stream_env->stream_config.pack_raw_pixels = true;
@@ -2122,51 +2070,6 @@ static void __configure_output(struct atomisp_sub_device *asd,
                pipe_id, width, height, format);
 }
 
-static void __configure_video_preview_output(struct atomisp_sub_device *asd,
-       unsigned int stream_index,
-       unsigned int width, unsigned int height,
-       unsigned int min_width,
-       enum ia_css_frame_format format,
-       enum ia_css_pipe_id pipe_id)
-{
-       struct atomisp_device *isp = asd->isp;
-       struct atomisp_stream_env *stream_env =
-                   &asd->stream_env[stream_index];
-       struct ia_css_frame_info *css_output_info;
-       struct ia_css_stream_config *stream_config = &stream_env->stream_config;
-
-       stream_env->pipe_configs[pipe_id].mode =
-           __pipe_id_to_pipe_mode(asd, pipe_id);
-       stream_env->update_pipe[pipe_id] = true;
-
-       /*
-        * second_output will be as video main output in SDV mode
-        * with SOC camera. output will be as video main output in
-        * normal video mode.
-        */
-       if (asd->continuous_mode->val)
-               css_output_info = &stream_env->pipe_configs[pipe_id].
-                                 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
-       else
-               css_output_info = &stream_env->pipe_configs[pipe_id].
-                                 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
-
-       css_output_info->res.width = width;
-       css_output_info->res.height = height;
-       css_output_info->format = format;
-       css_output_info->padded_width = min_width;
-
-       /* isp binary 2.2 specific setting*/
-       if (width > stream_config->input_config.effective_res.width ||
-           height > stream_config->input_config.effective_res.height) {
-               stream_config->input_config.effective_res.width = width;
-               stream_config->input_config.effective_res.height = height;
-       }
-
-       dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
-               pipe_id, width, height, format);
-}
-
 /*
  * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
  * downscaling input resolution.
@@ -2470,42 +2373,6 @@ static void __configure_vf_output(struct atomisp_sub_device *asd,
                pipe_id, width, height, format);
 }
 
-static void __configure_video_vf_output(struct atomisp_sub_device *asd,
-                                       unsigned int width, unsigned int height,
-                                       unsigned int min_width,
-                                       enum ia_css_frame_format format,
-                                       enum ia_css_pipe_id pipe_id)
-{
-       struct atomisp_device *isp = asd->isp;
-       struct atomisp_stream_env *stream_env =
-                   &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
-       struct ia_css_frame_info *css_output_info;
-
-       stream_env->pipe_configs[pipe_id].mode =
-           __pipe_id_to_pipe_mode(asd, pipe_id);
-       stream_env->update_pipe[pipe_id] = true;
-
-       /*
-        * second_vf_output will be as video viewfinder in SDV mode
-        * with SOC camera. vf_output will be as video viewfinder in
-        * normal video mode.
-        */
-       if (asd->continuous_mode->val)
-               css_output_info = &stream_env->pipe_configs[pipe_id].
-                                 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
-       else
-               css_output_info = &stream_env->pipe_configs[pipe_id].
-                                 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
-
-       css_output_info->res.width = width;
-       css_output_info->res.height = height;
-       css_output_info->format = format;
-       css_output_info->padded_width = min_width;
-       dev_dbg(isp->dev,
-               "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
-               pipe_id, width, height, format);
-}
-
 static int __get_frame_info(struct atomisp_sub_device *asd,
                            unsigned int stream_index,
                            struct ia_css_frame_info *info,
@@ -2565,16 +2432,9 @@ static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
        uint16_t source_pad)
 {
        struct atomisp_device *isp = asd->isp;
-       /*
-        * to SOC camera, use yuvpp pipe.
-        */
-       if (ATOMISP_USE_YUVPP(asd))
-               return IA_CSS_PIPE_ID_YUVPP;
 
        switch (source_pad) {
        case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
-               if (asd->yuvpp_mode)
-                       return IA_CSS_PIPE_ID_YUVPP;
                if (asd->copy_mode)
                        return IA_CSS_PIPE_ID_COPY;
                if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
@@ -2593,8 +2453,6 @@ static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
                }
                fallthrough;
        case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
-               if (asd->yuvpp_mode)
-                       return IA_CSS_PIPE_ID_YUVPP;
                if (asd->copy_mode)
                        return IA_CSS_PIPE_ID_COPY;
                if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
@@ -2617,13 +2475,9 @@ int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
        int stream_index;
        struct atomisp_device *isp = asd->isp;
 
-       if (ATOMISP_SOC_CAMERA(asd)) {
-               stream_index = ATOMISP_INPUT_STREAM_GENERAL;
-       } else {
-               stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
+       stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
                               ATOMISP_INPUT_STREAM_VIDEO :
                               ATOMISP_INPUT_STREAM_GENERAL;
-       }
 
        if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index]
                .pipes[pipe_index], &info)) {
@@ -2636,12 +2490,7 @@ int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
                *frame_info = info.output_info[0];
                break;
        case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
-               if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
-                       *frame_info = info.
-                                     output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
-               else
-                       *frame_info = info.
-                                     output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
+               *frame_info = info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
                break;
        case ATOMISP_SUBDEV_PAD_SOURCE_VF:
                if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
@@ -2653,15 +2502,7 @@ int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
                if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
                    (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
                     pipe_index == IA_CSS_PIPE_ID_YUVPP))
-                       if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
-                               *frame_info = info.
-                                             vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
-                       else
-                               *frame_info = info.
-                                             vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
-               else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
-                       *frame_info =
-                           info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
+                       *frame_info = info.vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
                else
                        *frame_info =
                            info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
@@ -2727,16 +2568,8 @@ int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
        unsigned int min_width,
        enum ia_css_frame_format format)
 {
-       /*
-        * to SOC camera, use yuvpp pipe.
-        */
-       if (ATOMISP_USE_YUVPP(asd))
-               __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
-                                                height,
-                                                min_width, format, IA_CSS_PIPE_ID_YUVPP);
-       else
-               __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
-                                  min_width, format, IA_CSS_PIPE_ID_PREVIEW);
+       __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
+                          min_width, format, IA_CSS_PIPE_ID_PREVIEW);
        return 0;
 }
 
@@ -2745,18 +2578,8 @@ int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
        unsigned int min_width,
        enum ia_css_frame_format format)
 {
-       enum ia_css_pipe_id pipe_id;
-
-       /*
-        * to SOC camera, use yuvpp pipe.
-        */
-       if (ATOMISP_USE_YUVPP(asd))
-               pipe_id = IA_CSS_PIPE_ID_YUVPP;
-       else
-               pipe_id = IA_CSS_PIPE_ID_CAPTURE;
-
        __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
-                          min_width, format, pipe_id);
+                          min_width, format, IA_CSS_PIPE_ID_CAPTURE);
        return 0;
 }
 
@@ -2765,16 +2588,8 @@ int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
                                       unsigned int min_width,
                                       enum ia_css_frame_format format)
 {
-       /*
-        * to SOC camera, use yuvpp pipe.
-        */
-       if (ATOMISP_USE_YUVPP(asd))
-               __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
-                                                height,
-                                                min_width, format, IA_CSS_PIPE_ID_YUVPP);
-       else
-               __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
-                                  min_width, format, IA_CSS_PIPE_ID_VIDEO);
+       __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
+                          min_width, format, IA_CSS_PIPE_ID_VIDEO);
        return 0;
 }
 
@@ -2784,15 +2599,8 @@ int atomisp_css_video_configure_viewfinder(
     unsigned int min_width,
     enum ia_css_frame_format format)
 {
-       /*
-        * to SOC camera, video will use yuvpp pipe.
-        */
-       if (ATOMISP_USE_YUVPP(asd))
-               __configure_video_vf_output(asd, width, height, min_width, format,
-                                           IA_CSS_PIPE_ID_YUVPP);
-       else
-               __configure_vf_output(asd, width, height, min_width, format,
-                                     IA_CSS_PIPE_ID_VIDEO);
+       __configure_vf_output(asd, width, height, min_width, format,
+                             IA_CSS_PIPE_ID_VIDEO);
        return 0;
 }
 
@@ -2802,18 +2610,7 @@ int atomisp_css_capture_configure_viewfinder(
     unsigned int min_width,
     enum ia_css_frame_format format)
 {
-       enum ia_css_pipe_id pipe_id;
-
-       /*
-        * to SOC camera, video will use yuvpp pipe.
-        */
-       if (ATOMISP_USE_YUVPP(asd))
-               pipe_id = IA_CSS_PIPE_ID_YUVPP;
-       else
-               pipe_id = IA_CSS_PIPE_ID_CAPTURE;
-
-       __configure_vf_output(asd, width, height, min_width, format,
-                             pipe_id);
+       __configure_vf_output(asd, width, height, min_width, format, IA_CSS_PIPE_ID_CAPTURE);
        return 0;
 }
 
@@ -2821,45 +2618,16 @@ int atomisp_css_video_get_viewfinder_frame_info(
     struct atomisp_sub_device *asd,
     struct ia_css_frame_info *info)
 {
-       enum ia_css_pipe_id pipe_id;
-       enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME;
-
-       if (ATOMISP_USE_YUVPP(asd)) {
-               pipe_id = IA_CSS_PIPE_ID_YUVPP;
-               if (asd->continuous_mode->val)
-                       frame_type = ATOMISP_CSS_SECOND_VF_FRAME;
-       } else {
-               pipe_id = IA_CSS_PIPE_ID_VIDEO;
-       }
-
        return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
-                               frame_type, pipe_id);
+                               ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_VIDEO);
 }
 
 int atomisp_css_capture_get_viewfinder_frame_info(
     struct atomisp_sub_device *asd,
     struct ia_css_frame_info *info)
 {
-       enum ia_css_pipe_id pipe_id;
-
-       if (ATOMISP_USE_YUVPP(asd))
-               pipe_id = IA_CSS_PIPE_ID_YUVPP;
-       else
-               pipe_id = IA_CSS_PIPE_ID_CAPTURE;
-
        return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
-                               ATOMISP_CSS_VF_FRAME, pipe_id);
-}
-
-int atomisp_css_capture_get_output_raw_frame_info(
-    struct atomisp_sub_device *asd,
-    struct ia_css_frame_info *info)
-{
-       if (ATOMISP_USE_YUVPP(asd))
-               return 0;
-
-       return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
-                               ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE);
+                               ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_CAPTURE);
 }
 
 int atomisp_css_copy_get_output_frame_info(
@@ -2875,53 +2643,24 @@ int atomisp_css_preview_get_output_frame_info(
     struct atomisp_sub_device *asd,
     struct ia_css_frame_info *info)
 {
-       enum ia_css_pipe_id pipe_id;
-       enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
-
-       if (ATOMISP_USE_YUVPP(asd)) {
-               pipe_id = IA_CSS_PIPE_ID_YUVPP;
-               if (asd->continuous_mode->val)
-                       frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
-       } else {
-               pipe_id = IA_CSS_PIPE_ID_PREVIEW;
-       }
-
        return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
-                               frame_type, pipe_id);
+                               ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_PREVIEW);
 }
 
 int atomisp_css_capture_get_output_frame_info(
     struct atomisp_sub_device *asd,
     struct ia_css_frame_info *info)
 {
-       enum ia_css_pipe_id pipe_id;
-
-       if (ATOMISP_USE_YUVPP(asd))
-               pipe_id = IA_CSS_PIPE_ID_YUVPP;
-       else
-               pipe_id = IA_CSS_PIPE_ID_CAPTURE;
-
        return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
-                               ATOMISP_CSS_OUTPUT_FRAME, pipe_id);
+                               ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_CAPTURE);
 }
 
 int atomisp_css_video_get_output_frame_info(
     struct atomisp_sub_device *asd,
     struct ia_css_frame_info *info)
 {
-       enum ia_css_pipe_id pipe_id;
-       enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
-
-       if (ATOMISP_USE_YUVPP(asd)) {
-               pipe_id = IA_CSS_PIPE_ID_YUVPP;
-               if (asd->continuous_mode->val)
-                       frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
-       } else {
-               pipe_id = IA_CSS_PIPE_ID_VIDEO;
-       }
-
        return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
-                               frame_type, pipe_id);
+                               ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_VIDEO);
 }
 
 int atomisp_css_preview_configure_pp_input(
@@ -2930,15 +2669,12 @@ int atomisp_css_preview_configure_pp_input(
 {
        struct atomisp_stream_env *stream_env =
                    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
-       __configure_preview_pp_input(asd, width, height,
-                                    ATOMISP_USE_YUVPP(asd) ?
-                                    IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW);
+       __configure_preview_pp_input(asd, width, height, IA_CSS_PIPE_ID_PREVIEW);
 
        if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
            capt_pp_in_res.width)
-               __configure_capture_pp_input(asd, width, height,
-                                            ATOMISP_USE_YUVPP(asd) ?
-                                            IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
+               __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
+
        return 0;
 }
 
@@ -2946,9 +2682,7 @@ int atomisp_css_capture_configure_pp_input(
     struct atomisp_sub_device *asd,
     unsigned int width, unsigned int height)
 {
-       __configure_capture_pp_input(asd, width, height,
-                                    ATOMISP_USE_YUVPP(asd) ?
-                                    IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
+       __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
        return 0;
 }
 
@@ -2959,15 +2693,12 @@ int atomisp_css_video_configure_pp_input(
        struct atomisp_stream_env *stream_env =
                    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
 
-       __configure_video_pp_input(asd, width, height,
-                                  ATOMISP_USE_YUVPP(asd) ?
-                                  IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO);
+       __configure_video_pp_input(asd, width, height, IA_CSS_PIPE_ID_VIDEO);
 
        if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
            capt_pp_in_res.width)
-               __configure_capture_pp_input(asd, width, height,
-                                            ATOMISP_USE_YUVPP(asd) ?
-                                            IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
+               __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
+
        return 0;
 }
 
@@ -3662,41 +3393,33 @@ void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
        ia_css_morph_table_free(table);
 }
 
-static struct atomisp_sub_device *__get_atomisp_subdev(
-    struct ia_css_pipe *css_pipe,
-    struct atomisp_device *isp,
-    enum atomisp_input_stream_id *stream_id)
+static bool atomisp_css_isr_get_stream_id(struct ia_css_pipe *css_pipe,
+                                         struct atomisp_device *isp,
+                                         enum atomisp_input_stream_id *stream_id)
 {
-       int i, j, k;
-       struct atomisp_sub_device *asd;
        struct atomisp_stream_env *stream_env;
+       int i, j;
 
-       for (i = 0; i < isp->num_of_streams; i++) {
-               asd = &isp->asd[i];
-               if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED)
-                       continue;
-               for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
-                       stream_env = &asd->stream_env[j];
-                       for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
-                               if (stream_env->pipes[k] &&
-                                   stream_env->pipes[k] == css_pipe) {
-                                       *stream_id = j;
-                                       return asd;
-                               }
+       if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_DISABLED)
+               return false;
+
+       for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
+               stream_env = &isp->asd.stream_env[i];
+               for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
+                       if (stream_env->pipes[j] && stream_env->pipes[j] == css_pipe) {
+                               *stream_id = i;
+                               return true;
                        }
                }
        }
 
-       return NULL;
+       return false;
 }
 
-int atomisp_css_isr_thread(struct atomisp_device *isp,
-                          bool *frame_done_found,
-                          bool *css_pipe_done)
+int atomisp_css_isr_thread(struct atomisp_device *isp)
 {
        enum atomisp_input_stream_id stream_id = 0;
        struct atomisp_css_event current_event;
-       struct atomisp_sub_device *asd;
 
        lockdep_assert_held(&isp->mutex);
 
@@ -3722,9 +3445,7 @@ int atomisp_css_isr_thread(struct atomisp_device *isp,
                        continue;
                }
 
-               asd = __get_atomisp_subdev(current_event.event.pipe,
-                                          isp, &stream_id);
-               if (!asd) {
+               if (!atomisp_css_isr_get_stream_id(current_event.event.pipe, isp, &stream_id)) {
                        if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
                                dev_dbg(isp->dev,
                                        "event: Timer event.");
@@ -3735,56 +3456,53 @@ int atomisp_css_isr_thread(struct atomisp_device *isp,
                        continue;
                }
 
-               atomisp_css_temp_pipe_to_pipe_id(asd, &current_event);
+               atomisp_css_temp_pipe_to_pipe_id(&isp->asd, &current_event);
                switch (current_event.event.type) {
                case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
                        dev_dbg(isp->dev, "event: Output frame done");
-                       frame_done_found[asd->index] = true;
-                       atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
+                       atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
                                         current_event.pipe, true, stream_id);
                        break;
                case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
                        dev_dbg(isp->dev, "event: Second output frame done");
-                       frame_done_found[asd->index] = true;
-                       atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
+                       atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
                                         current_event.pipe, true, stream_id);
                        break;
                case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
                        dev_dbg(isp->dev, "event: 3A stats frame done");
-                       atomisp_buf_done(asd, 0,
+                       atomisp_buf_done(&isp->asd, 0,
                                         IA_CSS_BUFFER_TYPE_3A_STATISTICS,
                                         current_event.pipe,
                                         false, stream_id);
                        break;
                case IA_CSS_EVENT_TYPE_METADATA_DONE:
                        dev_dbg(isp->dev, "event: metadata frame done");
-                       atomisp_buf_done(asd, 0,
+                       atomisp_buf_done(&isp->asd, 0,
                                         IA_CSS_BUFFER_TYPE_METADATA,
                                         current_event.pipe,
                                         false, stream_id);
                        break;
                case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
                        dev_dbg(isp->dev, "event: VF output frame done");
-                       atomisp_buf_done(asd, 0,
+                       atomisp_buf_done(&isp->asd, 0,
                                         IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
                                         current_event.pipe, true, stream_id);
                        break;
                case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
                        dev_dbg(isp->dev, "event: second VF output frame done");
-                       atomisp_buf_done(asd, 0,
+                       atomisp_buf_done(&isp->asd, 0,
                                         IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
                                         current_event.pipe, true, stream_id);
                        break;
                case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
                        dev_dbg(isp->dev, "event: dis stats frame done");
-                       atomisp_buf_done(asd, 0,
+                       atomisp_buf_done(&isp->asd, 0,
                                         IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
                                         current_event.pipe,
                                         false, stream_id);
                        break;
                case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
                        dev_dbg(isp->dev, "event: pipeline done");
-                       css_pipe_done[asd->index] = true;
                        break;
                case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
                        dev_warn(isp->dev, "unexpected event: acc stage done");
@@ -3801,23 +3519,17 @@ int atomisp_css_isr_thread(struct atomisp_device *isp,
 
 bool atomisp_css_valid_sof(struct atomisp_device *isp)
 {
-       unsigned int i, j;
-
-       /* Loop for each css stream */
-       for (i = 0; i < isp->num_of_streams; i++) {
-               struct atomisp_sub_device *asd = &isp->asd[i];
-               /* Loop for each css vc stream */
-               for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
-                       if (!asd->stream_env[j].stream)
-                               continue;
-
-                       dev_dbg(isp->dev,
-                               "stream #%d: mode: %d\n", j,
-                               asd->stream_env[j].stream_config.mode);
-                       if (asd->stream_env[j].stream_config.mode ==
-                           IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
-                               return false;
-               }
+       unsigned int i;
+
+       /* Loop for each css vc stream */
+       for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
+               if (!isp->asd.stream_env[i].stream)
+                       continue;
+
+               dev_dbg(isp->dev, "stream #%d: mode: %d\n",
+                       i, isp->asd.stream_env[i].stream_config.mode);
+               if (isp->asd.stream_env[i].stream_config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
+                       return false;
        }
 
        return true;
index ce01479bdd6822457e3eb0c48b539b762e695332..fa362c8a37e845f94c716b5b9014f89303a20bdd 100644 (file)
@@ -112,8 +112,7 @@ static int atomisp_q_one_metadata_buffer(struct atomisp_sub_device *asd,
        enum ia_css_pipe_id css_pipe_id)
 {
        struct atomisp_metadata_buf *metadata_buf;
-       enum atomisp_metadata_type md_type =
-           atomisp_get_metadata_type(asd, css_pipe_id);
+       enum atomisp_metadata_type md_type = ATOMISP_MAIN_METADATA;
        struct list_head *metadata_list;
 
        if (asd->metadata_bufs_in_css[stream_id][css_pipe_id] >=
@@ -347,41 +346,6 @@ static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd,
                                    enum ia_css_pipe_id pipe_id,
                                    uint16_t source_pad)
 {
-       if (ATOMISP_USE_YUVPP(asd)) {
-               /* when run ZSL case */
-               if (asd->continuous_mode->val &&
-                   asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
-                       if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE)
-                               return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
-                       else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
-                               return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
-                       else
-                               return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
-               }
-
-               /*when run SDV case*/
-               if (asd->continuous_mode->val &&
-                   asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
-                       if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE)
-                               return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
-                       else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
-                               return IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME;
-                       else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO)
-                               return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
-                       else
-                               return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
-               }
-
-               /*other case: default setting*/
-               if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
-                   source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
-                   (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
-                    asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO))
-                       return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
-               else
-                       return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
-       }
-
        if (pipe_id == IA_CSS_PIPE_ID_COPY ||
            source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
            source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
@@ -414,22 +378,10 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
                preview_pipe = &asd->video_out_capture;
                css_preview_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
        } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
-               if (asd->continuous_mode->val) {
-                       capture_pipe = &asd->video_out_capture;
-                       vf_pipe = &asd->video_out_vf;
-                       css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
-               }
                video_pipe = &asd->video_out_video_capture;
                preview_pipe = &asd->video_out_preview;
                css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
                css_preview_pipe_id = IA_CSS_PIPE_ID_VIDEO;
-       } else if (asd->continuous_mode->val) {
-               capture_pipe = &asd->video_out_capture;
-               vf_pipe = &asd->video_out_vf;
-               preview_pipe = &asd->video_out_preview;
-
-               css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
-               css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
        } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
                preview_pipe = &asd->video_out_preview;
                css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
@@ -447,27 +399,12 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
                css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
        }
 
-       if (asd->yuvpp_mode) {
-               capture_pipe = &asd->video_out_capture;
-               video_pipe   = &asd->video_out_video_capture;
-               preview_pipe = &asd->video_out_preview;
-               css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
-               css_video_pipe_id   = IA_CSS_PIPE_ID_YUVPP;
-               css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
-       }
-
        if (capture_pipe) {
                buf_type = atomisp_get_css_buf_type(
                               asd, css_capture_pipe_id,
                               atomisp_subdev_source_pad(&capture_pipe->vdev));
                input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
 
-               /*
-                * use yuvpp pipe for SOC camera.
-                */
-               if (ATOMISP_USE_YUVPP(asd))
-                       css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
-
                atomisp_q_video_buffers_to_css(asd, capture_pipe,
                                               input_stream_id,
                                               buf_type, css_capture_pipe_id);
@@ -482,11 +419,6 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
                else
                        input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
 
-               /*
-                * use yuvpp pipe for SOC camera.
-                */
-               if (ATOMISP_USE_YUVPP(asd))
-                       css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
                atomisp_q_video_buffers_to_css(asd, vf_pipe,
                                               input_stream_id,
                                               buf_type, css_capture_pipe_id);
@@ -496,22 +428,14 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
                buf_type = atomisp_get_css_buf_type(
                               asd, css_preview_pipe_id,
                               atomisp_subdev_source_pad(&preview_pipe->vdev));
-               if (ATOMISP_SOC_CAMERA(asd) && css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
-                       input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
-               /* else for ext isp use case */
-               else if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
+
+               if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
                        input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
                else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream)
                        input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
                else
                        input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
 
-               /*
-                * use yuvpp pipe for SOC camera.
-                */
-               if (ATOMISP_USE_YUVPP(asd))
-                       css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
-
                atomisp_q_video_buffers_to_css(asd, preview_pipe,
                                               input_stream_id,
                                               buf_type, css_preview_pipe_id);
@@ -526,12 +450,6 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
                else
                        input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
 
-               /*
-                * use yuvpp pipe for SOC camera.
-                */
-               if (ATOMISP_USE_YUVPP(asd))
-                       css_video_pipe_id = IA_CSS_PIPE_ID_YUVPP;
-
                atomisp_q_video_buffers_to_css(asd, video_pipe,
                                               input_stream_id,
                                               buf_type, css_video_pipe_id);
@@ -545,7 +463,6 @@ static void atomisp_buf_queue(struct vb2_buffer *vb)
        struct atomisp_video_pipe *pipe = vb_to_pipe(vb);
        struct ia_css_frame *frame = vb_to_frame(vb);
        struct atomisp_sub_device *asd = pipe->asd;
-       u16 source_pad = atomisp_subdev_source_pad(&pipe->vdev);
        unsigned long irqflags;
        int ret;
 
@@ -593,21 +510,6 @@ static void atomisp_buf_queue(struct vb2_buffer *vb)
                        atomisp_qbuffers_to_css(asd);
        }
 
-       /*
-        * Workaround: Due to the design of HALv3,
-        * sometimes in ZSL or SDV mode HAL needs to
-        * capture multiple images within one streaming cycle.
-        * But the capture number cannot be determined by HAL.
-        * So HAL only sets the capture number to be 1 and queue multiple
-        * buffers. Atomisp driver needs to check this case and re-trigger
-        * CSS to do capture when new buffer is queued.
-        */
-       if (asd->continuous_mode->val && source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE &&
-           !asd->enable_raw_buffer_lock->val && asd->params.offline_parm.num_captures == 1) {
-               asd->pending_capture_request++;
-               dev_dbg(asd->isp->dev, "Add one pending capture request.\n");
-       }
-
 out_unlock:
        mutex_unlock(&asd->isp->mutex);
 }
@@ -662,21 +564,15 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
        asd->params.fpn_en = false;
        asd->params.xnr_en = false;
        asd->params.false_color = 0;
-       asd->params.online_process = 1;
        asd->params.yuv_ds_en = 0;
        /* s3a grid not enabled for any pipe */
        asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM;
 
-       asd->params.offline_parm.num_captures = 1;
-       asd->params.offline_parm.skip_frames = 0;
-       asd->params.offline_parm.offset = 0;
-       asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
        /* Add for channel */
        asd->input_curr = 0;
 
        asd->mipi_frame_size = 0;
        asd->copy_mode = false;
-       asd->yuvpp_mode = false;
 
        asd->stream_prepared = false;
        asd->high_speed_mode = false;
@@ -698,12 +594,7 @@ static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd)
 
 unsigned int atomisp_dev_users(struct atomisp_device *isp)
 {
-       unsigned int i, sum;
-
-       for (i = 0, sum = 0; i < isp->num_of_streams; i++)
-               sum += atomisp_subdev_users(&isp->asd[i]);
-
-       return sum;
+       return atomisp_subdev_users(&isp->asd);
 }
 
 static int atomisp_open(struct file *file)
@@ -815,7 +706,7 @@ static int atomisp_release(struct file *file)
         * The sink pad setting can only be cleared when all device nodes
         * get released.
         */
-       if (asd->fmt_auto->val) {
+       {
                struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
 
                atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
index 7fc7dfa56172ba21bc4e449ebbc1b14050b93823..c718a74ea70a31f53f103c9cfec5c0cb133017ae 100644 (file)
@@ -304,7 +304,17 @@ static struct gmin_cfg_var surface3_vars[] = {
        {},
 };
 
+static struct gmin_cfg_var lenovo_ideapad_miix_310_vars[] = {
+       /* _DSM contains the wrong CsiPort! */
+       { "OVTI2680:01_CsiPort", "0" },
+       {}
+};
+
 static const struct dmi_system_id gmin_vars[] = {
+       /*
+        * These DMI IDs were present when the atomisp driver was merged into
+        * drivers/staging and it is unclear if they are really necessary.
+        */
        {
                .ident = "BYT-T FFD8",
                .matches = {
@@ -341,6 +351,7 @@ static const struct dmi_system_id gmin_vars[] = {
                },
                .driver_data = i8880_vars,
        },
+       /* Later added DMI ids, these are confirmed to really be necessary! */
        {
                .ident = "Surface 3",
                .matches = {
@@ -348,6 +359,14 @@ static const struct dmi_system_id gmin_vars[] = {
                },
                .driver_data = surface3_vars,
        },
+       {
+               .ident = "Lenovo Ideapad Miix 310",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10"),
+               },
+               .driver_data = lenovo_ideapad_miix_310_vars,
+       },
        {}
 };
 
@@ -1353,37 +1372,22 @@ static int gmin_get_config_var(struct device *maindev,
                               const char *var,
                               char *out, size_t *out_len)
 {
+       struct acpi_device *adev = ACPI_COMPANION(maindev);
        efi_char16_t var16[CFG_VAR_NAME_MAX];
        const struct dmi_system_id *id;
-       struct device *dev = maindev;
        char var8[CFG_VAR_NAME_MAX];
        efi_status_t status;
        int i, ret;
 
-       /* For sensors, try first to use the _DSM table */
-       if (!is_gmin) {
-               ret = gmin_get_config_dsm_var(maindev, var, out, out_len);
-               if (!ret)
-                       return 0;
-       }
-
-       /* Fall-back to other approaches */
-
-       if (!is_gmin && ACPI_COMPANION(dev))
-               dev = &ACPI_COMPANION(dev)->dev;
-
-       if (!is_gmin)
-               ret = snprintf(var8, sizeof(var8), "%s_%s", dev_name(dev), var);
+       if (!is_gmin && adev)
+               ret = snprintf(var8, sizeof(var8), "%s_%s", acpi_dev_name(adev), var);
        else
                ret = snprintf(var8, sizeof(var8), "gmin_%s", var);
 
        if (ret < 0 || ret >= sizeof(var8) - 1)
                return -EINVAL;
 
-       /* First check a hard-coded list of board-specific variables.
-        * Some device firmwares lack the ability to set EFI variables at
-        * runtime.
-        */
+       /* DMI based quirks override both the _DSM table and EFI variables */
        id = dmi_first_match(gmin_vars);
        if (id) {
                ret = gmin_get_hardcoded_var(maindev, id->driver_data, var8,
@@ -1392,6 +1396,13 @@ static int gmin_get_config_var(struct device *maindev,
                        return 0;
        }
 
+       /* For sensors, try first to use the _DSM table */
+       if (!is_gmin) {
+               ret = gmin_get_config_dsm_var(maindev, var, out, out_len);
+               if (!ret)
+                       return 0;
+       }
+
        /* Our variable names are ASCII by construction, but EFI names
         * are wide chars.  Convert and zero-pad.
         */
@@ -1447,3 +1458,243 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0f38, isp_pm_cap_fixup);
 
 MODULE_DESCRIPTION("Ancillary routines for binding ACPI devices");
 MODULE_LICENSE("GPL");
+
+/*
+ * The below helper functions don't really belong here and should eventually be
+ * moved to some place under drivers/media/v4l2-core.
+ */
+#include <linux/platform_data/x86/soc.h>
+
+/*
+ * 79234640-9e10-4fea-a5c1-b5aa8b19756f
+ * This _DSM GUID returns information about the GPIO lines mapped to a sensor.
+ * Function number 1 returns a count of the GPIO lines that are mapped.
+ * Subsequent functions return 32 bit ints encoding information about the GPIO.
+ */
+static const guid_t intel_sensor_gpio_info_guid =
+       GUID_INIT(0x79234640, 0x9e10, 0x4fea,
+                 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
+
+/*
+ * 822ace8f-2814-4174-a56b-5f029fe079ee
+ * This _DSM GUID returns a string from the sensor device, which acts as a
+ * module identifier.
+ */
+static const guid_t intel_sensor_module_guid =
+       GUID_INIT(0x822ace8f, 0x2814, 0x4174,
+                 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
+
+#define INTEL_DSM_TYPE_SHIFT                           0
+#define INTEL_DSM_TYPE_MASK                            GENMASK(7, 0)
+#define INTEL_DSM_PIN_SHIFT                            8
+#define INTEL_DSM_PIN_MASK                             GENMASK(15, 8)
+#define INTEL_DSM_SENSOR_ON_VAL_SHIFT                  24
+#define INTEL_DSM_SENSOR_ON_VAL_MASK                   GENMASK(31, 24)
+
+#define INTEL_DSM_TYPE(x) \
+       (((x) & INTEL_DSM_TYPE_MASK) >> INTEL_DSM_TYPE_SHIFT)
+#define INTEL_DSM_PIN(x) \
+       (((x) & INTEL_DSM_PIN_MASK) >> INTEL_DSM_PIN_SHIFT)
+#define INTEL_DSM_SENSOR_ON_VAL(x) \
+       (((x) & INTEL_DSM_SENSOR_ON_VAL_MASK) >> INTEL_DSM_SENSOR_ON_VAL_SHIFT)
+
+#define V4L2_SENSOR_MAX_ACPI_GPIOS                     2u
+
+struct v4l2_acpi_gpio_map {
+       struct acpi_gpio_params params[V4L2_SENSOR_MAX_ACPI_GPIOS];
+       struct acpi_gpio_mapping mapping[V4L2_SENSOR_MAX_ACPI_GPIOS + 1];
+};
+
+struct v4l2_acpi_gpio_parsing_data {
+       struct device *dev;
+       u32 settings[V4L2_SENSOR_MAX_ACPI_GPIOS];
+       unsigned int settings_count;
+       unsigned int res_count;
+       unsigned int map_count;
+       struct v4l2_acpi_gpio_map *map;
+};
+
+/* Note this always returns 1 to continue looping so that res_count is accurate */
+static int v4l2_acpi_handle_gpio_res(struct acpi_resource *ares, void *_data)
+{
+       struct v4l2_acpi_gpio_parsing_data *data = _data;
+       struct acpi_resource_gpio *agpio;
+       const char *name;
+       bool active_low;
+       unsigned int i;
+       u32 settings;
+       u8 pin;
+
+       if (!acpi_gpio_get_io_resource(ares, &agpio))
+               return 1; /* Not a GPIO, continue the loop */
+
+       data->res_count++;
+
+       pin = agpio->pin_table[0];
+       for (i = 0; i < data->settings_count; i++) {
+               if (INTEL_DSM_PIN(data->settings[i]) == pin) {
+                       settings = data->settings[i];
+                       break;
+               }
+       }
+
+       if (i == data->settings_count) {
+               dev_warn(data->dev, "Could not find DSM GPIO settings for pin %d\n", pin);
+               return 1;
+       }
+
+       switch (INTEL_DSM_TYPE(settings)) {
+       case 0:
+               name = "reset-gpios";
+               break;
+       case 1:
+               name = "powerdown-gpios";
+               break;
+       default:
+               dev_warn(data->dev, "Unknown GPIO type 0x%02lx for pin %d\n",
+                        INTEL_DSM_TYPE(settings), pin);
+               return 1;
+       }
+
+       /*
+        * Both reset and power-down need to be logical false when the sensor
+        * is on (sensor should not be in reset and not be powered-down). So
+        * when the sensor-on-value (which is the physical pin value) is high,
+        * then the signal is active-low.
+        */
+       active_low = INTEL_DSM_SENSOR_ON_VAL(settings) ? true : false;
+
+       i = data->map_count;
+       if (i == V4L2_SENSOR_MAX_ACPI_GPIOS)
+               return 1;
+
+       /* res_count is already incremented */
+       data->map->params[i].crs_entry_index = data->res_count - 1;
+       data->map->params[i].active_low = active_low;
+       data->map->mapping[i].name = name;
+       data->map->mapping[i].data = &data->map->params[i];
+       data->map->mapping[i].size = 1;
+       data->map_count++;
+
+       dev_info(data->dev, "%s crs %d %s pin %d active-%s\n", name,
+                data->res_count - 1, agpio->resource_source.string_ptr,
+                pin, active_low ? "low" : "high");
+
+       return 1;
+}
+
+/*
+ * Helper function to create an ACPI GPIO lookup table for sensor reset and
+ * powerdown signals on Intel Bay Trail (BYT) and Cherry Trail (CHT) devices,
+ * including setting the correct polarity for the GPIO.
+ *
+ * This uses the "79234640-9e10-4fea-a5c1-b5aa8b19756f" DSM method directly
+ * on the sensor device's ACPI node. This is different from later Intel
+ * hardware which has a separate INT3472 with this info. Since there is
+ * no separate firmware-node to which we can bind to register the GPIO lookups
+ * this unfortunately means that all sensor drivers which may be used on
+ * BYT or CHT hw need to call this function. This also means that this function
+ * may only fail when it is actually called on BYT/CHT hw. In all other cases
+ * it must always succeed.
+ *
+ * Note this code uses the same DSM GUID as the INT3472 discrete.c code
+ * and there is some overlap, but there are enough differences that it is
+ * difficult to share the code.
+ */
+int v4l2_get_acpi_sensor_info(struct device *dev, char **module_id_str)
+{
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+       struct v4l2_acpi_gpio_parsing_data data = { };
+       LIST_HEAD(resource_list);
+       union acpi_object *obj;
+       unsigned int i, j;
+       int ret;
+
+       if (module_id_str)
+               *module_id_str = NULL;
+
+       if (!adev)
+               return 0;
+
+       obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid,
+                                     0x00, 0x01, NULL, ACPI_TYPE_STRING);
+       if (obj) {
+               dev_info(dev, "Sensor module id: '%s'\n", obj->string.pointer);
+               if (module_id_str)
+                       *module_id_str = kstrdup(obj->string.pointer, GFP_KERNEL);
+
+               ACPI_FREE(obj);
+       }
+
+       if (!soc_intel_is_byt() && !soc_intel_is_cht())
+               return 0;
+
+       /*
+        * First get the GPIO-settings count and then get count GPIO-settings
+        * values. Note the order of these may differ from the order in which
+        * the GPIOs are listed on the ACPI resources! So we first store them all
+        * and then enumerate the ACPI resources and match them up by pin number.
+        */
+       obj = acpi_evaluate_dsm_typed(adev->handle,
+                                     &intel_sensor_gpio_info_guid, 0x00, 1,
+                                     NULL, ACPI_TYPE_INTEGER);
+       if (!obj)
+               return dev_err_probe(dev, -EIO, "No _DSM entry for GPIO pin count\n");
+
+       data.settings_count = obj->integer.value;
+       ACPI_FREE(obj);
+
+       if (data.settings_count > V4L2_SENSOR_MAX_ACPI_GPIOS)
+               return dev_err_probe(dev, -EIO, "Too many GPIOs %u > %u\n",
+                                    data.settings_count, V4L2_SENSOR_MAX_ACPI_GPIOS);
+
+       for (i = 0; i < data.settings_count; i++) {
+               /*
+                * i + 2 because the index of this _DSM function is 1-based
+                * and the first function is just a count.
+                */
+               obj = acpi_evaluate_dsm_typed(adev->handle,
+                                             &intel_sensor_gpio_info_guid,
+                                             0x00, i + 2,
+                                             NULL, ACPI_TYPE_INTEGER);
+               if (!obj)
+                       return dev_err_probe(dev, -EIO, "No _DSM entry for GPIO pin %u\n", i);
+
+               data.settings[i] = obj->integer.value;
+               ACPI_FREE(obj);
+       }
+
+       /* Since we match up by pin-number the pin-numbers must be unique */
+       for (i = 0; i < data.settings_count; i++) {
+               for (j = i + 1; j < data.settings_count; j++) {
+                       if (INTEL_DSM_PIN(data.settings[i]) !=
+                           INTEL_DSM_PIN(data.settings[j]))
+                               continue;
+
+                       return dev_err_probe(dev, -EIO, "Duplicate pin number %lu\n",
+                                            INTEL_DSM_PIN(data.settings[i]));
+               }
+       }
+
+       /* Use devm_kzalloc() for the mappings + params to auto-free them */
+       data.map = devm_kzalloc(dev, sizeof(*data.map), GFP_KERNEL);
+       if (!data.map)
+               return -ENOMEM;
+
+       /* Now parse the ACPI resources and build the lookup table */
+       data.dev = dev;
+       ret = acpi_dev_get_resources(adev, &resource_list,
+                                    v4l2_acpi_handle_gpio_res, &data);
+       if (ret < 0)
+               return ret;
+
+       acpi_dev_free_resource_list(&resource_list);
+
+       if (data.map_count != data.settings_count ||
+           data.res_count != data.settings_count)
+               dev_warn(dev, "ACPI GPIO resources vs DSM GPIO-info count mismatch (dsm: %d res: %d map %d\n",
+                        data.settings_count, data.res_count, data.map_count);
+
+       return devm_acpi_dev_add_driver_gpios(dev, data.map->mapping);
+}
+EXPORT_SYMBOL_GPL(v4l2_get_acpi_sensor_info);
index fa38d91420cf7479256928143dee201fbfe09998..1fac99f4e2b0144d17c0d3a34739224b49b74f7d 100644 (file)
@@ -48,8 +48,6 @@
        (((isp)->media_dev.hw_revision & ATOMISP_HW_REVISION_MASK) == \
         ((rev) << ATOMISP_HW_REVISION_SHIFT))
 
-#define MAX_STREAM_NUM 2
-
 #define ATOMISP_PCI_DEVICE_SOC_MASK    0xfff8
 /* MRFLD with 0x1178: ISP freq can burst to 457MHz */
 #define ATOMISP_PCI_DEVICE_SOC_MRFLD   0x1178
@@ -76,9 +74,6 @@
 #define ATOM_RESOLUTION_SUBQCIF_WIDTH  128
 #define ATOM_RESOLUTION_SUBQCIF_HEIGHT 96
 
-#define ATOM_ISP_MAX_WIDTH_TMP 1280
-#define ATOM_ISP_MAX_HEIGHT_TMP        720
-
 #define ATOM_ISP_I2C_BUS_1     4
 #define ATOM_ISP_I2C_BUS_2     5
 
 #define ATOMISP_METADATA_QUEUE_DEPTH_FOR_HAL   8
 #define ATOMISP_S3A_BUF_QUEUE_DEPTH_FOR_HAL    8
 
-#define ATOMISP_DELAYED_INIT_NOT_QUEUED        0
-#define ATOMISP_DELAYED_INIT_QUEUED    1
-#define ATOMISP_DELAYED_INIT_DONE      2
-
 /*
  * Define how fast CPU should be able to serve ISP interrupts.
  * The bigger the value, the higher risk that the ISP is not
 #define ATOMISP_CSS_OUTPUT_SECOND_INDEX     1
 #define ATOMISP_CSS_OUTPUT_DEFAULT_INDEX    0
 
-/*
- * ATOMISP_SOC_CAMERA
- * This is to differentiate between ext-isp and soc camera in
- * Moorefield/Baytrail platform.
- */
-#define ATOMISP_SOC_CAMERA(asd)  \
-       (asd->isp->inputs[asd->input_curr].type == SOC_CAMERA)
-
-#define ATOMISP_USE_YUVPP(asd)  \
-       (ATOMISP_SOC_CAMERA(asd) && ATOMISP_CSS_SUPPORT_YUVPP && \
-       !asd->copy_mode)
-
-#define ATOMISP_DEPTH_SENSOR_STREAMON_COUNT 2
-
-#define ATOMISP_DEPTH_DEFAULT_MASTER_SENSOR 0
-#define ATOMISP_DEPTH_DEFAULT_SLAVE_SENSOR 1
-
 /* ISP2401 */
 #define ATOMISP_ION_DEVICE_FD_OFFSET   16
 #define ATOMISP_ION_SHARED_FD_MASK     (0xFFFF)
@@ -205,6 +179,7 @@ struct atomisp_device {
        struct device *dev;
        struct v4l2_device v4l2_dev;
        struct media_device media_dev;
+       struct atomisp_sub_device asd;
        struct atomisp_platform_data *pdata;
        void *mmu_l1_base;
        void __iomem *base;
@@ -214,18 +189,6 @@ struct atomisp_device {
        struct pm_qos_request pm_qos;
        s32 max_isr_latency;
 
-       /*
-        * ISP modules
-        * Multiple streams are represents by multiple
-        * atomisp_sub_device instances
-        */
-       struct atomisp_sub_device *asd;
-       /*
-        * this will be assigned dyanamically.
-        * For Merr/BTY(ISP2400), 2 streams are supported.
-        */
-       unsigned int num_of_streams;
-
        struct atomisp_mipi_csi2_device csi2_port[ATOMISP_CAMERA_NR_PORTS];
        struct atomisp_tpg_device tpg;
 
@@ -246,7 +209,7 @@ struct atomisp_device {
        bool isp_fatal_error;
        struct work_struct assert_recovery_work;
 
-       spinlock_t lock; /* Protects asd[i].streaming */
+       spinlock_t lock; /* Protects asd.streaming */
 
        bool need_gfx_throttle;
 
index d1314bdbf7d5e00c0084b1862e4f0f2ea7cdc73c..384f31fc66c519b1b9c5f15eb8d988bd0ccade16 100644 (file)
@@ -626,13 +626,7 @@ atomisp_subdev_streaming_count(struct atomisp_sub_device *asd)
 
 unsigned int atomisp_streaming_count(struct atomisp_device *isp)
 {
-       unsigned int i, sum;
-
-       for (i = 0, sum = 0; i < isp->num_of_streams; i++)
-               sum += isp->asd[i].streaming ==
-                      ATOMISP_DEVICE_STREAMING_ENABLED;
-
-       return sum;
+       return isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED;
 }
 
 /*
@@ -677,18 +671,6 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input)
                return -EINVAL;
        }
 
-       /*
-        * check whether the request camera:
-        * 1: already in use
-        * 2: if in use, whether it is used by other streams
-        */
-       if (isp->inputs[input].asd && isp->inputs[input].asd != asd) {
-               dev_err(isp->dev,
-                       "%s, camera is already used by stream: %d\n", __func__,
-                       isp->inputs[input].asd->index);
-               return -EBUSY;
-       }
-
        camera = isp->inputs[input].camera;
        if (!camera) {
                dev_err(isp->dev, "%s, no camera\n", __func__);
@@ -1112,24 +1094,13 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer
        buf->reserved2 = pipe->frame_config_id[buf->index];
 
        dev_dbg(isp->dev,
-               "dqbuf buffer %d (%s) for asd%d with exp_id %d, isp_config_id %d\n",
-               buf->index, vdev->name, asd->index, buf->reserved >> 16,
-               buf->reserved2);
+               "dqbuf buffer %d (%s) with exp_id %d, isp_config_id %d\n",
+               buf->index, vdev->name, buf->reserved >> 16, buf->reserved2);
        return 0;
 }
 
 enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device *asd)
 {
-       if (ATOMISP_USE_YUVPP(asd))
-               return IA_CSS_PIPE_ID_YUVPP;
-
-       if (asd->continuous_mode->val) {
-               if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
-                       return IA_CSS_PIPE_ID_VIDEO;
-               else
-                       return IA_CSS_PIPE_ID_PREVIEW;
-       }
-
        /*
         * Disable vf_pp and run CSS in video mode. This allows using ISP
         * scaling but it has one frame delay due to CSS internal buffering.
@@ -1164,60 +1135,12 @@ static unsigned int atomisp_sensor_start_stream(struct atomisp_sub_device *asd)
 
        if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO ||
            (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE &&
-            !atomisp_is_mbuscode_raw(
-                asd->fmt[
-                 asd->capture_pad].fmt.code) &&
-            !asd->continuous_mode->val))
+            !atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)))
                return 2;
        else
                return 1;
 }
 
-int atomisp_stream_on_master_slave_sensor(struct atomisp_device *isp,
-       bool isp_timeout)
-{
-       unsigned int master, slave, delay_slave = 0;
-       int ret;
-
-       master = ATOMISP_DEPTH_DEFAULT_MASTER_SENSOR;
-       slave = ATOMISP_DEPTH_DEFAULT_SLAVE_SENSOR;
-       dev_warn(isp->dev,
-                "depth mode use default master=%s.slave=%s.\n",
-                isp->inputs[master].camera->name,
-                isp->inputs[slave].camera->name);
-
-       ret = v4l2_subdev_call(isp->inputs[master].camera, core,
-                              ioctl, ATOMISP_IOC_G_DEPTH_SYNC_COMP,
-                              &delay_slave);
-       if (ret)
-               dev_warn(isp->dev,
-                        "get depth sensor %s compensation delay failed.\n",
-                        isp->inputs[master].camera->name);
-
-       ret = v4l2_subdev_call(isp->inputs[master].camera,
-                              video, s_stream, 1);
-       if (ret) {
-               dev_err(isp->dev, "depth mode master sensor %s stream-on failed.\n",
-                       isp->inputs[master].camera->name);
-               return -EINVAL;
-       }
-
-       if (delay_slave != 0)
-               udelay(delay_slave);
-
-       ret = v4l2_subdev_call(isp->inputs[slave].camera,
-                              video, s_stream, 1);
-       if (ret) {
-               dev_err(isp->dev, "depth mode slave sensor %s stream-on failed.\n",
-                       isp->inputs[slave].camera->name);
-               v4l2_subdev_call(isp->inputs[master].camera, video, s_stream, 0);
-
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 /* Input system HW workaround */
 /* Input system address translation corrupts burst during */
 /* invalidate. SW workaround for this is to set burst length */
@@ -1250,8 +1173,7 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count)
 
        mutex_lock(&isp->mutex);
 
-       dev_dbg(isp->dev, "Start stream on pad %d for asd%d\n",
-               atomisp_subdev_source_pad(vdev), asd->index);
+       dev_dbg(isp->dev, "Start stream on pad %d\n", atomisp_subdev_source_pad(vdev));
 
        ret = atomisp_pipe_check(pipe, false);
        if (ret)
@@ -1266,57 +1188,7 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count)
         */
        sensor_start_stream = atomisp_sensor_start_stream(asd);
 
-       /* Reset pending capture request count. */
-       asd->pending_capture_request = 0;
-
        if (atomisp_subdev_streaming_count(asd) > sensor_start_stream) {
-               /* trigger still capture */
-               if (asd->continuous_mode->val &&
-                   atomisp_subdev_source_pad(vdev)
-                   == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE) {
-                       if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
-                               dev_dbg(isp->dev, "SDV last video raw buffer id: %u\n",
-                                       asd->latest_preview_exp_id);
-                       else
-                               dev_dbg(isp->dev, "ZSL last preview raw buffer id: %u\n",
-                                       asd->latest_preview_exp_id);
-
-                       if (asd->delayed_init == ATOMISP_DELAYED_INIT_QUEUED) {
-                               flush_work(&asd->delayed_init_work);
-                               mutex_unlock(&isp->mutex);
-                               ret = wait_for_completion_interruptible(&asd->init_done);
-                               mutex_lock(&isp->mutex);
-                               if (ret) {
-                                       ret = -ERESTARTSYS;
-                                       goto out_unlock;
-                               }
-                       }
-
-                       /* handle per_frame_setting parameter and buffers */
-                       atomisp_handle_parameter_and_buffer(pipe);
-
-                       /*
-                        * only ZSL/SDV capture request will be here, raise
-                        * the ISP freq to the highest possible to minimize
-                        * the S2S latency.
-                        */
-                       atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
-                       /*
-                        * When asd->enable_raw_buffer_lock->val is true,
-                        * An extra IOCTL is needed to call
-                        * atomisp_css_exp_id_capture and trigger real capture
-                        */
-                       if (!asd->enable_raw_buffer_lock->val) {
-                               ret = atomisp_css_offline_capture_configure(asd,
-                                       asd->params.offline_parm.num_captures,
-                                       asd->params.offline_parm.skip_frames,
-                                       asd->params.offline_parm.offset);
-                               if (ret) {
-                                       ret = -EINVAL;
-                                       goto out_unlock;
-                               }
-                       }
-               }
                atomisp_qbuffers_to_css(asd);
                ret = 0;
                goto out_unlock;
@@ -1396,19 +1268,6 @@ start_sensor:
                        dev_dbg(isp->dev, "DFS auto mode failed!\n");
        }
 
-       if (asd->depth_mode->val && atomisp_streaming_count(isp) ==
-           ATOMISP_DEPTH_SENSOR_STREAMON_COUNT) {
-               ret = atomisp_stream_on_master_slave_sensor(isp, false);
-               if (ret) {
-                       dev_err(isp->dev, "master slave sensor stream on failed!\n");
-                       goto out_unlock;
-               }
-               goto start_delay_wq;
-       } else if (asd->depth_mode->val && (atomisp_streaming_count(isp) <
-                                           ATOMISP_DEPTH_SENSOR_STREAMON_COUNT)) {
-               goto start_delay_wq;
-       }
-
        /* Enable the CSI interface on ANN B0/K0 */
        if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
                                            ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) {
@@ -1427,19 +1286,6 @@ start_sensor:
                goto out_unlock;
        }
 
-start_delay_wq:
-       if (asd->continuous_mode->val) {
-               atomisp_subdev_get_ffmt(&asd->subdev, NULL,
-                                       V4L2_SUBDEV_FORMAT_ACTIVE,
-                                       ATOMISP_SUBDEV_PAD_SINK);
-
-               reinit_completion(&asd->init_done);
-               asd->delayed_init = ATOMISP_DELAYED_INIT_QUEUED;
-               queue_work(asd->delayed_init_workq, &asd->delayed_init_work);
-       } else {
-               asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
-       }
-
 out_unlock:
        mutex_unlock(&isp->mutex);
        return ret;
@@ -1452,16 +1298,15 @@ void atomisp_stop_streaming(struct vb2_queue *vq)
        struct video_device *vdev = &pipe->vdev;
        struct atomisp_device *isp = asd->isp;
        struct pci_dev *pdev = to_pci_dev(isp->dev);
-       bool recreate_streams[MAX_STREAM_NUM] = {0};
        enum ia_css_pipe_id css_pipe_id;
+       bool recreate_stream = false;
        bool first_streamoff = false;
        unsigned long flags;
-       int i, ret;
+       int ret;
 
        mutex_lock(&isp->mutex);
 
-       dev_dbg(isp->dev, "Stop stream on pad %d for asd%d\n",
-               atomisp_subdev_source_pad(vdev), asd->index);
+       dev_dbg(isp->dev, "Stop stream on pad %d\n", atomisp_subdev_source_pad(vdev));
 
        /*
         * There is no guarantee that the buffers queued to / owned by the ISP
@@ -1479,24 +1324,6 @@ void atomisp_stop_streaming(struct vb2_queue *vq)
        if (ret == 0)
                dev_warn(isp->dev, "Warning timeout waiting for CSS to return buffers\n");
 
-       /*
-        * do only videobuf_streamoff for capture & vf pipes in
-        * case of continuous capture
-        */
-       if (asd->continuous_mode->val &&
-           atomisp_subdev_source_pad(vdev) != ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
-           atomisp_subdev_source_pad(vdev) != ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) {
-               if (atomisp_subdev_source_pad(vdev) == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE) {
-                       /* stop continuous still capture if needed */
-                       if (asd->params.offline_parm.num_captures == -1)
-                               atomisp_css_offline_capture_configure(asd,
-                                                                     0, 0, 0);
-                       atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, false);
-               }
-
-               goto out_unlock;
-       }
-
        if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED)
                first_streamoff = true;
 
@@ -1513,11 +1340,6 @@ void atomisp_stop_streaming(struct vb2_queue *vq)
        atomisp_clear_css_buffer_counters(asd);
        atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false);
 
-       if (asd->delayed_init == ATOMISP_DELAYED_INIT_QUEUED) {
-               cancel_work_sync(&asd->delayed_init_work);
-               asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
-       }
-
        css_pipe_id = atomisp_get_css_pipe_id(asd);
        atomisp_css_stop(asd, css_pipe_id, false);
 
@@ -1566,11 +1388,9 @@ stopsensor:
         *
         * So force stream destroy here.
         */
-       for (i = 0; i < isp->num_of_streams; i++) {
-               if (isp->asd[i].stream_prepared) {
-                       atomisp_destroy_pipes_stream_force(&isp->asd[i]);
-                       recreate_streams[i] = true;
-               }
+       if (isp->asd.stream_prepared) {
+               atomisp_destroy_pipes_stream_force(&isp->asd);
+               recreate_stream = true;
        }
 
        /* disable  PUNIT/ISP acknowlede/handshake - SRSE=3 */
@@ -1578,19 +1398,18 @@ stopsensor:
                               isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK);
        dev_err(isp->dev, "atomisp_reset");
        atomisp_reset(isp);
-       for (i = 0; i < isp->num_of_streams; i++) {
-               if (recreate_streams[i]) {
-                       int ret2;
-
-                       ret2 = atomisp_create_pipes_stream(&isp->asd[i]);
-                       if (ret2) {
-                               dev_err(isp->dev, "%s error re-creating streams: %d\n",
-                                       __func__, ret2);
-                               if (!ret)
-                                       ret = ret2;
-                       }
+
+       if (recreate_stream) {
+               int ret2;
+
+               ret2 = atomisp_create_pipes_stream(&isp->asd);
+               if (ret2) {
+                       dev_err(isp->dev, "%s error re-creating streams: %d\n", __func__, ret2);
+                       if (!ret)
+                               ret = ret2;
                }
        }
+
        isp->isp_timeout = false;
 out_unlock:
        mutex_unlock(&isp->mutex);
@@ -2304,9 +2123,6 @@ static long atomisp_vidioc_default(struct file *file, void *fh,
                err = atomisp_set_parameters(vdev, arg);
                break;
 
-       case ATOMISP_IOC_S_CONT_CAPTURE_CONFIG:
-               err = atomisp_offline_capture_configure(asd, arg);
-               break;
        case ATOMISP_IOC_G_METADATA:
                err = atomisp_get_metadata(asd, 0, arg);
                break;
index 59e071f035f9bc058a69503f5e8125ddf978b139..db6da77df06b727a4eca38b9156601dbe7eff65e 100644 (file)
@@ -53,10 +53,4 @@ unsigned int atomisp_streaming_count(struct atomisp_device *isp);
 long atomisp_compat_ioctl32(struct file *file,
                            unsigned int cmd, unsigned long arg);
 
-int atomisp_stream_on_master_slave_sensor(struct atomisp_device *isp,
-       bool isp_timeout);
-
-int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count);
-void atomisp_stop_streaming(struct vb2_queue *vq);
-
 #endif /* __ATOMISP_IOCTL_H__ */
index 9cfb85c61db6480773763d8d234a652f17b2bc53..a0acfdb87177665c18b88941f8b6646a2e72920f 100644 (file)
@@ -189,7 +189,6 @@ static int isp_subdev_subscribe_event(struct v4l2_subdev *sd,
            sub->type != V4L2_EVENT_ATOMISP_METADATA_READY &&
            sub->type != V4L2_EVENT_ATOMISP_PAUSE_BUFFER &&
            sub->type != V4L2_EVENT_ATOMISP_CSS_RESET &&
-           sub->type != V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE &&
            sub->type != V4L2_EVENT_ATOMISP_ACC_COMPLETE)
                return -EINVAL;
 
@@ -410,11 +409,6 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
                        padding_h = 12;
                }
 
-               if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA) {
-                       padding_w = 0;
-                       padding_h = 0;
-               }
-
                if (atomisp_subdev_format_conversion(isp_sd,
                                                     isp_sd->capture_pad)
                    && crop[pad]->width && crop[pad]->height) {
@@ -422,13 +416,8 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
                        crop[pad]->height -= padding_h;
                }
 
-               /* if subdev type is SOC camera,we do not need to set DVS */
-               if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA)
-                       isp_sd->params.video_dis_en = 0;
-
                if (isp_sd->params.video_dis_en &&
-                   isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
-                   !isp_sd->continuous_mode->val) {
+                   isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
                        /* This resolution contains 20 % of DVS slack
                         * (of the desired captured image before
                         * scaling, or 1 / 6 of what we get from the
@@ -459,8 +448,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
                        break;
 
                if (isp_sd->params.video_dis_en &&
-                   isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
-                   !isp_sd->continuous_mode->val) {
+                   isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
                        dvs_w = rounddown(crop[pad]->width / 5,
                                          ATOM_ISP_STEP_WIDTH);
                        dvs_h = rounddown(crop[pad]->height / 5,
@@ -727,11 +715,7 @@ static int __atomisp_update_run_mode(struct atomisp_sub_device *asd)
        struct v4l2_ctrl *c;
        s32 mode;
 
-       if (ctrl->val != ATOMISP_RUN_MODE_VIDEO &&
-           asd->continuous_mode->val)
-               mode = ATOMISP_RUN_MODE_PREVIEW;
-       else
-               mode = ctrl->val;
+       mode = ctrl->val;
 
        c = v4l2_ctrl_find(
                isp->inputs[asd->input_curr].camera->ctrl_handler,
@@ -758,23 +742,9 @@ static int s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct atomisp_sub_device *asd = container_of(
                                             ctrl->handler, struct atomisp_sub_device, ctrl_handler);
-       unsigned int streaming;
-       unsigned long flags;
-
        switch (ctrl->id) {
        case V4L2_CID_RUN_MODE:
                return __atomisp_update_run_mode(asd);
-       case V4L2_CID_DEPTH_MODE:
-               /* Use spinlock instead of mutex to avoid possible locking issues */
-               spin_lock_irqsave(&asd->isp->lock, flags);
-               streaming = asd->streaming;
-               spin_unlock_irqrestore(&asd->isp->lock, flags);
-               if (streaming != ATOMISP_DEVICE_STREAMING_DISABLED) {
-                       dev_err(asd->isp->dev,
-                               "ISP is streaming, it is not supported to change the depth mode\n");
-                       return -EINVAL;
-               }
-               break;
        }
 
        return 0;
@@ -784,17 +754,6 @@ static const struct v4l2_ctrl_ops ctrl_ops = {
        .s_ctrl = &s_ctrl,
 };
 
-static const struct v4l2_ctrl_config ctrl_fmt_auto = {
-       .ops = &ctrl_ops,
-       .id = V4L2_CID_FMT_AUTO,
-       .name = "Automatic format guessing",
-       .type = V4L2_CTRL_TYPE_BOOLEAN,
-       .min = 0,
-       .max = 1,
-       .step = 1,
-       .def = 1,
-};
-
 static const char *const ctrl_run_mode_menu[] = {
        NULL,
        "Video",
@@ -830,24 +789,6 @@ static const struct v4l2_ctrl_config ctrl_vfpp = {
        .qmenu = ctrl_vfpp_mode_menu,
 };
 
-/*
- * Control for ISP continuous mode
- *
- * When enabled, capture processing is possible without
- * stopping the preview pipeline. When disabled, ISP needs
- * to be restarted between preview and capture.
- */
-static const struct v4l2_ctrl_config ctrl_continuous_mode = {
-       .ops = &ctrl_ops,
-       .id = V4L2_CID_ATOMISP_CONTINUOUS_MODE,
-       .type = V4L2_CTRL_TYPE_BOOLEAN,
-       .name = "Continuous mode",
-       .min = 0,
-       .max = 1,
-       .step = 1,
-       .def = 0,
-};
-
 /*
  * Control for continuous mode raw buffer size
  *
@@ -930,24 +871,6 @@ static const struct v4l2_ctrl_config ctrl_disable_dz = {
        .def = 0,
 };
 
-/*
- * Control for ISP depth mode
- *
- * When enabled, that means ISP will deal with dual streams and sensors will be
- * in slave/master mode.
- * slave sensor will have no output until master sensor is streamed on.
- */
-static const struct v4l2_ctrl_config ctrl_depth_mode = {
-       .ops = &ctrl_ops,
-       .id = V4L2_CID_DEPTH_MODE,
-       .type = V4L2_CTRL_TYPE_BOOLEAN,
-       .name = "Depth mode",
-       .min = 0,
-       .max = 1,
-       .step = 1,
-       .def = 0,
-};
-
 static int atomisp_init_subdev_pipe(struct atomisp_sub_device *asd,
                                    struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type)
 {
@@ -995,7 +918,7 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
        int ret;
 
        v4l2_subdev_init(sd, &isp_subdev_v4l2_ops);
-       sprintf(sd->name, "ATOMISP_SUBDEV_%d", asd->index);
+       sprintf(sd->name, "ATOMISP_SUBDEV");
        v4l2_set_subdevdata(sd, asd);
        sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
 
@@ -1066,14 +989,10 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
        if (ret)
                return ret;
 
-       asd->fmt_auto = v4l2_ctrl_new_custom(&asd->ctrl_handler,
-                                            &ctrl_fmt_auto, NULL);
        asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
                                             &ctrl_run_mode, NULL);
        asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler,
                                         &ctrl_vfpp, NULL);
-       asd->continuous_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
-                              &ctrl_continuous_mode, NULL);
        asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler,
                                     &ctrl_continuous_viewfinder,
                                     NULL);
@@ -1086,10 +1005,6 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
            v4l2_ctrl_new_custom(&asd->ctrl_handler,
                                 &ctrl_enable_raw_buffer_lock,
                                 NULL);
-       asd->depth_mode =
-           v4l2_ctrl_new_custom(&asd->ctrl_handler,
-                                &ctrl_depth_mode,
-                                NULL);
        asd->disable_dz =
            v4l2_ctrl_new_custom(&asd->ctrl_handler,
                                 &ctrl_disable_dz,
@@ -1103,21 +1018,16 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
 
 int atomisp_create_pads_links(struct atomisp_device *isp)
 {
-       struct atomisp_sub_device *asd;
-       int i, j, ret = 0;
+       int i, ret;
 
-       isp->num_of_streams = 2;
        for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
-               for (j = 0; j < isp->num_of_streams; j++) {
-                       ret =
-                           media_create_pad_link(&isp->csi2_port[i].subdev.
-                                                 entity, CSI2_PAD_SOURCE,
-                                                 &isp->asd[j].subdev.entity,
-                                                 ATOMISP_SUBDEV_PAD_SINK, 0);
-                       if (ret < 0)
-                               return ret;
-               }
+               ret = media_create_pad_link(&isp->csi2_port[i].subdev.entity,
+                                           CSI2_PAD_SOURCE, &isp->asd.subdev.entity,
+                                           ATOMISP_SUBDEV_PAD_SINK, 0);
+               if (ret < 0)
+                       return ret;
        }
+
        for (i = 0; i < isp->input_cnt; i++) {
                /* Don't create links for the test-pattern-generator */
                if (isp->inputs[i].type == TEST_PATTERN)
@@ -1132,33 +1042,28 @@ int atomisp_create_pads_links(struct atomisp_device *isp)
                if (ret < 0)
                        return ret;
        }
-       for (i = 0; i < isp->num_of_streams; i++) {
-               asd = &isp->asd[i];
-               ret = media_create_pad_link(&asd->subdev.entity,
-                                           ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW,
-                                           &asd->video_out_preview.vdev.entity,
-                                           0, 0);
-               if (ret < 0)
-                       return ret;
-               ret = media_create_pad_link(&asd->subdev.entity,
-                                           ATOMISP_SUBDEV_PAD_SOURCE_VF,
-                                           &asd->video_out_vf.vdev.entity, 0,
-                                           0);
-               if (ret < 0)
-                       return ret;
-               ret = media_create_pad_link(&asd->subdev.entity,
-                                           ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
-                                           &asd->video_out_capture.vdev.entity,
-                                           0, 0);
-               if (ret < 0)
-                       return ret;
-               ret = media_create_pad_link(&asd->subdev.entity,
-                                           ATOMISP_SUBDEV_PAD_SOURCE_VIDEO,
-                                           &asd->video_out_video_capture.vdev.
-                                           entity, 0, 0);
-               if (ret < 0)
-                       return ret;
-       }
+
+       ret = media_create_pad_link(&isp->asd.subdev.entity,
+                                   ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW,
+                                   &isp->asd.video_out_preview.vdev.entity, 0, 0);
+       if (ret < 0)
+               return ret;
+       ret = media_create_pad_link(&isp->asd.subdev.entity,
+                                   ATOMISP_SUBDEV_PAD_SOURCE_VF,
+                                   &isp->asd.video_out_vf.vdev.entity, 0, 0);
+       if (ret < 0)
+               return ret;
+       ret = media_create_pad_link(&isp->asd.subdev.entity,
+                                   ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
+                                   &isp->asd.video_out_capture.vdev.entity, 0, 0);
+       if (ret < 0)
+               return ret;
+       ret = media_create_pad_link(&isp->asd.subdev.entity,
+                                   ATOMISP_SUBDEV_PAD_SOURCE_VIDEO,
+                                   &isp->asd.video_out_video_capture.vdev.entity, 0, 0);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
@@ -1254,29 +1159,13 @@ error:
  */
 int atomisp_subdev_init(struct atomisp_device *isp)
 {
-       struct atomisp_sub_device *asd;
-       int i, ret = 0;
+       int ret;
 
-       /*
-        * CSS2.0 running ISP2400 support
-        * multiple streams
-        */
-       isp->num_of_streams = 2;
-       isp->asd = devm_kzalloc(isp->dev, sizeof(struct atomisp_sub_device) *
-                               isp->num_of_streams, GFP_KERNEL);
-       if (!isp->asd)
-               return -ENOMEM;
-       for (i = 0; i < isp->num_of_streams; i++) {
-               asd = &isp->asd[i];
-               asd->isp = isp;
-               isp_subdev_init_params(asd);
-               asd->index = i;
-               ret = isp_subdev_init_entities(asd);
-               if (ret < 0) {
-                       atomisp_subdev_cleanup_entities(asd);
-                       break;
-               }
-       }
+       isp->asd.isp = isp;
+       isp_subdev_init_params(&isp->asd);
+       ret = isp_subdev_init_entities(&isp->asd);
+       if (ret < 0)
+               atomisp_subdev_cleanup_entities(&isp->asd);
 
        return ret;
 }
index daa6077a83bdd5eca3419db4b37e5f8ebc156941..fee663bc415a120ca981694f97d2fc038913b80c 100644 (file)
@@ -183,9 +183,6 @@ struct atomisp_css_params {
 };
 
 struct atomisp_subdev_params {
-       /* FIXME: Determines whether raw capture buffer are being passed to
-        * user space. Unimplemented for now. */
-       int online_process;
        int yuv_ds_en;
        unsigned int color_effect;
        bool gdc_cac_en;
@@ -237,8 +234,6 @@ struct atomisp_subdev_params {
        enum atomisp_flash_state flash_state;
        enum atomisp_frame_status last_frame_status;
 
-       /* continuous capture */
-       struct atomisp_cont_capture_conf offline_parm;
        /* Flag to check if driver needs to update params to css */
        bool css_update_params_needed;
 };
@@ -264,11 +259,8 @@ struct atomisp_sub_device {
        /* struct isp_subdev_params params; */
        struct atomisp_device *isp;
        struct v4l2_ctrl_handler ctrl_handler;
-       struct v4l2_ctrl *fmt_auto;
        struct v4l2_ctrl *run_mode;
-       struct v4l2_ctrl *depth_mode;
        struct v4l2_ctrl *vfpp;
-       struct v4l2_ctrl *continuous_mode;
        struct v4l2_ctrl *continuous_raw_buffer_size;
        struct v4l2_ctrl *continuous_viewfinder;
        struct v4l2_ctrl *enable_raw_buffer_lock;
@@ -307,7 +299,6 @@ struct atomisp_sub_device {
        spinlock_t dis_stats_lock;
 
        struct ia_css_frame *vf_frame; /* TODO: needed? */
-       struct ia_css_frame *raw_output_frame;
        enum atomisp_frame_status frame_status[VIDEO_MAX_FRAME];
 
        /* This field specifies which camera (v4l2 input) is selected. */
@@ -324,23 +315,11 @@ struct atomisp_sub_device {
        unsigned int streaming;
        bool stream_prepared; /* whether css stream is created */
 
-       /* subdev index: will be used to show which subdev is holding the
-        * resource, like which camera is used by which subdev
-        */
-       unsigned int index;
-
-       /* delayed memory allocation for css */
-       struct completion init_done;
-       struct workqueue_struct *delayed_init_workq;
-       unsigned int delayed_init;
-       struct work_struct delayed_init_work;
-
        unsigned int latest_preview_exp_id; /* CSS ZSL/SDV raw buffer id */
 
        unsigned int mipi_frame_size;
 
        bool copy_mode; /* CSI2+ use copy mode */
-       bool yuvpp_mode;        /* CSI2+ yuvpp pipe */
 
        int raw_buffer_bitmap[ATOMISP_MAX_EXP_ID / 32 +
                                                 1]; /* Record each Raw Buffer lock status */
@@ -352,7 +331,6 @@ struct atomisp_sub_device {
 
        struct atomisp_resolution sensor_array_res;
        bool high_speed_mode; /* Indicate whether now is a high speed mode */
-       int pending_capture_request; /* Indicates the number of pending capture requests. */
 
        unsigned int preview_exp_id;
        unsigned int postview_exp_id;
index ba628f7cf385bb8362a078babdbb517c3ae1d8ef..3f315dabbeeb4c9ad5ca105b3489a9c378e91fe7 100644 (file)
@@ -64,10 +64,10 @@ module_param(dbg_level, int, 0644);
 MODULE_PARM_DESC(dbg_level, "debug message level (default:0)");
 
 /* log function switch */
-int dbg_func = 2;
+int dbg_func = 1;
 module_param(dbg_func, int, 0644);
 MODULE_PARM_DESC(dbg_func,
-                "log function switch non/trace_printk/printk (default:printk)");
+                "log function switch non/printk (default:printk)");
 
 int mipicsi_flag;
 module_param(mipicsi_flag, int, 0644);
@@ -753,8 +753,6 @@ static int atomisp_suspend(struct device *dev)
 {
        struct atomisp_device *isp = (struct atomisp_device *)
                                     dev_get_drvdata(dev);
-       /* FIXME: only has one isp_subdev at present */
-       struct atomisp_sub_device *asd = &isp->asd[0];
        unsigned long flags;
 
        /*
@@ -765,7 +763,7 @@ static int atomisp_suspend(struct device *dev)
                return -EBUSY;
 
        spin_lock_irqsave(&isp->lock, flags);
-       if (asd->streaming != ATOMISP_DEVICE_STREAMING_DISABLED) {
+       if (isp->asd.streaming != ATOMISP_DEVICE_STREAMING_DISABLED) {
                spin_unlock_irqrestore(&isp->lock, flags);
                dev_err(isp->dev, "atomisp cannot suspend at this time.\n");
                return -EINVAL;
@@ -842,8 +840,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp)
        for (i = 0; i < isp->input_cnt; i++) {
                struct camera_mipi_info *mipi_info;
 
-               if (isp->inputs[i].type != RAW_CAMERA &&
-                   isp->inputs[i].type != SOC_CAMERA)
+               if (isp->inputs[i].type != RAW_CAMERA)
                        continue;
 
                mipi_info = atomisp_to_sensor_mipi_info(isp->inputs[i].camera);
@@ -923,8 +920,7 @@ static int atomisp_subdev_probe(struct atomisp_device *isp)
                int camera_count = 0;
 
                for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) {
-                       if (subdevs->type == RAW_CAMERA ||
-                           subdevs->type == SOC_CAMERA)
+                       if (subdevs->type == RAW_CAMERA)
                                camera_count++;
                }
                if (camera_count)
@@ -945,9 +941,6 @@ static int atomisp_subdev_probe(struct atomisp_device *isp)
                case RAW_CAMERA:
                        dev_dbg(isp->dev, "raw_index: %d\n", raw_index);
                        raw_index = isp->input_cnt;
-                       fallthrough;
-               case SOC_CAMERA:
-                       dev_dbg(isp->dev, "SOC_INDEX: %d\n", isp->input_cnt);
                        if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) {
                                dev_warn(isp->dev,
                                         "too many atomisp inputs, ignored\n");
@@ -974,7 +967,6 @@ static int atomisp_subdev_probe(struct atomisp_device *isp)
                        isp->motor = subdevs->subdev;
                        break;
                case LED_FLASH:
-               case XENON_FLASH:
                        if (isp->flash) {
                                dev_warn(isp->dev, "too many atomisp flash devices\n");
                                continue;
@@ -1010,8 +1002,7 @@ static void atomisp_unregister_entities(struct atomisp_device *isp)
        unsigned int i;
        struct v4l2_subdev *sd, *next;
 
-       for (i = 0; i < isp->num_of_streams; i++)
-               atomisp_subdev_unregister_entities(&isp->asd[i]);
+       atomisp_subdev_unregister_entities(&isp->asd);
        atomisp_tpg_unregister_entities(&isp->tpg);
        for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++)
                atomisp_mipi_csi2_unregister_entities(&isp->csi2_port[i]);
@@ -1070,38 +1061,10 @@ static int atomisp_register_entities(struct atomisp_device *isp)
                goto tpg_register_failed;
        }
 
-       for (i = 0; i < isp->num_of_streams; i++) {
-               struct atomisp_sub_device *asd = &isp->asd[i];
-
-               ret = atomisp_subdev_register_subdev(asd, &isp->v4l2_dev);
-               if (ret < 0) {
-                       dev_err(isp->dev, "atomisp_subdev_register_subdev fail\n");
-                       for (; i > 0; i--)
-                               atomisp_subdev_unregister_entities(
-                                   &isp->asd[i - 1]);
-                       goto subdev_register_failed;
-               }
-       }
-
-       for (i = 0; i < isp->num_of_streams; i++) {
-               struct atomisp_sub_device *asd = &isp->asd[i];
-
-               init_completion(&asd->init_done);
-
-               asd->delayed_init_workq =
-                   alloc_workqueue(isp->v4l2_dev.name, WQ_CPU_INTENSIVE,
-                                   1);
-               if (!asd->delayed_init_workq) {
-                       dev_err(isp->dev,
-                               "Failed to initialize delayed init workq\n");
-                       ret = -ENOMEM;
-
-                       for (; i > 0; i--)
-                               destroy_workqueue(isp->asd[i - 1].
-                                                 delayed_init_workq);
-                       goto wq_alloc_failed;
-               }
-               INIT_WORK(&asd->delayed_init_work, atomisp_delayed_init_work);
+       ret = atomisp_subdev_register_subdev(&isp->asd, &isp->v4l2_dev);
+       if (ret < 0) {
+               dev_err(isp->dev, "atomisp_subdev_register_subdev fail\n");
+               goto subdev_register_failed;
        }
 
        for (i = 0; i < isp->input_cnt; i++) {
@@ -1126,13 +1089,7 @@ static int atomisp_register_entities(struct atomisp_device *isp)
        return 0;
 
 link_failed:
-       for (i = 0; i < isp->num_of_streams; i++)
-               destroy_workqueue(isp->asd[i].
-                                 delayed_init_workq);
-wq_alloc_failed:
-       for (i = 0; i < isp->num_of_streams; i++)
-               atomisp_subdev_unregister_entities(
-                   &isp->asd[i]);
+       atomisp_subdev_unregister_entities(&isp->asd);
 subdev_register_failed:
        atomisp_tpg_unregister_entities(&isp->tpg);
 tpg_register_failed:
@@ -1148,13 +1105,11 @@ v4l2_device_failed:
 
 static int atomisp_register_device_nodes(struct atomisp_device *isp)
 {
-       int i, err;
+       int err;
 
-       for (i = 0; i < isp->num_of_streams; i++) {
-               err = atomisp_subdev_register_video_nodes(&isp->asd[i], &isp->v4l2_dev);
-               if (err)
-                       return err;
-       }
+       err = atomisp_subdev_register_video_nodes(&isp->asd, &isp->v4l2_dev);
+       if (err)
+               return err;
 
        err = atomisp_create_pads_links(isp);
        if (err)
index df81a9b744c2061f22bdb764c855fc71cbaceaf6..a5a431c14ea78bf0640e323cea2315b59d5b0cd7 100644 (file)
@@ -1106,9 +1106,11 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
        struct av7110 *av7110;
 
        /* pointer casting paranoia... */
-       BUG_ON(!demux);
+       if (WARN_ON(!demux))
+               return -EIO;
        dvbdemux = demux->priv;
-       BUG_ON(!dvbdemux);
+       if (WARN_ON(!dvbdemux))
+               return -EIO;
        av7110 = dvbdemux->priv;
 
        dprintk(4, "%p\n", av7110);
index 0bf513c26b6b5e363ea9fab610ac3b43626ab0d6..a5c5bebad306131ecf350e4f74611d28123859d3 100644 (file)
@@ -823,10 +823,10 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s
                av7110_ipack_flush(ipack);
 
        if (buf[3] & ADAPT_FIELD) {
+               if (buf[4] > len - 1 - 4)
+                       return 0;
                len -= buf[4] + 1;
                buf += buf[4] + 1;
-               if (!len)
-                       return 0;
        }
 
        av7110_ipack_instant_repack(buf + 4, len - 4, ipack);
index 93ca31e38ddd3949169ee0b1f11eb41ae2f58c9c..a0be377172596e0bb7d51fd87b2e88072ef831b3 100644 (file)
@@ -1007,7 +1007,8 @@ static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
 
        if (av7110->bmp_state == BMP_LOADING) {
                /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
-               BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
+               if (WARN_ON(FW_VERSION(av7110->arm_app) >= 0x261e))
+                       return -EIO;
                rc = WaitUntilBmpLoaded(av7110);
                if (rc)
                        return rc;
index c89f536f699c88ce9920eb77674e2b60ea60d32c..ed2c605808e8950b4fe8a7b0013671ab240798fb 100644 (file)
@@ -213,25 +213,14 @@ static const struct v4l2_audio msp3400_v4l2_audio = {
        .capability = V4L2_AUDCAP_STEREO
 };
 
-static int av7110_dvb_c_switch(struct saa7146_fh *fh)
+static int av7110_dvb_c_switch(struct saa7146_dev *dev)
 {
-       struct saa7146_dev *dev = fh->dev;
-       struct saa7146_vv *vv = dev->vv_data;
        struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
        u16 adswitch;
-       int source, sync, err;
+       int source, sync;
 
        dprintk(4, "%p\n", av7110);
 
-       if ((vv->video_status & STATUS_OVERLAY) != 0) {
-               vv->ov_suspend = vv->video_fh;
-               err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
-               if (err != 0) {
-                       dprintk(2, "suspending video failed\n");
-                       vv->ov_suspend = NULL;
-               }
-       }
-
        if (0 != av7110->current_input) {
                dprintk(1, "switching to analog TV:\n");
                adswitch = 1;
@@ -300,17 +289,12 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
 
        saa7146_set_hps_source_and_sync(dev, source, sync);
 
-       if (vv->ov_suspend != NULL) {
-               saa7146_start_preview(vv->ov_suspend);
-               vv->ov_suspend = NULL;
-       }
-
        return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
        u16 stereo_det;
        s8 stereo;
@@ -354,7 +338,7 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
 
 static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
        u16 fm_matrix, src;
        dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
@@ -398,7 +382,7 @@ static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *
 
 static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x\n", f->frequency);
@@ -414,7 +398,7 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency
 
 static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x\n", f->frequency);
@@ -444,7 +428,7 @@ static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_fre
 
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
@@ -464,7 +448,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 
 static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        *input = av7110->current_input;
@@ -474,7 +458,7 @@ static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
 
 static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
@@ -486,7 +470,29 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
                return -EINVAL;
 
        av7110->current_input = input;
-       return av7110_dvb_c_switch(fh);
+       return av7110_dvb_c_switch(dev);
+}
+
+static int vidioc_enum_output(struct file *file, void *fh, struct v4l2_output *o)
+{
+       if (o->index)
+               return -EINVAL;
+       strscpy(o->name, "Video Output", sizeof(o->name));
+       o->type = V4L2_OUTPUT_TYPE_ANALOG;
+       o->std = V4L2_STD_NTSC_M | V4L2_STD_PAL_BG;
+       o->capabilities = V4L2_OUT_CAP_STD;
+       return 0;
+}
+
+static int vidioc_g_output(struct file *file, void *fh, unsigned int *output)
+{
+       *output = 0;
+       return 0;
+}
+
+static int vidioc_s_output(struct file *file, void *fh, unsigned int output)
+{
+       return output ? -EINVAL : 0;
 }
 
 static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
@@ -500,7 +506,7 @@ static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
 
 static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
@@ -514,7 +520,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
 
 static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
@@ -526,7 +532,7 @@ static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *
 static int vidioc_g_sliced_vbi_cap(struct file *file, void *fh,
                                        struct v4l2_sliced_vbi_cap *cap)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
@@ -542,7 +548,7 @@ static int vidioc_g_sliced_vbi_cap(struct file *file, void *fh,
 static int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh,
                                        struct v4l2_format *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        dprintk(2, "VIDIOC_G_FMT:\n");
@@ -552,59 +558,58 @@ static int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh,
        if (av7110->wssMode) {
                f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
                f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
-               f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
        }
+       f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
+       return 0;
+}
+
+static int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *fh,
+                                        struct v4l2_format *f)
+{
+       struct saa7146_dev *dev = video_drvdata(file);
+       struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+       bool want_wss = (f->fmt.sliced.service_set & V4L2_SLICED_WSS_625) ||
+               (!f->fmt.sliced.service_set &&
+                f->fmt.sliced.service_lines[0][23] == V4L2_SLICED_WSS_625);
+
+       dprintk(2, "VIDIOC_G_FMT:\n");
+       if (FW_VERSION(av7110->arm_app) < 0x2623)
+               return -EINVAL;
+       memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
+       if (want_wss) {
+               f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+               f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+       }
+       f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
        return 0;
 }
 
 static int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh,
                                        struct v4l2_format *f)
 {
-       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
 
        dprintk(2, "VIDIOC_S_FMT\n");
-       if (FW_VERSION(av7110->arm_app) < 0x2623)
+       if (vidioc_try_fmt_sliced_vbi_out(file, fh, f))
                return -EINVAL;
-       if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
-           f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
-               memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
+       if (f->fmt.sliced.service_set & V4L2_SLICED_WSS_625) {
+               /* WSS controlled by userspace */
+               av7110->wssMode = 1;
+               av7110->wssData = 0;
+       } else {
                /* WSS controlled by firmware */
                av7110->wssMode = 0;
                av7110->wssData = 0;
                return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
                                     SetWSSConfig, 1, 0);
-       } else {
-               memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
-               f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
-               f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
-               f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
-               /* WSS controlled by userspace */
-               av7110->wssMode = 1;
-               av7110->wssData = 0;
        }
        return 0;
 }
 
-static int av7110_vbi_reset(struct file *file)
-{
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
-       struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
-
-       dprintk(2, "%s\n", __func__);
-       av7110->wssMode = 0;
-       av7110->wssData = 0;
-       if (FW_VERSION(av7110->arm_app) < 0x2623)
-               return 0;
-       else
-               return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
-}
-
 static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
 {
-       struct saa7146_fh *fh = file->private_data;
-       struct saa7146_dev *dev = fh->dev;
+       struct saa7146_dev *dev = video_drvdata(file);
        struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
        struct v4l2_sliced_vbi_data d;
        int rc;
@@ -819,13 +824,16 @@ int av7110_init_v4l(struct av7110 *av7110)
        vv_data->vid_ops.vidioc_s_audio = vidioc_s_audio;
        vv_data->vid_ops.vidioc_g_fmt_vbi_cap = NULL;
 
-       vv_data->vbi_ops.vidioc_g_tuner = vidioc_g_tuner;
-       vv_data->vbi_ops.vidioc_s_tuner = vidioc_s_tuner;
-       vv_data->vbi_ops.vidioc_g_frequency = vidioc_g_frequency;
-       vv_data->vbi_ops.vidioc_s_frequency = vidioc_s_frequency;
+       vv_data->vbi_ops.vidioc_enum_output = vidioc_enum_output;
+       vv_data->vbi_ops.vidioc_g_output = vidioc_g_output;
+       vv_data->vbi_ops.vidioc_s_output = vidioc_s_output;
+       vv_data->vbi_ops.vidioc_g_parm = NULL;
        vv_data->vbi_ops.vidioc_g_fmt_vbi_cap = NULL;
+       vv_data->vbi_ops.vidioc_try_fmt_vbi_cap = NULL;
+       vv_data->vbi_ops.vidioc_s_fmt_vbi_cap = NULL;
        vv_data->vbi_ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
        vv_data->vbi_ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
+       vv_data->vbi_ops.vidioc_try_fmt_sliced_vbi_out = vidioc_try_fmt_sliced_vbi_out;
        vv_data->vbi_ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
 
        if (FW_VERSION(av7110->arm_app) < 0x2623)
@@ -866,7 +874,7 @@ static struct saa7146_standard standard[] = {
                .h_offset       = 0x48, .h_pixels       = 708,
                .v_max_out      = 576,  .h_max_out      = 768,
        }, {
-               .name   = "NTSC",       .id             = V4L2_STD_NTSC,
+               .name   = "NTSC",       .id             = V4L2_STD_NTSC_M,
                .v_offset       = 0x10, .v_field        = 244,
                .h_offset       = 0x40, .h_pixels       = 708,
                .v_max_out      = 480,  .h_max_out      = 640,
@@ -880,7 +888,7 @@ static struct saa7146_standard analog_standard[] = {
                .h_offset       = 0x08, .h_pixels       = 708,
                .v_max_out      = 576,  .h_max_out      = 768,
        }, {
-               .name   = "NTSC",       .id             = V4L2_STD_NTSC,
+               .name   = "NTSC",       .id             = V4L2_STD_NTSC_M,
                .v_offset       = 0x10, .v_field        = 244,
                .h_offset       = 0x40, .h_pixels       = 708,
                .v_max_out      = 480,  .h_max_out      = 640,
@@ -894,7 +902,7 @@ static struct saa7146_standard dvb_standard[] = {
                .h_offset       = 0x48, .h_pixels       = 708,
                .v_max_out      = 576,  .h_max_out      = 768,
        }, {
-               .name   = "NTSC",       .id             = V4L2_STD_NTSC,
+               .name   = "NTSC",       .id             = V4L2_STD_NTSC_M,
                .v_offset       = 0x10, .v_field        = 244,
                .h_offset       = 0x40, .h_pixels       = 708,
                .v_max_out      = 480,  .h_max_out      = 640,
@@ -930,8 +938,6 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
        .num_stds       = ARRAY_SIZE(standard),
        .std_callback   = &std_callback,
 
-       .vbi_fops.open  = av7110_vbi_reset,
-       .vbi_fops.release = av7110_vbi_reset,
        .vbi_fops.write = av7110_vbi_write,
 };
 
@@ -945,8 +951,6 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
        .num_stds       = ARRAY_SIZE(standard),
        .std_callback   = &std_callback,
 
-       .vbi_fops.open  = av7110_vbi_reset,
-       .vbi_fops.release = av7110_vbi_reset,
        .vbi_fops.write = av7110_vbi_write,
 };
 
index 99e61bbfc9bc7a702ad321677c56101461f9bb7f..61c5afa581424299070a0d945808e5830d613dd3 100644 (file)
@@ -824,8 +824,10 @@ static int isc_try_configure_pipeline(struct isc_device *isc)
 static void isc_try_fse(struct isc_device *isc,
                        struct v4l2_subdev_state *sd_state)
 {
+       struct v4l2_subdev_frame_size_enum fse = {
+               .which = V4L2_SUBDEV_FORMAT_TRY,
+       };
        int ret;
-       struct v4l2_subdev_frame_size_enum fse = {};
 
        /*
         * If we do not know yet which format the subdev is using, we cannot
@@ -835,7 +837,6 @@ static void isc_try_fse(struct isc_device *isc,
                return;
 
        fse.code = isc->try_config.sd_format->mbus_code;
-       fse.which = V4L2_SUBDEV_FORMAT_TRY;
 
        ret = v4l2_subdev_call(isc->current_subdev->sd, pad, enum_frame_size,
                               sd_state, &fse);
@@ -860,8 +861,8 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f,
        struct v4l2_pix_format *pixfmt = &f->fmt.pix;
        struct v4l2_subdev_pad_config pad_cfg = {};
        struct v4l2_subdev_state pad_state = {
-               .pads = &pad_cfg
-               };
+               .pads = &pad_cfg,
+       };
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
        };
index ba0614f981a2e6c915f373afa848c8047d9727ea..cc86ebcc76af518c48176928e87875dddd6d4d42 100644 (file)
@@ -389,7 +389,6 @@ static int atmel_isc_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct isc_device *isc;
-       struct resource *res;
        void __iomem *io_base;
        struct isc_subdev_entity *subdev_entity;
        int irq;
@@ -403,8 +402,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, isc);
        isc->dev = dev;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       io_base = devm_ioremap_resource(dev, res);
+       io_base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(io_base))
                return PTR_ERR(io_base);
 
@@ -580,7 +578,7 @@ unprepare_hclk:
        return ret;
 }
 
-static int atmel_isc_remove(struct platform_device *pdev)
+static void atmel_isc_remove(struct platform_device *pdev)
 {
        struct isc_device *isc = platform_get_drvdata(pdev);
 
@@ -594,8 +592,6 @@ static int atmel_isc_remove(struct platform_device *pdev)
        clk_disable_unprepare(isc->hclock);
 
        atmel_isc_clk_cleanup(isc);
-
-       return 0;
 }
 
 static int __maybe_unused isc_runtime_suspend(struct device *dev)
@@ -638,7 +634,7 @@ MODULE_DEVICE_TABLE(of, atmel_isc_of_match);
 
 static struct platform_driver atmel_isc_driver = {
        .probe  = atmel_isc_probe,
-       .remove = atmel_isc_remove,
+       .remove_new = atmel_isc_remove,
        .driver = {
                .name           = "atmel-sama5d2-isc",
                .pm             = &atmel_isc_dev_pm_ops,
index 01ababdfcbd937f79bd3910c929000aea881d608..68ef3374d25e6eea93c3092f32bd7abfdd9060d2 100644 (file)
@@ -378,7 +378,6 @@ static int microchip_xisc_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct isc_device *isc;
-       struct resource *res;
        void __iomem *io_base;
        struct isc_subdev_entity *subdev_entity;
        int irq;
@@ -392,8 +391,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, isc);
        isc->dev = dev;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       io_base = devm_ioremap_resource(dev, res);
+       io_base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(io_base))
                return PTR_ERR(io_base);
 
@@ -549,7 +547,7 @@ unprepare_hclk:
        return ret;
 }
 
-static int microchip_xisc_remove(struct platform_device *pdev)
+static void microchip_xisc_remove(struct platform_device *pdev)
 {
        struct isc_device *isc = platform_get_drvdata(pdev);
 
@@ -562,8 +560,6 @@ static int microchip_xisc_remove(struct platform_device *pdev)
        clk_disable_unprepare(isc->hclock);
 
        atmel_isc_clk_cleanup(isc);
-
-       return 0;
 }
 
 static int __maybe_unused xisc_runtime_suspend(struct device *dev)
@@ -601,7 +597,7 @@ MODULE_DEVICE_TABLE(of, microchip_xisc_of_match);
 
 static struct platform_driver microchip_xisc_driver = {
        .probe  = microchip_xisc_probe,
-       .remove = microchip_xisc_remove,
+       .remove_new = microchip_xisc_remove,
        .driver = {
                .name           = "microchip-sama7g5-xisc",
                .pm             = &microchip_xisc_dev_pm_ops,
index 93ba092360105ad729c083ab521495668ff6efaa..4364df27c6d281582c8f506cb676d40fd12b18d4 100644 (file)
@@ -353,12 +353,13 @@ static int capture_legacy_enum_fmt_vid_cap(struct file *file, void *fh,
 {
        struct capture_priv *priv = video_drvdata(file);
        const struct imx_media_pixfmt *cc_src;
-       struct v4l2_subdev_format fmt_src;
+       struct v4l2_subdev_format fmt_src = {
+               .pad = priv->src_sd_pad,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        u32 fourcc;
        int ret;
 
-       fmt_src.pad = priv->src_sd_pad;
-       fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(priv->src_sd, pad, get_fmt, NULL, &fmt_src);
        if (ret) {
                dev_err(priv->dev, "failed to get src_sd format\n");
@@ -426,11 +427,12 @@ static int capture_legacy_try_fmt_vid_cap(struct file *file, void *fh,
                                          struct v4l2_format *f)
 {
        struct capture_priv *priv = video_drvdata(file);
-       struct v4l2_subdev_format fmt_src;
+       struct v4l2_subdev_format fmt_src = {
+               .pad = priv->src_sd_pad,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
-       fmt_src.pad = priv->src_sd_pad;
-       fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(priv->src_sd, pad, get_fmt, NULL, &fmt_src);
        if (ret)
                return ret;
@@ -445,7 +447,10 @@ static int capture_legacy_s_fmt_vid_cap(struct file *file, void *fh,
                                        struct v4l2_format *f)
 {
        struct capture_priv *priv = video_drvdata(file);
-       struct v4l2_subdev_format fmt_src;
+       struct v4l2_subdev_format fmt_src = {
+               .pad = priv->src_sd_pad,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        const struct imx_media_pixfmt *cc;
        int ret;
 
@@ -454,8 +459,6 @@ static int capture_legacy_s_fmt_vid_cap(struct file *file, void *fh,
                return -EBUSY;
        }
 
-       fmt_src.pad = priv->src_sd_pad;
-       fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(priv->src_sd, pad, get_fmt, NULL, &fmt_src);
        if (ret)
                return ret;
@@ -501,14 +504,14 @@ static int capture_legacy_g_parm(struct file *file, void *fh,
                                 struct v4l2_streamparm *a)
 {
        struct capture_priv *priv = video_drvdata(file);
-       struct v4l2_subdev_frame_interval fi;
+       struct v4l2_subdev_frame_interval fi = {
+               .pad = priv->src_sd_pad,
+       };
        int ret;
 
        if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       memset(&fi, 0, sizeof(fi));
-       fi.pad = priv->src_sd_pad;
        ret = v4l2_subdev_call(priv->src_sd, video, g_frame_interval, &fi);
        if (ret < 0)
                return ret;
@@ -523,14 +526,14 @@ static int capture_legacy_s_parm(struct file *file, void *fh,
                                 struct v4l2_streamparm *a)
 {
        struct capture_priv *priv = video_drvdata(file);
-       struct v4l2_subdev_frame_interval fi;
+       struct v4l2_subdev_frame_interval fi = {
+               .pad = priv->src_sd_pad,
+       };
        int ret;
 
        if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       memset(&fi, 0, sizeof(fi));
-       fi.pad = priv->src_sd_pad;
        fi.interval = a->parm.capture.timeperframe;
        ret = v4l2_subdev_call(priv->src_sd, video, s_frame_interval, &fi);
        if (ret < 0)
@@ -670,13 +673,14 @@ static void capture_buf_queue(struct vb2_buffer *vb)
 
 static int capture_validate_fmt(struct capture_priv *priv)
 {
-       struct v4l2_subdev_format fmt_src;
+       struct v4l2_subdev_format fmt_src = {
+               .pad = priv->src_sd_pad,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        const struct imx_media_pixfmt *cc;
        int ret;
 
        /* Retrieve the media bus format on the source subdev. */
-       fmt_src.pad = priv->src_sd_pad;
-       fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(priv->src_sd, pad, get_fmt, NULL, &fmt_src);
        if (ret)
                return ret;
index 44d87fe30d52f65e9a606d538724be36e49ac493..097171bb930d3b3c26387f914162731550b04cf0 100644 (file)
@@ -2041,7 +2041,7 @@ free:
        return ret;
 }
 
-static int imx_csi_remove(struct platform_device *pdev)
+static void imx_csi_remove(struct platform_device *pdev)
 {
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct csi_priv *priv = sd_to_dev(sd);
@@ -2052,8 +2052,6 @@ static int imx_csi_remove(struct platform_device *pdev)
        v4l2_async_nf_cleanup(&priv->notifier);
        v4l2_async_unregister_subdev(sd);
        media_entity_cleanup(&sd->entity);
-
-       return 0;
 }
 
 static const struct platform_device_id imx_csi_ids[] = {
@@ -2064,7 +2062,7 @@ MODULE_DEVICE_TABLE(platform, imx_csi_ids);
 
 static struct platform_driver imx_csi_driver = {
        .probe = imx_csi_probe,
-       .remove = imx_csi_remove,
+       .remove_new = imx_csi_remove,
        .id_table = imx_csi_ids,
        .driver = {
                .name = "imx-ipuv3-csi",
index e6d6ed3b11615532178231827f77b985723ee7f0..991820a8500fb82e9d96b0ce9f4ecd92fd8b169c 100644 (file)
@@ -19,18 +19,6 @@ static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
        return container_of(n, struct imx_media_dev, notifier);
 }
 
-/* async subdev bound notifier */
-static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
-                                 struct v4l2_subdev *sd,
-                                 struct v4l2_async_subdev *asd)
-{
-       struct imx_media_dev *imxmd = notifier2dev(notifier);
-
-       dev_dbg(imxmd->md.dev, "subdev %s bound\n", sd->name);
-
-       return 0;
-}
-
 /*
  * Create the missing media links from the CSI-2 receiver.
  * Called after all async subdevs have bound.
@@ -51,7 +39,6 @@ static void imx_media_create_csi2_links(struct imx_media_dev *imxmd)
        list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
                /* skip if not a CSI or a CSI mux */
                if (!(sd->grp_id & IMX_MEDIA_GRP_ID_IPU_CSI) &&
-                   !(sd->grp_id & IMX_MEDIA_GRP_ID_CSI) &&
                    !(sd->grp_id & IMX_MEDIA_GRP_ID_CSI_MUX))
                        continue;
 
@@ -337,7 +324,6 @@ static void imx_media_notify(struct v4l2_subdev *sd, unsigned int notification,
 }
 
 static const struct v4l2_async_notifier_operations imx_media_notifier_ops = {
-       .bound = imx_media_subdev_bound,
        .complete = imx_media_probe_complete,
 };
 
index f85462214e2213eac1f36d5bff01ad372abd0711..c80113905069b51ef21bf7c06156e3c9d8da73ac 100644 (file)
@@ -101,7 +101,7 @@ cleanup:
        return ret;
 }
 
-static int imx_media_remove(struct platform_device *pdev)
+static void imx_media_remove(struct platform_device *pdev)
 {
        struct imx_media_dev *imxmd =
                (struct imx_media_dev *)platform_get_drvdata(pdev);
@@ -119,8 +119,6 @@ static int imx_media_remove(struct platform_device *pdev)
        media_device_unregister(&imxmd->md);
        v4l2_device_unregister(&imxmd->v4l2_dev);
        media_device_cleanup(&imxmd->md);
-
-       return 0;
 }
 
 static const struct of_device_id imx_media_dt_ids[] = {
@@ -131,7 +129,7 @@ MODULE_DEVICE_TABLE(of, imx_media_dt_ids);
 
 static struct platform_driver imx_media_pdrv = {
        .probe          = imx_media_probe,
-       .remove         = imx_media_remove,
+       .remove_new     = imx_media_remove,
        .driver         = {
                .name   = "imx-media",
                .of_match_table = imx_media_dt_ids,
index 59f1eb7b62bcd9b40264cd98838a1e4068f6062a..92a99010c1505af0800c177ccce4cf873f3cc77e 100644 (file)
@@ -16,8 +16,8 @@
 #include <video/imx-ipu-v3.h>
 #include "imx-media.h"
 
-int imx_media_of_add_csi(struct imx_media_dev *imxmd,
-                        struct device_node *csi_np)
+static int imx_media_of_add_csi(struct imx_media_dev *imxmd,
+                               struct device_node *csi_np)
 {
        struct v4l2_async_subdev *asd;
        int ret = 0;
@@ -41,7 +41,6 @@ int imx_media_of_add_csi(struct imx_media_dev *imxmd,
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(imx_media_of_add_csi);
 
 int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
                             struct device_node *np)
index 411e907b68eba063fc4f6a3d73582b120af970e6..2d712eda2c5d7fed62eff06b1768326c5ae6f584 100644 (file)
@@ -432,15 +432,15 @@ int imx_media_init_cfg(struct v4l2_subdev *sd,
                       struct v4l2_subdev_state *sd_state)
 {
        struct v4l2_mbus_framefmt *mf_try;
-       struct v4l2_subdev_format format;
        unsigned int pad;
        int ret;
 
        for (pad = 0; pad < sd->entity.num_pads; pad++) {
-               memset(&format, 0, sizeof(format));
+               struct v4l2_subdev_format format = {
+                       .pad = pad,
+                       .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               };
 
-               format.pad = pad;
-               format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &format);
                if (ret)
                        continue;
@@ -626,36 +626,6 @@ void imx_media_grp_id_to_sd_name(char *sd_name, int sz, u32 grp_id, int ipu_id)
 }
 EXPORT_SYMBOL_GPL(imx_media_grp_id_to_sd_name);
 
-struct v4l2_subdev *
-imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
-                               struct fwnode_handle *fwnode)
-{
-       struct v4l2_subdev *sd;
-
-       list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
-               if (sd->fwnode == fwnode)
-                       return sd;
-       }
-
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_fwnode);
-
-struct v4l2_subdev *
-imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd,
-                                const char *devname)
-{
-       struct v4l2_subdev *sd;
-
-       list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
-               if (!strcmp(devname, dev_name(sd->dev)))
-                       return sd;
-       }
-
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname);
-
 /*
  * Adds a video device to the master video device list. This is called
  * when a video device is registered.
@@ -756,25 +726,6 @@ find_pipeline_entity(struct media_entity *start, u32 grp_id,
        return pad ? pad->entity : NULL;
 }
 
-/*
- * Find the upstream mipi-csi2 virtual channel reached from the given
- * start entity in the current pipeline.
- * Must be called with mdev->graph_mutex held.
- */
-int imx_media_pipeline_csi2_channel(struct media_entity *start_entity)
-{
-       struct media_pad *pad;
-       int ret = -EPIPE;
-
-       pad = imx_media_pipeline_pad(start_entity, IMX_MEDIA_GRP_ID_CSI2,
-                                    0, true);
-       if (pad)
-               ret = pad->index - 1;
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(imx_media_pipeline_csi2_channel);
-
 /*
  * Find a subdev reached upstream from the given start entity in
  * the current pipeline.
@@ -794,25 +745,6 @@ imx_media_pipeline_subdev(struct media_entity *start_entity, u32 grp_id,
 }
 EXPORT_SYMBOL_GPL(imx_media_pipeline_subdev);
 
-/*
- * Find a subdev reached upstream from the given start entity in
- * the current pipeline.
- * Must be called with mdev->graph_mutex held.
- */
-struct video_device *
-imx_media_pipeline_video_device(struct media_entity *start_entity,
-                               enum v4l2_buf_type buftype, bool upstream)
-{
-       struct media_entity *me;
-
-       me = find_pipeline_entity(start_entity, 0, buftype, upstream);
-       if (!me)
-               return ERR_PTR(-ENODEV);
-
-       return media_entity_to_video_device(me);
-}
-EXPORT_SYMBOL_GPL(imx_media_pipeline_video_device);
-
 /*
  * Turn current pipeline streaming on/off starting from entity.
  */
index 6f9a46573eddcb0d5f037d81f03fd2f570d07bf3..2640cd34dce2641e27cd9d932523bd120cbabcb9 100644 (file)
@@ -201,24 +201,14 @@ int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
                                  const struct imx_media_pixfmt *cc);
 void imx_media_grp_id_to_sd_name(char *sd_name, int sz,
                                 u32 grp_id, int ipu_id);
-struct v4l2_subdev *
-imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
-                               struct fwnode_handle *fwnode);
-struct v4l2_subdev *
-imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd,
-                                const char *devname);
 void imx_media_add_video_device(struct imx_media_dev *imxmd,
                                struct imx_media_video_dev *vdev);
-int imx_media_pipeline_csi2_channel(struct media_entity *start_entity);
 struct media_pad *
 imx_media_pipeline_pad(struct media_entity *start_entity, u32 grp_id,
                       enum v4l2_buf_type buftype, bool upstream);
 struct v4l2_subdev *
 imx_media_pipeline_subdev(struct media_entity *start_entity, u32 grp_id,
                          bool upstream);
-struct video_device *
-imx_media_pipeline_video_device(struct media_entity *start_entity,
-                               enum v4l2_buf_type buftype, bool upstream);
 
 struct imx_media_dma_buf {
        void          *virt;
@@ -261,8 +251,6 @@ void imx_media_unregister_ipu_internal_subdevs(struct imx_media_dev *imxmd);
 /* imx-media-of.c */
 int imx_media_add_of_subdevs(struct imx_media_dev *dev,
                             struct device_node *np);
-int imx_media_of_add_csi(struct imx_media_dev *imxmd,
-                        struct device_node *csi_np);
 
 /* imx-media-vdic.c */
 struct v4l2_subdev *imx_media_vdic_register(struct v4l2_device *v4l2_dev,
@@ -298,7 +286,6 @@ void imx_media_csc_scaler_device_unregister(struct imx_media_video_dev *vdev);
 
 /* subdev group ids */
 #define IMX_MEDIA_GRP_ID_CSI2          BIT(8)
-#define IMX_MEDIA_GRP_ID_CSI           BIT(9)
 #define IMX_MEDIA_GRP_ID_IPU_CSI_BIT   10
 #define IMX_MEDIA_GRP_ID_IPU_CSI       (0x3 << IMX_MEDIA_GRP_ID_IPU_CSI_BIT)
 #define IMX_MEDIA_GRP_ID_IPU_CSI0      BIT(IMX_MEDIA_GRP_ID_IPU_CSI_BIT)
index c4cb558a85c6379cc5219b617f7d97e50b557b65..c07994ea6e9626b35006794c8225881406393d3e 100644 (file)
@@ -765,7 +765,7 @@ rmmutex:
        return ret;
 }
 
-static int csi2_remove(struct platform_device *pdev)
+static void csi2_remove(struct platform_device *pdev)
 {
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct csi2_dev *csi2 = sd_to_dev(sd);
@@ -777,8 +777,6 @@ static int csi2_remove(struct platform_device *pdev)
        clk_disable_unprepare(csi2->pllref_clk);
        mutex_destroy(&csi2->lock);
        media_entity_cleanup(&sd->entity);
-
-       return 0;
 }
 
 static const struct of_device_id csi2_dt_ids[] = {
@@ -793,7 +791,7 @@ static struct platform_driver csi2_driver = {
                .of_match_table = csi2_dt_ids,
        },
        .probe = csi2_probe,
-       .remove = csi2_remove,
+       .remove_new = csi2_remove,
 };
 
 module_platform_driver(csi2_driver);
index 83194328d0107a4a1c1347321f6ac2703a04bba7..32700cb8bc4d551055b8d6f36618acbe07088042 100644 (file)
@@ -119,11 +119,8 @@ struct csi_state {
 
        struct v4l2_mbus_config_mipi_csi2 bus;
 
-       struct mutex lock; /* Protect csi2_fmt, format_mbus, state, hs_settle */
-       const struct csi2_pix_format *csi2_fmt;
-       struct v4l2_mbus_framefmt format_mbus[MIPI_CSI2_PADS_NUM];
+       struct mutex lock; /* Protect state */
        u32 state;
-       u32 hs_settle;
 
        struct regmap *phy_gpr;
        u8 phy_gpr_reg;
@@ -248,23 +245,6 @@ static int imx8mq_mipi_csi_sw_reset(struct csi_state *state)
        return 0;
 }
 
-static void imx8mq_mipi_csi_system_enable(struct csi_state *state, int on)
-{
-       if (!on) {
-               imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, 0xf);
-               return;
-       }
-
-       regmap_update_bits(state->phy_gpr,
-                          state->phy_gpr_reg,
-                          0x3fff,
-                          GPR_CSI2_1_RX_ENABLE |
-                          GPR_CSI2_1_VID_INTFC_ENB |
-                          GPR_CSI2_1_HSEL |
-                          GPR_CSI2_1_CONT_CLK_MODE |
-                          GPR_CSI2_1_S_PRG_RXHS_SETTLE(state->hs_settle));
-}
-
 static void imx8mq_mipi_csi_set_params(struct csi_state *state)
 {
        int lanes = state->bus.num_data_lanes;
@@ -304,16 +284,24 @@ static int imx8mq_mipi_csi_clk_get(struct csi_state *state)
        return devm_clk_bulk_get(state->dev, CSI2_NUM_CLKS, state->clks);
 }
 
-static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state)
+static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state,
+                                         struct v4l2_subdev_state *sd_state,
+                                         u32 *hs_settle)
 {
        s64 link_freq;
        u32 lane_rate;
        unsigned long esc_clk_rate;
        u32 min_ths_settle, max_ths_settle, ths_settle_ns, esc_clk_period_ns;
+       const struct v4l2_mbus_framefmt *fmt;
+       const struct csi2_pix_format *csi2_fmt;
 
        /* Calculate the line rate from the pixel rate. */
+
+       fmt = v4l2_subdev_get_pad_format(&state->sd, sd_state, MIPI_CSI2_PAD_SINK);
+       csi2_fmt = find_csi2_format(fmt->code);
+
        link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler,
-                                      state->csi2_fmt->width,
+                                      csi2_fmt->width,
                                       state->bus.num_data_lanes * 2);
        if (link_freq < 0) {
                dev_err(state->dev, "Unable to obtain link frequency: %d\n",
@@ -354,35 +342,44 @@ static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state)
        max_ths_settle = 140 + 10 * 1000000 / (lane_rate / 1000);
        ths_settle_ns = (min_ths_settle + max_ths_settle) / 2;
 
-       state->hs_settle = ths_settle_ns / esc_clk_period_ns - 1;
+       *hs_settle = ths_settle_ns / esc_clk_period_ns - 1;
 
        dev_dbg(state->dev, "lane rate %u Ths_settle %u hs_settle %u\n",
-               lane_rate, ths_settle_ns, state->hs_settle);
+               lane_rate, ths_settle_ns, *hs_settle);
 
        return 0;
 }
 
-static int imx8mq_mipi_csi_start_stream(struct csi_state *state)
+static int imx8mq_mipi_csi_start_stream(struct csi_state *state,
+                                       struct v4l2_subdev_state *sd_state)
 {
        int ret;
+       u32 hs_settle;
 
        ret = imx8mq_mipi_csi_sw_reset(state);
        if (ret)
                return ret;
 
        imx8mq_mipi_csi_set_params(state);
-       ret = imx8mq_mipi_csi_calc_hs_settle(state);
+       ret = imx8mq_mipi_csi_calc_hs_settle(state, sd_state, &hs_settle);
        if (ret)
                return ret;
 
-       imx8mq_mipi_csi_system_enable(state, true);
+       regmap_update_bits(state->phy_gpr,
+                          state->phy_gpr_reg,
+                          0x3fff,
+                          GPR_CSI2_1_RX_ENABLE |
+                          GPR_CSI2_1_VID_INTFC_ENB |
+                          GPR_CSI2_1_HSEL |
+                          GPR_CSI2_1_CONT_CLK_MODE |
+                          GPR_CSI2_1_S_PRG_RXHS_SETTLE(hs_settle));
 
        return 0;
 }
 
 static void imx8mq_mipi_csi_stop_stream(struct csi_state *state)
 {
-       imx8mq_mipi_csi_system_enable(state, false);
+       imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, 0xf);
 }
 
 /* -----------------------------------------------------------------------------
@@ -397,6 +394,7 @@ static struct csi_state *mipi_sd_to_csi2_state(struct v4l2_subdev *sdev)
 static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct csi_state *state = mipi_sd_to_csi2_state(sd);
+       struct v4l2_subdev_state *sd_state;
        int ret = 0;
 
        if (enable) {
@@ -413,7 +411,10 @@ static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable)
                        goto unlock;
                }
 
-               ret = imx8mq_mipi_csi_start_stream(state);
+               sd_state = v4l2_subdev_lock_and_get_active_state(sd);
+               ret = imx8mq_mipi_csi_start_stream(state, sd_state);
+               v4l2_subdev_unlock_state(sd_state);
+
                if (ret < 0)
                        goto unlock;
 
@@ -437,29 +438,14 @@ unlock:
        return ret;
 }
 
-static struct v4l2_mbus_framefmt *
-imx8mq_mipi_csi_get_format(struct csi_state *state,
-                          struct v4l2_subdev_state *sd_state,
-                          enum v4l2_subdev_format_whence which,
-                          unsigned int pad)
-{
-       if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(&state->sd, sd_state, pad);
-
-       return &state->format_mbus[pad];
-}
-
 static int imx8mq_mipi_csi_init_cfg(struct v4l2_subdev *sd,
                                    struct v4l2_subdev_state *sd_state)
 {
-       struct csi_state *state = mipi_sd_to_csi2_state(sd);
        struct v4l2_mbus_framefmt *fmt_sink;
        struct v4l2_mbus_framefmt *fmt_source;
-       enum v4l2_subdev_format_whence which;
 
-       which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-       fmt_sink = imx8mq_mipi_csi_get_format(state, sd_state, which,
-                                             MIPI_CSI2_PAD_SINK);
+       fmt_sink = v4l2_subdev_get_pad_format(sd, sd_state, MIPI_CSI2_PAD_SINK);
+       fmt_source = v4l2_subdev_get_pad_format(sd, sd_state, MIPI_CSI2_PAD_SOURCE);
 
        fmt_sink->code = MEDIA_BUS_FMT_SGBRG10_1X10;
        fmt_sink->width = MIPI_CSI2_DEF_PIX_WIDTH;
@@ -473,38 +459,15 @@ static int imx8mq_mipi_csi_init_cfg(struct v4l2_subdev *sd,
                V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
                                              fmt_sink->ycbcr_enc);
 
-       fmt_source = imx8mq_mipi_csi_get_format(state, sd_state, which,
-                                               MIPI_CSI2_PAD_SOURCE);
        *fmt_source = *fmt_sink;
 
        return 0;
 }
 
-static int imx8mq_mipi_csi_get_fmt(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_state *sd_state,
-                                  struct v4l2_subdev_format *sdformat)
-{
-       struct csi_state *state = mipi_sd_to_csi2_state(sd);
-       struct v4l2_mbus_framefmt *fmt;
-
-       fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which,
-                                        sdformat->pad);
-
-       mutex_lock(&state->lock);
-
-       sdformat->format = *fmt;
-
-       mutex_unlock(&state->lock);
-
-       return 0;
-}
-
 static int imx8mq_mipi_csi_enum_mbus_code(struct v4l2_subdev *sd,
                                          struct v4l2_subdev_state *sd_state,
                                          struct v4l2_subdev_mbus_code_enum *code)
 {
-       struct csi_state *state = mipi_sd_to_csi2_state(sd);
-
        /*
         * We can't transcode in any way, the source format is identical
         * to the sink format.
@@ -515,8 +478,7 @@ static int imx8mq_mipi_csi_enum_mbus_code(struct v4l2_subdev *sd,
                if (code->index > 0)
                        return -EINVAL;
 
-               fmt = imx8mq_mipi_csi_get_format(state, sd_state, code->which,
-                                                code->pad);
+               fmt = v4l2_subdev_get_pad_format(sd, sd_state, code->pad);
                code->code = fmt->code;
                return 0;
        }
@@ -536,8 +498,7 @@ static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd,
                                   struct v4l2_subdev_state *sd_state,
                                   struct v4l2_subdev_format *sdformat)
 {
-       struct csi_state *state = mipi_sd_to_csi2_state(sd);
-       struct csi2_pix_format const *csi2_fmt;
+       const struct csi2_pix_format *csi2_fmt;
        struct v4l2_mbus_framefmt *fmt;
 
        /*
@@ -545,7 +506,7 @@ static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd,
         * modified.
         */
        if (sdformat->pad == MIPI_CSI2_PAD_SOURCE)
-               return imx8mq_mipi_csi_get_fmt(sd, sd_state, sdformat);
+               return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
 
        if (sdformat->pad != MIPI_CSI2_PAD_SINK)
                return -EINVAL;
@@ -554,10 +515,7 @@ static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd,
        if (!csi2_fmt)
                csi2_fmt = &imx8mq_mipi_csi_formats[0];
 
-       fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which,
-                                        sdformat->pad);
-
-       mutex_lock(&state->lock);
+       fmt = v4l2_subdev_get_pad_format(sd, sd_state, sdformat->pad);
 
        fmt->code = csi2_fmt->code;
        fmt->width = sdformat->format.width;
@@ -566,16 +524,9 @@ static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd,
        sdformat->format = *fmt;
 
        /* Propagate the format from sink to source. */
-       fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which,
-                                        MIPI_CSI2_PAD_SOURCE);
+       fmt = v4l2_subdev_get_pad_format(sd, sd_state, MIPI_CSI2_PAD_SOURCE);
        *fmt = sdformat->format;
 
-       /* Store the CSI2 format descriptor for active formats. */
-       if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
-               state->csi2_fmt = csi2_fmt;
-
-       mutex_unlock(&state->lock);
-
        return 0;
 }
 
@@ -586,7 +537,7 @@ static const struct v4l2_subdev_video_ops imx8mq_mipi_csi_video_ops = {
 static const struct v4l2_subdev_pad_ops imx8mq_mipi_csi_pad_ops = {
        .init_cfg               = imx8mq_mipi_csi_init_cfg,
        .enum_mbus_code         = imx8mq_mipi_csi_enum_mbus_code,
-       .get_fmt                = imx8mq_mipi_csi_get_fmt,
+       .get_fmt                = v4l2_subdev_get_fmt,
        .set_fmt                = imx8mq_mipi_csi_set_fmt,
 };
 
@@ -714,6 +665,7 @@ static int imx8mq_mipi_csi_pm_resume(struct device *dev)
 {
        struct v4l2_subdev *sd = dev_get_drvdata(dev);
        struct csi_state *state = mipi_sd_to_csi2_state(sd);
+       struct v4l2_subdev_state *sd_state;
        int ret = 0;
 
        mutex_lock(&state->lock);
@@ -723,7 +675,9 @@ static int imx8mq_mipi_csi_pm_resume(struct device *dev)
                ret = imx8mq_mipi_csi_clk_enable(state);
        }
        if (state->state & ST_STREAMING) {
-               ret = imx8mq_mipi_csi_start_stream(state);
+               sd_state = v4l2_subdev_lock_and_get_active_state(sd);
+               ret = imx8mq_mipi_csi_start_stream(state, sd_state);
+               v4l2_subdev_unlock_state(sd_state);
                if (ret)
                        goto unlock;
        }
@@ -803,6 +757,7 @@ static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = {
 static int imx8mq_mipi_csi_subdev_init(struct csi_state *state)
 {
        struct v4l2_subdev *sd = &state->sd;
+       int ret;
 
        v4l2_subdev_init(sd, &imx8mq_mipi_csi_subdev_ops);
        sd->owner = THIS_MODULE;
@@ -816,15 +771,22 @@ static int imx8mq_mipi_csi_subdev_init(struct csi_state *state)
 
        sd->dev = state->dev;
 
-       state->csi2_fmt = &imx8mq_mipi_csi_formats[0];
-       imx8mq_mipi_csi_init_cfg(sd, NULL);
-
        state->pads[MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK
                                         | MEDIA_PAD_FL_MUST_CONNECT;
        state->pads[MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
                                           | MEDIA_PAD_FL_MUST_CONNECT;
-       return media_entity_pads_init(&sd->entity, MIPI_CSI2_PADS_NUM,
-                                     state->pads);
+       ret = media_entity_pads_init(&sd->entity, MIPI_CSI2_PADS_NUM,
+                                    state->pads);
+       if (ret)
+               return ret;
+
+       ret = v4l2_subdev_init_finalize(sd);
+       if (ret) {
+               media_entity_cleanup(&sd->entity);
+               return ret;
+       }
+
+       return 0;
 }
 
 static void imx8mq_mipi_csi_release_icc(struct platform_device *pdev)
@@ -950,6 +912,7 @@ cleanup:
        imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
 
        media_entity_cleanup(&state->sd.entity);
+       v4l2_subdev_cleanup(&state->sd);
        v4l2_async_nf_unregister(&state->notifier);
        v4l2_async_nf_cleanup(&state->notifier);
        v4l2_async_unregister_subdev(&state->sd);
@@ -961,7 +924,7 @@ mutex:
        return ret;
 }
 
-static int imx8mq_mipi_csi_remove(struct platform_device *pdev)
+static void imx8mq_mipi_csi_remove(struct platform_device *pdev)
 {
        struct v4l2_subdev *sd = platform_get_drvdata(pdev);
        struct csi_state *state = mipi_sd_to_csi2_state(sd);
@@ -973,11 +936,10 @@ static int imx8mq_mipi_csi_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
        imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
        media_entity_cleanup(&state->sd.entity);
+       v4l2_subdev_cleanup(&state->sd);
        mutex_destroy(&state->lock);
        pm_runtime_set_suspended(&pdev->dev);
        imx8mq_mipi_csi_release_icc(pdev);
-
-       return 0;
 }
 
 static const struct of_device_id imx8mq_mipi_csi_of_match[] = {
@@ -988,7 +950,7 @@ MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match);
 
 static struct platform_driver imx8mq_mipi_csi_driver = {
        .probe          = imx8mq_mipi_csi_probe,
-       .remove         = imx8mq_mipi_csi_remove,
+       .remove_new     = imx8mq_mipi_csi_remove,
        .driver         = {
                .of_match_table = imx8mq_mipi_csi_of_match,
                .name           = MIPI_CSI2_DRIVER_NAME,
index 52f224d8def10425ecb947a8fa99cd4672735c6b..5ca4b12008314c0c0ca0941799434e1eeceeec51 100644 (file)
@@ -1106,19 +1106,17 @@ err_vdev_release:
        return ret;
 }
 
-static int vdec_remove(struct platform_device *pdev)
+static void vdec_remove(struct platform_device *pdev)
 {
        struct amvdec_core *core = platform_get_drvdata(pdev);
 
        video_unregister_device(core->vdev_dec);
        v4l2_device_unregister(&core->v4l2_dev);
-
-       return 0;
 }
 
 static struct platform_driver meson_vdec_driver = {
        .probe = vdec_probe,
-       .remove = vdec_remove,
+       .remove_new = vdec_remove,
        .driver = {
                .name = "meson-vdec",
                .of_match_table = vdec_dt_match,
index fa2a36d829d3d48847a4925959c61e6726bfa5cd..0c4283bb48ad39db02a090b8e475bc134f6b6628 100644 (file)
@@ -1323,15 +1323,13 @@ error:
        return ret;
 }
 
-static int iss_remove(struct platform_device *pdev)
+static void iss_remove(struct platform_device *pdev)
 {
        struct iss_device *iss = platform_get_drvdata(pdev);
 
        iss_unregister_entities(iss);
        media_entity_enum_cleanup(&iss->crashed);
        iss_cleanup_modules(iss);
-
-       return 0;
 }
 
 static const struct platform_device_id omap4iss_id_table[] = {
@@ -1342,7 +1340,7 @@ MODULE_DEVICE_TABLE(platform, omap4iss_id_table);
 
 static struct platform_driver iss_driver = {
        .probe          = iss_probe,
-       .remove         = iss_remove,
+       .remove_new     = iss_remove,
        .id_table       = omap4iss_id_table,
        .driver = {
                .name   = "omap4iss",
index 05548eab7daadce384a5dff3d6f3fcb1807c5759..22fa4d6cae10b9b62e0e1a511b405c4ba90ffa7b 100644 (file)
@@ -237,7 +237,9 @@ static int
 __iss_video_get_format(struct iss_video *video,
                       struct v4l2_mbus_framefmt *format)
 {
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        u32 pad;
        int ret;
@@ -246,9 +248,7 @@ __iss_video_get_format(struct iss_video *video,
        if (!subdev)
                return -EINVAL;
 
-       memset(&fmt, 0, sizeof(fmt));
        fmt.pad = pad;
-       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 
        mutex_lock(&video->mutex);
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
@@ -610,7 +610,9 @@ static int
 iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
 {
        struct iss_video *video = video_drvdata(file);
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        u32 pad;
        int ret;
@@ -625,7 +627,6 @@ iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
        iss_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
 
        fmt.pad = pad;
-       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        if (ret)
                return ret;
@@ -638,7 +639,9 @@ static int
 iss_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel)
 {
        struct iss_video *video = video_drvdata(file);
-       struct v4l2_subdev_format format;
+       struct v4l2_subdev_format format = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        struct v4l2_subdev_selection sdsel = {
                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -679,7 +682,6 @@ iss_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel)
                return ret;
 
        format.pad = pad;
-       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
        if (ret < 0)
                return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
index 7bab7586918c11bbbb8a3315c187c97db5c42c53..134e2b9fa7d9a5f8953f79973da0bfc12440f883 100644 (file)
@@ -1062,14 +1062,15 @@ err_disable_runtime_pm:
        return ret;
 }
 
-static int rkvdec_remove(struct platform_device *pdev)
+static void rkvdec_remove(struct platform_device *pdev)
 {
        struct rkvdec_dev *rkvdec = platform_get_drvdata(pdev);
 
+       cancel_delayed_work_sync(&rkvdec->watchdog_work);
+
        rkvdec_v4l2_cleanup(rkvdec);
        pm_runtime_disable(&pdev->dev);
        pm_runtime_dont_use_autosuspend(&pdev->dev);
-       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1099,7 +1100,7 @@ static const struct dev_pm_ops rkvdec_pm_ops = {
 
 static struct platform_driver rkvdec_driver = {
        .probe = rkvdec_probe,
-       .remove = rkvdec_remove,
+       .remove_new = rkvdec_remove,
        .driver = {
                   .name = "rkvdec",
                   .of_match_table = of_rkvdec_match,
index a43d5ff667163d79ef04fa1441daa55be328bc43..8e248d4a0aecfca9c409330fb2564a32a28edfc5 100644 (file)
@@ -543,10 +543,11 @@ err_v4l2:
        return ret;
 }
 
-static int cedrus_remove(struct platform_device *pdev)
+static void cedrus_remove(struct platform_device *pdev)
 {
        struct cedrus_dev *dev = platform_get_drvdata(pdev);
 
+       cancel_delayed_work_sync(&dev->watchdog_work);
        if (media_devnode_is_registered(dev->mdev.devnode)) {
                media_device_unregister(&dev->mdev);
                v4l2_m2m_unregister_media_controller(dev->m2m_dev);
@@ -558,8 +559,6 @@ static int cedrus_remove(struct platform_device *pdev)
        v4l2_device_unregister(&dev->v4l2_dev);
 
        cedrus_hw_remove(dev);
-
-       return 0;
 }
 
 static const struct cedrus_variant sun4i_a10_cedrus_variant = {
@@ -706,7 +705,7 @@ static const struct dev_pm_ops cedrus_dev_pm_ops = {
 
 static struct platform_driver cedrus_driver = {
        .probe          = cedrus_probe,
-       .remove         = cedrus_remove,
+       .remove_new     = cedrus_remove,
        .driver         = {
                .name           = CEDRUS_NAME,
                .of_match_table = of_match_ptr(cedrus_dt_match),
index 7b7947509b69cb7c300437b65afb3b4ad28a116d..0dc75adbd9d86c3ba20f1bb3f3f2199229ae074f 100644 (file)
@@ -493,7 +493,7 @@ error_resources:
        return ret;
 }
 
-static int sun6i_isp_remove(struct platform_device *platform_dev)
+static void sun6i_isp_remove(struct platform_device *platform_dev)
 {
        struct sun6i_isp_device *isp_dev = platform_get_drvdata(platform_dev);
 
@@ -503,8 +503,6 @@ static int sun6i_isp_remove(struct platform_device *platform_dev)
        sun6i_isp_v4l2_cleanup(isp_dev);
        sun6i_isp_tables_cleanup(isp_dev);
        sun6i_isp_resources_cleanup(isp_dev);
-
-       return 0;
 }
 
 /*
@@ -540,7 +538,7 @@ MODULE_DEVICE_TABLE(of, sun6i_isp_of_match);
 
 static struct platform_driver sun6i_isp_platform_driver = {
        .probe  = sun6i_isp_probe,
-       .remove = sun6i_isp_remove,
+       .remove_new = sun6i_isp_remove,
        .driver = {
                .name           = SUN6I_ISP_NAME,
                .of_match_table = of_match_ptr(sun6i_isp_of_match),
index 26f7aedce718c2950fcab322f37f215b5ecab1c0..2f1aff7e87170c68098224a821ad6d537fcf726a 100644 (file)
@@ -493,7 +493,9 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
        const struct tegra_video_format *fmtinfo;
        static struct lock_class_key key;
        struct v4l2_subdev *subdev;
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_TRY,
+       };
        struct v4l2_subdev_state *sd_state;
        struct v4l2_subdev_frame_size_enum fse = {
                .which = V4L2_SUBDEV_FORMAT_TRY,
@@ -529,7 +531,6 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
        }
 
        pix->field = V4L2_FIELD_NONE;
-       fmt.which = V4L2_SUBDEV_FORMAT_TRY;
        fmt.pad = 0;
        v4l2_fill_mbus_format(&fmt.format, pix, fmtinfo->code);
 
@@ -590,7 +591,9 @@ static int tegra_channel_set_format(struct file *file, void *fh,
 {
        struct tegra_vi_channel *chan = video_drvdata(file);
        const struct tegra_video_format *fmtinfo;
-       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev_format fmt = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        struct v4l2_subdev *subdev;
        struct v4l2_pix_format *pix = &format->fmt.pix;
        int ret;
@@ -605,7 +608,6 @@ static int tegra_channel_set_format(struct file *file, void *fh,
 
        fmtinfo = tegra_get_format_by_fourcc(chan->vi, pix->pixelformat);
 
-       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        fmt.pad = 0;
        v4l2_fill_mbus_format(&fmt.format, pix, fmtinfo->code);
        subdev = tegra_channel_get_remote_source_subdev(chan);
index 635805fb35e876e754bb02cc17770c8784453d48..55c7d70b9febccbd94b275fc939f9b574b3a6773 100644 (file)
@@ -6,7 +6,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-fh.h>
 #include <media/drv-intf/saa7146.h>
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf2-dma-sg.h>
 
 #define MAX_SAA7146_CAPTURE_BUFFERS    32      /* arbitrary */
 #define BUFFER_TIMEOUT     (HZ/2)  /* 0.5 seconds */
@@ -57,10 +57,10 @@ struct saa7146_standard
 /* buffer for one video/vbi frame */
 struct saa7146_buf {
        /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
+       struct vb2_v4l2_buffer vb;
+       struct list_head list;
 
        /* saa7146 specific */
-       struct v4l2_pix_format  *fmt;
        int (*activate)(struct saa7146_dev *dev,
                        struct saa7146_buf *buf,
                        struct saa7146_buf *next);
@@ -74,58 +74,23 @@ struct saa7146_dmaqueue {
        struct saa7146_buf      *curr;
        struct list_head        queue;
        struct timer_list       timeout;
+       struct vb2_queue        q;
 };
 
-struct saa7146_overlay {
-       struct saa7146_fh       *fh;
-       struct v4l2_window      win;
-       struct v4l2_clip        clips[16];
-       int                     nclips;
-};
-
-/* per open data */
-struct saa7146_fh {
-       /* Must be the first field! */
-       struct v4l2_fh          fh;
-       struct saa7146_dev      *dev;
-
-       /* video capture */
-       struct videobuf_queue   video_q;
-
-       /* vbi capture */
-       struct videobuf_queue   vbi_q;
-
-       unsigned int resources; /* resource management for device open */
-};
-
-#define STATUS_OVERLAY 0x01
-#define STATUS_CAPTURE 0x02
-
 struct saa7146_vv
 {
        /* vbi capture */
        struct saa7146_dmaqueue         vbi_dmaq;
        struct v4l2_vbi_format          vbi_fmt;
        struct timer_list               vbi_read_timeout;
-       struct file                     *vbi_read_timeout_file;
        /* vbi workaround interrupt queue */
        wait_queue_head_t               vbi_wq;
-       int                             vbi_fieldcount;
-       struct saa7146_fh               *vbi_streaming;
-
-       int                             video_status;
-       struct saa7146_fh               *video_fh;
-
-       /* video overlay */
-       struct saa7146_overlay          ov;
-       struct v4l2_framebuffer         ov_fb;
-       struct saa7146_format           *ov_fmt;
-       struct saa7146_fh               *ov_suspend;
 
        /* video capture */
        struct saa7146_dmaqueue         video_dmaq;
        struct v4l2_pix_format          video_fmt;
        enum v4l2_field                 last_field;
+       u32                             seqnr;
 
        /* common: fixme? shouldn't this be in saa7146_fh?
           (this leads to a more complicated question: shall the driver
@@ -140,9 +105,7 @@ struct saa7146_vv
        int     current_hps_source;
        int     current_hps_sync;
 
-       struct saa7146_dma      d_clipping;     /* pointer to clipping memory */
-
-       unsigned int resources; /* resource management for device */
+       unsigned int resources; /* resource management for device */
 };
 
 /* flags */
@@ -172,10 +135,7 @@ struct saa7146_ext_vv
 
 struct saa7146_use_ops  {
        void (*init)(struct saa7146_dev *, struct saa7146_vv *);
-       int(*open)(struct saa7146_dev *, struct file *);
-       void (*release)(struct saa7146_dev *, struct file *);
        void (*irq_done)(struct saa7146_dev *, unsigned long status);
-       ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
 };
 
 /* from saa7146_fops.c */
@@ -185,16 +145,11 @@ void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,
 void saa7146_buffer_next(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,int vbi);
 int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf);
 void saa7146_buffer_timeout(struct timer_list *t);
-void saa7146_dma_free(struct saa7146_dev* dev,struct videobuf_queue *q,
-                                               struct saa7146_buf *buf);
 
 int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv);
 int saa7146_vv_release(struct saa7146_dev* dev);
 
 /* from saa7146_hlp.c */
-int saa7146_enable_overlay(struct saa7146_fh *fh);
-void saa7146_disable_overlay(struct saa7146_fh *fh);
-
 void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next);
 void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma) ;
 void saa7146_set_hps_source_and_sync(struct saa7146_dev *saa, int source, int sync);
@@ -204,17 +159,17 @@ void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data);
 extern const struct v4l2_ioctl_ops saa7146_video_ioctl_ops;
 extern const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops;
 extern const struct saa7146_use_ops saa7146_video_uops;
-int saa7146_start_preview(struct saa7146_fh *fh);
-int saa7146_stop_preview(struct saa7146_fh *fh);
+extern const struct vb2_ops video_qops;
 long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
 int saa7146_s_ctrl(struct v4l2_ctrl *ctrl);
 
 /* from saa7146_vbi.c */
 extern const struct saa7146_use_ops saa7146_vbi_uops;
+extern const struct vb2_ops vbi_qops;
 
 /* resource management functions */
-int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit);
-void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits);
+int saa7146_res_get(struct saa7146_dev *dev, unsigned int bit);
+void saa7146_res_free(struct saa7146_dev *dev, unsigned int bits);
 
 #define RESOURCE_DMA1_HPS      0x1
 #define RESOURCE_DMA2_CLP      0x2
index 5e31d37f25fac8581f0a6a9c5de90d896e2b3b29..9980b1dd750b34b878223e7ad227f197571a2d6a 100644 (file)
 #define _DVB_NET_H_
 
 #include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
 
 #include <media/dvbdev.h>
 
+struct net_device;
+
 #define DVB_NET_DEVICES_MAX 10
 
 #ifdef CONFIG_DVB_NET
diff --git a/include/media/i2c/ad9389b.h b/include/media/i2c/ad9389b.h
deleted file mode 100644 (file)
index 30f9ea9..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Analog Devices AD9389B/AD9889B video encoder driver header
- *
- * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef AD9389B_H
-#define AD9389B_H
-
-enum ad9389b_tmds_pll_gear {
-       AD9389B_TMDS_PLL_GEAR_AUTOMATIC,
-       AD9389B_TMDS_PLL_GEAR_SEMI_AUTOMATIC,
-};
-
-/* Platform dependent definitions */
-struct ad9389b_platform_data {
-       enum ad9389b_tmds_pll_gear tmds_pll_gear ;
-       /* Differential Data/Clock Output Drive Strength (reg. 0xa2/0xa3) */
-       u8 diff_data_drive_strength;
-       u8 diff_clk_drive_strength;
-};
-
-/* notify events */
-#define AD9389B_MONITOR_DETECT 0
-#define AD9389B_EDID_DETECT 1
-
-struct ad9389b_monitor_detect {
-       int present;
-};
-
-struct ad9389b_edid_detect {
-       int present;
-       int segment;
-};
-
-#endif
diff --git a/include/media/i2c/m5mols.h b/include/media/i2c/m5mols.h
deleted file mode 100644 (file)
index a56ae35..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Driver header for M-5MOLS 8M Pixel camera sensor with ISP
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim <riverful.kim@samsung.com>
- *
- * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
- */
-
-#ifndef MEDIA_M5MOLS_H
-#define MEDIA_M5MOLS_H
-
-/**
- * struct m5mols_platform_data - platform data for M-5MOLS driver
- * @set_power: an additional callback to the board setup code
- *             to be called after enabling and before disabling
- *             the sensor's supply regulators
- */
-struct m5mols_platform_data {
-       int (*set_power)(struct device *dev, int on);
-};
-
-#endif /* MEDIA_M5MOLS_H */
diff --git a/include/media/i2c/mt9m032.h b/include/media/i2c/mt9m032.h
deleted file mode 100644 (file)
index 1bd5875..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Driver for MT9M032 CMOS Image Sensor from Micron
- *
- * Copyright (C) 2010-2011 Lund Engineering
- * Contact: Gil Lund <gwlund@lundeng.com>
- * Author: Martin Hostettler <martin@neutronstar.dyndns.org>
- */
-
-#ifndef MT9M032_H
-#define MT9M032_H
-
-#define MT9M032_NAME           "mt9m032"
-#define MT9M032_I2C_ADDR       (0xb8 >> 1)
-
-struct mt9m032_platform_data {
-       u32 ext_clock;
-       u32 pix_clock;
-       bool invert_pixclock;
-
-};
-#endif /* MT9M032_H */
diff --git a/include/media/i2c/mt9t001.h b/include/media/i2c/mt9t001.h
deleted file mode 100644 (file)
index 4b10905..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _MEDIA_MT9T001_H
-#define _MEDIA_MT9T001_H
-
-struct mt9t001_platform_data {
-       unsigned int clk_pol:1;
-       unsigned int ext_clk;
-};
-
-#endif
diff --git a/include/media/i2c/noon010pc30.h b/include/media/i2c/noon010pc30.h
deleted file mode 100644 (file)
index 1880dad..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Driver header for NOON010PC30L camera sensor chip.
- *
- * Copyright (c) 2010 Samsung Electronics, Co. Ltd
- * Contact: Sylwester Nawrocki <s.nawrocki@samsung.com>
- */
-
-#ifndef NOON010PC30_H
-#define NOON010PC30_H
-
-/**
- * struct noon010pc30_platform_data - platform data
- * @clk_rate: the clock frequency in Hz
- */
-
-struct noon010pc30_platform_data {
-       unsigned long clk_rate;
-};
-
-#endif /* NOON010PC30_H */
diff --git a/include/media/i2c/s5k6aa.h b/include/media/i2c/s5k6aa.h
deleted file mode 100644 (file)
index eb3444d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * S5K6AAFX camera sensor driver header
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- */
-
-#ifndef S5K6AA_H
-#define S5K6AA_H
-
-#include <media/v4l2-mediabus.h>
-
-/**
- * struct s5k6aa_gpio - data structure describing a GPIO
- * @gpio:  GPIO number
- * @level: indicates active state of the @gpio
- */
-struct s5k6aa_gpio {
-       int gpio;
-       int level;
-};
-
-/**
- * struct s5k6aa_platform_data - s5k6aa driver platform data
- * @set_power:   an additional callback to the board code, called
- *               after enabling the regulators and before switching
- *               the sensor off
- * @mclk_frequency: sensor's master clock frequency in Hz
- * @gpio_reset:  GPIO driving RESET pin
- * @gpio_stby:   GPIO driving STBY pin
- * @bus_type:    bus type
- * @nlanes:      maximum number of MIPI-CSI lanes used
- * @horiz_flip:  default horizontal image flip value, non zero to enable
- * @vert_flip:   default vertical image flip value, non zero to enable
- */
-
-struct s5k6aa_platform_data {
-       int (*set_power)(int enable);
-       unsigned long mclk_frequency;
-       struct s5k6aa_gpio gpio_reset;
-       struct s5k6aa_gpio gpio_stby;
-       enum v4l2_mbus_type bus_type;
-       u8 nlanes;
-       u8 horiz_flip;
-       u8 vert_flip;
-};
-
-#endif /* S5K6AA_H */
diff --git a/include/media/i2c/sr030pc30.h b/include/media/i2c/sr030pc30.h
deleted file mode 100644 (file)
index 84c602d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Driver header for SR030PC30 camera sensor
- *
- * Copyright (c) 2010 Samsung Electronics, Co. Ltd
- * Contact: Sylwester Nawrocki <s.nawrocki@samsung.com>
- */
-
-#ifndef SR030PC30_H
-#define SR030PC30_H
-
-struct sr030pc30_platform_data {
-       unsigned long clk_rate; /* master clock frequency in Hz */
-       int (*set_power)(struct device *dev, int on);
-};
-
-#endif /* SR030PC30_H */
index 86716ee7cc6ce78f7b8f0d86c835d40266194d17..2c146d0b2b1cf984e05eb0abe0ce60f0ba7f7cbb 100644 (file)
@@ -364,7 +364,7 @@ void media_device_unregister_entity(struct media_entity *entity);
  *    media_entity_notify callbacks are invoked.
  */
 
-int __must_check media_device_register_entity_notify(struct media_device *mdev,
+void media_device_register_entity_notify(struct media_device *mdev,
                                        struct media_entity_notify *nptr);
 
 /**
@@ -444,11 +444,10 @@ static inline int media_device_register_entity(struct media_device *mdev,
 static inline void media_device_unregister_entity(struct media_entity *entity)
 {
 }
-static inline int media_device_register_entity_notify(
+static inline void media_device_register_entity_notify(
                                        struct media_device *mdev,
                                        struct media_entity_notify *nptr)
 {
-       return 0;
 }
 static inline void media_device_unregister_entity_notify(
                                        struct media_device *mdev,
index 793b54342dffe6ad31d1e4b545c077d2a831dcac..4676545ffd8faac30be341a919d383b165e3338b 100644 (file)
@@ -225,6 +225,7 @@ struct rc_map *rc_map_get(const char *name);
 #define RC_MAP_AVERTV_303                "rc-avertv-303"
 #define RC_MAP_AZUREWAVE_AD_TU700        "rc-azurewave-ad-tu700"
 #define RC_MAP_BEELINK_GS1               "rc-beelink-gs1"
+#define RC_MAP_BEELINK_MXIII             "rc-beelink-mxiii"
 #define RC_MAP_BEHOLD                    "rc-behold"
 #define RC_MAP_BEHOLD_COLUMBUS           "rc-behold-columbus"
 #define RC_MAP_BUDGET_CI_OLD             "rc-budget-ci-old"
@@ -241,6 +242,7 @@ struct rc_map *rc_map_get(const char *name);
 #define RC_MAP_DM1105_NEC                "rc-dm1105-nec"
 #define RC_MAP_DNTV_LIVE_DVB_T           "rc-dntv-live-dvb-t"
 #define RC_MAP_DNTV_LIVE_DVBT_PRO        "rc-dntv-live-dvbt-pro"
+#define RC_MAP_DREAMBOX                  "rc-dreambox"
 #define RC_MAP_DTT200U                   "rc-dtt200u"
 #define RC_MAP_DVBSKY                    "rc-dvbsky"
 #define RC_MAP_DVICO_MCE                "rc-dvico-mce"
index b56eaee82aa58e52f7f0a978863a2144ab88276b..f37c9b15ffdb51ba424e37afa4057a9b7f7581c9 100644 (file)
@@ -5,7 +5,7 @@
  *           eeproms.
  */
 
-#include <linux/if_ether.h>
+#include <uapi/linux/if_ether.h>
 
 /**
  * enum tveeprom_audio_processor - Specifies the type of audio processor
index e59d9a234631d130e77cfd7634cdbceecdf0c64c..7788eeb3e2bbc0f9ea9edd5164b79a55c94ff858 100644 (file)
@@ -1343,7 +1343,7 @@ void v4l2_ctrl_request_complete(struct media_request *req,
  * @parent: The parent control handler ('priv' in media_request_object_find())
  *
  * This function finds the control handler in the request. It may return
- * NULL if not found. When done, you must call v4l2_ctrl_request_put_hdl()
+ * NULL if not found. When done, you must call v4l2_ctrl_request_hdl_put()
  * with the returned handler pointer.
  *
  * If the request is not in state VALIDATING or QUEUED, then this function
index c181685923d526aa405f3d1c5167ae7aa94aadd5..b39586dfba358aab6a5558b31e0be185b55cda8f 100644 (file)
@@ -87,17 +87,17 @@ int v4l_vb2q_enable_media_source(struct vb2_queue *q);
 
 /**
  * v4l2_create_fwnode_links_to_pad - Create fwnode-based links from a
- *                                   source subdev to a sink subdev pad.
+ *                                   source subdev to a sink pad.
  *
  * @src_sd: pointer to a source subdev
- * @sink:  pointer to a subdev sink pad
+ * @sink:  pointer to a sink pad
  * @flags: the link flags
  *
  * This function searches for fwnode endpoint connections from a source
  * subdevice to a single sink pad, and if suitable connections are found,
  * translates them into media links to that pad. The function can be
- * called by the sink subdevice, in its v4l2-async notifier subdev bound
- * callback, to create links from a bound source subdevice.
+ * called by the sink, in its v4l2-async notifier bound callback, to create
+ * links from a bound source subdevice.
  *
  * The @flags argument specifies the link flags. The caller shall ensure that
  * the flags are valid regardless of the number of links that may be created.
index 7245887ef002fb4268d7ba9c0ed84311de58f1bf..cfd19e72d0fc455ee0a0784c47d78f733d7d9482 100644 (file)
@@ -1125,6 +1125,7 @@ struct v4l2_subdev_fh {
        struct module *owner;
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
        struct v4l2_subdev_state *state;
+       u64 client_caps;
 #endif
 };
 
@@ -1642,24 +1643,46 @@ u64 v4l2_subdev_state_xlate_streams(const struct v4l2_subdev_state *state,
  * enum v4l2_subdev_routing_restriction - Subdevice internal routing restrictions
  *
  * @V4L2_SUBDEV_ROUTING_NO_1_TO_N:
- *     an input stream may not be routed to multiple output streams (stream
+ *     an input stream shall not be routed to multiple output streams (stream
  *     duplication)
  * @V4L2_SUBDEV_ROUTING_NO_N_TO_1:
- *     multiple input streams may not be routed to the same output stream
+ *     multiple input streams shall not be routed to the same output stream
  *     (stream merging)
- * @V4L2_SUBDEV_ROUTING_NO_STREAM_MIX:
- *     streams on the same pad may not be routed to streams on different pads
+ * @V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX:
+ *     all streams from a sink pad must be routed to a single source pad
+ * @V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX:
+ *     all streams on a source pad must originate from a single sink pad
+ * @V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING:
+ *     source pads shall not contain multiplexed streams
+ * @V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING:
+ *     sink pads shall not contain multiplexed streams
  * @V4L2_SUBDEV_ROUTING_ONLY_1_TO_1:
  *     only non-overlapping 1-to-1 stream routing is allowed (a combination of
  *     @V4L2_SUBDEV_ROUTING_NO_1_TO_N and @V4L2_SUBDEV_ROUTING_NO_N_TO_1)
+ * @V4L2_SUBDEV_ROUTING_NO_STREAM_MIX:
+ *     all streams from a sink pad must be routed to a single source pad, and
+ *     that source pad shall not get routes from any other sink pad
+ *     (a combination of @V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX and
+ *     @V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX)
+ * @V4L2_SUBDEV_ROUTING_NO_MULTIPLEXING:
+ *     no multiplexed streams allowed on either source or sink sides.
  */
 enum v4l2_subdev_routing_restriction {
        V4L2_SUBDEV_ROUTING_NO_1_TO_N = BIT(0),
        V4L2_SUBDEV_ROUTING_NO_N_TO_1 = BIT(1),
-       V4L2_SUBDEV_ROUTING_NO_STREAM_MIX = BIT(2),
+       V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX = BIT(2),
+       V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX = BIT(3),
+       V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING = BIT(4),
+       V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING = BIT(5),
        V4L2_SUBDEV_ROUTING_ONLY_1_TO_1 =
                V4L2_SUBDEV_ROUTING_NO_1_TO_N |
                V4L2_SUBDEV_ROUTING_NO_N_TO_1,
+       V4L2_SUBDEV_ROUTING_NO_STREAM_MIX =
+               V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX |
+               V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX,
+       V4L2_SUBDEV_ROUTING_NO_MULTIPLEXING =
+               V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING |
+               V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING,
 };
 
 /**
index 654d659de83522217df923fd39243b9aaeefce91..4a195b68f28f6d788b17c962c19277ca4d822a1f 100644 (file)
@@ -233,6 +233,24 @@ struct v4l2_subdev_routing {
        __u32 reserved[6];
 };
 
+/*
+ * The client is aware of streams. Setting this flag enables the use of 'stream'
+ * fields (referring to the stream number) with various ioctls. If this is not
+ * set (which is the default), the 'stream' fields will be forced to 0 by the
+ * kernel.
+ */
+ #define V4L2_SUBDEV_CLIENT_CAP_STREAMS                (1U << 0)
+
+/**
+ * struct v4l2_subdev_client_capability - Capabilities of the client accessing
+ *                                       the subdev
+ *
+ * @capabilities: A bitmask of V4L2_SUBDEV_CLIENT_CAP_* flags.
+ */
+struct v4l2_subdev_client_capability {
+       __u64 capabilities;
+};
+
 /* Backwards compatibility define --- to be removed */
 #define v4l2_subdev_edid v4l2_edid
 
@@ -250,6 +268,9 @@ struct v4l2_subdev_routing {
 #define VIDIOC_SUBDEV_S_SELECTION              _IOWR('V', 62, struct v4l2_subdev_selection)
 #define VIDIOC_SUBDEV_G_ROUTING                        _IOWR('V', 38, struct v4l2_subdev_routing)
 #define VIDIOC_SUBDEV_S_ROUTING                        _IOWR('V', 39, struct v4l2_subdev_routing)
+#define VIDIOC_SUBDEV_G_CLIENT_CAP             _IOR('V',  101, struct v4l2_subdev_client_capability)
+#define VIDIOC_SUBDEV_S_CLIENT_CAP             _IOWR('V',  102, struct v4l2_subdev_client_capability)
+
 /* The following ioctls are identical to the ioctls in videodev2.h */
 #define VIDIOC_SUBDEV_G_STD                    _IOR('V', 23, v4l2_std_id)
 #define VIDIOC_SUBDEV_S_STD                    _IOW('V', 24, v4l2_std_id)
index 17a9b975177a10d1e05f8a0d84b37027ac9a5958..aee75eb9e686359a97a933c5e4c33df0c22a1500 100644 (file)
@@ -580,12 +580,17 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_RGBA1010102 v4l2_fourcc('R', 'A', '3', '0') /* 32  RGBA-10-10-10-2 */
 #define V4L2_PIX_FMT_ARGB2101010 v4l2_fourcc('A', 'R', '3', '0') /* 32  ARGB-2-10-10-10 */
 
+/* RGB formats (6 or 8 bytes per pixel) */
+#define V4L2_PIX_FMT_BGR48_12    v4l2_fourcc('B', '3', '1', '2') /* 48  BGR 12-bit per component */
+#define V4L2_PIX_FMT_ABGR64_12   v4l2_fourcc('B', '4', '1', '2') /* 64  BGRA 12-bit per component */
+
 /* Grey formats */
 #define V4L2_PIX_FMT_GREY    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
 #define V4L2_PIX_FMT_Y4      v4l2_fourcc('Y', '0', '4', ' ') /*  4  Greyscale     */
 #define V4L2_PIX_FMT_Y6      v4l2_fourcc('Y', '0', '6', ' ') /*  6  Greyscale     */
 #define V4L2_PIX_FMT_Y10     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
 #define V4L2_PIX_FMT_Y12     v4l2_fourcc('Y', '1', '2', ' ') /* 12  Greyscale     */
+#define V4L2_PIX_FMT_Y012    v4l2_fourcc('Y', '0', '1', '2') /* 12  Greyscale     */
 #define V4L2_PIX_FMT_Y14     v4l2_fourcc('Y', '1', '4', ' ') /* 14  Greyscale     */
 #define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
 #define V4L2_PIX_FMT_Y16_BE  v4l2_fourcc_be('Y', '1', '6', ' ') /* 16  Greyscale BE  */
@@ -620,6 +625,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_YUVA32  v4l2_fourcc('Y', 'U', 'V', 'A') /* 32  YUVA-8-8-8-8  */
 #define V4L2_PIX_FMT_YUVX32  v4l2_fourcc('Y', 'U', 'V', 'X') /* 32  YUVX-8-8-8-8  */
 #define V4L2_PIX_FMT_M420    v4l2_fourcc('M', '4', '2', '0') /* 12  YUV 4:2:0 2 lines y, 1 line uv interleaved */
+#define V4L2_PIX_FMT_YUV48_12    v4l2_fourcc('Y', '3', '1', '2') /* 48  YUV 4:4:4 12-bit per component */
 
 /*
  * YCbCr packed format. For each Y2xx format, xx bits of valid data occupy the MSBs
@@ -637,12 +643,14 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_NV24    v4l2_fourcc('N', 'V', '2', '4') /* 24  Y/CbCr 4:4:4  */
 #define V4L2_PIX_FMT_NV42    v4l2_fourcc('N', 'V', '4', '2') /* 24  Y/CrCb 4:4:4  */
 #define V4L2_PIX_FMT_P010    v4l2_fourcc('P', '0', '1', '0') /* 24  Y/CbCr 4:2:0 10-bit per component */
+#define V4L2_PIX_FMT_P012    v4l2_fourcc('P', '0', '1', '2') /* 24  Y/CbCr 4:2:0 12-bit per component */
 
 /* two non contiguous planes - one Y, one Cr + Cb interleaved  */
 #define V4L2_PIX_FMT_NV12M   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
 #define V4L2_PIX_FMT_NV21M   v4l2_fourcc('N', 'M', '2', '1') /* 21  Y/CrCb 4:2:0  */
 #define V4L2_PIX_FMT_NV16M   v4l2_fourcc('N', 'M', '1', '6') /* 16  Y/CbCr 4:2:2  */
 #define V4L2_PIX_FMT_NV61M   v4l2_fourcc('N', 'M', '6', '1') /* 16  Y/CrCb 4:2:2  */
+#define V4L2_PIX_FMT_P012M   v4l2_fourcc('P', 'M', '1', '2') /* 24  Y/CbCr 4:2:0 12-bit per component */
 
 /* three planes - Y Cb, Cr */
 #define V4L2_PIX_FMT_YUV410  v4l2_fourcc('Y', 'U', 'V', '9') /*  9  YUV 4:1:0     */
@@ -750,6 +758,9 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_FWHT_STATELESS     v4l2_fourcc('S', 'F', 'W', 'H') /* Stateless FWHT (vicodec) */
 #define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */
 #define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */
+#define V4L2_PIX_FMT_SPK      v4l2_fourcc('S', 'P', 'K', '0') /* Sorenson Spark */
+#define V4L2_PIX_FMT_RV30     v4l2_fourcc('R', 'V', '3', '0') /* RealVideo 8 */
+#define V4L2_PIX_FMT_RV40     v4l2_fourcc('R', 'V', '4', '0') /* RealVideo 9 & 10 */
 
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -1224,8 +1235,10 @@ struct v4l2_framebuffer {
 /*  Flags for the 'capability' field. Read only */
 #define V4L2_FBUF_CAP_EXTERNOVERLAY    0x0001
 #define V4L2_FBUF_CAP_CHROMAKEY                0x0002
+#ifndef __KERNEL__
 #define V4L2_FBUF_CAP_LIST_CLIPPING     0x0004
 #define V4L2_FBUF_CAP_BITMAP_CLIPPING  0x0008
+#endif
 #define V4L2_FBUF_CAP_LOCAL_ALPHA      0x0010
 #define V4L2_FBUF_CAP_GLOBAL_ALPHA     0x0020
 #define V4L2_FBUF_CAP_LOCAL_INV_ALPHA  0x0040