aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/media/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform')
-rw-r--r--drivers/media/platform/Kconfig191
-rw-r--r--drivers/media/platform/Makefile19
-rw-r--r--drivers/media/platform/am437x/Kconfig4
-rw-r--r--drivers/media/platform/atmel/Kconfig4
-rw-r--r--drivers/media/platform/cadence/Kconfig8
-rw-r--r--drivers/media/platform/cec-gpio/Makefile2
-rw-r--r--drivers/media/platform/cec-gpio/cec-gpio.c298
-rw-r--r--drivers/media/platform/coda/coda-bit.c9
-rw-r--r--drivers/media/platform/coda/coda-common.c199
-rw-r--r--drivers/media/platform/coda/coda-jpeg.c577
-rw-r--r--drivers/media/platform/coda/coda.h12
-rw-r--r--drivers/media/platform/cros-ec-cec/Makefile2
-rw-r--r--drivers/media/platform/cros-ec-cec/cros-ec-cec.c359
-rw-r--r--drivers/media/platform/davinci/vpif_display.c1
-rw-r--r--drivers/media/platform/exynos4-is/Kconfig5
-rw-r--r--drivers/media/platform/marvell-ccic/cafe-driver.c2
-rw-r--r--drivers/media/platform/meson/Makefile3
-rw-r--r--drivers/media/platform/meson/ao-cec-g12a.c796
-rw-r--r--drivers/media/platform/meson/ao-cec.c732
-rw-r--r--drivers/media/platform/mtk-mdp/mtk_mdp_comp.c8
-rw-r--r--drivers/media/platform/pxa_camera.c4
-rw-r--r--drivers/media/platform/qcom/venus/core.c21
-rw-r--r--drivers/media/platform/qcom/venus/core.h7
-rw-r--r--drivers/media/platform/qcom/venus/helpers.c18
-rw-r--r--drivers/media/platform/qcom/venus/helpers.h2
-rw-r--r--drivers/media/platform/qcom/venus/hfi.c10
-rw-r--r--drivers/media/platform/qcom/venus/hfi.h3
-rw-r--r--drivers/media/platform/qcom/venus/hfi_cmds.h2
-rw-r--r--drivers/media/platform/qcom/venus/hfi_msgs.c2
-rw-r--r--drivers/media/platform/qcom/venus/hfi_msgs.h10
-rw-r--r--drivers/media/platform/qcom/venus/vdec.c200
-rw-r--r--drivers/media/platform/qcom/venus/venc.c10
-rw-r--r--drivers/media/platform/rcar-fcp.c5
-rw-r--r--drivers/media/platform/rcar-vin/Kconfig8
-rw-r--r--drivers/media/platform/rcar-vin/rcar-csi2.c4
-rw-r--r--drivers/media/platform/rcar-vin/rcar-v4l2.c40
-rw-r--r--drivers/media/platform/s5p-cec/Makefile3
-rw-r--r--drivers/media/platform/s5p-cec/exynos_hdmi_cec.h34
-rw-r--r--drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c206
-rw-r--r--drivers/media/platform/s5p-cec/regs-cec.h93
-rw-r--r--drivers/media/platform/s5p-cec/s5p_cec.c307
-rw-r--r--drivers/media/platform/s5p-cec/s5p_cec.h76
-rw-r--r--drivers/media/platform/seco-cec/Makefile2
-rw-r--r--drivers/media/platform/seco-cec/seco-cec.c803
-rw-r--r--drivers/media/platform/seco-cec/seco-cec.h141
-rw-r--r--drivers/media/platform/sh_veu.c1203
-rw-r--r--drivers/media/platform/sti/cec/Makefile2
-rw-r--r--drivers/media/platform/sti/cec/stih-cec.c400
-rw-r--r--drivers/media/platform/stm32/Makefile1
-rw-r--r--drivers/media/platform/stm32/stm32-cec.c374
-rw-r--r--drivers/media/platform/sunxi/Kconfig2
-rw-r--r--drivers/media/platform/sunxi/Makefile2
-rw-r--r--drivers/media/platform/sunxi/sun4i-csi/Kconfig6
-rw-r--r--drivers/media/platform/sunxi/sun4i-csi/Makefile2
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/Kconfig4
-rw-r--r--drivers/media/platform/sunxi/sun8i-di/sun8i-di.c6
-rw-r--r--drivers/media/platform/tegra-cec/Makefile2
-rw-r--r--drivers/media/platform/tegra-cec/tegra_cec.c481
-rw-r--r--drivers/media/platform/tegra-cec/tegra_cec.h116
-rw-r--r--drivers/media/platform/ti-vpe/cal.c439
-rw-r--r--drivers/media/platform/ti-vpe/cal_regs.h21
-rw-r--r--drivers/media/platform/vicodec/Kconfig13
-rw-r--r--drivers/media/platform/vicodec/Makefile4
-rw-r--r--drivers/media/platform/vicodec/codec-fwht.c958
-rw-r--r--drivers/media/platform/vicodec/codec-fwht.h150
-rw-r--r--drivers/media/platform/vicodec/codec-v4l2-fwht.c367
-rw-r--r--drivers/media/platform/vicodec/codec-v4l2-fwht.h64
-rw-r--r--drivers/media/platform/vicodec/vicodec-core.c2238
-rw-r--r--drivers/media/platform/video-mux.c87
-rw-r--r--drivers/media/platform/vim2m.c1441
-rw-r--r--drivers/media/platform/vimc/Kconfig15
-rw-r--r--drivers/media/platform/vimc/Makefile6
-rw-r--r--drivers/media/platform/vimc/vimc-capture.c480
-rw-r--r--drivers/media/platform/vimc/vimc-common.c369
-rw-r--r--drivers/media/platform/vimc/vimc-common.h224
-rw-r--r--drivers/media/platform/vimc/vimc-core.c381
-rw-r--r--drivers/media/platform/vimc/vimc-debayer.c581
-rw-r--r--drivers/media/platform/vimc/vimc-scaler.c511
-rw-r--r--drivers/media/platform/vimc/vimc-sensor.c376
-rw-r--r--drivers/media/platform/vimc/vimc-streamer.c238
-rw-r--r--drivers/media/platform/vimc/vimc-streamer.h44
-rw-r--r--drivers/media/platform/vivid/Kconfig41
-rw-r--r--drivers/media/platform/vivid/Makefile12
-rw-r--r--drivers/media/platform/vivid/vivid-cec.c286
-rw-r--r--drivers/media/platform/vivid/vivid-cec.h20
-rw-r--r--drivers/media/platform/vivid/vivid-core.c2006
-rw-r--r--drivers/media/platform/vivid/vivid-core.h612
-rw-r--r--drivers/media/platform/vivid/vivid-ctrls.c1939
-rw-r--r--drivers/media/platform/vivid/vivid-ctrls.h22
-rw-r--r--drivers/media/platform/vivid/vivid-kthread-cap.c1007
-rw-r--r--drivers/media/platform/vivid/vivid-kthread-cap.h14
-rw-r--r--drivers/media/platform/vivid/vivid-kthread-out.c353
-rw-r--r--drivers/media/platform/vivid/vivid-kthread-out.h14
-rw-r--r--drivers/media/platform/vivid/vivid-kthread-touch.c181
-rw-r--r--drivers/media/platform/vivid/vivid-kthread-touch.h13
-rw-r--r--drivers/media/platform/vivid/vivid-meta-cap.c201
-rw-r--r--drivers/media/platform/vivid/vivid-meta-cap.h29
-rw-r--r--drivers/media/platform/vivid/vivid-meta-out.c174
-rw-r--r--drivers/media/platform/vivid/vivid-meta-out.h25
-rw-r--r--drivers/media/platform/vivid/vivid-osd.c388
-rw-r--r--drivers/media/platform/vivid/vivid-osd.h15
-rw-r--r--drivers/media/platform/vivid/vivid-radio-common.c177
-rw-r--r--drivers/media/platform/vivid/vivid-radio-common.h28
-rw-r--r--drivers/media/platform/vivid/vivid-radio-rx.c278
-rw-r--r--drivers/media/platform/vivid/vivid-radio-rx.h19
-rw-r--r--drivers/media/platform/vivid/vivid-radio-tx.c128
-rw-r--r--drivers/media/platform/vivid/vivid-radio-tx.h17
-rw-r--r--drivers/media/platform/vivid/vivid-rds-gen.c157
-rw-r--r--drivers/media/platform/vivid/vivid-rds-gen.h42
-rw-r--r--drivers/media/platform/vivid/vivid-sdr-cap.c570
-rw-r--r--drivers/media/platform/vivid/vivid-sdr-cap.h24
-rw-r--r--drivers/media/platform/vivid/vivid-touch-cap.c341
-rw-r--r--drivers/media/platform/vivid/vivid-touch-cap.h39
-rw-r--r--drivers/media/platform/vivid/vivid-vbi-cap.c365
-rw-r--r--drivers/media/platform/vivid/vivid-vbi-cap.h28
-rw-r--r--drivers/media/platform/vivid/vivid-vbi-gen.c311
-rw-r--r--drivers/media/platform/vivid/vivid-vbi-gen.h21
-rw-r--r--drivers/media/platform/vivid/vivid-vbi-out.c250
-rw-r--r--drivers/media/platform/vivid/vivid-vbi-out.h22
-rw-r--r--drivers/media/platform/vivid/vivid-vid-cap.c1918
-rw-r--r--drivers/media/platform/vivid/vivid-vid-cap.h59
-rw-r--r--drivers/media/platform/vivid/vivid-vid-common.c1035
-rw-r--r--drivers/media/platform/vivid/vivid-vid-common.h38
-rw-r--r--drivers/media/platform/vivid/vivid-vid-out.c1210
-rw-r--r--drivers/media/platform/vivid/vivid-vid-out.h44
-rw-r--r--drivers/media/platform/xilinx/Kconfig4
126 files changed, 1427 insertions, 29900 deletions
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index e01bbb9dd1c1..c57ee78fa99d 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -5,7 +5,6 @@
menuconfig V4L_PLATFORM_DRIVERS
bool "V4L platform devices"
- depends on MEDIA_CAMERA_SUPPORT
help
Say Y here to enable support for platform-specific V4L drivers.
@@ -15,7 +14,7 @@ source "drivers/media/platform/marvell-ccic/Kconfig"
config VIDEO_VIA_CAMERA
tristate "VIAFB camera controller support"
- depends on FB_VIA
+ depends on FB_VIA && VIDEO_V4L2
select VIDEOBUF2_DMA_SG
select VIDEO_OV7670
help
@@ -43,7 +42,6 @@ config VIDEO_ASPEED
config VIDEO_SH_VOU
tristate "SuperH VOU video output driver"
- depends on MEDIA_CAMERA_SUPPORT
depends on VIDEO_DEV && I2C
depends on ARCH_SHMOBILE || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
@@ -65,7 +63,9 @@ config VIDEO_VIU
config VIDEO_MUX
tristate "Video Multiplexer"
select MULTIPLEXER
- depends on VIDEO_V4L2 && OF && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
+ depends on VIDEO_V4L2 && OF
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select REGMAP
select V4L2_FWNODE
help
@@ -73,10 +73,12 @@ config VIDEO_MUX
config VIDEO_OMAP3
tristate "OMAP 3 Camera support"
- depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_V4L2 && I2C
depends on (ARCH_OMAP3 && OMAP_IOMMU) || COMPILE_TEST
depends on COMMON_CLK && OF
select ARM_DMA_USE_IOMMU if OMAP_IOMMU
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select MFD_SYSCON
select V4L2_FWNODE
@@ -101,16 +103,19 @@ config VIDEO_PXA27x
config VIDEO_QCOM_CAMSS
tristate "Qualcomm V4L2 Camera Subsystem driver"
- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_V4L2
depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_SG
select V4L2_FWNODE
config VIDEO_S3C_CAMIF
tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
- depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
- depends on PM
+ depends on VIDEO_V4L2 && I2C && PM
depends on ARCH_S3C64XX || PLAT_S3C24XX || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
help
This is a v4l2 driver for s3c24xx and s3c64xx SoC series camera
@@ -121,9 +126,10 @@ config VIDEO_S3C_CAMIF
config VIDEO_STM32_DCMI
tristate "STM32 Digital Camera Memory Interface (DCMI) support"
- depends on VIDEO_V4L2 && OF && MEDIA_CONTROLLER
+ depends on VIDEO_V4L2 && OF
depends on ARCH_STM32 || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
+ select MEDIA_CONTROLLER
select V4L2_FWNODE
help
This module makes the STM32 Digital Camera Memory Interface (DCMI)
@@ -150,7 +156,9 @@ source "drivers/media/platform/sunxi/Kconfig"
config VIDEO_TI_CAL
tristate "TI CAL (Camera Adaptation Layer) driver"
- depends on VIDEO_DEV && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_DEV && VIDEO_V4L2
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
depends on SOC_DRA7XX || ARCH_K3 || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
select V4L2_FWNODE
@@ -165,7 +173,6 @@ endif # V4L_PLATFORM_DRIVERS
menuconfig V4L_MEM2MEM_DRIVERS
bool "Memory-to-memory multimedia devices"
depends on VIDEO_V4L2
- depends on MEDIA_CAMERA_SUPPORT
help
Say Y here to enable selecting drivers for V4L devices that
use system memory for both source and destination buffers, as opposed
@@ -180,6 +187,7 @@ config VIDEO_CODA
select SRAM
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
+ select V4L2_JPEG_HELPER
select V4L2_MEM2MEM_DEV
select GENERIC_ALLOCATOR
help
@@ -385,15 +393,6 @@ config VIDEO_STI_DELTA_DRIVER
endif # VIDEO_STI_DELTA
-config VIDEO_SH_VEU
- tristate "SuperH VEU mem2mem video processing driver"
- depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
- select VIDEOBUF2_DMA_CONTIG
- select V4L2_MEM2MEM_DEV
- help
- Support for the Video Engine Unit (VEU) on SuperH and
- SH-Mobile SoCs.
-
config VIDEO_RENESAS_FDP1
tristate "Renesas Fine Display Processor"
depends on VIDEO_DEV && VIDEO_V4L2
@@ -435,9 +434,11 @@ config VIDEO_RENESAS_FCP
config VIDEO_RENESAS_VSP1
tristate "Renesas VSP1 Video Processing Engine"
- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_V4L2
depends on ARCH_RENESAS || COMPILE_TEST
depends on (!ARM64 && !VIDEO_RENESAS_FCP) || VIDEO_RENESAS_FCP
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
help
@@ -532,29 +533,6 @@ config VIDEO_TI_SC
config VIDEO_TI_CSC
tristate
-menuconfig V4L_TEST_DRIVERS
- bool "Media test drivers"
- depends on MEDIA_CAMERA_SUPPORT
-
-if V4L_TEST_DRIVERS
-
-source "drivers/media/platform/vimc/Kconfig"
-
-source "drivers/media/platform/vivid/Kconfig"
-
-config VIDEO_VIM2M
- tristate "Virtual Memory-to-Memory Driver"
- depends on VIDEO_DEV && VIDEO_V4L2
- select VIDEOBUF2_VMALLOC
- select V4L2_MEM2MEM_DEV
- help
- This is a virtual test device for the memory-to-memory driver
- framework.
-
-source "drivers/media/platform/vicodec/Kconfig"
-
-endif #V4L_TEST_DRIVERS
-
menuconfig DVB_PLATFORM_DRIVERS
bool "DVB platform devices"
depends on MEDIA_DIGITAL_TV_SUPPORT
@@ -565,131 +543,6 @@ if DVB_PLATFORM_DRIVERS
source "drivers/media/platform/sti/c8sectpfe/Kconfig"
endif #DVB_PLATFORM_DRIVERS
-menuconfig CEC_PLATFORM_DRIVERS
- bool "CEC platform devices"
- depends on MEDIA_CEC_SUPPORT
-
-if CEC_PLATFORM_DRIVERS
-
-config VIDEO_CROS_EC_CEC
- tristate "ChromeOS EC CEC driver"
- depends on CROS_EC
- select CEC_CORE
- select CEC_NOTIFIER
- select CROS_EC_PROTO
- help
- If you say yes here you will get support for the
- ChromeOS Embedded Controller's CEC.
- The CEC bus is present in the HDMI connector and enables communication
- between compatible devices.
-
-config VIDEO_MESON_AO_CEC
- tristate "Amlogic Meson AO CEC driver"
- depends on ARCH_MESON || COMPILE_TEST
- select CEC_CORE
- select CEC_NOTIFIER
- help
- This is a driver for Amlogic Meson SoCs AO CEC interface. It uses the
- generic CEC framework interface.
- CEC bus is present in the HDMI connector and enables communication
-
-config VIDEO_MESON_G12A_AO_CEC
- tristate "Amlogic Meson G12A AO CEC driver"
- depends on ARCH_MESON || COMPILE_TEST
- depends on COMMON_CLK && OF
- select REGMAP
- select REGMAP_MMIO
- select CEC_CORE
- select CEC_NOTIFIER
- ---help---
- This is a driver for Amlogic Meson G12A SoCs AO CEC interface.
- This driver if for the new AO-CEC module found in G12A SoCs,
- usually named AO_CEC_B in documentation.
- It uses the generic CEC framework interface.
- CEC bus is present in the HDMI connector and enables communication
- between compatible devices.
-
-config CEC_GPIO
- tristate "Generic GPIO-based CEC driver"
- depends on PREEMPTION || COMPILE_TEST
- select CEC_CORE
- select CEC_PIN
- select CEC_NOTIFIER
- select GPIOLIB
- help
- This is a generic GPIO-based CEC driver.
- The CEC bus is present in the HDMI connector and enables communication
- between compatible devices.
-
-config VIDEO_SAMSUNG_S5P_CEC
- tristate "Samsung S5P CEC driver"
- depends on ARCH_EXYNOS || COMPILE_TEST
- select CEC_CORE
- select CEC_NOTIFIER
- help
- This is a driver for Samsung S5P HDMI CEC interface. It uses the
- generic CEC framework interface.
- CEC bus is present in the HDMI connector and enables communication
- between compatible devices.
-
-config VIDEO_STI_HDMI_CEC
- tristate "STMicroelectronics STiH4xx HDMI CEC driver"
- depends on ARCH_STI || COMPILE_TEST
- select CEC_CORE
- select CEC_NOTIFIER
- help
- This is a driver for STIH4xx HDMI CEC interface. It uses the
- generic CEC framework interface.
- CEC bus is present in the HDMI connector and enables communication
- between compatible devices.
-
-config VIDEO_STM32_HDMI_CEC
- tristate "STMicroelectronics STM32 HDMI CEC driver"
- depends on ARCH_STM32 || COMPILE_TEST
- select REGMAP
- select REGMAP_MMIO
- select CEC_CORE
- help
- This is a driver for STM32 interface. It uses the
- generic CEC framework interface.
- CEC bus is present in the HDMI connector and enables communication
- between compatible devices.
-
-config VIDEO_TEGRA_HDMI_CEC
- tristate "Tegra HDMI CEC driver"
- depends on ARCH_TEGRA || COMPILE_TEST
- select CEC_CORE
- select CEC_NOTIFIER
- help
- This is a driver for the Tegra HDMI CEC interface. It uses the
- generic CEC framework interface.
- The CEC bus is present in the HDMI connector and enables communication
- between compatible devices.
-
-config VIDEO_SECO_CEC
- tristate "SECO Boards HDMI CEC driver"
- depends on (X86 || IA64) || COMPILE_TEST
- depends on PCI && DMI
- select CEC_CORE
- select CEC_NOTIFIER
- help
- This is a driver for SECO Boards integrated CEC interface.
- Selecting it will enable support for this device.
- CEC bus is present in the HDMI connector and enables communication
- between compatible devices.
-
-config VIDEO_SECO_RC
- bool "SECO Boards IR RC5 support"
- depends on VIDEO_SECO_CEC
- depends on RC_CORE=y || RC_CORE = VIDEO_SECO_CEC
- help
- If you say yes here you will get support for the
- SECO Boards Consumer-IR in seco-cec driver.
- The embedded controller supports RC5 protocol only, default mapping
- is set to rc-hauppauge.
-
-endif #CEC_PLATFORM_DRIVERS
-
menuconfig SDR_PLATFORM_DRIVERS
bool "SDR platform devices"
depends on MEDIA_SDR_SUPPORT
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index d13db96e3015..62b6cdc8c730 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -14,11 +14,6 @@ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o
-obj-$(CONFIG_VIDEO_VIMC) += vimc/
-obj-$(CONFIG_VIDEO_VIVID) += vivid/
-obj-$(CONFIG_VIDEO_VIM2M) += vim2m.o
-obj-$(CONFIG_VIDEO_VICODEC) += vicodec/
-
obj-y += ti-vpe/
obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o
@@ -26,10 +21,6 @@ obj-$(CONFIG_VIDEO_CODA) += coda/
obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o
-obj-$(CONFIG_VIDEO_SH_VEU) += sh_veu.o
-
-obj-$(CONFIG_CEC_GPIO) += cec-gpio/
-
obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE) += m2m-deinterlace.o
obj-$(CONFIG_VIDEO_MUX) += video-mux.o
@@ -40,22 +31,16 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_CEC) += s5p-cec/
obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC) += exynos-gsc/
obj-$(CONFIG_VIDEO_STI_BDISP) += sti/bdisp/
obj-$(CONFIG_VIDEO_STI_HVA) += sti/hva/
obj-$(CONFIG_DVB_C8SECTPFE) += sti/c8sectpfe/
-obj-$(CONFIG_VIDEO_STI_HDMI_CEC) += sti/cec/
obj-$(CONFIG_VIDEO_STI_DELTA) += sti/delta/
-obj-$(CONFIG_VIDEO_TEGRA_HDMI_CEC) += tegra-cec/
-
obj-y += stm32/
-obj-$(CONFIG_VIDEO_SECO_CEC) += seco-cec/
-
obj-y += davinci/
obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o
@@ -94,8 +79,4 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss/
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
-obj-y += meson/
-
-obj-y += cros-ec-cec/
-
obj-y += sunxi/
diff --git a/drivers/media/platform/am437x/Kconfig b/drivers/media/platform/am437x/Kconfig
index d6f2e3d0cbef..9ef898f512de 100644
--- a/drivers/media/platform/am437x/Kconfig
+++ b/drivers/media/platform/am437x/Kconfig
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
config VIDEO_AM437X_VPFE
tristate "TI AM437x VPFE video capture driver"
- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_V4L2
depends on SOC_AM43XX || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select V4L2_FWNODE
help
diff --git a/drivers/media/platform/atmel/Kconfig b/drivers/media/platform/atmel/Kconfig
index 5ae3f60b81b1..1850fe7f9360 100644
--- a/drivers/media/platform/atmel/Kconfig
+++ b/drivers/media/platform/atmel/Kconfig
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
config VIDEO_ATMEL_ISC
tristate "ATMEL Image Sensor Controller (ISC) support"
- depends on VIDEO_V4L2 && COMMON_CLK && VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_V4L2 && COMMON_CLK
depends on ARCH_AT91 || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select REGMAP_MMIO
select V4L2_FWNODE
diff --git a/drivers/media/platform/cadence/Kconfig b/drivers/media/platform/cadence/Kconfig
index c154e368d701..80cf601323ce 100644
--- a/drivers/media/platform/cadence/Kconfig
+++ b/drivers/media/platform/cadence/Kconfig
@@ -13,8 +13,8 @@ if VIDEO_CADENCE
config VIDEO_CADENCE_CSI2RX
tristate "Cadence MIPI-CSI2 RX Controller"
depends on VIDEO_V4L2
- depends on MEDIA_CONTROLLER
- depends on VIDEO_V4L2_SUBDEV_API
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
Support for the Cadence MIPI CSI2 Receiver controller.
@@ -25,8 +25,8 @@ config VIDEO_CADENCE_CSI2RX
config VIDEO_CADENCE_CSI2TX
tristate "Cadence MIPI-CSI2 TX Controller"
depends on VIDEO_V4L2
- depends on MEDIA_CONTROLLER
- depends on VIDEO_V4L2_SUBDEV_API
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
Support for the Cadence MIPI CSI2 Transceiver controller.
diff --git a/drivers/media/platform/cec-gpio/Makefile b/drivers/media/platform/cec-gpio/Makefile
deleted file mode 100644
index a40c621dbd24..000000000000
--- a/drivers/media/platform/cec-gpio/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_CEC_GPIO) += cec-gpio.o
diff --git a/drivers/media/platform/cec-gpio/cec-gpio.c b/drivers/media/platform/cec-gpio/cec-gpio.c
deleted file mode 100644
index 42d2c2cd9a78..000000000000
--- a/drivers/media/platform/cec-gpio/cec-gpio.c
+++ /dev/null
@@ -1,298 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/gpio/consumer.h>
-#include <media/cec-notifier.h>
-#include <media/cec-pin.h>
-
-struct cec_gpio {
- struct cec_adapter *adap;
- struct cec_notifier *notifier;
- struct device *dev;
-
- struct gpio_desc *cec_gpio;
- int cec_irq;
- bool cec_is_low;
-
- struct gpio_desc *hpd_gpio;
- int hpd_irq;
- bool hpd_is_high;
- ktime_t hpd_ts;
-
- struct gpio_desc *v5_gpio;
- int v5_irq;
- bool v5_is_high;
- ktime_t v5_ts;
-};
-
-static bool cec_gpio_read(struct cec_adapter *adap)
-{
- struct cec_gpio *cec = cec_get_drvdata(adap);
-
- if (cec->cec_is_low)
- return false;
- return gpiod_get_value(cec->cec_gpio);
-}
-
-static void cec_gpio_high(struct cec_adapter *adap)
-{
- struct cec_gpio *cec = cec_get_drvdata(adap);
-
- if (!cec->cec_is_low)
- return;
- cec->cec_is_low = false;
- gpiod_set_value(cec->cec_gpio, 1);
-}
-
-static void cec_gpio_low(struct cec_adapter *adap)
-{
- struct cec_gpio *cec = cec_get_drvdata(adap);
-
- if (cec->cec_is_low)
- return;
- cec->cec_is_low = true;
- gpiod_set_value(cec->cec_gpio, 0);
-}
-
-static irqreturn_t cec_hpd_gpio_irq_handler_thread(int irq, void *priv)
-{
- struct cec_gpio *cec = priv;
-
- cec_queue_pin_hpd_event(cec->adap, cec->hpd_is_high, cec->hpd_ts);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t cec_5v_gpio_irq_handler(int irq, void *priv)
-{
- struct cec_gpio *cec = priv;
- bool is_high = gpiod_get_value(cec->v5_gpio);
-
- if (is_high == cec->v5_is_high)
- return IRQ_HANDLED;
- cec->v5_ts = ktime_get();
- cec->v5_is_high = is_high;
- return IRQ_WAKE_THREAD;
-}
-
-static irqreturn_t cec_5v_gpio_irq_handler_thread(int irq, void *priv)
-{
- struct cec_gpio *cec = priv;
-
- cec_queue_pin_5v_event(cec->adap, cec->v5_is_high, cec->v5_ts);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t cec_hpd_gpio_irq_handler(int irq, void *priv)
-{
- struct cec_gpio *cec = priv;
- bool is_high = gpiod_get_value(cec->hpd_gpio);
-
- if (is_high == cec->hpd_is_high)
- return IRQ_HANDLED;
- cec->hpd_ts = ktime_get();
- cec->hpd_is_high = is_high;
- return IRQ_WAKE_THREAD;
-}
-
-static irqreturn_t cec_gpio_irq_handler(int irq, void *priv)
-{
- struct cec_gpio *cec = priv;
-
- cec_pin_changed(cec->adap, gpiod_get_value(cec->cec_gpio));
- return IRQ_HANDLED;
-}
-
-static bool cec_gpio_enable_irq(struct cec_adapter *adap)
-{
- struct cec_gpio *cec = cec_get_drvdata(adap);
-
- enable_irq(cec->cec_irq);
- return true;
-}
-
-static void cec_gpio_disable_irq(struct cec_adapter *adap)
-{
- struct cec_gpio *cec = cec_get_drvdata(adap);
-
- disable_irq(cec->cec_irq);
-}
-
-static void cec_gpio_status(struct cec_adapter *adap, struct seq_file *file)
-{
- struct cec_gpio *cec = cec_get_drvdata(adap);
-
- seq_printf(file, "mode: %s\n", cec->cec_is_low ? "low-drive" : "read");
- seq_printf(file, "using irq: %d\n", cec->cec_irq);
- if (cec->hpd_gpio)
- seq_printf(file, "hpd: %s\n",
- cec->hpd_is_high ? "high" : "low");
- if (cec->v5_gpio)
- seq_printf(file, "5V: %s\n",
- cec->v5_is_high ? "high" : "low");
-}
-
-static int cec_gpio_read_hpd(struct cec_adapter *adap)
-{
- struct cec_gpio *cec = cec_get_drvdata(adap);
-
- if (!cec->hpd_gpio)
- return -ENOTTY;
- return gpiod_get_value(cec->hpd_gpio);
-}
-
-static int cec_gpio_read_5v(struct cec_adapter *adap)
-{
- struct cec_gpio *cec = cec_get_drvdata(adap);
-
- if (!cec->v5_gpio)
- return -ENOTTY;
- return gpiod_get_value(cec->v5_gpio);
-}
-
-static void cec_gpio_free(struct cec_adapter *adap)
-{
- cec_gpio_disable_irq(adap);
-}
-
-static const struct cec_pin_ops cec_gpio_pin_ops = {
- .read = cec_gpio_read,
- .low = cec_gpio_low,
- .high = cec_gpio_high,
- .enable_irq = cec_gpio_enable_irq,
- .disable_irq = cec_gpio_disable_irq,
- .status = cec_gpio_status,
- .free = cec_gpio_free,
- .read_hpd = cec_gpio_read_hpd,
- .read_5v = cec_gpio_read_5v,
-};
-
-static int cec_gpio_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device *hdmi_dev;
- struct cec_gpio *cec;
- u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN;
- int ret;
-
- hdmi_dev = cec_notifier_parse_hdmi_phandle(dev);
- if (PTR_ERR(hdmi_dev) == -EPROBE_DEFER)
- return PTR_ERR(hdmi_dev);
- if (IS_ERR(hdmi_dev))
- caps |= CEC_CAP_PHYS_ADDR;
-
- cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL);
- if (!cec)
- return -ENOMEM;
-
- cec->dev = dev;
-
- cec->cec_gpio = devm_gpiod_get(dev, "cec", GPIOD_OUT_HIGH_OPEN_DRAIN);
- if (IS_ERR(cec->cec_gpio))
- return PTR_ERR(cec->cec_gpio);
- cec->cec_irq = gpiod_to_irq(cec->cec_gpio);
-
- cec->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN);
- if (IS_ERR(cec->hpd_gpio))
- return PTR_ERR(cec->hpd_gpio);
-
- cec->v5_gpio = devm_gpiod_get_optional(dev, "v5", GPIOD_IN);
- if (IS_ERR(cec->v5_gpio))
- return PTR_ERR(cec->v5_gpio);
-
- cec->adap = cec_pin_allocate_adapter(&cec_gpio_pin_ops,
- cec, pdev->name, caps);
- if (IS_ERR(cec->adap))
- return PTR_ERR(cec->adap);
-
- ret = devm_request_irq(dev, cec->cec_irq, cec_gpio_irq_handler,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- cec->adap->name, cec);
- if (ret)
- goto del_adap;
-
- cec_gpio_disable_irq(cec->adap);
-
- if (cec->hpd_gpio) {
- cec->hpd_irq = gpiod_to_irq(cec->hpd_gpio);
- ret = devm_request_threaded_irq(dev, cec->hpd_irq,
- cec_hpd_gpio_irq_handler,
- cec_hpd_gpio_irq_handler_thread,
- IRQF_ONESHOT |
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "hpd-gpio", cec);
- if (ret)
- goto del_adap;
- }
-
- if (cec->v5_gpio) {
- cec->v5_irq = gpiod_to_irq(cec->v5_gpio);
- ret = devm_request_threaded_irq(dev, cec->v5_irq,
- cec_5v_gpio_irq_handler,
- cec_5v_gpio_irq_handler_thread,
- IRQF_ONESHOT |
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "v5-gpio", cec);
- if (ret)
- goto del_adap;
- }
-
- if (!IS_ERR(hdmi_dev)) {
- cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
- cec->adap);
- if (!cec->notifier) {
- ret = -ENOMEM;
- goto del_adap;
- }
- }
-
- ret = cec_register_adapter(cec->adap, &pdev->dev);
- if (ret)
- goto unreg_notifier;
-
- platform_set_drvdata(pdev, cec);
- return 0;
-
-unreg_notifier:
- cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
-del_adap:
- cec_delete_adapter(cec->adap);
- return ret;
-}
-
-static int 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[] = {
- {
- .compatible = "cec-gpio",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, cec_gpio_match);
-
-static struct platform_driver cec_gpio_pdrv = {
- .probe = cec_gpio_probe,
- .remove = cec_gpio_remove,
- .driver = {
- .name = "cec-gpio",
- .of_match_table = cec_gpio_match,
- },
-};
-
-module_platform_driver(cec_gpio_pdrv);
-
-MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CEC GPIO driver");
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index 3443396ba5f3..b021604eceaa 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -1215,7 +1215,8 @@ static int coda_start_encoding(struct coda_ctx *ctx)
coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
}
- if (ctx->params.bitrate) {
+ if (ctx->params.bitrate && (ctx->params.frame_rc_enable ||
+ ctx->params.mb_rc_enable)) {
ctx->params.bitrate_changed = false;
ctx->params.h264_intra_qp_changed = false;
@@ -1276,7 +1277,11 @@ static int coda_start_encoding(struct coda_ctx *ctx)
}
coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION);
- coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE);
+ if (ctx->params.frame_rc_enable && !ctx->params.mb_rc_enable)
+ value = 1;
+ else
+ value = 0;
+ coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE);
coda_setup_iram(ctx);
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index d0d093dd8f7c..6f41f74d492c 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -159,6 +159,7 @@ static const struct coda_codec coda9_codecs[] = {
CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088),
CODA_CODEC(CODA9_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088),
CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088),
+ CODA_CODEC(CODA9_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420, 8192, 8192),
};
struct coda_video_device {
@@ -252,6 +253,22 @@ static const struct coda_video_device coda9_jpeg_encoder = {
},
};
+static const struct coda_video_device coda9_jpeg_decoder = {
+ .name = "coda-jpeg-decoder",
+ .type = CODA_INST_DECODER,
+ .ops = &coda9_jpeg_decode_ops,
+ .direct = true,
+ .src_formats = {
+ V4L2_PIX_FMT_JPEG,
+ },
+ .dst_formats = {
+ V4L2_PIX_FMT_NV12,
+ V4L2_PIX_FMT_YUV420,
+ V4L2_PIX_FMT_YVU420,
+ V4L2_PIX_FMT_YUV422P,
+ },
+};
+
static const struct coda_video_device *codadx6_video_devices[] = {
&coda_bit_encoder,
};
@@ -270,6 +287,7 @@ static const struct coda_video_device *coda7_video_devices[] = {
static const struct coda_video_device *coda9_video_devices[] = {
&coda9_jpeg_encoder,
+ &coda9_jpeg_decoder,
&coda_bit_encoder,
&coda_bit_decoder,
};
@@ -411,6 +429,12 @@ static int coda_querycap(struct file *file, void *priv,
return 0;
}
+static const u32 coda_formats_420[CODA_MAX_FORMATS] = {
+ V4L2_PIX_FMT_NV12,
+ V4L2_PIX_FMT_YUV420,
+ V4L2_PIX_FMT_YVU420,
+};
+
static int coda_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
@@ -421,10 +445,33 @@ static int coda_enum_fmt(struct file *file, void *priv,
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
formats = cvd->src_formats;
- else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ struct coda_q_data *q_data_src;
+ struct vb2_queue *src_vq;
+
formats = cvd->dst_formats;
- else
+
+ /*
+ * If the source format is already fixed, only allow the same
+ * chroma subsampling.
+ */
+ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
+ vb2_is_streaming(src_vq)) {
+ if (ctx->params.jpeg_chroma_subsampling ==
+ V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
+ formats = coda_formats_420;
+ } else if (ctx->params.jpeg_chroma_subsampling ==
+ V4L2_JPEG_CHROMA_SUBSAMPLING_422) {
+ f->pixelformat = V4L2_PIX_FMT_YUV422P;
+ return f->index ? -EINVAL : 0;
+ }
+ }
+ } else {
return -EINVAL;
+ }
if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0)
return -EINVAL;
@@ -614,12 +661,23 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
/*
* If the source format is already fixed, only allow the same output
- * resolution
+ * resolution. When decoding JPEG images, we also have to make sure to
+ * use the same chroma subsampling.
*/
src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (vb2_is_streaming(src_vq)) {
f->fmt.pix.width = q_data_src->width;
f->fmt.pix.height = q_data_src->height;
+
+ if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
+ if (ctx->params.jpeg_chroma_subsampling ==
+ V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
+ f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
+ else if (ctx->params.jpeg_chroma_subsampling ==
+ V4L2_JPEG_CHROMA_SUBSAMPLING_422)
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
+ }
}
f->fmt.pix.colorspace = ctx->colorspace;
@@ -637,12 +695,18 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
if (ret < 0)
return ret;
- /* The h.264 decoder only returns complete 16x16 macroblocks */
- if (codec && codec->src_fourcc == V4L2_PIX_FMT_H264) {
- f->fmt.pix.height = round_up(f->fmt.pix.height, 16);
+ /* The decoders always write complete macroblocks or MCUs */
+ if (ctx->inst_type == CODA_INST_DECODER) {
f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
- f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
- f->fmt.pix.height * 3 / 2;
+ f->fmt.pix.height = round_up(f->fmt.pix.height, 16);
+ if (codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
+ f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
+ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+ f->fmt.pix.height * 2;
+ } else {
+ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+ f->fmt.pix.height * 3 / 2;
+ }
ret = coda_try_fmt_vdoa(ctx, f, &use_vdoa);
if (ret < 0)
@@ -747,6 +811,7 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
/* else fall through */
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_YUV422P:
ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP;
break;
default:
@@ -1088,6 +1153,51 @@ static int coda_try_decoder_cmd(struct file *file, void *fh,
return v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
}
+static bool coda_mark_last_meta(struct coda_ctx *ctx)
+{
+ struct coda_buffer_meta *meta;
+
+ coda_dbg(1, ctx, "marking last meta\n");
+
+ spin_lock(&ctx->buffer_meta_lock);
+ if (list_empty(&ctx->buffer_meta_list)) {
+ spin_unlock(&ctx->buffer_meta_lock);
+ return false;
+ }
+
+ meta = list_last_entry(&ctx->buffer_meta_list, struct coda_buffer_meta,
+ list);
+ meta->last = true;
+
+ spin_unlock(&ctx->buffer_meta_lock);
+ return true;
+}
+
+static bool coda_mark_last_dst_buf(struct coda_ctx *ctx)
+{
+ struct vb2_v4l2_buffer *buf;
+ struct vb2_buffer *dst_vb;
+ struct vb2_queue *dst_vq;
+ unsigned long flags;
+
+ coda_dbg(1, ctx, "marking last capture buffer\n");
+
+ dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ spin_lock_irqsave(&dst_vq->done_lock, flags);
+ if (list_empty(&dst_vq->done_list)) {
+ spin_unlock_irqrestore(&dst_vq->done_lock, flags);
+ return false;
+ }
+
+ dst_vb = list_last_entry(&dst_vq->done_list, struct vb2_buffer,
+ done_entry);
+ buf = to_vb2_v4l2_buffer(dst_vb);
+ buf->flags |= V4L2_BUF_FLAG_LAST;
+
+ spin_unlock_irqrestore(&dst_vq->done_lock, flags);
+ return true;
+}
+
static int coda_decoder_cmd(struct file *file, void *fh,
struct v4l2_decoder_cmd *dc)
{
@@ -1120,6 +1230,8 @@ static int coda_decoder_cmd(struct file *file, void *fh,
stream_end = false;
wakeup = false;
+ mutex_lock(&ctx->wakeup_mutex);
+
buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
if (buf) {
coda_dbg(1, ctx, "marking last pending buffer\n");
@@ -1132,22 +1244,14 @@ static int coda_decoder_cmd(struct file *file, void *fh,
stream_end = true;
}
} else {
- coda_dbg(1, ctx, "marking last meta\n");
-
- /* Mark last meta */
- spin_lock(&ctx->buffer_meta_lock);
- if (!list_empty(&ctx->buffer_meta_list)) {
- struct coda_buffer_meta *meta;
-
- meta = list_last_entry(&ctx->buffer_meta_list,
- struct coda_buffer_meta,
- list);
- meta->last = true;
- stream_end = true;
- } else {
- wakeup = true;
- }
- spin_unlock(&ctx->buffer_meta_lock);
+ if (ctx->use_bit)
+ if (coda_mark_last_meta(ctx))
+ stream_end = true;
+ else
+ wakeup = true;
+ else
+ if (!coda_mark_last_dst_buf(ctx))
+ wakeup = true;
}
if (stream_end) {
@@ -1164,6 +1268,7 @@ static int coda_decoder_cmd(struct file *file, void *fh,
coda_wake_up_capture_queue(ctx);
}
+ mutex_unlock(&ctx->wakeup_mutex);
break;
default:
return -EINVAL;
@@ -1894,6 +1999,42 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
}
}
+ /*
+ * Check the first input JPEG buffer to determine chroma
+ * subsampling.
+ */
+ if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
+ buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ ret = coda_jpeg_decode_header(ctx, &buf->vb2_buf);
+ if (ret < 0) {
+ v4l2_err(v4l2_dev,
+ "failed to decode JPEG header: %d\n",
+ ret);
+ goto err;
+ }
+
+ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ q_data_dst->width = round_up(q_data_src->width, 16);
+ q_data_dst->height = round_up(q_data_src->height, 16);
+ q_data_dst->bytesperline = q_data_dst->width;
+ if (ctx->params.jpeg_chroma_subsampling ==
+ V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
+ q_data_dst->sizeimage =
+ q_data_dst->bytesperline *
+ q_data_dst->height * 3 / 2;
+ if (q_data_dst->fourcc != V4L2_PIX_FMT_YUV420)
+ q_data_dst->fourcc = V4L2_PIX_FMT_NV12;
+ } else {
+ q_data_dst->sizeimage =
+ q_data_dst->bytesperline *
+ q_data_dst->height * 2;
+ q_data_dst->fourcc = V4L2_PIX_FMT_YUV422P;
+ }
+ q_data_dst->rect.left = 0;
+ q_data_dst->rect.top = 0;
+ q_data_dst->rect.width = q_data_src->width;
+ q_data_dst->rect.height = q_data_src->height;
+ }
ctx->streamon_out = 1;
} else {
ctx->streamon_cap = 1;
@@ -2082,6 +2223,12 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION:
ctx->params.h264_constrained_intra_pred_flag = ctrl->val;
break;
+ case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+ ctx->params.frame_rc_enable = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
+ ctx->params.mb_rc_enable = ctrl->val;
+ break;
case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET:
ctx->params.h264_chroma_qp_index_offset = ctrl->val;
break;
@@ -2181,6 +2328,10 @@ static void coda_encode_ctrls(struct coda_ctx *ctx)
V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION, 0, 1, 1,
0);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1);
+ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE, 0, 1, 1, 1);
+ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET, -12, 12, 1, 0);
v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_H264_PROFILE,
diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c
index 92234fd1f4fd..00d19859db50 100644
--- a/drivers/media/platform/coda/coda-jpeg.c
+++ b/drivers/media/platform/coda/coda-jpeg.c
@@ -15,6 +15,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-fh.h>
+#include <media/v4l2-jpeg.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-dma-contig.h>
@@ -23,10 +24,12 @@
#include "trace.h"
#define SOI_MARKER 0xffd8
+#define APP9_MARKER 0xffe9
#define DRI_MARKER 0xffdd
#define DQT_MARKER 0xffdb
#define DHT_MARKER 0xffc4
#define SOF_MARKER 0xffc0
+#define SOS_MARKER 0xffda
#define EOI_MARKER 0xffd9
enum {
@@ -37,6 +40,18 @@ enum {
CODA9_JPEG_FORMAT_400,
};
+struct coda_huff_tab {
+ u8 luma_dc[16 + 12];
+ u8 chroma_dc[16 + 12];
+ u8 luma_ac[16 + 162];
+ u8 chroma_ac[16 + 162];
+
+ /* DC Luma, DC Chroma, AC Luma, AC Chroma */
+ s16 min[4 * 16];
+ s16 max[4 * 16];
+ s8 ptr[4 * 16];
+};
+
#define CODA9_JPEG_ENC_HUFF_DATA_SIZE (256 + 256 + 16 + 16)
/*
@@ -247,6 +262,291 @@ bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
return false;
}
+static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num);
+
+int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb)
+{
+ struct coda_dev *dev = ctx->dev;
+ u8 *buf = vb2_plane_vaddr(vb, 0);
+ size_t len = vb2_get_plane_payload(vb, 0);
+ struct v4l2_jpeg_scan_header scan_header;
+ struct v4l2_jpeg_reference quantization_tables[4] = { };
+ struct v4l2_jpeg_reference huffman_tables[4] = { };
+ struct v4l2_jpeg_header header = {
+ .scan = &scan_header,
+ .quantization_tables = quantization_tables,
+ .huffman_tables = huffman_tables,
+ };
+ struct coda_q_data *q_data_src;
+ struct coda_huff_tab *huff_tab;
+ int i, j, ret;
+
+ ret = v4l2_jpeg_parse_header(buf, len, &header);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev, "failed to parse header\n");
+ return ret;
+ }
+
+ ctx->params.jpeg_restart_interval = header.restart_interval;
+
+ /* check frame header */
+ if (header.frame.height > ctx->codec->max_h ||
+ header.frame.width > ctx->codec->max_w) {
+ v4l2_err(&dev->v4l2_dev, "invalid dimensions: %dx%d\n",
+ header.frame.width, header.frame.height);
+ return -EINVAL;
+ }
+
+ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ if (header.frame.height != q_data_src->height ||
+ header.frame.width != q_data_src->width) {
+ v4l2_err(&dev->v4l2_dev,
+ "dimensions don't match format: %dx%d\n",
+ header.frame.width, header.frame.height);
+ return -EINVAL;
+ }
+
+ if (header.frame.num_components != 3) {
+ v4l2_err(&dev->v4l2_dev,
+ "unsupported number of components: %d\n",
+ header.frame.num_components);
+ return -EINVAL;
+ }
+
+ /* install quantization tables */
+ if (quantization_tables[3].start) {
+ v4l2_err(&dev->v4l2_dev,
+ "only 3 quantization tables supported\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < 3; i++) {
+ if (!quantization_tables[i].start)
+ continue;
+ if (quantization_tables[i].length != 64) {
+ v4l2_err(&dev->v4l2_dev,
+ "only 8-bit quantization tables supported\n");
+ continue;
+ }
+ if (!ctx->params.jpeg_qmat_tab[i])
+ ctx->params.jpeg_qmat_tab[i] = kmalloc(64, GFP_KERNEL);
+ memcpy(ctx->params.jpeg_qmat_tab[i],
+ quantization_tables[i].start, 64);
+ }
+
+ /* install Huffman tables */
+ for (i = 0; i < 4; i++) {
+ if (!huffman_tables[i].start) {
+ v4l2_err(&dev->v4l2_dev, "missing Huffman table\n");
+ return -EINVAL;
+ }
+ /* AC tables should be between 17 -> 178, DC between 17 -> 28 */
+ if (huffman_tables[i].length < 17 ||
+ huffman_tables[i].length > 178 ||
+ ((i & 2) == 0 && huffman_tables[i].length > 28)) {
+ v4l2_err(&dev->v4l2_dev,
+ "invalid Huffman table %d length: %zu\n",
+ i, huffman_tables[i].length);
+ return -EINVAL;
+ }
+ }
+ huff_tab = ctx->params.jpeg_huff_tab;
+ if (!huff_tab) {
+ huff_tab = kzalloc(sizeof(struct coda_huff_tab), GFP_KERNEL);
+ if (!huff_tab)
+ return -ENOMEM;
+ ctx->params.jpeg_huff_tab = huff_tab;
+ }
+
+ memset(huff_tab, 0, sizeof(*huff_tab));
+ memcpy(huff_tab->luma_dc, huffman_tables[0].start, huffman_tables[0].length);
+ memcpy(huff_tab->chroma_dc, huffman_tables[1].start, huffman_tables[1].length);
+ memcpy(huff_tab->luma_ac, huffman_tables[2].start, huffman_tables[2].length);
+ memcpy(huff_tab->chroma_ac, huffman_tables[3].start, huffman_tables[3].length);
+
+ /* check scan header */
+ for (i = 0; i < scan_header.num_components; i++) {
+ struct v4l2_jpeg_scan_component_spec *scan_component;
+
+ scan_component = &scan_header.component[i];
+ for (j = 0; j < header.frame.num_components; j++) {
+ if (header.frame.component[j].component_identifier ==
+ scan_component->component_selector)
+ break;
+ }
+ if (j == header.frame.num_components)
+ continue;
+
+ ctx->params.jpeg_huff_dc_index[j] =
+ scan_component->dc_entropy_coding_table_selector;
+ ctx->params.jpeg_huff_ac_index[j] =
+ scan_component->ac_entropy_coding_table_selector;
+ }
+
+ /* Generate Huffman table information */
+ for (i = 0; i < 4; i++)
+ coda9_jpeg_gen_dec_huff_tab(ctx, i);
+
+ /* start of entropy coded segment */
+ ctx->jpeg_ecs_offset = header.ecs_offset;
+
+ switch (header.frame.subsampling) {
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+ ctx->params.jpeg_chroma_subsampling = header.frame.subsampling;
+ break;
+ default:
+ v4l2_err(&dev->v4l2_dev, "chroma subsampling not supported: %d",
+ header.frame.subsampling);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline void coda9_jpeg_write_huff_values(struct coda_dev *dev, u8 *bits,
+ int num_values)
+{
+ s8 *values = (s8 *)(bits + 16);
+ int huff_length, i;
+
+ for (huff_length = 0, i = 0; i < 16; i++)
+ huff_length += bits[i];
+ for (i = huff_length; i < num_values; i++)
+ values[i] = -1;
+ for (i = 0; i < num_values; i++)
+ coda_write(dev, (s32)values[i], CODA9_REG_JPEG_HUFF_DATA);
+}
+
+static int coda9_jpeg_dec_huff_setup(struct coda_ctx *ctx)
+{
+ struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab;
+ struct coda_dev *dev = ctx->dev;
+ s16 *huff_min = huff_tab->min;
+ s16 *huff_max = huff_tab->max;
+ s8 *huff_ptr = huff_tab->ptr;
+ int i;
+
+ /* MIN Tables */
+ coda_write(dev, 0x003, CODA9_REG_JPEG_HUFF_CTRL);
+ coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_ADDR);
+ for (i = 0; i < 4 * 16; i++)
+ coda_write(dev, (s32)huff_min[i], CODA9_REG_JPEG_HUFF_DATA);
+
+ /* MAX Tables */
+ coda_write(dev, 0x403, CODA9_REG_JPEG_HUFF_CTRL);
+ coda_write(dev, 0x440, CODA9_REG_JPEG_HUFF_ADDR);
+ for (i = 0; i < 4 * 16; i++)
+ coda_write(dev, (s32)huff_max[i], CODA9_REG_JPEG_HUFF_DATA);
+
+ /* PTR Tables */
+ coda_write(dev, 0x803, CODA9_REG_JPEG_HUFF_CTRL);
+ coda_write(dev, 0x880, CODA9_REG_JPEG_HUFF_ADDR);
+ for (i = 0; i < 4 * 16; i++)
+ coda_write(dev, (s32)huff_ptr[i], CODA9_REG_JPEG_HUFF_DATA);
+
+ /* VAL Tables: DC Luma, DC Chroma, AC Luma, AC Chroma */
+ coda_write(dev, 0xc03, CODA9_REG_JPEG_HUFF_CTRL);
+ coda9_jpeg_write_huff_values(dev, huff_tab->luma_dc, 12);
+ coda9_jpeg_write_huff_values(dev, huff_tab->chroma_dc, 12);
+ coda9_jpeg_write_huff_values(dev, huff_tab->luma_ac, 162);
+ coda9_jpeg_write_huff_values(dev, huff_tab->chroma_ac, 162);
+ coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_CTRL);
+ return 0;
+}
+
+static inline void coda9_jpeg_write_qmat_tab(struct coda_dev *dev,
+ u8 *qmat, int index)
+{
+ int i;
+
+ coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL);
+ for (i = 0; i < 64; i++)
+ coda_write(dev, qmat[i], CODA9_REG_JPEG_QMAT_DATA);
+ coda_write(dev, 0, CODA9_REG_JPEG_QMAT_CTRL);
+}
+
+static void coda9_jpeg_qmat_setup(struct coda_ctx *ctx)
+{
+ struct coda_dev *dev = ctx->dev;
+ int *qmat_index = ctx->params.jpeg_qmat_index;
+ u8 **qmat_tab = ctx->params.jpeg_qmat_tab;
+
+ coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[0]], 0x00);
+ coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[1]], 0x40);
+ coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[2]], 0x80);
+}
+
+static void coda9_jpeg_dec_bbc_gbu_setup(struct coda_ctx *ctx,
+ struct vb2_buffer *buf, u32 ecs_offset)
+{
+ struct coda_dev *dev = ctx->dev;
+ int page_ptr, word_ptr, bit_ptr;
+ u32 bbc_base_addr, end_addr;
+ int bbc_cur_pos;
+ int ret, val;
+
+ bbc_base_addr = vb2_dma_contig_plane_dma_addr(buf, 0);
+ end_addr = bbc_base_addr + vb2_get_plane_payload(buf, 0);
+
+ page_ptr = ecs_offset / 256;
+ word_ptr = (ecs_offset % 256) / 4;
+ if (page_ptr & 1)
+ word_ptr += 64;
+ bit_ptr = (ecs_offset % 4) * 8;
+ if (word_ptr & 1)
+ bit_ptr += 32;
+ word_ptr &= ~0x1;
+
+ coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_WR_PTR);
+ coda_write(dev, bbc_base_addr, CODA9_REG_JPEG_BBC_BAS_ADDR);
+
+ /* Leave 3 256-byte page margin to avoid a BBC interrupt */
+ coda_write(dev, end_addr + 256 * 3 + 256, CODA9_REG_JPEG_BBC_END_ADDR);
+ val = DIV_ROUND_UP(vb2_plane_size(buf, 0), 256) + 3;
+ coda_write(dev, BIT(31) | val, CODA9_REG_JPEG_BBC_STRM_CTRL);
+
+ bbc_cur_pos = page_ptr;
+ coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
+ coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8),
+ CODA9_REG_JPEG_BBC_EXT_ADDR);
+ coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR);
+ coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
+ coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND);
+ do {
+ ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY);
+ } while (ret == 1);
+
+ bbc_cur_pos++;
+ coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
+ coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8),
+ CODA9_REG_JPEG_BBC_EXT_ADDR);
+ coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR);
+ coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
+ coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND);
+ do {
+ ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY);
+ } while (ret == 1);
+
+ bbc_cur_pos++;
+ coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
+ coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL);
+
+ coda_write(dev, 0, CODA9_REG_JPEG_GBU_TT_CNT);
+ coda_write(dev, word_ptr, CODA9_REG_JPEG_GBU_WD_PTR);
+ coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR);
+ coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER);
+ if (page_ptr & 1) {
+ coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBIR);
+ coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBHR);
+ } else {
+ coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR);
+ coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR);
+ }
+ coda_write(dev, 4, CODA9_REG_JPEG_GBU_CTRL);
+ coda_write(dev, bit_ptr, CODA9_REG_JPEG_GBU_FF_RPTR);
+ coda_write(dev, 3, CODA9_REG_JPEG_GBU_CTRL);
+}
+
static const int bus_req_num[] = {
[CODA9_JPEG_FORMAT_420] = 2,
[CODA9_JPEG_FORMAT_422] = 3,
@@ -345,6 +645,71 @@ out:
#define DC_TABLE_INDEX1 2
#define AC_TABLE_INDEX1 3
+static u8 *coda9_jpeg_get_huff_bits(struct coda_ctx *ctx, int tab_num)
+{
+ struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab;
+
+ if (!huff_tab)
+ return NULL;
+
+ switch (tab_num) {
+ case DC_TABLE_INDEX0: return huff_tab->luma_dc;
+ case AC_TABLE_INDEX0: return huff_tab->luma_ac;
+ case DC_TABLE_INDEX1: return huff_tab->chroma_dc;
+ case AC_TABLE_INDEX1: return huff_tab->chroma_ac;
+ }
+
+ return NULL;
+}
+
+static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num)
+{
+ int ptr_cnt = 0, huff_code = 0, zero_flag = 0, data_flag = 0;
+ u8 *huff_bits;
+ s16 *huff_max;
+ s16 *huff_min;
+ s8 *huff_ptr;
+ int ofs;
+ int i;
+
+ huff_bits = coda9_jpeg_get_huff_bits(ctx, tab_num);
+ if (!huff_bits)
+ return -EINVAL;
+
+ /* DC/AC Luma, DC/AC Chroma -> DC Luma/Chroma, AC Luma/Chroma */
+ ofs = ((tab_num & 1) << 1) | ((tab_num >> 1) & 1);
+ ofs *= 16;
+
+ huff_ptr = ctx->params.jpeg_huff_tab->ptr + ofs;
+ huff_max = ctx->params.jpeg_huff_tab->max + ofs;
+ huff_min = ctx->params.jpeg_huff_tab->min + ofs;
+
+ for (i = 0; i < 16; i++) {
+ if (huff_bits[i]) {
+ huff_ptr[i] = ptr_cnt;
+ ptr_cnt += huff_bits[i];
+ huff_min[i] = huff_code;
+ huff_max[i] = huff_code + (huff_bits[i] - 1);
+ data_flag = 1;
+ zero_flag = 0;
+ } else {
+ huff_ptr[i] = -1;
+ huff_min[i] = -1;
+ huff_max[i] = -1;
+ zero_flag = 1;
+ }
+
+ if (data_flag == 1) {
+ if (zero_flag == 1)
+ huff_code <<= 1;
+ else
+ huff_code = (huff_max[i] + 1) << 1;
+ }
+ }
+
+ return 0;
+}
+
static int coda9_jpeg_load_huff_tab(struct coda_ctx *ctx)
{
struct {
@@ -880,6 +1245,13 @@ static void coda9_jpeg_finish_encode(struct coda_ctx *ctx)
coda_dbg(1, ctx, "job finished: encoded frame (%u)%s\n",
dst_buf->sequence,
(dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
+
+ /*
+ * Reset JPEG processing unit after each encode run to work
+ * around hangups when switching context between encoder and
+ * decoder.
+ */
+ coda_hw_reset(ctx);
}
static void coda9_jpeg_release(struct coda_ctx *ctx)
@@ -893,6 +1265,7 @@ static void coda9_jpeg_release(struct coda_ctx *ctx)
for (i = 0; i < 3; i++)
kfree(ctx->params.jpeg_qmat_tab[i]);
kfree(ctx->params.jpeg_huff_data);
+ kfree(ctx->params.jpeg_huff_tab);
}
const struct coda_context_ops coda9_jpeg_encode_ops = {
@@ -903,6 +1276,210 @@ const struct coda_context_ops coda9_jpeg_encode_ops = {
.release = coda9_jpeg_release,
};
+/*
+ * Decoder context operations
+ */
+
+static int coda9_jpeg_start_decoding(struct coda_ctx *ctx)
+{
+ ctx->params.jpeg_qmat_index[0] = 0;
+ ctx->params.jpeg_qmat_index[1] = 1;
+ ctx->params.jpeg_qmat_index[2] = 1;
+ ctx->params.jpeg_qmat_tab[0] = luma_q;
+ ctx->params.jpeg_qmat_tab[1] = chroma_q;
+ /* nothing more to do here */
+
+ /* TODO: we could already scan the first header to get the chroma
+ * format.
+ */
+
+ return 0;
+}
+
+static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
+{
+ struct coda_dev *dev = ctx->dev;
+ int aligned_width, aligned_height;
+ int chroma_format;
+ int ret;
+ u32 val, dst_fourcc;
+ struct coda_q_data *q_data_src, *q_data_dst;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ int chroma_interleave;
+
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ dst_fourcc = q_data_dst->fourcc;
+
+ if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
+ vb2_set_plane_payload(&src_buf->vb2_buf, 0,
+ vb2_plane_size(&src_buf->vb2_buf, 0));
+
+ chroma_format = coda9_jpeg_chroma_format(q_data_dst->fourcc);
+ if (chroma_format < 0) {
+ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+ return chroma_format;
+ }
+
+ ret = coda_jpeg_decode_header(ctx, &src_buf->vb2_buf);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev, "failed to decode JPEG header: %d\n",
+ ret);
+
+ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
+
+ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+ return ret;
+ }
+
+ /* Round image dimensions to multiple of MCU size */
+ aligned_width = round_up(q_data_src->width, width_align[chroma_format]);
+ aligned_height = round_up(q_data_src->height, height_align[chroma_format]);
+ if (aligned_width != q_data_dst->bytesperline) {
+ v4l2_err(&dev->v4l2_dev, "stride mismatch: %d != %d\n",
+ aligned_width, q_data_dst->bytesperline);
+ }
+
+ coda_set_gdi_regs(ctx);
+
+ val = ctx->params.jpeg_huff_ac_index[0] << 12 |
+ ctx->params.jpeg_huff_ac_index[1] << 11 |
+ ctx->params.jpeg_huff_ac_index[2] << 10 |
+ ctx->params.jpeg_huff_dc_index[0] << 9 |
+ ctx->params.jpeg_huff_dc_index[1] << 8 |
+ ctx->params.jpeg_huff_dc_index[2] << 7;
+ if (ctx->params.jpeg_huff_tab)
+ val |= CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN;
+ coda_write(dev, val, CODA9_REG_JPEG_PIC_CTRL);
+
+ coda_write(dev, aligned_width << 16 | aligned_height,
+ CODA9_REG_JPEG_PIC_SIZE);
+
+ chroma_interleave = (dst_fourcc == V4L2_PIX_FMT_NV12);
+ coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
+ coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
+ coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
+ coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO);
+ coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
+ coda_write(dev, ctx->params.jpeg_restart_interval,
+ CODA9_REG_JPEG_RST_INTVAL);
+
+ if (ctx->params.jpeg_huff_tab) {
+ ret = coda9_jpeg_dec_huff_setup(ctx);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev,
+ "failed to set up Huffman tables: %d\n", ret);
+ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+ return ret;
+ }
+ }
+
+ coda9_jpeg_qmat_setup(ctx);
+
+ coda9_jpeg_dec_bbc_gbu_setup(ctx, &src_buf->vb2_buf,
+ ctx->jpeg_ecs_offset);
+
+ coda_write(dev, 0, CODA9_REG_JPEG_RST_INDEX);
+ coda_write(dev, 0, CODA9_REG_JPEG_RST_COUNT);
+
+ coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_Y);
+ coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CB);
+ coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CR);
+
+ coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
+
+ coda_write(dev, 1, CODA9_GDI_CONTROL);
+ do {
+ ret = coda_read(dev, CODA9_GDI_STATUS);
+ } while (!ret);
+
+ val = (chroma_format << 17) | (chroma_interleave << 16) |
+ q_data_dst->bytesperline;
+ if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
+ val |= 3 << 20;
+ coda_write(dev, val, CODA9_GDI_INFO_CONTROL);
+
+ coda_write(dev, aligned_width << 16 | aligned_height,
+ CODA9_GDI_INFO_PIC_SIZE);
+
+ coda_write_base(ctx, q_data_dst, dst_buf, CODA9_GDI_INFO_BASE_Y);
+
+ coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00);
+ coda_write(dev, 0, CODA9_GDI_CONTROL);
+ coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST);
+
+ trace_coda_jpeg_run(ctx, src_buf);
+
+ coda_write(dev, 1, CODA9_REG_JPEG_PIC_START);
+
+ return 0;
+}
+
+static void coda9_jpeg_finish_decode(struct coda_ctx *ctx)
+{
+ struct coda_dev *dev = ctx->dev;
+ struct vb2_v4l2_buffer *dst_buf, *src_buf;
+ struct coda_q_data *q_data_dst;
+ u32 err_mb;
+
+ err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
+ if (err_mb)
+ v4l2_err(&dev->v4l2_dev, "ERRMB: 0x%x\n", err_mb);
+
+ coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
+
+ /*
+ * Lock to make sure that a decoder stop command running in parallel
+ * will either already have marked src_buf as last, or it will wake up
+ * the capture queue after the buffers are returned.
+ */
+ mutex_lock(&ctx->wakeup_mutex);
+ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ dst_buf->sequence = ctx->osequence++;
+
+ trace_coda_jpeg_done(ctx, dst_buf);
+
+ dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST);
+ dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
+ dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST;
+
+ v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
+
+ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, q_data_dst->sizeimage);
+
+ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+ coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR :
+ VB2_BUF_STATE_DONE);
+
+ mutex_unlock(&ctx->wakeup_mutex);
+
+ coda_dbg(1, ctx, "job finished: decoded frame (%u)%s\n",
+ dst_buf->sequence,
+ (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
+
+ /*
+ * Reset JPEG processing unit after each decode run to work
+ * around hangups when switching context between encoder and
+ * decoder.
+ */
+ coda_hw_reset(ctx);
+}
+
+const struct coda_context_ops coda9_jpeg_decode_ops = {
+ .queue_init = coda_encoder_queue_init, /* non-bitstream operation */
+ .start_streaming = coda9_jpeg_start_decoding,
+ .prepare_run = coda9_jpeg_prepare_decode,
+ .finish_run = coda9_jpeg_finish_decode,
+ .release = coda9_jpeg_release,
+};
+
irqreturn_t coda9_jpeg_irq_handler(int irq, void *data)
{
struct coda_dev *dev = data;
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 43bda175f517..b81f3aca9209 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -69,7 +69,7 @@ struct coda_aux_buf {
struct coda_dev {
struct v4l2_device v4l2_dev;
- struct video_device vfd[5];
+ struct video_device vfd[6];
struct device *dev;
const struct coda_devtype *devtype;
int firmware;
@@ -123,10 +123,15 @@ struct coda_params {
u8 mpeg4_inter_qp;
u8 gop_size;
int intra_refresh;
+ enum v4l2_jpeg_chroma_subsampling jpeg_chroma_subsampling;
u8 jpeg_quality;
u8 jpeg_restart_interval;
u8 *jpeg_qmat_tab[3];
+ int jpeg_qmat_index[3];
+ int jpeg_huff_dc_index[3];
+ int jpeg_huff_ac_index[3];
u32 *jpeg_huff_data;
+ struct coda_huff_tab *jpeg_huff_tab;
int codec_mode;
int codec_mode_aux;
enum v4l2_mpeg_video_multi_slice_mode slice_mode;
@@ -143,6 +148,8 @@ struct coda_params {
bool h264_intra_qp_changed;
bool intra_refresh_changed;
bool slice_mode_changed;
+ bool frame_rc_enable;
+ bool mb_rc_enable;
};
struct coda_buffer_meta {
@@ -238,6 +245,7 @@ struct coda_ctx {
struct v4l2_fh fh;
int gopcounter;
int runcounter;
+ int jpeg_ecs_offset;
char vpu_header[3][64];
int vpu_header_size[3];
struct kfifo bitstream_fifo;
@@ -362,12 +370,14 @@ void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc,
u8 level_idc);
bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
+int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb);
int coda_jpeg_write_tables(struct coda_ctx *ctx);
void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality);
extern const struct coda_context_ops coda_bit_encode_ops;
extern const struct coda_context_ops coda_bit_decode_ops;
extern const struct coda_context_ops coda9_jpeg_encode_ops;
+extern const struct coda_context_ops coda9_jpeg_decode_ops;
irqreturn_t coda_irq_handler(int irq, void *data);
irqreturn_t coda9_jpeg_irq_handler(int irq, void *data);
diff --git a/drivers/media/platform/cros-ec-cec/Makefile b/drivers/media/platform/cros-ec-cec/Makefile
deleted file mode 100644
index 2615cdc6e227..000000000000
--- a/drivers/media/platform/cros-ec-cec/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o
diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
deleted file mode 100644
index 0e7e2772f08f..000000000000
--- a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
+++ /dev/null
@@ -1,359 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * CEC driver for ChromeOS Embedded Controller
- *
- * Copyright (c) 2018 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/dmi.h>
-#include <linux/pci.h>
-#include <linux/cec.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/platform_data/cros_ec_commands.h>
-#include <linux/platform_data/cros_ec_proto.h>
-#include <media/cec.h>
-#include <media/cec-notifier.h>
-
-#define DRV_NAME "cros-ec-cec"
-
-/**
- * struct cros_ec_cec - Driver data for EC CEC
- *
- * @cros_ec: Pointer to EC device
- * @notifier: Notifier info for responding to EC events
- * @adap: CEC adapter
- * @notify: CEC notifier pointer
- * @rx_msg: storage for a received message
- */
-struct cros_ec_cec {
- struct cros_ec_device *cros_ec;
- struct notifier_block notifier;
- struct cec_adapter *adap;
- struct cec_notifier *notify;
- struct cec_msg rx_msg;
-};
-
-static void handle_cec_message(struct cros_ec_cec *cros_ec_cec)
-{
- struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
- uint8_t *cec_message = cros_ec->event_data.data.cec_message;
- unsigned int len = cros_ec->event_size;
-
- cros_ec_cec->rx_msg.len = len;
- memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);
-
- cec_received_msg(cros_ec_cec->adap, &cros_ec_cec->rx_msg);
-}
-
-static void handle_cec_event(struct cros_ec_cec *cros_ec_cec)
-{
- struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
- uint32_t events = cros_ec->event_data.data.cec_events;
-
- if (events & EC_MKBP_CEC_SEND_OK)
- cec_transmit_attempt_done(cros_ec_cec->adap,
- CEC_TX_STATUS_OK);
-
- /* FW takes care of all retries, tell core to avoid more retries */
- if (events & EC_MKBP_CEC_SEND_FAILED)
- cec_transmit_attempt_done(cros_ec_cec->adap,
- CEC_TX_STATUS_MAX_RETRIES |
- CEC_TX_STATUS_NACK);
-}
-
-static int cros_ec_cec_event(struct notifier_block *nb,
- unsigned long queued_during_suspend,
- void *_notify)
-{
- struct cros_ec_cec *cros_ec_cec;
- struct cros_ec_device *cros_ec;
-
- cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier);
- cros_ec = cros_ec_cec->cros_ec;
-
- if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_EVENT) {
- handle_cec_event(cros_ec_cec);
- return NOTIFY_OK;
- }
-
- if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) {
- handle_cec_message(cros_ec_cec);
- return NOTIFY_OK;
- }
-
- return NOTIFY_DONE;
-}
-
-static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
-{
- struct cros_ec_cec *cros_ec_cec = adap->priv;
- struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
- struct {
- struct cros_ec_command msg;
- struct ec_params_cec_set data;
- } __packed msg = {};
- int ret;
-
- msg.msg.command = EC_CMD_CEC_SET;
- msg.msg.outsize = sizeof(msg.data);
- msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS;
- msg.data.val = logical_addr;
-
- ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
- if (ret < 0) {
- dev_err(cros_ec->dev,
- "error setting CEC logical address on EC: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts,
- u32 signal_free_time, struct cec_msg *cec_msg)
-{
- struct cros_ec_cec *cros_ec_cec = adap->priv;
- struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
- struct {
- struct cros_ec_command msg;
- struct ec_params_cec_write data;
- } __packed msg = {};
- int ret;
-
- msg.msg.command = EC_CMD_CEC_WRITE_MSG;
- msg.msg.outsize = cec_msg->len;
- memcpy(msg.data.msg, cec_msg->msg, cec_msg->len);
-
- ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
- if (ret < 0) {
- dev_err(cros_ec->dev,
- "error writing CEC msg on EC: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable)
-{
- struct cros_ec_cec *cros_ec_cec = adap->priv;
- struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
- struct {
- struct cros_ec_command msg;
- struct ec_params_cec_set data;
- } __packed msg = {};
- int ret;
-
- msg.msg.command = EC_CMD_CEC_SET;
- msg.msg.outsize = sizeof(msg.data);
- msg.data.cmd = CEC_CMD_ENABLE;
- msg.data.val = enable;
-
- ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
- if (ret < 0) {
- dev_err(cros_ec->dev,
- "error %sabling CEC on EC: %d\n",
- (enable ? "en" : "dis"), ret);
- return ret;
- }
-
- return 0;
-}
-
-static const struct cec_adap_ops cros_ec_cec_ops = {
- .adap_enable = cros_ec_cec_adap_enable,
- .adap_log_addr = cros_ec_cec_set_log_addr,
- .adap_transmit = cros_ec_cec_transmit,
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int cros_ec_cec_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
-
- if (device_may_wakeup(dev))
- enable_irq_wake(cros_ec_cec->cros_ec->irq);
-
- return 0;
-}
-
-static int cros_ec_cec_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
-
- if (device_may_wakeup(dev))
- disable_irq_wake(cros_ec_cec->cros_ec->irq);
-
- return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops,
- cros_ec_cec_suspend, cros_ec_cec_resume);
-
-#if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI)
-
-/*
- * The Firmware only handles a single CEC interface tied to a single HDMI
- * connector we specify along with the DRM device name handling the HDMI output
- */
-
-struct cec_dmi_match {
- const char *sys_vendor;
- const char *product_name;
- const char *devname;
- const char *conn;
-};
-
-static const struct cec_dmi_match cec_dmi_match_table[] = {
- /* Google Fizz */
- { "Google", "Fizz", "0000:00:02.0", "Port B" },
-};
-
-static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev,
- const char **conn)
-{
- int i;
-
- for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) {
- const struct cec_dmi_match *m = &cec_dmi_match_table[i];
-
- if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) &&
- dmi_match(DMI_PRODUCT_NAME, m->product_name)) {
- struct device *d;
-
- /* Find the device, bail out if not yet registered */
- d = bus_find_device_by_name(&pci_bus_type, NULL,
- m->devname);
- if (!d)
- return ERR_PTR(-EPROBE_DEFER);
- put_device(d);
- *conn = m->conn;
- return d;
- }
- }
-
- /* Hardware support must be added in the cec_dmi_match_table */
- dev_warn(dev, "CEC notifier not configured for this hardware\n");
-
- return ERR_PTR(-ENODEV);
-}
-
-#else
-
-static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev,
- const char **conn)
-{
- return ERR_PTR(-ENODEV);
-}
-
-#endif
-
-static int cros_ec_cec_probe(struct platform_device *pdev)
-{
- struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
- struct cros_ec_device *cros_ec = ec_dev->ec_dev;
- struct cros_ec_cec *cros_ec_cec;
- struct device *hdmi_dev;
- const char *conn = NULL;
- int ret;
-
- hdmi_dev = cros_ec_cec_find_hdmi_dev(&pdev->dev, &conn);
- if (IS_ERR(hdmi_dev))
- return PTR_ERR(hdmi_dev);
-
- cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec),
- GFP_KERNEL);
- if (!cros_ec_cec)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, cros_ec_cec);
- cros_ec_cec->cros_ec = cros_ec;
-
- ret = device_init_wakeup(&pdev->dev, 1);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize wakeup\n");
- return ret;
- }
-
- cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec,
- DRV_NAME,
- CEC_CAP_DEFAULTS |
- CEC_CAP_CONNECTOR_INFO, 1);
- if (IS_ERR(cros_ec_cec->adap))
- return PTR_ERR(cros_ec_cec->adap);
-
- cros_ec_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, conn,
- cros_ec_cec->adap);
- if (!cros_ec_cec->notify) {
- ret = -ENOMEM;
- goto out_probe_adapter;
- }
-
- /* Get CEC events from the EC. */
- cros_ec_cec->notifier.notifier_call = cros_ec_cec_event;
- ret = blocking_notifier_chain_register(&cros_ec->event_notifier,
- &cros_ec_cec->notifier);
- if (ret) {
- dev_err(&pdev->dev, "failed to register notifier\n");
- goto out_probe_notify;
- }
-
- ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev);
- if (ret < 0)
- goto out_probe_notify;
-
- return 0;
-
-out_probe_notify:
- cec_notifier_cec_adap_unregister(cros_ec_cec->notify,
- cros_ec_cec->adap);
-out_probe_adapter:
- cec_delete_adapter(cros_ec_cec->adap);
- return ret;
-}
-
-static int 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;
-
- ret = blocking_notifier_chain_unregister(
- &cros_ec_cec->cros_ec->event_notifier,
- &cros_ec_cec->notifier);
-
- 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,
- .driver = {
- .name = DRV_NAME,
- .pm = &cros_ec_cec_pm_ops,
- },
-};
-
-module_platform_driver(cros_ec_cec_driver);
-
-MODULE_DESCRIPTION("CEC driver for ChromeOS ECs");
-MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index ead14c49d4f5..7d55fd45240e 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -1225,7 +1225,6 @@ static int vpif_probe_complete(void)
probe_out:
for (k = 0; k < j; k++) {
ch = vpif_obj.dev[k];
- common = &ch->common[k];
video_unregister_device(&ch->video_dev);
}
return err;
diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig
index be4effcbfe7b..136d3b2a0fbb 100644
--- a/drivers/media/platform/exynos4-is/Kconfig
+++ b/drivers/media/platform/exynos4-is/Kconfig
@@ -2,9 +2,10 @@
config VIDEO_SAMSUNG_EXYNOS4_IS
tristate "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver"
- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on VIDEO_V4L2 && OF && COMMON_CLK
depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
- depends on OF && COMMON_CLK
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
Say Y here to enable camera host interface devices for
diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c
index 37fdcc53a1c4..9a09a10a3631 100644
--- a/drivers/media/platform/marvell-ccic/cafe-driver.c
+++ b/drivers/media/platform/marvell-ccic/cafe-driver.c
@@ -556,7 +556,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
clkdev_create(mcam->mclk, "xclk", "%d-%04x",
i2c_adapter_id(cam->i2c_adapter), ov7670_info.addr);
- if (i2c_new_device(cam->i2c_adapter, &ov7670_info)) {
+ if (!IS_ERR(i2c_new_client_device(cam->i2c_adapter, &ov7670_info))) {
cam->registered = 1;
return 0;
}
diff --git a/drivers/media/platform/meson/Makefile b/drivers/media/platform/meson/Makefile
deleted file mode 100644
index 6bf728addbf8..000000000000
--- a/drivers/media/platform/meson/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_MESON_AO_CEC) += ao-cec.o
-obj-$(CONFIG_VIDEO_MESON_G12A_AO_CEC) += ao-cec-g12a.o
diff --git a/drivers/media/platform/meson/ao-cec-g12a.c b/drivers/media/platform/meson/ao-cec-g12a.c
deleted file mode 100644
index 891533060d49..000000000000
--- a/drivers/media/platform/meson/ao-cec-g12a.c
+++ /dev/null
@@ -1,796 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Amlogic Meson AO CEC G12A Controller
- *
- * Copyright (C) 2017 Amlogic, Inc. All rights reserved
- * Copyright (C) 2019 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- */
-
-#include <linux/bitfield.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/reset.h>
-#include <linux/slab.h>
-#include <linux/regmap.h>
-#include <media/cec.h>
-#include <media/cec-notifier.h>
-#include <linux/clk-provider.h>
-
-/* CEC Registers */
-
-#define CECB_CLK_CNTL_REG0 0x00
-
-#define CECB_CLK_CNTL_N1 GENMASK(11, 0)
-#define CECB_CLK_CNTL_N2 GENMASK(23, 12)
-#define CECB_CLK_CNTL_DUAL_EN BIT(28)
-#define CECB_CLK_CNTL_OUTPUT_EN BIT(30)
-#define CECB_CLK_CNTL_INPUT_EN BIT(31)
-
-#define CECB_CLK_CNTL_REG1 0x04
-
-#define CECB_CLK_CNTL_M1 GENMASK(11, 0)
-#define CECB_CLK_CNTL_M2 GENMASK(23, 12)
-#define CECB_CLK_CNTL_BYPASS_EN BIT(24)
-
-/*
- * [14:12] Filter_del. For glitch-filtering CEC line, ignore signal
- * change pulse width < filter_del * T(filter_tick) * 3.
- * [9:8] Filter_tick_sel: Select which periodical pulse for
- * glitch-filtering CEC line signal.
- * - 0=Use T(xtal)*3 = 125ns;
- * - 1=Use once-per-1us pulse;
- * - 2=Use once-per-10us pulse;
- * - 3=Use once-per-100us pulse.
- * [3] Sysclk_en. 0=Disable system clock; 1=Enable system clock.
- * [2:1] cntl_clk
- * - 0 = Disable clk (Power-off mode)
- * - 1 = Enable gated clock (Normal mode)
- * - 2 = Enable free-run clk (Debug mode)
- * [0] SW_RESET 1=Apply reset; 0=No reset.
- */
-#define CECB_GEN_CNTL_REG 0x08
-
-#define CECB_GEN_CNTL_RESET BIT(0)
-#define CECB_GEN_CNTL_CLK_DISABLE 0
-#define CECB_GEN_CNTL_CLK_ENABLE 1
-#define CECB_GEN_CNTL_CLK_ENABLE_DBG 2
-#define CECB_GEN_CNTL_CLK_CTRL_MASK GENMASK(2, 1)
-#define CECB_GEN_CNTL_SYS_CLK_EN BIT(3)
-#define CECB_GEN_CNTL_FILTER_TICK_125NS 0
-#define CECB_GEN_CNTL_FILTER_TICK_1US 1
-#define CECB_GEN_CNTL_FILTER_TICK_10US 2
-#define CECB_GEN_CNTL_FILTER_TICK_100US 3
-#define CECB_GEN_CNTL_FILTER_TICK_SEL GENMASK(9, 8)
-#define CECB_GEN_CNTL_FILTER_DEL GENMASK(14, 12)
-
-/*
- * [7:0] cec_reg_addr
- * [15:8] cec_reg_wrdata
- * [16] cec_reg_wr
- * - 0 = Read
- * - 1 = Write
- * [31:24] cec_reg_rddata
- */
-#define CECB_RW_REG 0x0c
-
-#define CECB_RW_ADDR GENMASK(7, 0)
-#define CECB_RW_WR_DATA GENMASK(15, 8)
-#define CECB_RW_WRITE_EN BIT(16)
-#define CECB_RW_BUS_BUSY BIT(23)
-#define CECB_RW_RD_DATA GENMASK(31, 24)
-
-/*
- * [0] DONE Interrupt
- * [1] End Of Message Interrupt
- * [2] Not Acknowlegde Interrupt
- * [3] Arbitration Loss Interrupt
- * [4] Initiator Error Interrupt
- * [5] Follower Error Interrupt
- * [6] Wake-Up Interrupt
- */
-#define CECB_INTR_MASKN_REG 0x10
-#define CECB_INTR_CLR_REG 0x14
-#define CECB_INTR_STAT_REG 0x18
-
-#define CECB_INTR_DONE BIT(0)
-#define CECB_INTR_EOM BIT(1)
-#define CECB_INTR_NACK BIT(2)
-#define CECB_INTR_ARB_LOSS BIT(3)
-#define CECB_INTR_INITIATOR_ERR BIT(4)
-#define CECB_INTR_FOLLOWER_ERR BIT(5)
-#define CECB_INTR_WAKE_UP BIT(6)
-
-/* CEC Commands */
-
-#define CECB_CTRL 0x00
-
-#define CECB_CTRL_SEND BIT(0)
-#define CECB_CTRL_TYPE GENMASK(2, 1)
-#define CECB_CTRL_TYPE_RETRY 0
-#define CECB_CTRL_TYPE_NEW 1
-#define CECB_CTRL_TYPE_NEXT 2
-
-#define CECB_CTRL2 0x01
-
-#define CECB_CTRL2_RISE_DEL_MAX GENMASK(4, 0)
-
-#define CECB_INTR_MASK 0x02
-#define CECB_LADD_LOW 0x05
-#define CECB_LADD_HIGH 0x06
-#define CECB_TX_CNT 0x07
-#define CECB_RX_CNT 0x08
-#define CECB_STAT0 0x09
-#define CECB_TX_DATA00 0x10
-#define CECB_TX_DATA01 0x11
-#define CECB_TX_DATA02 0x12
-#define CECB_TX_DATA03 0x13
-#define CECB_TX_DATA04 0x14
-#define CECB_TX_DATA05 0x15
-#define CECB_TX_DATA06 0x16
-#define CECB_TX_DATA07 0x17
-#define CECB_TX_DATA08 0x18
-#define CECB_TX_DATA09 0x19
-#define CECB_TX_DATA10 0x1A
-#define CECB_TX_DATA11 0x1B
-#define CECB_TX_DATA12 0x1C
-#define CECB_TX_DATA13 0x1D
-#define CECB_TX_DATA14 0x1E
-#define CECB_TX_DATA15 0x1F
-#define CECB_RX_DATA00 0x20
-#define CECB_RX_DATA01 0x21
-#define CECB_RX_DATA02 0x22
-#define CECB_RX_DATA03 0x23
-#define CECB_RX_DATA04 0x24
-#define CECB_RX_DATA05 0x25
-#define CECB_RX_DATA06 0x26
-#define CECB_RX_DATA07 0x27
-#define CECB_RX_DATA08 0x28
-#define CECB_RX_DATA09 0x29
-#define CECB_RX_DATA10 0x2A
-#define CECB_RX_DATA11 0x2B
-#define CECB_RX_DATA12 0x2C
-#define CECB_RX_DATA13 0x2D
-#define CECB_RX_DATA14 0x2E
-#define CECB_RX_DATA15 0x2F
-#define CECB_LOCK_BUF 0x30
-
-#define CECB_LOCK_BUF_EN BIT(0)
-
-#define CECB_WAKEUPCTRL 0x31
-
-struct meson_ao_cec_g12a_data {
- /* Setup the internal CECB_CTRL2 register */
- bool ctrl2_setup;
-};
-
-struct meson_ao_cec_g12a_device {
- struct platform_device *pdev;
- struct regmap *regmap;
- struct regmap *regmap_cec;
- spinlock_t cec_reg_lock;
- struct cec_notifier *notify;
- struct cec_adapter *adap;
- struct cec_msg rx_msg;
- struct clk *oscin;
- struct clk *core;
- const struct meson_ao_cec_g12a_data *data;
-};
-
-static const struct regmap_config meson_ao_cec_g12a_regmap_conf = {
- .reg_bits = 8,
- .val_bits = 32,
- .reg_stride = 4,
- .max_register = CECB_INTR_STAT_REG,
-};
-
-/*
- * The AO-CECB embeds a dual/divider to generate a more precise
- * 32,768KHz clock for CEC core clock.
- * ______ ______
- * | | | |
- * ______ | Div1 |-| Cnt1 | ______
- * | | /|______| |______|\ | |
- * Xtal-->| Gate |---| ______ ______ X-X--| Gate |-->
- * |______| | \| | | |/ | |______|
- * | | Div2 |-| Cnt2 | |
- * | |______| |______| |
- * |_______________________|
- *
- * The dividing can be switched to single or dual, with a counter
- * for each divider to set when the switching is done.
- * The entire dividing mechanism can be also bypassed.
- */
-
-struct meson_ao_cec_g12a_dualdiv_clk {
- struct clk_hw hw;
- struct regmap *regmap;
-};
-
-#define hw_to_meson_ao_cec_g12a_dualdiv_clk(_hw) \
- container_of(_hw, struct meson_ao_cec_g12a_dualdiv_clk, hw) \
-
-static unsigned long
-meson_ao_cec_g12a_dualdiv_clk_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
- hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
- unsigned long n1;
- u32 reg0, reg1;
-
- regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &reg0);
- regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &reg1);
-
- if (reg1 & CECB_CLK_CNTL_BYPASS_EN)
- return parent_rate;
-
- if (reg0 & CECB_CLK_CNTL_DUAL_EN) {
- unsigned long n2, m1, m2, f1, f2, p1, p2;
-
- n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1;
- n2 = FIELD_GET(CECB_CLK_CNTL_N2, reg0) + 1;
-
- m1 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1;
- m2 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1;
-
- f1 = DIV_ROUND_CLOSEST(parent_rate, n1);
- f2 = DIV_ROUND_CLOSEST(parent_rate, n2);
-
- p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2));
- p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2));
-
- return DIV_ROUND_UP(100000000, p1 + p2);
- }
-
- n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1;
-
- return DIV_ROUND_CLOSEST(parent_rate, n1);
-}
-
-static int meson_ao_cec_g12a_dualdiv_clk_enable(struct clk_hw *hw)
-{
- struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
- hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
-
-
- /* Disable Input & Output */
- regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
- CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
- 0);
-
- /* Set N1 & N2 */
- regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
- CECB_CLK_CNTL_N1,
- FIELD_PREP(CECB_CLK_CNTL_N1, 733 - 1));
-
- regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
- CECB_CLK_CNTL_N2,
- FIELD_PREP(CECB_CLK_CNTL_N2, 732 - 1));
-
- /* Set M1 & M2 */
- regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
- CECB_CLK_CNTL_M1,
- FIELD_PREP(CECB_CLK_CNTL_M1, 8 - 1));
-
- regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
- CECB_CLK_CNTL_M2,
- FIELD_PREP(CECB_CLK_CNTL_M2, 11 - 1));
-
- /* Enable Dual divisor */
- regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
- CECB_CLK_CNTL_DUAL_EN, CECB_CLK_CNTL_DUAL_EN);
-
- /* Disable divisor bypass */
- regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1,
- CECB_CLK_CNTL_BYPASS_EN, 0);
-
- /* Enable Input & Output */
- regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
- CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
- CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN);
-
- return 0;
-}
-
-static void meson_ao_cec_g12a_dualdiv_clk_disable(struct clk_hw *hw)
-{
- struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
- hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
-
- regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0,
- CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN,
- 0);
-}
-
-static int meson_ao_cec_g12a_dualdiv_clk_is_enabled(struct clk_hw *hw)
-{
- struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk =
- hw_to_meson_ao_cec_g12a_dualdiv_clk(hw);
- int val;
-
- regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &val);
-
- return !!(val & (CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN));
-}
-
-static const struct clk_ops meson_ao_cec_g12a_dualdiv_clk_ops = {
- .recalc_rate = meson_ao_cec_g12a_dualdiv_clk_recalc_rate,
- .is_enabled = meson_ao_cec_g12a_dualdiv_clk_is_enabled,
- .enable = meson_ao_cec_g12a_dualdiv_clk_enable,
- .disable = meson_ao_cec_g12a_dualdiv_clk_disable,
-};
-
-static int meson_ao_cec_g12a_setup_clk(struct meson_ao_cec_g12a_device *ao_cec)
-{
- struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk;
- struct device *dev = &ao_cec->pdev->dev;
- struct clk_init_data init;
- const char *parent_name;
- struct clk *clk;
- char *name;
-
- dualdiv_clk = devm_kzalloc(dev, sizeof(*dualdiv_clk), GFP_KERNEL);
- if (!dualdiv_clk)
- return -ENOMEM;
-
- name = kasprintf(GFP_KERNEL, "%s#dualdiv_clk", dev_name(dev));
- if (!name)
- return -ENOMEM;
-
- parent_name = __clk_get_name(ao_cec->oscin);
-
- init.name = name;
- init.ops = &meson_ao_cec_g12a_dualdiv_clk_ops;
- init.flags = 0;
- init.parent_names = &parent_name;
- init.num_parents = 1;
- dualdiv_clk->regmap = ao_cec->regmap;
- dualdiv_clk->hw.init = &init;
-
- clk = devm_clk_register(dev, &dualdiv_clk->hw);
- kfree(name);
- if (IS_ERR(clk)) {
- dev_err(dev, "failed to register clock\n");
- return PTR_ERR(clk);
- }
-
- ao_cec->core = clk;
-
- return 0;
-}
-
-static int meson_ao_cec_g12a_read(void *context, unsigned int addr,
- unsigned int *data)
-{
- struct meson_ao_cec_g12a_device *ao_cec = context;
- u32 reg = FIELD_PREP(CECB_RW_ADDR, addr);
- int ret = 0;
-
- ret = regmap_write(ao_cec->regmap, CECB_RW_REG, reg);
- if (ret)
- return ret;
-
- ret = regmap_read_poll_timeout(ao_cec->regmap, CECB_RW_REG, reg,
- !(reg & CECB_RW_BUS_BUSY),
- 5, 1000);
- if (ret)
- return ret;
-
- ret = regmap_read(ao_cec->regmap, CECB_RW_REG, &reg);
-
- *data = FIELD_GET(CECB_RW_RD_DATA, reg);
-
- return ret;
-}
-
-static int meson_ao_cec_g12a_write(void *context, unsigned int addr,
- unsigned int data)
-{
- struct meson_ao_cec_g12a_device *ao_cec = context;
- u32 reg = FIELD_PREP(CECB_RW_ADDR, addr) |
- FIELD_PREP(CECB_RW_WR_DATA, data) |
- CECB_RW_WRITE_EN;
-
- return regmap_write(ao_cec->regmap, CECB_RW_REG, reg);
-}
-
-static const struct regmap_config meson_ao_cec_g12a_cec_regmap_conf = {
- .reg_bits = 8,
- .val_bits = 8,
- .reg_read = meson_ao_cec_g12a_read,
- .reg_write = meson_ao_cec_g12a_write,
- .max_register = 0xffff,
-};
-
-static inline void
-meson_ao_cec_g12a_irq_setup(struct meson_ao_cec_g12a_device *ao_cec,
- bool enable)
-{
- u32 cfg = CECB_INTR_DONE | CECB_INTR_EOM | CECB_INTR_NACK |
- CECB_INTR_ARB_LOSS | CECB_INTR_INITIATOR_ERR |
- CECB_INTR_FOLLOWER_ERR;
-
- regmap_write(ao_cec->regmap, CECB_INTR_MASKN_REG,
- enable ? cfg : 0);
-}
-
-static void meson_ao_cec_g12a_irq_rx(struct meson_ao_cec_g12a_device *ao_cec)
-{
- int i, ret = 0;
- u32 val;
-
- ret = regmap_read(ao_cec->regmap_cec, CECB_RX_CNT, &val);
-
- ao_cec->rx_msg.len = val;
- if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
- ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;
-
- for (i = 0; i < ao_cec->rx_msg.len; i++) {
- ret |= regmap_read(ao_cec->regmap_cec,
- CECB_RX_DATA00 + i, &val);
-
- ao_cec->rx_msg.msg[i] = val & 0xff;
- }
-
- ret |= regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0);
- if (ret)
- return;
-
- cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);
-}
-
-static irqreturn_t meson_ao_cec_g12a_irq(int irq, void *data)
-{
- struct meson_ao_cec_g12a_device *ao_cec = data;
- u32 stat;
-
- regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat);
- if (stat)
- return IRQ_WAKE_THREAD;
-
- return IRQ_NONE;
-}
-
-static irqreturn_t meson_ao_cec_g12a_irq_thread(int irq, void *data)
-{
- struct meson_ao_cec_g12a_device *ao_cec = data;
- u32 stat;
-
- regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat);
- regmap_write(ao_cec->regmap, CECB_INTR_CLR_REG, stat);
-
- if (stat & CECB_INTR_DONE)
- cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_OK);
-
- if (stat & CECB_INTR_EOM)
- meson_ao_cec_g12a_irq_rx(ao_cec);
-
- if (stat & CECB_INTR_NACK)
- cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_NACK);
-
- if (stat & CECB_INTR_ARB_LOSS) {
- regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, 0);
- regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL,
- CECB_CTRL_SEND | CECB_CTRL_TYPE, 0);
- cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ARB_LOST);
- }
-
- /* Initiator reports an error on the CEC bus */
- if (stat & CECB_INTR_INITIATOR_ERR)
- cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR);
-
- /* Follower reports a receive error, just reset RX buffer */
- if (stat & CECB_INTR_FOLLOWER_ERR)
- regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0);
-
- return IRQ_HANDLED;
-}
-
-static int
-meson_ao_cec_g12a_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
-{
- struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
- int ret = 0;
-
- if (logical_addr == CEC_LOG_ADDR_INVALID) {
- /* Assume this will allways succeed */
- regmap_write(ao_cec->regmap_cec, CECB_LADD_LOW, 0);
- regmap_write(ao_cec->regmap_cec, CECB_LADD_HIGH, 0);
-
- return 0;
- } else if (logical_addr < 8) {
- ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_LOW,
- BIT(logical_addr),
- BIT(logical_addr));
- } else {
- ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH,
- BIT(logical_addr - 8),
- BIT(logical_addr - 8));
- }
-
- /* Always set Broadcast/Unregistered 15 address */
- ret |= regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH,
- BIT(CEC_LOG_ADDR_UNREGISTERED - 8),
- BIT(CEC_LOG_ADDR_UNREGISTERED - 8));
-
- return ret ? -EIO : 0;
-}
-
-static int meson_ao_cec_g12a_transmit(struct cec_adapter *adap, u8 attempts,
- u32 signal_free_time, struct cec_msg *msg)
-{
- struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
- unsigned int type;
- int ret = 0;
- u32 val;
- int i;
-
- /* Check if RX is in progress */
- ret = regmap_read(ao_cec->regmap_cec, CECB_LOCK_BUF, &val);
- if (ret)
- return ret;
- if (val & CECB_LOCK_BUF_EN)
- return -EBUSY;
-
- /* Check if TX Busy */
- ret = regmap_read(ao_cec->regmap_cec, CECB_CTRL, &val);
- if (ret)
- return ret;
- if (val & CECB_CTRL_SEND)
- return -EBUSY;
-
- switch (signal_free_time) {
- case CEC_SIGNAL_FREE_TIME_RETRY:
- type = CECB_CTRL_TYPE_RETRY;
- break;
- case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
- type = CECB_CTRL_TYPE_NEXT;
- break;
- case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
- default:
- type = CECB_CTRL_TYPE_NEW;
- break;
- }
-
- for (i = 0; i < msg->len; i++)
- ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_DATA00 + i,
- msg->msg[i]);
-
- ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, msg->len);
- if (ret)
- return -EIO;
-
- ret = regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL,
- CECB_CTRL_SEND |
- CECB_CTRL_TYPE,
- CECB_CTRL_SEND |
- FIELD_PREP(CECB_CTRL_TYPE, type));
-
- return ret;
-}
-
-static int meson_ao_cec_g12a_adap_enable(struct cec_adapter *adap, bool enable)
-{
- struct meson_ao_cec_g12a_device *ao_cec = adap->priv;
-
- meson_ao_cec_g12a_irq_setup(ao_cec, false);
-
- regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
- CECB_GEN_CNTL_RESET, CECB_GEN_CNTL_RESET);
-
- if (!enable)
- return 0;
-
- /* Setup Filter */
- regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
- CECB_GEN_CNTL_FILTER_TICK_SEL |
- CECB_GEN_CNTL_FILTER_DEL,
- FIELD_PREP(CECB_GEN_CNTL_FILTER_TICK_SEL,
- CECB_GEN_CNTL_FILTER_TICK_1US) |
- FIELD_PREP(CECB_GEN_CNTL_FILTER_DEL, 7));
-
- /* Enable System Clock */
- regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
- CECB_GEN_CNTL_SYS_CLK_EN,
- CECB_GEN_CNTL_SYS_CLK_EN);
-
- /* Enable gated clock (Normal mode). */
- regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
- CECB_GEN_CNTL_CLK_CTRL_MASK,
- FIELD_PREP(CECB_GEN_CNTL_CLK_CTRL_MASK,
- CECB_GEN_CNTL_CLK_ENABLE));
-
- /* Release Reset */
- regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG,
- CECB_GEN_CNTL_RESET, 0);
-
- if (ao_cec->data->ctrl2_setup)
- regmap_write(ao_cec->regmap_cec, CECB_CTRL2,
- FIELD_PREP(CECB_CTRL2_RISE_DEL_MAX, 2));
-
- meson_ao_cec_g12a_irq_setup(ao_cec, true);
-
- return 0;
-}
-
-static const struct cec_adap_ops meson_ao_cec_g12a_ops = {
- .adap_enable = meson_ao_cec_g12a_adap_enable,
- .adap_log_addr = meson_ao_cec_g12a_set_log_addr,
- .adap_transmit = meson_ao_cec_g12a_transmit,
-};
-
-static int meson_ao_cec_g12a_probe(struct platform_device *pdev)
-{
- struct meson_ao_cec_g12a_device *ao_cec;
- struct device *hdmi_dev;
- struct resource *res;
- void __iomem *base;
- int ret, irq;
-
- hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
- if (IS_ERR(hdmi_dev))
- return PTR_ERR(hdmi_dev);
-
- ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
- if (!ao_cec)
- return -ENOMEM;
-
- ao_cec->data = of_device_get_match_data(&pdev->dev);
- if (!ao_cec->data) {
- dev_err(&pdev->dev, "failed to get match data\n");
- return -ENODEV;
- }
-
- spin_lock_init(&ao_cec->cec_reg_lock);
- ao_cec->pdev = pdev;
-
- ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_g12a_ops, ao_cec,
- "meson_g12a_ao_cec",
- CEC_CAP_DEFAULTS |
- CEC_CAP_CONNECTOR_INFO,
- CEC_MAX_LOG_ADDRS);
- if (IS_ERR(ao_cec->adap))
- return PTR_ERR(ao_cec->adap);
-
- ao_cec->adap->owner = THIS_MODULE;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(base)) {
- ret = PTR_ERR(base);
- goto out_probe_adapter;
- }
-
- ao_cec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
- &meson_ao_cec_g12a_regmap_conf);
- if (IS_ERR(ao_cec->regmap)) {
- ret = PTR_ERR(ao_cec->regmap);
- goto out_probe_adapter;
- }
-
- ao_cec->regmap_cec = devm_regmap_init(&pdev->dev, NULL, ao_cec,
- &meson_ao_cec_g12a_cec_regmap_conf);
- if (IS_ERR(ao_cec->regmap_cec)) {
- ret = PTR_ERR(ao_cec->regmap_cec);
- goto out_probe_adapter;
- }
-
- irq = platform_get_irq(pdev, 0);
- ret = devm_request_threaded_irq(&pdev->dev, irq,
- meson_ao_cec_g12a_irq,
- meson_ao_cec_g12a_irq_thread,
- 0, NULL, ao_cec);
- if (ret) {
- dev_err(&pdev->dev, "irq request failed\n");
- goto out_probe_adapter;
- }
-
- ao_cec->oscin = devm_clk_get(&pdev->dev, "oscin");
- if (IS_ERR(ao_cec->oscin)) {
- dev_err(&pdev->dev, "oscin clock request failed\n");
- ret = PTR_ERR(ao_cec->oscin);
- goto out_probe_adapter;
- }
-
- ret = meson_ao_cec_g12a_setup_clk(ao_cec);
- if (ret)
- goto out_probe_adapter;
-
- ret = clk_prepare_enable(ao_cec->core);
- if (ret) {
- dev_err(&pdev->dev, "core clock enable failed\n");
- goto out_probe_adapter;
- }
-
- device_reset_optional(&pdev->dev);
-
- platform_set_drvdata(pdev, ao_cec);
-
- ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
- ao_cec->adap);
- if (!ao_cec->notify) {
- ret = -ENOMEM;
- goto out_probe_core_clk;
- }
-
- ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
- if (ret < 0)
- goto out_probe_notify;
-
- /* Setup Hardware */
- regmap_write(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET);
-
- return 0;
-
-out_probe_notify:
- cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
-
-out_probe_core_clk:
- clk_disable_unprepare(ao_cec->core);
-
-out_probe_adapter:
- cec_delete_adapter(ao_cec->adap);
-
- dev_err(&pdev->dev, "CEC controller registration failed\n");
-
- return ret;
-}
-
-static int meson_ao_cec_g12a_remove(struct platform_device *pdev)
-{
- struct meson_ao_cec_g12a_device *ao_cec = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(ao_cec->core);
-
- 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 = {
- .ctrl2_setup = false,
-};
-
-static const struct meson_ao_cec_g12a_data ao_cec_sm1_data = {
- .ctrl2_setup = true,
-};
-
-static const struct of_device_id meson_ao_cec_g12a_of_match[] = {
- {
- .compatible = "amlogic,meson-g12a-ao-cec",
- .data = &ao_cec_g12a_data,
- },
- {
- .compatible = "amlogic,meson-sm1-ao-cec",
- .data = &ao_cec_sm1_data,
- },
- { /* sentinel */ }
-};
-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,
- .driver = {
- .name = "meson-ao-cec-g12a",
- .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
- },
-};
-
-module_platform_driver(meson_ao_cec_g12a_driver);
-
-MODULE_DESCRIPTION("Meson AO CEC G12A Controller driver");
-MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/meson/ao-cec.c b/drivers/media/platform/meson/ao-cec.c
deleted file mode 100644
index 09aff82c3773..000000000000
--- a/drivers/media/platform/meson/ao-cec.c
+++ /dev/null
@@ -1,732 +0,0 @@
-/*
- * Driver for Amlogic Meson AO CEC Controller
- *
- * Copyright (C) 2015 Amlogic, Inc. All rights reserved
- * Copyright (C) 2017 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <linux/bitfield.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/reset.h>
-#include <media/cec.h>
-#include <media/cec-notifier.h>
-
-/* CEC Registers */
-
-/*
- * [2:1] cntl_clk
- * - 0 = Disable clk (Power-off mode)
- * - 1 = Enable gated clock (Normal mode)
- * - 2 = Enable free-run clk (Debug mode)
- */
-#define CEC_GEN_CNTL_REG 0x00
-
-#define CEC_GEN_CNTL_RESET BIT(0)
-#define CEC_GEN_CNTL_CLK_DISABLE 0
-#define CEC_GEN_CNTL_CLK_ENABLE 1
-#define CEC_GEN_CNTL_CLK_ENABLE_DBG 2
-#define CEC_GEN_CNTL_CLK_CTRL_MASK GENMASK(2, 1)
-
-/*
- * [7:0] cec_reg_addr
- * [15:8] cec_reg_wrdata
- * [16] cec_reg_wr
- * - 0 = Read
- * - 1 = Write
- * [23] bus free
- * [31:24] cec_reg_rddata
- */
-#define CEC_RW_REG 0x04
-
-#define CEC_RW_ADDR GENMASK(7, 0)
-#define CEC_RW_WR_DATA GENMASK(15, 8)
-#define CEC_RW_WRITE_EN BIT(16)
-#define CEC_RW_BUS_BUSY BIT(23)
-#define CEC_RW_RD_DATA GENMASK(31, 24)
-
-/*
- * [1] tx intr
- * [2] rx intr
- */
-#define CEC_INTR_MASKN_REG 0x08
-#define CEC_INTR_CLR_REG 0x0c
-#define CEC_INTR_STAT_REG 0x10
-
-#define CEC_INTR_TX BIT(1)
-#define CEC_INTR_RX BIT(2)
-
-/* CEC Commands */
-
-#define CEC_TX_MSG_0_HEADER 0x00
-#define CEC_TX_MSG_1_OPCODE 0x01
-#define CEC_TX_MSG_2_OP1 0x02
-#define CEC_TX_MSG_3_OP2 0x03
-#define CEC_TX_MSG_4_OP3 0x04
-#define CEC_TX_MSG_5_OP4 0x05
-#define CEC_TX_MSG_6_OP5 0x06
-#define CEC_TX_MSG_7_OP6 0x07
-#define CEC_TX_MSG_8_OP7 0x08
-#define CEC_TX_MSG_9_OP8 0x09
-#define CEC_TX_MSG_A_OP9 0x0A
-#define CEC_TX_MSG_B_OP10 0x0B
-#define CEC_TX_MSG_C_OP11 0x0C
-#define CEC_TX_MSG_D_OP12 0x0D
-#define CEC_TX_MSG_E_OP13 0x0E
-#define CEC_TX_MSG_F_OP14 0x0F
-#define CEC_TX_MSG_LENGTH 0x10
-#define CEC_TX_MSG_CMD 0x11
-#define CEC_TX_WRITE_BUF 0x12
-#define CEC_TX_CLEAR_BUF 0x13
-#define CEC_RX_MSG_CMD 0x14
-#define CEC_RX_CLEAR_BUF 0x15
-#define CEC_LOGICAL_ADDR0 0x16
-#define CEC_LOGICAL_ADDR1 0x17
-#define CEC_LOGICAL_ADDR2 0x18
-#define CEC_LOGICAL_ADDR3 0x19
-#define CEC_LOGICAL_ADDR4 0x1A
-#define CEC_CLOCK_DIV_H 0x1B
-#define CEC_CLOCK_DIV_L 0x1C
-#define CEC_QUIESCENT_25MS_BIT7_0 0x20
-#define CEC_QUIESCENT_25MS_BIT11_8 0x21
-#define CEC_STARTBITMINL2H_3MS5_BIT7_0 0x22
-#define CEC_STARTBITMINL2H_3MS5_BIT8 0x23
-#define CEC_STARTBITMAXL2H_3MS9_BIT7_0 0x24
-#define CEC_STARTBITMAXL2H_3MS9_BIT8 0x25
-#define CEC_STARTBITMINH_0MS6_BIT7_0 0x26
-#define CEC_STARTBITMINH_0MS6_BIT8 0x27
-#define CEC_STARTBITMAXH_1MS0_BIT7_0 0x28
-#define CEC_STARTBITMAXH_1MS0_BIT8 0x29
-#define CEC_STARTBITMINTOT_4MS3_BIT7_0 0x2A
-#define CEC_STARTBITMINTOT_4MS3_BIT9_8 0x2B
-#define CEC_STARTBITMAXTOT_4MS7_BIT7_0 0x2C
-#define CEC_STARTBITMAXTOT_4MS7_BIT9_8 0x2D
-#define CEC_LOGIC1MINL2H_0MS4_BIT7_0 0x2E
-#define CEC_LOGIC1MINL2H_0MS4_BIT8 0x2F
-#define CEC_LOGIC1MAXL2H_0MS8_BIT7_0 0x30
-#define CEC_LOGIC1MAXL2H_0MS8_BIT8 0x31
-#define CEC_LOGIC0MINL2H_1MS3_BIT7_0 0x32
-#define CEC_LOGIC0MINL2H_1MS3_BIT8 0x33
-#define CEC_LOGIC0MAXL2H_1MS7_BIT7_0 0x34
-#define CEC_LOGIC0MAXL2H_1MS7_BIT8 0x35
-#define CEC_LOGICMINTOTAL_2MS05_BIT7_0 0x36
-#define CEC_LOGICMINTOTAL_2MS05_BIT9_8 0x37
-#define CEC_LOGICMAXHIGH_2MS8_BIT7_0 0x38
-#define CEC_LOGICMAXHIGH_2MS8_BIT8 0x39
-#define CEC_LOGICERRLOW_3MS4_BIT7_0 0x3A
-#define CEC_LOGICERRLOW_3MS4_BIT8 0x3B
-#define CEC_NOMSMPPOINT_1MS05 0x3C
-#define CEC_DELCNTR_LOGICERR 0x3E
-#define CEC_TXTIME_17MS_BIT7_0 0x40
-#define CEC_TXTIME_17MS_BIT10_8 0x41
-#define CEC_TXTIME_2BIT_BIT7_0 0x42
-#define CEC_TXTIME_2BIT_BIT10_8 0x43
-#define CEC_TXTIME_4BIT_BIT7_0 0x44
-#define CEC_TXTIME_4BIT_BIT10_8 0x45
-#define CEC_STARTBITNOML2H_3MS7_BIT7_0 0x46
-#define CEC_STARTBITNOML2H_3MS7_BIT8 0x47
-#define CEC_STARTBITNOMH_0MS8_BIT7_0 0x48
-#define CEC_STARTBITNOMH_0MS8_BIT8 0x49
-#define CEC_LOGIC1NOML2H_0MS6_BIT7_0 0x4A
-#define CEC_LOGIC1NOML2H_0MS6_BIT8 0x4B
-#define CEC_LOGIC0NOML2H_1MS5_BIT7_0 0x4C
-#define CEC_LOGIC0NOML2H_1MS5_BIT8 0x4D
-#define CEC_LOGIC1NOMH_1MS8_BIT7_0 0x4E
-#define CEC_LOGIC1NOMH_1MS8_BIT8 0x4F
-#define CEC_LOGIC0NOMH_0MS9_BIT7_0 0x50
-#define CEC_LOGIC0NOMH_0MS9_BIT8 0x51
-#define CEC_LOGICERRLOW_3MS6_BIT7_0 0x52
-#define CEC_LOGICERRLOW_3MS6_BIT8 0x53
-#define CEC_CHKCONTENTION_0MS1 0x54
-#define CEC_PREPARENXTBIT_0MS05_BIT7_0 0x56
-#define CEC_PREPARENXTBIT_0MS05_BIT8 0x57
-#define CEC_NOMSMPACKPOINT_0MS45 0x58
-#define CEC_ACK0NOML2H_1MS5_BIT7_0 0x5A
-#define CEC_ACK0NOML2H_1MS5_BIT8 0x5B
-#define CEC_BUGFIX_DISABLE_0 0x60
-#define CEC_BUGFIX_DISABLE_1 0x61
-#define CEC_RX_MSG_0_HEADER 0x80
-#define CEC_RX_MSG_1_OPCODE 0x81
-#define CEC_RX_MSG_2_OP1 0x82
-#define CEC_RX_MSG_3_OP2 0x83
-#define CEC_RX_MSG_4_OP3 0x84
-#define CEC_RX_MSG_5_OP4 0x85
-#define CEC_RX_MSG_6_OP5 0x86
-#define CEC_RX_MSG_7_OP6 0x87
-#define CEC_RX_MSG_8_OP7 0x88
-#define CEC_RX_MSG_9_OP8 0x89
-#define CEC_RX_MSG_A_OP9 0x8A
-#define CEC_RX_MSG_B_OP10 0x8B
-#define CEC_RX_MSG_C_OP11 0x8C
-#define CEC_RX_MSG_D_OP12 0x8D
-#define CEC_RX_MSG_E_OP13 0x8E
-#define CEC_RX_MSG_F_OP14 0x8F
-#define CEC_RX_MSG_LENGTH 0x90
-#define CEC_RX_MSG_STATUS 0x91
-#define CEC_RX_NUM_MSG 0x92
-#define CEC_TX_MSG_STATUS 0x93
-#define CEC_TX_NUM_MSG 0x94
-
-
-/* CEC_TX_MSG_CMD definition */
-#define TX_NO_OP 0 /* No transaction */
-#define TX_REQ_CURRENT 1 /* Transmit earliest message in buffer */
-#define TX_ABORT 2 /* Abort transmitting earliest message */
-#define TX_REQ_NEXT 3 /* Overwrite earliest msg, transmit next */
-
-/* tx_msg_status definition */
-#define TX_IDLE 0 /* No transaction */
-#define TX_BUSY 1 /* Transmitter is busy */
-#define TX_DONE 2 /* Message successfully transmitted */
-#define TX_ERROR 3 /* Message transmitted with error */
-
-/* rx_msg_cmd */
-#define RX_NO_OP 0 /* No transaction */
-#define RX_ACK_CURRENT 1 /* Read earliest message in buffer */
-#define RX_DISABLE 2 /* Disable receiving latest message */
-#define RX_ACK_NEXT 3 /* Clear earliest msg, read next */
-
-/* rx_msg_status */
-#define RX_IDLE 0 /* No transaction */
-#define RX_BUSY 1 /* Receiver is busy */
-#define RX_DONE 2 /* Message has been received successfully */
-#define RX_ERROR 3 /* Message has been received with error */
-
-/* RX_CLEAR_BUF options */
-#define CLEAR_START 1
-#define CLEAR_STOP 0
-
-/* CEC_LOGICAL_ADDRx options */
-#define LOGICAL_ADDR_MASK 0xf
-#define LOGICAL_ADDR_VALID BIT(4)
-#define LOGICAL_ADDR_DISABLE 0
-
-#define CEC_CLK_RATE 32768
-
-struct meson_ao_cec_device {
- struct platform_device *pdev;
- void __iomem *base;
- struct clk *core;
- spinlock_t cec_reg_lock;
- struct cec_notifier *notify;
- struct cec_adapter *adap;
- struct cec_msg rx_msg;
-};
-
-#define writel_bits_relaxed(mask, val, addr) \
- writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr)
-
-static inline int meson_ao_cec_wait_busy(struct meson_ao_cec_device *ao_cec)
-{
- ktime_t timeout = ktime_add_us(ktime_get(), 5000);
-
- while (readl_relaxed(ao_cec->base + CEC_RW_REG) & CEC_RW_BUS_BUSY) {
- if (ktime_compare(ktime_get(), timeout) > 0)
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-static void meson_ao_cec_read(struct meson_ao_cec_device *ao_cec,
- unsigned long address, u8 *data,
- int *res)
-{
- unsigned long flags;
- u32 reg = FIELD_PREP(CEC_RW_ADDR, address);
- int ret = 0;
-
- if (res && *res)
- return;
-
- spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
-
- ret = meson_ao_cec_wait_busy(ao_cec);
- if (ret)
- goto read_out;
-
- writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
-
- ret = meson_ao_cec_wait_busy(ao_cec);
- if (ret)
- goto read_out;
-
- *data = FIELD_GET(CEC_RW_RD_DATA,
- readl_relaxed(ao_cec->base + CEC_RW_REG));
-
-read_out:
- spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
-
- if (res)
- *res = ret;
-}
-
-static void meson_ao_cec_write(struct meson_ao_cec_device *ao_cec,
- unsigned long address, u8 data,
- int *res)
-{
- unsigned long flags;
- u32 reg = FIELD_PREP(CEC_RW_ADDR, address) |
- FIELD_PREP(CEC_RW_WR_DATA, data) |
- CEC_RW_WRITE_EN;
- int ret = 0;
-
- if (res && *res)
- return;
-
- spin_lock_irqsave(&ao_cec->cec_reg_lock, flags);
-
- ret = meson_ao_cec_wait_busy(ao_cec);
- if (ret)
- goto write_out;
-
- writel_relaxed(reg, ao_cec->base + CEC_RW_REG);
-
-write_out:
- spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags);
-
- if (res)
- *res = ret;
-}
-
-static inline void meson_ao_cec_irq_setup(struct meson_ao_cec_device *ao_cec,
- bool enable)
-{
- u32 cfg = CEC_INTR_TX | CEC_INTR_RX;
-
- writel_bits_relaxed(cfg, enable ? cfg : 0,
- ao_cec->base + CEC_INTR_MASKN_REG);
-}
-
-static inline int meson_ao_cec_clear(struct meson_ao_cec_device *ao_cec)
-{
- int ret = 0;
-
- meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_DISABLE, &ret);
- meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT, &ret);
- meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 1, &ret);
- meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 1, &ret);
- if (ret)
- return ret;
-
- udelay(100);
-
- meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, 0, &ret);
- meson_ao_cec_write(ao_cec, CEC_TX_CLEAR_BUF, 0, &ret);
- if (ret)
- return ret;
-
- udelay(100);
-
- meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP, &ret);
- meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP, &ret);
-
- return ret;
-}
-
-static int meson_ao_cec_arbit_bit_time_set(struct meson_ao_cec_device *ao_cec,
- unsigned int bit_set,
- unsigned int time_set)
-{
- int ret = 0;
-
- switch (bit_set) {
- case CEC_SIGNAL_FREE_TIME_RETRY:
- meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT7_0,
- time_set & 0xff, &ret);
- meson_ao_cec_write(ao_cec, CEC_TXTIME_4BIT_BIT10_8,
- (time_set >> 8) & 0x7, &ret);
- break;
-
- case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
- meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT7_0,
- time_set & 0xff, &ret);
- meson_ao_cec_write(ao_cec, CEC_TXTIME_2BIT_BIT10_8,
- (time_set >> 8) & 0x7, &ret);
- break;
-
- case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
- meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT7_0,
- time_set & 0xff, &ret);
- meson_ao_cec_write(ao_cec, CEC_TXTIME_17MS_BIT10_8,
- (time_set >> 8) & 0x7, &ret);
- break;
- }
-
- return ret;
-}
-
-static irqreturn_t meson_ao_cec_irq(int irq, void *data)
-{
- struct meson_ao_cec_device *ao_cec = data;
- u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
-
- if (stat)
- return IRQ_WAKE_THREAD;
-
- return IRQ_NONE;
-}
-
-static void meson_ao_cec_irq_tx(struct meson_ao_cec_device *ao_cec)
-{
- unsigned long tx_status = 0;
- u8 stat;
- int ret = 0;
-
- meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS, &stat, &ret);
- if (ret)
- goto tx_reg_err;
-
- switch (stat) {
- case TX_DONE:
- tx_status = CEC_TX_STATUS_OK;
- break;
-
- case TX_BUSY:
- tx_status = CEC_TX_STATUS_ARB_LOST;
- break;
-
- case TX_IDLE:
- tx_status = CEC_TX_STATUS_LOW_DRIVE;
- break;
-
- case TX_ERROR:
- default:
- tx_status = CEC_TX_STATUS_NACK;
- break;
- }
-
- /* Clear Interruption */
- writel_relaxed(CEC_INTR_TX, ao_cec->base + CEC_INTR_CLR_REG);
-
- /* Stop TX */
- meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP, &ret);
- if (ret)
- goto tx_reg_err;
-
- cec_transmit_attempt_done(ao_cec->adap, tx_status);
- return;
-
-tx_reg_err:
- cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR);
-}
-
-static void meson_ao_cec_irq_rx(struct meson_ao_cec_device *ao_cec)
-{
- int i, ret = 0;
- u8 reg;
-
- meson_ao_cec_read(ao_cec, CEC_RX_MSG_STATUS, &reg, &ret);
- if (reg != RX_DONE)
- goto rx_out;
-
- meson_ao_cec_read(ao_cec, CEC_RX_NUM_MSG, &reg, &ret);
- if (reg != 1)
- goto rx_out;
-
- meson_ao_cec_read(ao_cec, CEC_RX_MSG_LENGTH, &reg, &ret);
-
- ao_cec->rx_msg.len = reg + 1;
- if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
- ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;
-
- for (i = 0; i < ao_cec->rx_msg.len; i++) {
- u8 byte;
-
- meson_ao_cec_read(ao_cec, CEC_RX_MSG_0_HEADER + i, &byte, &ret);
-
- ao_cec->rx_msg.msg[i] = byte;
- }
-
- if (ret)
- goto rx_out;
-
- cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);
-
-rx_out:
- /* Clear Interruption */
- writel_relaxed(CEC_INTR_RX, ao_cec->base + CEC_INTR_CLR_REG);
-
- /* Ack RX message */
- meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_ACK_CURRENT, &ret);
- meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP, &ret);
-
- /* Clear RX buffer */
- meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_START, &ret);
- meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_STOP, &ret);
-}
-
-static irqreturn_t meson_ao_cec_irq_thread(int irq, void *data)
-{
- struct meson_ao_cec_device *ao_cec = data;
- u32 stat = readl_relaxed(ao_cec->base + CEC_INTR_STAT_REG);
-
- if (stat & CEC_INTR_TX)
- meson_ao_cec_irq_tx(ao_cec);
-
- meson_ao_cec_irq_rx(ao_cec);
-
- return IRQ_HANDLED;
-}
-
-static int meson_ao_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
-{
- struct meson_ao_cec_device *ao_cec = adap->priv;
- int ret = 0;
-
- meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
- LOGICAL_ADDR_DISABLE, &ret);
- if (ret)
- return ret;
-
- ret = meson_ao_cec_clear(ao_cec);
- if (ret)
- return ret;
-
- if (logical_addr == CEC_LOG_ADDR_INVALID)
- return 0;
-
- meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
- logical_addr & LOGICAL_ADDR_MASK, &ret);
- if (ret)
- return ret;
-
- udelay(100);
-
- meson_ao_cec_write(ao_cec, CEC_LOGICAL_ADDR0,
- (logical_addr & LOGICAL_ADDR_MASK) |
- LOGICAL_ADDR_VALID, &ret);
-
- return ret;
-}
-
-static int meson_ao_cec_transmit(struct cec_adapter *adap, u8 attempts,
- u32 signal_free_time, struct cec_msg *msg)
-{
- struct meson_ao_cec_device *ao_cec = adap->priv;
- int i, ret = 0;
- u8 reg;
-
- meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS, &reg, &ret);
- if (ret)
- return ret;
-
- if (reg == TX_BUSY) {
- dev_dbg(&ao_cec->pdev->dev, "%s: busy TX: aborting\n",
- __func__);
- meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT, &ret);
- }
-
- for (i = 0; i < msg->len; i++) {
- meson_ao_cec_write(ao_cec, CEC_TX_MSG_0_HEADER + i,
- msg->msg[i], &ret);
- }
-
- meson_ao_cec_write(ao_cec, CEC_TX_MSG_LENGTH, msg->len - 1, &ret);
- meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_REQ_CURRENT, &ret);
-
- return ret;
-}
-
-static int meson_ao_cec_adap_enable(struct cec_adapter *adap, bool enable)
-{
- struct meson_ao_cec_device *ao_cec = adap->priv;
- int ret;
-
- meson_ao_cec_irq_setup(ao_cec, false);
-
- writel_bits_relaxed(CEC_GEN_CNTL_RESET, CEC_GEN_CNTL_RESET,
- ao_cec->base + CEC_GEN_CNTL_REG);
-
- if (!enable)
- return 0;
-
- /* Enable gated clock (Normal mode). */
- writel_bits_relaxed(CEC_GEN_CNTL_CLK_CTRL_MASK,
- FIELD_PREP(CEC_GEN_CNTL_CLK_CTRL_MASK,
- CEC_GEN_CNTL_CLK_ENABLE),
- ao_cec->base + CEC_GEN_CNTL_REG);
-
- udelay(100);
-
- /* Release Reset */
- writel_bits_relaxed(CEC_GEN_CNTL_RESET, 0,
- ao_cec->base + CEC_GEN_CNTL_REG);
-
- /* Clear buffers */
- ret = meson_ao_cec_clear(ao_cec);
- if (ret)
- return ret;
-
- /* CEC arbitration 3/5/7 bit time set. */
- ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
- CEC_SIGNAL_FREE_TIME_RETRY,
- 0x118);
- if (ret)
- return ret;
- ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
- CEC_SIGNAL_FREE_TIME_NEW_INITIATOR,
- 0x000);
- if (ret)
- return ret;
- ret = meson_ao_cec_arbit_bit_time_set(ao_cec,
- CEC_SIGNAL_FREE_TIME_NEXT_XFER,
- 0x2aa);
- if (ret)
- return ret;
-
- meson_ao_cec_irq_setup(ao_cec, true);
-
- return 0;
-}
-
-static const struct cec_adap_ops meson_ao_cec_ops = {
- .adap_enable = meson_ao_cec_adap_enable,
- .adap_log_addr = meson_ao_cec_set_log_addr,
- .adap_transmit = meson_ao_cec_transmit,
-};
-
-static int meson_ao_cec_probe(struct platform_device *pdev)
-{
- struct meson_ao_cec_device *ao_cec;
- struct device *hdmi_dev;
- struct resource *res;
- int ret, irq;
-
- hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
-
- if (IS_ERR(hdmi_dev))
- return PTR_ERR(hdmi_dev);
-
- ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL);
- if (!ao_cec)
- return -ENOMEM;
-
- spin_lock_init(&ao_cec->cec_reg_lock);
-
- ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
- "meson_ao_cec",
- CEC_CAP_DEFAULTS |
- CEC_CAP_CONNECTOR_INFO,
- 1); /* Use 1 for now */
- if (IS_ERR(ao_cec->adap))
- return PTR_ERR(ao_cec->adap);
-
- ao_cec->adap->owner = THIS_MODULE;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ao_cec->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(ao_cec->base)) {
- ret = PTR_ERR(ao_cec->base);
- goto out_probe_adapter;
- }
-
- irq = platform_get_irq(pdev, 0);
- ret = devm_request_threaded_irq(&pdev->dev, irq,
- meson_ao_cec_irq,
- meson_ao_cec_irq_thread,
- 0, NULL, ao_cec);
- if (ret) {
- dev_err(&pdev->dev, "irq request failed\n");
- goto out_probe_adapter;
- }
-
- ao_cec->core = devm_clk_get(&pdev->dev, "core");
- if (IS_ERR(ao_cec->core)) {
- dev_err(&pdev->dev, "core clock request failed\n");
- ret = PTR_ERR(ao_cec->core);
- goto out_probe_adapter;
- }
-
- ret = clk_prepare_enable(ao_cec->core);
- if (ret) {
- dev_err(&pdev->dev, "core clock enable failed\n");
- goto out_probe_adapter;
- }
-
- ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE);
- if (ret) {
- dev_err(&pdev->dev, "core clock set rate failed\n");
- goto out_probe_clk;
- }
-
- device_reset_optional(&pdev->dev);
-
- ao_cec->pdev = pdev;
- platform_set_drvdata(pdev, ao_cec);
-
- ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
- ao_cec->adap);
- if (!ao_cec->notify) {
- ret = -ENOMEM;
- goto out_probe_clk;
- }
-
- ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
- if (ret < 0)
- goto out_probe_notify;
-
- /* Setup Hardware */
- writel_relaxed(CEC_GEN_CNTL_RESET,
- ao_cec->base + CEC_GEN_CNTL_REG);
-
- return 0;
-
-out_probe_notify:
- cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
-
-out_probe_clk:
- clk_disable_unprepare(ao_cec->core);
-
-out_probe_adapter:
- cec_delete_adapter(ao_cec->adap);
-
- dev_err(&pdev->dev, "CEC controller registration failed\n");
-
- return ret;
-}
-
-static int meson_ao_cec_remove(struct platform_device *pdev)
-{
- struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(ao_cec->core);
-
- 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[] = {
- { .compatible = "amlogic,meson-gx-ao-cec", },
- { /* sentinel */ }
-};
-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,
- .driver = {
- .name = "meson-ao-cec",
- .of_match_table = of_match_ptr(meson_ao_cec_of_match),
- },
-};
-
-module_platform_driver(meson_ao_cec_driver);
-
-MODULE_DESCRIPTION("Meson AO CEC Controller driver");
-MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
index 14991685adb7..58abfbdfb82d 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
@@ -15,10 +15,10 @@
static const char * const mtk_mdp_comp_stem[MTK_MDP_COMP_TYPE_MAX] = {
- "mdp_rdma",
- "mdp_rsz",
- "mdp_wdma",
- "mdp_wrot",
+ "mdp-rdma",
+ "mdp-rsz",
+ "mdp-wdma",
+ "mdp-wrot",
};
struct mtk_mdp_comp_match {
diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c
index 70c85a2a10f5..3c5fe737d36f 100644
--- a/drivers/media/platform/pxa_camera.c
+++ b/drivers/media/platform/pxa_camera.c
@@ -1016,7 +1016,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
* - a videobuffer is queued on the pcdev->capture list
*
* Please check the "DMA hot chaining timeslice issue" in
- * Documentation/media/v4l-drivers/pxa_camera.rst
+ * Documentation/driver-api/media/drivers/pxa_camera.rst
*
* Context: should only be called within the dma irq handler
*/
@@ -1438,7 +1438,7 @@ static void pxac_vb2_queue(struct vb2_buffer *vb)
/*
* Please check the DMA prepared buffer structure in :
- * Documentation/media/v4l-drivers/pxa_camera.rst
+ * Documentation/driver-api/media/drivers/pxa_camera.rst
* Please check also in pxa_camera_check_link_miss() to understand why DMA chain
* modification while DMA chain is running will work anyway.
*/
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 194b10b98767..203c6538044f 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -210,6 +210,8 @@ static int venus_probe(struct platform_device *pdev)
if (!core->res)
return -ENODEV;
+ mutex_init(&core->pm_lock);
+
core->pm_ops = venus_pm_get(core->res->hfi_version);
if (!core->pm_ops)
return -ENODEV;
@@ -242,10 +244,6 @@ static int venus_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = icc_set_bw(core->cpucfg_path, 0, kbps_to_icc(1000));
- if (ret)
- return ret;
-
ret = hfi_create(core, &venus_core_ops);
if (ret)
return ret;
@@ -320,7 +318,6 @@ static int venus_remove(struct platform_device *pdev)
ret = hfi_core_deinit(core, true);
WARN_ON(ret);
- hfi_destroy(core);
venus_shutdown(core);
of_platform_depopulate(dev);
@@ -332,10 +329,14 @@ static int venus_remove(struct platform_device *pdev)
if (pm_ops->core_put)
pm_ops->core_put(dev);
+ hfi_destroy(core);
+
icc_put(core->video_path);
icc_put(core->cpucfg_path);
v4l2_device_unregister(&core->v4l2_dev);
+ mutex_destroy(&core->pm_lock);
+ mutex_destroy(&core->lock);
return ret;
}
@@ -350,6 +351,10 @@ static __maybe_unused int venus_runtime_suspend(struct device *dev)
if (ret)
return ret;
+ ret = icc_set_bw(core->cpucfg_path, 0, 0);
+ if (ret)
+ return ret;
+
if (pm_ops->core_power)
ret = pm_ops->core_power(dev, POWER_OFF);
@@ -368,6 +373,10 @@ static __maybe_unused int venus_runtime_resume(struct device *dev)
return ret;
}
+ ret = icc_set_bw(core->cpucfg_path, 0, kbps_to_icc(1000));
+ if (ret)
+ return ret;
+
return hfi_core_resume(core, false);
}
@@ -447,7 +456,7 @@ static const struct freq_tbl sdm845_freq_table[] = {
{ 244800, 100000000 }, /* 1920x1080@30 */
};
-static struct codec_freq_data sdm845_codec_freq_data[] = {
+static const struct codec_freq_data sdm845_codec_freq_data[] = {
{ V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 10 },
{ V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 10 },
{ V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 10 },
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index bd3ac6a4501f..7118612673c9 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -128,6 +128,7 @@ struct venus_caps {
* @error: an error returned during last HFI sync operations
* @sys_error: an error flag that signal system error event
* @core_ops: the core operations
+ * @pm_lock: a lock for PM operations
* @enc_codecs: encoders supported by this core
* @dec_codecs: decoders supported by this core
* @max_sessions_supported: holds the maximum number of sessions
@@ -168,6 +169,7 @@ struct venus_core {
bool sys_error;
const struct hfi_core_ops *core_ops;
const struct venus_pm_ops *pm_ops;
+ struct mutex pm_lock;
unsigned long enc_codecs;
unsigned long dec_codecs;
unsigned int max_sessions_supported;
@@ -259,7 +261,8 @@ enum venus_dec_state {
VENUS_DEC_STATE_SEEK = 4,
VENUS_DEC_STATE_DRAIN = 5,
VENUS_DEC_STATE_DECODING = 6,
- VENUS_DEC_STATE_DRC = 7
+ VENUS_DEC_STATE_DRC = 7,
+ VENUS_DEC_STATE_DRC_FLUSH_DONE = 8,
};
struct venus_ts_metadata {
@@ -324,6 +327,7 @@ struct venus_ts_metadata {
* @priv: a private for HFI operations callbacks
* @session_type: the type of the session (decoder or encoder)
* @hprop: a union used as a holder by get property
+ * @last_buf: last capture buffer for dynamic-resoluton-change
*/
struct venus_inst {
struct list_head list;
@@ -385,6 +389,7 @@ struct venus_inst {
union hfi_get_property hprop;
unsigned int core_acquired: 1;
unsigned int bit_depth;
+ struct vb2_buffer *last_buf;
};
#define IS_V1(core) ((core)->res->hfi_version == HFI_VERSION_1XX)
diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c
index bcc603804041..0143af7822b2 100644
--- a/drivers/media/platform/qcom/venus/helpers.c
+++ b/drivers/media/platform/qcom/venus/helpers.c
@@ -1129,15 +1129,18 @@ unlock:
}
EXPORT_SYMBOL_GPL(venus_helper_vb2_buf_queue);
-void venus_helper_buffers_done(struct venus_inst *inst,
+void venus_helper_buffers_done(struct venus_inst *inst, unsigned int type,
enum vb2_buffer_state state)
{
struct vb2_v4l2_buffer *buf;
- while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx)))
- v4l2_m2m_buf_done(buf, state);
- while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
- v4l2_m2m_buf_done(buf, state);
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ while ((buf = v4l2_m2m_src_buf_remove(inst->m2m_ctx)))
+ v4l2_m2m_buf_done(buf, state);
+ } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
+ v4l2_m2m_buf_done(buf, state);
+ }
}
EXPORT_SYMBOL_GPL(venus_helper_buffers_done);
@@ -1168,7 +1171,10 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q)
INIT_LIST_HEAD(&inst->registeredbufs);
}
- venus_helper_buffers_done(inst, VB2_BUF_STATE_ERROR);
+ venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+ VB2_BUF_STATE_ERROR);
+ venus_helper_buffers_done(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ VB2_BUF_STATE_ERROR);
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
inst->streamon_out = 0;
diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h
index b64875564064..8fbbda12a4fe 100644
--- a/drivers/media/platform/qcom/venus/helpers.h
+++ b/drivers/media/platform/qcom/venus/helpers.h
@@ -14,7 +14,7 @@ struct venus_core;
bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt);
struct vb2_v4l2_buffer *venus_helper_find_buf(struct venus_inst *inst,
unsigned int type, u32 idx);
-void venus_helper_buffers_done(struct venus_inst *inst,
+void venus_helper_buffers_done(struct venus_inst *inst, unsigned int type,
enum vb2_buffer_state state);
int venus_helper_vb2_buf_init(struct vb2_buffer *vb);
int venus_helper_vb2_buf_prepare(struct vb2_buffer *vb);
diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c
index 3d8b1284d1f3..a211eb93e0f9 100644
--- a/drivers/media/platform/qcom/venus/hfi.c
+++ b/drivers/media/platform/qcom/venus/hfi.c
@@ -382,7 +382,7 @@ int hfi_session_unload_res(struct venus_inst *inst)
}
EXPORT_SYMBOL_GPL(hfi_session_unload_res);
-int hfi_session_flush(struct venus_inst *inst, u32 type)
+int hfi_session_flush(struct venus_inst *inst, u32 type, bool block)
{
const struct hfi_ops *ops = inst->core->ops;
int ret;
@@ -393,9 +393,11 @@ int hfi_session_flush(struct venus_inst *inst, u32 type)
if (ret)
return ret;
- ret = wait_session_msg(inst);
- if (ret)
- return ret;
+ if (block) {
+ ret = wait_session_msg(inst);
+ if (ret)
+ return ret;
+ }
return 0;
}
diff --git a/drivers/media/platform/qcom/venus/hfi.h b/drivers/media/platform/qcom/venus/hfi.h
index 855822c9f39b..62c315291484 100644
--- a/drivers/media/platform/qcom/venus/hfi.h
+++ b/drivers/media/platform/qcom/venus/hfi.h
@@ -102,6 +102,7 @@ struct hfi_inst_ops {
u32 hfi_flags, u64 timestamp_us);
void (*event_notify)(struct venus_inst *inst, u32 event,
struct hfi_event_data *data);
+ void (*flush_done)(struct venus_inst *inst);
};
struct hfi_ops {
@@ -161,7 +162,7 @@ int hfi_session_continue(struct venus_inst *inst);
int hfi_session_abort(struct venus_inst *inst);
int hfi_session_load_res(struct venus_inst *inst);
int hfi_session_unload_res(struct venus_inst *inst);
-int hfi_session_flush(struct venus_inst *inst, u32 type);
+int hfi_session_flush(struct venus_inst *inst, u32 type, bool block);
int hfi_session_set_buffers(struct venus_inst *inst,
struct hfi_buffer_desc *bd);
int hfi_session_unset_buffers(struct venus_inst *inst,
diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h
index cae9d5d61c0c..83705e237f1c 100644
--- a/drivers/media/platform/qcom/venus/hfi_cmds.h
+++ b/drivers/media/platform/qcom/venus/hfi_cmds.h
@@ -107,7 +107,7 @@ struct hfi_session_abort_pkt {
struct hfi_session_set_property_pkt {
struct hfi_session_hdr_pkt shdr;
u32 num_properties;
- u32 data[0];
+ u32 data[];
};
struct hfi_session_set_buffers_pkt {
diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c
index 04ef2286efc6..279a9d6fe737 100644
--- a/drivers/media/platform/qcom/venus/hfi_msgs.c
+++ b/drivers/media/platform/qcom/venus/hfi_msgs.c
@@ -439,6 +439,8 @@ static void hfi_session_flush_done(struct venus_core *core,
inst->error = pkt->error_type;
complete(&inst->done);
+ if (inst->ops->flush_done)
+ inst->ops->flush_done(inst);
}
static void hfi_session_etb_done(struct venus_core *core,
diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.h b/drivers/media/platform/qcom/venus/hfi_msgs.h
index 7694b1d25d9d..526d9f5b487b 100644
--- a/drivers/media/platform/qcom/venus/hfi_msgs.h
+++ b/drivers/media/platform/qcom/venus/hfi_msgs.h
@@ -155,7 +155,7 @@ struct hfi_msg_session_empty_buffer_done_pkt {
u32 input_tag;
u32 packet_buffer;
u32 extradata_buffer;
- u32 data[0];
+ u32 data[];
};
struct hfi_msg_session_fbd_compressed_pkt {
@@ -175,7 +175,7 @@ struct hfi_msg_session_fbd_compressed_pkt {
u32 picture_type;
u32 packet_buffer;
u32 extradata_buffer;
- u32 data[0];
+ u32 data[];
};
struct hfi_msg_session_fbd_uncompressed_plane0_pkt {
@@ -202,7 +202,7 @@ struct hfi_msg_session_fbd_uncompressed_plane0_pkt {
u32 picture_type;
u32 packet_buffer;
u32 extradata_buffer;
- u32 data[0];
+ u32 data[];
};
struct hfi_msg_session_fbd_uncompressed_plane1_pkt {
@@ -211,7 +211,7 @@ struct hfi_msg_session_fbd_uncompressed_plane1_pkt {
u32 filled_len;
u32 offset;
u32 packet_buffer2;
- u32 data[0];
+ u32 data[];
};
struct hfi_msg_session_fbd_uncompressed_plane2_pkt {
@@ -220,7 +220,7 @@ struct hfi_msg_session_fbd_uncompressed_plane2_pkt {
u32 filled_len;
u32 offset;
u32 packet_buffer3;
- u32 data[0];
+ u32 data[];
};
struct hfi_msg_session_parse_sequence_header_done_pkt {
diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c
index 4ed2628585a1..7c4c483d5438 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -276,6 +276,14 @@ static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
const struct venus_format *fmt;
struct v4l2_format format;
u32 pixfmt_out = 0, pixfmt_cap = 0;
+ struct vb2_queue *q;
+
+ q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
+ if (!q)
+ return -EINVAL;
+
+ if (vb2_is_busy(q))
+ return -EBUSY;
orig_pixmp = *pixmp;
@@ -545,6 +553,64 @@ static const struct v4l2_ioctl_ops vdec_ioctl_ops = {
.vidioc_decoder_cmd = vdec_decoder_cmd,
};
+static int vdec_pm_get(struct venus_inst *inst)
+{
+ struct venus_core *core = inst->core;
+ struct device *dev = core->dev_dec;
+ int ret;
+
+ mutex_lock(&core->pm_lock);
+ ret = pm_runtime_get_sync(dev);
+ mutex_unlock(&core->pm_lock);
+
+ return ret < 0 ? ret : 0;
+}
+
+static int vdec_pm_put(struct venus_inst *inst, bool autosuspend)
+{
+ struct venus_core *core = inst->core;
+ struct device *dev = core->dev_dec;
+ int ret;
+
+ mutex_lock(&core->pm_lock);
+
+ if (autosuspend)
+ ret = pm_runtime_put_autosuspend(dev);
+ else
+ ret = pm_runtime_put_sync(dev);
+
+ mutex_unlock(&core->pm_lock);
+
+ return ret < 0 ? ret : 0;
+}
+
+static int vdec_pm_get_put(struct venus_inst *inst)
+{
+ struct venus_core *core = inst->core;
+ struct device *dev = core->dev_dec;
+ int ret = 0;
+
+ mutex_lock(&core->pm_lock);
+
+ if (pm_runtime_suspended(dev)) {
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0)
+ goto error;
+
+ ret = pm_runtime_put_autosuspend(dev);
+ }
+
+error:
+ mutex_unlock(&core->pm_lock);
+
+ return ret < 0 ? ret : 0;
+}
+
+static void vdec_pm_touch(struct venus_inst *inst)
+{
+ pm_runtime_mark_last_busy(inst->core->dev_dec);
+}
+
static int vdec_set_properties(struct venus_inst *inst)
{
struct vdec_controls *ctr = &inst->controls.dec;
@@ -746,12 +812,20 @@ static int vdec_queue_setup(struct vb2_queue *q,
return 0;
}
- ret = vdec_session_init(inst);
+ ret = vdec_pm_get(inst);
if (ret)
return ret;
+ ret = vdec_session_init(inst);
+ if (ret)
+ goto put_power;
+
ret = vdec_num_buffers(inst, &in_num, &out_num);
if (ret)
+ goto put_power;
+
+ ret = vdec_pm_put(inst, false);
+ if (ret)
return ret;
switch (q->type) {
@@ -786,6 +860,10 @@ static int vdec_queue_setup(struct vb2_queue *q,
}
return ret;
+
+put_power:
+ vdec_pm_put(inst, false);
+ return ret;
}
static int vdec_verify_conf(struct venus_inst *inst)
@@ -836,7 +914,7 @@ static int vdec_start_capture(struct venus_inst *inst)
return 0;
reconfigure:
- ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT);
+ ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, true);
if (ret)
return ret;
@@ -947,14 +1025,23 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
mutex_lock(&inst->lock);
- ret = venus_pm_acquire_core(inst);
- if (ret)
- goto error;
-
- if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
ret = vdec_start_capture(inst);
- else
+ } else {
+ ret = vdec_pm_get(inst);
+ if (ret)
+ goto error;
+
+ ret = venus_pm_acquire_core(inst);
+ if (ret)
+ goto put_power;
+
+ ret = vdec_pm_put(inst, true);
+ if (ret)
+ goto error;
+
ret = vdec_start_output(inst);
+ }
if (ret)
goto error;
@@ -962,8 +1049,10 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
mutex_unlock(&inst->lock);
return 0;
+put_power:
+ vdec_pm_put(inst, false);
error:
- venus_helper_buffers_done(inst, VB2_BUF_STATE_QUEUED);
+ venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
mutex_unlock(&inst->lock);
return ret;
}
@@ -982,23 +1071,25 @@ static int vdec_stop_capture(struct venus_inst *inst)
switch (inst->codec_state) {
case VENUS_DEC_STATE_DECODING:
- ret = hfi_session_flush(inst, HFI_FLUSH_ALL);
+ ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
/* fallthrough */
case VENUS_DEC_STATE_DRAIN:
vdec_cancel_dst_buffers(inst);
inst->codec_state = VENUS_DEC_STATE_STOPPED;
break;
case VENUS_DEC_STATE_DRC:
- ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT);
- vdec_cancel_dst_buffers(inst);
+ WARN_ON(1);
+ fallthrough;
+ case VENUS_DEC_STATE_DRC_FLUSH_DONE:
inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
- INIT_LIST_HEAD(&inst->registeredbufs);
venus_helper_free_dpb_bufs(inst);
break;
default:
- return 0;
+ break;
}
+ INIT_LIST_HEAD(&inst->registeredbufs);
+
return ret;
}
@@ -1010,12 +1101,12 @@ static int vdec_stop_output(struct venus_inst *inst)
case VENUS_DEC_STATE_DECODING:
case VENUS_DEC_STATE_DRAIN:
case VENUS_DEC_STATE_STOPPED:
- ret = hfi_session_flush(inst, HFI_FLUSH_ALL);
+ ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
inst->codec_state = VENUS_DEC_STATE_SEEK;
break;
case VENUS_DEC_STATE_INIT:
case VENUS_DEC_STATE_CAPTURE_SETUP:
- ret = hfi_session_flush(inst, HFI_FLUSH_INPUT);
+ ret = hfi_session_flush(inst, HFI_FLUSH_INPUT, true);
break;
default:
break;
@@ -1036,7 +1127,7 @@ static void vdec_stop_streaming(struct vb2_queue *q)
else
ret = vdec_stop_output(inst);
- venus_helper_buffers_done(inst, VB2_BUF_STATE_ERROR);
+ venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR);
if (ret)
goto unlock;
@@ -1055,8 +1146,9 @@ static void vdec_session_release(struct venus_inst *inst)
struct venus_core *core = inst->core;
int ret, abort = 0;
- mutex_lock(&inst->lock);
+ vdec_pm_get(inst);
+ mutex_lock(&inst->lock);
inst->codec_state = VENUS_DEC_STATE_DEINIT;
ret = hfi_session_stop(inst);
@@ -1078,10 +1170,11 @@ static void vdec_session_release(struct venus_inst *inst)
venus_helper_free_dpb_bufs(inst);
venus_pm_load_scale(inst);
- venus_pm_release_core(inst);
INIT_LIST_HEAD(&inst->registeredbufs);
-
mutex_unlock(&inst->lock);
+
+ venus_pm_release_core(inst);
+ vdec_pm_put(inst, false);
}
static int vdec_buf_init(struct vb2_buffer *vb)
@@ -1102,6 +1195,15 @@ static void vdec_buf_cleanup(struct vb2_buffer *vb)
vdec_session_release(inst);
}
+static void vdec_vb2_buf_queue(struct vb2_buffer *vb)
+{
+ struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
+
+ vdec_pm_get_put(inst);
+
+ venus_helper_vb2_buf_queue(vb);
+}
+
static const struct vb2_ops vdec_vb2_ops = {
.queue_setup = vdec_queue_setup,
.buf_init = vdec_buf_init,
@@ -1109,7 +1211,7 @@ static const struct vb2_ops vdec_vb2_ops = {
.buf_prepare = venus_helper_vb2_buf_prepare,
.start_streaming = vdec_start_streaming,
.stop_streaming = vdec_stop_streaming,
- .buf_queue = venus_helper_vb2_buf_queue,
+ .buf_queue = vdec_vb2_buf_queue,
};
static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
@@ -1121,6 +1223,8 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
struct vb2_buffer *vb;
unsigned int type;
+ vdec_pm_touch(inst);
+
if (buf_type == HFI_BUFFER_INPUT)
type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
else
@@ -1140,6 +1244,13 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
vb->timestamp = timestamp_us * NSEC_PER_USEC;
vbuf->sequence = inst->sequence_cap++;
+ if (inst->last_buf == vb) {
+ inst->last_buf = NULL;
+ vbuf->flags |= V4L2_BUF_FLAG_LAST;
+ vb2_set_plane_payload(vb, 0, 0);
+ vb->timestamp = 0;
+ }
+
if (vbuf->flags & V4L2_BUF_FLAG_LAST) {
const struct v4l2_event ev = { .type = V4L2_EVENT_EOS };
@@ -1148,6 +1259,9 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
if (inst->codec_state == VENUS_DEC_STATE_DRAIN)
inst->codec_state = VENUS_DEC_STATE_STOPPED;
}
+
+ if (!bytesused)
+ state = VB2_BUF_STATE_ERROR;
} else {
vbuf->sequence = inst->sequence_out++;
}
@@ -1214,6 +1328,25 @@ static void vdec_event_change(struct venus_inst *inst,
}
}
+ /*
+ * The assumption is that the firmware have to return the last buffer
+ * before this event is received in the v4l2 driver. Also the firmware
+ * itself doesn't mark the last decoder output buffer with HFI EOS flag.
+ */
+
+ if (!sufficient && inst->codec_state == VENUS_DEC_STATE_DRC) {
+ struct vb2_v4l2_buffer *last;
+ int ret;
+
+ last = v4l2_m2m_last_dst_buf(inst->m2m_ctx);
+ if (last)
+ inst->last_buf = &last->vb2_buf;
+
+ ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, false);
+ if (ret)
+ dev_dbg(dev, "flush output error %d\n", ret);
+ }
+
inst->reconfig = true;
v4l2_event_queue_fh(&inst->fh, &ev);
wake_up(&inst->reconf_wait);
@@ -1227,6 +1360,8 @@ static void vdec_event_notify(struct venus_inst *inst, u32 event,
struct venus_core *core = inst->core;
struct device *dev = core->dev_dec;
+ vdec_pm_touch(inst);
+
switch (event) {
case EVT_SESSION_ERROR:
inst->session_error = true;
@@ -1252,9 +1387,16 @@ static void vdec_event_notify(struct venus_inst *inst, u32 event,
}
}
+static void vdec_flush_done(struct venus_inst *inst)
+{
+ if (inst->codec_state == VENUS_DEC_STATE_DRC)
+ inst->codec_state = VENUS_DEC_STATE_DRC_FLUSH_DONE;
+}
+
static const struct hfi_inst_ops vdec_hfi_ops = {
.buf_done = vdec_buf_done,
.event_notify = vdec_event_notify,
+ .flush_done = vdec_flush_done,
};
static void vdec_inst_init(struct venus_inst *inst)
@@ -1347,13 +1489,9 @@ static int vdec_open(struct file *file)
init_waitqueue_head(&inst->reconf_wait);
venus_helper_init_instance(inst);
- ret = pm_runtime_get_sync(core->dev_dec);
- if (ret < 0)
- goto err_free_inst;
-
ret = vdec_ctrl_init(inst);
if (ret)
- goto err_put_sync;
+ goto err_free;
ret = hfi_session_create(inst, &vdec_hfi_ops);
if (ret)
@@ -1392,9 +1530,7 @@ err_session_destroy:
hfi_session_destroy(inst);
err_ctrl_deinit:
vdec_ctrl_deinit(inst);
-err_put_sync:
- pm_runtime_put_sync(core->dev_dec);
-err_free_inst:
+err_free:
kfree(inst);
return ret;
}
@@ -1403,6 +1539,8 @@ static int vdec_close(struct file *file)
{
struct venus_inst *inst = to_inst(file);
+ vdec_pm_get(inst);
+
v4l2_m2m_ctx_release(inst->m2m_ctx);
v4l2_m2m_release(inst->m2m_dev);
vdec_ctrl_deinit(inst);
@@ -1411,7 +1549,7 @@ static int vdec_close(struct file *file)
v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh);
- pm_runtime_put_sync(inst->core->dev_dec);
+ vdec_pm_put(inst, false);
kfree(inst);
return 0;
@@ -1468,6 +1606,8 @@ static int vdec_probe(struct platform_device *pdev)
core->dev_dec = dev;
video_set_drvdata(vdev, core);
+ pm_runtime_set_autosuspend_delay(dev, 2000);
+ pm_runtime_use_autosuspend(dev);
pm_runtime_enable(dev);
return 0;
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index 9981a2a27c90..feed648550d1 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -357,6 +357,14 @@ static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
const struct venus_format *fmt;
struct v4l2_format format;
u32 pixfmt_out = 0, pixfmt_cap = 0;
+ struct vb2_queue *q;
+
+ q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
+ if (!q)
+ return -EINVAL;
+
+ if (vb2_is_busy(q))
+ return -EBUSY;
orig_pixmp = *pixmp;
@@ -1018,7 +1026,7 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
deinit_sess:
hfi_session_deinit(inst);
bufs_done:
- venus_helper_buffers_done(inst, VB2_BUF_STATE_QUEUED);
+ venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
inst->streamon_out = 0;
else
diff --git a/drivers/media/platform/rcar-fcp.c b/drivers/media/platform/rcar-fcp.c
index 43c78620c9d8..5c6b00737fe7 100644
--- a/drivers/media/platform/rcar-fcp.c
+++ b/drivers/media/platform/rcar-fcp.c
@@ -8,6 +8,7 @@
*/
#include <linux/device.h>
+#include <linux/dma-mapping.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
@@ -21,6 +22,7 @@
struct rcar_fcp_device {
struct list_head list;
struct device *dev;
+ struct device_dma_parameters dma_parms;
};
static LIST_HEAD(fcp_devices);
@@ -136,6 +138,9 @@ static int rcar_fcp_probe(struct platform_device *pdev)
fcp->dev = &pdev->dev;
+ fcp->dev->dma_parms = &fcp->dma_parms;
+ dma_set_max_seg_size(fcp->dev, DMA_BIT_MASK(32));
+
pm_runtime_enable(&pdev->dev);
mutex_lock(&fcp_lock);
diff --git a/drivers/media/platform/rcar-vin/Kconfig b/drivers/media/platform/rcar-vin/Kconfig
index 240ac3f3c941..ca0d906dce2f 100644
--- a/drivers/media/platform/rcar-vin/Kconfig
+++ b/drivers/media/platform/rcar-vin/Kconfig
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
config VIDEO_RCAR_CSI2
tristate "R-Car MIPI CSI-2 Receiver"
- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF
+ depends on VIDEO_V4L2 && OF
depends on ARCH_RENESAS || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select RESET_CONTROLLER
select V4L2_FWNODE
help
@@ -14,8 +16,10 @@ config VIDEO_RCAR_CSI2
config VIDEO_RCAR_VIN
tristate "R-Car Video Input (VIN) Driver"
- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF && MEDIA_CONTROLLER
+ depends on VIDEO_V4L2 && OF
depends on ARCH_RENESAS || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select V4L2_FWNODE
help
diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
index faa9fb23a2e9..151e6a90c5fb 100644
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -52,8 +52,8 @@ struct rcar_csi2;
/*
* Channel Data Type Select
- * VCDT[0-15]: Channel 1 VCDT[16-31]: Channel 2
- * VCDT2[0-15]: Channel 3 VCDT2[16-31]: Channel 4
+ * VCDT[0-15]: Channel 0 VCDT[16-31]: Channel 1
+ * VCDT2[0-15]: Channel 2 VCDT2[16-31]: Channel 3
*/
#define VCDT_REG 0x10
#define VCDT2_REG 0x14
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 5151a3cd8a6e..f421e2584875 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -343,6 +343,29 @@ static int rvin_enum_fmt_vid_cap(struct file *file, void *priv,
unsigned int i;
int matched;
+ /*
+ * If mbus_code is set only enumerate supported pixel formats for that
+ * bus code. Converting from YCbCr to RGB and RGB to YCbCr is possible
+ * with VIN, so all supported YCbCr and RGB media bus codes can produce
+ * all of the related pixel formats. If mbus_code is not set enumerate
+ * all possible pixelformats.
+ *
+ * TODO: Once raw capture formats are added to the driver this needs
+ * to be extended so raw media bus codes only result in raw pixel
+ * formats.
+ */
+ switch (f->mbus_code) {
+ case 0:
+ case MEDIA_BUS_FMT_YUYV8_1X16:
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ case MEDIA_BUS_FMT_UYVY8_2X8:
+ case MEDIA_BUS_FMT_UYVY10_2X10:
+ case MEDIA_BUS_FMT_RGB888_1X24:
+ break;
+ default:
+ return -EINVAL;
+ }
+
matched = -1;
for (i = 0; i < ARRAY_SIZE(rvin_formats); i++) {
if (rvin_format_from_pixel(vin, rvin_formats[i].fourcc))
@@ -767,18 +790,6 @@ static int rvin_mc_s_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
-static int rvin_mc_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- if (i->index != 0)
- return -EINVAL;
-
- i->type = V4L2_INPUT_TYPE_CAMERA;
- strscpy(i->name, "Camera", sizeof(i->name));
-
- return 0;
-}
-
static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops = {
.vidioc_querycap = rvin_querycap,
.vidioc_try_fmt_vid_cap = rvin_mc_try_fmt_vid_cap,
@@ -786,10 +797,6 @@ static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops = {
.vidioc_s_fmt_vid_cap = rvin_mc_s_fmt_vid_cap,
.vidioc_enum_fmt_vid_cap = rvin_enum_fmt_vid_cap,
- .vidioc_enum_input = rvin_mc_enum_input,
- .vidioc_g_input = rvin_g_input,
- .vidioc_s_input = rvin_s_input,
-
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_querybuf = vb2_ioctl_querybuf,
@@ -961,6 +968,7 @@ int rvin_v4l2_register(struct rvin_dev *vin)
vin->format.colorspace = RVIN_DEFAULT_COLORSPACE;
if (vin->info->use_mc) {
+ vdev->device_caps |= V4L2_CAP_IO_MC;
vdev->ioctl_ops = &rvin_mc_ioctl_ops;
} else {
vdev->ioctl_ops = &rvin_ioctl_ops;
diff --git a/drivers/media/platform/s5p-cec/Makefile b/drivers/media/platform/s5p-cec/Makefile
deleted file mode 100644
index bd0103b91bee..000000000000
--- a/drivers/media/platform/s5p-cec/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_CEC) += s5p-cec.o
-s5p-cec-y += s5p_cec.o exynos_hdmi_cecctrl.o
diff --git a/drivers/media/platform/s5p-cec/exynos_hdmi_cec.h b/drivers/media/platform/s5p-cec/exynos_hdmi_cec.h
deleted file mode 100644
index 325db8c432bd..000000000000
--- a/drivers/media/platform/s5p-cec/exynos_hdmi_cec.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* drivers/media/platform/s5p-cec/exynos_hdmi_cec.h
- *
- * Copyright (c) 2010, 2014 Samsung Electronics
- * http://www.samsung.com/
- *
- * Header file for interface of Samsung Exynos hdmi cec hardware
- */
-
-#ifndef _EXYNOS_HDMI_CEC_H_
-#define _EXYNOS_HDMI_CEC_H_ __FILE__
-
-#include <linux/regmap.h>
-#include "s5p_cec.h"
-
-void s5p_cec_set_divider(struct s5p_cec_dev *cec);
-void s5p_cec_enable_rx(struct s5p_cec_dev *cec);
-void s5p_cec_mask_rx_interrupts(struct s5p_cec_dev *cec);
-void s5p_cec_unmask_rx_interrupts(struct s5p_cec_dev *cec);
-void s5p_cec_mask_tx_interrupts(struct s5p_cec_dev *cec);
-void s5p_cec_unmask_tx_interrupts(struct s5p_cec_dev *cec);
-void s5p_cec_reset(struct s5p_cec_dev *cec);
-void s5p_cec_tx_reset(struct s5p_cec_dev *cec);
-void s5p_cec_rx_reset(struct s5p_cec_dev *cec);
-void s5p_cec_threshold(struct s5p_cec_dev *cec);
-void s5p_cec_copy_packet(struct s5p_cec_dev *cec, char *data,
- size_t count, u8 retries);
-void s5p_cec_set_addr(struct s5p_cec_dev *cec, u32 addr);
-u32 s5p_cec_get_status(struct s5p_cec_dev *cec);
-void s5p_clr_pending_tx(struct s5p_cec_dev *cec);
-void s5p_clr_pending_rx(struct s5p_cec_dev *cec);
-void s5p_cec_get_rx_buf(struct s5p_cec_dev *cec, u32 size, u8 *buffer);
-
-#endif /* _EXYNOS_HDMI_CEC_H_ */
diff --git a/drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c b/drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c
deleted file mode 100644
index eb981ebce362..000000000000
--- a/drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c
+++ /dev/null
@@ -1,206 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c
- *
- * Copyright (c) 2009, 2014 Samsung Electronics
- * http://www.samsung.com/
- *
- * cec ftn file for Samsung TVOUT driver
- */
-
-#include <linux/io.h>
-#include <linux/device.h>
-
-#include "exynos_hdmi_cec.h"
-#include "regs-cec.h"
-
-#define S5P_HDMI_FIN 24000000
-#define CEC_DIV_RATIO 320000
-
-#define CEC_MESSAGE_BROADCAST_MASK 0x0F
-#define CEC_MESSAGE_BROADCAST 0x0F
-#define CEC_FILTER_THRESHOLD 0x15
-
-void s5p_cec_set_divider(struct s5p_cec_dev *cec)
-{
- u32 div_ratio, div_val;
- unsigned int reg;
-
- div_ratio = S5P_HDMI_FIN / CEC_DIV_RATIO - 1;
-
- if (regmap_read(cec->pmu, EXYNOS_HDMI_PHY_CONTROL, &reg)) {
- dev_err(cec->dev, "failed to read phy control\n");
- return;
- }
-
- reg = (reg & ~(0x3FF << 16)) | (div_ratio << 16);
-
- if (regmap_write(cec->pmu, EXYNOS_HDMI_PHY_CONTROL, reg)) {
- dev_err(cec->dev, "failed to write phy control\n");
- return;
- }
-
- div_val = CEC_DIV_RATIO * 0.00005 - 1;
-
- writeb(0x0, cec->reg + S5P_CEC_DIVISOR_3);
- writeb(0x0, cec->reg + S5P_CEC_DIVISOR_2);
- writeb(0x0, cec->reg + S5P_CEC_DIVISOR_1);
- writeb(div_val, cec->reg + S5P_CEC_DIVISOR_0);
-}
-
-void s5p_cec_enable_rx(struct s5p_cec_dev *cec)
-{
- u8 reg;
-
- reg = readb(cec->reg + S5P_CEC_RX_CTRL);
- reg |= S5P_CEC_RX_CTRL_ENABLE;
- writeb(reg, cec->reg + S5P_CEC_RX_CTRL);
-}
-
-void s5p_cec_mask_rx_interrupts(struct s5p_cec_dev *cec)
-{
- u8 reg;
-
- reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
- reg |= S5P_CEC_IRQ_RX_DONE;
- reg |= S5P_CEC_IRQ_RX_ERROR;
- writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
-}
-
-void s5p_cec_unmask_rx_interrupts(struct s5p_cec_dev *cec)
-{
- u8 reg;
-
- reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
- reg &= ~S5P_CEC_IRQ_RX_DONE;
- reg &= ~S5P_CEC_IRQ_RX_ERROR;
- writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
-}
-
-void s5p_cec_mask_tx_interrupts(struct s5p_cec_dev *cec)
-{
- u8 reg;
-
- reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
- reg |= S5P_CEC_IRQ_TX_DONE;
- reg |= S5P_CEC_IRQ_TX_ERROR;
- writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
-}
-
-void s5p_cec_unmask_tx_interrupts(struct s5p_cec_dev *cec)
-{
- u8 reg;
-
- reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
- reg &= ~S5P_CEC_IRQ_TX_DONE;
- reg &= ~S5P_CEC_IRQ_TX_ERROR;
- writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
-}
-
-void s5p_cec_reset(struct s5p_cec_dev *cec)
-{
- u8 reg;
-
- writeb(S5P_CEC_RX_CTRL_RESET, cec->reg + S5P_CEC_RX_CTRL);
- writeb(S5P_CEC_TX_CTRL_RESET, cec->reg + S5P_CEC_TX_CTRL);
-
- reg = readb(cec->reg + 0xc4);
- reg &= ~0x1;
- writeb(reg, cec->reg + 0xc4);
-}
-
-void s5p_cec_tx_reset(struct s5p_cec_dev *cec)
-{
- writeb(S5P_CEC_TX_CTRL_RESET, cec->reg + S5P_CEC_TX_CTRL);
-}
-
-void s5p_cec_rx_reset(struct s5p_cec_dev *cec)
-{
- u8 reg;
-
- writeb(S5P_CEC_RX_CTRL_RESET, cec->reg + S5P_CEC_RX_CTRL);
-
- reg = readb(cec->reg + 0xc4);
- reg &= ~0x1;
- writeb(reg, cec->reg + 0xc4);
-}
-
-void s5p_cec_threshold(struct s5p_cec_dev *cec)
-{
- writeb(CEC_FILTER_THRESHOLD, cec->reg + S5P_CEC_RX_FILTER_TH);
- writeb(0, cec->reg + S5P_CEC_RX_FILTER_CTRL);
-}
-
-void s5p_cec_copy_packet(struct s5p_cec_dev *cec, char *data,
- size_t count, u8 retries)
-{
- int i = 0;
- u8 reg;
-
- while (i < count) {
- writeb(data[i], cec->reg + (S5P_CEC_TX_BUFF0 + (i * 4)));
- i++;
- }
-
- writeb(count, cec->reg + S5P_CEC_TX_BYTES);
- reg = readb(cec->reg + S5P_CEC_TX_CTRL);
- reg |= S5P_CEC_TX_CTRL_START;
- reg &= ~0x70;
- reg |= retries << 4;
-
- if ((data[0] & CEC_MESSAGE_BROADCAST_MASK) == CEC_MESSAGE_BROADCAST) {
- dev_dbg(cec->dev, "Broadcast");
- reg |= S5P_CEC_TX_CTRL_BCAST;
- } else {
- dev_dbg(cec->dev, "No Broadcast");
- reg &= ~S5P_CEC_TX_CTRL_BCAST;
- }
-
- writeb(reg, cec->reg + S5P_CEC_TX_CTRL);
- dev_dbg(cec->dev, "cec-tx: cec count (%zu): %*ph", count,
- (int)count, data);
-}
-
-void s5p_cec_set_addr(struct s5p_cec_dev *cec, u32 addr)
-{
- writeb(addr & 0x0F, cec->reg + S5P_CEC_LOGIC_ADDR);
-}
-
-u32 s5p_cec_get_status(struct s5p_cec_dev *cec)
-{
- u32 status = 0;
-
- status = readb(cec->reg + S5P_CEC_STATUS_0) & 0xf;
- status |= (readb(cec->reg + S5P_CEC_TX_STAT1) & 0xf) << 4;
- status |= readb(cec->reg + S5P_CEC_STATUS_1) << 8;
- status |= readb(cec->reg + S5P_CEC_STATUS_2) << 16;
- status |= readb(cec->reg + S5P_CEC_STATUS_3) << 24;
-
- dev_dbg(cec->dev, "status = 0x%x!\n", status);
-
- return status;
-}
-
-void s5p_clr_pending_tx(struct s5p_cec_dev *cec)
-{
- writeb(S5P_CEC_IRQ_TX_DONE | S5P_CEC_IRQ_TX_ERROR,
- cec->reg + S5P_CEC_IRQ_CLEAR);
-}
-
-void s5p_clr_pending_rx(struct s5p_cec_dev *cec)
-{
- writeb(S5P_CEC_IRQ_RX_DONE | S5P_CEC_IRQ_RX_ERROR,
- cec->reg + S5P_CEC_IRQ_CLEAR);
-}
-
-void s5p_cec_get_rx_buf(struct s5p_cec_dev *cec, u32 size, u8 *buffer)
-{
- u32 i = 0;
- char debug[40];
-
- while (i < size) {
- buffer[i] = readb(cec->reg + S5P_CEC_RX_BUFF0 + (i * 4));
- sprintf(debug + i * 2, "%02x ", buffer[i]);
- i++;
- }
- dev_dbg(cec->dev, "cec-rx: cec size(%d): %s", size, debug);
-}
diff --git a/drivers/media/platform/s5p-cec/regs-cec.h b/drivers/media/platform/s5p-cec/regs-cec.h
deleted file mode 100644
index 447f717028a2..000000000000
--- a/drivers/media/platform/s5p-cec/regs-cec.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* drivers/media/platform/s5p-cec/regs-cec.h
- *
- * Copyright (c) 2010 Samsung Electronics
- * http://www.samsung.com/
- *
- * register header file for Samsung TVOUT driver
- */
-
-#ifndef __EXYNOS_REGS__H
-#define __EXYNOS_REGS__H
-
-/*
- * Register part
- */
-#define S5P_CEC_STATUS_0 (0x0000)
-#define S5P_CEC_STATUS_1 (0x0004)
-#define S5P_CEC_STATUS_2 (0x0008)
-#define S5P_CEC_STATUS_3 (0x000C)
-#define S5P_CEC_IRQ_MASK (0x0010)
-#define S5P_CEC_IRQ_CLEAR (0x0014)
-#define S5P_CEC_LOGIC_ADDR (0x0020)
-#define S5P_CEC_DIVISOR_0 (0x0030)
-#define S5P_CEC_DIVISOR_1 (0x0034)
-#define S5P_CEC_DIVISOR_2 (0x0038)
-#define S5P_CEC_DIVISOR_3 (0x003C)
-
-#define S5P_CEC_TX_CTRL (0x0040)
-#define S5P_CEC_TX_BYTES (0x0044)
-#define S5P_CEC_TX_STAT0 (0x0060)
-#define S5P_CEC_TX_STAT1 (0x0064)
-#define S5P_CEC_TX_BUFF0 (0x0080)
-#define S5P_CEC_TX_BUFF1 (0x0084)
-#define S5P_CEC_TX_BUFF2 (0x0088)
-#define S5P_CEC_TX_BUFF3 (0x008C)
-#define S5P_CEC_TX_BUFF4 (0x0090)
-#define S5P_CEC_TX_BUFF5 (0x0094)
-#define S5P_CEC_TX_BUFF6 (0x0098)
-#define S5P_CEC_TX_BUFF7 (0x009C)
-#define S5P_CEC_TX_BUFF8 (0x00A0)
-#define S5P_CEC_TX_BUFF9 (0x00A4)
-#define S5P_CEC_TX_BUFF10 (0x00A8)
-#define S5P_CEC_TX_BUFF11 (0x00AC)
-#define S5P_CEC_TX_BUFF12 (0x00B0)
-#define S5P_CEC_TX_BUFF13 (0x00B4)
-#define S5P_CEC_TX_BUFF14 (0x00B8)
-#define S5P_CEC_TX_BUFF15 (0x00BC)
-
-#define S5P_CEC_RX_CTRL (0x00C0)
-#define S5P_CEC_RX_STAT0 (0x00E0)
-#define S5P_CEC_RX_STAT1 (0x00E4)
-#define S5P_CEC_RX_BUFF0 (0x0100)
-#define S5P_CEC_RX_BUFF1 (0x0104)
-#define S5P_CEC_RX_BUFF2 (0x0108)
-#define S5P_CEC_RX_BUFF3 (0x010C)
-#define S5P_CEC_RX_BUFF4 (0x0110)
-#define S5P_CEC_RX_BUFF5 (0x0114)
-#define S5P_CEC_RX_BUFF6 (0x0118)
-#define S5P_CEC_RX_BUFF7 (0x011C)
-#define S5P_CEC_RX_BUFF8 (0x0120)
-#define S5P_CEC_RX_BUFF9 (0x0124)
-#define S5P_CEC_RX_BUFF10 (0x0128)
-#define S5P_CEC_RX_BUFF11 (0x012C)
-#define S5P_CEC_RX_BUFF12 (0x0130)
-#define S5P_CEC_RX_BUFF13 (0x0134)
-#define S5P_CEC_RX_BUFF14 (0x0138)
-#define S5P_CEC_RX_BUFF15 (0x013C)
-
-#define S5P_CEC_RX_FILTER_CTRL (0x0180)
-#define S5P_CEC_RX_FILTER_TH (0x0184)
-
-/*
- * Bit definition part
- */
-#define S5P_CEC_IRQ_TX_DONE (1<<0)
-#define S5P_CEC_IRQ_TX_ERROR (1<<1)
-#define S5P_CEC_IRQ_RX_DONE (1<<4)
-#define S5P_CEC_IRQ_RX_ERROR (1<<5)
-
-#define S5P_CEC_TX_CTRL_START (1<<0)
-#define S5P_CEC_TX_CTRL_BCAST (1<<1)
-#define S5P_CEC_TX_CTRL_RETRY (0x04<<4)
-#define S5P_CEC_TX_CTRL_RESET (1<<7)
-
-#define S5P_CEC_RX_CTRL_ENABLE (1<<0)
-#define S5P_CEC_RX_CTRL_RESET (1<<7)
-
-#define S5P_CEC_LOGIC_ADDR_MASK (0xF)
-
-/* PMU Registers for PHY */
-#define EXYNOS_HDMI_PHY_CONTROL 0x700
-
-#endif /* __EXYNOS_REGS__H */
diff --git a/drivers/media/platform/s5p-cec/s5p_cec.c b/drivers/media/platform/s5p-cec/s5p_cec.c
deleted file mode 100644
index 2a3e7ffefe0a..000000000000
--- a/drivers/media/platform/s5p-cec/s5p_cec.c
+++ /dev/null
@@ -1,307 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/* drivers/media/platform/s5p-cec/s5p_cec.c
- *
- * Samsung S5P CEC driver
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *
- * This driver is based on the "cec interface driver for exynos soc" by
- * SangPil Moon.
- */
-
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-#include <media/cec.h>
-#include <media/cec-notifier.h>
-
-#include "exynos_hdmi_cec.h"
-#include "regs-cec.h"
-#include "s5p_cec.h"
-
-#define CEC_NAME "s5p-cec"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "debug level (0-2)");
-
-static int s5p_cec_adap_enable(struct cec_adapter *adap, bool enable)
-{
- struct s5p_cec_dev *cec = cec_get_drvdata(adap);
-
- if (enable) {
- pm_runtime_get_sync(cec->dev);
-
- s5p_cec_reset(cec);
-
- s5p_cec_set_divider(cec);
- s5p_cec_threshold(cec);
-
- s5p_cec_unmask_tx_interrupts(cec);
- s5p_cec_unmask_rx_interrupts(cec);
- s5p_cec_enable_rx(cec);
- } else {
- s5p_cec_mask_tx_interrupts(cec);
- s5p_cec_mask_rx_interrupts(cec);
- pm_runtime_disable(cec->dev);
- }
-
- return 0;
-}
-
-static int s5p_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
-{
- struct s5p_cec_dev *cec = cec_get_drvdata(adap);
-
- s5p_cec_set_addr(cec, addr);
- return 0;
-}
-
-static int s5p_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
- u32 signal_free_time, struct cec_msg *msg)
-{
- struct s5p_cec_dev *cec = cec_get_drvdata(adap);
-
- /*
- * Unclear if 0 retries are allowed by the hardware, so have 1 as
- * the minimum.
- */
- s5p_cec_copy_packet(cec, msg->msg, msg->len, max(1, attempts - 1));
- return 0;
-}
-
-static irqreturn_t s5p_cec_irq_handler(int irq, void *priv)
-{
- struct s5p_cec_dev *cec = priv;
- u32 status = 0;
-
- status = s5p_cec_get_status(cec);
-
- dev_dbg(cec->dev, "irq received\n");
-
- if (status & CEC_STATUS_TX_DONE) {
- if (status & CEC_STATUS_TX_NACK) {
- dev_dbg(cec->dev, "CEC_STATUS_TX_NACK set\n");
- cec->tx = STATE_NACK;
- } else if (status & CEC_STATUS_TX_ERROR) {
- dev_dbg(cec->dev, "CEC_STATUS_TX_ERROR set\n");
- cec->tx = STATE_ERROR;
- } else {
- dev_dbg(cec->dev, "CEC_STATUS_TX_DONE\n");
- cec->tx = STATE_DONE;
- }
- s5p_clr_pending_tx(cec);
- }
-
- if (status & CEC_STATUS_RX_DONE) {
- if (status & CEC_STATUS_RX_ERROR) {
- dev_dbg(cec->dev, "CEC_STATUS_RX_ERROR set\n");
- s5p_cec_rx_reset(cec);
- s5p_cec_enable_rx(cec);
- } else {
- dev_dbg(cec->dev, "CEC_STATUS_RX_DONE set\n");
- if (cec->rx != STATE_IDLE)
- dev_dbg(cec->dev, "Buffer overrun (worker did not process previous message)\n");
- cec->rx = STATE_BUSY;
- cec->msg.len = status >> 24;
- cec->msg.rx_status = CEC_RX_STATUS_OK;
- s5p_cec_get_rx_buf(cec, cec->msg.len,
- cec->msg.msg);
- cec->rx = STATE_DONE;
- s5p_cec_enable_rx(cec);
- }
- /* Clear interrupt pending bit */
- s5p_clr_pending_rx(cec);
- }
- return IRQ_WAKE_THREAD;
-}
-
-static irqreturn_t s5p_cec_irq_handler_thread(int irq, void *priv)
-{
- struct s5p_cec_dev *cec = priv;
-
- dev_dbg(cec->dev, "irq processing thread\n");
- switch (cec->tx) {
- case STATE_DONE:
- cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
- cec->tx = STATE_IDLE;
- break;
- case STATE_NACK:
- cec_transmit_done(cec->adap,
- CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_NACK,
- 0, 1, 0, 0);
- cec->tx = STATE_IDLE;
- break;
- case STATE_ERROR:
- cec_transmit_done(cec->adap,
- CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_ERROR,
- 0, 0, 0, 1);
- cec->tx = STATE_IDLE;
- break;
- case STATE_BUSY:
- dev_err(cec->dev, "state set to busy, this should not occur here\n");
- break;
- default:
- break;
- }
-
- switch (cec->rx) {
- case STATE_DONE:
- cec_received_msg(cec->adap, &cec->msg);
- cec->rx = STATE_IDLE;
- break;
- default:
- break;
- }
-
- return IRQ_HANDLED;
-}
-
-static const struct cec_adap_ops s5p_cec_adap_ops = {
- .adap_enable = s5p_cec_adap_enable,
- .adap_log_addr = s5p_cec_adap_log_addr,
- .adap_transmit = s5p_cec_adap_transmit,
-};
-
-static int s5p_cec_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device *hdmi_dev;
- struct resource *res;
- struct s5p_cec_dev *cec;
- bool needs_hpd = of_property_read_bool(pdev->dev.of_node, "needs-hpd");
- int ret;
-
- hdmi_dev = cec_notifier_parse_hdmi_phandle(dev);
-
- if (IS_ERR(hdmi_dev))
- return PTR_ERR(hdmi_dev);
-
- cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
- if (!cec)
- return -ENOMEM;
-
- cec->dev = dev;
-
- cec->irq = platform_get_irq(pdev, 0);
- if (cec->irq < 0)
- return cec->irq;
-
- ret = devm_request_threaded_irq(dev, cec->irq, s5p_cec_irq_handler,
- s5p_cec_irq_handler_thread, 0, pdev->name, cec);
- if (ret)
- return ret;
-
- cec->clk = devm_clk_get(dev, "hdmicec");
- if (IS_ERR(cec->clk))
- return PTR_ERR(cec->clk);
-
- cec->pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
- "samsung,syscon-phandle");
- if (IS_ERR(cec->pmu))
- return -EPROBE_DEFER;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- cec->reg = devm_ioremap_resource(dev, res);
- if (IS_ERR(cec->reg))
- return PTR_ERR(cec->reg);
-
- cec->adap = cec_allocate_adapter(&s5p_cec_adap_ops, cec, CEC_NAME,
- CEC_CAP_DEFAULTS | (needs_hpd ? CEC_CAP_NEEDS_HPD : 0) |
- CEC_CAP_CONNECTOR_INFO, 1);
- ret = PTR_ERR_OR_ZERO(cec->adap);
- if (ret)
- return ret;
-
- cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
- cec->adap);
- if (!cec->notifier) {
- ret = -ENOMEM;
- goto err_delete_adapter;
- }
-
- ret = cec_register_adapter(cec->adap, &pdev->dev);
- if (ret)
- goto err_notifier;
-
- platform_set_drvdata(pdev, cec);
- pm_runtime_enable(dev);
-
- dev_dbg(dev, "successfully probed\n");
- return 0;
-
-err_notifier:
- cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
-
-err_delete_adapter:
- cec_delete_adapter(cec->adap);
- return ret;
-}
-
-static int 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)
-{
- struct s5p_cec_dev *cec = dev_get_drvdata(dev);
-
- clk_disable_unprepare(cec->clk);
- return 0;
-}
-
-static int __maybe_unused s5p_cec_runtime_resume(struct device *dev)
-{
- struct s5p_cec_dev *cec = dev_get_drvdata(dev);
- int ret;
-
- ret = clk_prepare_enable(cec->clk);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-static const struct dev_pm_ops s5p_cec_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
- SET_RUNTIME_PM_OPS(s5p_cec_runtime_suspend, s5p_cec_runtime_resume,
- NULL)
-};
-
-static const struct of_device_id s5p_cec_match[] = {
- {
- .compatible = "samsung,s5p-cec",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, s5p_cec_match);
-
-static struct platform_driver s5p_cec_pdrv = {
- .probe = s5p_cec_probe,
- .remove = s5p_cec_remove,
- .driver = {
- .name = CEC_NAME,
- .of_match_table = s5p_cec_match,
- .pm = &s5p_cec_pm_ops,
- },
-};
-
-module_platform_driver(s5p_cec_pdrv);
-
-MODULE_AUTHOR("Kamil Debski <kamil@wypas.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Samsung S5P CEC driver");
diff --git a/drivers/media/platform/s5p-cec/s5p_cec.h b/drivers/media/platform/s5p-cec/s5p_cec.h
deleted file mode 100644
index 34d033b20f96..000000000000
--- a/drivers/media/platform/s5p-cec/s5p_cec.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* drivers/media/platform/s5p-cec/s5p_cec.h
- *
- * Samsung S5P HDMI CEC driver
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- */
-
-#ifndef _S5P_CEC_H_
-#define _S5P_CEC_H_ __FILE__
-
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-#include <media/cec.h>
-
-#include "exynos_hdmi_cec.h"
-#include "regs-cec.h"
-#include "s5p_cec.h"
-
-#define CEC_NAME "s5p-cec"
-
-#define CEC_STATUS_TX_RUNNING (1 << 0)
-#define CEC_STATUS_TX_TRANSFERRING (1 << 1)
-#define CEC_STATUS_TX_DONE (1 << 2)
-#define CEC_STATUS_TX_ERROR (1 << 3)
-#define CEC_STATUS_TX_NACK (1 << 4)
-#define CEC_STATUS_TX_BYTES (0xFF << 8)
-#define CEC_STATUS_RX_RUNNING (1 << 16)
-#define CEC_STATUS_RX_RECEIVING (1 << 17)
-#define CEC_STATUS_RX_DONE (1 << 18)
-#define CEC_STATUS_RX_ERROR (1 << 19)
-#define CEC_STATUS_RX_BCAST (1 << 20)
-#define CEC_STATUS_RX_BYTES (0xFF << 24)
-
-#define CEC_WORKER_TX_DONE (1 << 0)
-#define CEC_WORKER_RX_MSG (1 << 1)
-
-/* CEC Rx buffer size */
-#define CEC_RX_BUFF_SIZE 16
-/* CEC Tx buffer size */
-#define CEC_TX_BUFF_SIZE 16
-
-enum cec_state {
- STATE_IDLE,
- STATE_BUSY,
- STATE_DONE,
- STATE_NACK,
- STATE_ERROR
-};
-
-struct cec_notifier;
-
-struct s5p_cec_dev {
- struct cec_adapter *adap;
- struct clk *clk;
- struct device *dev;
- struct mutex lock;
- struct regmap *pmu;
- struct cec_notifier *notifier;
- int irq;
- void __iomem *reg;
-
- enum cec_state rx;
- enum cec_state tx;
- struct cec_msg msg;
-};
-
-#endif /* _S5P_CEC_H_ */
diff --git a/drivers/media/platform/seco-cec/Makefile b/drivers/media/platform/seco-cec/Makefile
deleted file mode 100644
index 79fde6947ff2..000000000000
--- a/drivers/media/platform/seco-cec/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_SECO_CEC) += seco-cec.o
diff --git a/drivers/media/platform/seco-cec/seco-cec.c b/drivers/media/platform/seco-cec/seco-cec.c
deleted file mode 100644
index 2ff62a488b27..000000000000
--- a/drivers/media/platform/seco-cec/seco-cec.c
+++ /dev/null
@@ -1,803 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-/*
- * CEC driver for SECO X86 Boards
- *
- * Author: Ettore Chimenti <ek5.chimenti@gmail.com>
- * Copyright (C) 2018, SECO SpA.
- * Copyright (C) 2018, Aidilab Srl.
- */
-
-#include <linux/module.h>
-#include <linux/acpi.h>
-#include <linux/delay.h>
-#include <linux/dmi.h>
-#include <linux/gpio/consumer.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-
-/* CEC Framework */
-#include <media/cec-notifier.h>
-
-#include "seco-cec.h"
-
-struct secocec_data {
- struct device *dev;
- struct platform_device *pdev;
- struct cec_adapter *cec_adap;
- struct cec_notifier *notifier;
- struct rc_dev *ir;
- char ir_input_phys[32];
- int irq;
-};
-
-#define smb_wr16(cmd, data) smb_word_op(CMD_WORD_DATA, SECOCEC_MICRO_ADDRESS, \
- cmd, data, SMBUS_WRITE, NULL)
-#define smb_rd16(cmd, res) smb_word_op(CMD_WORD_DATA, SECOCEC_MICRO_ADDRESS, \
- cmd, 0, SMBUS_READ, res)
-
-static int smb_word_op(short data_format, u16 slave_addr, u8 cmd, u16 data,
- u8 operation, u16 *result)
-{
- unsigned int count;
- short _data_format;
- int status = 0;
-
- switch (data_format) {
- case CMD_BYTE_DATA:
- _data_format = BRA_SMB_CMD_BYTE_DATA;
- break;
- case CMD_WORD_DATA:
- _data_format = BRA_SMB_CMD_WORD_DATA;
- break;
- default:
- return -EINVAL;
- }
-
- /* Active wait until ready */
- for (count = 0; count <= SMBTIMEOUT; ++count) {
- if (!(inb(HSTS) & BRA_INUSE_STS))
- break;
- udelay(SMB_POLL_UDELAY);
- }
-
- if (count > SMBTIMEOUT)
- /* Reset the lock instead of failing */
- outb(0xff, HSTS);
-
- outb(0x00, HCNT);
- outb((u8)(slave_addr & 0xfe) | operation, XMIT_SLVA);
- outb(cmd, HCMD);
- inb(HCNT);
-
- if (operation == SMBUS_WRITE) {
- outb((u8)data, HDAT0);
- outb((u8)(data >> 8), HDAT1);
- }
-
- outb(BRA_START + _data_format, HCNT);
-
- for (count = 0; count <= SMBTIMEOUT; count++) {
- if (!(inb(HSTS) & BRA_HOST_BUSY))
- break;
- udelay(SMB_POLL_UDELAY);
- }
-
- if (count > SMBTIMEOUT) {
- status = -EBUSY;
- goto err;
- }
-
- if (inb(HSTS) & BRA_HSTS_ERR_MASK) {
- status = -EIO;
- goto err;
- }
-
- if (operation == SMBUS_READ)
- *result = ((inb(HDAT0) & 0xff) + ((inb(HDAT1) & 0xff) << 8));
-
-err:
- outb(0xff, HSTS);
- return status;
-}
-
-static int secocec_adap_enable(struct cec_adapter *adap, bool enable)
-{
- struct secocec_data *cec = cec_get_drvdata(adap);
- struct device *dev = cec->dev;
- u16 val = 0;
- int status;
-
- if (enable) {
- /* Clear the status register */
- status = smb_rd16(SECOCEC_STATUS_REG_1, &val);
- if (status)
- goto err;
-
- status = smb_wr16(SECOCEC_STATUS_REG_1, val);
- if (status)
- goto err;
-
- /* Enable the interrupts */
- status = smb_rd16(SECOCEC_ENABLE_REG_1, &val);
- if (status)
- goto err;
-
- status = smb_wr16(SECOCEC_ENABLE_REG_1,
- val | SECOCEC_ENABLE_REG_1_CEC);
- if (status)
- goto err;
-
- dev_dbg(dev, "Device enabled");
- } else {
- /* Clear the status register */
- status = smb_rd16(SECOCEC_STATUS_REG_1, &val);
- status = smb_wr16(SECOCEC_STATUS_REG_1, val);
-
- /* Disable the interrupts */
- status = smb_rd16(SECOCEC_ENABLE_REG_1, &val);
- status = smb_wr16(SECOCEC_ENABLE_REG_1, val &
- ~SECOCEC_ENABLE_REG_1_CEC &
- ~SECOCEC_ENABLE_REG_1_IR);
-
- dev_dbg(dev, "Device disabled");
- }
-
- return 0;
-err:
- return status;
-}
-
-static int secocec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
-{
- u16 enable_val = 0;
- int status;
-
- /* Disable device */
- status = smb_rd16(SECOCEC_ENABLE_REG_1, &enable_val);
- if (status)
- return status;
-
- status = smb_wr16(SECOCEC_ENABLE_REG_1,
- enable_val & ~SECOCEC_ENABLE_REG_1_CEC);
- if (status)
- return status;
-
- /* Write logical address
- * NOTE: CEC_LOG_ADDR_INVALID is mapped to the 'Unregistered' LA
- */
- status = smb_wr16(SECOCEC_DEVICE_LA, logical_addr & 0xf);
- if (status)
- return status;
-
- /* Re-enable device */
- status = smb_wr16(SECOCEC_ENABLE_REG_1,
- enable_val | SECOCEC_ENABLE_REG_1_CEC);
- if (status)
- return status;
-
- return 0;
-}
-
-static int secocec_adap_transmit(struct cec_adapter *adap, u8 attempts,
- u32 signal_free_time, struct cec_msg *msg)
-{
- u16 payload_len, payload_id_len, destination, val = 0;
- u8 *payload_msg;
- int status;
- u8 i;
-
- /* Device msg len already accounts for header */
- payload_id_len = msg->len - 1;
-
- /* Send data length */
- status = smb_wr16(SECOCEC_WRITE_DATA_LENGTH, payload_id_len);
- if (status)
- goto err;
-
- /* Send Operation ID if present */
- if (payload_id_len > 0) {
- status = smb_wr16(SECOCEC_WRITE_OPERATION_ID, msg->msg[1]);
- if (status)
- goto err;
- }
- /* Send data if present */
- if (payload_id_len > 1) {
- /* Only data; */
- payload_len = msg->len - 2;
- payload_msg = &msg->msg[2];
-
- /* Copy message into registers */
- for (i = 0; i < payload_len; i += 2) {
- /* hi byte */
- val = payload_msg[i + 1] << 8;
-
- /* lo byte */
- val |= payload_msg[i];
-
- status = smb_wr16(SECOCEC_WRITE_DATA_00 + i / 2, val);
- if (status)
- goto err;
- }
- }
- /* Send msg source/destination and fire msg */
- destination = msg->msg[0];
- status = smb_wr16(SECOCEC_WRITE_BYTE0, destination);
- if (status)
- goto err;
-
- return 0;
-
-err:
- return status;
-}
-
-static void secocec_tx_done(struct cec_adapter *adap, u16 status_val)
-{
- if (status_val & SECOCEC_STATUS_TX_ERROR_MASK) {
- if (status_val & SECOCEC_STATUS_TX_NACK_ERROR)
- cec_transmit_attempt_done(adap, CEC_TX_STATUS_NACK);
- else
- cec_transmit_attempt_done(adap, CEC_TX_STATUS_ERROR);
- } else {
- cec_transmit_attempt_done(adap, CEC_TX_STATUS_OK);
- }
-
- /* Reset status reg */
- status_val = SECOCEC_STATUS_TX_ERROR_MASK |
- SECOCEC_STATUS_MSG_SENT_MASK |
- SECOCEC_STATUS_TX_NACK_ERROR;
- smb_wr16(SECOCEC_STATUS, status_val);
-}
-
-static void secocec_rx_done(struct cec_adapter *adap, u16 status_val)
-{
- struct secocec_data *cec = cec_get_drvdata(adap);
- struct device *dev = cec->dev;
- struct cec_msg msg = { };
- bool flag_overflow = false;
- u8 payload_len, i = 0;
- u8 *payload_msg;
- u16 val = 0;
- int status;
-
- if (status_val & SECOCEC_STATUS_RX_OVERFLOW_MASK) {
- /* NOTE: Untested, it also might not be necessary */
- dev_warn(dev, "Received more than 16 bytes. Discarding");
- flag_overflow = true;
- }
-
- if (status_val & SECOCEC_STATUS_RX_ERROR_MASK) {
- dev_warn(dev, "Message received with errors. Discarding");
- status = -EIO;
- goto rxerr;
- }
-
- /* Read message length */
- status = smb_rd16(SECOCEC_READ_DATA_LENGTH, &val);
- if (status)
- return;
-
- /* Device msg len already accounts for the header */
- msg.len = min(val + 1, CEC_MAX_MSG_SIZE);
-
- /* Read logical address */
- status = smb_rd16(SECOCEC_READ_BYTE0, &val);
- if (status)
- return;
-
- /* device stores source LA and destination */
- msg.msg[0] = val;
-
- /* Read operation ID */
- status = smb_rd16(SECOCEC_READ_OPERATION_ID, &val);
- if (status)
- return;
-
- msg.msg[1] = val;
-
- /* Read data if present */
- if (msg.len > 1) {
- payload_len = msg.len - 2;
- payload_msg = &msg.msg[2];
-
- /* device stores 2 bytes in every 16-bit val */
- for (i = 0; i < payload_len; i += 2) {
- status = smb_rd16(SECOCEC_READ_DATA_00 + i / 2, &val);
- if (status)
- return;
-
- /* low byte, skipping header */
- payload_msg[i] = val & 0x00ff;
-
- /* hi byte */
- payload_msg[i + 1] = (val & 0xff00) >> 8;
- }
- }
-
- cec_received_msg(cec->cec_adap, &msg);
-
- /* Reset status reg */
- status_val = SECOCEC_STATUS_MSG_RECEIVED_MASK;
- if (flag_overflow)
- status_val |= SECOCEC_STATUS_RX_OVERFLOW_MASK;
-
- status = smb_wr16(SECOCEC_STATUS, status_val);
-
- return;
-
-rxerr:
- /* Reset error reg */
- status_val = SECOCEC_STATUS_MSG_RECEIVED_MASK |
- SECOCEC_STATUS_RX_ERROR_MASK;
- if (flag_overflow)
- status_val |= SECOCEC_STATUS_RX_OVERFLOW_MASK;
- smb_wr16(SECOCEC_STATUS, status_val);
-}
-
-static const struct cec_adap_ops secocec_cec_adap_ops = {
- /* Low-level callbacks */
- .adap_enable = secocec_adap_enable,
- .adap_log_addr = secocec_adap_log_addr,
- .adap_transmit = secocec_adap_transmit,
-};
-
-#ifdef CONFIG_VIDEO_SECO_RC
-static int secocec_ir_probe(void *priv)
-{
- struct secocec_data *cec = priv;
- struct device *dev = cec->dev;
- int status;
- u16 val;
-
- /* Prepare the RC input device */
- cec->ir = devm_rc_allocate_device(dev, RC_DRIVER_SCANCODE);
- if (!cec->ir)
- return -ENOMEM;
-
- snprintf(cec->ir_input_phys, sizeof(cec->ir_input_phys),
- "%s/input0", dev_name(dev));
-
- cec->ir->device_name = dev_name(dev);
- cec->ir->input_phys = cec->ir_input_phys;
- cec->ir->input_id.bustype = BUS_HOST;
- cec->ir->input_id.vendor = 0;
- cec->ir->input_id.product = 0;
- cec->ir->input_id.version = 1;
- cec->ir->driver_name = SECOCEC_DEV_NAME;
- cec->ir->allowed_protocols = RC_PROTO_BIT_RC5;
- cec->ir->priv = cec;
- cec->ir->map_name = RC_MAP_HAUPPAUGE;
- cec->ir->timeout = MS_TO_NS(100);
-
- /* Clear the status register */
- status = smb_rd16(SECOCEC_STATUS_REG_1, &val);
- if (status != 0)
- goto err;
-
- status = smb_wr16(SECOCEC_STATUS_REG_1, val);
- if (status != 0)
- goto err;
-
- /* Enable the interrupts */
- status = smb_rd16(SECOCEC_ENABLE_REG_1, &val);
- if (status != 0)
- goto err;
-
- status = smb_wr16(SECOCEC_ENABLE_REG_1,
- val | SECOCEC_ENABLE_REG_1_IR);
- if (status != 0)
- goto err;
-
- dev_dbg(dev, "IR enabled");
-
- status = devm_rc_register_device(dev, cec->ir);
-
- if (status) {
- dev_err(dev, "Failed to prepare input device");
- cec->ir = NULL;
- goto err;
- }
-
- return 0;
-
-err:
- smb_rd16(SECOCEC_ENABLE_REG_1, &val);
-
- smb_wr16(SECOCEC_ENABLE_REG_1,
- val & ~SECOCEC_ENABLE_REG_1_IR);
-
- dev_dbg(dev, "IR disabled");
- return status;
-}
-
-static int secocec_ir_rx(struct secocec_data *priv)
-{
- struct secocec_data *cec = priv;
- struct device *dev = cec->dev;
- u16 val, status, key, addr, toggle;
-
- if (!cec->ir)
- return -ENODEV;
-
- status = smb_rd16(SECOCEC_IR_READ_DATA, &val);
- if (status != 0)
- goto err;
-
- key = val & SECOCEC_IR_COMMAND_MASK;
- addr = (val & SECOCEC_IR_ADDRESS_MASK) >> SECOCEC_IR_ADDRESS_SHL;
- toggle = (val & SECOCEC_IR_TOGGLE_MASK) >> SECOCEC_IR_TOGGLE_SHL;
-
- rc_keydown(cec->ir, RC_PROTO_RC5, RC_SCANCODE_RC5(addr, key), toggle);
-
- dev_dbg(dev, "IR key pressed: 0x%02x addr 0x%02x toggle 0x%02x", key,
- addr, toggle);
-
- return 0;
-
-err:
- dev_err(dev, "IR Receive message failed (%d)", status);
- return -EIO;
-}
-#else
-static void secocec_ir_rx(struct secocec_data *priv)
-{
-}
-
-static int secocec_ir_probe(void *priv)
-{
- return 0;
-}
-#endif
-
-static irqreturn_t secocec_irq_handler(int irq, void *priv)
-{
- struct secocec_data *cec = priv;
- struct device *dev = cec->dev;
- u16 status_val, cec_val, val = 0;
- int status;
-
- /* Read status register */
- status = smb_rd16(SECOCEC_STATUS_REG_1, &status_val);
- if (status)
- goto err;
-
- if (status_val & SECOCEC_STATUS_REG_1_CEC) {
- /* Read CEC status register */
- status = smb_rd16(SECOCEC_STATUS, &cec_val);
- if (status)
- goto err;
-
- if (cec_val & SECOCEC_STATUS_MSG_RECEIVED_MASK)
- secocec_rx_done(cec->cec_adap, cec_val);
-
- if (cec_val & SECOCEC_STATUS_MSG_SENT_MASK)
- secocec_tx_done(cec->cec_adap, cec_val);
-
- if ((~cec_val & SECOCEC_STATUS_MSG_SENT_MASK) &&
- (~cec_val & SECOCEC_STATUS_MSG_RECEIVED_MASK))
- dev_warn_once(dev,
- "Message not received or sent, but interrupt fired");
-
- val = SECOCEC_STATUS_REG_1_CEC;
- }
-
- if (status_val & SECOCEC_STATUS_REG_1_IR) {
- val |= SECOCEC_STATUS_REG_1_IR;
-
- secocec_ir_rx(cec);
- }
-
- /* Reset status register */
- status = smb_wr16(SECOCEC_STATUS_REG_1, val);
- if (status)
- goto err;
-
- return IRQ_HANDLED;
-
-err:
- dev_err_once(dev, "IRQ: R/W SMBus operation failed (%d)", status);
-
- /* Reset status register */
- val = SECOCEC_STATUS_REG_1_CEC | SECOCEC_STATUS_REG_1_IR;
- smb_wr16(SECOCEC_STATUS_REG_1, val);
-
- return IRQ_HANDLED;
-}
-
-struct cec_dmi_match {
- const char *sys_vendor;
- const char *product_name;
- const char *devname;
- const char *conn;
-};
-
-static const struct cec_dmi_match secocec_dmi_match_table[] = {
- /* UDOO X86 */
- { "SECO", "UDOO x86", "0000:00:02.0", "Port B" },
-};
-
-static struct device *secocec_cec_find_hdmi_dev(struct device *dev,
- const char **conn)
-{
- int i;
-
- for (i = 0 ; i < ARRAY_SIZE(secocec_dmi_match_table) ; ++i) {
- const struct cec_dmi_match *m = &secocec_dmi_match_table[i];
-
- if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) &&
- dmi_match(DMI_PRODUCT_NAME, m->product_name)) {
- struct device *d;
-
- /* Find the device, bail out if not yet registered */
- d = bus_find_device_by_name(&pci_bus_type, NULL,
- m->devname);
- if (!d)
- return ERR_PTR(-EPROBE_DEFER);
-
- put_device(d);
- *conn = m->conn;
- return d;
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
-static int secocec_acpi_probe(struct secocec_data *sdev)
-{
- struct device *dev = sdev->dev;
- struct gpio_desc *gpio;
- int irq = 0;
-
- gpio = devm_gpiod_get(dev, NULL, GPIOF_IN);
- if (IS_ERR(gpio)) {
- dev_err(dev, "Cannot request interrupt gpio");
- return PTR_ERR(gpio);
- }
-
- irq = gpiod_to_irq(gpio);
- if (irq < 0) {
- dev_err(dev, "Cannot find valid irq");
- return -ENODEV;
- }
- dev_dbg(dev, "irq-gpio is bound to IRQ %d", irq);
-
- sdev->irq = irq;
-
- return 0;
-}
-
-static int secocec_probe(struct platform_device *pdev)
-{
- struct secocec_data *secocec;
- struct device *dev = &pdev->dev;
- struct device *hdmi_dev;
- const char *conn = NULL;
- int ret;
- u16 val;
-
- hdmi_dev = secocec_cec_find_hdmi_dev(&pdev->dev, &conn);
- if (IS_ERR(hdmi_dev))
- return PTR_ERR(hdmi_dev);
-
- secocec = devm_kzalloc(dev, sizeof(*secocec), GFP_KERNEL);
- if (!secocec)
- return -ENOMEM;
-
- dev_set_drvdata(dev, secocec);
-
- /* Request SMBus regions */
- if (!request_muxed_region(BRA_SMB_BASE_ADDR, 7, "CEC00001")) {
- dev_err(dev, "Request memory region failed");
- return -ENXIO;
- }
-
- secocec->pdev = pdev;
- secocec->dev = dev;
-
- if (!has_acpi_companion(dev)) {
- dev_dbg(dev, "Cannot find any ACPI companion");
- ret = -ENODEV;
- goto err;
- }
-
- ret = secocec_acpi_probe(secocec);
- if (ret) {
- dev_err(dev, "Cannot assign gpio to IRQ");
- ret = -ENODEV;
- goto err;
- }
-
- /* Firmware version check */
- ret = smb_rd16(SECOCEC_VERSION, &val);
- if (ret) {
- dev_err(dev, "Cannot check fw version");
- goto err;
- }
- if (val < SECOCEC_LATEST_FW) {
- dev_err(dev, "CEC Firmware not supported (v.%04x). Use ver > v.%04x",
- val, SECOCEC_LATEST_FW);
- ret = -EINVAL;
- goto err;
- }
-
- ret = devm_request_threaded_irq(dev,
- secocec->irq,
- NULL,
- secocec_irq_handler,
- IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- dev_name(&pdev->dev), secocec);
-
- if (ret) {
- dev_err(dev, "Cannot request IRQ %d", secocec->irq);
- ret = -EIO;
- goto err;
- }
-
- /* Allocate CEC adapter */
- secocec->cec_adap = cec_allocate_adapter(&secocec_cec_adap_ops,
- secocec,
- dev_name(dev),
- CEC_CAP_DEFAULTS |
- CEC_CAP_CONNECTOR_INFO,
- SECOCEC_MAX_ADDRS);
-
- if (IS_ERR(secocec->cec_adap)) {
- ret = PTR_ERR(secocec->cec_adap);
- goto err;
- }
-
- secocec->notifier = cec_notifier_cec_adap_register(hdmi_dev, conn,
- secocec->cec_adap);
- if (!secocec->notifier) {
- ret = -ENOMEM;
- goto err_delete_adapter;
- }
-
- ret = cec_register_adapter(secocec->cec_adap, dev);
- if (ret)
- goto err_notifier;
-
- ret = secocec_ir_probe(secocec);
- if (ret)
- goto err_notifier;
-
- platform_set_drvdata(pdev, secocec);
-
- dev_dbg(dev, "Device registered");
-
- return ret;
-
-err_notifier:
- cec_notifier_cec_adap_unregister(secocec->notifier, secocec->cec_adap);
-err_delete_adapter:
- cec_delete_adapter(secocec->cec_adap);
-err:
- release_region(BRA_SMB_BASE_ADDR, 7);
- dev_err(dev, "%s device probe failed\n", dev_name(dev));
-
- return ret;
-}
-
-static int secocec_remove(struct platform_device *pdev)
-{
- struct secocec_data *secocec = platform_get_drvdata(pdev);
- u16 val;
-
- if (secocec->ir) {
- smb_rd16(SECOCEC_ENABLE_REG_1, &val);
-
- smb_wr16(SECOCEC_ENABLE_REG_1, val & ~SECOCEC_ENABLE_REG_1_IR);
-
- dev_dbg(&pdev->dev, "IR disabled");
- }
- cec_notifier_cec_adap_unregister(secocec->notifier, secocec->cec_adap);
- cec_unregister_adapter(secocec->cec_adap);
-
- release_region(BRA_SMB_BASE_ADDR, 7);
-
- dev_dbg(&pdev->dev, "CEC device removed");
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int secocec_suspend(struct device *dev)
-{
- int status;
- u16 val;
-
- dev_dbg(dev, "Device going to suspend, disabling");
-
- /* Clear the status register */
- status = smb_rd16(SECOCEC_STATUS_REG_1, &val);
- if (status)
- goto err;
-
- status = smb_wr16(SECOCEC_STATUS_REG_1, val);
- if (status)
- goto err;
-
- /* Disable the interrupts */
- status = smb_rd16(SECOCEC_ENABLE_REG_1, &val);
- if (status)
- goto err;
-
- status = smb_wr16(SECOCEC_ENABLE_REG_1, val &
- ~SECOCEC_ENABLE_REG_1_CEC & ~SECOCEC_ENABLE_REG_1_IR);
- if (status)
- goto err;
-
- return 0;
-
-err:
- dev_err(dev, "Suspend failed (err: %d)", status);
- return status;
-}
-
-static int secocec_resume(struct device *dev)
-{
- int status;
- u16 val;
-
- dev_dbg(dev, "Resuming device from suspend");
-
- /* Clear the status register */
- status = smb_rd16(SECOCEC_STATUS_REG_1, &val);
- if (status)
- goto err;
-
- status = smb_wr16(SECOCEC_STATUS_REG_1, val);
- if (status)
- goto err;
-
- /* Enable the interrupts */
- status = smb_rd16(SECOCEC_ENABLE_REG_1, &val);
- if (status)
- goto err;
-
- status = smb_wr16(SECOCEC_ENABLE_REG_1, val | SECOCEC_ENABLE_REG_1_CEC);
- if (status)
- goto err;
-
- dev_dbg(dev, "Device resumed from suspend");
-
- return 0;
-
-err:
- dev_err(dev, "Resume failed (err: %d)", status);
- return status;
-}
-
-static SIMPLE_DEV_PM_OPS(secocec_pm_ops, secocec_suspend, secocec_resume);
-#define SECOCEC_PM_OPS (&secocec_pm_ops)
-#else
-#define SECOCEC_PM_OPS NULL
-#endif
-
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id secocec_acpi_match[] = {
- {"CEC00001", 0},
- {},
-};
-
-MODULE_DEVICE_TABLE(acpi, secocec_acpi_match);
-#endif
-
-static struct platform_driver secocec_driver = {
- .driver = {
- .name = SECOCEC_DEV_NAME,
- .acpi_match_table = ACPI_PTR(secocec_acpi_match),
- .pm = SECOCEC_PM_OPS,
- },
- .probe = secocec_probe,
- .remove = secocec_remove,
-};
-
-module_platform_driver(secocec_driver);
-
-MODULE_DESCRIPTION("SECO CEC X86 Driver");
-MODULE_AUTHOR("Ettore Chimenti <ek5.chimenti@gmail.com>");
-MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/media/platform/seco-cec/seco-cec.h b/drivers/media/platform/seco-cec/seco-cec.h
deleted file mode 100644
index 843de8c7dfd4..000000000000
--- a/drivers/media/platform/seco-cec/seco-cec.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/*
- * SECO X86 Boards CEC register defines
- *
- * Author: Ettore Chimenti <ek5.chimenti@gmail.com>
- * Copyright (C) 2018, SECO Spa.
- * Copyright (C) 2018, Aidilab Srl.
- */
-
-#ifndef __SECO_CEC_H__
-#define __SECO_CEC_H__
-
-#define SECOCEC_MAX_ADDRS 1
-#define SECOCEC_DEV_NAME "secocec"
-#define SECOCEC_LATEST_FW 0x0f0b
-
-#define SMBTIMEOUT 0xfff
-#define SMB_POLL_UDELAY 10
-
-#define SMBUS_WRITE 0
-#define SMBUS_READ 1
-
-#define CMD_BYTE_DATA 0
-#define CMD_WORD_DATA 1
-
-/*
- * SMBus definitons for Braswell
- */
-
-#define BRA_DONE_STATUS BIT(7)
-#define BRA_INUSE_STS BIT(6)
-#define BRA_FAILED_OP BIT(4)
-#define BRA_BUS_ERR BIT(3)
-#define BRA_DEV_ERR BIT(2)
-#define BRA_INTR BIT(1)
-#define BRA_HOST_BUSY BIT(0)
-#define BRA_HSTS_ERR_MASK (BRA_FAILED_OP | BRA_BUS_ERR | BRA_DEV_ERR)
-
-#define BRA_PEC_EN BIT(7)
-#define BRA_START BIT(6)
-#define BRA_LAST__BYTE BIT(5)
-#define BRA_INTREN BIT(0)
-#define BRA_SMB_CMD (7 << 2)
-#define BRA_SMB_CMD_QUICK (0 << 2)
-#define BRA_SMB_CMD_BYTE (1 << 2)
-#define BRA_SMB_CMD_BYTE_DATA (2 << 2)
-#define BRA_SMB_CMD_WORD_DATA (3 << 2)
-#define BRA_SMB_CMD_PROCESS_CALL (4 << 2)
-#define BRA_SMB_CMD_BLOCK (5 << 2)
-#define BRA_SMB_CMD_I2CREAD (6 << 2)
-#define BRA_SMB_CMD_BLOCK_PROCESS (7 << 2)
-
-#define BRA_SMB_BASE_ADDR 0x2040
-#define HSTS (BRA_SMB_BASE_ADDR + 0)
-#define HCNT (BRA_SMB_BASE_ADDR + 2)
-#define HCMD (BRA_SMB_BASE_ADDR + 3)
-#define XMIT_SLVA (BRA_SMB_BASE_ADDR + 4)
-#define HDAT0 (BRA_SMB_BASE_ADDR + 5)
-#define HDAT1 (BRA_SMB_BASE_ADDR + 6)
-
-/*
- * Microcontroller Address
- */
-
-#define SECOCEC_MICRO_ADDRESS 0x40
-
-/*
- * STM32 SMBus Registers
- */
-
-#define SECOCEC_VERSION 0x00
-#define SECOCEC_ENABLE_REG_1 0x01
-#define SECOCEC_ENABLE_REG_2 0x02
-#define SECOCEC_STATUS_REG_1 0x03
-#define SECOCEC_STATUS_REG_2 0x04
-
-#define SECOCEC_STATUS 0x28
-#define SECOCEC_DEVICE_LA 0x29
-#define SECOCEC_READ_OPERATION_ID 0x2a
-#define SECOCEC_READ_DATA_LENGTH 0x2b
-#define SECOCEC_READ_DATA_00 0x2c
-#define SECOCEC_READ_DATA_02 0x2d
-#define SECOCEC_READ_DATA_04 0x2e
-#define SECOCEC_READ_DATA_06 0x2f
-#define SECOCEC_READ_DATA_08 0x30
-#define SECOCEC_READ_DATA_10 0x31
-#define SECOCEC_READ_DATA_12 0x32
-#define SECOCEC_READ_BYTE0 0x33
-#define SECOCEC_WRITE_OPERATION_ID 0x34
-#define SECOCEC_WRITE_DATA_LENGTH 0x35
-#define SECOCEC_WRITE_DATA_00 0x36
-#define SECOCEC_WRITE_DATA_02 0x37
-#define SECOCEC_WRITE_DATA_04 0x38
-#define SECOCEC_WRITE_DATA_06 0x39
-#define SECOCEC_WRITE_DATA_08 0x3a
-#define SECOCEC_WRITE_DATA_10 0x3b
-#define SECOCEC_WRITE_DATA_12 0x3c
-#define SECOCEC_WRITE_BYTE0 0x3d
-
-#define SECOCEC_IR_READ_DATA 0x3e
-
-/*
- * IR
- */
-
-#define SECOCEC_IR_COMMAND_MASK 0x007F
-#define SECOCEC_IR_COMMAND_SHL 0
-#define SECOCEC_IR_ADDRESS_MASK 0x1F00
-#define SECOCEC_IR_ADDRESS_SHL 8
-#define SECOCEC_IR_TOGGLE_MASK 0x8000
-#define SECOCEC_IR_TOGGLE_SHL 15
-
-/*
- * Enabling register
- */
-
-#define SECOCEC_ENABLE_REG_1_CEC 0x1000
-#define SECOCEC_ENABLE_REG_1_IR 0x2000
-#define SECOCEC_ENABLE_REG_1_IR_PASSTHROUGH 0x4000
-
-/*
- * Status register
- */
-
-#define SECOCEC_STATUS_REG_1_CEC SECOCEC_ENABLE_REG_1_CEC
-#define SECOCEC_STATUS_REG_1_IR SECOCEC_ENABLE_REG_1_IR
-#define SECOCEC_STATUS_REG_1_IR_PASSTHR SECOCEC_ENABLE_REG_1_IR_PASSTHR
-
-/*
- * Status data
- */
-
-#define SECOCEC_STATUS_MSG_RECEIVED_MASK BIT(0)
-#define SECOCEC_STATUS_RX_ERROR_MASK BIT(1)
-#define SECOCEC_STATUS_MSG_SENT_MASK BIT(2)
-#define SECOCEC_STATUS_TX_ERROR_MASK BIT(3)
-
-#define SECOCEC_STATUS_TX_NACK_ERROR BIT(4)
-#define SECOCEC_STATUS_RX_OVERFLOW_MASK BIT(5)
-
-#endif /* __SECO_CEC_H__ */
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
deleted file mode 100644
index f08b8fc192d8..000000000000
--- a/drivers/media/platform/sh_veu.c
+++ /dev/null
@@ -1,1203 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * sh-mobile VEU mem2mem driver
- *
- * Copyright (C) 2012 Renesas Electronics Corporation
- * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
- * Copyright (C) 2008 Magnus Damm
- */
-
-#include <linux/err.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/videodev2.h>
-
-#include <media/v4l2-dev.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/v4l2-image-sizes.h>
-#include <media/videobuf2-dma-contig.h>
-
-#define VEU_STR 0x00 /* start register */
-#define VEU_SWR 0x10 /* src: line length */
-#define VEU_SSR 0x14 /* src: image size */
-#define VEU_SAYR 0x18 /* src: y/rgb plane address */
-#define VEU_SACR 0x1c /* src: c plane address */
-#define VEU_BSSR 0x20 /* bundle mode register */
-#define VEU_EDWR 0x30 /* dst: line length */
-#define VEU_DAYR 0x34 /* dst: y/rgb plane address */
-#define VEU_DACR 0x38 /* dst: c plane address */
-#define VEU_TRCR 0x50 /* transform control */
-#define VEU_RFCR 0x54 /* resize scale */
-#define VEU_RFSR 0x58 /* resize clip */
-#define VEU_ENHR 0x5c /* enhance */
-#define VEU_FMCR 0x70 /* filter mode */
-#define VEU_VTCR 0x74 /* lowpass vertical */
-#define VEU_HTCR 0x78 /* lowpass horizontal */
-#define VEU_APCR 0x80 /* color match */
-#define VEU_ECCR 0x84 /* color replace */
-#define VEU_AFXR 0x90 /* fixed mode */
-#define VEU_SWPR 0x94 /* swap */
-#define VEU_EIER 0xa0 /* interrupt mask */
-#define VEU_EVTR 0xa4 /* interrupt event */
-#define VEU_STAR 0xb0 /* status */
-#define VEU_BSRR 0xb4 /* reset */
-
-#define VEU_MCR00 0x200 /* color conversion matrix coefficient 00 */
-#define VEU_MCR01 0x204 /* color conversion matrix coefficient 01 */
-#define VEU_MCR02 0x208 /* color conversion matrix coefficient 02 */
-#define VEU_MCR10 0x20c /* color conversion matrix coefficient 10 */
-#define VEU_MCR11 0x210 /* color conversion matrix coefficient 11 */
-#define VEU_MCR12 0x214 /* color conversion matrix coefficient 12 */
-#define VEU_MCR20 0x218 /* color conversion matrix coefficient 20 */
-#define VEU_MCR21 0x21c /* color conversion matrix coefficient 21 */
-#define VEU_MCR22 0x220 /* color conversion matrix coefficient 22 */
-#define VEU_COFFR 0x224 /* color conversion offset */
-#define VEU_CBR 0x228 /* color conversion clip */
-
-/*
- * 4092x4092 max size is the normal case. In some cases it can be reduced to
- * 2048x2048, in other cases it can be 4092x8188 or even 8188x8188.
- */
-#define MAX_W 4092
-#define MAX_H 4092
-#define MIN_W 8
-#define MIN_H 8
-#define ALIGN_W 4
-
-/* 3 buffers of 2048 x 1536 - 3 megapixels @ 16bpp */
-#define VIDEO_MEM_LIMIT ALIGN(2048 * 1536 * 2 * 3, 1024 * 1024)
-
-#define MEM2MEM_DEF_TRANSLEN 1
-
-struct sh_veu_dev;
-
-struct sh_veu_file {
- struct v4l2_fh fh;
- struct sh_veu_dev *veu_dev;
- bool cfg_needed;
-};
-
-struct sh_veu_format {
- u32 fourcc;
- unsigned int depth;
- unsigned int ydepth;
-};
-
-/* video data format */
-struct sh_veu_vfmt {
- /* Replace with v4l2_rect */
- struct v4l2_rect frame;
- unsigned int bytesperline;
- unsigned int offset_y;
- unsigned int offset_c;
- const struct sh_veu_format *fmt;
-};
-
-struct sh_veu_dev {
- struct v4l2_device v4l2_dev;
- struct video_device vdev;
- struct v4l2_m2m_dev *m2m_dev;
- struct device *dev;
- struct v4l2_m2m_ctx *m2m_ctx;
- struct sh_veu_vfmt vfmt_out;
- struct sh_veu_vfmt vfmt_in;
- /* Only single user per direction so far */
- struct sh_veu_file *capture;
- struct sh_veu_file *output;
- struct mutex fop_lock;
- void __iomem *base;
- spinlock_t lock;
- bool is_2h;
- unsigned int xaction;
- bool aborting;
-};
-
-enum sh_veu_fmt_idx {
- SH_VEU_FMT_NV12,
- SH_VEU_FMT_NV16,
- SH_VEU_FMT_NV24,
- SH_VEU_FMT_RGB332,
- SH_VEU_FMT_RGB444,
- SH_VEU_FMT_RGB565,
- SH_VEU_FMT_RGB666,
- SH_VEU_FMT_RGB24,
-};
-
-#define DEFAULT_IN_WIDTH VGA_WIDTH
-#define DEFAULT_IN_HEIGHT VGA_HEIGHT
-#define DEFAULT_IN_FMTIDX SH_VEU_FMT_NV12
-#define DEFAULT_OUT_WIDTH VGA_WIDTH
-#define DEFAULT_OUT_HEIGHT VGA_HEIGHT
-#define DEFAULT_OUT_FMTIDX SH_VEU_FMT_RGB565
-
-/*
- * Alignment: Y-plane should be 4-byte aligned for NV12 and NV16, and 8-byte
- * aligned for NV24.
- */
-static const struct sh_veu_format sh_veu_fmt[] = {
- [SH_VEU_FMT_NV12] = { .ydepth = 8, .depth = 12, .fourcc = V4L2_PIX_FMT_NV12 },
- [SH_VEU_FMT_NV16] = { .ydepth = 8, .depth = 16, .fourcc = V4L2_PIX_FMT_NV16 },
- [SH_VEU_FMT_NV24] = { .ydepth = 8, .depth = 24, .fourcc = V4L2_PIX_FMT_NV24 },
- [SH_VEU_FMT_RGB332] = { .ydepth = 8, .depth = 8, .fourcc = V4L2_PIX_FMT_RGB332 },
- [SH_VEU_FMT_RGB444] = { .ydepth = 16, .depth = 16, .fourcc = V4L2_PIX_FMT_RGB444 },
- [SH_VEU_FMT_RGB565] = { .ydepth = 16, .depth = 16, .fourcc = V4L2_PIX_FMT_RGB565 },
- [SH_VEU_FMT_RGB666] = { .ydepth = 32, .depth = 32, .fourcc = V4L2_PIX_FMT_BGR666 },
- [SH_VEU_FMT_RGB24] = { .ydepth = 24, .depth = 24, .fourcc = V4L2_PIX_FMT_RGB24 },
-};
-
-#define DEFAULT_IN_VFMT (struct sh_veu_vfmt){ \
- .frame = { \
- .width = VGA_WIDTH, \
- .height = VGA_HEIGHT, \
- }, \
- .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_IN_FMTIDX].ydepth) >> 3, \
- .fmt = &sh_veu_fmt[DEFAULT_IN_FMTIDX], \
-}
-
-#define DEFAULT_OUT_VFMT (struct sh_veu_vfmt){ \
- .frame = { \
- .width = VGA_WIDTH, \
- .height = VGA_HEIGHT, \
- }, \
- .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_OUT_FMTIDX].ydepth) >> 3, \
- .fmt = &sh_veu_fmt[DEFAULT_OUT_FMTIDX], \
-}
-
-/*
- * TODO: add support for further output formats:
- * SH_VEU_FMT_NV12,
- * SH_VEU_FMT_NV16,
- * SH_VEU_FMT_NV24,
- * SH_VEU_FMT_RGB332,
- * SH_VEU_FMT_RGB444,
- * SH_VEU_FMT_RGB666,
- * SH_VEU_FMT_RGB24,
- */
-
-static const int sh_veu_fmt_out[] = {
- SH_VEU_FMT_RGB565,
-};
-
-/*
- * TODO: add support for further input formats:
- * SH_VEU_FMT_NV16,
- * SH_VEU_FMT_NV24,
- * SH_VEU_FMT_RGB565,
- * SH_VEU_FMT_RGB666,
- * SH_VEU_FMT_RGB24,
- */
-static const int sh_veu_fmt_in[] = {
- SH_VEU_FMT_NV12,
-};
-
-static enum v4l2_colorspace sh_veu_4cc2cspace(u32 fourcc)
-{
- switch (fourcc) {
- default:
- BUG();
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV24:
- return V4L2_COLORSPACE_SMPTE170M;
- case V4L2_PIX_FMT_RGB332:
- case V4L2_PIX_FMT_RGB444:
- case V4L2_PIX_FMT_RGB565:
- case V4L2_PIX_FMT_BGR666:
- case V4L2_PIX_FMT_RGB24:
- return V4L2_COLORSPACE_SRGB;
- }
-}
-
-static u32 sh_veu_reg_read(struct sh_veu_dev *veu, unsigned int reg)
-{
- return ioread32(veu->base + reg);
-}
-
-static void sh_veu_reg_write(struct sh_veu_dev *veu, unsigned int reg,
- u32 value)
-{
- iowrite32(value, veu->base + reg);
-}
-
- /* ========== mem2mem callbacks ========== */
-
-static void sh_veu_job_abort(void *priv)
-{
- struct sh_veu_dev *veu = priv;
-
- /* Will cancel the transaction in the next interrupt handler */
- veu->aborting = true;
-}
-
-static void sh_veu_process(struct sh_veu_dev *veu,
- struct vb2_buffer *src_buf,
- struct vb2_buffer *dst_buf)
-{
- dma_addr_t addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
-
- sh_veu_reg_write(veu, VEU_DAYR, addr + veu->vfmt_out.offset_y);
- sh_veu_reg_write(veu, VEU_DACR, veu->vfmt_out.offset_c ?
- addr + veu->vfmt_out.offset_c : 0);
- dev_dbg(veu->dev, "%s(): dst base %lx, y: %x, c: %x\n", __func__,
- (unsigned long)addr,
- veu->vfmt_out.offset_y, veu->vfmt_out.offset_c);
-
- addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
- sh_veu_reg_write(veu, VEU_SAYR, addr + veu->vfmt_in.offset_y);
- sh_veu_reg_write(veu, VEU_SACR, veu->vfmt_in.offset_c ?
- addr + veu->vfmt_in.offset_c : 0);
- dev_dbg(veu->dev, "%s(): src base %lx, y: %x, c: %x\n", __func__,
- (unsigned long)addr,
- veu->vfmt_in.offset_y, veu->vfmt_in.offset_c);
-
- sh_veu_reg_write(veu, VEU_STR, 1);
-
- sh_veu_reg_write(veu, VEU_EIER, 1); /* enable interrupt in VEU */
-}
-
-/*
- * sh_veu_device_run() - prepares and starts the device
- *
- * This will be called by the framework when it decides to schedule a particular
- * instance.
- */
-static void sh_veu_device_run(void *priv)
-{
- struct sh_veu_dev *veu = priv;
- struct vb2_v4l2_buffer *src_buf, *dst_buf;
-
- src_buf = v4l2_m2m_next_src_buf(veu->m2m_ctx);
- dst_buf = v4l2_m2m_next_dst_buf(veu->m2m_ctx);
-
- if (src_buf && dst_buf)
- sh_veu_process(veu, &src_buf->vb2_buf, &dst_buf->vb2_buf);
-}
-
- /* ========== video ioctls ========== */
-
-static bool sh_veu_is_streamer(struct sh_veu_dev *veu, struct sh_veu_file *veu_file,
- enum v4l2_buf_type type)
-{
- return (type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
- veu_file == veu->capture) ||
- (type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
- veu_file == veu->output);
-}
-
-static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq,
- struct vb2_queue *dst_vq);
-
-/*
- * It is not unusual to have video nodes open()ed multiple times. While some
- * V4L2 operations are non-intrusive, like querying formats and various
- * parameters, others, like setting formats, starting and stopping streaming,
- * queuing and dequeuing buffers, directly affect hardware configuration and /
- * or execution. This function verifies availability of the requested interface
- * and, if available, reserves it for the requesting user.
- */
-static int sh_veu_stream_init(struct sh_veu_dev *veu, struct sh_veu_file *veu_file,
- enum v4l2_buf_type type)
-{
- struct sh_veu_file **stream;
-
- switch (type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- stream = &veu->capture;
- break;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- stream = &veu->output;
- break;
- default:
- return -EINVAL;
- }
-
- if (*stream == veu_file)
- return 0;
-
- if (*stream)
- return -EBUSY;
-
- *stream = veu_file;
-
- return 0;
-}
-
-static int sh_veu_context_init(struct sh_veu_dev *veu)
-{
- if (veu->m2m_ctx)
- return 0;
-
- veu->m2m_ctx = v4l2_m2m_ctx_init(veu->m2m_dev, veu,
- sh_veu_queue_init);
-
- return PTR_ERR_OR_ZERO(veu->m2m_ctx);
-}
-
-static int sh_veu_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- strscpy(cap->driver, "sh-veu", sizeof(cap->driver));
- strscpy(cap->card, "sh-mobile VEU", sizeof(cap->card));
- strscpy(cap->bus_info, "platform:sh-veu", sizeof(cap->bus_info));
- return 0;
-}
-
-static int sh_veu_enum_fmt(struct v4l2_fmtdesc *f, const int *fmt, int fmt_num)
-{
- if (f->index >= fmt_num)
- return -EINVAL;
-
- f->pixelformat = sh_veu_fmt[fmt[f->index]].fourcc;
- return 0;
-}
-
-static int sh_veu_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- return sh_veu_enum_fmt(f, sh_veu_fmt_out, ARRAY_SIZE(sh_veu_fmt_out));
-}
-
-static int sh_veu_enum_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- return sh_veu_enum_fmt(f, sh_veu_fmt_in, ARRAY_SIZE(sh_veu_fmt_in));
-}
-
-static struct sh_veu_vfmt *sh_veu_get_vfmt(struct sh_veu_dev *veu,
- enum v4l2_buf_type type)
-{
- switch (type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- return &veu->vfmt_out;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- return &veu->vfmt_in;
- default:
- return NULL;
- }
-}
-
-static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
-{
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct sh_veu_dev *veu = veu_file->veu_dev;
- struct sh_veu_vfmt *vfmt;
-
- vfmt = sh_veu_get_vfmt(veu, f->type);
-
- pix->width = vfmt->frame.width;
- pix->height = vfmt->frame.height;
- pix->field = V4L2_FIELD_NONE;
- pix->pixelformat = vfmt->fmt->fourcc;
- pix->colorspace = sh_veu_4cc2cspace(pix->pixelformat);
- pix->bytesperline = vfmt->bytesperline;
- pix->sizeimage = vfmt->bytesperline * pix->height *
- vfmt->fmt->depth / vfmt->fmt->ydepth;
- dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__,
- f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat);
-
- return 0;
-}
-
-static int sh_veu_g_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- return sh_veu_g_fmt(priv, f);
-}
-
-static int sh_veu_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- return sh_veu_g_fmt(priv, f);
-}
-
-static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt)
-{
- struct v4l2_pix_format *pix = &f->fmt.pix;
- unsigned int y_bytes_used;
-
- /*
- * V4L2 specification suggests, that the driver should correct the
- * format struct if any of the dimensions is unsupported
- */
- switch (pix->field) {
- default:
- case V4L2_FIELD_ANY:
- pix->field = V4L2_FIELD_NONE;
- /* fall through: continue handling V4L2_FIELD_NONE */
- case V4L2_FIELD_NONE:
- break;
- }
-
- v4l_bound_align_image(&pix->width, MIN_W, MAX_W, ALIGN_W,
- &pix->height, MIN_H, MAX_H, 0, 0);
-
- y_bytes_used = (pix->width * fmt->ydepth) >> 3;
-
- if (pix->bytesperline < y_bytes_used)
- pix->bytesperline = y_bytes_used;
- pix->sizeimage = pix->height * pix->bytesperline * fmt->depth / fmt->ydepth;
-
- pix->pixelformat = fmt->fourcc;
- pix->colorspace = sh_veu_4cc2cspace(pix->pixelformat);
-
- pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage);
-
- return 0;
-}
-
-static const struct sh_veu_format *sh_veu_find_fmt(const struct v4l2_format *f)
-{
- const int *fmt;
- int i, n, dflt;
-
- pr_debug("%s(%d;%d)\n", __func__, f->type, f->fmt.pix.field);
-
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- fmt = sh_veu_fmt_out;
- n = ARRAY_SIZE(sh_veu_fmt_out);
- dflt = DEFAULT_OUT_FMTIDX;
- break;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- default:
- fmt = sh_veu_fmt_in;
- n = ARRAY_SIZE(sh_veu_fmt_in);
- dflt = DEFAULT_IN_FMTIDX;
- break;
- }
-
- for (i = 0; i < n; i++)
- if (sh_veu_fmt[fmt[i]].fourcc == f->fmt.pix.pixelformat)
- return &sh_veu_fmt[fmt[i]];
-
- return &sh_veu_fmt[dflt];
-}
-
-static int sh_veu_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- const struct sh_veu_format *fmt;
-
- fmt = sh_veu_find_fmt(f);
-
- return sh_veu_try_fmt(f, fmt);
-}
-
-static int sh_veu_try_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- const struct sh_veu_format *fmt;
-
- fmt = sh_veu_find_fmt(f);
-
- return sh_veu_try_fmt(f, fmt);
-}
-
-static void sh_veu_colour_offset(struct sh_veu_dev *veu, struct sh_veu_vfmt *vfmt)
-{
- /* dst_left and dst_top validity will be verified in CROP / COMPOSE */
- unsigned int left = vfmt->frame.left & ~0x03;
- unsigned int top = vfmt->frame.top;
- dma_addr_t offset = (dma_addr_t)top * veu->vfmt_out.bytesperline +
- (((dma_addr_t)left * veu->vfmt_out.fmt->depth) >> 3);
- unsigned int y_line;
-
- vfmt->offset_y = offset;
-
- switch (vfmt->fmt->fourcc) {
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV24:
- y_line = ALIGN(vfmt->frame.width, 16);
- vfmt->offset_c = offset + y_line * vfmt->frame.height;
- break;
- case V4L2_PIX_FMT_RGB332:
- case V4L2_PIX_FMT_RGB444:
- case V4L2_PIX_FMT_RGB565:
- case V4L2_PIX_FMT_BGR666:
- case V4L2_PIX_FMT_RGB24:
- vfmt->offset_c = 0;
- break;
- default:
- BUG();
- }
-}
-
-static int sh_veu_s_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
-{
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct sh_veu_dev *veu = veu_file->veu_dev;
- struct sh_veu_vfmt *vfmt;
- struct vb2_queue *vq;
- int ret = sh_veu_context_init(veu);
- if (ret < 0)
- return ret;
-
- vq = v4l2_m2m_get_vq(veu->m2m_ctx, f->type);
- if (!vq)
- return -EINVAL;
-
- if (vb2_is_busy(vq)) {
- v4l2_err(&veu_file->veu_dev->v4l2_dev, "%s queue busy\n", __func__);
- return -EBUSY;
- }
-
- vfmt = sh_veu_get_vfmt(veu, f->type);
- /* called after try_fmt(), hence vfmt != NULL. Implicit BUG_ON() below */
-
- vfmt->fmt = sh_veu_find_fmt(f);
- /* vfmt->fmt != NULL following the same argument as above */
- vfmt->frame.width = pix->width;
- vfmt->frame.height = pix->height;
- vfmt->bytesperline = pix->bytesperline;
-
- sh_veu_colour_offset(veu, vfmt);
-
- /*
- * We could also verify and require configuration only if any parameters
- * actually have changed, but it is unlikely, that the user requests the
- * same configuration several times without closing the device.
- */
- veu_file->cfg_needed = true;
-
- dev_dbg(veu->dev,
- "Setting format for type %d, wxh: %dx%d, fmt: %x\n",
- f->type, pix->width, pix->height, vfmt->fmt->fourcc);
-
- return 0;
-}
-
-static int sh_veu_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- int ret = sh_veu_try_fmt_vid_cap(file, priv, f);
- if (ret)
- return ret;
-
- return sh_veu_s_fmt(priv, f);
-}
-
-static int sh_veu_s_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- int ret = sh_veu_try_fmt_vid_out(file, priv, f);
- if (ret)
- return ret;
-
- return sh_veu_s_fmt(priv, f);
-}
-
-static int sh_veu_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *reqbufs)
-{
- struct sh_veu_file *veu_file = priv;
- struct sh_veu_dev *veu = veu_file->veu_dev;
- int ret = sh_veu_context_init(veu);
- if (ret < 0)
- return ret;
-
- ret = sh_veu_stream_init(veu, veu_file, reqbufs->type);
- if (ret < 0)
- return ret;
-
- return v4l2_m2m_reqbufs(file, veu->m2m_ctx, reqbufs);
-}
-
-static int sh_veu_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *buf)
-{
- struct sh_veu_file *veu_file = priv;
-
- if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type))
- return -EBUSY;
-
- return v4l2_m2m_querybuf(file, veu_file->veu_dev->m2m_ctx, buf);
-}
-
-static int sh_veu_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
- struct sh_veu_file *veu_file = priv;
-
- dev_dbg(veu_file->veu_dev->dev, "%s(%d)\n", __func__, buf->type);
- if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type))
- return -EBUSY;
-
- return v4l2_m2m_qbuf(file, veu_file->veu_dev->m2m_ctx, buf);
-}
-
-static int sh_veu_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
- struct sh_veu_file *veu_file = priv;
-
- dev_dbg(veu_file->veu_dev->dev, "%s(%d)\n", __func__, buf->type);
- if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type))
- return -EBUSY;
-
- return v4l2_m2m_dqbuf(file, veu_file->veu_dev->m2m_ctx, buf);
-}
-
-static void sh_veu_calc_scale(struct sh_veu_dev *veu,
- int size_in, int size_out, int crop_out,
- u32 *mant, u32 *frac, u32 *rep)
-{
- u32 fixpoint;
-
- /* calculate FRAC and MANT */
- *rep = *mant = *frac = 0;
-
- if (size_in == size_out) {
- if (crop_out != size_out)
- *mant = 1; /* needed for cropping */
- return;
- }
-
- /* VEU2H special upscale */
- if (veu->is_2h && size_out > size_in) {
- u32 fixpoint = (4096 * size_in) / size_out;
- *mant = fixpoint / 4096;
- *frac = (fixpoint - (*mant * 4096)) & ~0x07;
-
- switch (*frac) {
- case 0x800:
- *rep = 1;
- break;
- case 0x400:
- *rep = 3;
- break;
- case 0x200:
- *rep = 7;
- break;
- }
- if (*rep)
- return;
- }
-
- fixpoint = (4096 * (size_in - 1)) / (size_out + 1);
- *mant = fixpoint / 4096;
- *frac = fixpoint - (*mant * 4096);
-
- if (*frac & 0x07) {
- /*
- * FIXME: do we really have to round down twice in the
- * up-scaling case?
- */
- *frac &= ~0x07;
- if (size_out > size_in)
- *frac -= 8; /* round down if scaling up */
- else
- *frac += 8; /* round up if scaling down */
- }
-}
-
-static unsigned long sh_veu_scale_v(struct sh_veu_dev *veu,
- int size_in, int size_out, int crop_out)
-{
- u32 mant, frac, value, rep;
-
- sh_veu_calc_scale(veu, size_in, size_out, crop_out, &mant, &frac, &rep);
-
- /* set scale */
- value = (sh_veu_reg_read(veu, VEU_RFCR) & ~0xffff0000) |
- (((mant << 12) | frac) << 16);
-
- sh_veu_reg_write(veu, VEU_RFCR, value);
-
- /* set clip */
- value = (sh_veu_reg_read(veu, VEU_RFSR) & ~0xffff0000) |
- (((rep << 12) | crop_out) << 16);
-
- sh_veu_reg_write(veu, VEU_RFSR, value);
-
- return ALIGN((size_in * crop_out) / size_out, 4);
-}
-
-static unsigned long sh_veu_scale_h(struct sh_veu_dev *veu,
- int size_in, int size_out, int crop_out)
-{
- u32 mant, frac, value, rep;
-
- sh_veu_calc_scale(veu, size_in, size_out, crop_out, &mant, &frac, &rep);
-
- /* set scale */
- value = (sh_veu_reg_read(veu, VEU_RFCR) & ~0xffff) |
- (mant << 12) | frac;
-
- sh_veu_reg_write(veu, VEU_RFCR, value);
-
- /* set clip */
- value = (sh_veu_reg_read(veu, VEU_RFSR) & ~0xffff) |
- (rep << 12) | crop_out;
-
- sh_veu_reg_write(veu, VEU_RFSR, value);
-
- return ALIGN((size_in * crop_out) / size_out, 4);
-}
-
-static void sh_veu_configure(struct sh_veu_dev *veu)
-{
- u32 src_width, src_stride, src_height;
- u32 dst_width, dst_stride, dst_height;
- u32 real_w, real_h;
-
- /* reset VEU */
- sh_veu_reg_write(veu, VEU_BSRR, 0x100);
-
- src_width = veu->vfmt_in.frame.width;
- src_height = veu->vfmt_in.frame.height;
- src_stride = ALIGN(veu->vfmt_in.frame.width, 16);
-
- dst_width = real_w = veu->vfmt_out.frame.width;
- dst_height = real_h = veu->vfmt_out.frame.height;
- /* Datasheet is unclear - whether it's always number of bytes or not */
- dst_stride = veu->vfmt_out.bytesperline;
-
- /*
- * So far real_w == dst_width && real_h == dst_height, but it wasn't
- * necessarily the case in the original vidix driver, so, it may change
- * here in the future too.
- */
- src_width = sh_veu_scale_h(veu, src_width, real_w, dst_width);
- src_height = sh_veu_scale_v(veu, src_height, real_h, dst_height);
-
- sh_veu_reg_write(veu, VEU_SWR, src_stride);
- sh_veu_reg_write(veu, VEU_SSR, src_width | (src_height << 16));
- sh_veu_reg_write(veu, VEU_BSSR, 0); /* not using bundle mode */
-
- sh_veu_reg_write(veu, VEU_EDWR, dst_stride);
- sh_veu_reg_write(veu, VEU_DACR, 0); /* unused for RGB */
-
- sh_veu_reg_write(veu, VEU_SWPR, 0x67);
- sh_veu_reg_write(veu, VEU_TRCR, (6 << 16) | (0 << 14) | 2 | 4);
-
- if (veu->is_2h) {
- sh_veu_reg_write(veu, VEU_MCR00, 0x0cc5);
- sh_veu_reg_write(veu, VEU_MCR01, 0x0950);
- sh_veu_reg_write(veu, VEU_MCR02, 0x0000);
-
- sh_veu_reg_write(veu, VEU_MCR10, 0x397f);
- sh_veu_reg_write(veu, VEU_MCR11, 0x0950);
- sh_veu_reg_write(veu, VEU_MCR12, 0x3ccd);
-
- sh_veu_reg_write(veu, VEU_MCR20, 0x0000);
- sh_veu_reg_write(veu, VEU_MCR21, 0x0950);
- sh_veu_reg_write(veu, VEU_MCR22, 0x1023);
-
- sh_veu_reg_write(veu, VEU_COFFR, 0x00800010);
- }
-}
-
-static int sh_veu_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct sh_veu_file *veu_file = priv;
-
- if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, type))
- return -EBUSY;
-
- if (veu_file->cfg_needed) {
- struct sh_veu_dev *veu = veu_file->veu_dev;
- veu_file->cfg_needed = false;
- sh_veu_configure(veu_file->veu_dev);
- veu->xaction = 0;
- veu->aborting = false;
- }
-
- return v4l2_m2m_streamon(file, veu_file->veu_dev->m2m_ctx, type);
-}
-
-static int sh_veu_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct sh_veu_file *veu_file = priv;
-
- if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, type))
- return -EBUSY;
-
- return v4l2_m2m_streamoff(file, veu_file->veu_dev->m2m_ctx, type);
-}
-
-static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = {
- .vidioc_querycap = sh_veu_querycap,
-
- .vidioc_enum_fmt_vid_cap = sh_veu_enum_fmt_vid_cap,
- .vidioc_g_fmt_vid_cap = sh_veu_g_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = sh_veu_try_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = sh_veu_s_fmt_vid_cap,
-
- .vidioc_enum_fmt_vid_out = sh_veu_enum_fmt_vid_out,
- .vidioc_g_fmt_vid_out = sh_veu_g_fmt_vid_out,
- .vidioc_try_fmt_vid_out = sh_veu_try_fmt_vid_out,
- .vidioc_s_fmt_vid_out = sh_veu_s_fmt_vid_out,
-
- .vidioc_reqbufs = sh_veu_reqbufs,
- .vidioc_querybuf = sh_veu_querybuf,
-
- .vidioc_qbuf = sh_veu_qbuf,
- .vidioc_dqbuf = sh_veu_dqbuf,
-
- .vidioc_streamon = sh_veu_streamon,
- .vidioc_streamoff = sh_veu_streamoff,
-};
-
- /* ========== Queue operations ========== */
-
-static int sh_veu_queue_setup(struct vb2_queue *vq,
- unsigned int *nbuffers, unsigned int *nplanes,
- unsigned int sizes[], struct device *alloc_devs[])
-{
- struct sh_veu_dev *veu = vb2_get_drv_priv(vq);
- struct sh_veu_vfmt *vfmt = sh_veu_get_vfmt(veu, vq->type);
- unsigned int count = *nbuffers;
- unsigned int size = vfmt->bytesperline * vfmt->frame.height *
- vfmt->fmt->depth / vfmt->fmt->ydepth;
-
- if (count < 2)
- *nbuffers = count = 2;
-
- if (size * count > VIDEO_MEM_LIMIT) {
- count = VIDEO_MEM_LIMIT / size;
- *nbuffers = count;
- }
-
- if (*nplanes)
- return sizes[0] < size ? -EINVAL : 0;
-
- *nplanes = 1;
- sizes[0] = size;
-
- dev_dbg(veu->dev, "get %d buffer(s) of size %d each.\n", count, size);
-
- return 0;
-}
-
-static int sh_veu_buf_prepare(struct vb2_buffer *vb)
-{
- struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue);
- struct sh_veu_vfmt *vfmt;
- unsigned int sizeimage;
-
- vfmt = sh_veu_get_vfmt(veu, vb->vb2_queue->type);
- sizeimage = vfmt->bytesperline * vfmt->frame.height *
- vfmt->fmt->depth / vfmt->fmt->ydepth;
-
- if (vb2_plane_size(vb, 0) < sizeimage) {
- dev_dbg(veu->dev, "%s data will not fit into plane (%lu < %u)\n",
- __func__, vb2_plane_size(vb, 0), sizeimage);
- return -EINVAL;
- }
-
- vb2_set_plane_payload(vb, 0, sizeimage);
-
- return 0;
-}
-
-static void sh_veu_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue);
- dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->type);
- v4l2_m2m_buf_queue(veu->m2m_ctx, vbuf);
-}
-
-static const struct vb2_ops sh_veu_qops = {
- .queue_setup = sh_veu_queue_setup,
- .buf_prepare = sh_veu_buf_prepare,
- .buf_queue = sh_veu_buf_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq,
- struct vb2_queue *dst_vq)
-{
- struct sh_veu_dev *veu = priv;
- int ret;
-
- memset(src_vq, 0, sizeof(*src_vq));
- src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
- src_vq->drv_priv = veu;
- src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
- src_vq->ops = &sh_veu_qops;
- src_vq->mem_ops = &vb2_dma_contig_memops;
- src_vq->lock = &veu->fop_lock;
- src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- src_vq->dev = veu->v4l2_dev.dev;
-
- ret = vb2_queue_init(src_vq);
- if (ret < 0)
- return ret;
-
- memset(dst_vq, 0, sizeof(*dst_vq));
- dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
- dst_vq->drv_priv = veu;
- dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
- dst_vq->ops = &sh_veu_qops;
- dst_vq->mem_ops = &vb2_dma_contig_memops;
- dst_vq->lock = &veu->fop_lock;
- dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- dst_vq->dev = veu->v4l2_dev.dev;
-
- return vb2_queue_init(dst_vq);
-}
-
- /* ========== File operations ========== */
-
-static int sh_veu_open(struct file *file)
-{
- struct sh_veu_dev *veu = video_drvdata(file);
- struct sh_veu_file *veu_file;
-
- veu_file = kzalloc(sizeof(*veu_file), GFP_KERNEL);
- if (!veu_file)
- return -ENOMEM;
-
- v4l2_fh_init(&veu_file->fh, video_devdata(file));
- veu_file->veu_dev = veu;
- veu_file->cfg_needed = true;
-
- file->private_data = veu_file;
-
- pm_runtime_get_sync(veu->dev);
- v4l2_fh_add(&veu_file->fh);
-
- dev_dbg(veu->dev, "Created instance %p\n", veu_file);
-
- return 0;
-}
-
-static int sh_veu_release(struct file *file)
-{
- struct sh_veu_dev *veu = video_drvdata(file);
- struct sh_veu_file *veu_file = file->private_data;
-
- dev_dbg(veu->dev, "Releasing instance %p\n", veu_file);
-
- if (veu_file == veu->capture) {
- veu->capture = NULL;
- vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE));
- }
-
- if (veu_file == veu->output) {
- veu->output = NULL;
- vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT));
- }
-
- if (!veu->output && !veu->capture && veu->m2m_ctx) {
- v4l2_m2m_ctx_release(veu->m2m_ctx);
- veu->m2m_ctx = NULL;
- }
-
- pm_runtime_put(veu->dev);
- v4l2_fh_del(&veu_file->fh);
- v4l2_fh_exit(&veu_file->fh);
-
- kfree(veu_file);
-
- return 0;
-}
-
-static __poll_t sh_veu_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- struct sh_veu_file *veu_file = file->private_data;
-
- return v4l2_m2m_poll(file, veu_file->veu_dev->m2m_ctx, wait);
-}
-
-static int sh_veu_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct sh_veu_file *veu_file = file->private_data;
-
- return v4l2_m2m_mmap(file, veu_file->veu_dev->m2m_ctx, vma);
-}
-
-static const struct v4l2_file_operations sh_veu_fops = {
- .owner = THIS_MODULE,
- .open = sh_veu_open,
- .release = sh_veu_release,
- .poll = sh_veu_poll,
- .unlocked_ioctl = video_ioctl2,
- .mmap = sh_veu_mmap,
-};
-
-static const struct video_device sh_veu_videodev = {
- .name = "sh-veu",
- .fops = &sh_veu_fops,
- .ioctl_ops = &sh_veu_ioctl_ops,
- .minor = -1,
- .release = video_device_release_empty,
- .vfl_dir = VFL_DIR_M2M,
- .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
-};
-
-static const struct v4l2_m2m_ops sh_veu_m2m_ops = {
- .device_run = sh_veu_device_run,
- .job_abort = sh_veu_job_abort,
-};
-
-static irqreturn_t sh_veu_bh(int irq, void *dev_id)
-{
- struct sh_veu_dev *veu = dev_id;
-
- if (veu->xaction == MEM2MEM_DEF_TRANSLEN || veu->aborting) {
- v4l2_m2m_job_finish(veu->m2m_dev, veu->m2m_ctx);
- veu->xaction = 0;
- } else {
- sh_veu_device_run(veu);
- }
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t sh_veu_isr(int irq, void *dev_id)
-{
- struct sh_veu_dev *veu = dev_id;
- struct vb2_v4l2_buffer *dst;
- struct vb2_v4l2_buffer *src;
- u32 status = sh_veu_reg_read(veu, VEU_EVTR);
-
- /* bundle read mode not used */
- if (!(status & 1))
- return IRQ_NONE;
-
- /* disable interrupt in VEU */
- sh_veu_reg_write(veu, VEU_EIER, 0);
- /* halt operation */
- sh_veu_reg_write(veu, VEU_STR, 0);
- /* ack int, write 0 to clear bits */
- sh_veu_reg_write(veu, VEU_EVTR, status & ~1);
-
- /* conversion completed */
- dst = v4l2_m2m_dst_buf_remove(veu->m2m_ctx);
- src = v4l2_m2m_src_buf_remove(veu->m2m_ctx);
- if (!src || !dst)
- return IRQ_NONE;
-
- dst->vb2_buf.timestamp = src->vb2_buf.timestamp;
- dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst->flags |=
- src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- dst->timecode = src->timecode;
-
- spin_lock(&veu->lock);
- v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
- v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
- spin_unlock(&veu->lock);
-
- veu->xaction++;
-
- return IRQ_WAKE_THREAD;
-}
-
-static int sh_veu_probe(struct platform_device *pdev)
-{
- struct sh_veu_dev *veu;
- struct resource *reg_res;
- struct video_device *vdev;
- int irq, ret;
-
- reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
-
- if (!reg_res || irq <= 0) {
- dev_err(&pdev->dev, "Insufficient VEU platform information.\n");
- return -ENODEV;
- }
-
- veu = devm_kzalloc(&pdev->dev, sizeof(*veu), GFP_KERNEL);
- if (!veu)
- return -ENOMEM;
-
- veu->is_2h = resource_size(reg_res) == 0x22c;
-
- veu->base = devm_ioremap_resource(&pdev->dev, reg_res);
- if (IS_ERR(veu->base))
- return PTR_ERR(veu->base);
-
- ret = devm_request_threaded_irq(&pdev->dev, irq, sh_veu_isr, sh_veu_bh,
- 0, "veu", veu);
- if (ret < 0)
- return ret;
-
- ret = v4l2_device_register(&pdev->dev, &veu->v4l2_dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "Error registering v4l2 device\n");
- return ret;
- }
-
- vdev = &veu->vdev;
-
- *vdev = sh_veu_videodev;
- vdev->v4l2_dev = &veu->v4l2_dev;
- spin_lock_init(&veu->lock);
- mutex_init(&veu->fop_lock);
- vdev->lock = &veu->fop_lock;
-
- video_set_drvdata(vdev, veu);
-
- veu->dev = &pdev->dev;
- veu->vfmt_out = DEFAULT_OUT_VFMT;
- veu->vfmt_in = DEFAULT_IN_VFMT;
-
- veu->m2m_dev = v4l2_m2m_init(&sh_veu_m2m_ops);
- if (IS_ERR(veu->m2m_dev)) {
- ret = PTR_ERR(veu->m2m_dev);
- v4l2_err(&veu->v4l2_dev, "Failed to init mem2mem device: %d\n", ret);
- goto em2minit;
- }
-
- pm_runtime_enable(&pdev->dev);
- pm_runtime_resume(&pdev->dev);
-
- ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
- pm_runtime_suspend(&pdev->dev);
- if (ret < 0)
- goto evidreg;
-
- return ret;
-
-evidreg:
- pm_runtime_disable(&pdev->dev);
- v4l2_m2m_release(veu->m2m_dev);
-em2minit:
- v4l2_device_unregister(&veu->v4l2_dev);
- return ret;
-}
-
-static int sh_veu_remove(struct platform_device *pdev)
-{
- struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
- struct sh_veu_dev *veu = container_of(v4l2_dev,
- struct sh_veu_dev, v4l2_dev);
-
- video_unregister_device(&veu->vdev);
- pm_runtime_disable(&pdev->dev);
- v4l2_m2m_release(veu->m2m_dev);
- v4l2_device_unregister(&veu->v4l2_dev);
-
- return 0;
-}
-
-static struct platform_driver __refdata sh_veu_pdrv = {
- .remove = sh_veu_remove,
- .driver = {
- .name = "sh_veu",
- },
-};
-
-module_platform_driver_probe(sh_veu_pdrv, sh_veu_probe);
-
-MODULE_DESCRIPTION("sh-mobile VEU mem2mem driver");
-MODULE_AUTHOR("Guennadi Liakhovetski, <g.liakhovetski@gmx.de>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/sti/cec/Makefile b/drivers/media/platform/sti/cec/Makefile
deleted file mode 100644
index d0c6b4ae94d6..000000000000
--- a/drivers/media/platform/sti/cec/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_STI_HDMI_CEC) += stih-cec.o
diff --git a/drivers/media/platform/sti/cec/stih-cec.c b/drivers/media/platform/sti/cec/stih-cec.c
deleted file mode 100644
index f0c73e64b586..000000000000
--- a/drivers/media/platform/sti/cec/stih-cec.c
+++ /dev/null
@@ -1,400 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * STIH4xx CEC driver
- * Copyright (C) STMicroelectronics SA 2016
- *
- */
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-
-#include <media/cec.h>
-#include <media/cec-notifier.h>
-
-#define CEC_NAME "stih-cec"
-
-/* CEC registers */
-#define CEC_CLK_DIV 0x0
-#define CEC_CTRL 0x4
-#define CEC_IRQ_CTRL 0x8
-#define CEC_STATUS 0xC
-#define CEC_EXT_STATUS 0x10
-#define CEC_TX_CTRL 0x14
-#define CEC_FREE_TIME_THRESH 0x18
-#define CEC_BIT_TOUT_THRESH 0x1C
-#define CEC_BIT_PULSE_THRESH 0x20
-#define CEC_DATA 0x24
-#define CEC_TX_ARRAY_CTRL 0x28
-#define CEC_CTRL2 0x2C
-#define CEC_TX_ERROR_STS 0x30
-#define CEC_ADDR_TABLE 0x34
-#define CEC_DATA_ARRAY_CTRL 0x38
-#define CEC_DATA_ARRAY_STATUS 0x3C
-#define CEC_TX_DATA_BASE 0x40
-#define CEC_TX_DATA_TOP 0x50
-#define CEC_TX_DATA_SIZE 0x1
-#define CEC_RX_DATA_BASE 0x54
-#define CEC_RX_DATA_TOP 0x64
-#define CEC_RX_DATA_SIZE 0x1
-
-/* CEC_CTRL2 */
-#define CEC_LINE_INACTIVE_EN BIT(0)
-#define CEC_AUTO_BUS_ERR_EN BIT(1)
-#define CEC_STOP_ON_ARB_ERR_EN BIT(2)
-#define CEC_TX_REQ_WAIT_EN BIT(3)
-
-/* CEC_DATA_ARRAY_CTRL */
-#define CEC_TX_ARRAY_EN BIT(0)
-#define CEC_RX_ARRAY_EN BIT(1)
-#define CEC_TX_ARRAY_RESET BIT(2)
-#define CEC_RX_ARRAY_RESET BIT(3)
-#define CEC_TX_N_OF_BYTES_IRQ_EN BIT(4)
-#define CEC_TX_STOP_ON_NACK BIT(7)
-
-/* CEC_TX_ARRAY_CTRL */
-#define CEC_TX_N_OF_BYTES 0x1F
-#define CEC_TX_START BIT(5)
-#define CEC_TX_AUTO_SOM_EN BIT(6)
-#define CEC_TX_AUTO_EOM_EN BIT(7)
-
-/* CEC_IRQ_CTRL */
-#define CEC_TX_DONE_IRQ_EN BIT(0)
-#define CEC_ERROR_IRQ_EN BIT(2)
-#define CEC_RX_DONE_IRQ_EN BIT(3)
-#define CEC_RX_SOM_IRQ_EN BIT(4)
-#define CEC_RX_EOM_IRQ_EN BIT(5)
-#define CEC_FREE_TIME_IRQ_EN BIT(6)
-#define CEC_PIN_STS_IRQ_EN BIT(7)
-
-/* CEC_CTRL */
-#define CEC_IN_FILTER_EN BIT(0)
-#define CEC_PWR_SAVE_EN BIT(1)
-#define CEC_EN BIT(4)
-#define CEC_ACK_CTRL BIT(5)
-#define CEC_RX_RESET_EN BIT(6)
-#define CEC_IGNORE_RX_ERROR BIT(7)
-
-/* CEC_STATUS */
-#define CEC_TX_DONE_STS BIT(0)
-#define CEC_TX_ACK_GET_STS BIT(1)
-#define CEC_ERROR_STS BIT(2)
-#define CEC_RX_DONE_STS BIT(3)
-#define CEC_RX_SOM_STS BIT(4)
-#define CEC_RX_EOM_STS BIT(5)
-#define CEC_FREE_TIME_IRQ_STS BIT(6)
-#define CEC_PIN_STS BIT(7)
-#define CEC_SBIT_TOUT_STS BIT(8)
-#define CEC_DBIT_TOUT_STS BIT(9)
-#define CEC_LPULSE_ERROR_STS BIT(10)
-#define CEC_HPULSE_ERROR_STS BIT(11)
-#define CEC_TX_ERROR BIT(12)
-#define CEC_TX_ARB_ERROR BIT(13)
-#define CEC_RX_ERROR_MIN BIT(14)
-#define CEC_RX_ERROR_MAX BIT(15)
-
-/* Signal free time in bit periods (2.4ms) */
-#define CEC_PRESENT_INIT_SFT 7
-#define CEC_NEW_INIT_SFT 5
-#define CEC_RETRANSMIT_SFT 3
-
-/* Constants for CEC_BIT_TOUT_THRESH register */
-#define CEC_SBIT_TOUT_47MS BIT(1)
-#define CEC_SBIT_TOUT_48MS (BIT(0) | BIT(1))
-#define CEC_SBIT_TOUT_50MS BIT(2)
-#define CEC_DBIT_TOUT_27MS BIT(0)
-#define CEC_DBIT_TOUT_28MS BIT(1)
-#define CEC_DBIT_TOUT_29MS (BIT(0) | BIT(1))
-
-/* Constants for CEC_BIT_PULSE_THRESH register */
-#define CEC_BIT_LPULSE_03MS BIT(1)
-#define CEC_BIT_HPULSE_03MS BIT(3)
-
-/* Constants for CEC_DATA_ARRAY_STATUS register */
-#define CEC_RX_N_OF_BYTES 0x1F
-#define CEC_TX_N_OF_BYTES_SENT BIT(5)
-#define CEC_RX_OVERRUN BIT(6)
-
-struct stih_cec {
- struct cec_adapter *adap;
- struct device *dev;
- struct clk *clk;
- void __iomem *regs;
- int irq;
- u32 irq_status;
- struct cec_notifier *notifier;
-};
-
-static int stih_cec_adap_enable(struct cec_adapter *adap, bool enable)
-{
- struct stih_cec *cec = cec_get_drvdata(adap);
-
- if (enable) {
- /* The doc says (input TCLK_PERIOD * CEC_CLK_DIV) = 0.1ms */
- unsigned long clk_freq = clk_get_rate(cec->clk);
- u32 cec_clk_div = clk_freq / 10000;
-
- writel(cec_clk_div, cec->regs + CEC_CLK_DIV);
-
- /* Configuration of the durations activating a timeout */
- writel(CEC_SBIT_TOUT_47MS | (CEC_DBIT_TOUT_28MS << 4),
- cec->regs + CEC_BIT_TOUT_THRESH);
-
- /* Configuration of the smallest allowed duration for pulses */
- writel(CEC_BIT_LPULSE_03MS | CEC_BIT_HPULSE_03MS,
- cec->regs + CEC_BIT_PULSE_THRESH);
-
- /* Minimum received bit period threshold */
- writel(BIT(5) | BIT(7), cec->regs + CEC_TX_CTRL);
-
- /* Configuration of transceiver data arrays */
- writel(CEC_TX_ARRAY_EN | CEC_RX_ARRAY_EN | CEC_TX_STOP_ON_NACK,
- cec->regs + CEC_DATA_ARRAY_CTRL);
-
- /* Configuration of the control bits for CEC Transceiver */
- writel(CEC_IN_FILTER_EN | CEC_EN | CEC_RX_RESET_EN,
- cec->regs + CEC_CTRL);
-
- /* Clear logical addresses */
- writel(0, cec->regs + CEC_ADDR_TABLE);
-
- /* Clear the status register */
- writel(0x0, cec->regs + CEC_STATUS);
-
- /* Enable the interrupts */
- writel(CEC_TX_DONE_IRQ_EN | CEC_RX_DONE_IRQ_EN |
- CEC_RX_SOM_IRQ_EN | CEC_RX_EOM_IRQ_EN |
- CEC_ERROR_IRQ_EN,
- cec->regs + CEC_IRQ_CTRL);
-
- } else {
- /* Clear logical addresses */
- writel(0, cec->regs + CEC_ADDR_TABLE);
-
- /* Clear the status register */
- writel(0x0, cec->regs + CEC_STATUS);
-
- /* Disable the interrupts */
- writel(0, cec->regs + CEC_IRQ_CTRL);
- }
-
- return 0;
-}
-
-static int stih_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
-{
- struct stih_cec *cec = cec_get_drvdata(adap);
- u32 reg = readl(cec->regs + CEC_ADDR_TABLE);
-
- reg |= 1 << logical_addr;
-
- if (logical_addr == CEC_LOG_ADDR_INVALID)
- reg = 0;
-
- writel(reg, cec->regs + CEC_ADDR_TABLE);
-
- return 0;
-}
-
-static int stih_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
- u32 signal_free_time, struct cec_msg *msg)
-{
- struct stih_cec *cec = cec_get_drvdata(adap);
- int i;
-
- /* Copy message into registers */
- for (i = 0; i < msg->len; i++)
- writeb(msg->msg[i], cec->regs + CEC_TX_DATA_BASE + i);
-
- /*
- * Start transmission, configure hardware to add start and stop bits
- * Signal free time is handled by the hardware
- */
- writel(CEC_TX_AUTO_SOM_EN | CEC_TX_AUTO_EOM_EN | CEC_TX_START |
- msg->len, cec->regs + CEC_TX_ARRAY_CTRL);
-
- return 0;
-}
-
-static void stih_tx_done(struct stih_cec *cec, u32 status)
-{
- if (status & CEC_TX_ERROR) {
- cec_transmit_attempt_done(cec->adap, CEC_TX_STATUS_ERROR);
- return;
- }
-
- if (status & CEC_TX_ARB_ERROR) {
- cec_transmit_attempt_done(cec->adap, CEC_TX_STATUS_ARB_LOST);
- return;
- }
-
- if (!(status & CEC_TX_ACK_GET_STS)) {
- cec_transmit_attempt_done(cec->adap, CEC_TX_STATUS_NACK);
- return;
- }
-
- cec_transmit_attempt_done(cec->adap, CEC_TX_STATUS_OK);
-}
-
-static void stih_rx_done(struct stih_cec *cec, u32 status)
-{
- struct cec_msg msg = {};
- u8 i;
-
- if (status & CEC_RX_ERROR_MIN)
- return;
-
- if (status & CEC_RX_ERROR_MAX)
- return;
-
- msg.len = readl(cec->regs + CEC_DATA_ARRAY_STATUS) & 0x1f;
-
- if (!msg.len)
- return;
-
- if (msg.len > 16)
- msg.len = 16;
-
- for (i = 0; i < msg.len; i++)
- msg.msg[i] = readl(cec->regs + CEC_RX_DATA_BASE + i);
-
- cec_received_msg(cec->adap, &msg);
-}
-
-static irqreturn_t stih_cec_irq_handler_thread(int irq, void *priv)
-{
- struct stih_cec *cec = priv;
-
- if (cec->irq_status & CEC_TX_DONE_STS)
- stih_tx_done(cec, cec->irq_status);
-
- if (cec->irq_status & CEC_RX_DONE_STS)
- stih_rx_done(cec, cec->irq_status);
-
- cec->irq_status = 0;
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t stih_cec_irq_handler(int irq, void *priv)
-{
- struct stih_cec *cec = priv;
-
- cec->irq_status = readl(cec->regs + CEC_STATUS);
- writel(cec->irq_status, cec->regs + CEC_STATUS);
-
- return IRQ_WAKE_THREAD;
-}
-
-static const struct cec_adap_ops sti_cec_adap_ops = {
- .adap_enable = stih_cec_adap_enable,
- .adap_log_addr = stih_cec_adap_log_addr,
- .adap_transmit = stih_cec_adap_transmit,
-};
-
-static int stih_cec_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct resource *res;
- struct stih_cec *cec;
- struct device *hdmi_dev;
- int ret;
-
- hdmi_dev = cec_notifier_parse_hdmi_phandle(dev);
-
- if (IS_ERR(hdmi_dev))
- return PTR_ERR(hdmi_dev);
-
- cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL);
- if (!cec)
- return -ENOMEM;
-
- cec->dev = dev;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- cec->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(cec->regs))
- return PTR_ERR(cec->regs);
-
- cec->irq = platform_get_irq(pdev, 0);
- if (cec->irq < 0)
- return cec->irq;
-
- ret = devm_request_threaded_irq(dev, cec->irq, stih_cec_irq_handler,
- stih_cec_irq_handler_thread, 0,
- pdev->name, cec);
- if (ret)
- return ret;
-
- cec->clk = devm_clk_get(dev, "cec-clk");
- if (IS_ERR(cec->clk)) {
- dev_err(dev, "Cannot get cec clock\n");
- return PTR_ERR(cec->clk);
- }
-
- cec->adap = cec_allocate_adapter(&sti_cec_adap_ops, cec, CEC_NAME,
- CEC_CAP_DEFAULTS |
- CEC_CAP_CONNECTOR_INFO,
- CEC_MAX_LOG_ADDRS);
- ret = PTR_ERR_OR_ZERO(cec->adap);
- if (ret)
- return ret;
-
- cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
- cec->adap);
- if (!cec->notifier) {
- ret = -ENOMEM;
- goto err_delete_adapter;
- }
-
- ret = cec_register_adapter(cec->adap, &pdev->dev);
- if (ret)
- goto err_notifier;
-
- platform_set_drvdata(pdev, cec);
- return 0;
-
-err_notifier:
- cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
-
-err_delete_adapter:
- cec_delete_adapter(cec->adap);
- return ret;
-}
-
-static int 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[] = {
- {
- .compatible = "st,stih-cec",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, stih_cec_match);
-
-static struct platform_driver stih_cec_pdrv = {
- .probe = stih_cec_probe,
- .remove = stih_cec_remove,
- .driver = {
- .name = CEC_NAME,
- .of_match_table = stih_cec_match,
- },
-};
-
-module_platform_driver(stih_cec_pdrv);
-
-MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@linaro.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("STIH4xx CEC driver");
diff --git a/drivers/media/platform/stm32/Makefile b/drivers/media/platform/stm32/Makefile
index 5ed73599ca44..48b36db2c2e2 100644
--- a/drivers/media/platform/stm32/Makefile
+++ b/drivers/media/platform/stm32/Makefile
@@ -1,3 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32-dcmi.o
-obj-$(CONFIG_VIDEO_STM32_HDMI_CEC) += stm32-cec.o
diff --git a/drivers/media/platform/stm32/stm32-cec.c b/drivers/media/platform/stm32/stm32-cec.c
deleted file mode 100644
index ea4b1ebfca99..000000000000
--- a/drivers/media/platform/stm32/stm32-cec.c
+++ /dev/null
@@ -1,374 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * STM32 CEC driver
- * Copyright (C) STMicroelectronics SA 2017
- *
- */
-
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#include <media/cec.h>
-
-#define CEC_NAME "stm32-cec"
-
-/* CEC registers */
-#define CEC_CR 0x0000 /* Control Register */
-#define CEC_CFGR 0x0004 /* ConFiGuration Register */
-#define CEC_TXDR 0x0008 /* Rx data Register */
-#define CEC_RXDR 0x000C /* Rx data Register */
-#define CEC_ISR 0x0010 /* Interrupt and status Register */
-#define CEC_IER 0x0014 /* Interrupt enable Register */
-
-#define TXEOM BIT(2)
-#define TXSOM BIT(1)
-#define CECEN BIT(0)
-
-#define LSTN BIT(31)
-#define OAR GENMASK(30, 16)
-#define SFTOP BIT(8)
-#define BRDNOGEN BIT(7)
-#define LBPEGEN BIT(6)
-#define BREGEN BIT(5)
-#define BRESTP BIT(4)
-#define RXTOL BIT(3)
-#define SFT GENMASK(2, 0)
-#define FULL_CFG (LSTN | SFTOP | BRDNOGEN | LBPEGEN | BREGEN | BRESTP \
- | RXTOL)
-
-#define TXACKE BIT(12)
-#define TXERR BIT(11)
-#define TXUDR BIT(10)
-#define TXEND BIT(9)
-#define TXBR BIT(8)
-#define ARBLST BIT(7)
-#define RXACKE BIT(6)
-#define RXOVR BIT(2)
-#define RXEND BIT(1)
-#define RXBR BIT(0)
-
-#define ALL_TX_IT (TXEND | TXBR | TXACKE | TXERR | TXUDR | ARBLST)
-#define ALL_RX_IT (RXEND | RXBR | RXACKE | RXOVR)
-
-/*
- * 400 ms is the time it takes for one 16 byte message to be
- * transferred and 5 is the maximum number of retries. Add
- * another 100 ms as a margin.
- */
-#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
-
-struct stm32_cec {
- struct cec_adapter *adap;
- struct device *dev;
- struct clk *clk_cec;
- struct clk *clk_hdmi_cec;
- struct reset_control *rstc;
- struct regmap *regmap;
- int irq;
- u32 irq_status;
- struct cec_msg rx_msg;
- struct cec_msg tx_msg;
- int tx_cnt;
-};
-
-static void cec_hw_init(struct stm32_cec *cec)
-{
- regmap_update_bits(cec->regmap, CEC_CR, TXEOM | TXSOM | CECEN, 0);
-
- regmap_update_bits(cec->regmap, CEC_IER, ALL_TX_IT | ALL_RX_IT,
- ALL_TX_IT | ALL_RX_IT);
-
- regmap_update_bits(cec->regmap, CEC_CFGR, FULL_CFG, FULL_CFG);
-}
-
-static void stm32_tx_done(struct stm32_cec *cec, u32 status)
-{
- if (status & (TXERR | TXUDR)) {
- cec_transmit_done(cec->adap, CEC_TX_STATUS_ERROR,
- 0, 0, 0, 1);
- return;
- }
-
- if (status & ARBLST) {
- cec_transmit_done(cec->adap, CEC_TX_STATUS_ARB_LOST,
- 1, 0, 0, 0);
- return;
- }
-
- if (status & TXACKE) {
- cec_transmit_done(cec->adap, CEC_TX_STATUS_NACK,
- 0, 1, 0, 0);
- return;
- }
-
- if (cec->irq_status & TXBR) {
- /* send next byte */
- if (cec->tx_cnt < cec->tx_msg.len)
- regmap_write(cec->regmap, CEC_TXDR,
- cec->tx_msg.msg[cec->tx_cnt++]);
-
- /* TXEOM is set to command transmission of the last byte */
- if (cec->tx_cnt == cec->tx_msg.len)
- regmap_update_bits(cec->regmap, CEC_CR, TXEOM, TXEOM);
- }
-
- if (cec->irq_status & TXEND)
- cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
-}
-
-static void stm32_rx_done(struct stm32_cec *cec, u32 status)
-{
- if (cec->irq_status & (RXACKE | RXOVR)) {
- cec->rx_msg.len = 0;
- return;
- }
-
- if (cec->irq_status & RXBR) {
- u32 val;
-
- regmap_read(cec->regmap, CEC_RXDR, &val);
- cec->rx_msg.msg[cec->rx_msg.len++] = val & 0xFF;
- }
-
- if (cec->irq_status & RXEND) {
- cec_received_msg(cec->adap, &cec->rx_msg);
- cec->rx_msg.len = 0;
- }
-}
-
-static irqreturn_t stm32_cec_irq_thread(int irq, void *arg)
-{
- struct stm32_cec *cec = arg;
-
- if (cec->irq_status & ALL_TX_IT)
- stm32_tx_done(cec, cec->irq_status);
-
- if (cec->irq_status & ALL_RX_IT)
- stm32_rx_done(cec, cec->irq_status);
-
- cec->irq_status = 0;
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t stm32_cec_irq_handler(int irq, void *arg)
-{
- struct stm32_cec *cec = arg;
-
- regmap_read(cec->regmap, CEC_ISR, &cec->irq_status);
-
- regmap_update_bits(cec->regmap, CEC_ISR,
- ALL_TX_IT | ALL_RX_IT,
- ALL_TX_IT | ALL_RX_IT);
-
- return IRQ_WAKE_THREAD;
-}
-
-static int stm32_cec_adap_enable(struct cec_adapter *adap, bool enable)
-{
- struct stm32_cec *cec = adap->priv;
- int ret = 0;
-
- if (enable) {
- ret = clk_enable(cec->clk_cec);
- if (ret)
- dev_err(cec->dev, "fail to enable cec clock\n");
-
- clk_enable(cec->clk_hdmi_cec);
- regmap_update_bits(cec->regmap, CEC_CR, CECEN, CECEN);
- } else {
- clk_disable(cec->clk_cec);
- clk_disable(cec->clk_hdmi_cec);
- regmap_update_bits(cec->regmap, CEC_CR, CECEN, 0);
- }
-
- return ret;
-}
-
-static int stm32_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
-{
- struct stm32_cec *cec = adap->priv;
- u32 oar = (1 << logical_addr) << 16;
- u32 val;
-
- /* Poll every 100µs the register CEC_CR to wait end of transmission */
- regmap_read_poll_timeout(cec->regmap, CEC_CR, val, !(val & TXSOM),
- 100, CEC_XFER_TIMEOUT_MS * 1000);
- regmap_update_bits(cec->regmap, CEC_CR, CECEN, 0);
-
- if (logical_addr == CEC_LOG_ADDR_INVALID)
- regmap_update_bits(cec->regmap, CEC_CFGR, OAR, 0);
- else
- regmap_update_bits(cec->regmap, CEC_CFGR, oar, oar);
-
- regmap_update_bits(cec->regmap, CEC_CR, CECEN, CECEN);
-
- return 0;
-}
-
-static int stm32_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
- u32 signal_free_time, struct cec_msg *msg)
-{
- struct stm32_cec *cec = adap->priv;
-
- /* Copy message */
- cec->tx_msg = *msg;
- cec->tx_cnt = 0;
-
- /*
- * If the CEC message consists of only one byte,
- * TXEOM must be set before of TXSOM.
- */
- if (cec->tx_msg.len == 1)
- regmap_update_bits(cec->regmap, CEC_CR, TXEOM, TXEOM);
-
- /* TXSOM is set to command transmission of the first byte */
- regmap_update_bits(cec->regmap, CEC_CR, TXSOM, TXSOM);
-
- /* Write the header (first byte of message) */
- regmap_write(cec->regmap, CEC_TXDR, cec->tx_msg.msg[0]);
- cec->tx_cnt++;
-
- return 0;
-}
-
-static const struct cec_adap_ops stm32_cec_adap_ops = {
- .adap_enable = stm32_cec_adap_enable,
- .adap_log_addr = stm32_cec_adap_log_addr,
- .adap_transmit = stm32_cec_adap_transmit,
-};
-
-static const struct regmap_config stm32_cec_regmap_cfg = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = sizeof(u32),
- .max_register = 0x14,
- .fast_io = true,
-};
-
-static int stm32_cec_probe(struct platform_device *pdev)
-{
- u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | CEC_MODE_MONITOR_ALL;
- struct resource *res;
- struct stm32_cec *cec;
- void __iomem *mmio;
- int ret;
-
- cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
- if (!cec)
- return -ENOMEM;
-
- cec->dev = &pdev->dev;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mmio = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(mmio))
- return PTR_ERR(mmio);
-
- cec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "cec", mmio,
- &stm32_cec_regmap_cfg);
-
- if (IS_ERR(cec->regmap))
- return PTR_ERR(cec->regmap);
-
- cec->irq = platform_get_irq(pdev, 0);
- if (cec->irq < 0)
- return cec->irq;
-
- ret = devm_request_threaded_irq(&pdev->dev, cec->irq,
- stm32_cec_irq_handler,
- stm32_cec_irq_thread,
- 0,
- pdev->name, cec);
- if (ret)
- return ret;
-
- cec->clk_cec = devm_clk_get(&pdev->dev, "cec");
- if (IS_ERR(cec->clk_cec)) {
- if (PTR_ERR(cec->clk_cec) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Cannot get cec clock\n");
-
- return PTR_ERR(cec->clk_cec);
- }
-
- ret = clk_prepare(cec->clk_cec);
- if (ret) {
- dev_err(&pdev->dev, "Unable to prepare cec clock\n");
- return ret;
- }
-
- cec->clk_hdmi_cec = devm_clk_get(&pdev->dev, "hdmi-cec");
- if (IS_ERR(cec->clk_hdmi_cec) &&
- PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-
- if (!IS_ERR(cec->clk_hdmi_cec)) {
- ret = clk_prepare(cec->clk_hdmi_cec);
- if (ret) {
- dev_err(&pdev->dev, "Can't prepare hdmi-cec clock\n");
- return ret;
- }
- }
-
- /*
- * CEC_CAP_PHYS_ADDR caps should be removed when a cec notifier is
- * available for example when a drm driver can provide edid
- */
- cec->adap = cec_allocate_adapter(&stm32_cec_adap_ops, cec,
- CEC_NAME, caps, CEC_MAX_LOG_ADDRS);
- ret = PTR_ERR_OR_ZERO(cec->adap);
- if (ret)
- return ret;
-
- ret = cec_register_adapter(cec->adap, &pdev->dev);
- if (ret) {
- cec_delete_adapter(cec->adap);
- return ret;
- }
-
- cec_hw_init(cec);
-
- platform_set_drvdata(pdev, cec);
-
- return 0;
-}
-
-static int stm32_cec_remove(struct platform_device *pdev)
-{
- struct stm32_cec *cec = platform_get_drvdata(pdev);
-
- clk_unprepare(cec->clk_cec);
- clk_unprepare(cec->clk_hdmi_cec);
-
- cec_unregister_adapter(cec->adap);
-
- return 0;
-}
-
-static const struct of_device_id stm32_cec_of_match[] = {
- { .compatible = "st,stm32-cec" },
- { /* end node */ }
-};
-MODULE_DEVICE_TABLE(of, stm32_cec_of_match);
-
-static struct platform_driver stm32_cec_driver = {
- .probe = stm32_cec_probe,
- .remove = stm32_cec_remove,
- .driver = {
- .name = CEC_NAME,
- .of_match_table = stm32_cec_of_match,
- },
-};
-
-module_platform_driver(stm32_cec_driver);
-
-MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
-MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics STM32 Consumer Electronics Control");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/sunxi/Kconfig b/drivers/media/platform/sunxi/Kconfig
index 71808e93ac2e..7151cc249afa 100644
--- a/drivers/media/platform/sunxi/Kconfig
+++ b/drivers/media/platform/sunxi/Kconfig
@@ -1,2 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
source "drivers/media/platform/sunxi/sun4i-csi/Kconfig"
source "drivers/media/platform/sunxi/sun6i-csi/Kconfig"
diff --git a/drivers/media/platform/sunxi/Makefile b/drivers/media/platform/sunxi/Makefile
index ff0993f70dc3..fc537c9f5ca9 100644
--- a/drivers/media/platform/sunxi/Makefile
+++ b/drivers/media/platform/sunxi/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
obj-y += sun4i-csi/
obj-y += sun6i-csi/
obj-y += sun8i-di/
diff --git a/drivers/media/platform/sunxi/sun4i-csi/Kconfig b/drivers/media/platform/sunxi/sun4i-csi/Kconfig
index e86e29b6a603..903c6152f6e8 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/Kconfig
+++ b/drivers/media/platform/sunxi/sun4i-csi/Kconfig
@@ -1,7 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+
config VIDEO_SUN4I_CSI
tristate "Allwinner A10 CMOS Sensor Interface Support"
- depends on VIDEO_V4L2 && COMMON_CLK && VIDEO_V4L2_SUBDEV_API && HAS_DMA
+ depends on VIDEO_V4L2 && COMMON_CLK && HAS_DMA
depends on ARCH_SUNXI || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select V4L2_FWNODE
help
diff --git a/drivers/media/platform/sunxi/sun4i-csi/Makefile b/drivers/media/platform/sunxi/sun4i-csi/Makefile
index 7c790a57f5ee..5062b006d63e 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/Makefile
+++ b/drivers/media/platform/sunxi/sun4i-csi/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
sun4i-csi-y += sun4i_csi.o
sun4i-csi-y += sun4i_dma.o
sun4i-csi-y += sun4i_v4l2.o
diff --git a/drivers/media/platform/sunxi/sun6i-csi/Kconfig b/drivers/media/platform/sunxi/sun6i-csi/Kconfig
index 269b3ebf4f52..586e3fb3a80d 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/Kconfig
+++ b/drivers/media/platform/sunxi/sun6i-csi/Kconfig
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
config VIDEO_SUN6I_CSI
tristate "Allwinner V3s Camera Sensor Interface driver"
- depends on VIDEO_V4L2 && COMMON_CLK && VIDEO_V4L2_SUBDEV_API && HAS_DMA
+ depends on VIDEO_V4L2 && COMMON_CLK && HAS_DMA
depends on ARCH_SUNXI || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select REGMAP_MMIO
select V4L2_FWNODE
diff --git a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
index d78f6593ddd1..ba5d07886607 100644
--- a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
+++ b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
@@ -941,7 +941,7 @@ static int deinterlace_runtime_resume(struct device *device)
if (ret) {
dev_err(dev->dev, "Failed to enable bus clock\n");
- goto err_exlusive_rate;
+ goto err_exclusive_rate;
}
ret = clk_prepare_enable(dev->mod_clk);
@@ -969,14 +969,14 @@ static int deinterlace_runtime_resume(struct device *device)
return 0;
-err_exlusive_rate:
- clk_rate_exclusive_put(dev->mod_clk);
err_ram_clk:
clk_disable_unprepare(dev->ram_clk);
err_mod_clk:
clk_disable_unprepare(dev->mod_clk);
err_bus_clk:
clk_disable_unprepare(dev->bus_clk);
+err_exclusive_rate:
+ clk_rate_exclusive_put(dev->mod_clk);
return ret;
}
diff --git a/drivers/media/platform/tegra-cec/Makefile b/drivers/media/platform/tegra-cec/Makefile
deleted file mode 100644
index 97e57c7493c0..000000000000
--- a/drivers/media/platform/tegra-cec/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_TEGRA_HDMI_CEC) += tegra_cec.o
diff --git a/drivers/media/platform/tegra-cec/tegra_cec.c b/drivers/media/platform/tegra-cec/tegra_cec.c
deleted file mode 100644
index 1ac0c70a5981..000000000000
--- a/drivers/media/platform/tegra-cec/tegra_cec.c
+++ /dev/null
@@ -1,481 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Tegra CEC implementation
- *
- * The original 3.10 CEC driver using a custom API:
- *
- * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved.
- *
- * Conversion to the CEC framework and to the mainline kernel:
- *
- * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/clk/tegra.h>
-
-#include <media/cec-notifier.h>
-
-#include "tegra_cec.h"
-
-#define TEGRA_CEC_NAME "tegra-cec"
-
-struct tegra_cec {
- struct cec_adapter *adap;
- struct device *dev;
- struct clk *clk;
- void __iomem *cec_base;
- struct cec_notifier *notifier;
- int tegra_cec_irq;
- bool rx_done;
- bool tx_done;
- int tx_status;
- u8 rx_buf[CEC_MAX_MSG_SIZE];
- u8 rx_buf_cnt;
- u32 tx_buf[CEC_MAX_MSG_SIZE];
- u8 tx_buf_cur;
- u8 tx_buf_cnt;
-};
-
-static inline u32 cec_read(struct tegra_cec *cec, u32 reg)
-{
- return readl(cec->cec_base + reg);
-}
-
-static inline void cec_write(struct tegra_cec *cec, u32 reg, u32 val)
-{
- writel(val, cec->cec_base + reg);
-}
-
-static void tegra_cec_error_recovery(struct tegra_cec *cec)
-{
- u32 hw_ctrl;
-
- hw_ctrl = cec_read(cec, TEGRA_CEC_HW_CONTROL);
- cec_write(cec, TEGRA_CEC_HW_CONTROL, 0);
- cec_write(cec, TEGRA_CEC_INT_STAT, 0xffffffff);
- cec_write(cec, TEGRA_CEC_HW_CONTROL, hw_ctrl);
-}
-
-static irqreturn_t tegra_cec_irq_thread_handler(int irq, void *data)
-{
- struct device *dev = data;
- struct tegra_cec *cec = dev_get_drvdata(dev);
-
- if (cec->tx_done) {
- cec_transmit_attempt_done(cec->adap, cec->tx_status);
- cec->tx_done = false;
- }
- if (cec->rx_done) {
- struct cec_msg msg = {};
-
- msg.len = cec->rx_buf_cnt;
- memcpy(msg.msg, cec->rx_buf, msg.len);
- cec_received_msg(cec->adap, &msg);
- cec->rx_done = false;
- cec->rx_buf_cnt = 0;
- }
- return IRQ_HANDLED;
-}
-
-static irqreturn_t tegra_cec_irq_handler(int irq, void *data)
-{
- struct device *dev = data;
- struct tegra_cec *cec = dev_get_drvdata(dev);
- u32 status, mask;
-
- status = cec_read(cec, TEGRA_CEC_INT_STAT);
- mask = cec_read(cec, TEGRA_CEC_INT_MASK);
-
- status &= mask;
-
- if (!status)
- return IRQ_HANDLED;
-
- if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_UNDERRUN) {
- dev_err(dev, "TX underrun, interrupt timing issue!\n");
-
- tegra_cec_error_recovery(cec);
- cec_write(cec, TEGRA_CEC_INT_MASK,
- mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY);
-
- cec->tx_done = true;
- cec->tx_status = CEC_TX_STATUS_ERROR;
- return IRQ_WAKE_THREAD;
- }
-
- if ((status & TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED) ||
- (status & TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED)) {
- tegra_cec_error_recovery(cec);
- cec_write(cec, TEGRA_CEC_INT_MASK,
- mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY);
-
- cec->tx_done = true;
- if (status & TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED)
- cec->tx_status = CEC_TX_STATUS_LOW_DRIVE;
- else
- cec->tx_status = CEC_TX_STATUS_ARB_LOST;
- return IRQ_WAKE_THREAD;
- }
-
- if (status & TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED) {
- cec_write(cec, TEGRA_CEC_INT_STAT,
- TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED);
-
- if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD) {
- tegra_cec_error_recovery(cec);
-
- cec->tx_done = true;
- cec->tx_status = CEC_TX_STATUS_NACK;
- } else {
- cec->tx_done = true;
- cec->tx_status = CEC_TX_STATUS_OK;
- }
- return IRQ_WAKE_THREAD;
- }
-
- if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD)
- dev_warn(dev, "TX NAKed on the fly!\n");
-
- if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY) {
- if (cec->tx_buf_cur == cec->tx_buf_cnt) {
- cec_write(cec, TEGRA_CEC_INT_MASK,
- mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY);
- } else {
- cec_write(cec, TEGRA_CEC_TX_REGISTER,
- cec->tx_buf[cec->tx_buf_cur++]);
- cec_write(cec, TEGRA_CEC_INT_STAT,
- TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY);
- }
- }
-
- if (status & TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED) {
- cec_write(cec, TEGRA_CEC_INT_STAT,
- TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED);
- cec->rx_done = false;
- cec->rx_buf_cnt = 0;
- }
- if (status & TEGRA_CEC_INT_STAT_RX_REGISTER_FULL) {
- u32 v;
-
- cec_write(cec, TEGRA_CEC_INT_STAT,
- TEGRA_CEC_INT_STAT_RX_REGISTER_FULL);
- v = cec_read(cec, TEGRA_CEC_RX_REGISTER);
- if (cec->rx_buf_cnt < CEC_MAX_MSG_SIZE)
- cec->rx_buf[cec->rx_buf_cnt++] = v & 0xff;
- if (v & TEGRA_CEC_RX_REGISTER_EOM) {
- cec->rx_done = true;
- return IRQ_WAKE_THREAD;
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static int tegra_cec_adap_enable(struct cec_adapter *adap, bool enable)
-{
- struct tegra_cec *cec = adap->priv;
-
- cec->rx_buf_cnt = 0;
- cec->tx_buf_cnt = 0;
- cec->tx_buf_cur = 0;
-
- cec_write(cec, TEGRA_CEC_HW_CONTROL, 0);
- cec_write(cec, TEGRA_CEC_INT_MASK, 0);
- cec_write(cec, TEGRA_CEC_INT_STAT, 0xffffffff);
- cec_write(cec, TEGRA_CEC_SW_CONTROL, 0);
-
- if (!enable)
- return 0;
-
- cec_write(cec, TEGRA_CEC_INPUT_FILTER, (1U << 31) | 0x20);
-
- cec_write(cec, TEGRA_CEC_RX_TIMING_0,
- (0x7a << TEGRA_CEC_RX_TIM0_START_BIT_MAX_LO_TIME_SHIFT) |
- (0x6d << TEGRA_CEC_RX_TIM0_START_BIT_MIN_LO_TIME_SHIFT) |
- (0x93 << TEGRA_CEC_RX_TIM0_START_BIT_MAX_DURATION_SHIFT) |
- (0x86 << TEGRA_CEC_RX_TIM0_START_BIT_MIN_DURATION_SHIFT));
-
- cec_write(cec, TEGRA_CEC_RX_TIMING_1,
- (0x35 << TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_LO_TIME_SHIFT) |
- (0x21 << TEGRA_CEC_RX_TIM1_DATA_BIT_SAMPLE_TIME_SHIFT) |
- (0x56 << TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_DURATION_SHIFT) |
- (0x40 << TEGRA_CEC_RX_TIM1_DATA_BIT_MIN_DURATION_SHIFT));
-
- cec_write(cec, TEGRA_CEC_RX_TIMING_2,
- (0x50 << TEGRA_CEC_RX_TIM2_END_OF_BLOCK_TIME_SHIFT));
-
- cec_write(cec, TEGRA_CEC_TX_TIMING_0,
- (0x74 << TEGRA_CEC_TX_TIM0_START_BIT_LO_TIME_SHIFT) |
- (0x8d << TEGRA_CEC_TX_TIM0_START_BIT_DURATION_SHIFT) |
- (0x08 << TEGRA_CEC_TX_TIM0_BUS_XITION_TIME_SHIFT) |
- (0x71 << TEGRA_CEC_TX_TIM0_BUS_ERROR_LO_TIME_SHIFT));
-
- cec_write(cec, TEGRA_CEC_TX_TIMING_1,
- (0x2f << TEGRA_CEC_TX_TIM1_LO_DATA_BIT_LO_TIME_SHIFT) |
- (0x13 << TEGRA_CEC_TX_TIM1_HI_DATA_BIT_LO_TIME_SHIFT) |
- (0x4b << TEGRA_CEC_TX_TIM1_DATA_BIT_DURATION_SHIFT) |
- (0x21 << TEGRA_CEC_TX_TIM1_ACK_NAK_BIT_SAMPLE_TIME_SHIFT));
-
- cec_write(cec, TEGRA_CEC_TX_TIMING_2,
- (0x07 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_ADDITIONAL_FRAME_SHIFT) |
- (0x05 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_NEW_FRAME_SHIFT) |
- (0x03 << TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_RETRY_FRAME_SHIFT));
-
- cec_write(cec, TEGRA_CEC_INT_MASK,
- TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN |
- TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD |
- TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED |
- TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED |
- TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED |
- TEGRA_CEC_INT_MASK_RX_REGISTER_FULL |
- TEGRA_CEC_INT_MASK_RX_START_BIT_DETECTED);
-
- cec_write(cec, TEGRA_CEC_HW_CONTROL, TEGRA_CEC_HWCTRL_TX_RX_MODE);
- return 0;
-}
-
-static int tegra_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
-{
- struct tegra_cec *cec = adap->priv;
- u32 state = cec_read(cec, TEGRA_CEC_HW_CONTROL);
-
- if (logical_addr == CEC_LOG_ADDR_INVALID)
- state &= ~TEGRA_CEC_HWCTRL_RX_LADDR_MASK;
- else
- state |= TEGRA_CEC_HWCTRL_RX_LADDR((1 << logical_addr));
-
- cec_write(cec, TEGRA_CEC_HW_CONTROL, state);
- return 0;
-}
-
-static int tegra_cec_adap_monitor_all_enable(struct cec_adapter *adap,
- bool enable)
-{
- struct tegra_cec *cec = adap->priv;
- u32 reg = cec_read(cec, TEGRA_CEC_HW_CONTROL);
-
- if (enable)
- reg |= TEGRA_CEC_HWCTRL_RX_SNOOP;
- else
- reg &= ~TEGRA_CEC_HWCTRL_RX_SNOOP;
- cec_write(cec, TEGRA_CEC_HW_CONTROL, reg);
- return 0;
-}
-
-static int tegra_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
- u32 signal_free_time_ms, struct cec_msg *msg)
-{
- bool retry_xfer = signal_free_time_ms == CEC_SIGNAL_FREE_TIME_RETRY;
- struct tegra_cec *cec = adap->priv;
- unsigned int i;
- u32 mode = 0;
- u32 mask;
-
- if (cec_msg_is_broadcast(msg))
- mode = TEGRA_CEC_TX_REG_BCAST;
-
- cec->tx_buf_cur = 0;
- cec->tx_buf_cnt = msg->len;
-
- for (i = 0; i < msg->len; i++) {
- cec->tx_buf[i] = mode | msg->msg[i];
- if (i == 0)
- cec->tx_buf[i] |= TEGRA_CEC_TX_REG_START_BIT;
- if (i == msg->len - 1)
- cec->tx_buf[i] |= TEGRA_CEC_TX_REG_EOM;
- if (i == 0 && retry_xfer)
- cec->tx_buf[i] |= TEGRA_CEC_TX_REG_RETRY;
- }
-
- mask = cec_read(cec, TEGRA_CEC_INT_MASK);
- cec_write(cec, TEGRA_CEC_INT_MASK,
- mask | TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY);
-
- return 0;
-}
-
-static const struct cec_adap_ops tegra_cec_ops = {
- .adap_enable = tegra_cec_adap_enable,
- .adap_log_addr = tegra_cec_adap_log_addr,
- .adap_transmit = tegra_cec_adap_transmit,
- .adap_monitor_all_enable = tegra_cec_adap_monitor_all_enable,
-};
-
-static int tegra_cec_probe(struct platform_device *pdev)
-{
- struct device *hdmi_dev;
- struct tegra_cec *cec;
- struct resource *res;
- int ret = 0;
-
- hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
-
- if (IS_ERR(hdmi_dev))
- return PTR_ERR(hdmi_dev);
-
- cec = devm_kzalloc(&pdev->dev, sizeof(struct tegra_cec), GFP_KERNEL);
-
- if (!cec)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- if (!res) {
- dev_err(&pdev->dev,
- "Unable to allocate resources for device\n");
- return -EBUSY;
- }
-
- if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
- pdev->name)) {
- dev_err(&pdev->dev,
- "Unable to request mem region for device\n");
- return -EBUSY;
- }
-
- cec->tegra_cec_irq = platform_get_irq(pdev, 0);
-
- if (cec->tegra_cec_irq <= 0)
- return -EBUSY;
-
- cec->cec_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
-
- if (!cec->cec_base) {
- dev_err(&pdev->dev, "Unable to grab IOs for device\n");
- return -EBUSY;
- }
-
- cec->clk = devm_clk_get(&pdev->dev, "cec");
-
- if (IS_ERR_OR_NULL(cec->clk)) {
- dev_err(&pdev->dev, "Can't get clock for CEC\n");
- return -ENOENT;
- }
-
- clk_prepare_enable(cec->clk);
-
- /* set context info. */
- cec->dev = &pdev->dev;
-
- platform_set_drvdata(pdev, cec);
-
- ret = devm_request_threaded_irq(&pdev->dev, cec->tegra_cec_irq,
- tegra_cec_irq_handler, tegra_cec_irq_thread_handler,
- 0, "cec_irq", &pdev->dev);
-
- if (ret) {
- dev_err(&pdev->dev,
- "Unable to request interrupt for device\n");
- goto err_clk;
- }
-
- cec->adap = cec_allocate_adapter(&tegra_cec_ops, cec, TEGRA_CEC_NAME,
- CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL |
- CEC_CAP_CONNECTOR_INFO,
- CEC_MAX_LOG_ADDRS);
- if (IS_ERR(cec->adap)) {
- ret = -ENOMEM;
- dev_err(&pdev->dev, "Couldn't create cec adapter\n");
- goto err_clk;
- }
-
- cec->notifier = cec_notifier_cec_adap_register(hdmi_dev, NULL,
- cec->adap);
- if (!cec->notifier) {
- ret = -ENOMEM;
- goto err_adapter;
- }
-
- ret = cec_register_adapter(cec->adap, &pdev->dev);
- if (ret) {
- dev_err(&pdev->dev, "Couldn't register device\n");
- goto err_notifier;
- }
-
- return 0;
-
-err_notifier:
- cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
-err_adapter:
- cec_delete_adapter(cec->adap);
-err_clk:
- clk_disable_unprepare(cec->clk);
- return ret;
-}
-
-static int tegra_cec_remove(struct platform_device *pdev)
-{
- struct tegra_cec *cec = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(cec->clk);
-
- cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
- cec_unregister_adapter(cec->adap);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int tegra_cec_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct tegra_cec *cec = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(cec->clk);
-
- dev_notice(&pdev->dev, "suspended\n");
- return 0;
-}
-
-static int tegra_cec_resume(struct platform_device *pdev)
-{
- struct tegra_cec *cec = platform_get_drvdata(pdev);
-
- dev_notice(&pdev->dev, "Resuming\n");
-
- clk_prepare_enable(cec->clk);
-
- return 0;
-}
-#endif
-
-static const struct of_device_id tegra_cec_of_match[] = {
- { .compatible = "nvidia,tegra114-cec", },
- { .compatible = "nvidia,tegra124-cec", },
- { .compatible = "nvidia,tegra210-cec", },
- {},
-};
-
-static struct platform_driver tegra_cec_driver = {
- .driver = {
- .name = TEGRA_CEC_NAME,
- .of_match_table = of_match_ptr(tegra_cec_of_match),
- },
- .probe = tegra_cec_probe,
- .remove = tegra_cec_remove,
-
-#ifdef CONFIG_PM
- .suspend = tegra_cec_suspend,
- .resume = tegra_cec_resume,
-#endif
-};
-
-module_platform_driver(tegra_cec_driver);
-
-MODULE_DESCRIPTION("Tegra HDMI CEC driver");
-MODULE_AUTHOR("NVIDIA CORPORATION");
-MODULE_AUTHOR("Cisco Systems, Inc. and/or its affiliates");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/tegra-cec/tegra_cec.h b/drivers/media/platform/tegra-cec/tegra_cec.h
deleted file mode 100644
index 8c370be38e1e..000000000000
--- a/drivers/media/platform/tegra-cec/tegra_cec.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Tegra CEC register definitions
- *
- * The original 3.10 CEC driver using a custom API:
- *
- * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved.
- *
- * Conversion to the CEC framework and to the mainline kernel:
- *
- * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef TEGRA_CEC_H
-#define TEGRA_CEC_H
-
-/* CEC registers */
-#define TEGRA_CEC_SW_CONTROL 0x000
-#define TEGRA_CEC_HW_CONTROL 0x004
-#define TEGRA_CEC_INPUT_FILTER 0x008
-#define TEGRA_CEC_TX_REGISTER 0x010
-#define TEGRA_CEC_RX_REGISTER 0x014
-#define TEGRA_CEC_RX_TIMING_0 0x018
-#define TEGRA_CEC_RX_TIMING_1 0x01c
-#define TEGRA_CEC_RX_TIMING_2 0x020
-#define TEGRA_CEC_TX_TIMING_0 0x024
-#define TEGRA_CEC_TX_TIMING_1 0x028
-#define TEGRA_CEC_TX_TIMING_2 0x02c
-#define TEGRA_CEC_INT_STAT 0x030
-#define TEGRA_CEC_INT_MASK 0x034
-#define TEGRA_CEC_HW_DEBUG_RX 0x038
-#define TEGRA_CEC_HW_DEBUG_TX 0x03c
-
-#define TEGRA_CEC_HWCTRL_RX_LADDR_MASK 0x7fff
-#define TEGRA_CEC_HWCTRL_RX_LADDR(x) \
- ((x) & TEGRA_CEC_HWCTRL_RX_LADDR_MASK)
-#define TEGRA_CEC_HWCTRL_RX_SNOOP BIT(15)
-#define TEGRA_CEC_HWCTRL_RX_NAK_MODE BIT(16)
-#define TEGRA_CEC_HWCTRL_TX_NAK_MODE BIT(24)
-#define TEGRA_CEC_HWCTRL_FAST_SIM_MODE BIT(30)
-#define TEGRA_CEC_HWCTRL_TX_RX_MODE BIT(31)
-
-#define TEGRA_CEC_INPUT_FILTER_MODE BIT(31)
-#define TEGRA_CEC_INPUT_FILTER_FIFO_LENGTH_SHIFT 0
-
-#define TEGRA_CEC_TX_REG_DATA_SHIFT 0
-#define TEGRA_CEC_TX_REG_EOM BIT(8)
-#define TEGRA_CEC_TX_REG_BCAST BIT(12)
-#define TEGRA_CEC_TX_REG_START_BIT BIT(16)
-#define TEGRA_CEC_TX_REG_RETRY BIT(17)
-
-#define TEGRA_CEC_RX_REGISTER_SHIFT 0
-#define TEGRA_CEC_RX_REGISTER_EOM BIT(8)
-#define TEGRA_CEC_RX_REGISTER_ACK BIT(9)
-
-#define TEGRA_CEC_RX_TIM0_START_BIT_MAX_LO_TIME_SHIFT 0
-#define TEGRA_CEC_RX_TIM0_START_BIT_MIN_LO_TIME_SHIFT 8
-#define TEGRA_CEC_RX_TIM0_START_BIT_MAX_DURATION_SHIFT 16
-#define TEGRA_CEC_RX_TIM0_START_BIT_MIN_DURATION_SHIFT 24
-
-#define TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_LO_TIME_SHIFT 0
-#define TEGRA_CEC_RX_TIM1_DATA_BIT_SAMPLE_TIME_SHIFT 8
-#define TEGRA_CEC_RX_TIM1_DATA_BIT_MAX_DURATION_SHIFT 16
-#define TEGRA_CEC_RX_TIM1_DATA_BIT_MIN_DURATION_SHIFT 24
-
-#define TEGRA_CEC_RX_TIM2_END_OF_BLOCK_TIME_SHIFT 0
-
-#define TEGRA_CEC_TX_TIM0_START_BIT_LO_TIME_SHIFT 0
-#define TEGRA_CEC_TX_TIM0_START_BIT_DURATION_SHIFT 8
-#define TEGRA_CEC_TX_TIM0_BUS_XITION_TIME_SHIFT 16
-#define TEGRA_CEC_TX_TIM0_BUS_ERROR_LO_TIME_SHIFT 24
-
-#define TEGRA_CEC_TX_TIM1_LO_DATA_BIT_LO_TIME_SHIFT 0
-#define TEGRA_CEC_TX_TIM1_HI_DATA_BIT_LO_TIME_SHIFT 8
-#define TEGRA_CEC_TX_TIM1_DATA_BIT_DURATION_SHIFT 16
-#define TEGRA_CEC_TX_TIM1_ACK_NAK_BIT_SAMPLE_TIME_SHIFT 24
-
-#define TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_ADDITIONAL_FRAME_SHIFT 0
-#define TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_NEW_FRAME_SHIFT 4
-#define TEGRA_CEC_TX_TIM2_BUS_IDLE_TIME_RETRY_FRAME_SHIFT 8
-
-#define TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY BIT(0)
-#define TEGRA_CEC_INT_STAT_TX_REGISTER_UNDERRUN BIT(1)
-#define TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD BIT(2)
-#define TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED BIT(3)
-#define TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED BIT(4)
-#define TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED BIT(5)
-#define TEGRA_CEC_INT_STAT_RX_REGISTER_FULL BIT(8)
-#define TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN BIT(9)
-#define TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED BIT(10)
-#define TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED BIT(11)
-#define TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED BIT(12)
-#define TEGRA_CEC_INT_STAT_FILTERED_RX_DATA_PIN_TRANSITION_H2L BIT(13)
-#define TEGRA_CEC_INT_STAT_FILTERED_RX_DATA_PIN_TRANSITION_L2H BIT(14)
-
-#define TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY BIT(0)
-#define TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN BIT(1)
-#define TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD BIT(2)
-#define TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED BIT(3)
-#define TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED BIT(4)
-#define TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED BIT(5)
-#define TEGRA_CEC_INT_MASK_RX_REGISTER_FULL BIT(8)
-#define TEGRA_CEC_INT_MASK_RX_REGISTER_OVERRUN BIT(9)
-#define TEGRA_CEC_INT_MASK_RX_START_BIT_DETECTED BIT(10)
-#define TEGRA_CEC_INT_MASK_RX_BUS_ANOMALY_DETECTED BIT(11)
-#define TEGRA_CEC_INT_MASK_RX_BUS_ERROR_DETECTED BIT(12)
-#define TEGRA_CEC_INT_MASK_FILTERED_RX_DATA_PIN_TRANSITION_H2L BIT(13)
-#define TEGRA_CEC_INT_MASK_FILTERED_RX_DATA_PIN_TRANSITION_L2H BIT(14)
-
-#define TEGRA_CEC_HW_DEBUG_TX_DURATION_COUNT_SHIFT 0
-#define TEGRA_CEC_HW_DEBUG_TX_TXBIT_COUNT_SHIFT 17
-#define TEGRA_CEC_HW_DEBUG_TX_STATE_SHIFT 21
-#define TEGRA_CEC_HW_DEBUG_TX_FORCELOOUT BIT(25)
-#define TEGRA_CEC_HW_DEBUG_TX_TXDATABIT_SAMPLE_TIMER BIT(26)
-
-#endif /* TEGRA_CEC_H */
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 6c8f3702eac0..9b18db7af6c3 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -6,6 +6,7 @@
* Benoit Parrot, <bparrot@ti.com>
*/
+#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioctl.h>
@@ -340,6 +341,7 @@ static const struct cal_data am654_cal_data = {
* all instances.
*/
struct cal_dev {
+ struct clk *fclk;
int irq;
void __iomem *base;
struct resource *res;
@@ -412,6 +414,8 @@ struct cal_ctx {
struct cal_buffer *cur_frm;
/* Pointer pointing to next v4l2_buffer */
struct cal_buffer *next_frm;
+
+ bool dma_act;
};
static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
@@ -643,36 +647,12 @@ static void i913_errata(struct cal_dev *dev, unsigned int port)
{
u32 reg10 = reg_read(dev->cc[port], CAL_CSI2_PHY_REG10);
- set_field(&reg10, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
- CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
+ set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
cal_dbg(1, dev, "CSI2_%d_REG10 = 0x%08x\n", port, reg10);
reg_write(dev->cc[port], CAL_CSI2_PHY_REG10, reg10);
}
-static int cal_runtime_get(struct cal_dev *dev)
-{
- int r;
-
- r = pm_runtime_get_sync(&dev->pdev->dev);
-
- if (dev->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
- /*
- * Apply errata on both port eveytime we (re-)enable
- * the clock
- */
- i913_errata(dev, 0);
- i913_errata(dev, 1);
- }
-
- return r;
-}
-
-static inline void cal_runtime_put(struct cal_dev *dev)
-{
- pm_runtime_put_sync(&dev->pdev->dev);
-}
-
static void cal_quickdump_regs(struct cal_dev *dev)
{
cal_info(dev, "CAL Registers @ 0x%pa:\n", &dev->res->start);
@@ -704,16 +684,31 @@ static void cal_quickdump_regs(struct cal_dev *dev)
*/
static void enable_irqs(struct cal_ctx *ctx)
{
+ u32 val;
+
+ const u32 cio_err_mask =
+ CAL_CSI2_COMPLEXIO_IRQ_LANE_ERRORS_MASK |
+ CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
+ CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
+ CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
+
+ /* Enable CIO error irqs */
+ reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(1),
+ CAL_HL_IRQ_CIO_MASK(ctx->csi2_port));
+ reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
+ cio_err_mask);
+
+ /* Always enable OCPO error */
+ reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(1), CAL_HL_IRQ_OCPO_ERR_MASK);
+
/* Enable IRQ_WDMA_END 0/1 */
- reg_write_field(ctx->dev,
- CAL_HL_IRQENABLE_SET(2),
- CAL_HL_IRQ_ENABLE,
- CAL_HL_IRQ_MASK(ctx->csi2_port));
+ val = 0;
+ set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
+ reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(2), val);
/* Enable IRQ_WDMA_START 0/1 */
- reg_write_field(ctx->dev,
- CAL_HL_IRQENABLE_SET(3),
- CAL_HL_IRQ_ENABLE,
- CAL_HL_IRQ_MASK(ctx->csi2_port));
+ val = 0;
+ set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
+ reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(3), val);
/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0xFF000000);
}
@@ -722,24 +717,59 @@ static void disable_irqs(struct cal_ctx *ctx)
{
u32 val;
+ /* Disable CIO error irqs */
+ reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(1),
+ CAL_HL_IRQ_CIO_MASK(ctx->csi2_port));
+ reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
+ 0);
+
/* Disable IRQ_WDMA_END 0/1 */
val = 0;
- set_field(&val, CAL_HL_IRQ_CLEAR, CAL_HL_IRQ_MASK(ctx->csi2_port));
+ set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(2), val);
/* Disable IRQ_WDMA_START 0/1 */
val = 0;
- set_field(&val, CAL_HL_IRQ_CLEAR, CAL_HL_IRQ_MASK(ctx->csi2_port));
+ set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(3), val);
/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0);
}
+static void csi2_cio_power(struct cal_ctx *ctx, bool enable)
+{
+ u32 target_state;
+ unsigned int i;
+
+ target_state = enable ? CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON :
+ CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF;
+
+ reg_write_field(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+ target_state, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
+
+ for (i = 0; i < 10; i++) {
+ u32 current_state;
+
+ current_state = reg_read_field(ctx->dev,
+ CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+ CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK);
+
+ if (current_state == target_state)
+ break;
+
+ usleep_range(1000, 1100);
+ }
+
+ if (i == 10)
+ ctx_err(ctx, "Failed to power %s complexio\n",
+ enable ? "up" : "down");
+}
+
static void csi2_phy_config(struct cal_ctx *ctx);
static void csi2_phy_init(struct cal_ctx *ctx)
{
- int i;
u32 val;
+ u32 sscounter;
/* Steps
* 1. Configure D-PHY mode and enable required lanes
@@ -762,66 +792,90 @@ static void csi2_phy_init(struct cal_ctx *ctx)
camerarx_phy_enable(ctx);
/* 2. Reset complex IO - Do not wait for reset completion */
- val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
- set_field(&val, CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
- CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
- reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
+ reg_write_field(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+ CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
+ CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x De-assert Complex IO Reset\n",
ctx->csi2_port,
reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)));
- /* Dummy read to allow SCP to complete */
- val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
+ /* Dummy read to allow SCP reset to complete */
+ reg_read(ctx->cc, CAL_CSI2_PHY_REG0);
/* 3.A. Program Phy Timing Parameters */
csi2_phy_config(ctx);
/* 3.B. Program Stop States */
+ /*
+ * The stop-state-counter is based on fclk cycles, and we always use
+ * the x16 and x4 settings, so stop-state-timeout =
+ * fclk-cycle * 16 * 4 * counter.
+ *
+ * Stop-state-timeout must be more than 100us as per CSI2 spec, so we
+ * calculate a timeout that's 100us (rounding up).
+ */
+ sscounter = DIV_ROUND_UP(clk_get_rate(ctx->dev->fclk), 10000 * 16 * 4);
+
val = reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port));
- set_field(&val, CAL_GEN_ENABLE,
- CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK);
- set_field(&val, CAL_GEN_DISABLE,
- CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK);
- set_field(&val, 407, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK);
+ set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK);
+ set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK);
+ set_field(&val, sscounter, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK);
reg_write(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port), val);
ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x Stop States\n",
ctx->csi2_port,
reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)));
/* 4. Force FORCERXMODE */
- val = reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port));
- set_field(&val, CAL_GEN_ENABLE,
- CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK);
- reg_write(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port), val);
+ reg_write_field(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port),
+ 1, CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK);
ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x Force RXMODE\n",
ctx->csi2_port,
reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)));
/* E. Power up the PHY using the complex IO */
- val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
- set_field(&val, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON,
- CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
- reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
+ csi2_cio_power(ctx, true);
+}
- /* F. Wait for power up completion */
- for (i = 0; i < 10; i++) {
+static void csi2_wait_complexio_reset(struct cal_ctx *ctx)
+{
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(750);
+ while (time_before(jiffies, timeout)) {
if (reg_read_field(ctx->dev,
CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
- CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK) ==
- CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON)
+ CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
+ CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
break;
- usleep_range(1000, 1100);
+ usleep_range(500, 5000);
}
- ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Powered UP %s\n",
- ctx->csi2_port,
- reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)),
- (i >= 10) ? "(timeout)" : "");
+
+ if (reg_read_field(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+ CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) !=
+ CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
+ ctx_err(ctx, "Timeout waiting for Complex IO reset done\n");
}
-static void csi2_wait_for_phy(struct cal_ctx *ctx)
+static void csi2_wait_stop_state(struct cal_ctx *ctx)
{
- int i;
+ unsigned long timeout;
+ timeout = jiffies + msecs_to_jiffies(750);
+ while (time_before(jiffies, timeout)) {
+ if (reg_read_field(ctx->dev,
+ CAL_CSI2_TIMING(ctx->csi2_port),
+ CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) == 0)
+ break;
+ usleep_range(500, 5000);
+ }
+
+ if (reg_read_field(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port),
+ CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) != 0)
+ ctx_err(ctx, "Timeout waiting for stop state\n");
+}
+
+static void csi2_wait_for_phy(struct cal_ctx *ctx)
+{
/* Steps
* 2. Wait for completion of reset
* Note if the external sensor is not sending byte clock,
@@ -832,32 +886,10 @@ static void csi2_wait_for_phy(struct cal_ctx *ctx)
*/
/* 2. Wait for reset completion */
- for (i = 0; i < 250; i++) {
- if (reg_read_field(ctx->dev,
- CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
- CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
- CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
- break;
- usleep_range(1000, 1100);
- }
- ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO Reset Done (%d) %s\n",
- ctx->csi2_port,
- reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)), i,
- (i >= 250) ? "(timeout)" : "");
+ csi2_wait_complexio_reset(ctx);
/* 4. G. Wait for all enabled lane to reach stop state */
- for (i = 0; i < 10; i++) {
- if (reg_read_field(ctx->dev,
- CAL_CSI2_TIMING(ctx->csi2_port),
- CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) ==
- CAL_GEN_DISABLE)
- break;
- usleep_range(1000, 1100);
- }
- ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x Stop State Reached %s\n",
- ctx->csi2_port,
- reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)),
- (i >= 10) ? "(timeout)" : "");
+ csi2_wait_stop_state(ctx);
ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x (Bit(31,28) should be set!)\n",
(ctx->csi2_port - 1), reg_read(ctx->cc, CAL_CSI2_PHY_REG1));
@@ -866,33 +898,13 @@ static void csi2_wait_for_phy(struct cal_ctx *ctx)
static void csi2_phy_deinit(struct cal_ctx *ctx)
{
int i;
- u32 val;
- /* Power down the PHY using the complex IO */
- val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
- set_field(&val, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF,
- CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
- reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
-
- /* Wait for power down completion */
- for (i = 0; i < 10; i++) {
- if (reg_read_field(ctx->dev,
- CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
- CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK) ==
- CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_OFF)
- break;
- usleep_range(1000, 1100);
- }
- ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Powered Down %s\n",
- ctx->csi2_port,
- reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)),
- (i >= 10) ? "(timeout)" : "");
+ csi2_cio_power(ctx, false);
/* Assert Comple IO Reset */
- val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
- set_field(&val, CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
- CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
- reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
+ reg_write_field(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+ CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
+ CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
/* Wait for power down completion */
for (i = 0; i < 10; i++) {
@@ -942,14 +954,15 @@ static void csi2_lane_config(struct cal_ctx *ctx)
static void csi2_ppi_enable(struct cal_ctx *ctx)
{
+ reg_write(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port), BIT(3));
reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
- CAL_GEN_ENABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
+ 1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
}
static void csi2_ppi_disable(struct cal_ctx *ctx)
{
reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
- CAL_GEN_DISABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
+ 0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
}
static void csi2_ctx_config(struct cal_ctx *ctx)
@@ -969,8 +982,7 @@ static void csi2_ctx_config(struct cal_ctx *ctx)
set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
/* Virtual Channel from the CSI2 sensor usually 0! */
set_field(&val, ctx->virtual_channel, CAL_CSI2_CTX_VC_MASK);
- /* NUM_LINES_PER_FRAME => 0 means auto detect */
- set_field(&val, 0, CAL_CSI2_CTX_LINES_MASK);
+ set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
CAL_CSI2_CTX_PACK_MODE_MASK);
@@ -1024,7 +1036,7 @@ static void pix_proc_config(struct cal_ctx *ctx)
set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
set_field(&val, ctx->csi2_port, CAL_PIX_PROC_CPORT_MASK);
- set_field(&val, CAL_GEN_ENABLE, CAL_PIX_PROC_EN_MASK);
+ set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
reg_write(ctx->dev, CAL_PIX_PROC(ctx->csi2_port), val);
ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->csi2_port,
reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port)));
@@ -1044,7 +1056,7 @@ static void cal_wr_dma_config(struct cal_ctx *ctx,
CAL_WR_DMA_CTRL_MODE_MASK);
set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
CAL_WR_DMA_CTRL_PATTERN_MASK);
- set_field(&val, CAL_GEN_ENABLE, CAL_WR_DMA_CTRL_STALL_RD_MASK);
+ set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
reg_write(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port), val);
ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->csi2_port,
reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port)));
@@ -1192,57 +1204,74 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
struct cal_dev *dev = (struct cal_dev *)data;
struct cal_ctx *ctx;
struct cal_dmaqueue *dma_q;
- u32 irqst2, irqst3;
+ u32 irqst1, irqst2, irqst3;
+
+ irqst1 = reg_read(dev, CAL_HL_IRQSTATUS(1));
+ if (irqst1) {
+ int i;
+
+ reg_write(dev, CAL_HL_IRQSTATUS(1), irqst1);
+
+ if (irqst1 & CAL_HL_IRQ_OCPO_ERR_MASK)
+ dev_err_ratelimited(&dev->pdev->dev, "OCPO ERROR\n");
+
+ for (i = 1; i <= 2; ++i) {
+ if (irqst1 & CAL_HL_IRQ_CIO_MASK(i)) {
+ u32 cio_stat = reg_read(dev,
+ CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
+
+ dev_err_ratelimited(&dev->pdev->dev,
+ "CIO%d error: %#08x\n", i, cio_stat);
+
+ reg_write(dev, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
+ cio_stat);
+ }
+ }
+ }
/* Check which DMA just finished */
irqst2 = reg_read(dev, CAL_HL_IRQSTATUS(2));
if (irqst2) {
+ int i;
+
/* Clear Interrupt status */
reg_write(dev, CAL_HL_IRQSTATUS(2), irqst2);
- /* Need to check both port */
- if (isportirqset(irqst2, 1)) {
- ctx = dev->ctx[0];
+ for (i = 1; i <= 2; ++i) {
+ if (isportirqset(irqst2, i)) {
+ ctx = dev->ctx[i - 1];
- if (ctx->cur_frm != ctx->next_frm)
- cal_process_buffer_complete(ctx);
- }
+ spin_lock(&ctx->slock);
+ ctx->dma_act = false;
- if (isportirqset(irqst2, 2)) {
- ctx = dev->ctx[1];
+ if (ctx->cur_frm != ctx->next_frm)
+ cal_process_buffer_complete(ctx);
- if (ctx->cur_frm != ctx->next_frm)
- cal_process_buffer_complete(ctx);
+ spin_unlock(&ctx->slock);
+ }
}
}
/* Check which DMA just started */
irqst3 = reg_read(dev, CAL_HL_IRQSTATUS(3));
if (irqst3) {
+ int i;
+
/* Clear Interrupt status */
reg_write(dev, CAL_HL_IRQSTATUS(3), irqst3);
- /* Need to check both port */
- if (isportirqset(irqst3, 1)) {
- ctx = dev->ctx[0];
- dma_q = &ctx->vidq;
-
- spin_lock(&ctx->slock);
- if (!list_empty(&dma_q->active) &&
- ctx->cur_frm == ctx->next_frm)
- cal_schedule_next_buffer(ctx);
- spin_unlock(&ctx->slock);
- }
-
- if (isportirqset(irqst3, 2)) {
- ctx = dev->ctx[1];
- dma_q = &ctx->vidq;
-
- spin_lock(&ctx->slock);
- if (!list_empty(&dma_q->active) &&
- ctx->cur_frm == ctx->next_frm)
- cal_schedule_next_buffer(ctx);
- spin_unlock(&ctx->slock);
+ for (i = 1; i <= 2; ++i) {
+ if (isportirqset(irqst3, i)) {
+ ctx = dev->ctx[i - 1];
+ dma_q = &ctx->vidq;
+
+ spin_lock(&ctx->slock);
+ ctx->dma_act = true;
+ if (!list_empty(&dma_q->active) &&
+ ctx->cur_frm == ctx->next_frm)
+ cal_schedule_next_buffer(ctx);
+ spin_unlock(&ctx->slock);
+ }
}
}
@@ -1665,7 +1694,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
goto err;
}
- cal_runtime_get(ctx->dev);
+ pm_runtime_get_sync(&ctx->dev->pdev->dev);
csi2_ctx_config(ctx);
pix_proc_config(ctx);
@@ -1680,7 +1709,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
if (ret) {
v4l2_subdev_call(ctx->sensor, core, s_power, 0);
ctx_err(ctx, "stream on failed in subdev\n");
- cal_runtime_put(ctx->dev);
+ pm_runtime_put_sync(&ctx->dev->pdev->dev);
goto err;
}
@@ -1711,10 +1740,27 @@ static void cal_stop_streaming(struct vb2_queue *vq)
struct cal_ctx *ctx = vb2_get_drv_priv(vq);
struct cal_dmaqueue *dma_q = &ctx->vidq;
struct cal_buffer *buf, *tmp;
+ unsigned long timeout;
unsigned long flags;
int ret;
+ bool dma_act;
csi2_ppi_disable(ctx);
+
+ /* wait for stream and dma to finish */
+ dma_act = true;
+ timeout = jiffies + msecs_to_jiffies(500);
+ while (dma_act && time_before(jiffies, timeout)) {
+ msleep(50);
+
+ spin_lock_irqsave(&ctx->slock, flags);
+ dma_act = ctx->dma_act;
+ spin_unlock_irqrestore(&ctx->slock, flags);
+ }
+
+ if (dma_act)
+ ctx_err(ctx, "failed to disable dma cleanly\n");
+
disable_irqs(ctx);
csi2_phy_deinit(ctx);
@@ -1743,7 +1789,7 @@ static void cal_stop_streaming(struct vb2_queue *vq)
ctx->next_frm = NULL;
spin_unlock_irqrestore(&ctx->slock, flags);
- cal_runtime_put(ctx->dev);
+ pm_runtime_put_sync(&ctx->dev->pdev->dev);
}
static const struct vb2_ops cal_video_qops = {
@@ -2191,7 +2237,26 @@ err_exit:
return NULL;
}
-static const struct of_device_id cal_of_match[];
+static const struct of_device_id cal_of_match[] = {
+ {
+ .compatible = "ti,dra72-cal",
+ .data = (void *)&dra72x_cal_data,
+ },
+ {
+ .compatible = "ti,dra72-pre-es2-cal",
+ .data = (void *)&dra72x_es1_cal_data,
+ },
+ {
+ .compatible = "ti,dra76-cal",
+ .data = (void *)&dra76x_cal_data,
+ },
+ {
+ .compatible = "ti,am654-cal",
+ .data = (void *)&am654_cal_data,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cal_of_match);
static int cal_probe(struct platform_device *pdev)
{
@@ -2223,6 +2288,12 @@ static int cal_probe(struct platform_device *pdev)
/* save pdev pointer */
dev->pdev = pdev;
+ dev->fclk = devm_clk_get(&pdev->dev, "fck");
+ if (IS_ERR(dev->fclk)) {
+ dev_err(&pdev->dev, "cannot get CAL fclk\n");
+ return PTR_ERR(dev->fclk);
+ }
+
syscon_camerrx = syscon_regmap_lookup_by_phandle(parent,
"ti,camerrx-control");
ret = of_property_read_u32_index(parent, "ti,camerrx-control", 1,
@@ -2296,20 +2367,24 @@ static int cal_probe(struct platform_device *pdev)
return -ENODEV;
}
+ vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
+
pm_runtime_enable(&pdev->dev);
- ret = cal_runtime_get(dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
if (ret)
goto runtime_disable;
/* Just check we can actually access the module */
cal_get_hwinfo(dev);
- cal_runtime_put(dev);
+ pm_runtime_put_sync(&pdev->dev);
return 0;
runtime_disable:
+ vb2_dma_contig_clear_max_seg_size(&pdev->dev);
+
pm_runtime_disable(&pdev->dev);
for (i = 0; i < CAL_NUM_CONTEXT; i++) {
ctx = dev->ctx[i];
@@ -2333,7 +2408,7 @@ static int cal_remove(struct platform_device *pdev)
cal_dbg(1, dev, "Removing %s\n", CAL_MODULE_NAME);
- cal_runtime_get(dev);
+ pm_runtime_get_sync(&pdev->dev);
for (i = 0; i < CAL_NUM_CONTEXT; i++) {
ctx = dev->ctx[i];
@@ -2349,41 +2424,41 @@ static int cal_remove(struct platform_device *pdev)
}
}
- cal_runtime_put(dev);
+ pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ vb2_dma_contig_clear_max_seg_size(&pdev->dev);
+
return 0;
}
-#if defined(CONFIG_OF)
-static const struct of_device_id cal_of_match[] = {
- {
- .compatible = "ti,dra72-cal",
- .data = (void *)&dra72x_cal_data,
- },
- {
- .compatible = "ti,dra72-pre-es2-cal",
- .data = (void *)&dra72x_es1_cal_data,
- },
- {
- .compatible = "ti,dra76-cal",
- .data = (void *)&dra76x_cal_data,
- },
- {
- .compatible = "ti,am654-cal",
- .data = (void *)&am654_cal_data,
- },
- {},
+static int cal_runtime_resume(struct device *dev)
+{
+ struct cal_dev *caldev = dev_get_drvdata(dev);
+
+ if (caldev->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
+ /*
+ * Apply errata on both port everytime we (re-)enable
+ * the clock
+ */
+ i913_errata(caldev, 0);
+ i913_errata(caldev, 1);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops cal_pm_ops = {
+ .runtime_resume = cal_runtime_resume,
};
-MODULE_DEVICE_TABLE(of, cal_of_match);
-#endif
static struct platform_driver cal_pdrv = {
.probe = cal_probe,
.remove = cal_remove,
.driver = {
.name = CAL_MODULE_NAME,
- .of_match_table = of_match_ptr(cal_of_match),
+ .pm = &cal_pm_ops,
+ .of_match_table = cal_of_match,
},
};
diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h
index 0b76d1186074..ac54a2fe7bb6 100644
--- a/drivers/media/platform/ti-vpe/cal_regs.h
+++ b/drivers/media/platform/ti-vpe/cal_regs.h
@@ -101,15 +101,6 @@
#define CM_CTRL_CORE_CAMERRX_CONTROL 0x000
/*********************************************************************
-* Generic value used in various field below
-*********************************************************************/
-
-#define CAL_GEN_DISABLE 0
-#define CAL_GEN_ENABLE 1
-#define CAL_GEN_FALSE 0
-#define CAL_GEN_TRUE 1
-
-/*********************************************************************
* Field Definition Macros
*********************************************************************/
@@ -151,12 +142,11 @@
#define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0 0
#define CAL_HL_IRQ_MASK(m) BIT((m) - 1)
-#define CAL_HL_IRQ_NOACTION 0x0
-#define CAL_HL_IRQ_ENABLE 0x1
-#define CAL_HL_IRQ_CLEAR 0x1
-#define CAL_HL_IRQ_DISABLED 0x0
-#define CAL_HL_IRQ_ENABLED 0x1
-#define CAL_HL_IRQ_PENDING 0x1
+
+#define CAL_HL_IRQ_OCPO_ERR_MASK BIT(6)
+
+#define CAL_HL_IRQ_CIO_MASK(i) BIT(16 + ((i) - 1) * 8)
+#define CAL_HL_IRQ_VC_MASK(i) BIT(17 + ((i) - 1) * 8)
#define CAL_PIX_PROC_EN_MASK BIT(0)
#define CAL_PIX_PROC_EXTRACT_MASK GENMASK(4, 1)
@@ -414,6 +404,7 @@
#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL3_MASK BIT(17)
#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL4_MASK BIT(18)
#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL5_MASK BIT(19)
+#define CAL_CSI2_COMPLEXIO_IRQ_LANE_ERRORS_MASK GENMASK(19, 0)
#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM1_MASK BIT(20)
#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM2_MASK BIT(21)
#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM3_MASK BIT(22)
diff --git a/drivers/media/platform/vicodec/Kconfig b/drivers/media/platform/vicodec/Kconfig
deleted file mode 100644
index 89456665cb16..000000000000
--- a/drivers/media/platform/vicodec/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_VICODEC
- tristate "Virtual Codec Driver"
- depends on VIDEO_DEV && VIDEO_V4L2
- select VIDEOBUF2_VMALLOC
- select V4L2_MEM2MEM_DEV
- help
- Driver for a Virtual Codec
-
- This driver can be compared to the vim2m driver for emulating
- a video device node that exposes an emulated hardware codec.
-
- When in doubt, say N.
diff --git a/drivers/media/platform/vicodec/Makefile b/drivers/media/platform/vicodec/Makefile
deleted file mode 100644
index 01bf7e9308a6..000000000000
--- a/drivers/media/platform/vicodec/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-vicodec-objs := vicodec-core.o codec-fwht.o codec-v4l2-fwht.o
-
-obj-$(CONFIG_VIDEO_VICODEC) += vicodec.o
diff --git a/drivers/media/platform/vicodec/codec-fwht.c b/drivers/media/platform/vicodec/codec-fwht.c
deleted file mode 100644
index 31faf319e508..000000000000
--- a/drivers/media/platform/vicodec/codec-fwht.c
+++ /dev/null
@@ -1,958 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1+
-/*
- * Copyright 2016 Tom aan de Wiel
- * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- *
- * 8x8 Fast Walsh Hadamard Transform in sequency order based on the paper:
- *
- * A Recursive Algorithm for Sequency-Ordered Fast Walsh Transforms,
- * R.D. Brown, 1977
- */
-
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include "codec-fwht.h"
-
-#define OVERFLOW_BIT BIT(14)
-
-/*
- * Note: bit 0 of the header must always be 0. Otherwise it cannot
- * be guaranteed that the magic 8 byte sequence (see below) can
- * never occur in the rlc output.
- */
-#define PFRAME_BIT BIT(15)
-#define DUPS_MASK 0x1ffe
-
-#define PBLOCK 0
-#define IBLOCK 1
-
-#define ALL_ZEROS 15
-
-static const uint8_t zigzag[64] = {
- 0,
- 1, 8,
- 2, 9, 16,
- 3, 10, 17, 24,
- 4, 11, 18, 25, 32,
- 5, 12, 19, 26, 33, 40,
- 6, 13, 20, 27, 34, 41, 48,
- 7, 14, 21, 28, 35, 42, 49, 56,
- 15, 22, 29, 36, 43, 50, 57,
- 23, 30, 37, 44, 51, 58,
- 31, 38, 45, 52, 59,
- 39, 46, 53, 60,
- 47, 54, 61,
- 55, 62,
- 63,
-};
-
-/*
- * noinline_for_stack to work around
- * https://bugs.llvm.org/show_bug.cgi?id=38809
- */
-static int noinline_for_stack
-rlc(const s16 *in, __be16 *output, int blocktype)
-{
- s16 block[8 * 8];
- s16 *wp = block;
- int i = 0;
- int x, y;
- int ret = 0;
-
- /* read in block from framebuffer */
- int lastzero_run = 0;
- int to_encode;
-
- for (y = 0; y < 8; y++) {
- for (x = 0; x < 8; x++) {
- *wp = in[x + y * 8];
- wp++;
- }
- }
-
- /* keep track of amount of trailing zeros */
- for (i = 63; i >= 0 && !block[zigzag[i]]; i--)
- lastzero_run++;
-
- *output++ = (blocktype == PBLOCK ? htons(PFRAME_BIT) : 0);
- ret++;
-
- to_encode = 8 * 8 - (lastzero_run > 14 ? lastzero_run : 0);
-
- i = 0;
- while (i < to_encode) {
- int cnt = 0;
- int tmp;
-
- /* count leading zeros */
- while ((tmp = block[zigzag[i]]) == 0 && cnt < 14) {
- cnt++;
- i++;
- if (i == to_encode) {
- cnt--;
- break;
- }
- }
- /* 4 bits for run, 12 for coefficient (quantization by 4) */
- *output++ = htons((cnt | tmp << 4));
- i++;
- ret++;
- }
- if (lastzero_run > 14) {
- *output = htons(ALL_ZEROS | 0);
- ret++;
- }
-
- return ret;
-}
-
-/*
- * This function will worst-case increase rlc_in by 65*2 bytes:
- * one s16 value for the header and 8 * 8 coefficients of type s16.
- */
-static noinline_for_stack u16
-derlc(const __be16 **rlc_in, s16 *dwht_out, const __be16 *end_of_input)
-{
- /* header */
- const __be16 *input = *rlc_in;
- u16 stat;
- int dec_count = 0;
- s16 block[8 * 8 + 16];
- s16 *wp = block;
- int i;
-
- if (input > end_of_input)
- return OVERFLOW_BIT;
- stat = ntohs(*input++);
-
- /*
- * Now de-compress, it expands one byte to up to 15 bytes
- * (or fills the remainder of the 64 bytes with zeroes if it
- * is the last byte to expand).
- *
- * So block has to be 8 * 8 + 16 bytes, the '+ 16' is to
- * allow for overflow if the incoming data was malformed.
- */
- while (dec_count < 8 * 8) {
- s16 in;
- int length;
- int coeff;
-
- if (input > end_of_input)
- return OVERFLOW_BIT;
- in = ntohs(*input++);
- length = in & 0xf;
- coeff = in >> 4;
-
- /* fill remainder with zeros */
- if (length == 15) {
- for (i = 0; i < 64 - dec_count; i++)
- *wp++ = 0;
- break;
- }
-
- for (i = 0; i < length; i++)
- *wp++ = 0;
- *wp++ = coeff;
- dec_count += length + 1;
- }
-
- wp = block;
-
- for (i = 0; i < 64; i++) {
- int pos = zigzag[i];
- int y = pos / 8;
- int x = pos % 8;
-
- dwht_out[x + y * 8] = *wp++;
- }
- *rlc_in = input;
- return stat;
-}
-
-static const int quant_table[] = {
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 3,
- 2, 2, 2, 2, 2, 2, 3, 6,
- 2, 2, 2, 2, 2, 3, 6, 6,
- 2, 2, 2, 2, 3, 6, 6, 6,
- 2, 2, 2, 3, 6, 6, 6, 6,
- 2, 2, 3, 6, 6, 6, 6, 8,
-};
-
-static const int quant_table_p[] = {
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 6,
- 3, 3, 3, 3, 3, 3, 6, 6,
- 3, 3, 3, 3, 3, 6, 6, 9,
- 3, 3, 3, 3, 6, 6, 9, 9,
- 3, 3, 3, 6, 6, 9, 9, 10,
-};
-
-static void quantize_intra(s16 *coeff, s16 *de_coeff, u16 qp)
-{
- const int *quant = quant_table;
- int i, j;
-
- for (j = 0; j < 8; j++) {
- for (i = 0; i < 8; i++, quant++, coeff++, de_coeff++) {
- *coeff >>= *quant;
- if (*coeff >= -qp && *coeff <= qp)
- *coeff = *de_coeff = 0;
- else
- *de_coeff = *coeff << *quant;
- }
- }
-}
-
-static void dequantize_intra(s16 *coeff)
-{
- const int *quant = quant_table;
- int i, j;
-
- for (j = 0; j < 8; j++)
- for (i = 0; i < 8; i++, quant++, coeff++)
- *coeff <<= *quant;
-}
-
-static void quantize_inter(s16 *coeff, s16 *de_coeff, u16 qp)
-{
- const int *quant = quant_table_p;
- int i, j;
-
- for (j = 0; j < 8; j++) {
- for (i = 0; i < 8; i++, quant++, coeff++, de_coeff++) {
- *coeff >>= *quant;
- if (*coeff >= -qp && *coeff <= qp)
- *coeff = *de_coeff = 0;
- else
- *de_coeff = *coeff << *quant;
- }
- }
-}
-
-static void dequantize_inter(s16 *coeff)
-{
- const int *quant = quant_table_p;
- int i, j;
-
- for (j = 0; j < 8; j++)
- for (i = 0; i < 8; i++, quant++, coeff++)
- *coeff <<= *quant;
-}
-
-static void noinline_for_stack fwht(const u8 *block, s16 *output_block,
- unsigned int stride,
- unsigned int input_step, bool intra)
-{
- /* we'll need more than 8 bits for the transformed coefficients */
- s32 workspace1[8], workspace2[8];
- const u8 *tmp = block;
- s16 *out = output_block;
- int add = intra ? 256 : 0;
- unsigned int i;
-
- /* stage 1 */
- for (i = 0; i < 8; i++, tmp += stride, out += 8) {
- switch (input_step) {
- case 1:
- workspace1[0] = tmp[0] + tmp[1] - add;
- workspace1[1] = tmp[0] - tmp[1];
-
- workspace1[2] = tmp[2] + tmp[3] - add;
- workspace1[3] = tmp[2] - tmp[3];
-
- workspace1[4] = tmp[4] + tmp[5] - add;
- workspace1[5] = tmp[4] - tmp[5];
-
- workspace1[6] = tmp[6] + tmp[7] - add;
- workspace1[7] = tmp[6] - tmp[7];
- break;
- case 2:
- workspace1[0] = tmp[0] + tmp[2] - add;
- workspace1[1] = tmp[0] - tmp[2];
-
- workspace1[2] = tmp[4] + tmp[6] - add;
- workspace1[3] = tmp[4] - tmp[6];
-
- workspace1[4] = tmp[8] + tmp[10] - add;
- workspace1[5] = tmp[8] - tmp[10];
-
- workspace1[6] = tmp[12] + tmp[14] - add;
- workspace1[7] = tmp[12] - tmp[14];
- break;
- case 3:
- workspace1[0] = tmp[0] + tmp[3] - add;
- workspace1[1] = tmp[0] - tmp[3];
-
- workspace1[2] = tmp[6] + tmp[9] - add;
- workspace1[3] = tmp[6] - tmp[9];
-
- workspace1[4] = tmp[12] + tmp[15] - add;
- workspace1[5] = tmp[12] - tmp[15];
-
- workspace1[6] = tmp[18] + tmp[21] - add;
- workspace1[7] = tmp[18] - tmp[21];
- break;
- default:
- workspace1[0] = tmp[0] + tmp[4] - add;
- workspace1[1] = tmp[0] - tmp[4];
-
- workspace1[2] = tmp[8] + tmp[12] - add;
- workspace1[3] = tmp[8] - tmp[12];
-
- workspace1[4] = tmp[16] + tmp[20] - add;
- workspace1[5] = tmp[16] - tmp[20];
-
- workspace1[6] = tmp[24] + tmp[28] - add;
- workspace1[7] = tmp[24] - tmp[28];
- break;
- }
-
- /* stage 2 */
- workspace2[0] = workspace1[0] + workspace1[2];
- workspace2[1] = workspace1[0] - workspace1[2];
- workspace2[2] = workspace1[1] - workspace1[3];
- workspace2[3] = workspace1[1] + workspace1[3];
-
- workspace2[4] = workspace1[4] + workspace1[6];
- workspace2[5] = workspace1[4] - workspace1[6];
- workspace2[6] = workspace1[5] - workspace1[7];
- workspace2[7] = workspace1[5] + workspace1[7];
-
- /* stage 3 */
- out[0] = workspace2[0] + workspace2[4];
- out[1] = workspace2[0] - workspace2[4];
- out[2] = workspace2[1] - workspace2[5];
- out[3] = workspace2[1] + workspace2[5];
- out[4] = workspace2[2] + workspace2[6];
- out[5] = workspace2[2] - workspace2[6];
- out[6] = workspace2[3] - workspace2[7];
- out[7] = workspace2[3] + workspace2[7];
- }
-
- out = output_block;
-
- for (i = 0; i < 8; i++, out++) {
- /* stage 1 */
- workspace1[0] = out[0] + out[1 * 8];
- workspace1[1] = out[0] - out[1 * 8];
-
- workspace1[2] = out[2 * 8] + out[3 * 8];
- workspace1[3] = out[2 * 8] - out[3 * 8];
-
- workspace1[4] = out[4 * 8] + out[5 * 8];
- workspace1[5] = out[4 * 8] - out[5 * 8];
-
- workspace1[6] = out[6 * 8] + out[7 * 8];
- workspace1[7] = out[6 * 8] - out[7 * 8];
-
- /* stage 2 */
- workspace2[0] = workspace1[0] + workspace1[2];
- workspace2[1] = workspace1[0] - workspace1[2];
- workspace2[2] = workspace1[1] - workspace1[3];
- workspace2[3] = workspace1[1] + workspace1[3];
-
- workspace2[4] = workspace1[4] + workspace1[6];
- workspace2[5] = workspace1[4] - workspace1[6];
- workspace2[6] = workspace1[5] - workspace1[7];
- workspace2[7] = workspace1[5] + workspace1[7];
- /* stage 3 */
- out[0 * 8] = workspace2[0] + workspace2[4];
- out[1 * 8] = workspace2[0] - workspace2[4];
- out[2 * 8] = workspace2[1] - workspace2[5];
- out[3 * 8] = workspace2[1] + workspace2[5];
- out[4 * 8] = workspace2[2] + workspace2[6];
- out[5 * 8] = workspace2[2] - workspace2[6];
- out[6 * 8] = workspace2[3] - workspace2[7];
- out[7 * 8] = workspace2[3] + workspace2[7];
- }
-}
-
-/*
- * Not the nicest way of doing it, but P-blocks get twice the range of
- * that of the I-blocks. Therefore we need a type bigger than 8 bits.
- * Furthermore values can be negative... This is just a version that
- * works with 16 signed data
- */
-static void noinline_for_stack
-fwht16(const s16 *block, s16 *output_block, int stride, int intra)
-{
- /* we'll need more than 8 bits for the transformed coefficients */
- s32 workspace1[8], workspace2[8];
- const s16 *tmp = block;
- s16 *out = output_block;
- int i;
-
- for (i = 0; i < 8; i++, tmp += stride, out += 8) {
- /* stage 1 */
- workspace1[0] = tmp[0] + tmp[1];
- workspace1[1] = tmp[0] - tmp[1];
-
- workspace1[2] = tmp[2] + tmp[3];
- workspace1[3] = tmp[2] - tmp[3];
-
- workspace1[4] = tmp[4] + tmp[5];
- workspace1[5] = tmp[4] - tmp[5];
-
- workspace1[6] = tmp[6] + tmp[7];
- workspace1[7] = tmp[6] - tmp[7];
-
- /* stage 2 */
- workspace2[0] = workspace1[0] + workspace1[2];
- workspace2[1] = workspace1[0] - workspace1[2];
- workspace2[2] = workspace1[1] - workspace1[3];
- workspace2[3] = workspace1[1] + workspace1[3];
-
- workspace2[4] = workspace1[4] + workspace1[6];
- workspace2[5] = workspace1[4] - workspace1[6];
- workspace2[6] = workspace1[5] - workspace1[7];
- workspace2[7] = workspace1[5] + workspace1[7];
-
- /* stage 3 */
- out[0] = workspace2[0] + workspace2[4];
- out[1] = workspace2[0] - workspace2[4];
- out[2] = workspace2[1] - workspace2[5];
- out[3] = workspace2[1] + workspace2[5];
- out[4] = workspace2[2] + workspace2[6];
- out[5] = workspace2[2] - workspace2[6];
- out[6] = workspace2[3] - workspace2[7];
- out[7] = workspace2[3] + workspace2[7];
- }
-
- out = output_block;
-
- for (i = 0; i < 8; i++, out++) {
- /* stage 1 */
- workspace1[0] = out[0] + out[1*8];
- workspace1[1] = out[0] - out[1*8];
-
- workspace1[2] = out[2*8] + out[3*8];
- workspace1[3] = out[2*8] - out[3*8];
-
- workspace1[4] = out[4*8] + out[5*8];
- workspace1[5] = out[4*8] - out[5*8];
-
- workspace1[6] = out[6*8] + out[7*8];
- workspace1[7] = out[6*8] - out[7*8];
-
- /* stage 2 */
- workspace2[0] = workspace1[0] + workspace1[2];
- workspace2[1] = workspace1[0] - workspace1[2];
- workspace2[2] = workspace1[1] - workspace1[3];
- workspace2[3] = workspace1[1] + workspace1[3];
-
- workspace2[4] = workspace1[4] + workspace1[6];
- workspace2[5] = workspace1[4] - workspace1[6];
- workspace2[6] = workspace1[5] - workspace1[7];
- workspace2[7] = workspace1[5] + workspace1[7];
-
- /* stage 3 */
- out[0*8] = workspace2[0] + workspace2[4];
- out[1*8] = workspace2[0] - workspace2[4];
- out[2*8] = workspace2[1] - workspace2[5];
- out[3*8] = workspace2[1] + workspace2[5];
- out[4*8] = workspace2[2] + workspace2[6];
- out[5*8] = workspace2[2] - workspace2[6];
- out[6*8] = workspace2[3] - workspace2[7];
- out[7*8] = workspace2[3] + workspace2[7];
- }
-}
-
-static noinline_for_stack void
-ifwht(const s16 *block, s16 *output_block, int intra)
-{
- /*
- * we'll need more than 8 bits for the transformed coefficients
- * use native unit of cpu
- */
- int workspace1[8], workspace2[8];
- int inter = intra ? 0 : 1;
- const s16 *tmp = block;
- s16 *out = output_block;
- int i;
-
- for (i = 0; i < 8; i++, tmp += 8, out += 8) {
- /* stage 1 */
- workspace1[0] = tmp[0] + tmp[1];
- workspace1[1] = tmp[0] - tmp[1];
-
- workspace1[2] = tmp[2] + tmp[3];
- workspace1[3] = tmp[2] - tmp[3];
-
- workspace1[4] = tmp[4] + tmp[5];
- workspace1[5] = tmp[4] - tmp[5];
-
- workspace1[6] = tmp[6] + tmp[7];
- workspace1[7] = tmp[6] - tmp[7];
-
- /* stage 2 */
- workspace2[0] = workspace1[0] + workspace1[2];
- workspace2[1] = workspace1[0] - workspace1[2];
- workspace2[2] = workspace1[1] - workspace1[3];
- workspace2[3] = workspace1[1] + workspace1[3];
-
- workspace2[4] = workspace1[4] + workspace1[6];
- workspace2[5] = workspace1[4] - workspace1[6];
- workspace2[6] = workspace1[5] - workspace1[7];
- workspace2[7] = workspace1[5] + workspace1[7];
-
- /* stage 3 */
- out[0] = workspace2[0] + workspace2[4];
- out[1] = workspace2[0] - workspace2[4];
- out[2] = workspace2[1] - workspace2[5];
- out[3] = workspace2[1] + workspace2[5];
- out[4] = workspace2[2] + workspace2[6];
- out[5] = workspace2[2] - workspace2[6];
- out[6] = workspace2[3] - workspace2[7];
- out[7] = workspace2[3] + workspace2[7];
- }
-
- out = output_block;
-
- for (i = 0; i < 8; i++, out++) {
- /* stage 1 */
- workspace1[0] = out[0] + out[1 * 8];
- workspace1[1] = out[0] - out[1 * 8];
-
- workspace1[2] = out[2 * 8] + out[3 * 8];
- workspace1[3] = out[2 * 8] - out[3 * 8];
-
- workspace1[4] = out[4 * 8] + out[5 * 8];
- workspace1[5] = out[4 * 8] - out[5 * 8];
-
- workspace1[6] = out[6 * 8] + out[7 * 8];
- workspace1[7] = out[6 * 8] - out[7 * 8];
-
- /* stage 2 */
- workspace2[0] = workspace1[0] + workspace1[2];
- workspace2[1] = workspace1[0] - workspace1[2];
- workspace2[2] = workspace1[1] - workspace1[3];
- workspace2[3] = workspace1[1] + workspace1[3];
-
- workspace2[4] = workspace1[4] + workspace1[6];
- workspace2[5] = workspace1[4] - workspace1[6];
- workspace2[6] = workspace1[5] - workspace1[7];
- workspace2[7] = workspace1[5] + workspace1[7];
-
- /* stage 3 */
- if (inter) {
- int d;
-
- out[0 * 8] = workspace2[0] + workspace2[4];
- out[1 * 8] = workspace2[0] - workspace2[4];
- out[2 * 8] = workspace2[1] - workspace2[5];
- out[3 * 8] = workspace2[1] + workspace2[5];
- out[4 * 8] = workspace2[2] + workspace2[6];
- out[5 * 8] = workspace2[2] - workspace2[6];
- out[6 * 8] = workspace2[3] - workspace2[7];
- out[7 * 8] = workspace2[3] + workspace2[7];
-
- for (d = 0; d < 8; d++)
- out[8 * d] >>= 6;
- } else {
- int d;
-
- out[0 * 8] = workspace2[0] + workspace2[4];
- out[1 * 8] = workspace2[0] - workspace2[4];
- out[2 * 8] = workspace2[1] - workspace2[5];
- out[3 * 8] = workspace2[1] + workspace2[5];
- out[4 * 8] = workspace2[2] + workspace2[6];
- out[5 * 8] = workspace2[2] - workspace2[6];
- out[6 * 8] = workspace2[3] - workspace2[7];
- out[7 * 8] = workspace2[3] + workspace2[7];
-
- for (d = 0; d < 8; d++) {
- out[8 * d] >>= 6;
- out[8 * d] += 128;
- }
- }
- }
-}
-
-static void fill_encoder_block(const u8 *input, s16 *dst,
- unsigned int stride, unsigned int input_step)
-{
- int i, j;
-
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 8; j++, input += input_step)
- *dst++ = *input;
- input += stride - 8 * input_step;
- }
-}
-
-static int var_intra(const s16 *input)
-{
- int32_t mean = 0;
- int32_t ret = 0;
- const s16 *tmp = input;
- int i;
-
- for (i = 0; i < 8 * 8; i++, tmp++)
- mean += *tmp;
- mean /= 64;
- tmp = input;
- for (i = 0; i < 8 * 8; i++, tmp++)
- ret += (*tmp - mean) < 0 ? -(*tmp - mean) : (*tmp - mean);
- return ret;
-}
-
-static int var_inter(const s16 *old, const s16 *new)
-{
- int32_t ret = 0;
- int i;
-
- for (i = 0; i < 8 * 8; i++, old++, new++)
- ret += (*old - *new) < 0 ? -(*old - *new) : (*old - *new);
- return ret;
-}
-
-static noinline_for_stack int
-decide_blocktype(const u8 *cur, const u8 *reference, s16 *deltablock,
- unsigned int stride, unsigned int input_step)
-{
- s16 tmp[64];
- s16 old[64];
- s16 *work = tmp;
- unsigned int k, l;
- int vari;
- int vard;
-
- fill_encoder_block(cur, tmp, stride, input_step);
- fill_encoder_block(reference, old, 8, 1);
- vari = var_intra(tmp);
-
- for (k = 0; k < 8; k++) {
- for (l = 0; l < 8; l++) {
- *deltablock = *work - *reference;
- deltablock++;
- work++;
- reference++;
- }
- }
- deltablock -= 64;
- vard = var_inter(old, tmp);
- return vari <= vard ? IBLOCK : PBLOCK;
-}
-
-static void fill_decoder_block(u8 *dst, const s16 *input, int stride,
- unsigned int dst_step)
-{
- int i, j;
-
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 8; j++, input++, dst += dst_step) {
- if (*input < 0)
- *dst = 0;
- else if (*input > 255)
- *dst = 255;
- else
- *dst = *input;
- }
- dst += stride - (8 * dst_step);
- }
-}
-
-static void add_deltas(s16 *deltas, const u8 *ref, int stride,
- unsigned int ref_step)
-{
- int k, l;
-
- for (k = 0; k < 8; k++) {
- for (l = 0; l < 8; l++) {
- *deltas += *ref;
- ref += ref_step;
- /*
- * Due to quantizing, it might possible that the
- * decoded coefficients are slightly out of range
- */
- if (*deltas < 0)
- *deltas = 0;
- else if (*deltas > 255)
- *deltas = 255;
- deltas++;
- }
- ref += stride - (8 * ref_step);
- }
-}
-
-static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
- struct fwht_cframe *cf, u32 height, u32 width,
- u32 stride, unsigned int input_step,
- bool is_intra, bool next_is_intra)
-{
- u8 *input_start = input;
- __be16 *rlco_start = *rlco;
- s16 deltablock[64];
- __be16 pframe_bit = htons(PFRAME_BIT);
- u32 encoding = 0;
- unsigned int last_size = 0;
- unsigned int i, j;
-
- width = round_up(width, 8);
- height = round_up(height, 8);
-
- for (j = 0; j < height / 8; j++) {
- input = input_start + j * 8 * stride;
- for (i = 0; i < width / 8; i++) {
- /* intra code, first frame is always intra coded. */
- int blocktype = IBLOCK;
- unsigned int size;
-
- if (!is_intra)
- blocktype = decide_blocktype(input, refp,
- deltablock, stride, input_step);
- if (blocktype == IBLOCK) {
- fwht(input, cf->coeffs, stride, input_step, 1);
- quantize_intra(cf->coeffs, cf->de_coeffs,
- cf->i_frame_qp);
- } else {
- /* inter code */
- encoding |= FWHT_FRAME_PCODED;
- fwht16(deltablock, cf->coeffs, 8, 0);
- quantize_inter(cf->coeffs, cf->de_coeffs,
- cf->p_frame_qp);
- }
- if (!next_is_intra) {
- ifwht(cf->de_coeffs, cf->de_fwht, blocktype);
-
- if (blocktype == PBLOCK)
- add_deltas(cf->de_fwht, refp, 8, 1);
- fill_decoder_block(refp, cf->de_fwht, 8, 1);
- }
-
- input += 8 * input_step;
- refp += 8 * 8;
-
- size = rlc(cf->coeffs, *rlco, blocktype);
- if (last_size == size &&
- !memcmp(*rlco + 1, *rlco - size + 1, 2 * size - 2)) {
- __be16 *last_rlco = *rlco - size;
- s16 hdr = ntohs(*last_rlco);
-
- if (!((*last_rlco ^ **rlco) & pframe_bit) &&
- (hdr & DUPS_MASK) < DUPS_MASK)
- *last_rlco = htons(hdr + 2);
- else
- *rlco += size;
- } else {
- *rlco += size;
- }
- if (*rlco >= rlco_max) {
- encoding |= FWHT_FRAME_UNENCODED;
- goto exit_loop;
- }
- last_size = size;
- }
- }
-
-exit_loop:
- if (encoding & FWHT_FRAME_UNENCODED) {
- u8 *out = (u8 *)rlco_start;
- u8 *p;
-
- input = input_start;
- /*
- * The compressed stream should never contain the magic
- * header, so when we copy the YUV data we replace 0xff
- * by 0xfe. Since YUV is limited range such values
- * shouldn't appear anyway.
- */
- for (j = 0; j < height; j++) {
- for (i = 0, p = input; i < width; i++, p += input_step)
- *out++ = (*p == 0xff) ? 0xfe : *p;
- input += stride;
- }
- *rlco = (__be16 *)out;
- encoding &= ~FWHT_FRAME_PCODED;
- }
- return encoding;
-}
-
-u32 fwht_encode_frame(struct fwht_raw_frame *frm,
- struct fwht_raw_frame *ref_frm,
- struct fwht_cframe *cf,
- bool is_intra, bool next_is_intra,
- unsigned int width, unsigned int height,
- unsigned int stride, unsigned int chroma_stride)
-{
- unsigned int size = height * width;
- __be16 *rlco = cf->rlc_data;
- __be16 *rlco_max;
- u32 encoding;
-
- rlco_max = rlco + size / 2 - 256;
- encoding = encode_plane(frm->luma, ref_frm->luma, &rlco, rlco_max, cf,
- height, width, stride,
- frm->luma_alpha_step, is_intra, next_is_intra);
- if (encoding & FWHT_FRAME_UNENCODED)
- encoding |= FWHT_LUMA_UNENCODED;
- encoding &= ~FWHT_FRAME_UNENCODED;
-
- if (frm->components_num >= 3) {
- u32 chroma_h = height / frm->height_div;
- u32 chroma_w = width / frm->width_div;
- unsigned int chroma_size = chroma_h * chroma_w;
-
- rlco_max = rlco + chroma_size / 2 - 256;
- encoding |= encode_plane(frm->cb, ref_frm->cb, &rlco, rlco_max,
- cf, chroma_h, chroma_w,
- chroma_stride, frm->chroma_step,
- is_intra, next_is_intra);
- if (encoding & FWHT_FRAME_UNENCODED)
- encoding |= FWHT_CB_UNENCODED;
- encoding &= ~FWHT_FRAME_UNENCODED;
- rlco_max = rlco + chroma_size / 2 - 256;
- encoding |= encode_plane(frm->cr, ref_frm->cr, &rlco, rlco_max,
- cf, chroma_h, chroma_w,
- chroma_stride, frm->chroma_step,
- is_intra, next_is_intra);
- if (encoding & FWHT_FRAME_UNENCODED)
- encoding |= FWHT_CR_UNENCODED;
- encoding &= ~FWHT_FRAME_UNENCODED;
- }
-
- if (frm->components_num == 4) {
- rlco_max = rlco + size / 2 - 256;
- encoding |= encode_plane(frm->alpha, ref_frm->alpha, &rlco,
- rlco_max, cf, height, width,
- stride, frm->luma_alpha_step,
- is_intra, next_is_intra);
- if (encoding & FWHT_FRAME_UNENCODED)
- encoding |= FWHT_ALPHA_UNENCODED;
- encoding &= ~FWHT_FRAME_UNENCODED;
- }
-
- cf->size = (rlco - cf->rlc_data) * sizeof(*rlco);
- return encoding;
-}
-
-static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco,
- u32 height, u32 width, const u8 *ref, u32 ref_stride,
- unsigned int ref_step, u8 *dst,
- unsigned int dst_stride, unsigned int dst_step,
- bool uncompressed, const __be16 *end_of_rlco_buf)
-{
- unsigned int copies = 0;
- s16 copy[8 * 8];
- u16 stat;
- unsigned int i, j;
- bool is_intra = !ref;
-
- width = round_up(width, 8);
- height = round_up(height, 8);
-
- if (uncompressed) {
- int i;
-
- if (end_of_rlco_buf + 1 < *rlco + width * height / 2)
- return false;
- for (i = 0; i < height; i++) {
- memcpy(dst, *rlco, width);
- dst += dst_stride;
- *rlco += width / 2;
- }
- return true;
- }
-
- /*
- * When decoding each macroblock the rlco pointer will be increased
- * by 65 * 2 bytes worst-case.
- * To avoid overflow the buffer has to be 65/64th of the actual raw
- * image size, just in case someone feeds it malicious data.
- */
- for (j = 0; j < height / 8; j++) {
- for (i = 0; i < width / 8; i++) {
- const u8 *refp = ref + j * 8 * ref_stride +
- i * 8 * ref_step;
- u8 *dstp = dst + j * 8 * dst_stride + i * 8 * dst_step;
-
- if (copies) {
- memcpy(cf->de_fwht, copy, sizeof(copy));
- if ((stat & PFRAME_BIT) && !is_intra)
- add_deltas(cf->de_fwht, refp,
- ref_stride, ref_step);
- fill_decoder_block(dstp, cf->de_fwht,
- dst_stride, dst_step);
- copies--;
- continue;
- }
-
- stat = derlc(rlco, cf->coeffs, end_of_rlco_buf);
- if (stat & OVERFLOW_BIT)
- return false;
- if ((stat & PFRAME_BIT) && !is_intra)
- dequantize_inter(cf->coeffs);
- else
- dequantize_intra(cf->coeffs);
-
- ifwht(cf->coeffs, cf->de_fwht,
- ((stat & PFRAME_BIT) && !is_intra) ? 0 : 1);
-
- copies = (stat & DUPS_MASK) >> 1;
- if (copies)
- memcpy(copy, cf->de_fwht, sizeof(copy));
- if ((stat & PFRAME_BIT) && !is_intra)
- add_deltas(cf->de_fwht, refp,
- ref_stride, ref_step);
- fill_decoder_block(dstp, cf->de_fwht, dst_stride,
- dst_step);
- }
- }
- return true;
-}
-
-bool fwht_decode_frame(struct fwht_cframe *cf, u32 hdr_flags,
- unsigned int components_num, unsigned int width,
- unsigned int height, const struct fwht_raw_frame *ref,
- unsigned int ref_stride, unsigned int ref_chroma_stride,
- struct fwht_raw_frame *dst, unsigned int dst_stride,
- unsigned int dst_chroma_stride)
-{
- const __be16 *rlco = cf->rlc_data;
- const __be16 *end_of_rlco_buf = cf->rlc_data +
- (cf->size / sizeof(*rlco)) - 1;
-
- if (!decode_plane(cf, &rlco, height, width, ref->luma, ref_stride,
- ref->luma_alpha_step, dst->luma, dst_stride,
- dst->luma_alpha_step,
- hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED,
- end_of_rlco_buf))
- return false;
-
- if (components_num >= 3) {
- u32 h = height;
- u32 w = width;
-
- if (!(hdr_flags & FWHT_FL_CHROMA_FULL_HEIGHT))
- h /= 2;
- if (!(hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH))
- w /= 2;
-
- if (!decode_plane(cf, &rlco, h, w, ref->cb, ref_chroma_stride,
- ref->chroma_step, dst->cb, dst_chroma_stride,
- dst->chroma_step,
- hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED,
- end_of_rlco_buf))
- return false;
- if (!decode_plane(cf, &rlco, h, w, ref->cr, ref_chroma_stride,
- ref->chroma_step, dst->cr, dst_chroma_stride,
- dst->chroma_step,
- hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED,
- end_of_rlco_buf))
- return false;
- }
-
- if (components_num == 4)
- if (!decode_plane(cf, &rlco, height, width, ref->alpha, ref_stride,
- ref->luma_alpha_step, dst->alpha, dst_stride,
- dst->luma_alpha_step,
- hdr_flags & FWHT_FL_ALPHA_IS_UNCOMPRESSED,
- end_of_rlco_buf))
- return false;
- return true;
-}
diff --git a/drivers/media/platform/vicodec/codec-fwht.h b/drivers/media/platform/vicodec/codec-fwht.h
deleted file mode 100644
index b6fec2b1cbca..000000000000
--- a/drivers/media/platform/vicodec/codec-fwht.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * Copyright 2016 Tom aan de Wiel
- * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef CODEC_FWHT_H
-#define CODEC_FWHT_H
-
-#include <linux/types.h>
-#include <linux/bitops.h>
-#include <asm/byteorder.h>
-
-/*
- * The compressed format consists of a fwht_cframe_hdr struct followed by the
- * compressed frame data. The header contains the size of that data.
- * Each Y, Cb and Cr plane is compressed separately. If the compressed
- * size of each plane becomes larger than the uncompressed size, then
- * that plane is stored uncompressed and the corresponding bit is set
- * in the flags field of the header.
- *
- * Each compressed plane consists of macroblocks and each macroblock
- * is run-length-encoded. Each macroblock starts with a 16 bit value.
- * Bit 15 indicates if this is a P-coded macroblock (1) or not (0).
- * P-coded macroblocks contain a delta against the previous frame.
- *
- * Bits 1-12 contain a number. If non-zero, then this same macroblock
- * repeats that number of times. This results in a high degree of
- * compression for generated images like colorbars.
- *
- * Following this macroblock header the MB coefficients are run-length
- * encoded: the top 12 bits contain the coefficient, the bottom 4 bits
- * tell how many times this coefficient occurs. The value 0xf indicates
- * that the remainder of the macroblock should be filled with zeroes.
- *
- * All 16 and 32 bit values are stored in big-endian (network) order.
- *
- * Each fwht_cframe_hdr starts with an 8 byte magic header that is
- * guaranteed not to occur in the compressed frame data. This header
- * can be used to sync to the next frame.
- *
- * This codec uses the Fast Walsh Hadamard Transform. Tom aan de Wiel
- * developed this as part of a university project, specifically for use
- * with this driver. His project report can be found here:
- *
- * https://hverkuil.home.xs4all.nl/fwht.pdf
- */
-
-/*
- * This is a sequence of 8 bytes with the low 4 bits set to 0xf.
- *
- * This sequence cannot occur in the encoded data
- *
- * Note that these two magic values are symmetrical so endian issues here.
- */
-#define FWHT_MAGIC1 0x4f4f4f4f
-#define FWHT_MAGIC2 0xffffffff
-
-#define FWHT_VERSION 3
-
-/* Set if this is an interlaced format */
-#define FWHT_FL_IS_INTERLACED BIT(0)
-/* Set if this is a bottom-first (NTSC) interlaced format */
-#define FWHT_FL_IS_BOTTOM_FIRST BIT(1)
-/* Set if each 'frame' contains just one field */
-#define FWHT_FL_IS_ALTERNATE BIT(2)
-/*
- * If FWHT_FL_IS_ALTERNATE was set, then this is set if this
- * 'frame' is the bottom field, else it is the top field.
- */
-#define FWHT_FL_IS_BOTTOM_FIELD BIT(3)
-/* Set if this frame is uncompressed */
-#define FWHT_FL_LUMA_IS_UNCOMPRESSED BIT(4)
-#define FWHT_FL_CB_IS_UNCOMPRESSED BIT(5)
-#define FWHT_FL_CR_IS_UNCOMPRESSED BIT(6)
-#define FWHT_FL_CHROMA_FULL_HEIGHT BIT(7)
-#define FWHT_FL_CHROMA_FULL_WIDTH BIT(8)
-#define FWHT_FL_ALPHA_IS_UNCOMPRESSED BIT(9)
-#define FWHT_FL_I_FRAME BIT(10)
-
-/* A 4-values flag - the number of components - 1 */
-#define FWHT_FL_COMPONENTS_NUM_MSK GENMASK(18, 16)
-#define FWHT_FL_COMPONENTS_NUM_OFFSET 16
-
-#define FWHT_FL_PIXENC_MSK GENMASK(20, 19)
-#define FWHT_FL_PIXENC_OFFSET 19
-#define FWHT_FL_PIXENC_YUV (1 << FWHT_FL_PIXENC_OFFSET)
-#define FWHT_FL_PIXENC_RGB (2 << FWHT_FL_PIXENC_OFFSET)
-#define FWHT_FL_PIXENC_HSV (3 << FWHT_FL_PIXENC_OFFSET)
-
-/*
- * A macro to calculate the needed padding in order to make sure
- * both luma and chroma components resolutions are rounded up to
- * a multiple of 8
- */
-#define vic_round_dim(dim, div) (round_up((dim) / (div), 8) * (div))
-
-struct fwht_cframe_hdr {
- u32 magic1;
- u32 magic2;
- __be32 version;
- __be32 width, height;
- __be32 flags;
- __be32 colorspace;
- __be32 xfer_func;
- __be32 ycbcr_enc;
- __be32 quantization;
- __be32 size;
-};
-
-struct fwht_cframe {
- u16 i_frame_qp;
- u16 p_frame_qp;
- __be16 *rlc_data;
- s16 coeffs[8 * 8];
- s16 de_coeffs[8 * 8];
- s16 de_fwht[8 * 8];
- u32 size;
-};
-
-struct fwht_raw_frame {
- unsigned int width_div;
- unsigned int height_div;
- unsigned int luma_alpha_step;
- unsigned int chroma_step;
- unsigned int components_num;
- u8 *buf;
- u8 *luma, *cb, *cr, *alpha;
-};
-
-#define FWHT_FRAME_PCODED BIT(0)
-#define FWHT_FRAME_UNENCODED BIT(1)
-#define FWHT_LUMA_UNENCODED BIT(2)
-#define FWHT_CB_UNENCODED BIT(3)
-#define FWHT_CR_UNENCODED BIT(4)
-#define FWHT_ALPHA_UNENCODED BIT(5)
-
-u32 fwht_encode_frame(struct fwht_raw_frame *frm,
- struct fwht_raw_frame *ref_frm,
- struct fwht_cframe *cf,
- bool is_intra, bool next_is_intra,
- unsigned int width, unsigned int height,
- unsigned int stride, unsigned int chroma_stride);
-bool fwht_decode_frame(struct fwht_cframe *cf, u32 hdr_flags,
- unsigned int components_num, unsigned int width,
- unsigned int height, const struct fwht_raw_frame *ref,
- unsigned int ref_stride, unsigned int ref_chroma_stride,
- struct fwht_raw_frame *dst, unsigned int dst_stride,
- unsigned int dst_chroma_stride);
-#endif
diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c
deleted file mode 100644
index b6e39fbd8ad5..000000000000
--- a/drivers/media/platform/vicodec/codec-v4l2-fwht.c
+++ /dev/null
@@ -1,367 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- * A V4L2 frontend for the FWHT codec
- *
- * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/videodev2.h>
-#include "codec-v4l2-fwht.h"
-
-static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = {
- { V4L2_PIX_FMT_YUV420, 1, 3, 2, 1, 1, 2, 2, 3, 3, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_YVU420, 1, 3, 2, 1, 1, 2, 2, 3, 3, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1, 3, 3, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_NV12, 1, 3, 2, 1, 2, 2, 2, 3, 2, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_NV21, 1, 3, 2, 1, 2, 2, 2, 3, 2, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_NV16, 1, 2, 1, 1, 2, 2, 1, 3, 2, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_NV61, 1, 2, 1, 1, 2, 2, 1, 3, 2, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_NV24, 1, 3, 1, 1, 2, 1, 1, 3, 2, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_NV42, 1, 3, 1, 1, 2, 1, 1, 3, 2, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_YUYV, 2, 2, 1, 2, 4, 2, 1, 3, 1, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_YVYU, 2, 2, 1, 2, 4, 2, 1, 3, 1, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_UYVY, 2, 2, 1, 2, 4, 2, 1, 3, 1, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_VYUY, 2, 2, 1, 2, 4, 2, 1, 3, 1, FWHT_FL_PIXENC_YUV},
- { V4L2_PIX_FMT_BGR24, 3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_RGB24, 3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_HSV24, 3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV},
- { V4L2_PIX_FMT_BGR32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_XBGR32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_ABGR32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_RGB32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_XRGB32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_ARGB32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_BGRX32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_BGRA32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_RGBX32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_RGBA32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
- { V4L2_PIX_FMT_HSV32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_HSV},
- { V4L2_PIX_FMT_GREY, 1, 1, 1, 1, 0, 1, 1, 1, 1, FWHT_FL_PIXENC_RGB},
-};
-
-bool v4l2_fwht_validate_fmt(const struct v4l2_fwht_pixfmt_info *info,
- u32 width_div, u32 height_div, u32 components_num,
- u32 pixenc)
-{
- if (info->width_div == width_div &&
- info->height_div == height_div &&
- (!pixenc || info->pixenc == pixenc) &&
- info->components_num == components_num)
- return true;
- return false;
-}
-
-const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_nth_fmt(u32 width_div,
- u32 height_div,
- u32 components_num,
- u32 pixenc,
- unsigned int start_idx)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(v4l2_fwht_pixfmts); i++) {
- bool is_valid = v4l2_fwht_validate_fmt(&v4l2_fwht_pixfmts[i],
- width_div, height_div,
- components_num, pixenc);
- if (is_valid) {
- if (start_idx == 0)
- return v4l2_fwht_pixfmts + i;
- start_idx--;
- }
- }
- return NULL;
-}
-
-const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(v4l2_fwht_pixfmts); i++)
- if (v4l2_fwht_pixfmts[i].id == pixelformat)
- return v4l2_fwht_pixfmts + i;
- return NULL;
-}
-
-const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx)
-{
- if (idx >= ARRAY_SIZE(v4l2_fwht_pixfmts))
- return NULL;
- return v4l2_fwht_pixfmts + idx;
-}
-
-static int prepare_raw_frame(struct fwht_raw_frame *rf,
- const struct v4l2_fwht_pixfmt_info *info, u8 *buf,
- unsigned int size)
-{
- rf->luma = buf;
- rf->width_div = info->width_div;
- rf->height_div = info->height_div;
- rf->luma_alpha_step = info->luma_alpha_step;
- rf->chroma_step = info->chroma_step;
- rf->alpha = NULL;
- rf->components_num = info->components_num;
-
- /*
- * The buffer is NULL if it is the reference
- * frame of an I-frame in the stateless decoder
- */
- if (!buf) {
- rf->luma = NULL;
- rf->cb = NULL;
- rf->cr = NULL;
- rf->alpha = NULL;
- return 0;
- }
- switch (info->id) {
- case V4L2_PIX_FMT_GREY:
- rf->cb = NULL;
- rf->cr = NULL;
- break;
- case V4L2_PIX_FMT_YUV420:
- rf->cb = rf->luma + size;
- rf->cr = rf->cb + size / 4;
- break;
- case V4L2_PIX_FMT_YVU420:
- rf->cr = rf->luma + size;
- rf->cb = rf->cr + size / 4;
- break;
- case V4L2_PIX_FMT_YUV422P:
- rf->cb = rf->luma + size;
- rf->cr = rf->cb + size / 2;
- break;
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV24:
- rf->cb = rf->luma + size;
- rf->cr = rf->cb + 1;
- break;
- case V4L2_PIX_FMT_NV21:
- case V4L2_PIX_FMT_NV61:
- case V4L2_PIX_FMT_NV42:
- rf->cr = rf->luma + size;
- rf->cb = rf->cr + 1;
- break;
- case V4L2_PIX_FMT_YUYV:
- rf->cb = rf->luma + 1;
- rf->cr = rf->cb + 2;
- break;
- case V4L2_PIX_FMT_YVYU:
- rf->cr = rf->luma + 1;
- rf->cb = rf->cr + 2;
- break;
- case V4L2_PIX_FMT_UYVY:
- rf->cb = rf->luma;
- rf->cr = rf->cb + 2;
- rf->luma++;
- break;
- case V4L2_PIX_FMT_VYUY:
- rf->cr = rf->luma;
- rf->cb = rf->cr + 2;
- rf->luma++;
- break;
- case V4L2_PIX_FMT_RGB24:
- case V4L2_PIX_FMT_HSV24:
- rf->cr = rf->luma;
- rf->cb = rf->cr + 2;
- rf->luma++;
- break;
- case V4L2_PIX_FMT_BGR24:
- rf->cb = rf->luma;
- rf->cr = rf->cb + 2;
- rf->luma++;
- break;
- case V4L2_PIX_FMT_RGB32:
- case V4L2_PIX_FMT_XRGB32:
- case V4L2_PIX_FMT_HSV32:
- case V4L2_PIX_FMT_ARGB32:
- rf->alpha = rf->luma;
- rf->cr = rf->luma + 1;
- rf->cb = rf->cr + 2;
- rf->luma += 2;
- break;
- case V4L2_PIX_FMT_BGR32:
- case V4L2_PIX_FMT_XBGR32:
- case V4L2_PIX_FMT_ABGR32:
- rf->cb = rf->luma;
- rf->cr = rf->cb + 2;
- rf->luma++;
- rf->alpha = rf->cr + 1;
- break;
- case V4L2_PIX_FMT_BGRX32:
- case V4L2_PIX_FMT_BGRA32:
- rf->alpha = rf->luma;
- rf->cb = rf->luma + 1;
- rf->cr = rf->cb + 2;
- rf->luma += 2;
- break;
- case V4L2_PIX_FMT_RGBX32:
- case V4L2_PIX_FMT_RGBA32:
- rf->alpha = rf->luma + 3;
- rf->cr = rf->luma;
- rf->cb = rf->cr + 2;
- rf->luma++;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
-{
- unsigned int size = state->stride * state->coded_height;
- unsigned int chroma_stride = state->stride;
- const struct v4l2_fwht_pixfmt_info *info = state->info;
- struct fwht_cframe_hdr *p_hdr;
- struct fwht_cframe cf;
- struct fwht_raw_frame rf;
- u32 encoding;
- u32 flags = 0;
-
- if (!info)
- return -EINVAL;
-
- if (prepare_raw_frame(&rf, info, p_in, size))
- return -EINVAL;
-
- if (info->planes_num == 3)
- chroma_stride /= 2;
-
- if (info->id == V4L2_PIX_FMT_NV24 ||
- info->id == V4L2_PIX_FMT_NV42)
- chroma_stride *= 2;
-
- cf.i_frame_qp = state->i_frame_qp;
- cf.p_frame_qp = state->p_frame_qp;
- cf.rlc_data = (__be16 *)(p_out + sizeof(*p_hdr));
-
- encoding = fwht_encode_frame(&rf, &state->ref_frame, &cf,
- !state->gop_cnt,
- state->gop_cnt == state->gop_size - 1,
- state->visible_width,
- state->visible_height,
- state->stride, chroma_stride);
- if (!(encoding & FWHT_FRAME_PCODED))
- state->gop_cnt = 0;
- if (++state->gop_cnt >= state->gop_size)
- state->gop_cnt = 0;
-
- p_hdr = (struct fwht_cframe_hdr *)p_out;
- p_hdr->magic1 = FWHT_MAGIC1;
- p_hdr->magic2 = FWHT_MAGIC2;
- p_hdr->version = htonl(FWHT_VERSION);
- p_hdr->width = htonl(state->visible_width);
- p_hdr->height = htonl(state->visible_height);
- flags |= (info->components_num - 1) << FWHT_FL_COMPONENTS_NUM_OFFSET;
- flags |= info->pixenc;
- if (encoding & FWHT_LUMA_UNENCODED)
- flags |= FWHT_FL_LUMA_IS_UNCOMPRESSED;
- if (encoding & FWHT_CB_UNENCODED)
- flags |= FWHT_FL_CB_IS_UNCOMPRESSED;
- if (encoding & FWHT_CR_UNENCODED)
- flags |= FWHT_FL_CR_IS_UNCOMPRESSED;
- if (encoding & FWHT_ALPHA_UNENCODED)
- flags |= FWHT_FL_ALPHA_IS_UNCOMPRESSED;
- if (!(encoding & FWHT_FRAME_PCODED))
- flags |= FWHT_FL_I_FRAME;
- if (rf.height_div == 1)
- flags |= FWHT_FL_CHROMA_FULL_HEIGHT;
- if (rf.width_div == 1)
- flags |= FWHT_FL_CHROMA_FULL_WIDTH;
- p_hdr->flags = htonl(flags);
- p_hdr->colorspace = htonl(state->colorspace);
- p_hdr->xfer_func = htonl(state->xfer_func);
- p_hdr->ycbcr_enc = htonl(state->ycbcr_enc);
- p_hdr->quantization = htonl(state->quantization);
- p_hdr->size = htonl(cf.size);
- return cf.size + sizeof(*p_hdr);
-}
-
-int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
-{
- u32 flags;
- struct fwht_cframe cf;
- unsigned int components_num = 3;
- unsigned int version;
- const struct v4l2_fwht_pixfmt_info *info;
- unsigned int hdr_width_div, hdr_height_div;
- struct fwht_raw_frame dst_rf;
- unsigned int dst_chroma_stride = state->stride;
- unsigned int ref_chroma_stride = state->ref_stride;
- unsigned int dst_size = state->stride * state->coded_height;
- unsigned int ref_size;
-
- if (!state->info)
- return -EINVAL;
-
- info = state->info;
-
- version = ntohl(state->header.version);
- if (!version || version > FWHT_VERSION) {
- pr_err("version %d is not supported, current version is %d\n",
- version, FWHT_VERSION);
- return -EINVAL;
- }
-
- if (state->header.magic1 != FWHT_MAGIC1 ||
- state->header.magic2 != FWHT_MAGIC2)
- return -EINVAL;
-
- /* TODO: support resolution changes */
- if (ntohl(state->header.width) != state->visible_width ||
- ntohl(state->header.height) != state->visible_height)
- return -EINVAL;
-
- flags = ntohl(state->header.flags);
-
- if (version >= 2) {
- if ((flags & FWHT_FL_PIXENC_MSK) != info->pixenc)
- return -EINVAL;
- components_num = 1 + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
- FWHT_FL_COMPONENTS_NUM_OFFSET);
- }
-
- if (components_num != info->components_num)
- return -EINVAL;
-
- state->colorspace = ntohl(state->header.colorspace);
- state->xfer_func = ntohl(state->header.xfer_func);
- state->ycbcr_enc = ntohl(state->header.ycbcr_enc);
- state->quantization = ntohl(state->header.quantization);
- cf.rlc_data = (__be16 *)p_in;
- cf.size = ntohl(state->header.size);
-
- hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
- hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
- if (hdr_width_div != info->width_div ||
- hdr_height_div != info->height_div)
- return -EINVAL;
-
- if (prepare_raw_frame(&dst_rf, info, p_out, dst_size))
- return -EINVAL;
- if (info->planes_num == 3) {
- dst_chroma_stride /= 2;
- ref_chroma_stride /= 2;
- }
- if (info->id == V4L2_PIX_FMT_NV24 ||
- info->id == V4L2_PIX_FMT_NV42) {
- dst_chroma_stride *= 2;
- ref_chroma_stride *= 2;
- }
-
-
- ref_size = state->ref_stride * state->coded_height;
-
- if (prepare_raw_frame(&state->ref_frame, info, state->ref_frame.buf,
- ref_size))
- return -EINVAL;
-
- if (!fwht_decode_frame(&cf, flags, components_num,
- state->visible_width, state->visible_height,
- &state->ref_frame, state->ref_stride, ref_chroma_stride,
- &dst_rf, state->stride, dst_chroma_stride))
- return -EINVAL;
- return 0;
-}
diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.h b/drivers/media/platform/vicodec/codec-v4l2-fwht.h
deleted file mode 100644
index 1a0d2a9f931a..000000000000
--- a/drivers/media/platform/vicodec/codec-v4l2-fwht.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef CODEC_V4L2_FWHT_H
-#define CODEC_V4L2_FWHT_H
-
-#include "codec-fwht.h"
-
-struct v4l2_fwht_pixfmt_info {
- u32 id;
- unsigned int bytesperline_mult;
- unsigned int sizeimage_mult;
- unsigned int sizeimage_div;
- unsigned int luma_alpha_step;
- unsigned int chroma_step;
- /* Chroma plane subsampling */
- unsigned int width_div;
- unsigned int height_div;
- unsigned int components_num;
- unsigned int planes_num;
- unsigned int pixenc;
-};
-
-struct v4l2_fwht_state {
- const struct v4l2_fwht_pixfmt_info *info;
- unsigned int visible_width;
- unsigned int visible_height;
- unsigned int coded_width;
- unsigned int coded_height;
- unsigned int stride;
- unsigned int ref_stride;
- unsigned int gop_size;
- unsigned int gop_cnt;
- u16 i_frame_qp;
- u16 p_frame_qp;
-
- enum v4l2_colorspace colorspace;
- enum v4l2_ycbcr_encoding ycbcr_enc;
- enum v4l2_xfer_func xfer_func;
- enum v4l2_quantization quantization;
-
- struct fwht_raw_frame ref_frame;
- struct fwht_cframe_hdr header;
- u8 *compressed_frame;
- u64 ref_frame_ts;
-};
-
-const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat);
-const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx);
-bool v4l2_fwht_validate_fmt(const struct v4l2_fwht_pixfmt_info *info,
- u32 width_div, u32 height_div, u32 components_num,
- u32 pixenc);
-const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_nth_fmt(u32 width_div,
- u32 height_div,
- u32 components_num,
- u32 pixenc,
- unsigned int start_idx);
-
-int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out);
-int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out);
-
-#endif
diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c
deleted file mode 100644
index 30ced1c21387..000000000000
--- a/drivers/media/platform/vicodec/vicodec-core.c
+++ /dev/null
@@ -1,2238 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * A virtual codec example device.
- *
- * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- *
- * This is a virtual codec device driver for testing the codec framework.
- * It simulates a device that uses memory buffers for both source and
- * destination and encodes or decodes the data.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <linux/platform_device.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-vmalloc.h>
-
-#include "codec-v4l2-fwht.h"
-
-MODULE_DESCRIPTION("Virtual codec device");
-MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
-MODULE_LICENSE("GPL v2");
-
-static bool multiplanar;
-module_param(multiplanar, bool, 0444);
-MODULE_PARM_DESC(multiplanar,
- " use multi-planar API instead of single-planar API");
-
-static unsigned int debug;
-module_param(debug, uint, 0644);
-MODULE_PARM_DESC(debug, " activates debug info");
-
-#define VICODEC_NAME "vicodec"
-#define MAX_WIDTH 4096U
-#define MIN_WIDTH 640U
-#define MAX_HEIGHT 2160U
-#define MIN_HEIGHT 360U
-
-#define dprintk(dev, fmt, arg...) \
- v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
-
-
-struct pixfmt_info {
- u32 id;
- unsigned int bytesperline_mult;
- unsigned int sizeimage_mult;
- unsigned int sizeimage_div;
- unsigned int luma_step;
- unsigned int chroma_step;
- /* Chroma plane subsampling */
- unsigned int width_div;
- unsigned int height_div;
-};
-
-static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = {
- V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1, 0, 1
-};
-
-static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht = {
- V4L2_PIX_FMT_FWHT_STATELESS, 0, 3, 1, 1, 1, 1, 1, 0, 1
-};
-
-static void vicodec_dev_release(struct device *dev)
-{
-}
-
-static struct platform_device vicodec_pdev = {
- .name = VICODEC_NAME,
- .dev.release = vicodec_dev_release,
-};
-
-/* Per-queue, driver-specific private data */
-struct vicodec_q_data {
- unsigned int coded_width;
- unsigned int coded_height;
- unsigned int visible_width;
- unsigned int visible_height;
- unsigned int sizeimage;
- unsigned int vb2_sizeimage;
- unsigned int sequence;
- const struct v4l2_fwht_pixfmt_info *info;
-};
-
-enum {
- V4L2_M2M_SRC = 0,
- V4L2_M2M_DST = 1,
-};
-
-struct vicodec_dev_instance {
- struct video_device vfd;
- struct mutex mutex;
- spinlock_t lock;
- struct v4l2_m2m_dev *m2m_dev;
-};
-
-struct vicodec_dev {
- struct v4l2_device v4l2_dev;
- struct vicodec_dev_instance stateful_enc;
- struct vicodec_dev_instance stateful_dec;
- struct vicodec_dev_instance stateless_dec;
-#ifdef CONFIG_MEDIA_CONTROLLER
- struct media_device mdev;
-#endif
-
-};
-
-struct vicodec_ctx {
- struct v4l2_fh fh;
- struct vicodec_dev *dev;
- bool is_enc;
- bool is_stateless;
- spinlock_t *lock;
-
- struct v4l2_ctrl_handler hdl;
-
- /* Source and destination queue data */
- struct vicodec_q_data q_data[2];
- struct v4l2_fwht_state state;
-
- u32 cur_buf_offset;
- u32 comp_max_size;
- u32 comp_size;
- u32 header_size;
- u32 comp_magic_cnt;
- bool comp_has_frame;
- bool comp_has_next_frame;
- bool first_source_change_sent;
- bool source_changed;
-};
-
-static const struct v4l2_event vicodec_eos_event = {
- .type = V4L2_EVENT_EOS
-};
-
-static inline struct vicodec_ctx *file2ctx(struct file *file)
-{
- return container_of(file->private_data, struct vicodec_ctx, fh);
-}
-
-static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx,
- enum v4l2_buf_type type)
-{
- switch (type) {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- return &ctx->q_data[V4L2_M2M_SRC];
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- return &ctx->q_data[V4L2_M2M_DST];
- default:
- break;
- }
- return NULL;
-}
-
-static void copy_cap_to_ref(const u8 *cap, const struct v4l2_fwht_pixfmt_info *info,
- struct v4l2_fwht_state *state)
-{
- int plane_idx;
- u8 *p_ref = state->ref_frame.buf;
- unsigned int cap_stride = state->stride;
- unsigned int ref_stride = state->ref_stride;
-
- for (plane_idx = 0; plane_idx < info->planes_num; plane_idx++) {
- int i;
- unsigned int h_div = (plane_idx == 1 || plane_idx == 2) ?
- info->height_div : 1;
- const u8 *row_cap = cap;
- u8 *row_ref = p_ref;
-
- if (info->planes_num == 3 && plane_idx == 1) {
- cap_stride /= 2;
- ref_stride /= 2;
- }
-
- if (plane_idx == 1 &&
- (info->id == V4L2_PIX_FMT_NV24 ||
- info->id == V4L2_PIX_FMT_NV42)) {
- cap_stride *= 2;
- ref_stride *= 2;
- }
-
- for (i = 0; i < state->visible_height / h_div; i++) {
- memcpy(row_ref, row_cap, ref_stride);
- row_ref += ref_stride;
- row_cap += cap_stride;
- }
- cap += cap_stride * (state->coded_height / h_div);
- p_ref += ref_stride * (state->coded_height / h_div);
- }
-}
-
-static bool validate_by_version(unsigned int flags, unsigned int version)
-{
- if (!version || version > FWHT_VERSION)
- return false;
-
- if (version >= 2) {
- unsigned int components_num = 1 +
- ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
- FWHT_FL_COMPONENTS_NUM_OFFSET);
- unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK;
-
- if (components_num == 0 || components_num > 4 || !pixenc)
- return false;
- }
- return true;
-}
-
-static bool validate_stateless_params_flags(const struct v4l2_ctrl_fwht_params *params,
- const struct v4l2_fwht_pixfmt_info *cur_info)
-{
- unsigned int width_div =
- (params->flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
- unsigned int height_div =
- (params->flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
- unsigned int components_num = 3;
- unsigned int pixenc = 0;
-
- if (params->version < 3)
- return false;
-
- components_num = 1 + ((params->flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
- FWHT_FL_COMPONENTS_NUM_OFFSET);
- pixenc = (params->flags & FWHT_FL_PIXENC_MSK);
- if (v4l2_fwht_validate_fmt(cur_info, width_div, height_div,
- components_num, pixenc))
- return true;
- return false;
-}
-
-
-static void update_state_from_header(struct vicodec_ctx *ctx)
-{
- const struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
-
- ctx->state.visible_width = ntohl(p_hdr->width);
- ctx->state.visible_height = ntohl(p_hdr->height);
- ctx->state.colorspace = ntohl(p_hdr->colorspace);
- ctx->state.xfer_func = ntohl(p_hdr->xfer_func);
- ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
- ctx->state.quantization = ntohl(p_hdr->quantization);
-}
-
-static int device_process(struct vicodec_ctx *ctx,
- struct vb2_v4l2_buffer *src_vb,
- struct vb2_v4l2_buffer *dst_vb)
-{
- struct vicodec_dev *dev = ctx->dev;
- struct v4l2_fwht_state *state = &ctx->state;
- u8 *p_src, *p_dst;
- int ret = 0;
-
- if (ctx->is_enc || ctx->is_stateless)
- p_src = vb2_plane_vaddr(&src_vb->vb2_buf, 0);
- else
- p_src = state->compressed_frame;
-
- if (ctx->is_stateless) {
- struct media_request *src_req = src_vb->vb2_buf.req_obj.req;
-
- ret = v4l2_ctrl_request_setup(src_req, &ctx->hdl);
- if (ret)
- return ret;
- update_state_from_header(ctx);
-
- ctx->state.header.size =
- htonl(vb2_get_plane_payload(&src_vb->vb2_buf, 0));
- /*
- * set the reference buffer from the reference timestamp
- * only if this is a P-frame
- */
- if (!(ntohl(ctx->state.header.flags) & FWHT_FL_I_FRAME)) {
- struct vb2_buffer *ref_vb2_buf;
- int ref_buf_idx;
- struct vb2_queue *vq_cap =
- v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
- ref_buf_idx = vb2_find_timestamp(vq_cap,
- ctx->state.ref_frame_ts, 0);
- if (ref_buf_idx < 0)
- return -EINVAL;
-
- ref_vb2_buf = vq_cap->bufs[ref_buf_idx];
- if (ref_vb2_buf->state == VB2_BUF_STATE_ERROR)
- ret = -EINVAL;
- ctx->state.ref_frame.buf =
- vb2_plane_vaddr(ref_vb2_buf, 0);
- } else {
- ctx->state.ref_frame.buf = NULL;
- }
- }
- p_dst = vb2_plane_vaddr(&dst_vb->vb2_buf, 0);
- if (!p_src || !p_dst) {
- v4l2_err(&dev->v4l2_dev,
- "Acquiring kernel pointers to buffers failed\n");
- return -EFAULT;
- }
-
- if (ctx->is_enc) {
- struct vicodec_q_data *q_src;
- int comp_sz_or_errcode;
-
- q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
- state->info = q_src->info;
- comp_sz_or_errcode = v4l2_fwht_encode(state, p_src, p_dst);
- if (comp_sz_or_errcode < 0)
- return comp_sz_or_errcode;
- vb2_set_plane_payload(&dst_vb->vb2_buf, 0, comp_sz_or_errcode);
- } else {
- struct vicodec_q_data *q_dst;
- unsigned int comp_frame_size = ntohl(ctx->state.header.size);
-
- q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (comp_frame_size > ctx->comp_max_size)
- return -EINVAL;
- state->info = q_dst->info;
- ret = v4l2_fwht_decode(state, p_src, p_dst);
- if (ret < 0)
- return ret;
- if (!ctx->is_stateless)
- copy_cap_to_ref(p_dst, ctx->state.info, &ctx->state);
-
- vb2_set_plane_payload(&dst_vb->vb2_buf, 0, q_dst->sizeimage);
- if (ntohl(ctx->state.header.flags) & FWHT_FL_I_FRAME)
- dst_vb->flags |= V4L2_BUF_FLAG_KEYFRAME;
- else
- dst_vb->flags |= V4L2_BUF_FLAG_PFRAME;
- }
- return ret;
-}
-
-/*
- * mem2mem callbacks
- */
-static enum vb2_buffer_state get_next_header(struct vicodec_ctx *ctx,
- u8 **pp, u32 sz)
-{
- static const u8 magic[] = {
- 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
- };
- u8 *p = *pp;
- u32 state;
- u8 *header = (u8 *)&ctx->state.header;
-
- state = VB2_BUF_STATE_DONE;
-
- if (!ctx->header_size) {
- state = VB2_BUF_STATE_ERROR;
- for (; p < *pp + sz; p++) {
- u32 copy;
-
- p = memchr(p, magic[ctx->comp_magic_cnt],
- *pp + sz - p);
- if (!p) {
- ctx->comp_magic_cnt = 0;
- p = *pp + sz;
- break;
- }
- copy = sizeof(magic) - ctx->comp_magic_cnt;
- if (*pp + sz - p < copy)
- copy = *pp + sz - p;
-
- memcpy(header + ctx->comp_magic_cnt, p, copy);
- ctx->comp_magic_cnt += copy;
- if (!memcmp(header, magic, ctx->comp_magic_cnt)) {
- p += copy;
- state = VB2_BUF_STATE_DONE;
- break;
- }
- ctx->comp_magic_cnt = 0;
- }
- if (ctx->comp_magic_cnt < sizeof(magic)) {
- *pp = p;
- return state;
- }
- ctx->header_size = sizeof(magic);
- }
-
- if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
- u32 copy = sizeof(struct fwht_cframe_hdr) - ctx->header_size;
-
- if (*pp + sz - p < copy)
- copy = *pp + sz - p;
-
- memcpy(header + ctx->header_size, p, copy);
- p += copy;
- ctx->header_size += copy;
- }
- *pp = p;
- return state;
-}
-
-/* device_run() - prepares and starts the device */
-static void device_run(void *priv)
-{
- struct vicodec_ctx *ctx = priv;
- struct vicodec_dev *dev = ctx->dev;
- struct vb2_v4l2_buffer *src_buf, *dst_buf;
- struct vicodec_q_data *q_src, *q_dst;
- u32 state;
- struct media_request *src_req;
-
- src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- src_req = src_buf->vb2_buf.req_obj.req;
-
- q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
- q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
- state = VB2_BUF_STATE_DONE;
- if (device_process(ctx, src_buf, dst_buf))
- state = VB2_BUF_STATE_ERROR;
- else
- dst_buf->sequence = q_dst->sequence++;
- dst_buf->flags &= ~V4L2_BUF_FLAG_LAST;
- v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
-
- spin_lock(ctx->lock);
- if (!ctx->comp_has_next_frame &&
- v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {
- dst_buf->flags |= V4L2_BUF_FLAG_LAST;
- v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
- v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
- }
- if (ctx->is_enc || ctx->is_stateless) {
- src_buf->sequence = q_src->sequence++;
- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_buf_done(src_buf, state);
- } else if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == ctx->cur_buf_offset) {
- src_buf->sequence = q_src->sequence++;
- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_buf_done(src_buf, state);
- ctx->cur_buf_offset = 0;
- ctx->comp_has_next_frame = false;
- }
- v4l2_m2m_buf_done(dst_buf, state);
-
- ctx->comp_size = 0;
- ctx->header_size = 0;
- ctx->comp_magic_cnt = 0;
- ctx->comp_has_frame = false;
- spin_unlock(ctx->lock);
- if (ctx->is_stateless && src_req)
- v4l2_ctrl_request_complete(src_req, &ctx->hdl);
-
- if (ctx->is_enc)
- v4l2_m2m_job_finish(dev->stateful_enc.m2m_dev, ctx->fh.m2m_ctx);
- else if (ctx->is_stateless)
- v4l2_m2m_job_finish(dev->stateless_dec.m2m_dev,
- ctx->fh.m2m_ctx);
- else
- v4l2_m2m_job_finish(dev->stateful_dec.m2m_dev, ctx->fh.m2m_ctx);
-}
-
-static void job_remove_src_buf(struct vicodec_ctx *ctx, u32 state)
-{
- struct vb2_v4l2_buffer *src_buf;
- struct vicodec_q_data *q_src;
-
- q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
- spin_lock(ctx->lock);
- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- src_buf->sequence = q_src->sequence++;
- v4l2_m2m_buf_done(src_buf, state);
- ctx->cur_buf_offset = 0;
- spin_unlock(ctx->lock);
-}
-
-static const struct v4l2_fwht_pixfmt_info *
-info_from_header(const struct fwht_cframe_hdr *p_hdr)
-{
- unsigned int flags = ntohl(p_hdr->flags);
- unsigned int width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
- unsigned int height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
- unsigned int components_num = 3;
- unsigned int pixenc = 0;
- unsigned int version = ntohl(p_hdr->version);
-
- if (version >= 2) {
- components_num = 1 + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
- FWHT_FL_COMPONENTS_NUM_OFFSET);
- pixenc = (flags & FWHT_FL_PIXENC_MSK);
- }
- return v4l2_fwht_find_nth_fmt(width_div, height_div,
- components_num, pixenc, 0);
-}
-
-static bool is_header_valid(const struct fwht_cframe_hdr *p_hdr)
-{
- const struct v4l2_fwht_pixfmt_info *info;
- unsigned int w = ntohl(p_hdr->width);
- unsigned int h = ntohl(p_hdr->height);
- unsigned int version = ntohl(p_hdr->version);
- unsigned int flags = ntohl(p_hdr->flags);
-
- if (w < MIN_WIDTH || w > MAX_WIDTH || h < MIN_HEIGHT || h > MAX_HEIGHT)
- return false;
-
- if (!validate_by_version(flags, version))
- return false;
-
- info = info_from_header(p_hdr);
- if (!info)
- return false;
- return true;
-}
-
-static void update_capture_data_from_header(struct vicodec_ctx *ctx)
-{
- struct vicodec_q_data *q_dst = get_q_data(ctx,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
- const struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
- const struct v4l2_fwht_pixfmt_info *info = info_from_header(p_hdr);
- unsigned int flags = ntohl(p_hdr->flags);
- unsigned int hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
- unsigned int hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
-
- /*
- * This function should not be used by a stateless codec since
- * it changes values in q_data that are not request specific
- */
- WARN_ON(ctx->is_stateless);
-
- q_dst->info = info;
- q_dst->visible_width = ntohl(p_hdr->width);
- q_dst->visible_height = ntohl(p_hdr->height);
- q_dst->coded_width = vic_round_dim(q_dst->visible_width, hdr_width_div);
- q_dst->coded_height = vic_round_dim(q_dst->visible_height,
- hdr_height_div);
-
- q_dst->sizeimage = q_dst->coded_width * q_dst->coded_height *
- q_dst->info->sizeimage_mult / q_dst->info->sizeimage_div;
- ctx->state.colorspace = ntohl(p_hdr->colorspace);
-
- ctx->state.xfer_func = ntohl(p_hdr->xfer_func);
- ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
- ctx->state.quantization = ntohl(p_hdr->quantization);
-}
-
-static void set_last_buffer(struct vb2_v4l2_buffer *dst_buf,
- const struct vb2_v4l2_buffer *src_buf,
- struct vicodec_ctx *ctx)
-{
- struct vicodec_q_data *q_dst = get_q_data(ctx,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
- vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0);
- dst_buf->sequence = q_dst->sequence++;
-
- v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, !ctx->is_enc);
- dst_buf->flags |= V4L2_BUF_FLAG_LAST;
- v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
-}
-
-static int job_ready(void *priv)
-{
- static const u8 magic[] = {
- 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
- };
- struct vicodec_ctx *ctx = priv;
- struct vb2_v4l2_buffer *src_buf;
- u8 *p_src;
- u8 *p;
- u32 sz;
- u32 state;
- struct vicodec_q_data *q_dst = get_q_data(ctx,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
- unsigned int flags;
- unsigned int hdr_width_div;
- unsigned int hdr_height_div;
- unsigned int max_to_copy;
- unsigned int comp_frame_size;
-
- if (ctx->source_changed)
- return 0;
- if (ctx->is_stateless || ctx->is_enc || ctx->comp_has_frame)
- return 1;
-
-restart:
- ctx->comp_has_next_frame = false;
- src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
- if (!src_buf)
- return 0;
- p_src = vb2_plane_vaddr(&src_buf->vb2_buf, 0);
- sz = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
- p = p_src + ctx->cur_buf_offset;
-
- state = VB2_BUF_STATE_DONE;
-
- if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
- state = get_next_header(ctx, &p, p_src + sz - p);
- if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
- if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx,
- src_buf))
- return 1;
- job_remove_src_buf(ctx, state);
- goto restart;
- }
- }
-
- comp_frame_size = ntohl(ctx->state.header.size);
-
- /*
- * The current scanned frame might be the first frame of a new
- * resolution so its size might be larger than ctx->comp_max_size.
- * In that case it is copied up to the current buffer capacity and
- * the copy will continue after allocating new large enough buffer
- * when restreaming
- */
- max_to_copy = min(comp_frame_size, ctx->comp_max_size);
-
- if (ctx->comp_size < max_to_copy) {
- u32 copy = max_to_copy - ctx->comp_size;
-
- if (copy > p_src + sz - p)
- copy = p_src + sz - p;
-
- memcpy(ctx->state.compressed_frame + ctx->comp_size,
- p, copy);
- p += copy;
- ctx->comp_size += copy;
- if (ctx->comp_size < max_to_copy) {
- if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx,
- src_buf))
- return 1;
- job_remove_src_buf(ctx, state);
- goto restart;
- }
- }
- ctx->cur_buf_offset = p - p_src;
- if (ctx->comp_size == comp_frame_size)
- ctx->comp_has_frame = true;
- ctx->comp_has_next_frame = false;
- if (ctx->comp_has_frame && sz - ctx->cur_buf_offset >=
- sizeof(struct fwht_cframe_hdr)) {
- struct fwht_cframe_hdr *p_hdr = (struct fwht_cframe_hdr *)p;
- u32 frame_size = ntohl(p_hdr->size);
- u32 remaining = sz - ctx->cur_buf_offset - sizeof(*p_hdr);
-
- if (!memcmp(p, magic, sizeof(magic)))
- ctx->comp_has_next_frame = remaining >= frame_size;
- }
- /*
- * if the header is invalid the device_run will just drop the frame
- * with an error
- */
- if (!is_header_valid(&ctx->state.header) && ctx->comp_has_frame)
- return 1;
- flags = ntohl(ctx->state.header.flags);
- hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
- hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
-
- if (ntohl(ctx->state.header.width) != q_dst->visible_width ||
- ntohl(ctx->state.header.height) != q_dst->visible_height ||
- !q_dst->info ||
- hdr_width_div != q_dst->info->width_div ||
- hdr_height_div != q_dst->info->height_div) {
- static const struct v4l2_event rs_event = {
- .type = V4L2_EVENT_SOURCE_CHANGE,
- .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
- };
-
- struct vb2_v4l2_buffer *dst_buf =
- v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
- update_capture_data_from_header(ctx);
- v4l2_event_queue_fh(&ctx->fh, &rs_event);
- set_last_buffer(dst_buf, src_buf, ctx);
- ctx->source_changed = true;
- return 0;
- }
- return 1;
-}
-
-/*
- * video ioctls
- */
-
-static const struct v4l2_fwht_pixfmt_info *find_fmt(u32 fmt)
-{
- const struct v4l2_fwht_pixfmt_info *info =
- v4l2_fwht_find_pixfmt(fmt);
-
- if (!info)
- info = v4l2_fwht_get_pixfmt(0);
- return info;
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- strscpy(cap->driver, VICODEC_NAME, sizeof(cap->driver));
- strscpy(cap->card, VICODEC_NAME, sizeof(cap->card));
- snprintf(cap->bus_info, sizeof(cap->bus_info),
- "platform:%s", VICODEC_NAME);
- return 0;
-}
-
-static int enum_fmt(struct v4l2_fmtdesc *f, struct vicodec_ctx *ctx,
- bool is_out)
-{
- bool is_uncomp = (ctx->is_enc && is_out) || (!ctx->is_enc && !is_out);
-
- if (V4L2_TYPE_IS_MULTIPLANAR(f->type) && !multiplanar)
- return -EINVAL;
- if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && multiplanar)
- return -EINVAL;
-
- if (is_uncomp) {
- const struct v4l2_fwht_pixfmt_info *info =
- get_q_data(ctx, f->type)->info;
-
- if (ctx->is_enc ||
- !vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q))
- info = v4l2_fwht_get_pixfmt(f->index);
- else
- info = v4l2_fwht_find_nth_fmt(info->width_div,
- info->height_div,
- info->components_num,
- info->pixenc,
- f->index);
- if (!info)
- return -EINVAL;
- f->pixelformat = info->id;
- } else {
- if (f->index)
- return -EINVAL;
- f->pixelformat = ctx->is_stateless ?
- V4L2_PIX_FMT_FWHT_STATELESS : V4L2_PIX_FMT_FWHT;
- if (!ctx->is_enc && !ctx->is_stateless)
- f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION |
- V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM;
- }
- return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- struct vicodec_ctx *ctx = file2ctx(file);
-
- return enum_fmt(f, ctx, false);
-}
-
-static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- struct vicodec_ctx *ctx = file2ctx(file);
-
- return enum_fmt(f, ctx, true);
-}
-
-static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
-{
- struct vb2_queue *vq;
- struct vicodec_q_data *q_data;
- struct v4l2_pix_format_mplane *pix_mp;
- struct v4l2_pix_format *pix;
- const struct v4l2_fwht_pixfmt_info *info;
-
- vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
- if (!vq)
- return -EINVAL;
-
- q_data = get_q_data(ctx, f->type);
- info = q_data->info;
-
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (multiplanar)
- return -EINVAL;
- pix = &f->fmt.pix;
- pix->width = q_data->coded_width;
- pix->height = q_data->coded_height;
- pix->field = V4L2_FIELD_NONE;
- pix->pixelformat = info->id;
- pix->bytesperline = q_data->coded_width *
- info->bytesperline_mult;
- pix->sizeimage = q_data->sizeimage;
- pix->colorspace = ctx->state.colorspace;
- pix->xfer_func = ctx->state.xfer_func;
- pix->ycbcr_enc = ctx->state.ycbcr_enc;
- pix->quantization = ctx->state.quantization;
- break;
-
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- if (!multiplanar)
- return -EINVAL;
- pix_mp = &f->fmt.pix_mp;
- pix_mp->width = q_data->coded_width;
- pix_mp->height = q_data->coded_height;
- pix_mp->field = V4L2_FIELD_NONE;
- pix_mp->pixelformat = info->id;
- pix_mp->num_planes = 1;
- pix_mp->plane_fmt[0].bytesperline =
- q_data->coded_width * info->bytesperline_mult;
- pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage;
- pix_mp->colorspace = ctx->state.colorspace;
- pix_mp->xfer_func = ctx->state.xfer_func;
- pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
- pix_mp->quantization = ctx->state.quantization;
- memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
- memset(pix_mp->plane_fmt[0].reserved, 0,
- sizeof(pix_mp->plane_fmt[0].reserved));
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- return vidioc_g_fmt(file2ctx(file), f);
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- return vidioc_g_fmt(file2ctx(file), f);
-}
-
-static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
-{
- struct v4l2_pix_format_mplane *pix_mp;
- struct v4l2_pix_format *pix;
- struct v4l2_plane_pix_format *plane;
- const struct v4l2_fwht_pixfmt_info *info = ctx->is_stateless ?
- &pixfmt_stateless_fwht : &pixfmt_fwht;
-
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- pix = &f->fmt.pix;
- if (pix->pixelformat != V4L2_PIX_FMT_FWHT &&
- pix->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS)
- info = find_fmt(pix->pixelformat);
-
- pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH);
- pix->width = vic_round_dim(pix->width, info->width_div);
-
- pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT);
- pix->height = vic_round_dim(pix->height, info->height_div);
-
- pix->field = V4L2_FIELD_NONE;
- pix->bytesperline =
- pix->width * info->bytesperline_mult;
- pix->sizeimage = pix->width * pix->height *
- info->sizeimage_mult / info->sizeimage_div;
- if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
- pix->sizeimage += sizeof(struct fwht_cframe_hdr);
- break;
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- pix_mp = &f->fmt.pix_mp;
- plane = pix_mp->plane_fmt;
- if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT &&
- pix_mp->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS)
- info = find_fmt(pix_mp->pixelformat);
- pix_mp->num_planes = 1;
-
- pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH);
- pix_mp->width = vic_round_dim(pix_mp->width, info->width_div);
-
- pix_mp->height = clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT);
- pix_mp->height = vic_round_dim(pix_mp->height,
- info->height_div);
-
- pix_mp->field = V4L2_FIELD_NONE;
- plane->bytesperline =
- pix_mp->width * info->bytesperline_mult;
- plane->sizeimage = pix_mp->width * pix_mp->height *
- info->sizeimage_mult / info->sizeimage_div;
- if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
- plane->sizeimage += sizeof(struct fwht_cframe_hdr);
- memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
- memset(plane->reserved, 0, sizeof(plane->reserved));
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vicodec_ctx *ctx = file2ctx(file);
- struct v4l2_pix_format_mplane *pix_mp;
- struct v4l2_pix_format *pix;
-
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (multiplanar)
- return -EINVAL;
- pix = &f->fmt.pix;
- pix->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
- find_fmt(f->fmt.pix.pixelformat)->id;
- pix->colorspace = ctx->state.colorspace;
- pix->xfer_func = ctx->state.xfer_func;
- pix->ycbcr_enc = ctx->state.ycbcr_enc;
- pix->quantization = ctx->state.quantization;
- break;
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- if (!multiplanar)
- return -EINVAL;
- pix_mp = &f->fmt.pix_mp;
- pix_mp->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
- find_fmt(pix_mp->pixelformat)->id;
- pix_mp->colorspace = ctx->state.colorspace;
- pix_mp->xfer_func = ctx->state.xfer_func;
- pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
- pix_mp->quantization = ctx->state.quantization;
- break;
- default:
- return -EINVAL;
- }
-
- return vidioc_try_fmt(ctx, f);
-}
-
-static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vicodec_ctx *ctx = file2ctx(file);
- struct v4l2_pix_format_mplane *pix_mp;
- struct v4l2_pix_format *pix;
-
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (multiplanar)
- return -EINVAL;
- pix = &f->fmt.pix;
- if (ctx->is_enc)
- pix->pixelformat = find_fmt(pix->pixelformat)->id;
- else if (ctx->is_stateless)
- pix->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS;
- else
- pix->pixelformat = V4L2_PIX_FMT_FWHT;
- if (!pix->colorspace)
- pix->colorspace = V4L2_COLORSPACE_REC709;
- break;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- if (!multiplanar)
- return -EINVAL;
- pix_mp = &f->fmt.pix_mp;
- if (ctx->is_enc)
- pix_mp->pixelformat = find_fmt(pix_mp->pixelformat)->id;
- else if (ctx->is_stateless)
- pix_mp->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS;
- else
- pix_mp->pixelformat = V4L2_PIX_FMT_FWHT;
- if (!pix_mp->colorspace)
- pix_mp->colorspace = V4L2_COLORSPACE_REC709;
- break;
- default:
- return -EINVAL;
- }
-
- return vidioc_try_fmt(ctx, f);
-}
-
-static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
-{
- struct vicodec_q_data *q_data;
- struct vb2_queue *vq;
- bool fmt_changed = true;
- struct v4l2_pix_format_mplane *pix_mp;
- struct v4l2_pix_format *pix;
-
- vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
- if (!vq)
- return -EINVAL;
-
- q_data = get_q_data(ctx, f->type);
- if (!q_data)
- return -EINVAL;
-
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- pix = &f->fmt.pix;
- if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
- fmt_changed =
- !q_data->info ||
- q_data->info->id != pix->pixelformat ||
- q_data->coded_width != pix->width ||
- q_data->coded_height != pix->height;
-
- if (vb2_is_busy(vq) && fmt_changed)
- return -EBUSY;
-
- if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
- q_data->info = &pixfmt_fwht;
- else if (pix->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS)
- q_data->info = &pixfmt_stateless_fwht;
- else
- q_data->info = find_fmt(pix->pixelformat);
- q_data->coded_width = pix->width;
- q_data->coded_height = pix->height;
- q_data->sizeimage = pix->sizeimage;
- break;
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- pix_mp = &f->fmt.pix_mp;
- if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
- fmt_changed =
- !q_data->info ||
- q_data->info->id != pix_mp->pixelformat ||
- q_data->coded_width != pix_mp->width ||
- q_data->coded_height != pix_mp->height;
-
- if (vb2_is_busy(vq) && fmt_changed)
- return -EBUSY;
-
- if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
- q_data->info = &pixfmt_fwht;
- else if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS)
- q_data->info = &pixfmt_stateless_fwht;
- else
- q_data->info = find_fmt(pix_mp->pixelformat);
- q_data->coded_width = pix_mp->width;
- q_data->coded_height = pix_mp->height;
- q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage;
- break;
- default:
- return -EINVAL;
- }
-
- dprintk(ctx->dev,
- "Setting format for type %d, coded wxh: %dx%d, fourcc: 0x%08x\n",
- f->type, q_data->coded_width, q_data->coded_height,
- q_data->info->id);
-
- return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- int ret;
-
- ret = vidioc_try_fmt_vid_cap(file, priv, f);
- if (ret)
- return ret;
-
- return vidioc_s_fmt(file2ctx(file), f);
-}
-
-static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vicodec_ctx *ctx = file2ctx(file);
- struct vicodec_q_data *q_data;
- struct vicodec_q_data *q_data_cap;
- struct v4l2_pix_format *pix;
- struct v4l2_pix_format_mplane *pix_mp;
- u32 coded_w = 0, coded_h = 0;
- unsigned int size = 0;
- int ret;
-
- q_data = get_q_data(ctx, f->type);
- q_data_cap = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
- ret = vidioc_try_fmt_vid_out(file, priv, f);
- if (ret)
- return ret;
-
- if (ctx->is_enc) {
- struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
- struct vb2_queue *vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
- const struct v4l2_fwht_pixfmt_info *info = ctx->is_stateless ?
- &pixfmt_stateless_fwht : &pixfmt_fwht;
-
- if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
- coded_w = f->fmt.pix.width;
- coded_h = f->fmt.pix.height;
- } else {
- coded_w = f->fmt.pix_mp.width;
- coded_h = f->fmt.pix_mp.height;
- }
- if (vb2_is_busy(vq) && (coded_w != q_data->coded_width ||
- coded_h != q_data->coded_height))
- return -EBUSY;
- size = coded_w * coded_h *
- info->sizeimage_mult / info->sizeimage_div;
- if (!ctx->is_stateless)
- size += sizeof(struct fwht_cframe_hdr);
-
- if (vb2_is_busy(vq_cap) && size > q_data_cap->sizeimage)
- return -EBUSY;
- }
-
- ret = vidioc_s_fmt(file2ctx(file), f);
- if (!ret) {
- if (ctx->is_enc) {
- q_data->visible_width = coded_w;
- q_data->visible_height = coded_h;
- q_data_cap->coded_width = coded_w;
- q_data_cap->coded_height = coded_h;
- q_data_cap->sizeimage = size;
- }
-
- switch (f->type) {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- pix = &f->fmt.pix;
- ctx->state.colorspace = pix->colorspace;
- ctx->state.xfer_func = pix->xfer_func;
- ctx->state.ycbcr_enc = pix->ycbcr_enc;
- ctx->state.quantization = pix->quantization;
- break;
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- pix_mp = &f->fmt.pix_mp;
- ctx->state.colorspace = pix_mp->colorspace;
- ctx->state.xfer_func = pix_mp->xfer_func;
- ctx->state.ycbcr_enc = pix_mp->ycbcr_enc;
- ctx->state.quantization = pix_mp->quantization;
- break;
- default:
- break;
- }
- }
- return ret;
-}
-
-static int vidioc_g_selection(struct file *file, void *priv,
- struct v4l2_selection *s)
-{
- struct vicodec_ctx *ctx = file2ctx(file);
- struct vicodec_q_data *q_data;
-
- q_data = get_q_data(ctx, s->type);
- if (!q_data)
- return -EINVAL;
- /*
- * encoder supports only cropping on the OUTPUT buffer
- * decoder supports only composing on the CAPTURE buffer
- */
- if (ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
- switch (s->target) {
- case V4L2_SEL_TGT_CROP:
- s->r.left = 0;
- s->r.top = 0;
- s->r.width = q_data->visible_width;
- s->r.height = q_data->visible_height;
- return 0;
- case V4L2_SEL_TGT_CROP_DEFAULT:
- case V4L2_SEL_TGT_CROP_BOUNDS:
- s->r.left = 0;
- s->r.top = 0;
- s->r.width = q_data->coded_width;
- s->r.height = q_data->coded_height;
- return 0;
- }
- } else if (!ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- switch (s->target) {
- case V4L2_SEL_TGT_COMPOSE:
- s->r.left = 0;
- s->r.top = 0;
- s->r.width = q_data->visible_width;
- s->r.height = q_data->visible_height;
- return 0;
- case V4L2_SEL_TGT_COMPOSE_DEFAULT:
- case V4L2_SEL_TGT_COMPOSE_BOUNDS:
- s->r.left = 0;
- s->r.top = 0;
- s->r.width = q_data->coded_width;
- s->r.height = q_data->coded_height;
- return 0;
- }
- }
- return -EINVAL;
-}
-
-static int vidioc_s_selection(struct file *file, void *priv,
- struct v4l2_selection *s)
-{
- struct vicodec_ctx *ctx = file2ctx(file);
- struct vicodec_q_data *q_data;
-
- if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
- return -EINVAL;
-
- q_data = get_q_data(ctx, s->type);
- if (!q_data)
- return -EINVAL;
-
- if (!ctx->is_enc || s->target != V4L2_SEL_TGT_CROP)
- return -EINVAL;
-
- s->r.left = 0;
- s->r.top = 0;
- q_data->visible_width = clamp(s->r.width, MIN_WIDTH,
- q_data->coded_width);
- s->r.width = q_data->visible_width;
- q_data->visible_height = clamp(s->r.height, MIN_HEIGHT,
- q_data->coded_height);
- s->r.height = q_data->visible_height;
- return 0;
-}
-
-static int vicodec_encoder_cmd(struct file *file, void *fh,
- struct v4l2_encoder_cmd *ec)
-{
- struct vicodec_ctx *ctx = file2ctx(file);
- int ret;
-
- ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec);
- if (ret < 0)
- return ret;
-
- if (!vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q) ||
- !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))
- return 0;
-
- ret = v4l2_m2m_ioctl_encoder_cmd(file, fh, ec);
- if (ret < 0)
- return ret;
-
- if (ec->cmd == V4L2_ENC_CMD_STOP &&
- v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
- v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
-
- if (ec->cmd == V4L2_ENC_CMD_START &&
- v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
- vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
-
- return 0;
-}
-
-static int vicodec_decoder_cmd(struct file *file, void *fh,
- struct v4l2_decoder_cmd *dc)
-{
- struct vicodec_ctx *ctx = file2ctx(file);
- int ret;
-
- ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
- if (ret < 0)
- return ret;
-
- if (!vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q) ||
- !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))
- return 0;
-
- ret = v4l2_m2m_ioctl_decoder_cmd(file, fh, dc);
- if (ret < 0)
- return ret;
-
- if (dc->cmd == V4L2_DEC_CMD_STOP &&
- v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
- v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
-
- if (dc->cmd == V4L2_DEC_CMD_START &&
- v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
- vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
-
- return 0;
-}
-
-static int vicodec_enum_framesizes(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
-{
- switch (fsize->pixel_format) {
- case V4L2_PIX_FMT_FWHT_STATELESS:
- break;
- case V4L2_PIX_FMT_FWHT:
- break;
- default:
- if (find_fmt(fsize->pixel_format)->id == fsize->pixel_format)
- break;
- return -EINVAL;
- }
-
- if (fsize->index)
- return -EINVAL;
-
- fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
-
- fsize->stepwise.min_width = MIN_WIDTH;
- fsize->stepwise.max_width = MAX_WIDTH;
- fsize->stepwise.step_width = 8;
- fsize->stepwise.min_height = MIN_HEIGHT;
- fsize->stepwise.max_height = MAX_HEIGHT;
- fsize->stepwise.step_height = 8;
-
- return 0;
-}
-
-static int vicodec_subscribe_event(struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub)
-{
- struct vicodec_ctx *ctx = container_of(fh, struct vicodec_ctx, fh);
-
- switch (sub->type) {
- case V4L2_EVENT_SOURCE_CHANGE:
- if (ctx->is_enc)
- return -EINVAL;
- /* fall through */
- case V4L2_EVENT_EOS:
- if (ctx->is_stateless)
- return -EINVAL;
- return v4l2_event_subscribe(fh, sub, 0, NULL);
- default:
- return v4l2_ctrl_subscribe_event(fh, sub);
- }
-}
-
-static const struct v4l2_ioctl_ops vicodec_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
-
- .vidioc_enum_fmt_vid_cap = 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_cap_mplane = vidioc_g_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap,
-
- .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
- .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
- .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
- .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
-
- .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out,
- .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out,
- .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out,
-
- .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
- .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
- .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
- .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
- .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
- .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
- .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
-
- .vidioc_streamon = v4l2_m2m_ioctl_streamon,
- .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
-
- .vidioc_g_selection = vidioc_g_selection,
- .vidioc_s_selection = vidioc_s_selection,
-
- .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
- .vidioc_encoder_cmd = vicodec_encoder_cmd,
- .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
- .vidioc_decoder_cmd = vicodec_decoder_cmd,
- .vidioc_enum_framesizes = vicodec_enum_framesizes,
-
- .vidioc_subscribe_event = vicodec_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-
-/*
- * Queue operations
- */
-
-static int vicodec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned int sizes[],
- struct device *alloc_devs[])
-{
- struct vicodec_ctx *ctx = vb2_get_drv_priv(vq);
- struct vicodec_q_data *q_data = get_q_data(ctx, vq->type);
- unsigned int size = q_data->sizeimage;
-
- if (*nplanes)
- return sizes[0] < size ? -EINVAL : 0;
-
- *nplanes = 1;
- sizes[0] = size;
- q_data->vb2_sizeimage = size;
- return 0;
-}
-
-static int vicodec_buf_out_validate(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-
- vbuf->field = V4L2_FIELD_NONE;
- return 0;
-}
-
-static int vicodec_buf_prepare(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- struct vicodec_q_data *q_data;
-
- dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
-
- q_data = get_q_data(ctx, vb->vb2_queue->type);
- if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
- if (vbuf->field == V4L2_FIELD_ANY)
- vbuf->field = V4L2_FIELD_NONE;
- if (vbuf->field != V4L2_FIELD_NONE) {
- dprintk(ctx->dev, "%s field isn't supported\n",
- __func__);
- return -EINVAL;
- }
- }
-
- if (vb2_plane_size(vb, 0) < q_data->vb2_sizeimage) {
- dprintk(ctx->dev,
- "%s data will not fit into plane (%lu < %lu)\n",
- __func__, vb2_plane_size(vb, 0),
- (long)q_data->vb2_sizeimage);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void vicodec_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- unsigned int sz = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
- u8 *p_src = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
- u8 *p = p_src;
- struct vb2_queue *vq_out = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
- V4L2_BUF_TYPE_VIDEO_OUTPUT);
- struct vb2_queue *vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
- bool header_valid = false;
- static const struct v4l2_event rs_event = {
- .type = V4L2_EVENT_SOURCE_CHANGE,
- .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
- };
-
- if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type) &&
- vb2_is_streaming(vb->vb2_queue) &&
- v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {
- unsigned int i;
-
- for (i = 0; i < vb->num_planes; i++)
- vb->planes[i].bytesused = 0;
-
- vbuf->field = V4L2_FIELD_NONE;
- vbuf->sequence =
- get_q_data(ctx, vb->vb2_queue->type)->sequence++;
-
- v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);
- v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
- return;
- }
-
- /* buf_queue handles only the first source change event */
- if (ctx->first_source_change_sent) {
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
- return;
- }
-
- /*
- * if both queues are streaming, the source change event is
- * handled in job_ready
- */
- if (vb2_is_streaming(vq_cap) && vb2_is_streaming(vq_out)) {
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
- return;
- }
-
- /*
- * source change event is relevant only for the stateful decoder
- * in the compressed stream
- */
- if (ctx->is_stateless || ctx->is_enc ||
- !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
- return;
- }
-
- do {
- enum vb2_buffer_state state =
- get_next_header(ctx, &p, p_src + sz - p);
-
- if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
- v4l2_m2m_buf_done(vbuf, state);
- return;
- }
- header_valid = is_header_valid(&ctx->state.header);
- /*
- * p points right after the end of the header in the
- * buffer. If the header is invalid we set p to point
- * to the next byte after the start of the header
- */
- if (!header_valid) {
- p = p - sizeof(struct fwht_cframe_hdr) + 1;
- if (p < p_src)
- p = p_src;
- ctx->header_size = 0;
- ctx->comp_magic_cnt = 0;
- }
-
- } while (!header_valid);
-
- ctx->cur_buf_offset = p - p_src;
- update_capture_data_from_header(ctx);
- ctx->first_source_change_sent = true;
- v4l2_event_queue_fh(&ctx->fh, &rs_event);
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-}
-
-static void vicodec_return_bufs(struct vb2_queue *q, u32 state)
-{
- struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
- struct vb2_v4l2_buffer *vbuf;
-
- for (;;) {
- if (V4L2_TYPE_IS_OUTPUT(q->type))
- vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- else
- vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- if (vbuf == NULL)
- return;
- v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
- &ctx->hdl);
- spin_lock(ctx->lock);
- v4l2_m2m_buf_done(vbuf, state);
- spin_unlock(ctx->lock);
- }
-}
-
-static unsigned int total_frame_size(struct vicodec_q_data *q_data)
-{
- unsigned int size;
- unsigned int chroma_div;
-
- if (!q_data->info) {
- WARN_ON(1);
- return 0;
- }
- size = q_data->coded_width * q_data->coded_height;
- chroma_div = q_data->info->width_div * q_data->info->height_div;
-
- if (q_data->info->components_num == 4)
- return 2 * size + 2 * (size / chroma_div);
- else if (q_data->info->components_num == 3)
- return size + 2 * (size / chroma_div);
- return size;
-}
-
-static int vicodec_start_streaming(struct vb2_queue *q,
- unsigned int count)
-{
- struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
- struct vicodec_q_data *q_data = get_q_data(ctx, q->type);
- struct v4l2_fwht_state *state = &ctx->state;
- const struct v4l2_fwht_pixfmt_info *info = q_data->info;
- unsigned int size = q_data->coded_width * q_data->coded_height;
- unsigned int chroma_div;
- unsigned int total_planes_size;
- u8 *new_comp_frame = NULL;
-
- chroma_div = info->width_div * info->height_div;
- q_data->sequence = 0;
-
- v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
-
- state->gop_cnt = 0;
-
- if ((V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
- (!V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc))
- return 0;
-
- if (info->id == V4L2_PIX_FMT_FWHT ||
- info->id == V4L2_PIX_FMT_FWHT_STATELESS) {
- vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
- return -EINVAL;
- }
- total_planes_size = total_frame_size(q_data);
- ctx->comp_max_size = total_planes_size;
-
- state->visible_width = q_data->visible_width;
- state->visible_height = q_data->visible_height;
- state->coded_width = q_data->coded_width;
- state->coded_height = q_data->coded_height;
- state->stride = q_data->coded_width *
- info->bytesperline_mult;
-
- if (ctx->is_stateless) {
- state->ref_stride = state->stride;
- return 0;
- }
- state->ref_stride = q_data->coded_width * info->luma_alpha_step;
-
- state->ref_frame.buf = kvmalloc(total_planes_size, GFP_KERNEL);
- state->ref_frame.luma = state->ref_frame.buf;
- new_comp_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
-
- if (!state->ref_frame.luma || !new_comp_frame) {
- kvfree(state->ref_frame.luma);
- kvfree(new_comp_frame);
- vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
- return -ENOMEM;
- }
- /*
- * if state->compressed_frame was already allocated then
- * it contain data of the first frame of the new resolution
- */
- if (state->compressed_frame) {
- if (ctx->comp_size > ctx->comp_max_size)
- ctx->comp_size = ctx->comp_max_size;
-
- memcpy(new_comp_frame,
- state->compressed_frame, ctx->comp_size);
- }
-
- kvfree(state->compressed_frame);
- state->compressed_frame = new_comp_frame;
-
- if (info->components_num < 3) {
- state->ref_frame.cb = NULL;
- state->ref_frame.cr = NULL;
- state->ref_frame.alpha = NULL;
- return 0;
- }
-
- state->ref_frame.cb = state->ref_frame.luma + size;
- state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
-
- if (info->components_num == 4)
- state->ref_frame.alpha =
- state->ref_frame.cr + size / chroma_div;
- else
- state->ref_frame.alpha = NULL;
-
- return 0;
-}
-
-static void vicodec_stop_streaming(struct vb2_queue *q)
-{
- struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
-
- vicodec_return_bufs(q, VB2_BUF_STATE_ERROR);
-
- v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
-
- if (V4L2_TYPE_IS_OUTPUT(q->type) &&
- v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
- v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
-
- if (!ctx->is_enc && V4L2_TYPE_IS_OUTPUT(q->type))
- ctx->first_source_change_sent = false;
-
- if ((!V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
- (V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) {
- if (!ctx->is_stateless)
- kvfree(ctx->state.ref_frame.buf);
- ctx->state.ref_frame.buf = NULL;
- ctx->state.ref_frame.luma = NULL;
- ctx->comp_max_size = 0;
- ctx->source_changed = false;
- }
- if (V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) {
- ctx->cur_buf_offset = 0;
- ctx->comp_size = 0;
- ctx->header_size = 0;
- ctx->comp_magic_cnt = 0;
- ctx->comp_has_frame = 0;
- ctx->comp_has_next_frame = 0;
- }
-}
-
-static void vicodec_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
-}
-
-
-static const struct vb2_ops vicodec_qops = {
- .queue_setup = vicodec_queue_setup,
- .buf_out_validate = vicodec_buf_out_validate,
- .buf_prepare = vicodec_buf_prepare,
- .buf_queue = vicodec_buf_queue,
- .buf_request_complete = vicodec_buf_request_complete,
- .start_streaming = vicodec_start_streaming,
- .stop_streaming = vicodec_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-static int queue_init(void *priv, struct vb2_queue *src_vq,
- struct vb2_queue *dst_vq)
-{
- struct vicodec_ctx *ctx = priv;
- int ret;
-
- src_vq->type = (multiplanar ?
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
- V4L2_BUF_TYPE_VIDEO_OUTPUT);
- src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
- src_vq->drv_priv = ctx;
- src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
- src_vq->ops = &vicodec_qops;
- src_vq->mem_ops = &vb2_vmalloc_memops;
- src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- if (ctx->is_enc)
- src_vq->lock = &ctx->dev->stateful_enc.mutex;
- else if (ctx->is_stateless)
- src_vq->lock = &ctx->dev->stateless_dec.mutex;
- else
- src_vq->lock = &ctx->dev->stateful_dec.mutex;
- src_vq->supports_requests = ctx->is_stateless;
- src_vq->requires_requests = ctx->is_stateless;
- ret = vb2_queue_init(src_vq);
- if (ret)
- return ret;
-
- dst_vq->type = (multiplanar ?
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
- dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
- dst_vq->drv_priv = ctx;
- dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
- dst_vq->ops = &vicodec_qops;
- dst_vq->mem_ops = &vb2_vmalloc_memops;
- dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- dst_vq->lock = src_vq->lock;
-
- return vb2_queue_init(dst_vq);
-}
-
-static int vicodec_try_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vicodec_ctx *ctx = container_of(ctrl->handler,
- struct vicodec_ctx, hdl);
- const struct v4l2_ctrl_fwht_params *params;
- struct vicodec_q_data *q_dst = get_q_data(ctx,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:
- if (!q_dst->info)
- return -EINVAL;
- params = ctrl->p_new.p_fwht_params;
- if (params->width > q_dst->coded_width ||
- params->width < MIN_WIDTH ||
- params->height > q_dst->coded_height ||
- params->height < MIN_HEIGHT)
- return -EINVAL;
- if (!validate_by_version(params->flags, params->version))
- return -EINVAL;
- if (!validate_stateless_params_flags(params, q_dst->info))
- return -EINVAL;
- return 0;
- default:
- return 0;
- }
- return 0;
-}
-
-static void update_header_from_stateless_params(struct vicodec_ctx *ctx,
- const struct v4l2_ctrl_fwht_params *params)
-{
- struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
-
- p_hdr->magic1 = FWHT_MAGIC1;
- p_hdr->magic2 = FWHT_MAGIC2;
- p_hdr->version = htonl(params->version);
- p_hdr->width = htonl(params->width);
- p_hdr->height = htonl(params->height);
- p_hdr->flags = htonl(params->flags);
- p_hdr->colorspace = htonl(params->colorspace);
- p_hdr->xfer_func = htonl(params->xfer_func);
- p_hdr->ycbcr_enc = htonl(params->ycbcr_enc);
- p_hdr->quantization = htonl(params->quantization);
-}
-
-static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vicodec_ctx *ctx = container_of(ctrl->handler,
- struct vicodec_ctx, hdl);
- const struct v4l2_ctrl_fwht_params *params;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- ctx->state.gop_size = ctrl->val;
- return 0;
- case V4L2_CID_FWHT_I_FRAME_QP:
- ctx->state.i_frame_qp = ctrl->val;
- return 0;
- case V4L2_CID_FWHT_P_FRAME_QP:
- ctx->state.p_frame_qp = ctrl->val;
- return 0;
- case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:
- params = ctrl->p_new.p_fwht_params;
- update_header_from_stateless_params(ctx, params);
- ctx->state.ref_frame_ts = params->backward_ref_ts;
- return 0;
- }
- return -EINVAL;
-}
-
-static const struct v4l2_ctrl_ops vicodec_ctrl_ops = {
- .s_ctrl = vicodec_s_ctrl,
- .try_ctrl = vicodec_try_ctrl,
-};
-
-static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state = {
- .ops = &vicodec_ctrl_ops,
- .id = V4L2_CID_MPEG_VIDEO_FWHT_PARAMS,
- .elem_size = sizeof(struct v4l2_ctrl_fwht_params),
-};
-
-/*
- * File operations
- */
-static int vicodec_open(struct file *file)
-{
- const struct v4l2_fwht_pixfmt_info *info = v4l2_fwht_get_pixfmt(0);
- struct video_device *vfd = video_devdata(file);
- struct vicodec_dev *dev = video_drvdata(file);
- struct vicodec_ctx *ctx = NULL;
- struct v4l2_ctrl_handler *hdl;
- unsigned int raw_size;
- unsigned int comp_size;
- int rc = 0;
-
- if (mutex_lock_interruptible(vfd->lock))
- return -ERESTARTSYS;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx) {
- rc = -ENOMEM;
- goto open_unlock;
- }
-
- if (vfd == &dev->stateful_enc.vfd)
- ctx->is_enc = true;
- else if (vfd == &dev->stateless_dec.vfd)
- ctx->is_stateless = true;
-
- v4l2_fh_init(&ctx->fh, video_devdata(file));
- file->private_data = &ctx->fh;
- ctx->dev = dev;
- hdl = &ctx->hdl;
- v4l2_ctrl_handler_init(hdl, 5);
- v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE,
- 1, 16, 1, 10);
- v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_I_FRAME_QP,
- 1, 31, 1, 20);
- v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_P_FRAME_QP,
- 1, 31, 1, 20);
- if (ctx->is_enc)
- v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops,
- V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 1, 1, 1);
- if (ctx->is_stateless)
- v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_stateless_state, NULL);
- if (hdl->error) {
- rc = hdl->error;
- v4l2_ctrl_handler_free(hdl);
- kfree(ctx);
- goto open_unlock;
- }
- ctx->fh.ctrl_handler = hdl;
- v4l2_ctrl_handler_setup(hdl);
-
- if (ctx->is_enc)
- ctx->q_data[V4L2_M2M_SRC].info = info;
- else if (ctx->is_stateless)
- ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_stateless_fwht;
- else
- ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_fwht;
- ctx->q_data[V4L2_M2M_SRC].coded_width = 1280;
- ctx->q_data[V4L2_M2M_SRC].coded_height = 720;
- ctx->q_data[V4L2_M2M_SRC].visible_width = 1280;
- ctx->q_data[V4L2_M2M_SRC].visible_height = 720;
- raw_size = 1280 * 720 * info->sizeimage_mult / info->sizeimage_div;
- comp_size = 1280 * 720 * pixfmt_fwht.sizeimage_mult /
- pixfmt_fwht.sizeimage_div;
- if (ctx->is_enc)
- ctx->q_data[V4L2_M2M_SRC].sizeimage = raw_size;
- else if (ctx->is_stateless)
- ctx->q_data[V4L2_M2M_SRC].sizeimage = comp_size;
- else
- ctx->q_data[V4L2_M2M_SRC].sizeimage =
- comp_size + sizeof(struct fwht_cframe_hdr);
- ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
- if (ctx->is_enc) {
- ctx->q_data[V4L2_M2M_DST].info = &pixfmt_fwht;
- ctx->q_data[V4L2_M2M_DST].sizeimage =
- comp_size + sizeof(struct fwht_cframe_hdr);
- } else {
- ctx->q_data[V4L2_M2M_DST].info = info;
- ctx->q_data[V4L2_M2M_DST].sizeimage = raw_size;
- }
-
- ctx->state.colorspace = V4L2_COLORSPACE_REC709;
-
- if (ctx->is_enc) {
- ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_enc.m2m_dev,
- ctx, &queue_init);
- ctx->lock = &dev->stateful_enc.lock;
- } else if (ctx->is_stateless) {
- ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateless_dec.m2m_dev,
- ctx, &queue_init);
- ctx->lock = &dev->stateless_dec.lock;
- } else {
- ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_dec.m2m_dev,
- ctx, &queue_init);
- ctx->lock = &dev->stateful_dec.lock;
- }
-
- if (IS_ERR(ctx->fh.m2m_ctx)) {
- rc = PTR_ERR(ctx->fh.m2m_ctx);
-
- v4l2_ctrl_handler_free(hdl);
- v4l2_fh_exit(&ctx->fh);
- kfree(ctx);
- goto open_unlock;
- }
-
- v4l2_fh_add(&ctx->fh);
-
-open_unlock:
- mutex_unlock(vfd->lock);
- return rc;
-}
-
-static int vicodec_release(struct file *file)
-{
- struct video_device *vfd = video_devdata(file);
- struct vicodec_ctx *ctx = file2ctx(file);
-
- mutex_lock(vfd->lock);
- v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
- mutex_unlock(vfd->lock);
- v4l2_fh_del(&ctx->fh);
- v4l2_fh_exit(&ctx->fh);
- v4l2_ctrl_handler_free(&ctx->hdl);
- kvfree(ctx->state.compressed_frame);
- kfree(ctx);
-
- return 0;
-}
-
-static int vicodec_request_validate(struct media_request *req)
-{
- struct media_request_object *obj;
- struct v4l2_ctrl_handler *parent_hdl, *hdl;
- struct vicodec_ctx *ctx = NULL;
- struct v4l2_ctrl *ctrl;
- unsigned int count;
-
- list_for_each_entry(obj, &req->objects, list) {
- struct vb2_buffer *vb;
-
- if (vb2_request_object_is_buffer(obj)) {
- vb = container_of(obj, struct vb2_buffer, req_obj);
- ctx = vb2_get_drv_priv(vb->vb2_queue);
-
- break;
- }
- }
-
- if (!ctx) {
- pr_err("No buffer was provided with the request\n");
- return -ENOENT;
- }
-
- count = vb2_request_buffer_cnt(req);
- if (!count) {
- v4l2_info(&ctx->dev->v4l2_dev,
- "No buffer was provided with the request\n");
- return -ENOENT;
- } else if (count > 1) {
- v4l2_info(&ctx->dev->v4l2_dev,
- "More than one buffer was provided with the request\n");
- return -EINVAL;
- }
-
- parent_hdl = &ctx->hdl;
-
- hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
- if (!hdl) {
- v4l2_info(&ctx->dev->v4l2_dev, "Missing codec control\n");
- return -ENOENT;
- }
- ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl,
- vicodec_ctrl_stateless_state.id);
- if (!ctrl) {
- v4l2_info(&ctx->dev->v4l2_dev,
- "Missing required codec control\n");
- return -ENOENT;
- }
-
- return vb2_request_validate(req);
-}
-
-static const struct v4l2_file_operations vicodec_fops = {
- .owner = THIS_MODULE,
- .open = vicodec_open,
- .release = vicodec_release,
- .poll = v4l2_m2m_fop_poll,
- .unlocked_ioctl = video_ioctl2,
- .mmap = v4l2_m2m_fop_mmap,
-};
-
-static const struct video_device vicodec_videodev = {
- .name = VICODEC_NAME,
- .vfl_dir = VFL_DIR_M2M,
- .fops = &vicodec_fops,
- .ioctl_ops = &vicodec_ioctl_ops,
- .minor = -1,
- .release = video_device_release_empty,
-};
-
-static const struct media_device_ops vicodec_m2m_media_ops = {
- .req_validate = vicodec_request_validate,
- .req_queue = v4l2_m2m_request_queue,
-};
-
-static const struct v4l2_m2m_ops m2m_ops = {
- .device_run = device_run,
- .job_ready = job_ready,
-};
-
-static int register_instance(struct vicodec_dev *dev,
- struct vicodec_dev_instance *dev_instance,
- const char *name, bool is_enc)
-{
- struct video_device *vfd;
- int ret;
-
- spin_lock_init(&dev_instance->lock);
- mutex_init(&dev_instance->mutex);
- dev_instance->m2m_dev = v4l2_m2m_init(&m2m_ops);
- if (IS_ERR(dev_instance->m2m_dev)) {
- v4l2_err(&dev->v4l2_dev, "Failed to init vicodec enc device\n");
- return PTR_ERR(dev_instance->m2m_dev);
- }
-
- dev_instance->vfd = vicodec_videodev;
- vfd = &dev_instance->vfd;
- vfd->lock = &dev_instance->mutex;
- vfd->v4l2_dev = &dev->v4l2_dev;
- strscpy(vfd->name, name, sizeof(vfd->name));
- vfd->device_caps = V4L2_CAP_STREAMING |
- (multiplanar ? V4L2_CAP_VIDEO_M2M_MPLANE : V4L2_CAP_VIDEO_M2M);
- if (is_enc) {
- v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
- v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
- } else {
- v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
- v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
- }
- video_set_drvdata(vfd, dev);
-
- ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
- if (ret) {
- v4l2_err(&dev->v4l2_dev, "Failed to register video device '%s'\n", name);
- v4l2_m2m_release(dev_instance->m2m_dev);
- return ret;
- }
- v4l2_info(&dev->v4l2_dev, "Device '%s' registered as /dev/video%d\n",
- name, vfd->num);
- return 0;
-}
-
-static void vicodec_v4l2_dev_release(struct v4l2_device *v4l2_dev)
-{
- struct vicodec_dev *dev = container_of(v4l2_dev, struct vicodec_dev, v4l2_dev);
-
- v4l2_device_unregister(&dev->v4l2_dev);
- v4l2_m2m_release(dev->stateful_enc.m2m_dev);
- v4l2_m2m_release(dev->stateful_dec.m2m_dev);
- v4l2_m2m_release(dev->stateless_dec.m2m_dev);
-#ifdef CONFIG_MEDIA_CONTROLLER
- media_device_cleanup(&dev->mdev);
-#endif
- kfree(dev);
-}
-
-static int vicodec_probe(struct platform_device *pdev)
-{
- struct vicodec_dev *dev;
- int ret;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
-
- ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
- if (ret)
- goto free_dev;
-
- dev->v4l2_dev.release = vicodec_v4l2_dev_release;
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->mdev.dev = &pdev->dev;
- strscpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model));
- strscpy(dev->mdev.bus_info, "platform:vicodec",
- sizeof(dev->mdev.bus_info));
- media_device_init(&dev->mdev);
- dev->mdev.ops = &vicodec_m2m_media_ops;
- dev->v4l2_dev.mdev = &dev->mdev;
-#endif
-
- platform_set_drvdata(pdev, dev);
-
- if (register_instance(dev, &dev->stateful_enc,
- "stateful-encoder", true))
- goto unreg_dev;
-
- if (register_instance(dev, &dev->stateful_dec,
- "stateful-decoder", false))
- goto unreg_sf_enc;
-
- if (register_instance(dev, &dev->stateless_dec,
- "stateless-decoder", false))
- goto unreg_sf_dec;
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- ret = v4l2_m2m_register_media_controller(dev->stateful_enc.m2m_dev,
- &dev->stateful_enc.vfd,
- MEDIA_ENT_F_PROC_VIDEO_ENCODER);
- if (ret) {
- v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for enc\n");
- goto unreg_m2m;
- }
-
- ret = v4l2_m2m_register_media_controller(dev->stateful_dec.m2m_dev,
- &dev->stateful_dec.vfd,
- MEDIA_ENT_F_PROC_VIDEO_DECODER);
- if (ret) {
- v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for dec\n");
- goto unreg_m2m_sf_enc_mc;
- }
-
- ret = v4l2_m2m_register_media_controller(dev->stateless_dec.m2m_dev,
- &dev->stateless_dec.vfd,
- MEDIA_ENT_F_PROC_VIDEO_DECODER);
- if (ret) {
- v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for stateless dec\n");
- goto unreg_m2m_sf_dec_mc;
- }
-
- ret = media_device_register(&dev->mdev);
- if (ret) {
- v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
- goto unreg_m2m_sl_dec_mc;
- }
-#endif
- return 0;
-
-#ifdef CONFIG_MEDIA_CONTROLLER
-unreg_m2m_sl_dec_mc:
- v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev);
-unreg_m2m_sf_dec_mc:
- v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev);
-unreg_m2m_sf_enc_mc:
- v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev);
-unreg_m2m:
- video_unregister_device(&dev->stateless_dec.vfd);
- v4l2_m2m_release(dev->stateless_dec.m2m_dev);
-#endif
-unreg_sf_dec:
- video_unregister_device(&dev->stateful_dec.vfd);
- v4l2_m2m_release(dev->stateful_dec.m2m_dev);
-unreg_sf_enc:
- video_unregister_device(&dev->stateful_enc.vfd);
- v4l2_m2m_release(dev->stateful_enc.m2m_dev);
-unreg_dev:
- v4l2_device_unregister(&dev->v4l2_dev);
-free_dev:
- kfree(dev);
-
- return ret;
-}
-
-static int vicodec_remove(struct platform_device *pdev)
-{
- struct vicodec_dev *dev = platform_get_drvdata(pdev);
-
- v4l2_info(&dev->v4l2_dev, "Removing " VICODEC_NAME);
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- media_device_unregister(&dev->mdev);
- v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev);
- v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev);
- v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev);
-#endif
-
- video_unregister_device(&dev->stateful_enc.vfd);
- 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,
- .driver = {
- .name = VICODEC_NAME,
- },
-};
-
-static void __exit vicodec_exit(void)
-{
- platform_driver_unregister(&vicodec_pdrv);
- platform_device_unregister(&vicodec_pdev);
-}
-
-static int __init vicodec_init(void)
-{
- int ret;
-
- ret = platform_device_register(&vicodec_pdev);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&vicodec_pdrv);
- if (ret)
- platform_device_unregister(&vicodec_pdev);
-
- return ret;
-}
-
-module_init(vicodec_init);
-module_exit(vicodec_exit);
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
index ddd0e338f9e4..53570250a25d 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -17,10 +17,12 @@
#include <media/v4l2-async.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
#include <media/v4l2-subdev.h>
struct video_mux {
struct v4l2_subdev subdev;
+ struct v4l2_async_notifier notifier;
struct media_pad *pads;
struct v4l2_mbus_framefmt *format_mbus;
struct mux_control *mux;
@@ -35,6 +37,12 @@ static const struct v4l2_mbus_framefmt video_mux_format_mbus_default = {
.field = V4L2_FIELD_NONE,
};
+static inline struct video_mux *
+notifier_to_video_mux(struct v4l2_async_notifier *n)
+{
+ return container_of(n, struct video_mux, notifier);
+}
+
static inline struct video_mux *v4l2_subdev_to_video_mux(struct v4l2_subdev *sd)
{
return container_of(sd, struct video_mux, subdev);
@@ -96,6 +104,7 @@ out:
static const struct media_entity_operations video_mux_ops = {
.link_setup = video_mux_link_setup,
.link_validate = v4l2_subdev_link_validate,
+ .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
};
static int video_mux_s_stream(struct v4l2_subdev *sd, int enable)
@@ -330,36 +339,64 @@ static const struct v4l2_subdev_ops video_mux_subdev_ops = {
.video = &video_mux_subdev_video_ops,
};
-static int video_mux_parse_endpoint(struct device *dev,
- struct v4l2_fwnode_endpoint *vep,
- struct v4l2_async_subdev *asd)
+static int video_mux_notify_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
{
- /*
- * it's not an error if remote is missing on a video-mux
- * input port, return -ENOTCONN to skip this endpoint with
- * no error.
- */
- return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN;
+ struct video_mux *vmux = notifier_to_video_mux(notifier);
+
+ return v4l2_create_fwnode_links(sd, &vmux->subdev);
}
+static const struct v4l2_async_notifier_operations video_mux_notify_ops = {
+ .bound = video_mux_notify_bound,
+};
+
static int video_mux_async_register(struct video_mux *vmux,
unsigned int num_input_pads)
{
- unsigned int i, *ports;
+ unsigned int i;
int ret;
- ports = kcalloc(num_input_pads, sizeof(*ports), GFP_KERNEL);
- if (!ports)
- return -ENOMEM;
- for (i = 0; i < num_input_pads; i++)
- ports[i] = i;
+ v4l2_async_notifier_init(&vmux->notifier);
- ret = v4l2_async_register_fwnode_subdev(
- &vmux->subdev, sizeof(struct v4l2_async_subdev),
- ports, num_input_pads, video_mux_parse_endpoint);
+ for (i = 0; i < num_input_pads; i++) {
+ struct v4l2_async_subdev *asd;
+ struct fwnode_handle *ep;
- kfree(ports);
- return ret;
+ ep = fwnode_graph_get_endpoint_by_id(
+ dev_fwnode(vmux->subdev.dev), i, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+ if (!ep)
+ continue;
+
+ asd = kzalloc(sizeof(*asd), GFP_KERNEL);
+ if (!asd) {
+ fwnode_handle_put(ep);
+ return -ENOMEM;
+ }
+
+ ret = v4l2_async_notifier_add_fwnode_remote_subdev(
+ &vmux->notifier, ep, asd);
+
+ fwnode_handle_put(ep);
+
+ if (ret) {
+ kfree(asd);
+ /* OK if asd already exists */
+ if (ret != -EEXIST)
+ return ret;
+ }
+ }
+
+ vmux->notifier.ops = &video_mux_notify_ops;
+
+ ret = v4l2_async_subdev_notifier_register(&vmux->subdev,
+ &vmux->notifier);
+ if (ret)
+ return ret;
+
+ return v4l2_async_register_subdev(&vmux->subdev);
}
static int video_mux_probe(struct platform_device *pdev)
@@ -434,7 +471,13 @@ static int video_mux_probe(struct platform_device *pdev)
vmux->subdev.entity.ops = &video_mux_ops;
- return video_mux_async_register(vmux, num_pads - 1);
+ ret = video_mux_async_register(vmux, num_pads - 1);
+ if (ret) {
+ v4l2_async_notifier_unregister(&vmux->notifier);
+ v4l2_async_notifier_cleanup(&vmux->notifier);
+ }
+
+ return ret;
}
static int video_mux_remove(struct platform_device *pdev)
@@ -442,6 +485,8 @@ static int video_mux_remove(struct platform_device *pdev)
struct video_mux *vmux = platform_get_drvdata(pdev);
struct v4l2_subdev *sd = &vmux->subdev;
+ v4l2_async_notifier_unregister(&vmux->notifier);
+ v4l2_async_notifier_cleanup(&vmux->notifier);
v4l2_async_unregister_subdev(sd);
media_entity_cleanup(&sd->entity);
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
deleted file mode 100644
index ac6717fbb764..000000000000
--- a/drivers/media/platform/vim2m.c
+++ /dev/null
@@ -1,1441 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * A virtual v4l2-mem2mem example device.
- *
- * This is a virtual device driver for testing mem-to-mem videobuf framework.
- * It simulates a device that uses memory buffers for both source and
- * destination, processes the data and issues an "irq" (simulated by a delayed
- * workqueue).
- * The device is capable of multi-instance, multi-buffer-per-transaction
- * operation (via the mem2mem framework).
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * Pawel Osciak, <pawel@osciak.com>
- * Marek Szyprowski, <m.szyprowski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version
- */
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <linux/platform_device.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-vmalloc.h>
-
-MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
-MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.2");
-MODULE_ALIAS("mem2mem_testdev");
-
-static unsigned int debug;
-module_param(debug, uint, 0644);
-MODULE_PARM_DESC(debug, "debug level");
-
-/* Default transaction time in msec */
-static unsigned int default_transtime = 40; /* Max 25 fps */
-module_param(default_transtime, uint, 0644);
-MODULE_PARM_DESC(default_transtime, "default transaction time in ms");
-
-#define MIN_W 32
-#define MIN_H 32
-#define MAX_W 640
-#define MAX_H 480
-
-/* Pixel alignment for non-bayer formats */
-#define WIDTH_ALIGN 2
-#define HEIGHT_ALIGN 1
-
-/* Pixel alignment for bayer formats */
-#define BAYER_WIDTH_ALIGN 2
-#define BAYER_HEIGHT_ALIGN 2
-
-/* Flags that indicate a format can be used for capture/output */
-#define MEM2MEM_CAPTURE BIT(0)
-#define MEM2MEM_OUTPUT BIT(1)
-
-#define MEM2MEM_NAME "vim2m"
-
-/* Per queue */
-#define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME
-/* In bytes, per queue */
-#define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024)
-
-/* Flags that indicate processing mode */
-#define MEM2MEM_HFLIP BIT(0)
-#define MEM2MEM_VFLIP BIT(1)
-
-#define dprintk(dev, lvl, fmt, arg...) \
- v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg)
-
-static void vim2m_dev_release(struct device *dev)
-{}
-
-static struct platform_device vim2m_pdev = {
- .name = MEM2MEM_NAME,
- .dev.release = vim2m_dev_release,
-};
-
-struct vim2m_fmt {
- u32 fourcc;
- int depth;
- /* Types the format can be used for */
- u32 types;
-};
-
-static struct vim2m_fmt formats[] = {
- {
- .fourcc = V4L2_PIX_FMT_RGB565, /* rrrrrggg gggbbbbb */
- .depth = 16,
- .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
- }, {
- .fourcc = V4L2_PIX_FMT_RGB565X, /* gggbbbbb rrrrrggg */
- .depth = 16,
- .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
- }, {
- .fourcc = V4L2_PIX_FMT_RGB24,
- .depth = 24,
- .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
- }, {
- .fourcc = V4L2_PIX_FMT_BGR24,
- .depth = 24,
- .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
- }, {
- .fourcc = V4L2_PIX_FMT_YUYV,
- .depth = 16,
- .types = MEM2MEM_CAPTURE,
- }, {
- .fourcc = V4L2_PIX_FMT_SBGGR8,
- .depth = 8,
- .types = MEM2MEM_CAPTURE,
- }, {
- .fourcc = V4L2_PIX_FMT_SGBRG8,
- .depth = 8,
- .types = MEM2MEM_CAPTURE,
- }, {
- .fourcc = V4L2_PIX_FMT_SGRBG8,
- .depth = 8,
- .types = MEM2MEM_CAPTURE,
- }, {
- .fourcc = V4L2_PIX_FMT_SRGGB8,
- .depth = 8,
- .types = MEM2MEM_CAPTURE,
- },
-};
-
-#define NUM_FORMATS ARRAY_SIZE(formats)
-
-/* Per-queue, driver-specific private data */
-struct vim2m_q_data {
- unsigned int width;
- unsigned int height;
- unsigned int sizeimage;
- unsigned int sequence;
- struct vim2m_fmt *fmt;
-};
-
-enum {
- V4L2_M2M_SRC = 0,
- V4L2_M2M_DST = 1,
-};
-
-#define V4L2_CID_TRANS_TIME_MSEC (V4L2_CID_USER_BASE + 0x1000)
-#define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_USER_BASE + 0x1001)
-
-static struct vim2m_fmt *find_format(u32 fourcc)
-{
- struct vim2m_fmt *fmt;
- unsigned int k;
-
- for (k = 0; k < NUM_FORMATS; k++) {
- fmt = &formats[k];
- if (fmt->fourcc == fourcc)
- break;
- }
-
- if (k == NUM_FORMATS)
- return NULL;
-
- return &formats[k];
-}
-
-static void get_alignment(u32 fourcc,
- unsigned int *walign, unsigned int *halign)
-{
- switch (fourcc) {
- case V4L2_PIX_FMT_SBGGR8:
- case V4L2_PIX_FMT_SGBRG8:
- case V4L2_PIX_FMT_SGRBG8:
- case V4L2_PIX_FMT_SRGGB8:
- *walign = BAYER_WIDTH_ALIGN;
- *halign = BAYER_HEIGHT_ALIGN;
- return;
- default:
- *walign = WIDTH_ALIGN;
- *halign = HEIGHT_ALIGN;
- return;
- }
-}
-
-struct vim2m_dev {
- struct v4l2_device v4l2_dev;
- struct video_device vfd;
-#ifdef CONFIG_MEDIA_CONTROLLER
- struct media_device mdev;
-#endif
-
- atomic_t num_inst;
- struct mutex dev_mutex;
-
- struct v4l2_m2m_dev *m2m_dev;
-};
-
-struct vim2m_ctx {
- struct v4l2_fh fh;
- struct vim2m_dev *dev;
-
- struct v4l2_ctrl_handler hdl;
-
- /* Processed buffers in this transaction */
- u8 num_processed;
-
- /* Transaction length (i.e. how many buffers per transaction) */
- u32 translen;
- /* Transaction time (i.e. simulated processing time) in milliseconds */
- u32 transtime;
-
- struct mutex vb_mutex;
- struct delayed_work work_run;
- spinlock_t irqlock;
-
- /* Abort requested by m2m */
- int aborting;
-
- /* Processing mode */
- int mode;
-
- enum v4l2_colorspace colorspace;
- enum v4l2_ycbcr_encoding ycbcr_enc;
- enum v4l2_xfer_func xfer_func;
- enum v4l2_quantization quant;
-
- /* Source and destination queue data */
- struct vim2m_q_data q_data[2];
-};
-
-static inline struct vim2m_ctx *file2ctx(struct file *file)
-{
- return container_of(file->private_data, struct vim2m_ctx, fh);
-}
-
-static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx,
- enum v4l2_buf_type type)
-{
- switch (type) {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- return &ctx->q_data[V4L2_M2M_SRC];
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- return &ctx->q_data[V4L2_M2M_DST];
- default:
- return NULL;
- }
-}
-
-static const char *type_name(enum v4l2_buf_type type)
-{
- switch (type) {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- return "Output";
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- return "Capture";
- default:
- return "Invalid";
- }
-}
-
-#define CLIP(__color) \
- (u8)(((__color) > 0xff) ? 0xff : (((__color) < 0) ? 0 : (__color)))
-
-static void copy_line(struct vim2m_q_data *q_data_out,
- u8 *src, u8 *dst, bool reverse)
-{
- int x, depth = q_data_out->fmt->depth >> 3;
-
- if (!reverse) {
- memcpy(dst, src, q_data_out->width * depth);
- } else {
- for (x = 0; x < q_data_out->width >> 1; x++) {
- memcpy(dst, src, depth);
- memcpy(dst + depth, src - depth, depth);
- src -= depth << 1;
- dst += depth << 1;
- }
- return;
- }
-}
-
-static void copy_two_pixels(struct vim2m_q_data *q_data_in,
- struct vim2m_q_data *q_data_out,
- u8 *src[2], u8 **dst, int ypos, bool reverse)
-{
- struct vim2m_fmt *out = q_data_out->fmt;
- struct vim2m_fmt *in = q_data_in->fmt;
- u8 _r[2], _g[2], _b[2], *r, *g, *b;
- int i;
-
- /* Step 1: read two consecutive pixels from src pointer */
-
- r = _r;
- g = _g;
- b = _b;
-
- switch (in->fourcc) {
- case V4L2_PIX_FMT_RGB565: /* rrrrrggg gggbbbbb */
- for (i = 0; i < 2; i++) {
- u16 pix = le16_to_cpu(*(__le16 *)(src[i]));
-
- *r++ = (u8)(((pix & 0xf800) >> 11) << 3) | 0x07;
- *g++ = (u8)((((pix & 0x07e0) >> 5)) << 2) | 0x03;
- *b++ = (u8)((pix & 0x1f) << 3) | 0x07;
- }
- break;
- case V4L2_PIX_FMT_RGB565X: /* gggbbbbb rrrrrggg */
- for (i = 0; i < 2; i++) {
- u16 pix = be16_to_cpu(*(__be16 *)(src[i]));
-
- *r++ = (u8)(((pix & 0xf800) >> 11) << 3) | 0x07;
- *g++ = (u8)((((pix & 0x07e0) >> 5)) << 2) | 0x03;
- *b++ = (u8)((pix & 0x1f) << 3) | 0x07;
- }
- break;
- default:
- case V4L2_PIX_FMT_RGB24:
- for (i = 0; i < 2; i++) {
- *r++ = src[i][0];
- *g++ = src[i][1];
- *b++ = src[i][2];
- }
- break;
- case V4L2_PIX_FMT_BGR24:
- for (i = 0; i < 2; i++) {
- *b++ = src[i][0];
- *g++ = src[i][1];
- *r++ = src[i][2];
- }
- break;
- }
-
- /* Step 2: store two consecutive points, reversing them if needed */
-
- r = _r;
- g = _g;
- b = _b;
-
- switch (out->fourcc) {
- case V4L2_PIX_FMT_RGB565: /* rrrrrggg gggbbbbb */
- for (i = 0; i < 2; i++) {
- u16 pix;
- __le16 *dst_pix = (__le16 *)*dst;
-
- pix = ((*r << 8) & 0xf800) | ((*g << 3) & 0x07e0) |
- (*b >> 3);
-
- *dst_pix = cpu_to_le16(pix);
-
- *dst += 2;
- }
- return;
- case V4L2_PIX_FMT_RGB565X: /* gggbbbbb rrrrrggg */
- for (i = 0; i < 2; i++) {
- u16 pix;
- __be16 *dst_pix = (__be16 *)*dst;
-
- pix = ((*r << 8) & 0xf800) | ((*g << 3) & 0x07e0) |
- (*b >> 3);
-
- *dst_pix = cpu_to_be16(pix);
-
- *dst += 2;
- }
- return;
- case V4L2_PIX_FMT_RGB24:
- for (i = 0; i < 2; i++) {
- *(*dst)++ = *r++;
- *(*dst)++ = *g++;
- *(*dst)++ = *b++;
- }
- return;
- case V4L2_PIX_FMT_BGR24:
- for (i = 0; i < 2; i++) {
- *(*dst)++ = *b++;
- *(*dst)++ = *g++;
- *(*dst)++ = *r++;
- }
- return;
- case V4L2_PIX_FMT_YUYV:
- default:
- {
- u8 y, y1, u, v;
-
- y = ((8453 * (*r) + 16594 * (*g) + 3223 * (*b)
- + 524288) >> 15);
- u = ((-4878 * (*r) - 9578 * (*g) + 14456 * (*b)
- + 4210688) >> 15);
- v = ((14456 * (*r++) - 12105 * (*g++) - 2351 * (*b++)
- + 4210688) >> 15);
- y1 = ((8453 * (*r) + 16594 * (*g) + 3223 * (*b)
- + 524288) >> 15);
-
- *(*dst)++ = y;
- *(*dst)++ = u;
-
- *(*dst)++ = y1;
- *(*dst)++ = v;
- return;
- }
- case V4L2_PIX_FMT_SBGGR8:
- if (!(ypos & 1)) {
- *(*dst)++ = *b;
- *(*dst)++ = *++g;
- } else {
- *(*dst)++ = *g;
- *(*dst)++ = *++r;
- }
- return;
- case V4L2_PIX_FMT_SGBRG8:
- if (!(ypos & 1)) {
- *(*dst)++ = *g;
- *(*dst)++ = *++b;
- } else {
- *(*dst)++ = *r;
- *(*dst)++ = *++g;
- }
- return;
- case V4L2_PIX_FMT_SGRBG8:
- if (!(ypos & 1)) {
- *(*dst)++ = *g;
- *(*dst)++ = *++r;
- } else {
- *(*dst)++ = *b;
- *(*dst)++ = *++g;
- }
- return;
- case V4L2_PIX_FMT_SRGGB8:
- if (!(ypos & 1)) {
- *(*dst)++ = *r;
- *(*dst)++ = *++g;
- } else {
- *(*dst)++ = *g;
- *(*dst)++ = *++b;
- }
- return;
- }
-}
-
-static int device_process(struct vim2m_ctx *ctx,
- struct vb2_v4l2_buffer *in_vb,
- struct vb2_v4l2_buffer *out_vb)
-{
- struct vim2m_dev *dev = ctx->dev;
- struct vim2m_q_data *q_data_in, *q_data_out;
- u8 *p_in, *p_line, *p_in_x[2], *p, *p_out;
- unsigned int width, height, bytesperline, bytes_per_pixel;
- unsigned int x, y, y_in, y_out, x_int, x_fract, x_err, x_offset;
- int start, end, step;
-
- q_data_in = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
- if (!q_data_in)
- return 0;
- bytesperline = (q_data_in->width * q_data_in->fmt->depth) >> 3;
- bytes_per_pixel = q_data_in->fmt->depth >> 3;
-
- q_data_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (!q_data_out)
- return 0;
-
- /* As we're doing scaling, use the output dimensions here */
- height = q_data_out->height;
- width = q_data_out->width;
-
- p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0);
- p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0);
- if (!p_in || !p_out) {
- v4l2_err(&dev->v4l2_dev,
- "Acquiring kernel pointers to buffers failed\n");
- return -EFAULT;
- }
-
- out_vb->sequence = q_data_out->sequence++;
- in_vb->sequence = q_data_in->sequence++;
- v4l2_m2m_buf_copy_metadata(in_vb, out_vb, true);
-
- if (ctx->mode & MEM2MEM_VFLIP) {
- start = height - 1;
- end = -1;
- step = -1;
- } else {
- start = 0;
- end = height;
- step = 1;
- }
- y_out = 0;
-
- /*
- * When format and resolution are identical,
- * we can use a faster copy logic
- */
- if (q_data_in->fmt->fourcc == q_data_out->fmt->fourcc &&
- q_data_in->width == q_data_out->width &&
- q_data_in->height == q_data_out->height) {
- for (y = start; y != end; y += step, y_out++) {
- p = p_in + (y * bytesperline);
- if (ctx->mode & MEM2MEM_HFLIP)
- p += bytesperline - (q_data_in->fmt->depth >> 3);
-
- copy_line(q_data_out, p, p_out,
- ctx->mode & MEM2MEM_HFLIP);
-
- p_out += bytesperline;
- }
- return 0;
- }
-
- /* Slower algorithm with format conversion, hflip, vflip and scaler */
-
- /* To speed scaler up, use Bresenham for X dimension */
- x_int = q_data_in->width / q_data_out->width;
- x_fract = q_data_in->width % q_data_out->width;
-
- for (y = start; y != end; y += step, y_out++) {
- y_in = (y * q_data_in->height) / q_data_out->height;
- x_offset = 0;
- x_err = 0;
-
- p_line = p_in + (y_in * bytesperline);
- if (ctx->mode & MEM2MEM_HFLIP)
- p_line += bytesperline - (q_data_in->fmt->depth >> 3);
- p_in_x[0] = p_line;
-
- for (x = 0; x < width >> 1; x++) {
- x_offset += x_int;
- x_err += x_fract;
- if (x_err > width) {
- x_offset++;
- x_err -= width;
- }
-
- if (ctx->mode & MEM2MEM_HFLIP)
- p_in_x[1] = p_line - x_offset * bytes_per_pixel;
- else
- p_in_x[1] = p_line + x_offset * bytes_per_pixel;
-
- copy_two_pixels(q_data_in, q_data_out,
- p_in_x, &p_out, y_out,
- ctx->mode & MEM2MEM_HFLIP);
-
- /* Calculate the next p_in_x0 */
- x_offset += x_int;
- x_err += x_fract;
- if (x_err > width) {
- x_offset++;
- x_err -= width;
- }
-
- if (ctx->mode & MEM2MEM_HFLIP)
- p_in_x[0] = p_line - x_offset * bytes_per_pixel;
- else
- p_in_x[0] = p_line + x_offset * bytes_per_pixel;
- }
- }
-
- return 0;
-}
-
-/*
- * mem2mem callbacks
- */
-
-/*
- * job_ready() - check whether an instance is ready to be scheduled to run
- */
-static int job_ready(void *priv)
-{
- struct vim2m_ctx *ctx = priv;
-
- if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen
- || v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen) {
- dprintk(ctx->dev, 1, "Not enough buffers available\n");
- return 0;
- }
-
- return 1;
-}
-
-static void job_abort(void *priv)
-{
- struct vim2m_ctx *ctx = priv;
-
- /* Will cancel the transaction in the next interrupt handler */
- ctx->aborting = 1;
-}
-
-/* device_run() - prepares and starts the device
- *
- * This simulates all the immediate preparations required before starting
- * a device. This will be called by the framework when it decides to schedule
- * a particular instance.
- */
-static void device_run(void *priv)
-{
- struct vim2m_ctx *ctx = priv;
- struct vb2_v4l2_buffer *src_buf, *dst_buf;
-
- src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
- dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-
- /* Apply request controls if any */
- v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req,
- &ctx->hdl);
-
- device_process(ctx, src_buf, dst_buf);
-
- /* Complete request controls if any */
- v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req,
- &ctx->hdl);
-
- /* Run delayed work, which simulates a hardware irq */
- schedule_delayed_work(&ctx->work_run, msecs_to_jiffies(ctx->transtime));
-}
-
-static void device_work(struct work_struct *w)
-{
- struct vim2m_ctx *curr_ctx;
- struct vim2m_dev *vim2m_dev;
- struct vb2_v4l2_buffer *src_vb, *dst_vb;
- unsigned long flags;
-
- curr_ctx = container_of(w, struct vim2m_ctx, work_run.work);
-
- if (!curr_ctx) {
- pr_err("Instance released before the end of transaction\n");
- return;
- }
-
- vim2m_dev = curr_ctx->dev;
-
- src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
- dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
-
- curr_ctx->num_processed++;
-
- spin_lock_irqsave(&curr_ctx->irqlock, flags);
- v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
- v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
- spin_unlock_irqrestore(&curr_ctx->irqlock, flags);
-
- if (curr_ctx->num_processed == curr_ctx->translen
- || curr_ctx->aborting) {
- dprintk(curr_ctx->dev, 2, "Finishing capture buffer fill\n");
- curr_ctx->num_processed = 0;
- v4l2_m2m_job_finish(vim2m_dev->m2m_dev, curr_ctx->fh.m2m_ctx);
- } else {
- device_run(curr_ctx);
- }
-}
-
-/*
- * video ioctls
- */
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
- strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
- snprintf(cap->bus_info, sizeof(cap->bus_info),
- "platform:%s", MEM2MEM_NAME);
- return 0;
-}
-
-static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
-{
- int i, num;
- struct vim2m_fmt *fmt;
-
- num = 0;
-
- for (i = 0; i < NUM_FORMATS; ++i) {
- if (formats[i].types & type) {
- /* index-th format of type type found ? */
- if (num == f->index)
- break;
- /*
- * Correct type but haven't reached our index yet,
- * just increment per-type index
- */
- ++num;
- }
- }
-
- if (i < NUM_FORMATS) {
- /* Format found */
- fmt = &formats[i];
- f->pixelformat = fmt->fourcc;
- return 0;
- }
-
- /* Format not found */
- return -EINVAL;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- return enum_fmt(f, MEM2MEM_CAPTURE);
-}
-
-static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- return enum_fmt(f, MEM2MEM_OUTPUT);
-}
-
-static int vidioc_enum_framesizes(struct file *file, void *priv,
- struct v4l2_frmsizeenum *fsize)
-{
- if (fsize->index != 0)
- return -EINVAL;
-
- if (!find_format(fsize->pixel_format))
- return -EINVAL;
-
- fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
- fsize->stepwise.min_width = MIN_W;
- fsize->stepwise.min_height = MIN_H;
- fsize->stepwise.max_width = MAX_W;
- fsize->stepwise.max_height = MAX_H;
-
- get_alignment(fsize->pixel_format,
- &fsize->stepwise.step_width,
- &fsize->stepwise.step_height);
- return 0;
-}
-
-static int vidioc_g_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
-{
- struct vb2_queue *vq;
- struct vim2m_q_data *q_data;
-
- vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
- if (!vq)
- return -EINVAL;
-
- q_data = get_q_data(ctx, f->type);
- if (!q_data)
- return -EINVAL;
-
- f->fmt.pix.width = q_data->width;
- f->fmt.pix.height = q_data->height;
- f->fmt.pix.field = V4L2_FIELD_NONE;
- f->fmt.pix.pixelformat = q_data->fmt->fourcc;
- f->fmt.pix.bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
- f->fmt.pix.sizeimage = q_data->sizeimage;
- f->fmt.pix.colorspace = ctx->colorspace;
- f->fmt.pix.xfer_func = ctx->xfer_func;
- f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
- f->fmt.pix.quantization = ctx->quant;
-
- return 0;
-}
-
-static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- return vidioc_g_fmt(file2ctx(file), f);
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- return vidioc_g_fmt(file2ctx(file), f);
-}
-
-static int vidioc_try_fmt(struct v4l2_format *f, struct vim2m_fmt *fmt)
-{
- int walign, halign;
- /*
- * V4L2 specification specifies the driver corrects the
- * format struct if any of the dimensions is unsupported
- */
- if (f->fmt.pix.height < MIN_H)
- f->fmt.pix.height = MIN_H;
- else if (f->fmt.pix.height > MAX_H)
- f->fmt.pix.height = MAX_H;
-
- if (f->fmt.pix.width < MIN_W)
- f->fmt.pix.width = MIN_W;
- else if (f->fmt.pix.width > MAX_W)
- f->fmt.pix.width = MAX_W;
-
- get_alignment(f->fmt.pix.pixelformat, &walign, &halign);
- f->fmt.pix.width &= ~(walign - 1);
- f->fmt.pix.height &= ~(halign - 1);
- f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
- f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
- f->fmt.pix.field = V4L2_FIELD_NONE;
-
- return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vim2m_fmt *fmt;
- struct vim2m_ctx *ctx = file2ctx(file);
-
- fmt = find_format(f->fmt.pix.pixelformat);
- if (!fmt) {
- f->fmt.pix.pixelformat = formats[0].fourcc;
- fmt = find_format(f->fmt.pix.pixelformat);
- }
- if (!(fmt->types & MEM2MEM_CAPTURE)) {
- v4l2_err(&ctx->dev->v4l2_dev,
- "Fourcc format (0x%08x) invalid.\n",
- f->fmt.pix.pixelformat);
- return -EINVAL;
- }
- f->fmt.pix.colorspace = ctx->colorspace;
- f->fmt.pix.xfer_func = ctx->xfer_func;
- f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
- f->fmt.pix.quantization = ctx->quant;
-
- return vidioc_try_fmt(f, fmt);
-}
-
-static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vim2m_fmt *fmt;
- struct vim2m_ctx *ctx = file2ctx(file);
-
- fmt = find_format(f->fmt.pix.pixelformat);
- if (!fmt) {
- f->fmt.pix.pixelformat = formats[0].fourcc;
- fmt = find_format(f->fmt.pix.pixelformat);
- }
- if (!(fmt->types & MEM2MEM_OUTPUT)) {
- v4l2_err(&ctx->dev->v4l2_dev,
- "Fourcc format (0x%08x) invalid.\n",
- f->fmt.pix.pixelformat);
- return -EINVAL;
- }
- if (!f->fmt.pix.colorspace)
- f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
-
- return vidioc_try_fmt(f, fmt);
-}
-
-static int vidioc_s_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
-{
- struct vim2m_q_data *q_data;
- struct vb2_queue *vq;
-
- vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
- if (!vq)
- return -EINVAL;
-
- q_data = get_q_data(ctx, f->type);
- if (!q_data)
- return -EINVAL;
-
- if (vb2_is_busy(vq)) {
- v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
- return -EBUSY;
- }
-
- q_data->fmt = find_format(f->fmt.pix.pixelformat);
- q_data->width = f->fmt.pix.width;
- q_data->height = f->fmt.pix.height;
- q_data->sizeimage = q_data->width * q_data->height
- * q_data->fmt->depth >> 3;
-
- dprintk(ctx->dev, 1,
- "Format for type %s: %dx%d (%d bpp), fmt: %c%c%c%c\n",
- type_name(f->type), q_data->width, q_data->height,
- q_data->fmt->depth,
- (q_data->fmt->fourcc & 0xff),
- (q_data->fmt->fourcc >> 8) & 0xff,
- (q_data->fmt->fourcc >> 16) & 0xff,
- (q_data->fmt->fourcc >> 24) & 0xff);
-
- return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- int ret;
-
- ret = vidioc_try_fmt_vid_cap(file, priv, f);
- if (ret)
- return ret;
-
- return vidioc_s_fmt(file2ctx(file), f);
-}
-
-static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vim2m_ctx *ctx = file2ctx(file);
- int ret;
-
- ret = vidioc_try_fmt_vid_out(file, priv, f);
- if (ret)
- return ret;
-
- ret = vidioc_s_fmt(file2ctx(file), f);
- if (!ret) {
- ctx->colorspace = f->fmt.pix.colorspace;
- ctx->xfer_func = f->fmt.pix.xfer_func;
- ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
- ctx->quant = f->fmt.pix.quantization;
- }
- return ret;
-}
-
-static int vim2m_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vim2m_ctx *ctx =
- container_of(ctrl->handler, struct vim2m_ctx, hdl);
-
- switch (ctrl->id) {
- case V4L2_CID_HFLIP:
- if (ctrl->val)
- ctx->mode |= MEM2MEM_HFLIP;
- else
- ctx->mode &= ~MEM2MEM_HFLIP;
- break;
-
- case V4L2_CID_VFLIP:
- if (ctrl->val)
- ctx->mode |= MEM2MEM_VFLIP;
- else
- ctx->mode &= ~MEM2MEM_VFLIP;
- break;
-
- case V4L2_CID_TRANS_TIME_MSEC:
- ctx->transtime = ctrl->val;
- if (ctx->transtime < 1)
- ctx->transtime = 1;
- break;
-
- case V4L2_CID_TRANS_NUM_BUFS:
- ctx->translen = ctrl->val;
- break;
-
- default:
- v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vim2m_ctrl_ops = {
- .s_ctrl = vim2m_s_ctrl,
-};
-
-static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
-
- .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
- .vidioc_enum_framesizes = vidioc_enum_framesizes,
- .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_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
- .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
- .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
- .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
-
- .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
- .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
- .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
- .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
- .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
- .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
- .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
-
- .vidioc_streamon = v4l2_m2m_ioctl_streamon,
- .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
-
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-/*
- * Queue operations
- */
-
-static int vim2m_queue_setup(struct vb2_queue *vq,
- unsigned int *nbuffers,
- unsigned int *nplanes,
- unsigned int sizes[],
- struct device *alloc_devs[])
-{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(vq);
- struct vim2m_q_data *q_data;
- unsigned int size, count = *nbuffers;
-
- q_data = get_q_data(ctx, vq->type);
- if (!q_data)
- return -EINVAL;
-
- size = q_data->width * q_data->height * q_data->fmt->depth >> 3;
-
- while (size * count > MEM2MEM_VID_MEM_LIMIT)
- (count)--;
- *nbuffers = count;
-
- if (*nplanes)
- return sizes[0] < size ? -EINVAL : 0;
-
- *nplanes = 1;
- sizes[0] = size;
-
- dprintk(ctx->dev, 1, "%s: get %d buffer(s) of size %d each.\n",
- type_name(vq->type), count, size);
-
- return 0;
-}
-
-static int vim2m_buf_out_validate(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-
- if (vbuf->field == V4L2_FIELD_ANY)
- vbuf->field = V4L2_FIELD_NONE;
- if (vbuf->field != V4L2_FIELD_NONE) {
- dprintk(ctx->dev, 1, "%s field isn't supported\n", __func__);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vim2m_buf_prepare(struct vb2_buffer *vb)
-{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- struct vim2m_q_data *q_data;
-
- dprintk(ctx->dev, 2, "type: %s\n", type_name(vb->vb2_queue->type));
-
- q_data = get_q_data(ctx, vb->vb2_queue->type);
- if (!q_data)
- return -EINVAL;
- if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
- dprintk(ctx->dev, 1,
- "%s data will not fit into plane (%lu < %lu)\n",
- __func__, vb2_plane_size(vb, 0),
- (long)q_data->sizeimage);
- return -EINVAL;
- }
-
- vb2_set_plane_payload(vb, 0, q_data->sizeimage);
-
- return 0;
-}
-
-static void vim2m_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-}
-
-static int vim2m_start_streaming(struct vb2_queue *q, unsigned int count)
-{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
- struct vim2m_q_data *q_data = get_q_data(ctx, q->type);
-
- if (!q_data)
- return -EINVAL;
-
- if (V4L2_TYPE_IS_OUTPUT(q->type))
- ctx->aborting = 0;
-
- q_data->sequence = 0;
- return 0;
-}
-
-static void vim2m_stop_streaming(struct vb2_queue *q)
-{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
- struct vb2_v4l2_buffer *vbuf;
- unsigned long flags;
-
- cancel_delayed_work_sync(&ctx->work_run);
-
- for (;;) {
- if (V4L2_TYPE_IS_OUTPUT(q->type))
- vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- else
- vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- if (!vbuf)
- return;
- v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
- &ctx->hdl);
- spin_lock_irqsave(&ctx->irqlock, flags);
- v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
- spin_unlock_irqrestore(&ctx->irqlock, flags);
- }
-}
-
-static void vim2m_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
-}
-
-static const struct vb2_ops vim2m_qops = {
- .queue_setup = vim2m_queue_setup,
- .buf_out_validate = vim2m_buf_out_validate,
- .buf_prepare = vim2m_buf_prepare,
- .buf_queue = vim2m_buf_queue,
- .start_streaming = vim2m_start_streaming,
- .stop_streaming = vim2m_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
- .buf_request_complete = vim2m_buf_request_complete,
-};
-
-static int queue_init(void *priv, struct vb2_queue *src_vq,
- struct vb2_queue *dst_vq)
-{
- struct vim2m_ctx *ctx = priv;
- int ret;
-
- src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
- src_vq->drv_priv = ctx;
- src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
- src_vq->ops = &vim2m_qops;
- src_vq->mem_ops = &vb2_vmalloc_memops;
- src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- src_vq->lock = &ctx->vb_mutex;
- src_vq->supports_requests = true;
-
- ret = vb2_queue_init(src_vq);
- if (ret)
- return ret;
-
- dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
- dst_vq->drv_priv = ctx;
- dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
- dst_vq->ops = &vim2m_qops;
- dst_vq->mem_ops = &vb2_vmalloc_memops;
- dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
- dst_vq->lock = &ctx->vb_mutex;
-
- return vb2_queue_init(dst_vq);
-}
-
-static struct v4l2_ctrl_config vim2m_ctrl_trans_time_msec = {
- .ops = &vim2m_ctrl_ops,
- .id = V4L2_CID_TRANS_TIME_MSEC,
- .name = "Transaction Time (msec)",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 1,
- .max = 10001,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vim2m_ctrl_trans_num_bufs = {
- .ops = &vim2m_ctrl_ops,
- .id = V4L2_CID_TRANS_NUM_BUFS,
- .name = "Buffers Per Transaction",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .def = 1,
- .min = 1,
- .max = MEM2MEM_DEF_NUM_BUFS,
- .step = 1,
-};
-
-/*
- * File operations
- */
-static int vim2m_open(struct file *file)
-{
- struct vim2m_dev *dev = video_drvdata(file);
- struct vim2m_ctx *ctx = NULL;
- struct v4l2_ctrl_handler *hdl;
- int rc = 0;
-
- if (mutex_lock_interruptible(&dev->dev_mutex))
- return -ERESTARTSYS;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (!ctx) {
- rc = -ENOMEM;
- goto open_unlock;
- }
-
- v4l2_fh_init(&ctx->fh, video_devdata(file));
- file->private_data = &ctx->fh;
- ctx->dev = dev;
- hdl = &ctx->hdl;
- v4l2_ctrl_handler_init(hdl, 4);
- v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
-
- vim2m_ctrl_trans_time_msec.def = default_transtime;
- v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_time_msec, NULL);
- v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_num_bufs, NULL);
- if (hdl->error) {
- rc = hdl->error;
- v4l2_ctrl_handler_free(hdl);
- kfree(ctx);
- goto open_unlock;
- }
- ctx->fh.ctrl_handler = hdl;
- v4l2_ctrl_handler_setup(hdl);
-
- ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
- ctx->q_data[V4L2_M2M_SRC].width = 640;
- ctx->q_data[V4L2_M2M_SRC].height = 480;
- ctx->q_data[V4L2_M2M_SRC].sizeimage =
- ctx->q_data[V4L2_M2M_SRC].width *
- ctx->q_data[V4L2_M2M_SRC].height *
- (ctx->q_data[V4L2_M2M_SRC].fmt->depth >> 3);
- ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
- ctx->colorspace = V4L2_COLORSPACE_REC709;
-
- ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
-
- mutex_init(&ctx->vb_mutex);
- spin_lock_init(&ctx->irqlock);
- INIT_DELAYED_WORK(&ctx->work_run, device_work);
-
- if (IS_ERR(ctx->fh.m2m_ctx)) {
- rc = PTR_ERR(ctx->fh.m2m_ctx);
-
- v4l2_ctrl_handler_free(hdl);
- v4l2_fh_exit(&ctx->fh);
- kfree(ctx);
- goto open_unlock;
- }
-
- v4l2_fh_add(&ctx->fh);
- atomic_inc(&dev->num_inst);
-
- dprintk(dev, 1, "Created instance: %p, m2m_ctx: %p\n",
- ctx, ctx->fh.m2m_ctx);
-
-open_unlock:
- mutex_unlock(&dev->dev_mutex);
- return rc;
-}
-
-static int vim2m_release(struct file *file)
-{
- struct vim2m_dev *dev = video_drvdata(file);
- struct vim2m_ctx *ctx = file2ctx(file);
-
- dprintk(dev, 1, "Releasing instance %p\n", ctx);
-
- v4l2_fh_del(&ctx->fh);
- v4l2_fh_exit(&ctx->fh);
- v4l2_ctrl_handler_free(&ctx->hdl);
- mutex_lock(&dev->dev_mutex);
- v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
- mutex_unlock(&dev->dev_mutex);
- kfree(ctx);
-
- atomic_dec(&dev->num_inst);
-
- return 0;
-}
-
-static void vim2m_device_release(struct video_device *vdev)
-{
- struct vim2m_dev *dev = container_of(vdev, struct vim2m_dev, vfd);
-
- v4l2_device_unregister(&dev->v4l2_dev);
- v4l2_m2m_release(dev->m2m_dev);
-#ifdef CONFIG_MEDIA_CONTROLLER
- media_device_cleanup(&dev->mdev);
-#endif
- kfree(dev);
-}
-
-static const struct v4l2_file_operations vim2m_fops = {
- .owner = THIS_MODULE,
- .open = vim2m_open,
- .release = vim2m_release,
- .poll = v4l2_m2m_fop_poll,
- .unlocked_ioctl = video_ioctl2,
- .mmap = v4l2_m2m_fop_mmap,
-};
-
-static const struct video_device vim2m_videodev = {
- .name = MEM2MEM_NAME,
- .vfl_dir = VFL_DIR_M2M,
- .fops = &vim2m_fops,
- .ioctl_ops = &vim2m_ioctl_ops,
- .minor = -1,
- .release = vim2m_device_release,
- .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
-};
-
-static const struct v4l2_m2m_ops m2m_ops = {
- .device_run = device_run,
- .job_ready = job_ready,
- .job_abort = job_abort,
-};
-
-static const struct media_device_ops m2m_media_ops = {
- .req_validate = vb2_request_validate,
- .req_queue = v4l2_m2m_request_queue,
-};
-
-static int vim2m_probe(struct platform_device *pdev)
-{
- struct vim2m_dev *dev;
- struct video_device *vfd;
- int ret;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
-
- ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
- if (ret)
- goto error_free;
-
- atomic_set(&dev->num_inst, 0);
- mutex_init(&dev->dev_mutex);
-
- dev->vfd = vim2m_videodev;
- vfd = &dev->vfd;
- vfd->lock = &dev->dev_mutex;
- vfd->v4l2_dev = &dev->v4l2_dev;
-
- ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
- if (ret) {
- v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
- goto error_v4l2;
- }
-
- video_set_drvdata(vfd, dev);
- v4l2_info(&dev->v4l2_dev,
- "Device registered as /dev/video%d\n", vfd->num);
-
- platform_set_drvdata(pdev, dev);
-
- dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
- if (IS_ERR(dev->m2m_dev)) {
- v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
- ret = PTR_ERR(dev->m2m_dev);
- dev->m2m_dev = NULL;
- goto error_dev;
- }
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->mdev.dev = &pdev->dev;
- strscpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
- strscpy(dev->mdev.bus_info, "platform:vim2m",
- sizeof(dev->mdev.bus_info));
- media_device_init(&dev->mdev);
- dev->mdev.ops = &m2m_media_ops;
- dev->v4l2_dev.mdev = &dev->mdev;
-
- ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
- MEDIA_ENT_F_PROC_VIDEO_SCALER);
- if (ret) {
- v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
- goto error_dev;
- }
-
- ret = media_device_register(&dev->mdev);
- if (ret) {
- v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
- goto error_m2m_mc;
- }
-#endif
- return 0;
-
-#ifdef CONFIG_MEDIA_CONTROLLER
-error_m2m_mc:
- v4l2_m2m_unregister_media_controller(dev->m2m_dev);
-#endif
-error_dev:
- video_unregister_device(&dev->vfd);
- /* vim2m_device_release called by video_unregister_device to release various objects */
- return ret;
-error_v4l2:
- v4l2_device_unregister(&dev->v4l2_dev);
-error_free:
- kfree(dev);
-
- return ret;
-}
-
-static int vim2m_remove(struct platform_device *pdev)
-{
- struct vim2m_dev *dev = platform_get_drvdata(pdev);
-
- v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- media_device_unregister(&dev->mdev);
- 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,
- .driver = {
- .name = MEM2MEM_NAME,
- },
-};
-
-static void __exit vim2m_exit(void)
-{
- platform_driver_unregister(&vim2m_pdrv);
- platform_device_unregister(&vim2m_pdev);
-}
-
-static int __init vim2m_init(void)
-{
- int ret;
-
- ret = platform_device_register(&vim2m_pdev);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&vim2m_pdrv);
- if (ret)
- platform_device_unregister(&vim2m_pdev);
-
- return ret;
-}
-
-module_init(vim2m_init);
-module_exit(vim2m_exit);
diff --git a/drivers/media/platform/vimc/Kconfig b/drivers/media/platform/vimc/Kconfig
deleted file mode 100644
index bd221d3e1a4a..000000000000
--- a/drivers/media/platform/vimc/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_VIMC
- tristate "Virtual Media Controller Driver (VIMC)"
- depends on VIDEO_DEV && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
- select VIDEOBUF2_VMALLOC
- select VIDEO_V4L2_TPG
- help
- Skeleton driver for Virtual Media Controller
-
- This driver can be compared to the vivid driver for emulating
- a media node that exposes a complex media topology. The topology
- is hard coded for now but is meant to be highly configurable in
- the future.
-
- When in doubt, say N.
diff --git a/drivers/media/platform/vimc/Makefile b/drivers/media/platform/vimc/Makefile
deleted file mode 100644
index a53b2b532e9f..000000000000
--- a/drivers/media/platform/vimc/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-vimc-y := vimc-core.o vimc-common.o vimc-streamer.o vimc-capture.o \
- vimc-debayer.o vimc-scaler.o vimc-sensor.o
-
-obj-$(CONFIG_VIDEO_VIMC) += vimc.o
-
diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c
deleted file mode 100644
index 23e740c1c5c0..000000000000
--- a/drivers/media/platform/vimc/vimc-capture.c
+++ /dev/null
@@ -1,480 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-capture.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
-#include <media/videobuf2-vmalloc.h>
-
-#include "vimc-common.h"
-#include "vimc-streamer.h"
-
-struct vimc_cap_device {
- struct vimc_ent_device ved;
- struct video_device vdev;
- struct v4l2_pix_format format;
- struct vb2_queue queue;
- struct list_head buf_list;
- /*
- * NOTE: in a real driver, a spin lock must be used to access the
- * queue because the frames are generated from a hardware interruption
- * and the isr is not allowed to sleep.
- * Even if it is not necessary a spinlock in the vimc driver, we
- * use it here as a code reference
- */
- spinlock_t qlock;
- struct mutex lock;
- u32 sequence;
- struct vimc_stream stream;
- struct media_pad pad;
-};
-
-static const struct v4l2_pix_format fmt_default = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_RGB24,
- .field = V4L2_FIELD_NONE,
- .colorspace = V4L2_COLORSPACE_DEFAULT,
-};
-
-struct vimc_cap_buffer {
- /*
- * struct vb2_v4l2_buffer must be the first element
- * the videobuf2 framework will allocate this struct based on
- * buf_struct_size and use the first sizeof(struct vb2_buffer) bytes of
- * memory as a vb2_buffer
- */
- struct vb2_v4l2_buffer vb2;
- struct list_head list;
-};
-
-static int vimc_cap_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- strscpy(cap->driver, VIMC_PDEV_NAME, sizeof(cap->driver));
- strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card));
- snprintf(cap->bus_info, sizeof(cap->bus_info),
- "platform:%s", VIMC_PDEV_NAME);
-
- return 0;
-}
-
-static void vimc_cap_get_format(struct vimc_ent_device *ved,
- struct v4l2_pix_format *fmt)
-{
- struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device,
- ved);
-
- *fmt = vcap->format;
-}
-
-static int vimc_cap_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vimc_cap_device *vcap = video_drvdata(file);
-
- f->fmt.pix = vcap->format;
-
- return 0;
-}
-
-static int vimc_cap_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct v4l2_pix_format *format = &f->fmt.pix;
- const struct vimc_pix_map *vpix;
-
- format->width = clamp_t(u32, format->width, VIMC_FRAME_MIN_WIDTH,
- VIMC_FRAME_MAX_WIDTH) & ~1;
- format->height = clamp_t(u32, format->height, VIMC_FRAME_MIN_HEIGHT,
- VIMC_FRAME_MAX_HEIGHT) & ~1;
-
- /* Don't accept a pixelformat that is not on the table */
- vpix = vimc_pix_map_by_pixelformat(format->pixelformat);
- if (!vpix) {
- format->pixelformat = fmt_default.pixelformat;
- vpix = vimc_pix_map_by_pixelformat(format->pixelformat);
- }
- /* TODO: Add support for custom bytesperline values */
- format->bytesperline = format->width * vpix->bpp;
- format->sizeimage = format->bytesperline * format->height;
-
- if (format->field == V4L2_FIELD_ANY)
- format->field = fmt_default.field;
-
- vimc_colorimetry_clamp(format);
-
- return 0;
-}
-
-static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vimc_cap_device *vcap = video_drvdata(file);
- int ret;
-
- /* Do not change the format while stream is on */
- if (vb2_is_busy(&vcap->queue))
- return -EBUSY;
-
- ret = vimc_cap_try_fmt_vid_cap(file, priv, f);
- if (ret)
- return ret;
-
- dev_dbg(vcap->ved.dev, "%s: format update: "
- "old:%dx%d (0x%x, %d, %d, %d, %d) "
- "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vcap->vdev.name,
- /* old */
- vcap->format.width, vcap->format.height,
- vcap->format.pixelformat, vcap->format.colorspace,
- vcap->format.quantization, vcap->format.xfer_func,
- vcap->format.ycbcr_enc,
- /* new */
- f->fmt.pix.width, f->fmt.pix.height,
- f->fmt.pix.pixelformat, f->fmt.pix.colorspace,
- f->fmt.pix.quantization, f->fmt.pix.xfer_func,
- f->fmt.pix.ycbcr_enc);
-
- vcap->format = f->fmt.pix;
-
- return 0;
-}
-
-static int vimc_cap_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- const struct vimc_pix_map *vpix = vimc_pix_map_by_index(f->index);
-
- if (!vpix)
- return -EINVAL;
-
- f->pixelformat = vpix->pixelformat;
-
- return 0;
-}
-
-static int vimc_cap_enum_framesizes(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
-{
- const struct vimc_pix_map *vpix;
-
- if (fsize->index)
- return -EINVAL;
-
- /* Only accept code in the pix map table */
- vpix = vimc_pix_map_by_code(fsize->pixel_format);
- if (!vpix)
- return -EINVAL;
-
- fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
- fsize->stepwise.min_width = VIMC_FRAME_MIN_WIDTH;
- fsize->stepwise.max_width = VIMC_FRAME_MAX_WIDTH;
- fsize->stepwise.min_height = VIMC_FRAME_MIN_HEIGHT;
- fsize->stepwise.max_height = VIMC_FRAME_MAX_HEIGHT;
- fsize->stepwise.step_width = 1;
- fsize->stepwise.step_height = 1;
-
- return 0;
-}
-
-static const struct v4l2_file_operations vimc_cap_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = vb2_fop_release,
- .read = vb2_fop_read,
- .poll = vb2_fop_poll,
- .unlocked_ioctl = video_ioctl2,
- .mmap = vb2_fop_mmap,
-};
-
-static const struct v4l2_ioctl_ops vimc_cap_ioctl_ops = {
- .vidioc_querycap = vimc_cap_querycap,
-
- .vidioc_g_fmt_vid_cap = vimc_cap_g_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = vimc_cap_s_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = vimc_cap_try_fmt_vid_cap,
- .vidioc_enum_fmt_vid_cap = vimc_cap_enum_fmt_vid_cap,
- .vidioc_enum_framesizes = vimc_cap_enum_framesizes,
-
- .vidioc_reqbufs = vb2_ioctl_reqbufs,
- .vidioc_create_bufs = vb2_ioctl_create_bufs,
- .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
- .vidioc_querybuf = vb2_ioctl_querybuf,
- .vidioc_qbuf = vb2_ioctl_qbuf,
- .vidioc_dqbuf = vb2_ioctl_dqbuf,
- .vidioc_expbuf = vb2_ioctl_expbuf,
- .vidioc_streamon = vb2_ioctl_streamon,
- .vidioc_streamoff = vb2_ioctl_streamoff,
-};
-
-static void vimc_cap_return_all_buffers(struct vimc_cap_device *vcap,
- enum vb2_buffer_state state)
-{
- struct vimc_cap_buffer *vbuf, *node;
-
- spin_lock(&vcap->qlock);
-
- list_for_each_entry_safe(vbuf, node, &vcap->buf_list, list) {
- list_del(&vbuf->list);
- vb2_buffer_done(&vbuf->vb2.vb2_buf, state);
- }
-
- spin_unlock(&vcap->qlock);
-}
-
-static int vimc_cap_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
- struct media_entity *entity = &vcap->vdev.entity;
- int ret;
-
- vcap->sequence = 0;
-
- /* Start the media pipeline */
- ret = media_pipeline_start(entity, &vcap->stream.pipe);
- if (ret) {
- vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED);
- return ret;
- }
-
- ret = vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 1);
- if (ret) {
- media_pipeline_stop(entity);
- vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED);
- return ret;
- }
-
- return 0;
-}
-
-/*
- * Stop the stream engine. Any remaining buffers in the stream queue are
- * dequeued and passed on to the vb2 framework marked as STATE_ERROR.
- */
-static void vimc_cap_stop_streaming(struct vb2_queue *vq)
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
-
- vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 0);
-
- /* Stop the media pipeline */
- media_pipeline_stop(&vcap->vdev.entity);
-
- /* Release all active buffers */
- vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_ERROR);
-}
-
-static void vimc_cap_buf_queue(struct vb2_buffer *vb2_buf)
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vb2_buf->vb2_queue);
- struct vimc_cap_buffer *buf = container_of(vb2_buf,
- struct vimc_cap_buffer,
- vb2.vb2_buf);
-
- spin_lock(&vcap->qlock);
- list_add_tail(&buf->list, &vcap->buf_list);
- spin_unlock(&vcap->qlock);
-}
-
-static int vimc_cap_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned int sizes[],
- struct device *alloc_devs[])
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
-
- if (*nplanes)
- return sizes[0] < vcap->format.sizeimage ? -EINVAL : 0;
- /* We don't support multiplanes for now */
- *nplanes = 1;
- sizes[0] = vcap->format.sizeimage;
-
- return 0;
-}
-
-static int vimc_cap_buffer_prepare(struct vb2_buffer *vb)
-{
- struct vimc_cap_device *vcap = vb2_get_drv_priv(vb->vb2_queue);
- unsigned long size = vcap->format.sizeimage;
-
- if (vb2_plane_size(vb, 0) < size) {
- dev_err(vcap->ved.dev, "%s: buffer too small (%lu < %lu)\n",
- vcap->vdev.name, vb2_plane_size(vb, 0), size);
- return -EINVAL;
- }
- return 0;
-}
-
-static const struct vb2_ops vimc_cap_qops = {
- .start_streaming = vimc_cap_start_streaming,
- .stop_streaming = vimc_cap_stop_streaming,
- .buf_queue = vimc_cap_buf_queue,
- .queue_setup = vimc_cap_queue_setup,
- .buf_prepare = vimc_cap_buffer_prepare,
- /*
- * Since q->lock is set we can use the standard
- * vb2_ops_wait_prepare/finish helper functions.
- */
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-static const struct media_entity_operations vimc_cap_mops = {
- .link_validate = vimc_vdev_link_validate,
-};
-
-void vimc_cap_release(struct vimc_ent_device *ved)
-{
- struct vimc_cap_device *vcap =
- container_of(ved, struct vimc_cap_device, ved);
-
- media_entity_cleanup(vcap->ved.ent);
- kfree(vcap);
-}
-
-void vimc_cap_unregister(struct vimc_ent_device *ved)
-{
- struct vimc_cap_device *vcap =
- container_of(ved, struct vimc_cap_device, ved);
-
- vb2_queue_release(&vcap->queue);
- video_unregister_device(&vcap->vdev);
-}
-
-static void *vimc_cap_process_frame(struct vimc_ent_device *ved,
- const void *frame)
-{
- struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device,
- ved);
- struct vimc_cap_buffer *vimc_buf;
- void *vbuf;
-
- spin_lock(&vcap->qlock);
-
- /* Get the first entry of the list */
- vimc_buf = list_first_entry_or_null(&vcap->buf_list,
- typeof(*vimc_buf), list);
- if (!vimc_buf) {
- spin_unlock(&vcap->qlock);
- return ERR_PTR(-EAGAIN);
- }
-
- /* Remove this entry from the list */
- list_del(&vimc_buf->list);
-
- spin_unlock(&vcap->qlock);
-
- /* Fill the buffer */
- vimc_buf->vb2.vb2_buf.timestamp = ktime_get_ns();
- vimc_buf->vb2.sequence = vcap->sequence++;
- vimc_buf->vb2.field = vcap->format.field;
-
- vbuf = vb2_plane_vaddr(&vimc_buf->vb2.vb2_buf, 0);
-
- memcpy(vbuf, frame, vcap->format.sizeimage);
-
- /* Set it as ready */
- vb2_set_plane_payload(&vimc_buf->vb2.vb2_buf, 0,
- vcap->format.sizeimage);
- vb2_buffer_done(&vimc_buf->vb2.vb2_buf, VB2_BUF_STATE_DONE);
- return NULL;
-}
-
-struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc,
- const char *vcfg_name)
-{
- struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
- const struct vimc_pix_map *vpix;
- struct vimc_cap_device *vcap;
- struct video_device *vdev;
- struct vb2_queue *q;
- int ret;
-
- /* Allocate the vimc_cap_device struct */
- vcap = kzalloc(sizeof(*vcap), GFP_KERNEL);
- if (!vcap)
- return NULL;
-
- /* Initialize the media entity */
- vcap->vdev.entity.name = vcfg_name;
- vcap->vdev.entity.function = MEDIA_ENT_F_IO_V4L;
- vcap->pad.flags = MEDIA_PAD_FL_SINK;
- ret = media_entity_pads_init(&vcap->vdev.entity,
- 1, &vcap->pad);
- if (ret)
- goto err_free_vcap;
-
- /* Initialize the lock */
- mutex_init(&vcap->lock);
-
- /* Initialize the vb2 queue */
- q = &vcap->queue;
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_USERPTR;
- q->drv_priv = vcap;
- q->buf_struct_size = sizeof(struct vimc_cap_buffer);
- q->ops = &vimc_cap_qops;
- q->mem_ops = &vb2_vmalloc_memops;
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->min_buffers_needed = 2;
- q->lock = &vcap->lock;
-
- ret = vb2_queue_init(q);
- if (ret) {
- dev_err(vimc->mdev.dev, "%s: vb2 queue init failed (err=%d)\n",
- vcfg_name, ret);
- goto err_clean_m_ent;
- }
-
- /* Initialize buffer list and its lock */
- INIT_LIST_HEAD(&vcap->buf_list);
- spin_lock_init(&vcap->qlock);
-
- /* Set default frame format */
- vcap->format = fmt_default;
- vpix = vimc_pix_map_by_pixelformat(vcap->format.pixelformat);
- vcap->format.bytesperline = vcap->format.width * vpix->bpp;
- vcap->format.sizeimage = vcap->format.bytesperline *
- vcap->format.height;
-
- /* Fill the vimc_ent_device struct */
- vcap->ved.ent = &vcap->vdev.entity;
- vcap->ved.process_frame = vimc_cap_process_frame;
- vcap->ved.vdev_get_format = vimc_cap_get_format;
- vcap->ved.dev = vimc->mdev.dev;
-
- /* Initialize the video_device struct */
- vdev = &vcap->vdev;
- vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- vdev->entity.ops = &vimc_cap_mops;
- vdev->release = video_device_release_empty;
- vdev->fops = &vimc_cap_fops;
- vdev->ioctl_ops = &vimc_cap_ioctl_ops;
- vdev->lock = &vcap->lock;
- vdev->queue = q;
- vdev->v4l2_dev = v4l2_dev;
- vdev->vfl_dir = VFL_DIR_RX;
- strscpy(vdev->name, vcfg_name, sizeof(vdev->name));
- video_set_drvdata(vdev, &vcap->ved);
-
- /* Register the video_device with the v4l2 and the media framework */
- ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
- if (ret) {
- dev_err(vimc->mdev.dev, "%s: video register failed (err=%d)\n",
- vcap->vdev.name, ret);
- goto err_release_queue;
- }
-
- return &vcap->ved;
-
-err_release_queue:
- vb2_queue_release(q);
-err_clean_m_ent:
- media_entity_cleanup(&vcap->vdev.entity);
-err_free_vcap:
- kfree(vcap);
-
- return NULL;
-}
diff --git a/drivers/media/platform/vimc/vimc-common.c b/drivers/media/platform/vimc/vimc-common.c
deleted file mode 100644
index c95c17c048f2..000000000000
--- a/drivers/media/platform/vimc/vimc-common.c
+++ /dev/null
@@ -1,369 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-common.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include "vimc-common.h"
-
-/*
- * NOTE: non-bayer formats need to come first (necessary for enum_mbus_code
- * in the scaler)
- */
-static const struct vimc_pix_map vimc_pix_map_list[] = {
- /* TODO: add all missing formats */
-
- /* RGB formats */
- {
- .code = MEDIA_BUS_FMT_BGR888_1X24,
- .pixelformat = V4L2_PIX_FMT_BGR24,
- .bpp = 3,
- .bayer = false,
- },
- {
- .code = MEDIA_BUS_FMT_RGB888_1X24,
- .pixelformat = V4L2_PIX_FMT_RGB24,
- .bpp = 3,
- .bayer = false,
- },
- {
- .code = MEDIA_BUS_FMT_ARGB8888_1X32,
- .pixelformat = V4L2_PIX_FMT_ARGB32,
- .bpp = 4,
- .bayer = false,
- },
-
- /* Bayer formats */
- {
- .code = MEDIA_BUS_FMT_SBGGR8_1X8,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGBRG8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGRBG8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB8_1X8,
- .pixelformat = V4L2_PIX_FMT_SRGGB8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SBGGR10_1X10,
- .pixelformat = V4L2_PIX_FMT_SBGGR10,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG10_1X10,
- .pixelformat = V4L2_PIX_FMT_SGBRG10,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
- .pixelformat = V4L2_PIX_FMT_SGRBG10,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB10_1X10,
- .pixelformat = V4L2_PIX_FMT_SRGGB10,
- .bpp = 2,
- .bayer = true,
- },
-
- /* 10bit raw bayer a-law compressed to 8 bits */
- {
- .code = MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8,
- .pixelformat = V4L2_PIX_FMT_SBGGR10ALAW8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGBRG10ALAW8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGRBG10ALAW8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8,
- .pixelformat = V4L2_PIX_FMT_SRGGB10ALAW8,
- .bpp = 1,
- .bayer = true,
- },
-
- /* 10bit raw bayer DPCM compressed to 8 bits */
- {
- .code = MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8,
- .pixelformat = V4L2_PIX_FMT_SBGGR10DPCM8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGBRG10DPCM8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
- .pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8,
- .pixelformat = V4L2_PIX_FMT_SRGGB10DPCM8,
- .bpp = 1,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SBGGR12_1X12,
- .pixelformat = V4L2_PIX_FMT_SBGGR12,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG12_1X12,
- .pixelformat = V4L2_PIX_FMT_SGBRG12,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG12_1X12,
- .pixelformat = V4L2_PIX_FMT_SGRBG12,
- .bpp = 2,
- .bayer = true,
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB12_1X12,
- .pixelformat = V4L2_PIX_FMT_SRGGB12,
- .bpp = 2,
- .bayer = true,
- },
-};
-
-bool vimc_is_source(struct media_entity *ent)
-{
- unsigned int i;
-
- for (i = 0; i < ent->num_pads; i++)
- if (ent->pads[i].flags & MEDIA_PAD_FL_SINK)
- return false;
- return true;
-}
-
-const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i)
-{
- if (i >= ARRAY_SIZE(vimc_pix_map_list))
- return NULL;
-
- return &vimc_pix_map_list[i];
-}
-
-const struct vimc_pix_map *vimc_pix_map_by_code(u32 code)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) {
- if (vimc_pix_map_list[i].code == code)
- return &vimc_pix_map_list[i];
- }
- return NULL;
-}
-
-const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) {
- if (vimc_pix_map_list[i].pixelformat == pixelformat)
- return &vimc_pix_map_list[i];
- }
- return NULL;
-}
-
-static int vimc_get_pix_format(struct media_pad *pad,
- struct v4l2_pix_format *fmt)
-{
- 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;
- 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;
-
- v4l2_fill_pix_format(fmt, &sd_fmt.format);
- pix_map = vimc_pix_map_by_code(sd_fmt.format.code);
- fmt->pixelformat = pix_map->pixelformat;
- } else if (is_media_entity_v4l2_video_device(pad->entity)) {
- struct video_device *vdev = container_of(pad->entity,
- struct video_device,
- entity);
- struct vimc_ent_device *ved = video_get_drvdata(vdev);
-
- if (!ved->vdev_get_format)
- return -ENOIOCTLCMD;
-
- ved->vdev_get_format(ved, fmt);
- } else {
- return -EINVAL;
- }
-
- return 0;
-}
-
-int vimc_vdev_link_validate(struct media_link *link)
-{
- struct v4l2_pix_format source_fmt, sink_fmt;
- int ret;
-
- ret = vimc_get_pix_format(link->source, &source_fmt);
- if (ret)
- return ret;
-
- ret = vimc_get_pix_format(link->sink, &sink_fmt);
- if (ret)
- return ret;
-
- pr_info("vimc link validate: "
- "%s:src:%dx%d (0x%x, %d, %d, %d, %d) "
- "%s:snk:%dx%d (0x%x, %d, %d, %d, %d)\n",
- /* src */
- link->source->entity->name,
- source_fmt.width, source_fmt.height,
- source_fmt.pixelformat, source_fmt.colorspace,
- source_fmt.quantization, source_fmt.xfer_func,
- source_fmt.ycbcr_enc,
- /* sink */
- link->sink->entity->name,
- sink_fmt.width, sink_fmt.height,
- sink_fmt.pixelformat, sink_fmt.colorspace,
- sink_fmt.quantization, sink_fmt.xfer_func,
- sink_fmt.ycbcr_enc);
-
- /* The width, height and pixelformat must match. */
- if (source_fmt.width != sink_fmt.width ||
- source_fmt.height != sink_fmt.height ||
- source_fmt.pixelformat != sink_fmt.pixelformat)
- return -EPIPE;
-
- /*
- * The field order must match, or the sink field order must be NONE
- * to support interlaced hardware connected to bridges that support
- * progressive formats only.
- */
- if (source_fmt.field != sink_fmt.field &&
- sink_fmt.field != V4L2_FIELD_NONE)
- return -EPIPE;
-
- /*
- * If colorspace is DEFAULT, then assume all the colorimetry is also
- * DEFAULT, return 0 to skip comparing the other colorimetry parameters
- */
- if (source_fmt.colorspace == V4L2_COLORSPACE_DEFAULT ||
- sink_fmt.colorspace == V4L2_COLORSPACE_DEFAULT)
- return 0;
-
- /* Colorspace must match. */
- if (source_fmt.colorspace != sink_fmt.colorspace)
- return -EPIPE;
-
- /* Colorimetry must match if they are not set to DEFAULT */
- if (source_fmt.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT &&
- sink_fmt.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT &&
- source_fmt.ycbcr_enc != sink_fmt.ycbcr_enc)
- return -EPIPE;
-
- if (source_fmt.quantization != V4L2_QUANTIZATION_DEFAULT &&
- sink_fmt.quantization != V4L2_QUANTIZATION_DEFAULT &&
- source_fmt.quantization != sink_fmt.quantization)
- return -EPIPE;
-
- if (source_fmt.xfer_func != V4L2_XFER_FUNC_DEFAULT &&
- sink_fmt.xfer_func != V4L2_XFER_FUNC_DEFAULT &&
- source_fmt.xfer_func != sink_fmt.xfer_func)
- return -EPIPE;
-
- return 0;
-}
-
-static const struct media_entity_operations vimc_ent_sd_mops = {
- .link_validate = v4l2_subdev_link_validate,
-};
-
-int vimc_ent_sd_register(struct vimc_ent_device *ved,
- struct v4l2_subdev *sd,
- struct v4l2_device *v4l2_dev,
- const char *const name,
- u32 function,
- u16 num_pads,
- struct media_pad *pads,
- const struct v4l2_subdev_ops *sd_ops)
-{
- int ret;
-
- /* Fill the vimc_ent_device struct */
- ved->ent = &sd->entity;
-
- /* Initialize the subdev */
- v4l2_subdev_init(sd, sd_ops);
- sd->entity.function = function;
- sd->entity.ops = &vimc_ent_sd_mops;
- sd->owner = THIS_MODULE;
- strscpy(sd->name, name, sizeof(sd->name));
- v4l2_set_subdevdata(sd, ved);
-
- /* Expose this subdev to user space */
- sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- if (sd->ctrl_handler)
- sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
-
- /* Initialize the media entity */
- ret = media_entity_pads_init(&sd->entity, num_pads, pads);
- if (ret)
- return ret;
-
- /* Register the subdev with the v4l2 and the media framework */
- ret = v4l2_device_register_subdev(v4l2_dev, sd);
- if (ret) {
- dev_err(v4l2_dev->dev,
- "%s: subdev register failed (err=%d)\n",
- name, ret);
- goto err_clean_m_ent;
- }
-
- return 0;
-
-err_clean_m_ent:
- media_entity_cleanup(&sd->entity);
- return ret;
-}
diff --git a/drivers/media/platform/vimc/vimc-common.h b/drivers/media/platform/vimc/vimc-common.h
deleted file mode 100644
index 616d5a6b0754..000000000000
--- a/drivers/media/platform/vimc/vimc-common.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * vimc-common.h Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#ifndef _VIMC_COMMON_H_
-#define _VIMC_COMMON_H_
-
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <media/media-device.h>
-#include <media/v4l2-device.h>
-
-#define VIMC_PDEV_NAME "vimc"
-
-/* VIMC-specific controls */
-#define VIMC_CID_VIMC_BASE (0x00f00000 | 0xf000)
-#define VIMC_CID_VIMC_CLASS (0x00f00000 | 1)
-#define VIMC_CID_TEST_PATTERN (VIMC_CID_VIMC_BASE + 0)
-#define VIMC_CID_MEAN_WIN_SIZE (VIMC_CID_VIMC_BASE + 1)
-
-#define VIMC_FRAME_MAX_WIDTH 4096
-#define VIMC_FRAME_MAX_HEIGHT 2160
-#define VIMC_FRAME_MIN_WIDTH 16
-#define VIMC_FRAME_MIN_HEIGHT 16
-
-#define VIMC_FRAME_INDEX(lin, col, width, bpp) ((lin * width + col) * bpp)
-
-/* Source and sink pad checks */
-#define VIMC_IS_SRC(pad) (pad)
-#define VIMC_IS_SINK(pad) (!(pad))
-
-/**
- * struct vimc_colorimetry_clamp - Adjust colorimetry parameters
- *
- * @fmt: the pointer to struct v4l2_pix_format or
- * struct v4l2_mbus_framefmt
- *
- * Entities must check if colorimetry given by the userspace is valid, if not
- * then set them as DEFAULT
- */
-#define vimc_colorimetry_clamp(fmt) \
-do { \
- if ((fmt)->colorspace == V4L2_COLORSPACE_DEFAULT \
- || (fmt)->colorspace > V4L2_COLORSPACE_DCI_P3) { \
- (fmt)->colorspace = V4L2_COLORSPACE_DEFAULT; \
- (fmt)->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; \
- (fmt)->quantization = V4L2_QUANTIZATION_DEFAULT; \
- (fmt)->xfer_func = V4L2_XFER_FUNC_DEFAULT; \
- } \
- if ((fmt)->ycbcr_enc > V4L2_YCBCR_ENC_SMPTE240M) \
- (fmt)->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; \
- if ((fmt)->quantization > V4L2_QUANTIZATION_LIM_RANGE) \
- (fmt)->quantization = V4L2_QUANTIZATION_DEFAULT; \
- if ((fmt)->xfer_func > V4L2_XFER_FUNC_SMPTE2084) \
- (fmt)->xfer_func = V4L2_XFER_FUNC_DEFAULT; \
-} while (0)
-
-/**
- * struct vimc_pix_map - maps media bus code with v4l2 pixel format
- *
- * @code: media bus format code defined by MEDIA_BUS_FMT_* macros
- * @bbp: number of bytes each pixel occupies
- * @pixelformat: pixel format devined by V4L2_PIX_FMT_* macros
- *
- * Struct which matches the MEDIA_BUS_FMT_* codes with the corresponding
- * V4L2_PIX_FMT_* fourcc pixelformat and its bytes per pixel (bpp)
- */
-struct vimc_pix_map {
- unsigned int code;
- unsigned int bpp;
- u32 pixelformat;
- bool bayer;
-};
-
-/**
- * struct vimc_ent_device - core struct that represents an entity in the
- * topology
- *
- * @dev: a pointer of the device struct of the driver
- * @ent: the pointer to struct media_entity for the node
- * @process_frame: callback send a frame to that node
- * @vdev_get_format: callback that returns the current format a pad, used
- * only when is_media_entity_v4l2_video_device(ent) returns
- * true
- *
- * Each node of the topology must create a vimc_ent_device struct. Depending on
- * the node it will be of an instance of v4l2_subdev or video_device struct
- * where both contains a struct media_entity.
- * Those structures should embedded the vimc_ent_device struct through
- * v4l2_set_subdevdata() and video_set_drvdata() respectivaly, allowing the
- * vimc_ent_device struct to be retrieved from the corresponding struct
- * media_entity
- */
-struct vimc_ent_device {
- struct device *dev;
- struct media_entity *ent;
- void * (*process_frame)(struct vimc_ent_device *ved,
- const void *frame);
- void (*vdev_get_format)(struct vimc_ent_device *ved,
- struct v4l2_pix_format *fmt);
-};
-
-/**
- * struct vimc_device - main device for vimc driver
- *
- * @pipe_cfg pointer to the vimc pipeline configuration structure
- * @ent_devs array of vimc_ent_device pointers
- * @mdev the associated media_device parent
- * @v4l2_dev Internal v4l2 parent device
- */
-struct vimc_device {
- const struct vimc_pipeline_config *pipe_cfg;
- struct vimc_ent_device **ent_devs;
- struct media_device mdev;
- struct v4l2_device v4l2_dev;
-};
-
-/**
- * struct vimc_ent_config Structure which describes individual
- * configuration for each entity
- *
- * @name entity name
- * @ved pointer to vimc_ent_device (a node in the
- * topology)
- * @add initializes and registers
- * vim entity - called from vimc-core
- * @unregister unregisters vimc entity - called from vimc-core
- * @release releases vimc entity - called from the v4l2_dev
- * release callback
- */
-struct vimc_ent_config {
- const char *name;
- struct vimc_ent_device *(*add)(struct vimc_device *vimc,
- const char *vcfg_name);
- void (*unregister)(struct vimc_ent_device *ved);
- void (*release)(struct vimc_ent_device *ved);
-};
-
-/**
- * vimc_is_source - returns true if the entity has only source pads
- *
- * @ent: pointer to &struct media_entity
- *
- */
-bool vimc_is_source(struct media_entity *ent);
-
-/* prototypes for vimc_ent_config hooks */
-struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc,
- const char *vcfg_name);
-void vimc_cap_unregister(struct vimc_ent_device *ved);
-void vimc_cap_release(struct vimc_ent_device *ved);
-
-struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc,
- const char *vcfg_name);
-void vimc_deb_release(struct vimc_ent_device *ved);
-
-struct vimc_ent_device *vimc_sca_add(struct vimc_device *vimc,
- const char *vcfg_name);
-void vimc_sca_release(struct vimc_ent_device *ved);
-
-struct vimc_ent_device *vimc_sen_add(struct vimc_device *vimc,
- const char *vcfg_name);
-void vimc_sen_release(struct vimc_ent_device *ved);
-
-/**
- * vimc_pix_map_by_index - get vimc_pix_map struct by its index
- *
- * @i: index of the vimc_pix_map struct in vimc_pix_map_list
- */
-const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i);
-
-/**
- * vimc_pix_map_by_code - get vimc_pix_map struct by media bus code
- *
- * @code: media bus format code defined by MEDIA_BUS_FMT_* macros
- */
-const struct vimc_pix_map *vimc_pix_map_by_code(u32 code);
-
-/**
- * vimc_pix_map_by_pixelformat - get vimc_pix_map struct by v4l2 pixel format
- *
- * @pixelformat: pixel format devined by V4L2_PIX_FMT_* macros
- */
-const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat);
-
-/**
- * vimc_ent_sd_register - initialize and register a subdev node
- *
- * @ved: the vimc_ent_device struct to be initialize
- * @sd: the v4l2_subdev struct to be initialize and registered
- * @v4l2_dev: the v4l2 device to register the v4l2_subdev
- * @name: name of the sub-device. Please notice that the name must be
- * unique.
- * @function: media entity function defined by MEDIA_ENT_F_* macros
- * @num_pads: number of pads to initialize
- * @pads: the array of pads of the entity, the caller should set the
- flags of the pads
- * @sd_ops: pointer to &struct v4l2_subdev_ops.
- *
- * Helper function initialize and register the struct vimc_ent_device and struct
- * v4l2_subdev which represents a subdev node in the topology
- */
-int vimc_ent_sd_register(struct vimc_ent_device *ved,
- struct v4l2_subdev *sd,
- struct v4l2_device *v4l2_dev,
- const char *const name,
- u32 function,
- u16 num_pads,
- struct media_pad *pads,
- const struct v4l2_subdev_ops *sd_ops);
-
-/**
- * vimc_vdev_link_validate - validates a media link
- *
- * @link: pointer to &struct media_link
- *
- * This function calls validates if a media link is valid for streaming.
- */
-int vimc_vdev_link_validate(struct media_link *link);
-
-#endif
diff --git a/drivers/media/platform/vimc/vimc-core.c b/drivers/media/platform/vimc/vimc-core.c
deleted file mode 100644
index 339126e565dc..000000000000
--- a/drivers/media/platform/vimc/vimc-core.c
+++ /dev/null
@@ -1,381 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-core.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <media/media-device.h>
-#include <media/v4l2-device.h>
-
-#include "vimc-common.h"
-
-#define VIMC_MDEV_MODEL_NAME "VIMC MDEV"
-
-#define VIMC_ENT_LINK(src, srcpad, sink, sinkpad, link_flags) { \
- .src_ent = src, \
- .src_pad = srcpad, \
- .sink_ent = sink, \
- .sink_pad = sinkpad, \
- .flags = link_flags, \
-}
-
-/* Structure which describes links between entities */
-struct vimc_ent_link {
- unsigned int src_ent;
- u16 src_pad;
- unsigned int sink_ent;
- u16 sink_pad;
- u32 flags;
-};
-
-/* Structure which describes the whole topology */
-struct vimc_pipeline_config {
- const struct vimc_ent_config *ents;
- size_t num_ents;
- const struct vimc_ent_link *links;
- size_t num_links;
-};
-
-/* --------------------------------------------------------------------------
- * Topology Configuration
- */
-
-static struct vimc_ent_config ent_config[] = {
- {
- .name = "Sensor A",
- .add = vimc_sen_add,
- .release = vimc_sen_release,
- },
- {
- .name = "Sensor B",
- .add = vimc_sen_add,
- .release = vimc_sen_release,
- },
- {
- .name = "Debayer A",
- .add = vimc_deb_add,
- .release = vimc_deb_release,
- },
- {
- .name = "Debayer B",
- .add = vimc_deb_add,
- .release = vimc_deb_release,
- },
- {
- .name = "Raw Capture 0",
- .add = vimc_cap_add,
- .unregister = vimc_cap_unregister,
- .release = vimc_cap_release,
- },
- {
- .name = "Raw Capture 1",
- .add = vimc_cap_add,
- .unregister = vimc_cap_unregister,
- .release = vimc_cap_release,
- },
- {
- /* TODO: change this to vimc-input when it is implemented */
- .name = "RGB/YUV Input",
- .add = vimc_sen_add,
- .release = vimc_sen_release,
- },
- {
- .name = "Scaler",
- .add = vimc_sca_add,
- .release = vimc_sca_release,
- },
- {
- .name = "RGB/YUV Capture",
- .add = vimc_cap_add,
- .unregister = vimc_cap_unregister,
- .release = vimc_cap_release,
- },
-};
-
-static const struct vimc_ent_link ent_links[] = {
- /* Link: Sensor A (Pad 0)->(Pad 0) Debayer A */
- VIMC_ENT_LINK(0, 0, 2, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
- /* Link: Sensor A (Pad 0)->(Pad 0) Raw Capture 0 */
- VIMC_ENT_LINK(0, 0, 4, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
- /* Link: Sensor B (Pad 0)->(Pad 0) Debayer B */
- VIMC_ENT_LINK(1, 0, 3, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
- /* Link: Sensor B (Pad 0)->(Pad 0) Raw Capture 1 */
- VIMC_ENT_LINK(1, 0, 5, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
- /* Link: Debayer A (Pad 1)->(Pad 0) Scaler */
- VIMC_ENT_LINK(2, 1, 7, 0, MEDIA_LNK_FL_ENABLED),
- /* Link: Debayer B (Pad 1)->(Pad 0) Scaler */
- VIMC_ENT_LINK(3, 1, 7, 0, 0),
- /* Link: RGB/YUV Input (Pad 0)->(Pad 0) Scaler */
- VIMC_ENT_LINK(6, 0, 7, 0, 0),
- /* Link: Scaler (Pad 1)->(Pad 0) RGB/YUV Capture */
- VIMC_ENT_LINK(7, 1, 8, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
-};
-
-static struct vimc_pipeline_config pipe_cfg = {
- .ents = ent_config,
- .num_ents = ARRAY_SIZE(ent_config),
- .links = ent_links,
- .num_links = ARRAY_SIZE(ent_links)
-};
-
-/* -------------------------------------------------------------------------- */
-
-static void vimc_rm_links(struct vimc_device *vimc)
-{
- unsigned int i;
-
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
- media_entity_remove_links(vimc->ent_devs[i]->ent);
-}
-
-static int vimc_create_links(struct vimc_device *vimc)
-{
- unsigned int i;
- int ret;
-
- /* Initialize the links between entities */
- for (i = 0; i < vimc->pipe_cfg->num_links; i++) {
- const struct vimc_ent_link *link = &vimc->pipe_cfg->links[i];
-
- struct vimc_ent_device *ved_src =
- vimc->ent_devs[link->src_ent];
- struct vimc_ent_device *ved_sink =
- vimc->ent_devs[link->sink_ent];
-
- ret = media_create_pad_link(ved_src->ent, link->src_pad,
- ved_sink->ent, link->sink_pad,
- link->flags);
- if (ret)
- goto err_rm_links;
- }
-
- return 0;
-
-err_rm_links:
- vimc_rm_links(vimc);
- return ret;
-}
-
-static int vimc_add_subdevs(struct vimc_device *vimc)
-{
- unsigned int i;
-
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++) {
- dev_dbg(vimc->mdev.dev, "new entity for %s\n",
- vimc->pipe_cfg->ents[i].name);
- vimc->ent_devs[i] = vimc->pipe_cfg->ents[i].add(vimc,
- vimc->pipe_cfg->ents[i].name);
- if (!vimc->ent_devs[i]) {
- dev_err(vimc->mdev.dev, "add new entity for %s\n",
- vimc->pipe_cfg->ents[i].name);
- return -EINVAL;
- }
- }
- return 0;
-}
-
-static void vimc_release_subdevs(struct vimc_device *vimc)
-{
- unsigned int i;
-
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
- if (vimc->ent_devs[i])
- vimc->pipe_cfg->ents[i].release(vimc->ent_devs[i]);
-}
-
-static void vimc_unregister_subdevs(struct vimc_device *vimc)
-{
- unsigned int i;
-
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
- if (vimc->ent_devs[i] && vimc->pipe_cfg->ents[i].unregister)
- vimc->pipe_cfg->ents[i].unregister(vimc->ent_devs[i]);
-}
-
-static void vimc_v4l2_dev_release(struct v4l2_device *v4l2_dev)
-{
- struct vimc_device *vimc =
- container_of(v4l2_dev, struct vimc_device, v4l2_dev);
-
- vimc_release_subdevs(vimc);
- media_device_cleanup(&vimc->mdev);
- kfree(vimc->ent_devs);
- kfree(vimc);
-}
-
-static int vimc_register_devices(struct vimc_device *vimc)
-{
- int ret;
-
- /* Register the v4l2 struct */
- ret = v4l2_device_register(vimc->mdev.dev, &vimc->v4l2_dev);
- if (ret) {
- dev_err(vimc->mdev.dev,
- "v4l2 device register failed (err=%d)\n", ret);
- return ret;
- }
- /* allocate ent_devs */
- vimc->ent_devs = kcalloc(vimc->pipe_cfg->num_ents,
- sizeof(*vimc->ent_devs), GFP_KERNEL);
- if (!vimc->ent_devs) {
- ret = -ENOMEM;
- goto err_v4l2_unregister;
- }
-
- /* Invoke entity config hooks to initialize and register subdevs */
- ret = vimc_add_subdevs(vimc);
- if (ret)
- /* remove sundevs that got added */
- goto err_rm_subdevs;
-
- /* Initialize links */
- ret = vimc_create_links(vimc);
- if (ret)
- goto err_rm_subdevs;
-
- /* Register the media device */
- ret = media_device_register(&vimc->mdev);
- if (ret) {
- dev_err(vimc->mdev.dev,
- "media device register failed (err=%d)\n", ret);
- goto err_rm_subdevs;
- }
-
- /* Expose all subdev's nodes*/
- ret = v4l2_device_register_subdev_nodes(&vimc->v4l2_dev);
- if (ret) {
- dev_err(vimc->mdev.dev,
- "vimc subdev nodes registration failed (err=%d)\n",
- ret);
- goto err_mdev_unregister;
- }
-
- return 0;
-
-err_mdev_unregister:
- media_device_unregister(&vimc->mdev);
-err_rm_subdevs:
- vimc_unregister_subdevs(vimc);
- vimc_release_subdevs(vimc);
- kfree(vimc->ent_devs);
-err_v4l2_unregister:
- v4l2_device_unregister(&vimc->v4l2_dev);
-
- return ret;
-}
-
-static void vimc_unregister(struct vimc_device *vimc)
-{
- vimc_unregister_subdevs(vimc);
- media_device_unregister(&vimc->mdev);
- v4l2_device_unregister(&vimc->v4l2_dev);
-}
-
-static int vimc_probe(struct platform_device *pdev)
-{
- struct vimc_device *vimc;
- int ret;
-
- dev_dbg(&pdev->dev, "probe");
-
- vimc = kzalloc(sizeof(*vimc), GFP_KERNEL);
- if (!vimc)
- return -ENOMEM;
-
- vimc->pipe_cfg = &pipe_cfg;
-
- /* Link the media device within the v4l2_device */
- vimc->v4l2_dev.mdev = &vimc->mdev;
-
- /* Initialize media device */
- strscpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME,
- sizeof(vimc->mdev.model));
- snprintf(vimc->mdev.bus_info, sizeof(vimc->mdev.bus_info),
- "platform:%s", VIMC_PDEV_NAME);
- vimc->mdev.dev = &pdev->dev;
- media_device_init(&vimc->mdev);
-
- ret = vimc_register_devices(vimc);
- if (ret) {
- media_device_cleanup(&vimc->mdev);
- kfree(vimc);
- return ret;
- }
- /*
- * the release cb is set only after successful registration.
- * if the registration fails, we release directly from probe
- */
-
- vimc->v4l2_dev.release = vimc_v4l2_dev_release;
- platform_set_drvdata(pdev, vimc);
- return 0;
-}
-
-static int vimc_remove(struct platform_device *pdev)
-{
- struct vimc_device *vimc = platform_get_drvdata(pdev);
-
- dev_dbg(&pdev->dev, "remove");
-
- vimc_unregister(vimc);
- v4l2_device_put(&vimc->v4l2_dev);
-
- return 0;
-}
-
-static void vimc_dev_release(struct device *dev)
-{
-}
-
-static struct platform_device vimc_pdev = {
- .name = VIMC_PDEV_NAME,
- .dev.release = vimc_dev_release,
-};
-
-static struct platform_driver vimc_pdrv = {
- .probe = vimc_probe,
- .remove = vimc_remove,
- .driver = {
- .name = VIMC_PDEV_NAME,
- },
-};
-
-static int __init vimc_init(void)
-{
- int ret;
-
- ret = platform_device_register(&vimc_pdev);
- if (ret) {
- dev_err(&vimc_pdev.dev,
- "platform device registration failed (err=%d)\n", ret);
- return ret;
- }
-
- ret = platform_driver_register(&vimc_pdrv);
- if (ret) {
- dev_err(&vimc_pdev.dev,
- "platform driver registration failed (err=%d)\n", ret);
- platform_driver_unregister(&vimc_pdrv);
- return ret;
- }
-
- return 0;
-}
-
-static void __exit vimc_exit(void)
-{
- platform_driver_unregister(&vimc_pdrv);
-
- platform_device_unregister(&vimc_pdev);
-}
-
-module_init(vimc_init);
-module_exit(vimc_exit);
-
-MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC)");
-MODULE_AUTHOR("Helen Fornazier <helen.fornazier@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/vimc/vimc-debayer.c b/drivers/media/platform/vimc/vimc-debayer.c
deleted file mode 100644
index baf6bf9f65b5..000000000000
--- a/drivers/media/platform/vimc/vimc-debayer.c
+++ /dev/null
@@ -1,581 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-debayer.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/vmalloc.h>
-#include <linux/v4l2-mediabus.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-subdev.h>
-
-#include "vimc-common.h"
-
-enum vimc_deb_rgb_colors {
- VIMC_DEB_RED = 0,
- VIMC_DEB_GREEN = 1,
- VIMC_DEB_BLUE = 2,
-};
-
-struct vimc_deb_pix_map {
- u32 code;
- enum vimc_deb_rgb_colors order[2][2];
-};
-
-struct vimc_deb_device {
- struct vimc_ent_device ved;
- struct v4l2_subdev sd;
- /* The active format */
- struct v4l2_mbus_framefmt sink_fmt;
- u32 src_code;
- void (*set_rgb_src)(struct vimc_deb_device *vdeb, unsigned int lin,
- unsigned int col, unsigned int rgb[3]);
- /* Values calculated when the stream starts */
- u8 *src_frame;
- const struct vimc_deb_pix_map *sink_pix_map;
- unsigned int sink_bpp;
- unsigned int mean_win_size;
- struct v4l2_ctrl_handler hdl;
- struct media_pad pads[2];
-};
-
-static const struct v4l2_mbus_framefmt sink_fmt_default = {
- .width = 640,
- .height = 480,
- .code = MEDIA_BUS_FMT_SRGGB8_1X8,
- .field = V4L2_FIELD_NONE,
- .colorspace = V4L2_COLORSPACE_DEFAULT,
-};
-
-static const struct vimc_deb_pix_map vimc_deb_pix_map_list[] = {
- {
- .code = MEDIA_BUS_FMT_SBGGR8_1X8,
- .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_RED } }
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG8_1X8,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
- { VIMC_DEB_RED, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG8_1X8,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
- { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB8_1X8,
- .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
- },
- {
- .code = MEDIA_BUS_FMT_SBGGR10_1X10,
- .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_RED } }
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG10_1X10,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
- { VIMC_DEB_RED, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
- { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB10_1X10,
- .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
- },
- {
- .code = MEDIA_BUS_FMT_SBGGR12_1X12,
- .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_RED } }
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG12_1X12,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE },
- { VIMC_DEB_RED, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG12_1X12,
- .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED },
- { VIMC_DEB_BLUE, VIMC_DEB_GREEN } }
- },
- {
- .code = MEDIA_BUS_FMT_SRGGB12_1X12,
- .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN },
- { VIMC_DEB_GREEN, VIMC_DEB_BLUE } }
- },
-};
-
-static const struct vimc_deb_pix_map *vimc_deb_pix_map_by_code(u32 code)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(vimc_deb_pix_map_list); i++)
- if (vimc_deb_pix_map_list[i].code == code)
- return &vimc_deb_pix_map_list[i];
-
- return NULL;
-}
-
-static int vimc_deb_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *mf;
- unsigned int i;
-
- mf = v4l2_subdev_get_try_format(sd, cfg, 0);
- *mf = sink_fmt_default;
-
- for (i = 1; i < sd->entity.num_pads; i++) {
- mf = v4l2_subdev_get_try_format(sd, cfg, i);
- *mf = sink_fmt_default;
- mf->code = vdeb->src_code;
- }
-
- return 0;
-}
-
-static int vimc_deb_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- /* We only support one format for source pads */
- if (VIMC_IS_SRC(code->pad)) {
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
-
- if (code->index)
- return -EINVAL;
-
- code->code = vdeb->src_code;
- } else {
- if (code->index >= ARRAY_SIZE(vimc_deb_pix_map_list))
- return -EINVAL;
-
- code->code = vimc_deb_pix_map_list[code->index].code;
- }
-
- return 0;
-}
-
-static int vimc_deb_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
-
- if (fse->index)
- return -EINVAL;
-
- if (VIMC_IS_SINK(fse->pad)) {
- const struct vimc_deb_pix_map *vpix =
- vimc_deb_pix_map_by_code(fse->code);
-
- if (!vpix)
- return -EINVAL;
- } else if (fse->code != vdeb->src_code) {
- return -EINVAL;
- }
-
- fse->min_width = VIMC_FRAME_MIN_WIDTH;
- fse->max_width = VIMC_FRAME_MAX_WIDTH;
- fse->min_height = VIMC_FRAME_MIN_HEIGHT;
- fse->max_height = VIMC_FRAME_MAX_HEIGHT;
-
- return 0;
-}
-
-static int vimc_deb_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
-
- /* Get the current sink format */
- fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ?
- *v4l2_subdev_get_try_format(sd, cfg, 0) :
- vdeb->sink_fmt;
-
- /* Set the right code for the source pad */
- if (VIMC_IS_SRC(fmt->pad))
- fmt->format.code = vdeb->src_code;
-
- return 0;
-}
-
-static void vimc_deb_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
-{
- const struct vimc_deb_pix_map *vpix;
-
- /* Don't accept a code that is not on the debayer table */
- vpix = vimc_deb_pix_map_by_code(fmt->code);
- if (!vpix)
- fmt->code = sink_fmt_default.code;
-
- fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
- VIMC_FRAME_MAX_WIDTH) & ~1;
- fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
- VIMC_FRAME_MAX_HEIGHT) & ~1;
-
- if (fmt->field == V4L2_FIELD_ANY)
- fmt->field = sink_fmt_default.field;
-
- vimc_colorimetry_clamp(fmt);
-}
-
-static int vimc_deb_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *sink_fmt;
-
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- /* Do not change the format while stream is on */
- if (vdeb->src_frame)
- return -EBUSY;
-
- sink_fmt = &vdeb->sink_fmt;
- } else {
- sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
- }
-
- /*
- * Do not change the format of the source pad,
- * it is propagated from the sink
- */
- if (VIMC_IS_SRC(fmt->pad)) {
- fmt->format = *sink_fmt;
- /* TODO: Add support for other formats */
- fmt->format.code = vdeb->src_code;
- } else {
- /* Set the new format in the sink pad */
- vimc_deb_adjust_sink_fmt(&fmt->format);
-
- dev_dbg(vdeb->ved.dev, "%s: sink format update: "
- "old:%dx%d (0x%x, %d, %d, %d, %d) "
- "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vdeb->sd.name,
- /* old */
- sink_fmt->width, sink_fmt->height, sink_fmt->code,
- sink_fmt->colorspace, sink_fmt->quantization,
- sink_fmt->xfer_func, sink_fmt->ycbcr_enc,
- /* new */
- fmt->format.width, fmt->format.height, fmt->format.code,
- fmt->format.colorspace, fmt->format.quantization,
- fmt->format.xfer_func, fmt->format.ycbcr_enc);
-
- *sink_fmt = fmt->format;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_pad_ops vimc_deb_pad_ops = {
- .init_cfg = vimc_deb_init_cfg,
- .enum_mbus_code = vimc_deb_enum_mbus_code,
- .enum_frame_size = vimc_deb_enum_frame_size,
- .get_fmt = vimc_deb_get_fmt,
- .set_fmt = vimc_deb_set_fmt,
-};
-
-static void vimc_deb_set_rgb_mbus_fmt_rgb888_1x24(struct vimc_deb_device *vdeb,
- unsigned int lin,
- unsigned int col,
- unsigned int rgb[3])
-{
- unsigned int i, index;
-
- index = VIMC_FRAME_INDEX(lin, col, vdeb->sink_fmt.width, 3);
- for (i = 0; i < 3; i++)
- vdeb->src_frame[index + i] = rgb[i];
-}
-
-static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
-
- if (enable) {
- const struct vimc_pix_map *vpix;
- unsigned int frame_size;
-
- if (vdeb->src_frame)
- return 0;
-
- /* Calculate the frame size of the source pad */
- vpix = vimc_pix_map_by_code(vdeb->src_code);
- frame_size = vdeb->sink_fmt.width * vdeb->sink_fmt.height *
- vpix->bpp;
-
- /* Save the bytes per pixel of the sink */
- vpix = vimc_pix_map_by_code(vdeb->sink_fmt.code);
- vdeb->sink_bpp = vpix->bpp;
-
- /* Get the corresponding pixel map from the table */
- vdeb->sink_pix_map =
- vimc_deb_pix_map_by_code(vdeb->sink_fmt.code);
-
- /*
- * Allocate the frame buffer. Use vmalloc to be able to
- * allocate a large amount of memory
- */
- vdeb->src_frame = vmalloc(frame_size);
- if (!vdeb->src_frame)
- return -ENOMEM;
-
- } else {
- if (!vdeb->src_frame)
- return 0;
-
- vfree(vdeb->src_frame);
- vdeb->src_frame = NULL;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_core_ops vimc_deb_core_ops = {
- .log_status = v4l2_ctrl_subdev_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
-static const struct v4l2_subdev_video_ops vimc_deb_video_ops = {
- .s_stream = vimc_deb_s_stream,
-};
-
-static const struct v4l2_subdev_ops vimc_deb_ops = {
- .core = &vimc_deb_core_ops,
- .pad = &vimc_deb_pad_ops,
- .video = &vimc_deb_video_ops,
-};
-
-static unsigned int vimc_deb_get_val(const u8 *bytes,
- const unsigned int n_bytes)
-{
- unsigned int i;
- unsigned int acc = 0;
-
- for (i = 0; i < n_bytes; i++)
- acc = acc + (bytes[i] << (8 * i));
-
- return acc;
-}
-
-static void vimc_deb_calc_rgb_sink(struct vimc_deb_device *vdeb,
- const u8 *frame,
- const unsigned int lin,
- const unsigned int col,
- unsigned int rgb[3])
-{
- unsigned int i, seek, wlin, wcol;
- unsigned int n_rgb[3] = {0, 0, 0};
-
- for (i = 0; i < 3; i++)
- rgb[i] = 0;
-
- /*
- * Calculate how many we need to subtract to get to the pixel in
- * the top left corner of the mean window (considering the current
- * pixel as the center)
- */
- seek = vdeb->mean_win_size / 2;
-
- /* Sum the values of the colors in the mean window */
-
- dev_dbg(vdeb->ved.dev,
- "deb: %s: --- Calc pixel %dx%d, window mean %d, seek %d ---\n",
- vdeb->sd.name, lin, col, vdeb->sink_fmt.height, seek);
-
- /*
- * Iterate through all the lines in the mean window, start
- * with zero if the pixel is outside the frame and don't pass
- * the height when the pixel is in the bottom border of the
- * frame
- */
- for (wlin = seek > lin ? 0 : lin - seek;
- wlin < lin + seek + 1 && wlin < vdeb->sink_fmt.height;
- wlin++) {
-
- /*
- * Iterate through all the columns in the mean window, start
- * with zero if the pixel is outside the frame and don't pass
- * the width when the pixel is in the right border of the
- * frame
- */
- for (wcol = seek > col ? 0 : col - seek;
- wcol < col + seek + 1 && wcol < vdeb->sink_fmt.width;
- wcol++) {
- enum vimc_deb_rgb_colors color;
- unsigned int index;
-
- /* Check which color this pixel is */
- color = vdeb->sink_pix_map->order[wlin % 2][wcol % 2];
-
- index = VIMC_FRAME_INDEX(wlin, wcol,
- vdeb->sink_fmt.width,
- vdeb->sink_bpp);
-
- dev_dbg(vdeb->ved.dev,
- "deb: %s: RGB CALC: frame index %d, win pos %dx%d, color %d\n",
- vdeb->sd.name, index, wlin, wcol, color);
-
- /* Get its value */
- rgb[color] = rgb[color] +
- vimc_deb_get_val(&frame[index], vdeb->sink_bpp);
-
- /* Save how many values we already added */
- n_rgb[color]++;
-
- dev_dbg(vdeb->ved.dev, "deb: %s: RGB CALC: val %d, n %d\n",
- vdeb->sd.name, rgb[color], n_rgb[color]);
- }
- }
-
- /* Calculate the mean */
- for (i = 0; i < 3; i++) {
- dev_dbg(vdeb->ved.dev,
- "deb: %s: PRE CALC: %dx%d Color %d, val %d, n %d\n",
- vdeb->sd.name, lin, col, i, rgb[i], n_rgb[i]);
-
- if (n_rgb[i])
- rgb[i] = rgb[i] / n_rgb[i];
-
- dev_dbg(vdeb->ved.dev,
- "deb: %s: FINAL CALC: %dx%d Color %d, val %d\n",
- vdeb->sd.name, lin, col, i, rgb[i]);
- }
-}
-
-static void *vimc_deb_process_frame(struct vimc_ent_device *ved,
- const void *sink_frame)
-{
- struct vimc_deb_device *vdeb = container_of(ved, struct vimc_deb_device,
- ved);
- unsigned int rgb[3];
- unsigned int i, j;
-
- /* If the stream in this node is not active, just return */
- if (!vdeb->src_frame)
- return ERR_PTR(-EINVAL);
-
- for (i = 0; i < vdeb->sink_fmt.height; i++)
- for (j = 0; j < vdeb->sink_fmt.width; j++) {
- vimc_deb_calc_rgb_sink(vdeb, sink_frame, i, j, rgb);
- vdeb->set_rgb_src(vdeb, i, j, rgb);
- }
-
- return vdeb->src_frame;
-}
-
-static int vimc_deb_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vimc_deb_device *vdeb =
- container_of(ctrl->handler, struct vimc_deb_device, hdl);
-
- switch (ctrl->id) {
- case VIMC_CID_MEAN_WIN_SIZE:
- vdeb->mean_win_size = ctrl->val;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vimc_deb_ctrl_ops = {
- .s_ctrl = vimc_deb_s_ctrl,
-};
-
-void vimc_deb_release(struct vimc_ent_device *ved)
-{
- struct vimc_deb_device *vdeb =
- container_of(ved, struct vimc_deb_device, ved);
-
- v4l2_ctrl_handler_free(&vdeb->hdl);
- media_entity_cleanup(vdeb->ved.ent);
- kfree(vdeb);
-}
-
-static const struct v4l2_ctrl_config vimc_deb_ctrl_class = {
- .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
- .id = VIMC_CID_VIMC_CLASS,
- .name = "VIMC Controls",
- .type = V4L2_CTRL_TYPE_CTRL_CLASS,
-};
-
-static const struct v4l2_ctrl_config vimc_deb_ctrl_mean_win_size = {
- .ops = &vimc_deb_ctrl_ops,
- .id = VIMC_CID_MEAN_WIN_SIZE,
- .name = "Debayer Mean Window Size",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 1,
- .max = 25,
- .step = 2,
- .def = 3,
-};
-
-struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc,
- const char *vcfg_name)
-{
- struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
- struct vimc_deb_device *vdeb;
- int ret;
-
- /* Allocate the vdeb struct */
- vdeb = kzalloc(sizeof(*vdeb), GFP_KERNEL);
- if (!vdeb)
- return NULL;
-
- /* Create controls: */
- v4l2_ctrl_handler_init(&vdeb->hdl, 2);
- v4l2_ctrl_new_custom(&vdeb->hdl, &vimc_deb_ctrl_class, NULL);
- v4l2_ctrl_new_custom(&vdeb->hdl, &vimc_deb_ctrl_mean_win_size, NULL);
- vdeb->sd.ctrl_handler = &vdeb->hdl;
- if (vdeb->hdl.error) {
- ret = vdeb->hdl.error;
- goto err_free_vdeb;
- }
-
- /* Initialize ved and sd */
- vdeb->pads[0].flags = MEDIA_PAD_FL_SINK;
- vdeb->pads[1].flags = MEDIA_PAD_FL_SOURCE;
-
- ret = vimc_ent_sd_register(&vdeb->ved, &vdeb->sd, v4l2_dev,
- vcfg_name,
- MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, 2,
- vdeb->pads, &vimc_deb_ops);
- if (ret)
- goto err_free_hdl;
-
- vdeb->ved.process_frame = vimc_deb_process_frame;
- vdeb->ved.dev = vimc->mdev.dev;
- vdeb->mean_win_size = vimc_deb_ctrl_mean_win_size.def;
-
- /* Initialize the frame format */
- vdeb->sink_fmt = sink_fmt_default;
- /*
- * TODO: Add support for more output formats, we only support
- * RGB888 for now
- * NOTE: the src format is always the same as the sink, except
- * for the code
- */
- vdeb->src_code = MEDIA_BUS_FMT_RGB888_1X24;
- vdeb->set_rgb_src = vimc_deb_set_rgb_mbus_fmt_rgb888_1x24;
-
- return &vdeb->ved;
-
-err_free_hdl:
- v4l2_ctrl_handler_free(&vdeb->hdl);
-err_free_vdeb:
- kfree(vdeb);
-
- return NULL;
-}
diff --git a/drivers/media/platform/vimc/vimc-scaler.c b/drivers/media/platform/vimc/vimc-scaler.c
deleted file mode 100644
index 7521439747c5..000000000000
--- a/drivers/media/platform/vimc/vimc-scaler.c
+++ /dev/null
@@ -1,511 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-scaler.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/moduleparam.h>
-#include <linux/vmalloc.h>
-#include <linux/v4l2-mediabus.h>
-#include <media/v4l2-rect.h>
-#include <media/v4l2-subdev.h>
-
-#include "vimc-common.h"
-
-static unsigned int sca_mult = 3;
-module_param(sca_mult, uint, 0000);
-MODULE_PARM_DESC(sca_mult, " the image size multiplier");
-
-#define MAX_ZOOM 8
-
-#define VIMC_SCA_FMT_WIDTH_DEFAULT 640
-#define VIMC_SCA_FMT_HEIGHT_DEFAULT 480
-
-struct vimc_sca_device {
- struct vimc_ent_device ved;
- struct v4l2_subdev sd;
- /* NOTE: the source fmt is the same as the sink
- * with the width and hight multiplied by mult
- */
- struct v4l2_mbus_framefmt sink_fmt;
- struct v4l2_rect crop_rect;
- /* Values calculated when the stream starts */
- u8 *src_frame;
- unsigned int src_line_size;
- unsigned int bpp;
- struct media_pad pads[2];
-};
-
-static const struct v4l2_mbus_framefmt sink_fmt_default = {
- .width = VIMC_SCA_FMT_WIDTH_DEFAULT,
- .height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
- .code = MEDIA_BUS_FMT_RGB888_1X24,
- .field = V4L2_FIELD_NONE,
- .colorspace = V4L2_COLORSPACE_DEFAULT,
-};
-
-static const struct v4l2_rect crop_rect_default = {
- .width = VIMC_SCA_FMT_WIDTH_DEFAULT,
- .height = VIMC_SCA_FMT_HEIGHT_DEFAULT,
- .top = 0,
- .left = 0,
-};
-
-static const struct v4l2_rect crop_rect_min = {
- .width = VIMC_FRAME_MIN_WIDTH,
- .height = VIMC_FRAME_MIN_HEIGHT,
- .top = 0,
- .left = 0,
-};
-
-static struct v4l2_rect
-vimc_sca_get_crop_bound_sink(const struct v4l2_mbus_framefmt *sink_fmt)
-{
- /* Get the crop bounds to clamp the crop rectangle correctly */
- struct v4l2_rect r = {
- .left = 0,
- .top = 0,
- .width = sink_fmt->width,
- .height = sink_fmt->height,
- };
- return r;
-}
-
-static void vimc_sca_adjust_sink_crop(struct v4l2_rect *r,
- const struct v4l2_mbus_framefmt *sink_fmt)
-{
- const struct v4l2_rect sink_rect =
- vimc_sca_get_crop_bound_sink(sink_fmt);
-
- /* Disallow rectangles smaller than the minimal one. */
- v4l2_rect_set_min_size(r, &crop_rect_min);
- v4l2_rect_map_inside(r, &sink_rect);
-}
-
-static int vimc_sca_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg)
-{
- struct v4l2_mbus_framefmt *mf;
- struct v4l2_rect *r;
- unsigned int i;
-
- mf = v4l2_subdev_get_try_format(sd, cfg, 0);
- *mf = sink_fmt_default;
-
- r = v4l2_subdev_get_try_crop(sd, cfg, 0);
- *r = crop_rect_default;
-
- for (i = 1; i < sd->entity.num_pads; i++) {
- mf = v4l2_subdev_get_try_format(sd, cfg, i);
- *mf = sink_fmt_default;
- mf->width = mf->width * sca_mult;
- mf->height = mf->height * sca_mult;
- }
-
- return 0;
-}
-
-static int vimc_sca_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- const struct vimc_pix_map *vpix = vimc_pix_map_by_index(code->index);
-
- /* We don't support bayer format */
- if (!vpix || vpix->bayer)
- return -EINVAL;
-
- code->code = vpix->code;
-
- return 0;
-}
-
-static int vimc_sca_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
-{
- const struct vimc_pix_map *vpix;
-
- if (fse->index)
- return -EINVAL;
-
- /* Only accept code in the pix map table in non bayer format */
- vpix = vimc_pix_map_by_code(fse->code);
- if (!vpix || vpix->bayer)
- return -EINVAL;
-
- fse->min_width = VIMC_FRAME_MIN_WIDTH;
- fse->min_height = VIMC_FRAME_MIN_HEIGHT;
-
- if (VIMC_IS_SINK(fse->pad)) {
- fse->max_width = VIMC_FRAME_MAX_WIDTH;
- fse->max_height = VIMC_FRAME_MAX_HEIGHT;
- } else {
- fse->max_width = VIMC_FRAME_MAX_WIDTH * MAX_ZOOM;
- fse->max_height = VIMC_FRAME_MAX_HEIGHT * MAX_ZOOM;
- }
-
- return 0;
-}
-
-static int vimc_sca_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *format)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
- struct v4l2_rect *crop_rect;
-
- /* Get the current sink format */
- if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
- crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
- } else {
- format->format = vsca->sink_fmt;
- crop_rect = &vsca->crop_rect;
- }
-
- /* Scale the frame size for the source pad */
- if (VIMC_IS_SRC(format->pad)) {
- format->format.width = crop_rect->width * sca_mult;
- format->format.height = crop_rect->height * sca_mult;
- }
-
- return 0;
-}
-
-static void vimc_sca_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt)
-{
- const struct vimc_pix_map *vpix;
-
- /* Only accept code in the pix map table in non bayer format */
- vpix = vimc_pix_map_by_code(fmt->code);
- if (!vpix || vpix->bayer)
- fmt->code = sink_fmt_default.code;
-
- fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
- VIMC_FRAME_MAX_WIDTH) & ~1;
- fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
- VIMC_FRAME_MAX_HEIGHT) & ~1;
-
- if (fmt->field == V4L2_FIELD_ANY)
- fmt->field = sink_fmt_default.field;
-
- vimc_colorimetry_clamp(fmt);
-}
-
-static int vimc_sca_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *sink_fmt;
- struct v4l2_rect *crop_rect;
-
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- /* Do not change the format while stream is on */
- if (vsca->src_frame)
- return -EBUSY;
-
- sink_fmt = &vsca->sink_fmt;
- crop_rect = &vsca->crop_rect;
- } else {
- sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
- crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
- }
-
- /*
- * Do not change the format of the source pad,
- * it is propagated from the sink
- */
- if (VIMC_IS_SRC(fmt->pad)) {
- fmt->format = *sink_fmt;
- fmt->format.width = crop_rect->width * sca_mult;
- fmt->format.height = crop_rect->height * sca_mult;
- } else {
- /* Set the new format in the sink pad */
- vimc_sca_adjust_sink_fmt(&fmt->format);
-
- dev_dbg(vsca->ved.dev, "%s: sink format update: "
- "old:%dx%d (0x%x, %d, %d, %d, %d) "
- "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsca->sd.name,
- /* old */
- sink_fmt->width, sink_fmt->height, sink_fmt->code,
- sink_fmt->colorspace, sink_fmt->quantization,
- sink_fmt->xfer_func, sink_fmt->ycbcr_enc,
- /* new */
- fmt->format.width, fmt->format.height, fmt->format.code,
- fmt->format.colorspace, fmt->format.quantization,
- fmt->format.xfer_func, fmt->format.ycbcr_enc);
-
- *sink_fmt = fmt->format;
-
- /* Do the crop, but respect the current bounds */
- vimc_sca_adjust_sink_crop(crop_rect, sink_fmt);
- }
-
- return 0;
-}
-
-static int vimc_sca_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_selection *sel)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *sink_fmt;
- struct v4l2_rect *crop_rect;
-
- if (VIMC_IS_SRC(sel->pad))
- return -EINVAL;
-
- if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- sink_fmt = &vsca->sink_fmt;
- crop_rect = &vsca->crop_rect;
- } else {
- sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
- crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
- }
-
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP:
- sel->r = *crop_rect;
- break;
- case V4L2_SEL_TGT_CROP_BOUNDS:
- sel->r = vimc_sca_get_crop_bound_sink(sink_fmt);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vimc_sca_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_selection *sel)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *sink_fmt;
- struct v4l2_rect *crop_rect;
-
- if (VIMC_IS_SRC(sel->pad))
- return -EINVAL;
-
- if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- /* Do not change the format while stream is on */
- if (vsca->src_frame)
- return -EBUSY;
-
- crop_rect = &vsca->crop_rect;
- sink_fmt = &vsca->sink_fmt;
- } else {
- crop_rect = v4l2_subdev_get_try_crop(sd, cfg, 0);
- sink_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
- }
-
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP:
- /* Do the crop, but respect the current bounds */
- vimc_sca_adjust_sink_crop(&sel->r, sink_fmt);
- *crop_rect = sel->r;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_pad_ops vimc_sca_pad_ops = {
- .init_cfg = vimc_sca_init_cfg,
- .enum_mbus_code = vimc_sca_enum_mbus_code,
- .enum_frame_size = vimc_sca_enum_frame_size,
- .get_fmt = vimc_sca_get_fmt,
- .set_fmt = vimc_sca_set_fmt,
- .get_selection = vimc_sca_get_selection,
- .set_selection = vimc_sca_set_selection,
-};
-
-static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
-
- if (enable) {
- const struct vimc_pix_map *vpix;
- unsigned int frame_size;
-
- if (vsca->src_frame)
- return 0;
-
- /* Save the bytes per pixel of the sink */
- vpix = vimc_pix_map_by_code(vsca->sink_fmt.code);
- vsca->bpp = vpix->bpp;
-
- /* Calculate the width in bytes of the src frame */
- vsca->src_line_size = vsca->crop_rect.width *
- sca_mult * vsca->bpp;
-
- /* Calculate the frame size of the source pad */
- frame_size = vsca->src_line_size * vsca->crop_rect.height *
- sca_mult;
-
- /* Allocate the frame buffer. Use vmalloc to be able to
- * allocate a large amount of memory
- */
- vsca->src_frame = vmalloc(frame_size);
- if (!vsca->src_frame)
- return -ENOMEM;
-
- } else {
- if (!vsca->src_frame)
- return 0;
-
- vfree(vsca->src_frame);
- vsca->src_frame = NULL;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_video_ops vimc_sca_video_ops = {
- .s_stream = vimc_sca_s_stream,
-};
-
-static const struct v4l2_subdev_ops vimc_sca_ops = {
- .pad = &vimc_sca_pad_ops,
- .video = &vimc_sca_video_ops,
-};
-
-static void vimc_sca_fill_pix(u8 *const ptr,
- const u8 *const pixel,
- const unsigned int bpp)
-{
- unsigned int i;
-
- /* copy the pixel to the pointer */
- for (i = 0; i < bpp; i++)
- ptr[i] = pixel[i];
-}
-
-static void vimc_sca_scale_pix(const struct vimc_sca_device *const vsca,
- unsigned int lin, unsigned int col,
- const u8 *const sink_frame)
-{
- const struct v4l2_rect crop_rect = vsca->crop_rect;
- unsigned int i, j, index;
- const u8 *pixel;
-
- /* Point to the pixel value in position (lin, col) in the sink frame */
- index = VIMC_FRAME_INDEX(lin, col,
- vsca->sink_fmt.width,
- vsca->bpp);
- pixel = &sink_frame[index];
-
- dev_dbg(vsca->ved.dev,
- "sca: %s: --- scale_pix sink pos %dx%d, index %d ---\n",
- vsca->sd.name, lin, col, index);
-
- /* point to the place we are going to put the first pixel
- * in the scaled src frame
- */
- lin -= crop_rect.top;
- col -= crop_rect.left;
- index = VIMC_FRAME_INDEX(lin * sca_mult, col * sca_mult,
- crop_rect.width * sca_mult, vsca->bpp);
-
- dev_dbg(vsca->ved.dev, "sca: %s: scale_pix src pos %dx%d, index %d\n",
- vsca->sd.name, lin * sca_mult, col * sca_mult, index);
-
- /* Repeat this pixel mult times */
- for (i = 0; i < sca_mult; i++) {
- /* Iterate through each beginning of a
- * pixel repetition in a line
- */
- for (j = 0; j < sca_mult * vsca->bpp; j += vsca->bpp) {
- dev_dbg(vsca->ved.dev,
- "sca: %s: sca: scale_pix src pos %d\n",
- vsca->sd.name, index + j);
-
- /* copy the pixel to the position index + j */
- vimc_sca_fill_pix(&vsca->src_frame[index + j],
- pixel, vsca->bpp);
- }
-
- /* move the index to the next line */
- index += vsca->src_line_size;
- }
-}
-
-static void vimc_sca_fill_src_frame(const struct vimc_sca_device *const vsca,
- const u8 *const sink_frame)
-{
- const struct v4l2_rect r = vsca->crop_rect;
- unsigned int i, j;
-
- /* Scale each pixel from the original sink frame */
- /* TODO: implement scale down, only scale up is supported for now */
- for (i = r.top; i < r.top + r.height; i++)
- for (j = r.left; j < r.left + r.width; j++)
- vimc_sca_scale_pix(vsca, i, j, sink_frame);
-}
-
-static void *vimc_sca_process_frame(struct vimc_ent_device *ved,
- const void *sink_frame)
-{
- struct vimc_sca_device *vsca = container_of(ved, struct vimc_sca_device,
- ved);
-
- /* If the stream in this node is not active, just return */
- if (!vsca->src_frame)
- return ERR_PTR(-EINVAL);
-
- vimc_sca_fill_src_frame(vsca, sink_frame);
-
- return vsca->src_frame;
-};
-
-void vimc_sca_release(struct vimc_ent_device *ved)
-{
- struct vimc_sca_device *vsca =
- container_of(ved, struct vimc_sca_device, ved);
-
- media_entity_cleanup(vsca->ved.ent);
- kfree(vsca);
-}
-
-struct vimc_ent_device *vimc_sca_add(struct vimc_device *vimc,
- const char *vcfg_name)
-{
- struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
- struct vimc_sca_device *vsca;
- int ret;
-
- /* Allocate the vsca struct */
- vsca = kzalloc(sizeof(*vsca), GFP_KERNEL);
- if (!vsca)
- return NULL;
-
- /* Initialize ved and sd */
- vsca->pads[0].flags = MEDIA_PAD_FL_SINK;
- vsca->pads[1].flags = MEDIA_PAD_FL_SOURCE;
-
- ret = vimc_ent_sd_register(&vsca->ved, &vsca->sd, v4l2_dev,
- vcfg_name,
- MEDIA_ENT_F_PROC_VIDEO_SCALER, 2,
- vsca->pads, &vimc_sca_ops);
- if (ret) {
- kfree(vsca);
- return NULL;
- }
-
- vsca->ved.process_frame = vimc_sca_process_frame;
- vsca->ved.dev = vimc->mdev.dev;
-
- /* Initialize the frame format */
- vsca->sink_fmt = sink_fmt_default;
-
- /* Initialize the crop selection */
- vsca->crop_rect = crop_rect_default;
-
- return &vsca->ved;
-}
diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c
deleted file mode 100644
index 92daee58209e..000000000000
--- a/drivers/media/platform/vimc/vimc-sensor.c
+++ /dev/null
@@ -1,376 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * vimc-sensor.c Virtual Media Controller Driver
- *
- * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
- */
-
-#include <linux/v4l2-mediabus.h>
-#include <linux/vmalloc.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-subdev.h>
-#include <media/tpg/v4l2-tpg.h>
-
-#include "vimc-common.h"
-
-struct vimc_sen_device {
- struct vimc_ent_device ved;
- struct v4l2_subdev sd;
- struct tpg_data tpg;
- u8 *frame;
- /* The active format */
- struct v4l2_mbus_framefmt mbus_format;
- struct v4l2_ctrl_handler hdl;
- struct media_pad pad;
-};
-
-static const struct v4l2_mbus_framefmt fmt_default = {
- .width = 640,
- .height = 480,
- .code = MEDIA_BUS_FMT_RGB888_1X24,
- .field = V4L2_FIELD_NONE,
- .colorspace = V4L2_COLORSPACE_DEFAULT,
-};
-
-static int vimc_sen_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg)
-{
- unsigned int i;
-
- for (i = 0; i < sd->entity.num_pads; i++) {
- struct v4l2_mbus_framefmt *mf;
-
- mf = v4l2_subdev_get_try_format(sd, cfg, i);
- *mf = fmt_default;
- }
-
- return 0;
-}
-
-static int vimc_sen_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- const struct vimc_pix_map *vpix = vimc_pix_map_by_index(code->index);
-
- if (!vpix)
- return -EINVAL;
-
- code->code = vpix->code;
-
- return 0;
-}
-
-static int vimc_sen_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
-{
- const struct vimc_pix_map *vpix;
-
- if (fse->index)
- return -EINVAL;
-
- /* Only accept code in the pix map table */
- vpix = vimc_pix_map_by_code(fse->code);
- if (!vpix)
- return -EINVAL;
-
- fse->min_width = VIMC_FRAME_MIN_WIDTH;
- fse->max_width = VIMC_FRAME_MAX_WIDTH;
- fse->min_height = VIMC_FRAME_MIN_HEIGHT;
- fse->max_height = VIMC_FRAME_MAX_HEIGHT;
-
- return 0;
-}
-
-static int vimc_sen_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_sen_device *vsen =
- container_of(sd, struct vimc_sen_device, sd);
-
- fmt->format = fmt->which == V4L2_SUBDEV_FORMAT_TRY ?
- *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) :
- vsen->mbus_format;
-
- return 0;
-}
-
-static void vimc_sen_tpg_s_format(struct vimc_sen_device *vsen)
-{
- const struct vimc_pix_map *vpix =
- vimc_pix_map_by_code(vsen->mbus_format.code);
-
- tpg_reset_source(&vsen->tpg, vsen->mbus_format.width,
- vsen->mbus_format.height, vsen->mbus_format.field);
- tpg_s_bytesperline(&vsen->tpg, 0, vsen->mbus_format.width * vpix->bpp);
- tpg_s_buf_height(&vsen->tpg, vsen->mbus_format.height);
- tpg_s_fourcc(&vsen->tpg, vpix->pixelformat);
- /* TODO: add support for V4L2_FIELD_ALTERNATE */
- tpg_s_field(&vsen->tpg, vsen->mbus_format.field, false);
- tpg_s_colorspace(&vsen->tpg, vsen->mbus_format.colorspace);
- tpg_s_ycbcr_enc(&vsen->tpg, vsen->mbus_format.ycbcr_enc);
- tpg_s_quantization(&vsen->tpg, vsen->mbus_format.quantization);
- tpg_s_xfer_func(&vsen->tpg, vsen->mbus_format.xfer_func);
-}
-
-static void vimc_sen_adjust_fmt(struct v4l2_mbus_framefmt *fmt)
-{
- const struct vimc_pix_map *vpix;
-
- /* Only accept code in the pix map table */
- vpix = vimc_pix_map_by_code(fmt->code);
- if (!vpix)
- fmt->code = fmt_default.code;
-
- fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH,
- VIMC_FRAME_MAX_WIDTH) & ~1;
- fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT,
- VIMC_FRAME_MAX_HEIGHT) & ~1;
-
- /* TODO: add support for V4L2_FIELD_ALTERNATE */
- if (fmt->field == V4L2_FIELD_ANY || fmt->field == V4L2_FIELD_ALTERNATE)
- fmt->field = fmt_default.field;
-
- vimc_colorimetry_clamp(fmt);
-}
-
-static int vimc_sen_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct vimc_sen_device *vsen = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *mf;
-
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- /* Do not change the format while stream is on */
- if (vsen->frame)
- return -EBUSY;
-
- mf = &vsen->mbus_format;
- } else {
- mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
- }
-
- /* Set the new format */
- vimc_sen_adjust_fmt(&fmt->format);
-
- dev_dbg(vsen->ved.dev, "%s: format update: "
- "old:%dx%d (0x%x, %d, %d, %d, %d) "
- "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsen->sd.name,
- /* old */
- mf->width, mf->height, mf->code,
- mf->colorspace, mf->quantization,
- mf->xfer_func, mf->ycbcr_enc,
- /* new */
- fmt->format.width, fmt->format.height, fmt->format.code,
- fmt->format.colorspace, fmt->format.quantization,
- fmt->format.xfer_func, fmt->format.ycbcr_enc);
-
- *mf = fmt->format;
-
- return 0;
-}
-
-static const struct v4l2_subdev_pad_ops vimc_sen_pad_ops = {
- .init_cfg = vimc_sen_init_cfg,
- .enum_mbus_code = vimc_sen_enum_mbus_code,
- .enum_frame_size = vimc_sen_enum_frame_size,
- .get_fmt = vimc_sen_get_fmt,
- .set_fmt = vimc_sen_set_fmt,
-};
-
-static void *vimc_sen_process_frame(struct vimc_ent_device *ved,
- const void *sink_frame)
-{
- struct vimc_sen_device *vsen = container_of(ved, struct vimc_sen_device,
- ved);
-
- tpg_fill_plane_buffer(&vsen->tpg, 0, 0, vsen->frame);
- return vsen->frame;
-}
-
-static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct vimc_sen_device *vsen =
- container_of(sd, struct vimc_sen_device, sd);
-
- if (enable) {
- const struct vimc_pix_map *vpix;
- unsigned int frame_size;
-
- /* Calculate the frame size */
- vpix = vimc_pix_map_by_code(vsen->mbus_format.code);
- frame_size = vsen->mbus_format.width * vpix->bpp *
- vsen->mbus_format.height;
-
- /*
- * Allocate the frame buffer. Use vmalloc to be able to
- * allocate a large amount of memory
- */
- vsen->frame = vmalloc(frame_size);
- if (!vsen->frame)
- return -ENOMEM;
-
- /* configure the test pattern generator */
- vimc_sen_tpg_s_format(vsen);
-
- } else {
-
- vfree(vsen->frame);
- vsen->frame = NULL;
- }
-
- return 0;
-}
-
-static const struct v4l2_subdev_core_ops vimc_sen_core_ops = {
- .log_status = v4l2_ctrl_subdev_log_status,
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
-static const struct v4l2_subdev_video_ops vimc_sen_video_ops = {
- .s_stream = vimc_sen_s_stream,
-};
-
-static const struct v4l2_subdev_ops vimc_sen_ops = {
- .core = &vimc_sen_core_ops,
- .pad = &vimc_sen_pad_ops,
- .video = &vimc_sen_video_ops,
-};
-
-static int vimc_sen_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vimc_sen_device *vsen =
- container_of(ctrl->handler, struct vimc_sen_device, hdl);
-
- switch (ctrl->id) {
- case VIMC_CID_TEST_PATTERN:
- tpg_s_pattern(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_HFLIP:
- tpg_s_hflip(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_VFLIP:
- tpg_s_vflip(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_BRIGHTNESS:
- tpg_s_brightness(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_CONTRAST:
- tpg_s_contrast(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_HUE:
- tpg_s_hue(&vsen->tpg, ctrl->val);
- break;
- case V4L2_CID_SATURATION:
- tpg_s_saturation(&vsen->tpg, ctrl->val);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vimc_sen_ctrl_ops = {
- .s_ctrl = vimc_sen_s_ctrl,
-};
-
-void vimc_sen_release(struct vimc_ent_device *ved)
-{
- struct vimc_sen_device *vsen =
- container_of(ved, struct vimc_sen_device, ved);
-
- v4l2_ctrl_handler_free(&vsen->hdl);
- tpg_free(&vsen->tpg);
- media_entity_cleanup(vsen->ved.ent);
- kfree(vsen);
-}
-
-/* Image Processing Controls */
-static const struct v4l2_ctrl_config vimc_sen_ctrl_class = {
- .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
- .id = VIMC_CID_VIMC_CLASS,
- .name = "VIMC Controls",
- .type = V4L2_CTRL_TYPE_CTRL_CLASS,
-};
-
-static const struct v4l2_ctrl_config vimc_sen_ctrl_test_pattern = {
- .ops = &vimc_sen_ctrl_ops,
- .id = VIMC_CID_TEST_PATTERN,
- .name = "Test Pattern",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = TPG_PAT_NOISE,
- .qmenu = tpg_pattern_strings,
-};
-
-struct vimc_ent_device *vimc_sen_add(struct vimc_device *vimc,
- const char *vcfg_name)
-{
- struct v4l2_device *v4l2_dev = &vimc->v4l2_dev;
- struct vimc_sen_device *vsen;
- int ret;
-
- /* Allocate the vsen struct */
- vsen = kzalloc(sizeof(*vsen), GFP_KERNEL);
- if (!vsen)
- return NULL;
-
- v4l2_ctrl_handler_init(&vsen->hdl, 4);
-
- v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_class, NULL);
- v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_test_pattern, NULL);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_VFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_HFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_CONTRAST, 0, 255, 1, 128);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_HUE, -128, 127, 1, 0);
- v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops,
- V4L2_CID_SATURATION, 0, 255, 1, 128);
- vsen->sd.ctrl_handler = &vsen->hdl;
- if (vsen->hdl.error) {
- ret = vsen->hdl.error;
- goto err_free_vsen;
- }
-
- /* Initialize the test pattern generator */
- tpg_init(&vsen->tpg, vsen->mbus_format.width,
- vsen->mbus_format.height);
- ret = tpg_alloc(&vsen->tpg, VIMC_FRAME_MAX_WIDTH);
- if (ret)
- goto err_free_hdl;
-
- /* Initialize ved and sd */
- vsen->pad.flags = MEDIA_PAD_FL_SOURCE;
- ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev,
- vcfg_name,
- MEDIA_ENT_F_CAM_SENSOR, 1, &vsen->pad,
- &vimc_sen_ops);
- if (ret)
- goto err_free_tpg;
-
- vsen->ved.process_frame = vimc_sen_process_frame;
- vsen->ved.dev = vimc->mdev.dev;
-
- /* Initialize the frame format */
- vsen->mbus_format = fmt_default;
-
- return &vsen->ved;
-
-err_free_tpg:
- tpg_free(&vsen->tpg);
-err_free_hdl:
- v4l2_ctrl_handler_free(&vsen->hdl);
-err_free_vsen:
- kfree(vsen);
-
- return NULL;
-}
diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c
deleted file mode 100644
index 65feb3c596db..000000000000
--- a/drivers/media/platform/vimc/vimc-streamer.c
+++ /dev/null
@@ -1,238 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * vimc-streamer.c Virtual Media Controller Driver
- *
- * Copyright (C) 2018 Lucas A. M. Magalhães <lucmaga@gmail.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/freezer.h>
-#include <linux/kthread.h>
-
-#include "vimc-streamer.h"
-
-/**
- * vimc_get_source_entity - get the entity connected with the first sink pad
- *
- * @ent: reference media_entity
- *
- * Helper function that returns the media entity containing the source pad
- * linked with the first sink pad from the given media entity pad list.
- *
- * Return: The source pad or NULL, if it wasn't found.
- */
-static struct media_entity *vimc_get_source_entity(struct media_entity *ent)
-{
- struct media_pad *pad;
- int i;
-
- for (i = 0; i < ent->num_pads; i++) {
- if (ent->pads[i].flags & MEDIA_PAD_FL_SOURCE)
- continue;
- pad = media_entity_remote_pad(&ent->pads[i]);
- return pad ? pad->entity : NULL;
- }
- return NULL;
-}
-
-/**
- * vimc_streamer_pipeline_terminate - Disable stream in all ved in stream
- *
- * @stream: the pointer to the stream structure with the pipeline to be
- * disabled.
- *
- * Calls s_stream to disable the stream in each entity of the pipeline
- *
- */
-static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream)
-{
- struct vimc_ent_device *ved;
- struct v4l2_subdev *sd;
-
- while (stream->pipe_size) {
- stream->pipe_size--;
- ved = stream->ved_pipeline[stream->pipe_size];
- stream->ved_pipeline[stream->pipe_size] = NULL;
-
- if (!is_media_entity_v4l2_subdev(ved->ent))
- continue;
-
- sd = media_entity_to_v4l2_subdev(ved->ent);
- v4l2_subdev_call(sd, video, s_stream, 0);
- }
-}
-
-/**
- * vimc_streamer_pipeline_init - Initializes the stream structure
- *
- * @stream: the pointer to the stream structure to be initialized
- * @ved: the pointer to the vimc entity initializing the stream
- *
- * Initializes the stream structure. Walks through the entity graph to
- * construct the pipeline used later on the streamer thread.
- * Calls vimc_streamer_s_stream() to enable stream in all entities of
- * the pipeline.
- *
- * Return: 0 if success, error code otherwise.
- */
-static int vimc_streamer_pipeline_init(struct vimc_stream *stream,
- struct vimc_ent_device *ved)
-{
- struct media_entity *entity;
- struct video_device *vdev;
- struct v4l2_subdev *sd;
- int ret = 0;
-
- stream->pipe_size = 0;
- while (stream->pipe_size < VIMC_STREAMER_PIPELINE_MAX_SIZE) {
- if (!ved) {
- vimc_streamer_pipeline_terminate(stream);
- return -EINVAL;
- }
- stream->ved_pipeline[stream->pipe_size++] = ved;
-
- if (is_media_entity_v4l2_subdev(ved->ent)) {
- sd = media_entity_to_v4l2_subdev(ved->ent);
- ret = v4l2_subdev_call(sd, video, s_stream, 1);
- if (ret && ret != -ENOIOCTLCMD) {
- dev_err(ved->dev, "subdev_call error %s\n",
- ved->ent->name);
- vimc_streamer_pipeline_terminate(stream);
- return ret;
- }
- }
-
- entity = vimc_get_source_entity(ved->ent);
- /* Check if the end of the pipeline was reached */
- if (!entity) {
- /* the first entity of the pipe should be source only */
- if (!vimc_is_source(ved->ent)) {
- dev_err(ved->dev,
- "first entity in the pipe '%s' is not a source\n",
- ved->ent->name);
- vimc_streamer_pipeline_terminate(stream);
- return -EPIPE;
- }
- return 0;
- }
-
- /* Get the next device in the pipeline */
- if (is_media_entity_v4l2_subdev(entity)) {
- sd = media_entity_to_v4l2_subdev(entity);
- ved = v4l2_get_subdevdata(sd);
- } else {
- vdev = container_of(entity,
- struct video_device,
- entity);
- ved = video_get_drvdata(vdev);
- }
- }
-
- vimc_streamer_pipeline_terminate(stream);
- return -EINVAL;
-}
-
-/**
- * vimc_streamer_thread - Process frames through the pipeline
- *
- * @data: vimc_stream struct of the current stream
- *
- * From the source to the sink, gets a frame from each subdevice and send to
- * the next one of the pipeline at a fixed framerate.
- *
- * Return:
- * Always zero (created as ``int`` instead of ``void`` to comply with
- * kthread API).
- */
-static int vimc_streamer_thread(void *data)
-{
- struct vimc_stream *stream = data;
- u8 *frame = NULL;
- int i;
-
- set_freezable();
-
- for (;;) {
- try_to_freeze();
- if (kthread_should_stop())
- break;
-
- for (i = stream->pipe_size - 1; i >= 0; i--) {
- frame = stream->ved_pipeline[i]->process_frame(
- stream->ved_pipeline[i], frame);
- if (!frame || IS_ERR(frame))
- break;
- }
- //wait for 60hz
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 60);
- }
-
- return 0;
-}
-
-/**
- * vimc_streamer_s_stream - Start/stop the streaming on the media pipeline
- *
- * @stream: the pointer to the stream structure of the current stream
- * @ved: pointer to the vimc entity of the entity of the stream
- * @enable: flag to determine if stream should start/stop
- *
- * When starting, check if there is no ``stream->kthread`` allocated. This
- * should indicate that a stream is already running. Then, it initializes the
- * pipeline, creates and runs a kthread to consume buffers through the pipeline.
- * When stopping, analogously check if there is a stream running, stop the
- * thread and terminates the pipeline.
- *
- * Return: 0 if success, error code otherwise.
- */
-int vimc_streamer_s_stream(struct vimc_stream *stream,
- struct vimc_ent_device *ved,
- int enable)
-{
- int ret;
-
- if (!stream || !ved)
- return -EINVAL;
-
- if (enable) {
- if (stream->kthread)
- return 0;
-
- ret = vimc_streamer_pipeline_init(stream, ved);
- if (ret)
- return ret;
-
- stream->kthread = kthread_run(vimc_streamer_thread, stream,
- "vimc-streamer thread");
-
- if (IS_ERR(stream->kthread)) {
- ret = PTR_ERR(stream->kthread);
- dev_err(ved->dev, "kthread_run failed with %d\n", ret);
- vimc_streamer_pipeline_terminate(stream);
- stream->kthread = NULL;
- return ret;
- }
-
- } else {
- if (!stream->kthread)
- return 0;
-
- ret = kthread_stop(stream->kthread);
- /*
- * kthread_stop returns -EINTR in cases when streamon was
- * immediately followed by streamoff, and the thread didn't had
- * a chance to run. Ignore errors to stop the stream in the
- * pipeline.
- */
- if (ret)
- dev_dbg(ved->dev, "kthread_stop returned '%d'\n", ret);
-
- stream->kthread = NULL;
-
- vimc_streamer_pipeline_terminate(stream);
- }
-
- return 0;
-}
diff --git a/drivers/media/platform/vimc/vimc-streamer.h b/drivers/media/platform/vimc/vimc-streamer.h
deleted file mode 100644
index fe3c51f15fad..000000000000
--- a/drivers/media/platform/vimc/vimc-streamer.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * vimc-streamer.h Virtual Media Controller Driver
- *
- * Copyright (C) 2018 Lucas A. M. Magalhães <lucmaga@gmail.com>
- *
- */
-
-#ifndef _VIMC_STREAMER_H_
-#define _VIMC_STREAMER_H_
-
-#include <media/media-device.h>
-
-#include "vimc-common.h"
-
-#define VIMC_STREAMER_PIPELINE_MAX_SIZE 16
-
-/**
- * struct vimc_stream - struct that represents a stream in the pipeline
- *
- * @pipe: the media pipeline object associated with this stream
- * @ved_pipeline: array containing all the entities participating in the
- * stream. The order is from a video device (usually a capture device) where
- * stream_on was called, to the entity generating the first base image to be
- * processed in the pipeline.
- * @pipe_size: size of @ved_pipeline
- * @kthread: thread that generates the frames of the stream.
- *
- * When the user call stream_on in a video device, struct vimc_stream is
- * used to keep track of all entities and subdevices that generates and
- * process frames for the stream.
- */
-struct vimc_stream {
- struct media_pipeline pipe;
- struct vimc_ent_device *ved_pipeline[VIMC_STREAMER_PIPELINE_MAX_SIZE];
- unsigned int pipe_size;
- struct task_struct *kthread;
-};
-
-int vimc_streamer_s_stream(struct vimc_stream *stream,
- struct vimc_ent_device *ved,
- int enable);
-
-#endif //_VIMC_STREAMER_H_
diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig
deleted file mode 100644
index e2ff06edfa93..000000000000
--- a/drivers/media/platform/vivid/Kconfig
+++ /dev/null
@@ -1,41 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_VIVID
- tristate "Virtual Video Test Driver"
- depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FB
- depends on HAS_DMA
- select FONT_SUPPORT
- select FONT_8x16
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select VIDEOBUF2_VMALLOC
- select VIDEOBUF2_DMA_CONTIG
- select VIDEO_V4L2_TPG
- help
- Enables a virtual video driver. This driver emulates a webcam,
- TV, S-Video and HDMI capture hardware, including VBI support for
- the SDTV inputs. Also video output, VBI output, radio receivers,
- transmitters and software defined radio capture is emulated.
-
- It is highly configurable and is ideal for testing applications.
- Error injection is supported to test rare errors that are hard
- to reproduce in real hardware.
-
- Say Y here if you want to test video apps or debug V4L devices.
- When in doubt, say N.
-
-config VIDEO_VIVID_CEC
- bool "Enable CEC emulation support"
- depends on VIDEO_VIVID
- select CEC_CORE
- help
- When selected the vivid module will emulate the optional
- HDMI CEC feature.
-
-config VIDEO_VIVID_MAX_DEVS
- int "Maximum number of devices"
- depends on VIDEO_VIVID
- default "64"
- help
- This allows you to specify the maximum number of devices supported
- by the vivid driver.
diff --git a/drivers/media/platform/vivid/Makefile b/drivers/media/platform/vivid/Makefile
deleted file mode 100644
index b12ad0152a3e..000000000000
--- a/drivers/media/platform/vivid/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-vivid-objs := vivid-core.o vivid-ctrls.o vivid-vid-common.o vivid-vbi-gen.o \
- vivid-vid-cap.o vivid-vid-out.o vivid-kthread-cap.o vivid-kthread-out.o \
- vivid-radio-rx.o vivid-radio-tx.o vivid-radio-common.o \
- vivid-rds-gen.o vivid-sdr-cap.o vivid-vbi-cap.o vivid-vbi-out.o \
- vivid-osd.o vivid-meta-cap.o vivid-meta-out.o \
- vivid-kthread-touch.o vivid-touch-cap.o
-ifeq ($(CONFIG_VIDEO_VIVID_CEC),y)
- vivid-objs += vivid-cec.o
-endif
-
-obj-$(CONFIG_VIDEO_VIVID) += vivid.o
diff --git a/drivers/media/platform/vivid/vivid-cec.c b/drivers/media/platform/vivid/vivid-cec.c
deleted file mode 100644
index 4d2413e87730..000000000000
--- a/drivers/media/platform/vivid/vivid-cec.c
+++ /dev/null
@@ -1,286 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-cec.c - A Virtual Video Test Driver, cec emulation
- *
- * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <media/cec.h>
-
-#include "vivid-core.h"
-#include "vivid-cec.h"
-
-#define CEC_TIM_START_BIT_TOTAL 4500
-#define CEC_TIM_START_BIT_LOW 3700
-#define CEC_TIM_START_BIT_HIGH 800
-#define CEC_TIM_DATA_BIT_TOTAL 2400
-#define CEC_TIM_DATA_BIT_0_LOW 1500
-#define CEC_TIM_DATA_BIT_0_HIGH 900
-#define CEC_TIM_DATA_BIT_1_LOW 600
-#define CEC_TIM_DATA_BIT_1_HIGH 1800
-
-void vivid_cec_bus_free_work(struct vivid_dev *dev)
-{
- spin_lock(&dev->cec_slock);
- while (!list_empty(&dev->cec_work_list)) {
- struct vivid_cec_work *cw =
- list_first_entry(&dev->cec_work_list,
- struct vivid_cec_work, list);
-
- spin_unlock(&dev->cec_slock);
- cancel_delayed_work_sync(&cw->work);
- spin_lock(&dev->cec_slock);
- list_del(&cw->list);
- cec_transmit_attempt_done(cw->adap, CEC_TX_STATUS_LOW_DRIVE);
- kfree(cw);
- }
- spin_unlock(&dev->cec_slock);
-}
-
-static bool vivid_cec_find_dest_adap(struct vivid_dev *dev,
- struct cec_adapter *adap, u8 dest)
-{
- unsigned int i;
-
- if (dest >= 0xf)
- return false;
-
- if (adap != dev->cec_rx_adap && dev->cec_rx_adap &&
- dev->cec_rx_adap->is_configured &&
- cec_has_log_addr(dev->cec_rx_adap, dest))
- return true;
-
- for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++) {
- if (adap == dev->cec_tx_adap[i])
- continue;
- if (!dev->cec_tx_adap[i]->is_configured)
- continue;
- if (cec_has_log_addr(dev->cec_tx_adap[i], dest))
- return true;
- }
- return false;
-}
-
-static void vivid_cec_pin_adap_events(struct cec_adapter *adap, ktime_t ts,
- const struct cec_msg *msg, bool nacked)
-{
- unsigned int len = nacked ? 1 : msg->len;
- unsigned int i;
- bool bit;
-
- if (adap == NULL)
- return;
-
- /*
- * Suffix ULL on constant 10 makes the expression
- * CEC_TIM_START_BIT_TOTAL + 10ULL * len * CEC_TIM_DATA_BIT_TOTAL
- * to be evaluated using 64-bit unsigned arithmetic (u64), which
- * is what ktime_sub_us expects as second argument.
- */
- ts = ktime_sub_us(ts, CEC_TIM_START_BIT_TOTAL +
- 10ULL * len * CEC_TIM_DATA_BIT_TOTAL);
- cec_queue_pin_cec_event(adap, false, false, ts);
- ts = ktime_add_us(ts, CEC_TIM_START_BIT_LOW);
- cec_queue_pin_cec_event(adap, true, false, ts);
- ts = ktime_add_us(ts, CEC_TIM_START_BIT_HIGH);
-
- for (i = 0; i < 10 * len; i++) {
- switch (i % 10) {
- case 0 ... 7:
- bit = msg->msg[i / 10] & (0x80 >> (i % 10));
- break;
- case 8: /* EOM */
- bit = i / 10 == msg->len - 1;
- break;
- case 9: /* ACK */
- bit = cec_msg_is_broadcast(msg) ^ nacked;
- break;
- }
- cec_queue_pin_cec_event(adap, false, false, ts);
- if (bit)
- ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_1_LOW);
- else
- ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_0_LOW);
- cec_queue_pin_cec_event(adap, true, false, ts);
- if (bit)
- ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_1_HIGH);
- else
- ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_0_HIGH);
- }
-}
-
-static void vivid_cec_pin_events(struct vivid_dev *dev,
- const struct cec_msg *msg, bool nacked)
-{
- ktime_t ts = ktime_get();
- unsigned int i;
-
- vivid_cec_pin_adap_events(dev->cec_rx_adap, ts, msg, nacked);
- for (i = 0; i < MAX_OUTPUTS; i++)
- vivid_cec_pin_adap_events(dev->cec_tx_adap[i], ts, msg, nacked);
-}
-
-static void vivid_cec_xfer_done_worker(struct work_struct *work)
-{
- struct vivid_cec_work *cw =
- container_of(work, struct vivid_cec_work, work.work);
- struct vivid_dev *dev = cw->dev;
- struct cec_adapter *adap = cw->adap;
- u8 dest = cec_msg_destination(&cw->msg);
- bool valid_dest;
- unsigned int i;
-
- valid_dest = cec_msg_is_broadcast(&cw->msg);
- if (!valid_dest)
- valid_dest = vivid_cec_find_dest_adap(dev, adap, dest);
-
- cw->tx_status = valid_dest ? CEC_TX_STATUS_OK : CEC_TX_STATUS_NACK;
- spin_lock(&dev->cec_slock);
- dev->cec_xfer_time_jiffies = 0;
- dev->cec_xfer_start_jiffies = 0;
- list_del(&cw->list);
- spin_unlock(&dev->cec_slock);
- vivid_cec_pin_events(dev, &cw->msg, !valid_dest);
- cec_transmit_attempt_done(cw->adap, cw->tx_status);
-
- /* Broadcast message */
- if (adap != dev->cec_rx_adap)
- cec_received_msg(dev->cec_rx_adap, &cw->msg);
- for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
- if (adap != dev->cec_tx_adap[i])
- cec_received_msg(dev->cec_tx_adap[i], &cw->msg);
- kfree(cw);
-}
-
-static void vivid_cec_xfer_try_worker(struct work_struct *work)
-{
- struct vivid_cec_work *cw =
- container_of(work, struct vivid_cec_work, work.work);
- struct vivid_dev *dev = cw->dev;
-
- spin_lock(&dev->cec_slock);
- if (dev->cec_xfer_time_jiffies) {
- list_del(&cw->list);
- spin_unlock(&dev->cec_slock);
- cec_transmit_attempt_done(cw->adap, CEC_TX_STATUS_ARB_LOST);
- kfree(cw);
- } else {
- INIT_DELAYED_WORK(&cw->work, vivid_cec_xfer_done_worker);
- dev->cec_xfer_start_jiffies = jiffies;
- dev->cec_xfer_time_jiffies = usecs_to_jiffies(cw->usecs);
- spin_unlock(&dev->cec_slock);
- schedule_delayed_work(&cw->work, dev->cec_xfer_time_jiffies);
- }
-}
-
-static int vivid_cec_adap_enable(struct cec_adapter *adap, bool enable)
-{
- adap->cec_pin_is_high = true;
- return 0;
-}
-
-static int vivid_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
-{
- return 0;
-}
-
-/*
- * One data bit takes 2400 us, each byte needs 10 bits so that's 24000 us
- * per byte.
- */
-#define USECS_PER_BYTE 24000
-
-static int vivid_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
- u32 signal_free_time, struct cec_msg *msg)
-{
- struct vivid_dev *dev = cec_get_drvdata(adap);
- struct vivid_cec_work *cw = kzalloc(sizeof(*cw), GFP_KERNEL);
- long delta_jiffies = 0;
-
- if (cw == NULL)
- return -ENOMEM;
- cw->dev = dev;
- cw->adap = adap;
- cw->usecs = CEC_FREE_TIME_TO_USEC(signal_free_time) +
- msg->len * USECS_PER_BYTE;
- cw->msg = *msg;
-
- spin_lock(&dev->cec_slock);
- list_add(&cw->list, &dev->cec_work_list);
- if (dev->cec_xfer_time_jiffies == 0) {
- INIT_DELAYED_WORK(&cw->work, vivid_cec_xfer_done_worker);
- dev->cec_xfer_start_jiffies = jiffies;
- dev->cec_xfer_time_jiffies = usecs_to_jiffies(cw->usecs);
- delta_jiffies = dev->cec_xfer_time_jiffies;
- } else {
- INIT_DELAYED_WORK(&cw->work, vivid_cec_xfer_try_worker);
- delta_jiffies = dev->cec_xfer_start_jiffies +
- dev->cec_xfer_time_jiffies - jiffies;
- }
- spin_unlock(&dev->cec_slock);
- schedule_delayed_work(&cw->work, delta_jiffies < 0 ? 0 : delta_jiffies);
- return 0;
-}
-
-static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg)
-{
- struct vivid_dev *dev = cec_get_drvdata(adap);
- struct cec_msg reply;
- u8 dest = cec_msg_destination(msg);
- u8 disp_ctl;
- char osd[14];
-
- if (cec_msg_is_broadcast(msg))
- dest = adap->log_addrs.log_addr[0];
- cec_msg_init(&reply, dest, cec_msg_initiator(msg));
-
- switch (cec_msg_opcode(msg)) {
- case CEC_MSG_SET_OSD_STRING:
- if (!cec_is_sink(adap))
- return -ENOMSG;
- cec_ops_set_osd_string(msg, &disp_ctl, osd);
- switch (disp_ctl) {
- case CEC_OP_DISP_CTL_DEFAULT:
- strscpy(dev->osd, osd, sizeof(dev->osd));
- dev->osd_jiffies = jiffies;
- break;
- case CEC_OP_DISP_CTL_UNTIL_CLEARED:
- strscpy(dev->osd, osd, sizeof(dev->osd));
- dev->osd_jiffies = 0;
- break;
- case CEC_OP_DISP_CTL_CLEAR:
- dev->osd[0] = 0;
- dev->osd_jiffies = 0;
- break;
- default:
- cec_msg_feature_abort(&reply, cec_msg_opcode(msg),
- CEC_OP_ABORT_INVALID_OP);
- cec_transmit_msg(adap, &reply, false);
- break;
- }
- break;
- default:
- return -ENOMSG;
- }
- return 0;
-}
-
-static const struct cec_adap_ops vivid_cec_adap_ops = {
- .adap_enable = vivid_cec_adap_enable,
- .adap_log_addr = vivid_cec_adap_log_addr,
- .adap_transmit = vivid_cec_adap_transmit,
- .received = vivid_received,
-};
-
-struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
- unsigned int idx,
- bool is_source)
-{
- u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN;
- char name[32];
-
- snprintf(name, sizeof(name), "vivid-%03d-vid-%s%d",
- dev->inst, is_source ? "out" : "cap", idx);
- return cec_allocate_adapter(&vivid_cec_adap_ops, dev,
- name, caps, 1);
-}
diff --git a/drivers/media/platform/vivid/vivid-cec.h b/drivers/media/platform/vivid/vivid-cec.h
deleted file mode 100644
index 7524ed48a914..000000000000
--- a/drivers/media/platform/vivid/vivid-cec.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-cec.h - A Virtual Video Test Driver, cec emulation
- *
- * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifdef CONFIG_VIDEO_VIVID_CEC
-struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
- unsigned int idx,
- bool is_source);
-void vivid_cec_bus_free_work(struct vivid_dev *dev);
-
-#else
-
-static inline void vivid_cec_bus_free_work(struct vivid_dev *dev)
-{
-}
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
deleted file mode 100644
index 6c740e3e6999..000000000000
--- a/drivers/media/platform/vivid/vivid-core.c
+++ /dev/null
@@ -1,2006 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-core.c - A Virtual Video Test Driver, core initialization
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/font.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/videodev2.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/videobuf2-vmalloc.h>
-#include <media/videobuf2-dma-contig.h>
-#include <media/v4l2-dv-timings.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-
-#include "vivid-core.h"
-#include "vivid-vid-common.h"
-#include "vivid-vid-cap.h"
-#include "vivid-vid-out.h"
-#include "vivid-radio-common.h"
-#include "vivid-radio-rx.h"
-#include "vivid-radio-tx.h"
-#include "vivid-sdr-cap.h"
-#include "vivid-vbi-cap.h"
-#include "vivid-vbi-out.h"
-#include "vivid-osd.h"
-#include "vivid-cec.h"
-#include "vivid-ctrls.h"
-#include "vivid-meta-cap.h"
-#include "vivid-meta-out.h"
-#include "vivid-touch-cap.h"
-
-#define VIVID_MODULE_NAME "vivid"
-
-/* The maximum number of vivid devices */
-#define VIVID_MAX_DEVS CONFIG_VIDEO_VIVID_MAX_DEVS
-
-MODULE_DESCRIPTION("Virtual Video Test Driver");
-MODULE_AUTHOR("Hans Verkuil");
-MODULE_LICENSE("GPL");
-
-static unsigned n_devs = 1;
-module_param(n_devs, uint, 0444);
-MODULE_PARM_DESC(n_devs, " number of driver instances to create");
-
-static int vid_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(vid_cap_nr, int, NULL, 0444);
-MODULE_PARM_DESC(vid_cap_nr, " videoX start number, -1 is autodetect");
-
-static int vid_out_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(vid_out_nr, int, NULL, 0444);
-MODULE_PARM_DESC(vid_out_nr, " videoX start number, -1 is autodetect");
-
-static int vbi_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(vbi_cap_nr, int, NULL, 0444);
-MODULE_PARM_DESC(vbi_cap_nr, " vbiX start number, -1 is autodetect");
-
-static int vbi_out_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(vbi_out_nr, int, NULL, 0444);
-MODULE_PARM_DESC(vbi_out_nr, " vbiX start number, -1 is autodetect");
-
-static int sdr_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(sdr_cap_nr, int, NULL, 0444);
-MODULE_PARM_DESC(sdr_cap_nr, " swradioX start number, -1 is autodetect");
-
-static int radio_rx_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(radio_rx_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_rx_nr, " radioX start number, -1 is autodetect");
-
-static int radio_tx_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(radio_tx_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_tx_nr, " radioX start number, -1 is autodetect");
-
-static int meta_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(meta_cap_nr, int, NULL, 0444);
-MODULE_PARM_DESC(meta_cap_nr, " videoX start number, -1 is autodetect");
-
-static int meta_out_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(meta_out_nr, int, NULL, 0444);
-MODULE_PARM_DESC(meta_out_nr, " videoX start number, -1 is autodetect");
-
-static int touch_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(touch_cap_nr, int, NULL, 0444);
-MODULE_PARM_DESC(touch_cap_nr, " v4l-touchX start number, -1 is autodetect");
-
-static int ccs_cap_mode[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(ccs_cap_mode, int, NULL, 0444);
-MODULE_PARM_DESC(ccs_cap_mode, " capture crop/compose/scale mode:\n"
- "\t\t bit 0=crop, 1=compose, 2=scale,\n"
- "\t\t -1=user-controlled (default)");
-
-static int ccs_out_mode[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 };
-module_param_array(ccs_out_mode, int, NULL, 0444);
-MODULE_PARM_DESC(ccs_out_mode, " output crop/compose/scale mode:\n"
- "\t\t bit 0=crop, 1=compose, 2=scale,\n"
- "\t\t -1=user-controlled (default)");
-
-static unsigned multiplanar[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 1 };
-module_param_array(multiplanar, uint, NULL, 0444);
-MODULE_PARM_DESC(multiplanar, " 1 (default) creates a single planar device, 2 creates a multiplanar device.");
-
-/*
- * Default: video + vbi-cap (raw and sliced) + radio rx + radio tx + sdr +
- * vbi-out + vid-out + meta-cap
- */
-static unsigned int node_types[VIVID_MAX_DEVS] = {
- [0 ... (VIVID_MAX_DEVS - 1)] = 0xe1d3d
-};
-module_param_array(node_types, uint, NULL, 0444);
-MODULE_PARM_DESC(node_types, " node types, default is 0xe1d3d. Bitmask with the following meaning:\n"
- "\t\t bit 0: Video Capture node\n"
- "\t\t bit 2-3: VBI Capture node: 0 = none, 1 = raw vbi, 2 = sliced vbi, 3 = both\n"
- "\t\t bit 4: Radio Receiver node\n"
- "\t\t bit 5: Software Defined Radio Receiver node\n"
- "\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 17: Metadata Capture node\n"
- "\t\t bit 18: Metadata Output node\n"
- "\t\t bit 19: Touch Capture node\n");
-
-/* Default: 4 inputs */
-static unsigned num_inputs[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 4 };
-module_param_array(num_inputs, uint, NULL, 0444);
-MODULE_PARM_DESC(num_inputs, " number of inputs, default is 4");
-
-/* Default: input 0 = WEBCAM, 1 = TV, 2 = SVID, 3 = HDMI */
-static unsigned input_types[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 0xe4 };
-module_param_array(input_types, uint, NULL, 0444);
-MODULE_PARM_DESC(input_types, " input types, default is 0xe4. Two bits per input,\n"
- "\t\t bits 0-1 == input 0, bits 31-30 == input 15.\n"
- "\t\t Type 0 == webcam, 1 == TV, 2 == S-Video, 3 == HDMI");
-
-/* Default: 2 outputs */
-static unsigned num_outputs[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 2 };
-module_param_array(num_outputs, uint, NULL, 0444);
-MODULE_PARM_DESC(num_outputs, " number of outputs, default is 2");
-
-/* Default: output 0 = SVID, 1 = HDMI */
-static unsigned output_types[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 2 };
-module_param_array(output_types, uint, NULL, 0444);
-MODULE_PARM_DESC(output_types, " output types, default is 0x02. One bit per output,\n"
- "\t\t bit 0 == output 0, bit 15 == output 15.\n"
- "\t\t Type 0 == S-Video, 1 == HDMI");
-
-unsigned vivid_debug;
-module_param(vivid_debug, uint, 0644);
-MODULE_PARM_DESC(vivid_debug, " activates debug info");
-
-static bool no_error_inj;
-module_param(no_error_inj, bool, 0444);
-MODULE_PARM_DESC(no_error_inj, " if set disable the error injecting controls");
-
-static unsigned int allocators[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 0 };
-module_param_array(allocators, uint, NULL, 0444);
-MODULE_PARM_DESC(allocators, " memory allocator selection, default is 0.\n"
- "\t\t 0 == vmalloc\n"
- "\t\t 1 == dma-contig");
-
-static struct vivid_dev *vivid_devs[VIVID_MAX_DEVS];
-
-const struct v4l2_rect vivid_min_rect = {
- 0, 0, MIN_WIDTH, MIN_HEIGHT
-};
-
-const struct v4l2_rect vivid_max_rect = {
- 0, 0, MAX_WIDTH * MAX_ZOOM, MAX_HEIGHT * MAX_ZOOM
-};
-
-static const u8 vivid_hdmi_edid[256] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x31, 0xd8, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00,
- 0x22, 0x1a, 0x01, 0x03, 0x80, 0x60, 0x36, 0x78,
- 0x0f, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
- 0x0f, 0x50, 0x54, 0x2f, 0xcf, 0x00, 0x31, 0x59,
- 0x45, 0x59, 0x81, 0x80, 0x81, 0x40, 0x90, 0x40,
- 0x95, 0x00, 0xa9, 0x40, 0xb3, 0x00, 0x08, 0xe8,
- 0x00, 0x30, 0xf2, 0x70, 0x5a, 0x80, 0xb0, 0x58,
- 0x8a, 0x00, 0xc0, 0x1c, 0x32, 0x00, 0x00, 0x1e,
- 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x55, 0x18,
- 0x87, 0x3c, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x76,
- 0x69, 0x76, 0x69, 0x64, 0x0a, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7b,
-
- 0x02, 0x03, 0x3f, 0xf0, 0x51, 0x61, 0x60, 0x5f,
- 0x5e, 0x5d, 0x10, 0x1f, 0x04, 0x13, 0x22, 0x21,
- 0x20, 0x05, 0x14, 0x02, 0x11, 0x01, 0x23, 0x09,
- 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x6d, 0x03,
- 0x0c, 0x00, 0x10, 0x00, 0x00, 0x3c, 0x21, 0x00,
- 0x60, 0x01, 0x02, 0x03, 0x67, 0xd8, 0x5d, 0xc4,
- 0x01, 0x78, 0x00, 0x00, 0xe2, 0x00, 0xea, 0xe3,
- 0x05, 0x00, 0x00, 0xe3, 0x06, 0x01, 0x00, 0x4d,
- 0xd0, 0x00, 0xa0, 0xf0, 0x70, 0x3e, 0x80, 0x30,
- 0x20, 0x35, 0x00, 0xc0, 0x1c, 0x32, 0x00, 0x00,
- 0x1e, 0x1a, 0x36, 0x80, 0xa0, 0x70, 0x38, 0x1f,
- 0x40, 0x30, 0x20, 0x35, 0x00, 0xc0, 0x1c, 0x32,
- 0x00, 0x00, 0x1a, 0x1a, 0x1d, 0x00, 0x80, 0x51,
- 0xd0, 0x1c, 0x20, 0x40, 0x80, 0x35, 0x00, 0xc0,
- 0x1c, 0x32, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63,
-};
-
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- strscpy(cap->driver, "vivid", sizeof(cap->driver));
- strscpy(cap->card, "vivid", sizeof(cap->card));
- snprintf(cap->bus_info, sizeof(cap->bus_info),
- "platform:%s", dev->v4l2_dev.name);
-
- cap->capabilities = dev->vid_cap_caps | dev->vid_out_caps |
- dev->vbi_cap_caps | dev->vbi_out_caps |
- dev->radio_rx_caps | dev->radio_tx_caps |
- dev->sdr_cap_caps | dev->meta_cap_caps |
- dev->meta_out_caps | dev->touch_cap_caps |
- V4L2_CAP_DEVICE_CAPS;
- return 0;
-}
-
-static int vidioc_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2_hw_freq_seek *a)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_RADIO)
- return vivid_radio_rx_s_hw_freq_seek(file, fh, a);
- return -ENOTTY;
-}
-
-static int vidioc_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_RADIO)
- return vivid_radio_rx_enum_freq_bands(file, fh, band);
- if (vdev->vfl_type == VFL_TYPE_SDR)
- return vivid_sdr_enum_freq_bands(file, fh, band);
- return -ENOTTY;
-}
-
-static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_RADIO)
- return vivid_radio_rx_g_tuner(file, fh, vt);
- if (vdev->vfl_type == VFL_TYPE_SDR)
- return vivid_sdr_g_tuner(file, fh, vt);
- return vivid_video_g_tuner(file, fh, vt);
-}
-
-static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_RADIO)
- return vivid_radio_rx_s_tuner(file, fh, vt);
- if (vdev->vfl_type == VFL_TYPE_SDR)
- return vivid_sdr_s_tuner(file, fh, vt);
- return vivid_video_s_tuner(file, fh, vt);
-}
-
-static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_RADIO)
- return vivid_radio_g_frequency(file,
- vdev->vfl_dir == VFL_DIR_RX ?
- &dev->radio_rx_freq : &dev->radio_tx_freq, vf);
- if (vdev->vfl_type == VFL_TYPE_SDR)
- return vivid_sdr_g_frequency(file, fh, vf);
- return vivid_video_g_frequency(file, fh, vf);
-}
-
-static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_RADIO)
- return vivid_radio_s_frequency(file,
- vdev->vfl_dir == VFL_DIR_RX ?
- &dev->radio_rx_freq : &dev->radio_tx_freq, vf);
- if (vdev->vfl_type == VFL_TYPE_SDR)
- return vivid_sdr_s_frequency(file, fh, vf);
- return vivid_video_s_frequency(file, fh, vf);
-}
-
-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 vivid_vid_out_overlay(file, fh, i);
-}
-
-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 vivid_vid_out_g_fbuf(file, fh, a);
-}
-
-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 vivid_vid_out_s_fbuf(file, fh, a);
-}
-
-static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX)
- return vivid_vid_cap_s_std(file, fh, id);
- return vivid_vid_out_s_std(file, fh, id);
-}
-
-static int vidioc_s_dv_timings(struct file *file, void *fh, struct v4l2_dv_timings *timings)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX)
- return vivid_vid_cap_s_dv_timings(file, fh, timings);
- return vivid_vid_out_s_dv_timings(file, fh, timings);
-}
-
-static int vidioc_g_pixelaspect(struct file *file, void *fh,
- int type, struct v4l2_fract *f)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX)
- return vivid_vid_cap_g_pixelaspect(file, fh, type, f);
- return vivid_vid_out_g_pixelaspect(file, fh, type, f);
-}
-
-static int vidioc_g_selection(struct file *file, void *fh,
- struct v4l2_selection *sel)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX)
- return vivid_vid_cap_g_selection(file, fh, sel);
- return vivid_vid_out_g_selection(file, fh, sel);
-}
-
-static int vidioc_s_selection(struct file *file, void *fh,
- struct v4l2_selection *sel)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX)
- return vivid_vid_cap_s_selection(file, fh, sel);
- return vivid_vid_out_s_selection(file, fh, sel);
-}
-
-static int vidioc_g_parm(struct file *file, void *fh,
- struct v4l2_streamparm *parm)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_g_parm_tch(file, fh, parm);
- if (vdev->vfl_dir == VFL_DIR_RX)
- return vivid_vid_cap_g_parm(file, fh, parm);
- return vivid_vid_out_g_parm(file, fh, parm);
-}
-
-static int vidioc_s_parm(struct file *file, void *fh,
- struct v4l2_streamparm *parm)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX)
- return vivid_vid_cap_s_parm(file, fh, parm);
- return -ENOTTY;
-}
-
-static int vidioc_log_status(struct file *file, void *fh)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
-
- v4l2_ctrl_log_status(file, fh);
- if (vdev->vfl_dir == VFL_DIR_RX && vdev->vfl_type == VFL_TYPE_VIDEO)
- tpg_log_status(&dev->tpg);
- return 0;
-}
-
-static ssize_t vivid_radio_read(struct file *file, char __user *buf,
- size_t size, loff_t *offset)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_TX)
- return -EINVAL;
- return vivid_radio_rx_read(file, buf, size, offset);
-}
-
-static ssize_t vivid_radio_write(struct file *file, const char __user *buf,
- size_t size, loff_t *offset)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX)
- return -EINVAL;
- return vivid_radio_tx_write(file, buf, size, offset);
-}
-
-static __poll_t vivid_radio_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX)
- return vivid_radio_rx_poll(file, wait);
- return vivid_radio_tx_poll(file, wait);
-}
-
-static int vivid_enum_input(struct file *file, void *priv,
- struct v4l2_input *inp)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_enum_input_tch(file, priv, inp);
- return vidioc_enum_input(file, priv, inp);
-}
-
-static int vivid_g_input(struct file *file, void *priv, unsigned int *i)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_g_input_tch(file, priv, i);
- return vidioc_g_input(file, priv, i);
-}
-
-static int vivid_s_input(struct file *file, void *priv, unsigned int i)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_s_input_tch(file, priv, i);
- return vidioc_s_input(file, priv, i);
-}
-
-static int vivid_enum_fmt_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_enum_fmt_tch(file, priv, f);
- return vivid_enum_fmt_vid(file, priv, f);
-}
-
-static int vivid_g_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_g_fmt_tch(file, priv, f);
- return vidioc_g_fmt_vid_cap(file, priv, f);
-}
-
-static int vivid_try_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_g_fmt_tch(file, priv, f);
- return vidioc_try_fmt_vid_cap(file, priv, f);
-}
-
-static int vivid_s_fmt_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_g_fmt_tch(file, priv, f);
- return vidioc_s_fmt_vid_cap(file, priv, f);
-}
-
-static int vivid_g_fmt_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_g_fmt_tch_mplane(file, priv, f);
- return vidioc_g_fmt_vid_cap_mplane(file, priv, f);
-}
-
-static int vivid_try_fmt_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_g_fmt_tch_mplane(file, priv, f);
- return vidioc_try_fmt_vid_cap_mplane(file, priv, f);
-}
-
-static int vivid_s_fmt_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_TOUCH)
- return vivid_g_fmt_tch_mplane(file, priv, f);
- return vidioc_s_fmt_vid_cap_mplane(file, priv, f);
-}
-
-static bool vivid_is_in_use(struct video_device *vdev)
-{
- unsigned long flags;
- bool res;
-
- spin_lock_irqsave(&vdev->fh_lock, flags);
- res = !list_empty(&vdev->fh_list);
- spin_unlock_irqrestore(&vdev->fh_lock, flags);
- return res;
-}
-
-static bool vivid_is_last_user(struct vivid_dev *dev)
-{
- unsigned uses = vivid_is_in_use(&dev->vid_cap_dev) +
- vivid_is_in_use(&dev->vid_out_dev) +
- vivid_is_in_use(&dev->vbi_cap_dev) +
- vivid_is_in_use(&dev->vbi_out_dev) +
- vivid_is_in_use(&dev->sdr_cap_dev) +
- vivid_is_in_use(&dev->radio_rx_dev) +
- vivid_is_in_use(&dev->radio_tx_dev) +
- vivid_is_in_use(&dev->meta_cap_dev) +
- vivid_is_in_use(&dev->meta_out_dev) +
- vivid_is_in_use(&dev->touch_cap_dev);
-
- return uses == 1;
-}
-
-static int vivid_fop_release(struct file *file)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
-
- mutex_lock(&dev->mutex);
- if (!no_error_inj && v4l2_fh_is_singular_file(file) &&
- !video_is_registered(vdev) && vivid_is_last_user(dev)) {
- /*
- * I am the last user of this driver, and a disconnect
- * was forced (since this video_device is unregistered),
- * so re-register all video_device's again.
- */
- v4l2_info(&dev->v4l2_dev, "reconnect\n");
- set_bit(V4L2_FL_REGISTERED, &dev->vid_cap_dev.flags);
- set_bit(V4L2_FL_REGISTERED, &dev->vid_out_dev.flags);
- set_bit(V4L2_FL_REGISTERED, &dev->vbi_cap_dev.flags);
- set_bit(V4L2_FL_REGISTERED, &dev->vbi_out_dev.flags);
- set_bit(V4L2_FL_REGISTERED, &dev->sdr_cap_dev.flags);
- set_bit(V4L2_FL_REGISTERED, &dev->radio_rx_dev.flags);
- set_bit(V4L2_FL_REGISTERED, &dev->radio_tx_dev.flags);
- set_bit(V4L2_FL_REGISTERED, &dev->meta_cap_dev.flags);
- set_bit(V4L2_FL_REGISTERED, &dev->meta_out_dev.flags);
- set_bit(V4L2_FL_REGISTERED, &dev->touch_cap_dev.flags);
- }
- 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;
- }
- if (file->private_data == dev->radio_tx_rds_owner) {
- dev->radio_tx_rds_last_block = 0;
- dev->radio_tx_rds_owner = NULL;
- }
- if (vdev->queue)
- return vb2_fop_release(file);
- return v4l2_fh_release(file);
-}
-
-static const struct v4l2_file_operations vivid_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = vivid_fop_release,
- .read = vb2_fop_read,
- .write = vb2_fop_write,
- .poll = vb2_fop_poll,
- .unlocked_ioctl = video_ioctl2,
- .mmap = vb2_fop_mmap,
-};
-
-static const struct v4l2_file_operations vivid_radio_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = vivid_fop_release,
- .read = vivid_radio_read,
- .write = vivid_radio_write,
- .poll = vivid_radio_poll,
- .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops vivid_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
-
- .vidioc_enum_fmt_vid_cap = vivid_enum_fmt_cap,
- .vidioc_g_fmt_vid_cap = vivid_g_fmt_cap,
- .vidioc_try_fmt_vid_cap = vivid_try_fmt_cap,
- .vidioc_s_fmt_vid_cap = vivid_s_fmt_cap,
- .vidioc_g_fmt_vid_cap_mplane = vivid_g_fmt_cap_mplane,
- .vidioc_try_fmt_vid_cap_mplane = vivid_try_fmt_cap_mplane,
- .vidioc_s_fmt_vid_cap_mplane = vivid_s_fmt_cap_mplane,
-
- .vidioc_enum_fmt_vid_out = vivid_enum_fmt_vid,
- .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
- .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
- .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
- .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out_mplane,
- .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out_mplane,
- .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out_mplane,
-
- .vidioc_g_selection = vidioc_g_selection,
- .vidioc_s_selection = vidioc_s_selection,
- .vidioc_g_pixelaspect = vidioc_g_pixelaspect,
-
- .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
- .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
- .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
-
- .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap,
- .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_fmt_sliced_vbi_cap,
- .vidioc_s_fmt_sliced_vbi_cap = vidioc_s_fmt_sliced_vbi_cap,
- .vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap,
-
- .vidioc_g_fmt_vbi_out = vidioc_g_fmt_vbi_out,
- .vidioc_try_fmt_vbi_out = vidioc_g_fmt_vbi_out,
- .vidioc_s_fmt_vbi_out = vidioc_s_fmt_vbi_out,
-
- .vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out,
- .vidioc_try_fmt_sliced_vbi_out = vidioc_try_fmt_sliced_vbi_out,
- .vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out,
-
- .vidioc_enum_fmt_sdr_cap = vidioc_enum_fmt_sdr_cap,
- .vidioc_g_fmt_sdr_cap = vidioc_g_fmt_sdr_cap,
- .vidioc_try_fmt_sdr_cap = vidioc_try_fmt_sdr_cap,
- .vidioc_s_fmt_sdr_cap = vidioc_s_fmt_sdr_cap,
-
- .vidioc_overlay = vidioc_overlay,
- .vidioc_enum_framesizes = vidioc_enum_framesizes,
- .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
- .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,
- .vidioc_g_fbuf = vidioc_g_fbuf,
- .vidioc_s_fbuf = vidioc_s_fbuf,
-
- .vidioc_reqbufs = vb2_ioctl_reqbufs,
- .vidioc_create_bufs = vb2_ioctl_create_bufs,
- .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
- .vidioc_querybuf = vb2_ioctl_querybuf,
- .vidioc_qbuf = vb2_ioctl_qbuf,
- .vidioc_dqbuf = vb2_ioctl_dqbuf,
- .vidioc_expbuf = vb2_ioctl_expbuf,
- .vidioc_streamon = vb2_ioctl_streamon,
- .vidioc_streamoff = vb2_ioctl_streamoff,
-
- .vidioc_enum_input = vivid_enum_input,
- .vidioc_g_input = vivid_g_input,
- .vidioc_s_input = vivid_s_input,
- .vidioc_s_audio = vidioc_s_audio,
- .vidioc_g_audio = vidioc_g_audio,
- .vidioc_enumaudio = vidioc_enumaudio,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_g_frequency = vidioc_g_frequency,
- .vidioc_s_tuner = vidioc_s_tuner,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_modulator = vidioc_s_modulator,
- .vidioc_g_modulator = vidioc_g_modulator,
- .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek,
- .vidioc_enum_freq_bands = vidioc_enum_freq_bands,
-
- .vidioc_enum_output = vidioc_enum_output,
- .vidioc_g_output = vidioc_g_output,
- .vidioc_s_output = vidioc_s_output,
- .vidioc_s_audout = vidioc_s_audout,
- .vidioc_g_audout = vidioc_g_audout,
- .vidioc_enumaudout = vidioc_enumaudout,
-
- .vidioc_querystd = vidioc_querystd,
- .vidioc_g_std = vidioc_g_std,
- .vidioc_s_std = vidioc_s_std,
- .vidioc_s_dv_timings = vidioc_s_dv_timings,
- .vidioc_g_dv_timings = vidioc_g_dv_timings,
- .vidioc_query_dv_timings = vidioc_query_dv_timings,
- .vidioc_enum_dv_timings = vidioc_enum_dv_timings,
- .vidioc_dv_timings_cap = vidioc_dv_timings_cap,
- .vidioc_g_edid = vidioc_g_edid,
- .vidioc_s_edid = vidioc_s_edid,
-
- .vidioc_log_status = vidioc_log_status,
- .vidioc_subscribe_event = vidioc_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-
- .vidioc_enum_fmt_meta_cap = vidioc_enum_fmt_meta_cap,
- .vidioc_g_fmt_meta_cap = vidioc_g_fmt_meta_cap,
- .vidioc_s_fmt_meta_cap = vidioc_g_fmt_meta_cap,
- .vidioc_try_fmt_meta_cap = vidioc_g_fmt_meta_cap,
-
- .vidioc_enum_fmt_meta_out = vidioc_enum_fmt_meta_out,
- .vidioc_g_fmt_meta_out = vidioc_g_fmt_meta_out,
- .vidioc_s_fmt_meta_out = vidioc_g_fmt_meta_out,
- .vidioc_try_fmt_meta_out = vidioc_g_fmt_meta_out,
-};
-
-/* -----------------------------------------------------------------
- Initialization and module stuff
- ------------------------------------------------------------------*/
-
-static void vivid_dev_release(struct v4l2_device *v4l2_dev)
-{
- struct vivid_dev *dev = container_of(v4l2_dev, struct vivid_dev, v4l2_dev);
-
- vivid_free_controls(dev);
- v4l2_device_unregister(&dev->v4l2_dev);
-#ifdef CONFIG_MEDIA_CONTROLLER
- media_device_cleanup(&dev->mdev);
-#endif
- 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);
- kfree(dev);
-}
-
-#ifdef CONFIG_MEDIA_CONTROLLER
-static int vivid_req_validate(struct media_request *req)
-{
- struct vivid_dev *dev = container_of(req->mdev, struct vivid_dev, mdev);
-
- if (dev->req_validate_error) {
- dev->req_validate_error = false;
- return -EINVAL;
- }
- return vb2_request_validate(req);
-}
-
-static const struct media_device_ops vivid_media_ops = {
- .req_validate = vivid_req_validate,
- .req_queue = vb2_request_queue,
-};
-#endif
-
-static int vivid_create_queue(struct vivid_dev *dev,
- struct vb2_queue *q,
- u32 buf_type,
- unsigned int min_buffers_needed,
- const struct vb2_ops *ops)
-{
- if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->multiplanar)
- buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- else if (buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT && dev->multiplanar)
- buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- else if (buf_type == V4L2_BUF_TYPE_VBI_CAPTURE && !dev->has_raw_vbi_cap)
- buf_type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
- else if (buf_type == V4L2_BUF_TYPE_VBI_OUTPUT && !dev->has_raw_vbi_out)
- buf_type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
-
- q->type = buf_type;
- q->io_modes = VB2_MMAP | VB2_DMABUF;
- q->io_modes |= V4L2_TYPE_IS_OUTPUT(buf_type) ? VB2_WRITE : VB2_READ;
- if (allocators[dev->inst] != 1)
- q->io_modes |= VB2_USERPTR;
- q->drv_priv = dev;
- q->buf_struct_size = sizeof(struct vivid_buffer);
- q->ops = ops;
- q->mem_ops = allocators[dev->inst] == 1 ? &vb2_dma_contig_memops :
- &vb2_vmalloc_memops;
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->min_buffers_needed = min_buffers_needed;
- q->lock = &dev->mutex;
- q->dev = dev->v4l2_dev.dev;
- q->supports_requests = true;
-
- return vb2_queue_init(q);
-}
-
-static int vivid_create_instance(struct platform_device *pdev, int inst)
-{
- static const struct v4l2_dv_timings def_dv_timings =
- V4L2_DV_BT_CEA_1280X720P60;
- unsigned in_type_counter[4] = { 0, 0, 0, 0 };
- unsigned out_type_counter[4] = { 0, 0, 0, 0 };
- int ccs_cap = ccs_cap_mode[inst];
- int ccs_out = ccs_out_mode[inst];
- bool has_tuner;
- bool has_modulator;
- struct vivid_dev *dev;
- struct video_device *vfd;
- unsigned node_type = node_types[inst];
- v4l2_std_id tvnorms_cap = 0, tvnorms_out = 0;
- int ret;
- int i;
-#ifdef CONFIG_VIDEO_VIVID_CEC
- unsigned int cec_tx_bus_cnt = 0;
-#endif
-
- /* allocate main vivid state structure */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
-
- dev->inst = inst;
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->v4l2_dev.mdev = &dev->mdev;
-
- /* Initialize media device */
- strscpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
- snprintf(dev->mdev.bus_info, sizeof(dev->mdev.bus_info),
- "platform:%s-%03d", VIVID_MODULE_NAME, inst);
- dev->mdev.dev = &pdev->dev;
- media_device_init(&dev->mdev);
- dev->mdev.ops = &vivid_media_ops;
-#endif
-
- /* register v4l2_device */
- snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
- "%s-%03d", VIVID_MODULE_NAME, inst);
- ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
- if (ret) {
- kfree(dev);
- return ret;
- }
- dev->v4l2_dev.release = vivid_dev_release;
-
- /* start detecting feature set */
-
- /* do we use single- or multi-planar? */
- dev->multiplanar = multiplanar[inst] > 1;
- v4l2_info(&dev->v4l2_dev, "using %splanar format API\n",
- dev->multiplanar ? "multi" : "single ");
-
- /* how many inputs do we have and of what type? */
- dev->num_inputs = num_inputs[inst];
- if (dev->num_inputs < 1)
- dev->num_inputs = 1;
- if (dev->num_inputs >= MAX_INPUTS)
- dev->num_inputs = MAX_INPUTS;
- for (i = 0; i < dev->num_inputs; i++) {
- dev->input_type[i] = (input_types[inst] >> (i * 2)) & 0x3;
- dev->input_name_counter[i] = in_type_counter[dev->input_type[i]]++;
- }
- dev->has_audio_inputs = in_type_counter[TV] && in_type_counter[SVID];
- if (in_type_counter[HDMI] == 16) {
- /* The CEC physical address only allows for max 15 inputs */
- in_type_counter[HDMI]--;
- dev->num_inputs--;
- }
- dev->num_hdmi_inputs = in_type_counter[HDMI];
-
- /* how many outputs do we have and of what type? */
- dev->num_outputs = num_outputs[inst];
- if (dev->num_outputs < 1)
- dev->num_outputs = 1;
- if (dev->num_outputs >= MAX_OUTPUTS)
- dev->num_outputs = MAX_OUTPUTS;
- for (i = 0; i < dev->num_outputs; i++) {
- dev->output_type[i] = ((output_types[inst] >> i) & 1) ? HDMI : SVID;
- dev->output_name_counter[i] = out_type_counter[dev->output_type[i]]++;
- dev->display_present[i] = true;
- }
- dev->has_audio_outputs = out_type_counter[SVID];
- if (out_type_counter[HDMI] == 16) {
- /*
- * The CEC physical address only allows for max 15 inputs,
- * so outputs are also limited to 15 to allow for easy
- * CEC output to input mapping.
- */
- out_type_counter[HDMI]--;
- dev->num_outputs--;
- }
- dev->num_hdmi_outputs = out_type_counter[HDMI];
-
- /* do we create a video capture device? */
- dev->has_vid_cap = node_type & 0x0001;
-
- /* do we create a vbi capture device? */
- if (in_type_counter[TV] || in_type_counter[SVID]) {
- dev->has_raw_vbi_cap = node_type & 0x0004;
- dev->has_sliced_vbi_cap = node_type & 0x0008;
- dev->has_vbi_cap = dev->has_raw_vbi_cap | dev->has_sliced_vbi_cap;
- }
-
- /* do we create a meta capture device */
- dev->has_meta_cap = node_type & 0x20000;
-
- /* sanity checks */
- if ((in_type_counter[WEBCAM] || in_type_counter[HDMI]) &&
- !dev->has_vid_cap && !dev->has_meta_cap) {
- v4l2_warn(&dev->v4l2_dev,
- "Webcam or HDMI input without video or metadata nodes\n");
- kfree(dev);
- return -EINVAL;
- }
- if ((in_type_counter[TV] || in_type_counter[SVID]) &&
- !dev->has_vid_cap && !dev->has_vbi_cap && !dev->has_meta_cap) {
- v4l2_warn(&dev->v4l2_dev,
- "TV or S-Video input without video, VBI or metadata nodes\n");
- kfree(dev);
- return -EINVAL;
- }
-
- /* do we create a video output device? */
- dev->has_vid_out = node_type & 0x0100;
-
- /* do we create a vbi output device? */
- if (out_type_counter[SVID]) {
- dev->has_raw_vbi_out = node_type & 0x0400;
- dev->has_sliced_vbi_out = node_type & 0x0800;
- dev->has_vbi_out = dev->has_raw_vbi_out | dev->has_sliced_vbi_out;
- }
-
- /* do we create a metadata output device */
- dev->has_meta_out = node_type & 0x40000;
-
- /* sanity checks */
- if (out_type_counter[SVID] &&
- !dev->has_vid_out && !dev->has_vbi_out && !dev->has_meta_out) {
- v4l2_warn(&dev->v4l2_dev,
- "S-Video output without video, VBI or metadata nodes\n");
- kfree(dev);
- return -EINVAL;
- }
- if (out_type_counter[HDMI] && !dev->has_vid_out && !dev->has_meta_out) {
- v4l2_warn(&dev->v4l2_dev,
- "HDMI output without video or metadata nodes\n");
- kfree(dev);
- return -EINVAL;
- }
-
- /* do we create a radio receiver device? */
- dev->has_radio_rx = node_type & 0x0010;
-
- /* do we create a radio transmitter device? */
- dev->has_radio_tx = node_type & 0x1000;
-
- /* do we create a software defined radio capture device? */
- dev->has_sdr_cap = node_type & 0x0020;
-
- /* do we have a TV tuner? */
- dev->has_tv_tuner = in_type_counter[TV];
-
- /* do we have a tuner? */
- has_tuner = ((dev->has_vid_cap || dev->has_vbi_cap) && in_type_counter[TV]) ||
- dev->has_radio_rx || dev->has_sdr_cap;
-
- /* do we have a modulator? */
- has_modulator = dev->has_radio_tx;
-
- if (dev->has_vid_cap)
- /* do we have a framebuffer for overlay testing? */
- dev->has_fb = node_type & 0x10000;
-
- /* can we do crop/compose/scaling while capturing? */
- if (no_error_inj && ccs_cap == -1)
- ccs_cap = 7;
-
- /* if ccs_cap == -1, then the user can select it using controls */
- if (ccs_cap != -1) {
- dev->has_crop_cap = ccs_cap & 1;
- dev->has_compose_cap = ccs_cap & 2;
- dev->has_scaler_cap = ccs_cap & 4;
- v4l2_info(&dev->v4l2_dev, "Capture Crop: %c Compose: %c Scaler: %c\n",
- dev->has_crop_cap ? 'Y' : 'N',
- dev->has_compose_cap ? 'Y' : 'N',
- dev->has_scaler_cap ? 'Y' : 'N');
- }
-
- /* can we do crop/compose/scaling with video output? */
- if (no_error_inj && ccs_out == -1)
- ccs_out = 7;
-
- /* if ccs_out == -1, then the user can select it using controls */
- if (ccs_out != -1) {
- dev->has_crop_out = ccs_out & 1;
- dev->has_compose_out = ccs_out & 2;
- dev->has_scaler_out = ccs_out & 4;
- v4l2_info(&dev->v4l2_dev, "Output Crop: %c Compose: %c Scaler: %c\n",
- dev->has_crop_out ? 'Y' : 'N',
- dev->has_compose_out ? 'Y' : 'N',
- dev->has_scaler_out ? 'Y' : 'N');
- }
-
- /* do we create a touch capture device */
- dev->has_touch_cap = node_type & 0x80000;
-
- /* end detecting feature set */
-
- if (dev->has_vid_cap) {
- /* 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;
- dev->vid_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
- if (dev->has_audio_inputs)
- dev->vid_cap_caps |= V4L2_CAP_AUDIO;
- if (dev->has_tv_tuner)
- dev->vid_cap_caps |= V4L2_CAP_TUNER;
- }
- if (dev->has_vid_out) {
- /* set up the capabilities of the video output device */
- dev->vid_out_caps = dev->multiplanar ?
- V4L2_CAP_VIDEO_OUTPUT_MPLANE :
- V4L2_CAP_VIDEO_OUTPUT;
- if (dev->has_fb)
- dev->vid_out_caps |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
- dev->vid_out_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
- if (dev->has_audio_outputs)
- dev->vid_out_caps |= V4L2_CAP_AUDIO;
- }
- if (dev->has_vbi_cap) {
- /* set up the capabilities of the vbi capture device */
- dev->vbi_cap_caps = (dev->has_raw_vbi_cap ? V4L2_CAP_VBI_CAPTURE : 0) |
- (dev->has_sliced_vbi_cap ? V4L2_CAP_SLICED_VBI_CAPTURE : 0);
- dev->vbi_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
- if (dev->has_audio_inputs)
- dev->vbi_cap_caps |= V4L2_CAP_AUDIO;
- if (dev->has_tv_tuner)
- dev->vbi_cap_caps |= V4L2_CAP_TUNER;
- }
- if (dev->has_vbi_out) {
- /* set up the capabilities of the vbi output device */
- dev->vbi_out_caps = (dev->has_raw_vbi_out ? V4L2_CAP_VBI_OUTPUT : 0) |
- (dev->has_sliced_vbi_out ? V4L2_CAP_SLICED_VBI_OUTPUT : 0);
- dev->vbi_out_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
- if (dev->has_audio_outputs)
- dev->vbi_out_caps |= V4L2_CAP_AUDIO;
- }
- if (dev->has_sdr_cap) {
- /* set up the capabilities of the sdr capture device */
- dev->sdr_cap_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER;
- dev->sdr_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
- }
- /* set up the capabilities of the radio receiver device */
- if (dev->has_radio_rx)
- dev->radio_rx_caps = V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE |
- V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
- V4L2_CAP_READWRITE;
- /* set up the capabilities of the radio transmitter device */
- if (dev->has_radio_tx)
- dev->radio_tx_caps = V4L2_CAP_RDS_OUTPUT | V4L2_CAP_MODULATOR |
- V4L2_CAP_READWRITE;
-
- /* set up the capabilities of meta capture device */
- if (dev->has_meta_cap) {
- dev->meta_cap_caps = V4L2_CAP_META_CAPTURE |
- V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
- if (dev->has_audio_inputs)
- dev->meta_cap_caps |= V4L2_CAP_AUDIO;
- if (dev->has_tv_tuner)
- dev->meta_cap_caps |= V4L2_CAP_TUNER;
- }
- /* set up the capabilities of meta output device */
- if (dev->has_meta_out) {
- dev->meta_out_caps = V4L2_CAP_META_OUTPUT |
- V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
- if (dev->has_audio_outputs)
- dev->meta_out_caps |= V4L2_CAP_AUDIO;
- }
- /* set up the capabilities of the touch capture device */
- if (dev->has_touch_cap) {
- dev->touch_cap_caps = V4L2_CAP_TOUCH | V4L2_CAP_STREAMING |
- V4L2_CAP_READWRITE;
- dev->touch_cap_caps |= dev->multiplanar ?
- V4L2_CAP_VIDEO_CAPTURE_MPLANE : V4L2_CAP_VIDEO_CAPTURE;
- }
-
- ret = -ENOMEM;
- /* initialize the test pattern generator */
- tpg_init(&dev->tpg, 640, 360);
- if (tpg_alloc(&dev->tpg, MAX_ZOOM * MAX_WIDTH))
- goto free_dev;
- dev->scaled_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM));
- if (!dev->scaled_line)
- goto free_dev;
- dev->blended_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM));
- if (!dev->blended_line)
- goto free_dev;
-
- /* load the edid */
- dev->edid = vmalloc(256 * 128);
- if (!dev->edid)
- goto free_dev;
-
- while (v4l2_dv_timings_presets[dev->query_dv_timings_size].bt.width)
- dev->query_dv_timings_size++;
-
- /*
- * Create a char pointer array that points to the names of all the
- * preset timings
- */
- dev->query_dv_timings_qmenu = kmalloc_array(dev->query_dv_timings_size,
- sizeof(char *), GFP_KERNEL);
- /*
- * Create a string array containing the names of all the preset
- * timings. Each name is max 31 chars long (+ terminating 0).
- */
- dev->query_dv_timings_qmenu_strings =
- kmalloc_array(dev->query_dv_timings_size, 32, GFP_KERNEL);
-
- if (!dev->query_dv_timings_qmenu ||
- !dev->query_dv_timings_qmenu_strings)
- goto free_dev;
-
- for (i = 0; i < dev->query_dv_timings_size; i++) {
- const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt;
- char *p = dev->query_dv_timings_qmenu_strings + i * 32;
- u32 htot, vtot;
-
- dev->query_dv_timings_qmenu[i] = p;
-
- htot = V4L2_DV_BT_FRAME_WIDTH(bt);
- vtot = V4L2_DV_BT_FRAME_HEIGHT(bt);
- snprintf(p, 32, "%ux%u%s%u",
- bt->width, bt->height, bt->interlaced ? "i" : "p",
- (u32)bt->pixelclock / (htot * vtot));
- }
-
- /* disable invalid ioctls based on the feature set */
- if (!dev->has_audio_inputs) {
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_AUDIO);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_AUDIO);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_ENUMAUDIO);
- v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_AUDIO);
- v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_G_AUDIO);
- v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_ENUMAUDIO);
- v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_AUDIO);
- v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_G_AUDIO);
- v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_ENUMAUDIO);
- }
- if (!dev->has_audio_outputs) {
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_AUDOUT);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_AUDOUT);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUMAUDOUT);
- v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_S_AUDOUT);
- v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_G_AUDOUT);
- v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_ENUMAUDOUT);
- v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_S_AUDOUT);
- v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_G_AUDOUT);
- v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_ENUMAUDOUT);
- }
- if (!in_type_counter[TV] && !in_type_counter[SVID]) {
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_STD);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_STD);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_ENUMSTD);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_QUERYSTD);
- }
- if (!out_type_counter[SVID]) {
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_STD);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_STD);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUMSTD);
- }
- if (!has_tuner && !has_modulator) {
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_FREQUENCY);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_FREQUENCY);
- v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_FREQUENCY);
- v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_G_FREQUENCY);
- v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_FREQUENCY);
- v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_G_FREQUENCY);
- }
- if (!has_tuner) {
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_TUNER);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_TUNER);
- v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_TUNER);
- v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_G_TUNER);
- v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_TUNER);
- v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_G_TUNER);
- }
- if (in_type_counter[HDMI] == 0) {
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_EDID);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_EDID);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_DV_TIMINGS_CAP);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_DV_TIMINGS);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_DV_TIMINGS);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_ENUM_DV_TIMINGS);
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_QUERY_DV_TIMINGS);
- }
- if (out_type_counter[HDMI] == 0) {
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_EDID);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_DV_TIMINGS_CAP);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_DV_TIMINGS);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_DV_TIMINGS);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_DV_TIMINGS);
- }
- if (!dev->has_fb) {
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_FBUF);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_FBUF);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_OVERLAY);
- }
- v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
- v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
- v4l2_disable_ioctl(&dev->sdr_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
- v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_FREQUENCY);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_FREQUENCY);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_FRAMESIZES);
- v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_FRAMEINTERVALS);
- v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_S_FREQUENCY);
- v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_G_FREQUENCY);
- v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_S_FREQUENCY);
- v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_G_FREQUENCY);
- v4l2_disable_ioctl(&dev->touch_cap_dev, VIDIOC_S_PARM);
- v4l2_disable_ioctl(&dev->touch_cap_dev, VIDIOC_ENUM_FRAMESIZES);
- v4l2_disable_ioctl(&dev->touch_cap_dev, VIDIOC_ENUM_FRAMEINTERVALS);
-
- /* configure internal data */
- dev->fmt_cap = &vivid_formats[0];
- dev->fmt_out = &vivid_formats[0];
- if (!dev->multiplanar)
- vivid_formats[0].data_offset[0] = 0;
- dev->webcam_size_idx = 1;
- dev->webcam_ival_idx = 3;
- tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
- dev->std_out = V4L2_STD_PAL;
- if (dev->input_type[0] == TV || dev->input_type[0] == SVID)
- tvnorms_cap = V4L2_STD_ALL;
- if (dev->output_type[0] == SVID)
- tvnorms_out = V4L2_STD_ALL;
- for (i = 0; i < MAX_INPUTS; i++) {
- dev->dv_timings_cap[i] = def_dv_timings;
- dev->std_cap[i] = V4L2_STD_PAL;
- }
- dev->dv_timings_out = def_dv_timings;
- dev->tv_freq = 2804 /* 175.25 * 16 */;
- dev->tv_audmode = V4L2_TUNER_MODE_STEREO;
- dev->tv_field_cap = V4L2_FIELD_INTERLACED;
- dev->tv_field_out = V4L2_FIELD_INTERLACED;
- dev->radio_rx_freq = 95000 * 16;
- dev->radio_rx_audmode = V4L2_TUNER_MODE_STEREO;
- if (dev->has_radio_tx) {
- dev->radio_tx_freq = 95500 * 16;
- dev->radio_rds_loop = false;
- }
- dev->radio_tx_subchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_RDS;
- dev->sdr_adc_freq = 300000;
- dev->sdr_fm_freq = 50000000;
- dev->sdr_pixelformat = V4L2_SDR_FMT_CU8;
- dev->sdr_buffersize = SDR_CAP_SAMPLES_PER_BUF * 2;
-
- dev->edid_max_blocks = dev->edid_blocks = 2;
- memcpy(dev->edid, vivid_hdmi_edid, sizeof(vivid_hdmi_edid));
- dev->radio_rds_init_time = ktime_get();
-
- /* create all controls */
- ret = vivid_create_controls(dev, ccs_cap == -1, ccs_out == -1, no_error_inj,
- in_type_counter[TV] || in_type_counter[SVID] ||
- out_type_counter[SVID],
- in_type_counter[HDMI] || out_type_counter[HDMI]);
- if (ret)
- goto unreg_dev;
-
- /* enable/disable interface specific controls */
- if (dev->num_outputs && dev->output_type[0] != HDMI)
- v4l2_ctrl_activate(dev->ctrl_display_present, false);
- if (dev->num_inputs && dev->input_type[0] != HDMI) {
- v4l2_ctrl_activate(dev->ctrl_dv_timings_signal_mode, false);
- v4l2_ctrl_activate(dev->ctrl_dv_timings, false);
- } else if (dev->num_inputs && dev->input_type[0] == HDMI) {
- v4l2_ctrl_activate(dev->ctrl_std_signal_mode, false);
- v4l2_ctrl_activate(dev->ctrl_standard, false);
- }
-
- /*
- * update the capture and output formats to do a proper initial
- * configuration.
- */
- 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;
- vivid_set_touch(dev, 0);
-
- /* initialize locks */
- spin_lock_init(&dev->slock);
- mutex_init(&dev->mutex);
-
- /* init dma queues */
- INIT_LIST_HEAD(&dev->vid_cap_active);
- INIT_LIST_HEAD(&dev->vid_out_active);
- INIT_LIST_HEAD(&dev->vbi_cap_active);
- INIT_LIST_HEAD(&dev->vbi_out_active);
- INIT_LIST_HEAD(&dev->sdr_cap_active);
- INIT_LIST_HEAD(&dev->meta_cap_active);
- INIT_LIST_HEAD(&dev->meta_out_active);
- INIT_LIST_HEAD(&dev->touch_cap_active);
-
- INIT_LIST_HEAD(&dev->cec_work_list);
- spin_lock_init(&dev->cec_slock);
- /*
- * Same as create_singlethread_workqueue, but now I can use the
- * string formatting of alloc_ordered_workqueue.
- */
- dev->cec_workqueue =
- alloc_ordered_workqueue("vivid-%03d-cec", WQ_MEM_RECLAIM, inst);
- if (!dev->cec_workqueue) {
- ret = -ENOMEM;
- goto unreg_dev;
- }
-
- if (allocators[inst] == 1)
- dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
-
- /* start creating the vb2 queues */
- if (dev->has_vid_cap) {
- /* initialize vid_cap queue */
- ret = vivid_create_queue(dev, &dev->vb_vid_cap_q,
- V4L2_BUF_TYPE_VIDEO_CAPTURE, 2,
- &vivid_vid_cap_qops);
- if (ret)
- goto unreg_dev;
- }
-
- if (dev->has_vid_out) {
- /* initialize vid_out queue */
- ret = vivid_create_queue(dev, &dev->vb_vid_out_q,
- V4L2_BUF_TYPE_VIDEO_OUTPUT, 2,
- &vivid_vid_out_qops);
- if (ret)
- goto unreg_dev;
- }
-
- if (dev->has_vbi_cap) {
- /* initialize vbi_cap queue */
- ret = vivid_create_queue(dev, &dev->vb_vbi_cap_q,
- V4L2_BUF_TYPE_VBI_CAPTURE, 2,
- &vivid_vbi_cap_qops);
- if (ret)
- goto unreg_dev;
- }
-
- if (dev->has_vbi_out) {
- /* initialize vbi_out queue */
- ret = vivid_create_queue(dev, &dev->vb_vbi_out_q,
- V4L2_BUF_TYPE_VBI_OUTPUT, 2,
- &vivid_vbi_out_qops);
- if (ret)
- goto unreg_dev;
- }
-
- if (dev->has_sdr_cap) {
- /* initialize sdr_cap queue */
- ret = vivid_create_queue(dev, &dev->vb_sdr_cap_q,
- V4L2_BUF_TYPE_SDR_CAPTURE, 8,
- &vivid_sdr_cap_qops);
- if (ret)
- goto unreg_dev;
- }
-
- if (dev->has_meta_cap) {
- /* initialize meta_cap queue */
- ret = vivid_create_queue(dev, &dev->vb_meta_cap_q,
- V4L2_BUF_TYPE_META_CAPTURE, 2,
- &vivid_meta_cap_qops);
- if (ret)
- goto unreg_dev;
- }
-
- if (dev->has_meta_out) {
- /* initialize meta_out queue */
- ret = vivid_create_queue(dev, &dev->vb_meta_out_q,
- V4L2_BUF_TYPE_META_OUTPUT, 1,
- &vivid_meta_out_qops);
- if (ret)
- goto unreg_dev;
- }
-
- if (dev->has_touch_cap) {
- /* initialize touch_cap queue */
- ret = vivid_create_queue(dev, &dev->vb_touch_cap_q,
- V4L2_BUF_TYPE_VIDEO_CAPTURE, 1,
- &vivid_touch_cap_qops);
- if (ret)
- goto unreg_dev;
- }
-
- if (dev->has_fb) {
- /* Create framebuffer for testing capture/output overlay */
- ret = vivid_fb_init(dev);
- if (ret)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev, "Framebuffer device registered as fb%d\n",
- dev->fb_info.node);
- }
-
-#ifdef CONFIG_VIDEO_VIVID_CEC
- if (dev->has_vid_cap && in_type_counter[HDMI]) {
- struct cec_adapter *adap;
-
- adap = vivid_cec_alloc_adap(dev, 0, false);
- ret = PTR_ERR_OR_ZERO(adap);
- if (ret < 0)
- goto unreg_dev;
- dev->cec_rx_adap = adap;
- }
-
- if (dev->has_vid_out) {
- for (i = 0; i < dev->num_outputs; i++) {
- struct cec_adapter *adap;
-
- if (dev->output_type[i] != HDMI)
- continue;
-
- dev->cec_output2bus_map[i] = cec_tx_bus_cnt;
- adap = vivid_cec_alloc_adap(dev, cec_tx_bus_cnt, true);
- ret = PTR_ERR_OR_ZERO(adap);
- if (ret < 0) {
- for (i = 0; i < dev->num_outputs; i++)
- cec_delete_adapter(dev->cec_tx_adap[i]);
- goto unreg_dev;
- }
-
- dev->cec_tx_adap[cec_tx_bus_cnt] = adap;
- cec_tx_bus_cnt++;
- }
- }
-#endif
-
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_meta_cap);
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_meta_out);
- v4l2_ctrl_handler_setup(&dev->ctrl_hdl_touch_cap);
-
- /* finally start creating the device nodes */
- if (dev->has_vid_cap) {
- vfd = &dev->vid_cap_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-vid-cap", inst);
- vfd->fops = &vivid_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->vid_cap_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->queue = &dev->vb_vid_cap_q;
- vfd->tvnorms = tvnorms_cap;
-
- /*
- * Provide a mutex to v4l2 core. It will be used to protect
- * all fops and v4l2 ioctls.
- */
- vfd->lock = &dev->mutex;
- video_set_drvdata(vfd, dev);
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK;
- ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_cap_pad);
- if (ret)
- goto unreg_dev;
-#endif
-
-#ifdef CONFIG_VIDEO_VIVID_CEC
- if (in_type_counter[HDMI]) {
- ret = cec_register_adapter(dev->cec_rx_adap, &pdev->dev);
- if (ret < 0) {
- cec_delete_adapter(dev->cec_rx_adap);
- dev->cec_rx_adap = NULL;
- goto unreg_dev;
- }
- cec_s_phys_addr(dev->cec_rx_adap, 0, false);
- v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI input 0\n",
- dev_name(&dev->cec_rx_adap->devnode.dev));
- }
-#endif
-
- ret = video_register_device(vfd, VFL_TYPE_VIDEO, vid_cap_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
- video_device_node_name(vfd));
- }
-
- if (dev->has_vid_out) {
- vfd = &dev->vid_out_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-vid-out", inst);
- vfd->vfl_dir = VFL_DIR_TX;
- vfd->fops = &vivid_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->vid_out_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->queue = &dev->vb_vid_out_q;
- vfd->tvnorms = tvnorms_out;
-
- /*
- * Provide a mutex to v4l2 core. It will be used to protect
- * all fops and v4l2 ioctls.
- */
- vfd->lock = &dev->mutex;
- video_set_drvdata(vfd, dev);
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE;
- ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_out_pad);
- if (ret)
- goto unreg_dev;
-#endif
-
-#ifdef CONFIG_VIDEO_VIVID_CEC
- for (i = 0; i < cec_tx_bus_cnt; i++) {
- ret = cec_register_adapter(dev->cec_tx_adap[i], &pdev->dev);
- if (ret < 0) {
- for (; i < cec_tx_bus_cnt; i++) {
- cec_delete_adapter(dev->cec_tx_adap[i]);
- dev->cec_tx_adap[i] = NULL;
- }
- goto unreg_dev;
- }
- v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI output %d\n",
- dev_name(&dev->cec_tx_adap[i]->devnode.dev), i);
- if (i < out_type_counter[HDMI])
- cec_s_phys_addr(dev->cec_tx_adap[i], (i + 1) << 12, false);
- else
- cec_s_phys_addr(dev->cec_tx_adap[i], 0x1000, false);
- }
-#endif
-
- ret = video_register_device(vfd, VFL_TYPE_VIDEO, vid_out_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s\n",
- video_device_node_name(vfd));
- }
-
- if (dev->has_vbi_cap) {
- vfd = &dev->vbi_cap_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-vbi-cap", inst);
- vfd->fops = &vivid_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->vbi_cap_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->queue = &dev->vb_vbi_cap_q;
- vfd->lock = &dev->mutex;
- vfd->tvnorms = tvnorms_cap;
- video_set_drvdata(vfd, dev);
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->vbi_cap_pad.flags = MEDIA_PAD_FL_SINK;
- ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_cap_pad);
- if (ret)
- goto unreg_dev;
-#endif
-
- ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_cap_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s, supports %s VBI\n",
- video_device_node_name(vfd),
- (dev->has_raw_vbi_cap && dev->has_sliced_vbi_cap) ?
- "raw and sliced" :
- (dev->has_raw_vbi_cap ? "raw" : "sliced"));
- }
-
- if (dev->has_vbi_out) {
- vfd = &dev->vbi_out_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-vbi-out", inst);
- vfd->vfl_dir = VFL_DIR_TX;
- vfd->fops = &vivid_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->vbi_out_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->queue = &dev->vb_vbi_out_q;
- vfd->lock = &dev->mutex;
- vfd->tvnorms = tvnorms_out;
- video_set_drvdata(vfd, dev);
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->vbi_out_pad.flags = MEDIA_PAD_FL_SOURCE;
- ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_out_pad);
- if (ret)
- goto unreg_dev;
-#endif
-
- ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_out_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s, supports %s VBI\n",
- video_device_node_name(vfd),
- (dev->has_raw_vbi_out && dev->has_sliced_vbi_out) ?
- "raw and sliced" :
- (dev->has_raw_vbi_out ? "raw" : "sliced"));
- }
-
- if (dev->has_sdr_cap) {
- vfd = &dev->sdr_cap_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-sdr-cap", inst);
- vfd->fops = &vivid_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->sdr_cap_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->queue = &dev->vb_sdr_cap_q;
- vfd->lock = &dev->mutex;
- video_set_drvdata(vfd, dev);
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK;
- ret = media_entity_pads_init(&vfd->entity, 1, &dev->sdr_cap_pad);
- if (ret)
- goto unreg_dev;
-#endif
-
- ret = video_register_device(vfd, VFL_TYPE_SDR, sdr_cap_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
- video_device_node_name(vfd));
- }
-
- if (dev->has_radio_rx) {
- vfd = &dev->radio_rx_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-rad-rx", inst);
- vfd->fops = &vivid_radio_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->radio_rx_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->lock = &dev->mutex;
- video_set_drvdata(vfd, dev);
-
- ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_rx_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev, "V4L2 receiver device registered as %s\n",
- video_device_node_name(vfd));
- }
-
- if (dev->has_radio_tx) {
- vfd = &dev->radio_tx_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-rad-tx", inst);
- vfd->vfl_dir = VFL_DIR_TX;
- vfd->fops = &vivid_radio_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->radio_tx_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->lock = &dev->mutex;
- video_set_drvdata(vfd, dev);
-
- ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_tx_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev, "V4L2 transmitter device registered as %s\n",
- video_device_node_name(vfd));
- }
-
- if (dev->has_meta_cap) {
- vfd = &dev->meta_cap_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-meta-cap", inst);
- vfd->fops = &vivid_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->meta_cap_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->queue = &dev->vb_meta_cap_q;
- vfd->lock = &dev->mutex;
- vfd->tvnorms = tvnorms_cap;
- video_set_drvdata(vfd, dev);
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->meta_cap_pad.flags = MEDIA_PAD_FL_SINK;
- ret = media_entity_pads_init(&vfd->entity, 1,
- &dev->meta_cap_pad);
- if (ret)
- goto unreg_dev;
-#endif
- ret = video_register_device(vfd, VFL_TYPE_VIDEO,
- meta_cap_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev,
- "V4L2 metadata capture device registered as %s\n",
- video_device_node_name(vfd));
- }
-
- if (dev->has_meta_out) {
- vfd = &dev->meta_out_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-meta-out", inst);
- vfd->vfl_dir = VFL_DIR_TX;
- vfd->fops = &vivid_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->meta_out_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->queue = &dev->vb_meta_out_q;
- vfd->lock = &dev->mutex;
- vfd->tvnorms = tvnorms_out;
- video_set_drvdata(vfd, dev);
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->meta_out_pad.flags = MEDIA_PAD_FL_SOURCE;
- ret = media_entity_pads_init(&vfd->entity, 1,
- &dev->meta_out_pad);
- if (ret)
- goto unreg_dev;
-#endif
- ret = video_register_device(vfd, VFL_TYPE_VIDEO,
- meta_out_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev,
- "V4L2 metadata output device registered as %s\n",
- video_device_node_name(vfd));
- }
-
- if (dev->has_touch_cap) {
- vfd = &dev->touch_cap_dev;
- snprintf(vfd->name, sizeof(vfd->name),
- "vivid-%03d-touch-cap", inst);
- vfd->fops = &vivid_fops;
- vfd->ioctl_ops = &vivid_ioctl_ops;
- vfd->device_caps = dev->touch_cap_caps;
- vfd->release = video_device_release_empty;
- vfd->v4l2_dev = &dev->v4l2_dev;
- vfd->queue = &dev->vb_touch_cap_q;
- vfd->tvnorms = tvnorms_cap;
- vfd->lock = &dev->mutex;
- video_set_drvdata(vfd, dev);
-#ifdef CONFIG_MEDIA_CONTROLLER
- dev->touch_cap_pad.flags = MEDIA_PAD_FL_SINK;
- ret = media_entity_pads_init(&vfd->entity, 1,
- &dev->touch_cap_pad);
- if (ret)
- goto unreg_dev;
-#endif
- ret = video_register_device(vfd, VFL_TYPE_TOUCH,
- touch_cap_nr[inst]);
- if (ret < 0)
- goto unreg_dev;
- v4l2_info(&dev->v4l2_dev,
- "V4L2 touch capture device registered as %s\n",
- video_device_node_name(vfd));
- }
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- /* Register the media device */
- ret = media_device_register(&dev->mdev);
- if (ret) {
- dev_err(dev->mdev.dev,
- "media device register failed (err=%d)\n", ret);
- goto unreg_dev;
- }
-#endif
-
- /* Now that everything is fine, let's add it to device list */
- vivid_devs[inst] = dev;
-
- return 0;
-
-unreg_dev:
- video_unregister_device(&dev->touch_cap_dev);
- video_unregister_device(&dev->meta_out_dev);
- video_unregister_device(&dev->meta_cap_dev);
- video_unregister_device(&dev->radio_tx_dev);
- video_unregister_device(&dev->radio_rx_dev);
- video_unregister_device(&dev->sdr_cap_dev);
- video_unregister_device(&dev->vbi_out_dev);
- video_unregister_device(&dev->vbi_cap_dev);
- video_unregister_device(&dev->vid_out_dev);
- video_unregister_device(&dev->vid_cap_dev);
- cec_unregister_adapter(dev->cec_rx_adap);
- for (i = 0; i < MAX_OUTPUTS; i++)
- cec_unregister_adapter(dev->cec_tx_adap[i]);
- if (dev->cec_workqueue) {
- vivid_cec_bus_free_work(dev);
- destroy_workqueue(dev->cec_workqueue);
- }
-free_dev:
- v4l2_device_put(&dev->v4l2_dev);
- return ret;
-}
-
-/* This routine allocates from 1 to n_devs virtual drivers.
-
- The real maximum number of virtual drivers will depend on how many drivers
- will succeed. This is limited to the maximum number of devices that
- videodev supports, which is equal to VIDEO_NUM_DEVICES.
- */
-static int vivid_probe(struct platform_device *pdev)
-{
- const struct font_desc *font = find_font("VGA8x16");
- int ret = 0, i;
-
- if (font == NULL) {
- pr_err("vivid: could not find font\n");
- return -ENODEV;
- }
-
- tpg_set_font(font->data);
-
- n_devs = clamp_t(unsigned, n_devs, 1, VIVID_MAX_DEVS);
-
- for (i = 0; i < n_devs; i++) {
- ret = vivid_create_instance(pdev, i);
- if (ret) {
- /* If some instantiations succeeded, keep driver */
- if (i)
- ret = 0;
- break;
- }
- }
-
- if (ret < 0) {
- pr_err("vivid: error %d while loading driver\n", ret);
- return ret;
- }
-
- /* n_devs will reflect the actual number of allocated devices */
- n_devs = i;
-
- return ret;
-}
-
-static int vivid_remove(struct platform_device *pdev)
-{
- struct vivid_dev *dev;
- unsigned int i, j;
-
- for (i = 0; i < n_devs; i++) {
- dev = vivid_devs[i];
- if (!dev)
- continue;
-
-#ifdef CONFIG_MEDIA_CONTROLLER
- media_device_unregister(&dev->mdev);
-#endif
-
- if (dev->has_vid_cap) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->vid_cap_dev));
- video_unregister_device(&dev->vid_cap_dev);
- }
- if (dev->has_vid_out) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->vid_out_dev));
- video_unregister_device(&dev->vid_out_dev);
- }
- if (dev->has_vbi_cap) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->vbi_cap_dev));
- video_unregister_device(&dev->vbi_cap_dev);
- }
- if (dev->has_vbi_out) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->vbi_out_dev));
- video_unregister_device(&dev->vbi_out_dev);
- }
- if (dev->has_sdr_cap) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->sdr_cap_dev));
- video_unregister_device(&dev->sdr_cap_dev);
- }
- if (dev->has_radio_rx) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->radio_rx_dev));
- video_unregister_device(&dev->radio_rx_dev);
- }
- if (dev->has_radio_tx) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->radio_tx_dev));
- video_unregister_device(&dev->radio_tx_dev);
- }
- if (dev->has_fb) {
- v4l2_info(&dev->v4l2_dev, "unregistering fb%d\n",
- dev->fb_info.node);
- unregister_framebuffer(&dev->fb_info);
- vivid_fb_release_buffers(dev);
- }
- if (dev->has_meta_cap) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->meta_cap_dev));
- video_unregister_device(&dev->meta_cap_dev);
- }
- if (dev->has_meta_out) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->meta_out_dev));
- video_unregister_device(&dev->meta_out_dev);
- }
- if (dev->has_touch_cap) {
- v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
- video_device_node_name(&dev->touch_cap_dev));
- video_unregister_device(&dev->touch_cap_dev);
- }
- cec_unregister_adapter(dev->cec_rx_adap);
- for (j = 0; j < MAX_OUTPUTS; j++)
- cec_unregister_adapter(dev->cec_tx_adap[j]);
- if (dev->cec_workqueue) {
- vivid_cec_bus_free_work(dev);
- destroy_workqueue(dev->cec_workqueue);
- }
- v4l2_device_put(&dev->v4l2_dev);
- vivid_devs[i] = NULL;
- }
- return 0;
-}
-
-static void vivid_pdev_release(struct device *dev)
-{
-}
-
-static struct platform_device vivid_pdev = {
- .name = "vivid",
- .dev.release = vivid_pdev_release,
-};
-
-static struct platform_driver vivid_pdrv = {
- .probe = vivid_probe,
- .remove = vivid_remove,
- .driver = {
- .name = "vivid",
- },
-};
-
-static int __init vivid_init(void)
-{
- int ret;
-
- ret = platform_device_register(&vivid_pdev);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&vivid_pdrv);
- if (ret)
- platform_device_unregister(&vivid_pdev);
-
- return ret;
-}
-
-static void __exit vivid_exit(void)
-{
- platform_driver_unregister(&vivid_pdrv);
- platform_device_unregister(&vivid_pdev);
-}
-
-module_init(vivid_init);
-module_exit(vivid_exit);
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
deleted file mode 100644
index 99e69b8f770f..000000000000
--- a/drivers/media/platform/vivid/vivid-core.h
+++ /dev/null
@@ -1,612 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-core.h - core datastructures
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_CORE_H_
-#define _VIVID_CORE_H_
-
-#include <linux/fb.h>
-#include <linux/workqueue.h>
-#include <media/cec.h>
-#include <media/videobuf2-v4l2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-ctrls.h>
-#include <media/tpg/v4l2-tpg.h>
-#include "vivid-rds-gen.h"
-#include "vivid-vbi-gen.h"
-
-#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 */
-#define MAX_OUTPUTS 16
-/* The maximum up or down scaling factor is 4 */
-#define MAX_ZOOM 4
-/* The maximum image width/height are set to 4K DMT */
-#define MAX_WIDTH 4096
-#define MAX_HEIGHT 2160
-/* The minimum image width/height */
-#define MIN_WIDTH 16
-#define MIN_HEIGHT 16
-/* The data_offset of plane 0 for the multiplanar formats */
-#define PLANE0_DATA_OFFSET 128
-
-/* The supported TV frequency range in MHz */
-#define MIN_TV_FREQ (44U * 16U)
-#define MAX_TV_FREQ (958U * 16U)
-
-/* The number of samples returned in every SDR buffer */
-#define SDR_CAP_SAMPLES_PER_BUF 0x4000
-
-/* used by the threads to know when to resync internal counters */
-#define JIFFIES_PER_DAY (3600U * 24U * HZ)
-#define JIFFIES_RESYNC (JIFFIES_PER_DAY * (0xf0000000U / JIFFIES_PER_DAY))
-
-extern const struct v4l2_rect vivid_min_rect;
-extern const struct v4l2_rect vivid_max_rect;
-extern unsigned vivid_debug;
-
-struct vivid_fmt {
- u32 fourcc; /* v4l2 format id */
- enum tgp_color_enc color_enc;
- bool can_do_overlay;
- u8 vdownsampling[TPG_MAX_PLANES];
- u32 alpha_mask;
- u8 planes;
- u8 buffers;
- u32 data_offset[TPG_MAX_PLANES];
- u32 bit_depth[TPG_MAX_PLANES];
-};
-
-extern struct vivid_fmt vivid_formats[];
-
-/* buffer for one video frame */
-struct vivid_buffer {
- /* common v4l buffer stuff -- must be first */
- struct vb2_v4l2_buffer vb;
- struct list_head list;
-};
-
-enum vivid_input {
- WEBCAM,
- TV,
- SVID,
- HDMI,
-};
-
-enum vivid_signal_mode {
- CURRENT_DV_TIMINGS,
- CURRENT_STD = CURRENT_DV_TIMINGS,
- NO_SIGNAL,
- NO_LOCK,
- OUT_OF_RANGE,
- SELECTED_DV_TIMINGS,
- SELECTED_STD = SELECTED_DV_TIMINGS,
- CYCLE_DV_TIMINGS,
- CYCLE_STD = CYCLE_DV_TIMINGS,
- CUSTOM_DV_TIMINGS,
-};
-
-enum vivid_colorspace {
- VIVID_CS_170M,
- VIVID_CS_709,
- VIVID_CS_SRGB,
- VIVID_CS_OPRGB,
- VIVID_CS_2020,
- VIVID_CS_DCI_P3,
- VIVID_CS_240M,
- VIVID_CS_SYS_M,
- VIVID_CS_SYS_BG,
-};
-
-#define VIVID_INVALID_SIGNAL(mode) \
- ((mode) == NO_SIGNAL || (mode) == NO_LOCK || (mode) == OUT_OF_RANGE)
-
-struct vivid_cec_work {
- struct list_head list;
- struct delayed_work work;
- struct cec_adapter *adap;
- struct vivid_dev *dev;
- unsigned int usecs;
- unsigned int timeout_ms;
- u8 tx_status;
- struct cec_msg msg;
-};
-
-struct vivid_dev {
- unsigned inst;
- struct v4l2_device v4l2_dev;
-#ifdef CONFIG_MEDIA_CONTROLLER
- struct media_device mdev;
- struct media_pad vid_cap_pad;
- struct media_pad vid_out_pad;
- struct media_pad vbi_cap_pad;
- struct media_pad vbi_out_pad;
- struct media_pad sdr_cap_pad;
- struct media_pad meta_cap_pad;
- struct media_pad meta_out_pad;
- struct media_pad touch_cap_pad;
-#endif
- struct v4l2_ctrl_handler ctrl_hdl_user_gen;
- struct v4l2_ctrl_handler ctrl_hdl_user_vid;
- struct v4l2_ctrl_handler ctrl_hdl_user_aud;
- struct v4l2_ctrl_handler ctrl_hdl_streaming;
- struct v4l2_ctrl_handler ctrl_hdl_sdtv_cap;
- struct v4l2_ctrl_handler ctrl_hdl_loop_cap;
- struct v4l2_ctrl_handler ctrl_hdl_fb;
- struct video_device vid_cap_dev;
- struct v4l2_ctrl_handler ctrl_hdl_vid_cap;
- struct video_device vid_out_dev;
- struct v4l2_ctrl_handler ctrl_hdl_vid_out;
- struct video_device vbi_cap_dev;
- struct v4l2_ctrl_handler ctrl_hdl_vbi_cap;
- struct video_device vbi_out_dev;
- struct v4l2_ctrl_handler ctrl_hdl_vbi_out;
- struct video_device radio_rx_dev;
- struct v4l2_ctrl_handler ctrl_hdl_radio_rx;
- struct video_device radio_tx_dev;
- struct v4l2_ctrl_handler ctrl_hdl_radio_tx;
- struct video_device sdr_cap_dev;
- struct v4l2_ctrl_handler ctrl_hdl_sdr_cap;
- struct video_device meta_cap_dev;
- struct v4l2_ctrl_handler ctrl_hdl_meta_cap;
- struct video_device meta_out_dev;
- struct v4l2_ctrl_handler ctrl_hdl_meta_out;
- struct video_device touch_cap_dev;
- struct v4l2_ctrl_handler ctrl_hdl_touch_cap;
-
- spinlock_t slock;
- struct mutex mutex;
-
- /* capabilities */
- u32 vid_cap_caps;
- u32 vid_out_caps;
- u32 vbi_cap_caps;
- u32 vbi_out_caps;
- u32 sdr_cap_caps;
- u32 radio_rx_caps;
- u32 radio_tx_caps;
- u32 meta_cap_caps;
- u32 meta_out_caps;
- u32 touch_cap_caps;
-
- /* supported features */
- bool multiplanar;
- unsigned num_inputs;
- unsigned int num_hdmi_inputs;
- u8 input_type[MAX_INPUTS];
- u8 input_name_counter[MAX_INPUTS];
- unsigned num_outputs;
- unsigned int num_hdmi_outputs;
- u8 output_type[MAX_OUTPUTS];
- u8 output_name_counter[MAX_OUTPUTS];
- bool has_audio_inputs;
- bool has_audio_outputs;
- bool has_vid_cap;
- bool has_vid_out;
- bool has_vbi_cap;
- bool has_raw_vbi_cap;
- bool has_sliced_vbi_cap;
- bool has_vbi_out;
- bool has_raw_vbi_out;
- bool has_sliced_vbi_out;
- bool has_radio_rx;
- bool has_radio_tx;
- bool has_sdr_cap;
- bool has_fb;
- bool has_meta_cap;
- bool has_meta_out;
- bool has_tv_tuner;
- bool has_touch_cap;
-
- bool can_loop_video;
-
- /* controls */
- struct v4l2_ctrl *brightness;
- struct v4l2_ctrl *contrast;
- struct v4l2_ctrl *saturation;
- struct v4l2_ctrl *hue;
- struct {
- /* autogain/gain cluster */
- struct v4l2_ctrl *autogain;
- struct v4l2_ctrl *gain;
- };
- struct v4l2_ctrl *volume;
- struct v4l2_ctrl *mute;
- struct v4l2_ctrl *alpha;
- struct v4l2_ctrl *button;
- struct v4l2_ctrl *boolean;
- struct v4l2_ctrl *int32;
- struct v4l2_ctrl *int64;
- struct v4l2_ctrl *menu;
- struct v4l2_ctrl *string;
- struct v4l2_ctrl *bitmask;
- struct v4l2_ctrl *int_menu;
- struct v4l2_ctrl *test_pattern;
- struct v4l2_ctrl *colorspace;
- struct v4l2_ctrl *rgb_range_cap;
- struct v4l2_ctrl *real_rgb_range_cap;
- struct {
- /* std_signal_mode/standard cluster */
- struct v4l2_ctrl *ctrl_std_signal_mode;
- struct v4l2_ctrl *ctrl_standard;
- };
- struct {
- /* dv_timings_signal_mode/timings cluster */
- struct v4l2_ctrl *ctrl_dv_timings_signal_mode;
- struct v4l2_ctrl *ctrl_dv_timings;
- };
- struct v4l2_ctrl *ctrl_display_present;
- struct v4l2_ctrl *ctrl_has_crop_cap;
- struct v4l2_ctrl *ctrl_has_compose_cap;
- struct v4l2_ctrl *ctrl_has_scaler_cap;
- struct v4l2_ctrl *ctrl_has_crop_out;
- struct v4l2_ctrl *ctrl_has_compose_out;
- struct v4l2_ctrl *ctrl_has_scaler_out;
- struct v4l2_ctrl *ctrl_tx_mode;
- struct v4l2_ctrl *ctrl_tx_rgb_range;
- struct v4l2_ctrl *ctrl_tx_edid_present;
- struct v4l2_ctrl *ctrl_tx_hotplug;
- struct v4l2_ctrl *ctrl_tx_rxsense;
-
- struct v4l2_ctrl *ctrl_rx_power_present;
-
- struct v4l2_ctrl *radio_tx_rds_pi;
- struct v4l2_ctrl *radio_tx_rds_pty;
- struct v4l2_ctrl *radio_tx_rds_mono_stereo;
- struct v4l2_ctrl *radio_tx_rds_art_head;
- struct v4l2_ctrl *radio_tx_rds_compressed;
- struct v4l2_ctrl *radio_tx_rds_dyn_pty;
- struct v4l2_ctrl *radio_tx_rds_ta;
- struct v4l2_ctrl *radio_tx_rds_tp;
- struct v4l2_ctrl *radio_tx_rds_ms;
- struct v4l2_ctrl *radio_tx_rds_psname;
- struct v4l2_ctrl *radio_tx_rds_radiotext;
-
- struct v4l2_ctrl *radio_rx_rds_pty;
- struct v4l2_ctrl *radio_rx_rds_ta;
- struct v4l2_ctrl *radio_rx_rds_tp;
- struct v4l2_ctrl *radio_rx_rds_ms;
- struct v4l2_ctrl *radio_rx_rds_psname;
- struct v4l2_ctrl *radio_rx_rds_radiotext;
-
- unsigned input_brightness[MAX_INPUTS];
- unsigned osd_mode;
- unsigned button_pressed;
- bool sensor_hflip;
- bool sensor_vflip;
- bool hflip;
- bool vflip;
- bool vbi_cap_interlaced;
- bool loop_video;
- bool reduced_fps;
-
- /* Framebuffer */
- unsigned long video_pbase;
- void *video_vbase;
- u32 video_buffer_size;
- int display_width;
- int display_height;
- int display_byte_stride;
- int bits_per_pixel;
- int bytes_per_pixel;
- struct fb_info fb_info;
- struct fb_var_screeninfo fb_defined;
- struct fb_fix_screeninfo fb_fix;
-
- /* Error injection */
- bool queue_setup_error;
- bool buf_prepare_error;
- bool start_streaming_error;
- bool dqbuf_error;
- bool req_validate_error;
- bool seq_wrap;
- bool time_wrap;
- u64 time_wrap_offset;
- unsigned perc_dropped_buffers;
- enum vivid_signal_mode std_signal_mode[MAX_INPUTS];
- unsigned int query_std_last[MAX_INPUTS];
- v4l2_std_id query_std[MAX_INPUTS];
- enum tpg_video_aspect std_aspect_ratio[MAX_INPUTS];
-
- enum vivid_signal_mode dv_timings_signal_mode[MAX_INPUTS];
- char **query_dv_timings_qmenu;
- char *query_dv_timings_qmenu_strings;
- unsigned query_dv_timings_size;
- unsigned int query_dv_timings_last[MAX_INPUTS];
- unsigned int query_dv_timings[MAX_INPUTS];
- enum tpg_video_aspect dv_timings_aspect_ratio[MAX_INPUTS];
-
- /* Input */
- unsigned input;
- v4l2_std_id std_cap[MAX_INPUTS];
- struct v4l2_dv_timings dv_timings_cap[MAX_INPUTS];
- int dv_timings_cap_sel[MAX_INPUTS];
- u32 service_set_cap;
- struct vivid_vbi_gen_data vbi_gen;
- u8 *edid;
- unsigned edid_blocks;
- unsigned edid_max_blocks;
- unsigned webcam_size_idx;
- unsigned webcam_ival_idx;
- unsigned tv_freq;
- unsigned tv_audmode;
- unsigned tv_field_cap;
- unsigned tv_audio_input;
-
- 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;
- struct v4l2_dv_timings dv_timings_out;
- u32 colorspace_out;
- u32 ycbcr_enc_out;
- u32 hsv_enc_out;
- u32 quantization_out;
- u32 xfer_func_out;
- u32 service_set_out;
- unsigned bytesperline_out[TPG_MAX_PLANES];
- unsigned tv_field_out;
- unsigned tv_audio_output;
- bool vbi_out_have_wss;
- u8 vbi_out_wss[2];
- bool vbi_out_have_cc[2];
- u8 vbi_out_cc[2][2];
- bool dvi_d_out;
- u8 *scaled_line;
- u8 *blended_line;
- unsigned cur_scaled_line;
- bool display_present[MAX_OUTPUTS];
-
- /* Output Overlay */
- 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;
-
- /* video capture */
- struct tpg_data tpg;
- unsigned ms_vid_cap;
- bool must_blank[VIDEO_MAX_FRAME];
-
- const struct vivid_fmt *fmt_cap;
- struct v4l2_fract timeperframe_vid_cap;
- enum v4l2_field field_cap;
- struct v4l2_rect src_rect;
- struct v4l2_rect fmt_cap_rect;
- struct v4l2_rect crop_cap;
- struct v4l2_rect compose_cap;
- struct v4l2_rect crop_bounds_cap;
- struct vb2_queue vb_vid_cap_q;
- struct list_head vid_cap_active;
- struct vb2_queue vb_vbi_cap_q;
- struct list_head vbi_cap_active;
- struct vb2_queue vb_meta_cap_q;
- struct list_head meta_cap_active;
- struct vb2_queue vb_touch_cap_q;
- struct list_head touch_cap_active;
-
- /* thread for generating video capture stream */
- struct task_struct *kthread_vid_cap;
- unsigned long jiffies_vid_cap;
- u64 cap_stream_start;
- u64 cap_frame_period;
- u64 cap_frame_eof_offset;
- u32 cap_seq_offset;
- u32 cap_seq_count;
- bool cap_seq_resync;
- u32 vid_cap_seq_start;
- u32 vid_cap_seq_count;
- bool vid_cap_streaming;
- u32 vbi_cap_seq_start;
- u32 vbi_cap_seq_count;
- bool vbi_cap_streaming;
- bool stream_sliced_vbi_cap;
- u32 meta_cap_seq_start;
- u32 meta_cap_seq_count;
- bool meta_cap_streaming;
-
- /* Touch capture */
- struct task_struct *kthread_touch_cap;
- unsigned long jiffies_touch_cap;
- u64 touch_cap_stream_start;
- u32 touch_cap_seq_offset;
- bool touch_cap_seq_resync;
- u32 touch_cap_seq_start;
- u32 touch_cap_seq_count;
- bool touch_cap_streaming;
- struct v4l2_fract timeperframe_tch_cap;
- struct v4l2_pix_format tch_format;
- int tch_pat_random;
-
- /* video output */
- const struct vivid_fmt *fmt_out;
- struct v4l2_fract timeperframe_vid_out;
- enum v4l2_field field_out;
- struct v4l2_rect sink_rect;
- struct v4l2_rect fmt_out_rect;
- struct v4l2_rect crop_out;
- struct v4l2_rect compose_out;
- struct v4l2_rect compose_bounds_out;
- struct vb2_queue vb_vid_out_q;
- struct list_head vid_out_active;
- struct vb2_queue vb_vbi_out_q;
- struct list_head vbi_out_active;
- struct vb2_queue vb_meta_out_q;
- struct list_head meta_out_active;
-
- /* video loop precalculated rectangles */
-
- /*
- * Intersection between what the output side composes and the capture side
- * crops. I.e., what actually needs to be copied from the output buffer to
- * the capture buffer.
- */
- struct v4l2_rect loop_vid_copy;
- /* The part of the output buffer that (after scaling) corresponds to loop_vid_copy. */
- struct v4l2_rect loop_vid_out;
- /* The part of the capture buffer that (after scaling) corresponds to loop_vid_copy. */
- struct v4l2_rect loop_vid_cap;
- /*
- * The intersection of the framebuffer, the overlay output window and
- * loop_vid_copy. I.e., the part of the framebuffer that actually should be
- * blended with the compose_out rectangle. This uses the framebuffer origin.
- */
- struct v4l2_rect loop_fb_copy;
- /* The same as loop_fb_copy but with compose_out origin. */
- struct v4l2_rect loop_vid_overlay;
- /*
- * The part of the capture buffer that (after scaling) corresponds
- * to loop_vid_overlay.
- */
- struct v4l2_rect loop_vid_overlay_cap;
-
- /* thread for generating video output stream */
- struct task_struct *kthread_vid_out;
- unsigned long jiffies_vid_out;
- u32 out_seq_offset;
- u32 out_seq_count;
- bool out_seq_resync;
- u32 vid_out_seq_start;
- u32 vid_out_seq_count;
- bool vid_out_streaming;
- u32 vbi_out_seq_start;
- u32 vbi_out_seq_count;
- bool vbi_out_streaming;
- bool stream_sliced_vbi_out;
- u32 meta_out_seq_start;
- u32 meta_out_seq_count;
- bool meta_out_streaming;
-
- /* SDR capture */
- struct vb2_queue vb_sdr_cap_q;
- struct list_head sdr_cap_active;
- u32 sdr_pixelformat; /* v4l2 format id */
- unsigned sdr_buffersize;
- unsigned sdr_adc_freq;
- unsigned sdr_fm_freq;
- unsigned sdr_fm_deviation;
- int sdr_fixp_src_phase;
- int sdr_fixp_mod_phase;
-
- bool tstamp_src_is_soe;
- bool has_crop_cap;
- bool has_compose_cap;
- bool has_scaler_cap;
- bool has_crop_out;
- bool has_compose_out;
- bool has_scaler_out;
-
- /* thread for generating SDR stream */
- struct task_struct *kthread_sdr_cap;
- unsigned long jiffies_sdr_cap;
- u32 sdr_cap_seq_offset;
- u32 sdr_cap_seq_count;
- bool sdr_cap_seq_resync;
-
- /* RDS generator */
- struct vivid_rds_gen rds_gen;
-
- /* Radio receiver */
- unsigned radio_rx_freq;
- unsigned radio_rx_audmode;
- int radio_rx_sig_qual;
- unsigned radio_rx_hw_seek_mode;
- bool radio_rx_hw_seek_prog_lim;
- bool radio_rx_rds_controls;
- bool radio_rx_rds_enabled;
- unsigned radio_rx_rds_use_alternates;
- unsigned radio_rx_rds_last_block;
- struct v4l2_fh *radio_rx_rds_owner;
-
- /* Radio transmitter */
- unsigned radio_tx_freq;
- unsigned radio_tx_subchans;
- bool radio_tx_rds_controls;
- unsigned radio_tx_rds_last_block;
- struct v4l2_fh *radio_tx_rds_owner;
-
- /* Shared between radio receiver and transmitter */
- bool radio_rds_loop;
- ktime_t radio_rds_init_time;
-
- /* CEC */
- struct cec_adapter *cec_rx_adap;
- struct cec_adapter *cec_tx_adap[MAX_OUTPUTS];
- struct workqueue_struct *cec_workqueue;
- spinlock_t cec_slock;
- struct list_head cec_work_list;
- unsigned int cec_xfer_time_jiffies;
- unsigned long cec_xfer_start_jiffies;
- u8 cec_output2bus_map[MAX_OUTPUTS];
-
- /* CEC OSD String */
- char osd[14];
- unsigned long osd_jiffies;
-
- bool meta_pts;
- bool meta_scr;
-};
-
-static inline bool vivid_is_webcam(const struct vivid_dev *dev)
-{
- return dev->input_type[dev->input] == WEBCAM;
-}
-
-static inline bool vivid_is_tv_cap(const struct vivid_dev *dev)
-{
- return dev->input_type[dev->input] == TV;
-}
-
-static inline bool vivid_is_svid_cap(const struct vivid_dev *dev)
-{
- return dev->input_type[dev->input] == SVID;
-}
-
-static inline bool vivid_is_hdmi_cap(const struct vivid_dev *dev)
-{
- return dev->input_type[dev->input] == HDMI;
-}
-
-static inline bool vivid_is_sdtv_cap(const struct vivid_dev *dev)
-{
- return vivid_is_tv_cap(dev) || vivid_is_svid_cap(dev);
-}
-
-static inline bool vivid_is_svid_out(const struct vivid_dev *dev)
-{
- return dev->output_type[dev->output] == SVID;
-}
-
-static inline bool vivid_is_hdmi_out(const struct vivid_dev *dev)
-{
- return dev->output_type[dev->output] == HDMI;
-}
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
deleted file mode 100644
index 334130568dcb..000000000000
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ /dev/null
@@ -1,1939 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-ctrls.c - control support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-common.h>
-
-#include "vivid-core.h"
-#include "vivid-vid-cap.h"
-#include "vivid-vid-out.h"
-#include "vivid-vid-common.h"
-#include "vivid-radio-common.h"
-#include "vivid-osd.h"
-#include "vivid-ctrls.h"
-#include "vivid-cec.h"
-
-#define VIVID_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
-#define VIVID_CID_BUTTON (VIVID_CID_CUSTOM_BASE + 0)
-#define VIVID_CID_BOOLEAN (VIVID_CID_CUSTOM_BASE + 1)
-#define VIVID_CID_INTEGER (VIVID_CID_CUSTOM_BASE + 2)
-#define VIVID_CID_INTEGER64 (VIVID_CID_CUSTOM_BASE + 3)
-#define VIVID_CID_MENU (VIVID_CID_CUSTOM_BASE + 4)
-#define VIVID_CID_STRING (VIVID_CID_CUSTOM_BASE + 5)
-#define VIVID_CID_BITMASK (VIVID_CID_CUSTOM_BASE + 6)
-#define VIVID_CID_INTMENU (VIVID_CID_CUSTOM_BASE + 7)
-#define VIVID_CID_U32_ARRAY (VIVID_CID_CUSTOM_BASE + 8)
-#define VIVID_CID_U16_MATRIX (VIVID_CID_CUSTOM_BASE + 9)
-#define VIVID_CID_U8_4D_ARRAY (VIVID_CID_CUSTOM_BASE + 10)
-#define VIVID_CID_AREA (VIVID_CID_CUSTOM_BASE + 11)
-
-#define VIVID_CID_VIVID_BASE (0x00f00000 | 0xf000)
-#define VIVID_CID_VIVID_CLASS (0x00f00000 | 1)
-#define VIVID_CID_TEST_PATTERN (VIVID_CID_VIVID_BASE + 0)
-#define VIVID_CID_OSD_TEXT_MODE (VIVID_CID_VIVID_BASE + 1)
-#define VIVID_CID_HOR_MOVEMENT (VIVID_CID_VIVID_BASE + 2)
-#define VIVID_CID_VERT_MOVEMENT (VIVID_CID_VIVID_BASE + 3)
-#define VIVID_CID_SHOW_BORDER (VIVID_CID_VIVID_BASE + 4)
-#define VIVID_CID_SHOW_SQUARE (VIVID_CID_VIVID_BASE + 5)
-#define VIVID_CID_INSERT_SAV (VIVID_CID_VIVID_BASE + 6)
-#define VIVID_CID_INSERT_EAV (VIVID_CID_VIVID_BASE + 7)
-#define VIVID_CID_VBI_CAP_INTERLACED (VIVID_CID_VIVID_BASE + 8)
-
-#define VIVID_CID_HFLIP (VIVID_CID_VIVID_BASE + 20)
-#define VIVID_CID_VFLIP (VIVID_CID_VIVID_BASE + 21)
-#define VIVID_CID_STD_ASPECT_RATIO (VIVID_CID_VIVID_BASE + 22)
-#define VIVID_CID_DV_TIMINGS_ASPECT_RATIO (VIVID_CID_VIVID_BASE + 23)
-#define VIVID_CID_TSTAMP_SRC (VIVID_CID_VIVID_BASE + 24)
-#define VIVID_CID_COLORSPACE (VIVID_CID_VIVID_BASE + 25)
-#define VIVID_CID_XFER_FUNC (VIVID_CID_VIVID_BASE + 26)
-#define VIVID_CID_YCBCR_ENC (VIVID_CID_VIVID_BASE + 27)
-#define VIVID_CID_QUANTIZATION (VIVID_CID_VIVID_BASE + 28)
-#define VIVID_CID_LIMITED_RGB_RANGE (VIVID_CID_VIVID_BASE + 29)
-#define VIVID_CID_ALPHA_MODE (VIVID_CID_VIVID_BASE + 30)
-#define VIVID_CID_HAS_CROP_CAP (VIVID_CID_VIVID_BASE + 31)
-#define VIVID_CID_HAS_COMPOSE_CAP (VIVID_CID_VIVID_BASE + 32)
-#define VIVID_CID_HAS_SCALER_CAP (VIVID_CID_VIVID_BASE + 33)
-#define VIVID_CID_HAS_CROP_OUT (VIVID_CID_VIVID_BASE + 34)
-#define VIVID_CID_HAS_COMPOSE_OUT (VIVID_CID_VIVID_BASE + 35)
-#define VIVID_CID_HAS_SCALER_OUT (VIVID_CID_VIVID_BASE + 36)
-#define VIVID_CID_LOOP_VIDEO (VIVID_CID_VIVID_BASE + 37)
-#define VIVID_CID_SEQ_WRAP (VIVID_CID_VIVID_BASE + 38)
-#define VIVID_CID_TIME_WRAP (VIVID_CID_VIVID_BASE + 39)
-#define VIVID_CID_MAX_EDID_BLOCKS (VIVID_CID_VIVID_BASE + 40)
-#define VIVID_CID_PERCENTAGE_FILL (VIVID_CID_VIVID_BASE + 41)
-#define VIVID_CID_REDUCED_FPS (VIVID_CID_VIVID_BASE + 42)
-#define VIVID_CID_HSV_ENC (VIVID_CID_VIVID_BASE + 43)
-#define VIVID_CID_DISPLAY_PRESENT (VIVID_CID_VIVID_BASE + 44)
-
-#define VIVID_CID_STD_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 60)
-#define VIVID_CID_STANDARD (VIVID_CID_VIVID_BASE + 61)
-#define VIVID_CID_DV_TIMINGS_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 62)
-#define VIVID_CID_DV_TIMINGS (VIVID_CID_VIVID_BASE + 63)
-#define VIVID_CID_PERC_DROPPED (VIVID_CID_VIVID_BASE + 64)
-#define VIVID_CID_DISCONNECT (VIVID_CID_VIVID_BASE + 65)
-#define VIVID_CID_DQBUF_ERROR (VIVID_CID_VIVID_BASE + 66)
-#define VIVID_CID_QUEUE_SETUP_ERROR (VIVID_CID_VIVID_BASE + 67)
-#define VIVID_CID_BUF_PREPARE_ERROR (VIVID_CID_VIVID_BASE + 68)
-#define VIVID_CID_START_STR_ERROR (VIVID_CID_VIVID_BASE + 69)
-#define VIVID_CID_QUEUE_ERROR (VIVID_CID_VIVID_BASE + 70)
-#define VIVID_CID_CLEAR_FB (VIVID_CID_VIVID_BASE + 71)
-#define VIVID_CID_REQ_VALIDATE_ERROR (VIVID_CID_VIVID_BASE + 72)
-
-#define VIVID_CID_RADIO_SEEK_MODE (VIVID_CID_VIVID_BASE + 90)
-#define VIVID_CID_RADIO_SEEK_PROG_LIM (VIVID_CID_VIVID_BASE + 91)
-#define VIVID_CID_RADIO_RX_RDS_RBDS (VIVID_CID_VIVID_BASE + 92)
-#define VIVID_CID_RADIO_RX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 93)
-
-#define VIVID_CID_RADIO_TX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 94)
-
-#define VIVID_CID_SDR_CAP_FM_DEVIATION (VIVID_CID_VIVID_BASE + 110)
-
-#define VIVID_CID_META_CAP_GENERATE_PTS (VIVID_CID_VIVID_BASE + 111)
-#define VIVID_CID_META_CAP_GENERATE_SCR (VIVID_CID_VIVID_BASE + 112)
-
-/* General User Controls */
-
-static int vivid_user_gen_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_gen);
-
- switch (ctrl->id) {
- case VIVID_CID_DISCONNECT:
- v4l2_info(&dev->v4l2_dev, "disconnect\n");
- clear_bit(V4L2_FL_REGISTERED, &dev->vid_cap_dev.flags);
- clear_bit(V4L2_FL_REGISTERED, &dev->vid_out_dev.flags);
- clear_bit(V4L2_FL_REGISTERED, &dev->vbi_cap_dev.flags);
- clear_bit(V4L2_FL_REGISTERED, &dev->vbi_out_dev.flags);
- clear_bit(V4L2_FL_REGISTERED, &dev->sdr_cap_dev.flags);
- clear_bit(V4L2_FL_REGISTERED, &dev->radio_rx_dev.flags);
- clear_bit(V4L2_FL_REGISTERED, &dev->radio_tx_dev.flags);
- clear_bit(V4L2_FL_REGISTERED, &dev->meta_cap_dev.flags);
- break;
- case VIVID_CID_BUTTON:
- dev->button_pressed = 30;
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_user_gen_ctrl_ops = {
- .s_ctrl = vivid_user_gen_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_button = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_BUTTON,
- .name = "Button",
- .type = V4L2_CTRL_TYPE_BUTTON,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_boolean = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_BOOLEAN,
- .name = "Boolean",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .min = 0,
- .max = 1,
- .step = 1,
- .def = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_int32 = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_INTEGER,
- .name = "Integer 32 Bits",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 0xffffffff80000000ULL,
- .max = 0x7fffffff,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_int64 = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_INTEGER64,
- .name = "Integer 64 Bits",
- .type = V4L2_CTRL_TYPE_INTEGER64,
- .min = 0x8000000000000000ULL,
- .max = 0x7fffffffffffffffLL,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_u32_array = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_U32_ARRAY,
- .name = "U32 1 Element Array",
- .type = V4L2_CTRL_TYPE_U32,
- .def = 0x18,
- .min = 0x10,
- .max = 0x20000,
- .step = 1,
- .dims = { 1 },
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_u16_matrix = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_U16_MATRIX,
- .name = "U16 8x16 Matrix",
- .type = V4L2_CTRL_TYPE_U16,
- .def = 0x18,
- .min = 0x10,
- .max = 0x2000,
- .step = 1,
- .dims = { 8, 16 },
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_u8_4d_array = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_U8_4D_ARRAY,
- .name = "U8 2x3x4x5 Array",
- .type = V4L2_CTRL_TYPE_U8,
- .def = 0x18,
- .min = 0x10,
- .max = 0x20,
- .step = 1,
- .dims = { 2, 3, 4, 5 },
-};
-
-static const char * const vivid_ctrl_menu_strings[] = {
- "Menu Item 0 (Skipped)",
- "Menu Item 1",
- "Menu Item 2 (Skipped)",
- "Menu Item 3",
- "Menu Item 4",
- "Menu Item 5 (Skipped)",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_menu = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_MENU,
- .name = "Menu",
- .type = V4L2_CTRL_TYPE_MENU,
- .min = 1,
- .max = 4,
- .def = 3,
- .menu_skip_mask = 0x04,
- .qmenu = vivid_ctrl_menu_strings,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_string = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_STRING,
- .name = "String",
- .type = V4L2_CTRL_TYPE_STRING,
- .min = 2,
- .max = 4,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_bitmask = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_BITMASK,
- .name = "Bitmask",
- .type = V4L2_CTRL_TYPE_BITMASK,
- .def = 0x80002000,
- .min = 0,
- .max = 0x80402010,
- .step = 0,
-};
-
-static const s64 vivid_ctrl_int_menu_values[] = {
- 1, 1, 2, 3, 5, 8, 13, 21, 42,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_int_menu = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_INTMENU,
- .name = "Integer Menu",
- .type = V4L2_CTRL_TYPE_INTEGER_MENU,
- .min = 1,
- .max = 8,
- .def = 4,
- .menu_skip_mask = 0x02,
- .qmenu_int = vivid_ctrl_int_menu_values,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_disconnect = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_DISCONNECT,
- .name = "Disconnect",
- .type = V4L2_CTRL_TYPE_BUTTON,
-};
-
-static const struct v4l2_area area = {
- .width = 1000,
- .height = 2000,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_area = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_AREA,
- .name = "Area",
- .type = V4L2_CTRL_TYPE_AREA,
- .p_def.p_const = &area,
-};
-
-/* Framebuffer Controls */
-
-static int vivid_fb_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler,
- struct vivid_dev, ctrl_hdl_fb);
-
- switch (ctrl->id) {
- case VIVID_CID_CLEAR_FB:
- vivid_clear_fb(dev);
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_fb_ctrl_ops = {
- .s_ctrl = vivid_fb_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_clear_fb = {
- .ops = &vivid_fb_ctrl_ops,
- .id = VIVID_CID_CLEAR_FB,
- .name = "Clear Framebuffer",
- .type = V4L2_CTRL_TYPE_BUTTON,
-};
-
-
-/* Video User Controls */
-
-static int vivid_user_vid_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
-
- switch (ctrl->id) {
- case V4L2_CID_AUTOGAIN:
- dev->gain->val = (jiffies_to_msecs(jiffies) / 1000) & 0xff;
- break;
- }
- return 0;
-}
-
-static int vivid_user_vid_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
-
- switch (ctrl->id) {
- case V4L2_CID_BRIGHTNESS:
- dev->input_brightness[dev->input] = ctrl->val - dev->input * 128;
- tpg_s_brightness(&dev->tpg, dev->input_brightness[dev->input]);
- break;
- case V4L2_CID_CONTRAST:
- tpg_s_contrast(&dev->tpg, ctrl->val);
- break;
- case V4L2_CID_SATURATION:
- tpg_s_saturation(&dev->tpg, ctrl->val);
- break;
- case V4L2_CID_HUE:
- tpg_s_hue(&dev->tpg, ctrl->val);
- break;
- case V4L2_CID_HFLIP:
- dev->hflip = ctrl->val;
- tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
- break;
- case V4L2_CID_VFLIP:
- dev->vflip = ctrl->val;
- tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
- break;
- case V4L2_CID_ALPHA_COMPONENT:
- tpg_s_alpha_component(&dev->tpg, ctrl->val);
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_user_vid_ctrl_ops = {
- .g_volatile_ctrl = vivid_user_vid_g_volatile_ctrl,
- .s_ctrl = vivid_user_vid_s_ctrl,
-};
-
-
-/* Video Capture Controls */
-
-static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- static const u32 colorspaces[] = {
- V4L2_COLORSPACE_SMPTE170M,
- V4L2_COLORSPACE_REC709,
- V4L2_COLORSPACE_SRGB,
- V4L2_COLORSPACE_OPRGB,
- V4L2_COLORSPACE_BT2020,
- V4L2_COLORSPACE_DCI_P3,
- V4L2_COLORSPACE_SMPTE240M,
- V4L2_COLORSPACE_470_SYSTEM_M,
- V4L2_COLORSPACE_470_SYSTEM_BG,
- };
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap);
- unsigned int i, j;
-
- switch (ctrl->id) {
- case VIVID_CID_TEST_PATTERN:
- vivid_update_quality(dev);
- tpg_s_pattern(&dev->tpg, ctrl->val);
- break;
- case VIVID_CID_COLORSPACE:
- tpg_s_colorspace(&dev->tpg, colorspaces[ctrl->val]);
- vivid_send_source_change(dev, TV);
- vivid_send_source_change(dev, SVID);
- vivid_send_source_change(dev, HDMI);
- vivid_send_source_change(dev, WEBCAM);
- break;
- case VIVID_CID_XFER_FUNC:
- tpg_s_xfer_func(&dev->tpg, ctrl->val);
- vivid_send_source_change(dev, TV);
- vivid_send_source_change(dev, SVID);
- vivid_send_source_change(dev, HDMI);
- vivid_send_source_change(dev, WEBCAM);
- break;
- case VIVID_CID_YCBCR_ENC:
- tpg_s_ycbcr_enc(&dev->tpg, ctrl->val);
- vivid_send_source_change(dev, TV);
- vivid_send_source_change(dev, SVID);
- vivid_send_source_change(dev, HDMI);
- vivid_send_source_change(dev, WEBCAM);
- break;
- case VIVID_CID_HSV_ENC:
- tpg_s_hsv_enc(&dev->tpg, ctrl->val ? V4L2_HSV_ENC_256 :
- V4L2_HSV_ENC_180);
- vivid_send_source_change(dev, TV);
- vivid_send_source_change(dev, SVID);
- vivid_send_source_change(dev, HDMI);
- vivid_send_source_change(dev, WEBCAM);
- break;
- case VIVID_CID_QUANTIZATION:
- tpg_s_quantization(&dev->tpg, ctrl->val);
- vivid_send_source_change(dev, TV);
- vivid_send_source_change(dev, SVID);
- vivid_send_source_change(dev, HDMI);
- vivid_send_source_change(dev, WEBCAM);
- break;
- case V4L2_CID_DV_RX_RGB_RANGE:
- if (!vivid_is_hdmi_cap(dev))
- break;
- tpg_s_rgb_range(&dev->tpg, ctrl->val);
- break;
- case VIVID_CID_LIMITED_RGB_RANGE:
- tpg_s_real_rgb_range(&dev->tpg, ctrl->val ?
- V4L2_DV_RGB_RANGE_LIMITED : V4L2_DV_RGB_RANGE_FULL);
- break;
- case VIVID_CID_ALPHA_MODE:
- tpg_s_alpha_mode(&dev->tpg, ctrl->val);
- break;
- case VIVID_CID_HOR_MOVEMENT:
- tpg_s_mv_hor_mode(&dev->tpg, ctrl->val);
- break;
- case VIVID_CID_VERT_MOVEMENT:
- tpg_s_mv_vert_mode(&dev->tpg, ctrl->val);
- break;
- case VIVID_CID_OSD_TEXT_MODE:
- dev->osd_mode = ctrl->val;
- break;
- case VIVID_CID_PERCENTAGE_FILL:
- tpg_s_perc_fill(&dev->tpg, ctrl->val);
- for (i = 0; i < VIDEO_MAX_FRAME; i++)
- dev->must_blank[i] = ctrl->val < 100;
- break;
- case VIVID_CID_INSERT_SAV:
- tpg_s_insert_sav(&dev->tpg, ctrl->val);
- break;
- case VIVID_CID_INSERT_EAV:
- tpg_s_insert_eav(&dev->tpg, ctrl->val);
- break;
- case VIVID_CID_HFLIP:
- dev->sensor_hflip = ctrl->val;
- tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
- break;
- case VIVID_CID_VFLIP:
- dev->sensor_vflip = ctrl->val;
- tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
- break;
- case VIVID_CID_REDUCED_FPS:
- dev->reduced_fps = ctrl->val;
- vivid_update_format_cap(dev, true);
- break;
- case VIVID_CID_HAS_CROP_CAP:
- dev->has_crop_cap = ctrl->val;
- vivid_update_format_cap(dev, true);
- break;
- case VIVID_CID_HAS_COMPOSE_CAP:
- dev->has_compose_cap = ctrl->val;
- vivid_update_format_cap(dev, true);
- break;
- case VIVID_CID_HAS_SCALER_CAP:
- dev->has_scaler_cap = ctrl->val;
- vivid_update_format_cap(dev, true);
- break;
- case VIVID_CID_SHOW_BORDER:
- tpg_s_show_border(&dev->tpg, ctrl->val);
- break;
- case VIVID_CID_SHOW_SQUARE:
- tpg_s_show_square(&dev->tpg, ctrl->val);
- break;
- case VIVID_CID_STD_ASPECT_RATIO:
- dev->std_aspect_ratio[dev->input] = ctrl->val;
- tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
- break;
- case VIVID_CID_DV_TIMINGS_SIGNAL_MODE:
- dev->dv_timings_signal_mode[dev->input] =
- dev->ctrl_dv_timings_signal_mode->val;
- dev->query_dv_timings[dev->input] = dev->ctrl_dv_timings->val;
-
- dev->power_present = 0;
- for (i = 0, j = 0;
- i < ARRAY_SIZE(dev->dv_timings_signal_mode);
- i++)
- if (dev->input_type[i] == HDMI) {
- if (dev->dv_timings_signal_mode[i] != NO_SIGNAL)
- dev->power_present |= (1 << j);
- j++;
- }
- __v4l2_ctrl_s_ctrl(dev->ctrl_rx_power_present,
- dev->power_present);
-
- v4l2_ctrl_activate(dev->ctrl_dv_timings,
- dev->dv_timings_signal_mode[dev->input] ==
- SELECTED_DV_TIMINGS);
-
- vivid_update_quality(dev);
- vivid_send_source_change(dev, HDMI);
- break;
- case VIVID_CID_DV_TIMINGS_ASPECT_RATIO:
- dev->dv_timings_aspect_ratio[dev->input] = ctrl->val;
- tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
- break;
- case VIVID_CID_TSTAMP_SRC:
- dev->tstamp_src_is_soe = ctrl->val;
- dev->vb_vid_cap_q.timestamp_flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- if (dev->tstamp_src_is_soe)
- dev->vb_vid_cap_q.timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
- break;
- case VIVID_CID_MAX_EDID_BLOCKS:
- dev->edid_max_blocks = ctrl->val;
- if (dev->edid_blocks > dev->edid_max_blocks)
- dev->edid_blocks = dev->edid_max_blocks;
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_vid_cap_ctrl_ops = {
- .s_ctrl = vivid_vid_cap_s_ctrl,
-};
-
-static const char * const vivid_ctrl_hor_movement_strings[] = {
- "Move Left Fast",
- "Move Left",
- "Move Left Slow",
- "No Movement",
- "Move Right Slow",
- "Move Right",
- "Move Right Fast",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_hor_movement = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_HOR_MOVEMENT,
- .name = "Horizontal Movement",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = TPG_MOVE_POS_FAST,
- .def = TPG_MOVE_NONE,
- .qmenu = vivid_ctrl_hor_movement_strings,
-};
-
-static const char * const vivid_ctrl_vert_movement_strings[] = {
- "Move Up Fast",
- "Move Up",
- "Move Up Slow",
- "No Movement",
- "Move Down Slow",
- "Move Down",
- "Move Down Fast",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_vert_movement = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_VERT_MOVEMENT,
- .name = "Vertical Movement",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = TPG_MOVE_POS_FAST,
- .def = TPG_MOVE_NONE,
- .qmenu = vivid_ctrl_vert_movement_strings,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_show_border = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_SHOW_BORDER,
- .name = "Show Border",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_show_square = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_SHOW_SQUARE,
- .name = "Show Square",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const char * const vivid_ctrl_osd_mode_strings[] = {
- "All",
- "Counters Only",
- "None",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_osd_mode = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_OSD_TEXT_MODE,
- .name = "OSD Text Mode",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = ARRAY_SIZE(vivid_ctrl_osd_mode_strings) - 2,
- .qmenu = vivid_ctrl_osd_mode_strings,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_perc_fill = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_PERCENTAGE_FILL,
- .name = "Fill Percentage of Frame",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 0,
- .max = 100,
- .def = 100,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_insert_sav = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_INSERT_SAV,
- .name = "Insert SAV Code in Image",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_insert_eav = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_INSERT_EAV,
- .name = "Insert EAV Code in Image",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_hflip = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_HFLIP,
- .name = "Sensor Flipped Horizontally",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_vflip = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_VFLIP,
- .name = "Sensor Flipped Vertically",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_reduced_fps = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_REDUCED_FPS,
- .name = "Reduced Framerate",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_has_crop_cap = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_HAS_CROP_CAP,
- .name = "Enable Capture Cropping",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .def = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_has_compose_cap = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_HAS_COMPOSE_CAP,
- .name = "Enable Capture Composing",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .def = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_cap = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_HAS_SCALER_CAP,
- .name = "Enable Capture Scaler",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .def = 1,
- .step = 1,
-};
-
-static const char * const vivid_ctrl_tstamp_src_strings[] = {
- "End of Frame",
- "Start of Exposure",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_tstamp_src = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_TSTAMP_SRC,
- .name = "Timestamp Source",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = ARRAY_SIZE(vivid_ctrl_tstamp_src_strings) - 2,
- .qmenu = vivid_ctrl_tstamp_src_strings,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_std_aspect_ratio = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_STD_ASPECT_RATIO,
- .name = "Standard Aspect Ratio",
- .type = V4L2_CTRL_TYPE_MENU,
- .min = 1,
- .max = 4,
- .def = 1,
- .qmenu = tpg_aspect_strings,
-};
-
-static const char * const vivid_ctrl_dv_timings_signal_mode_strings[] = {
- "Current DV Timings",
- "No Signal",
- "No Lock",
- "Out of Range",
- "Selected DV Timings",
- "Cycle Through All DV Timings",
- "Custom DV Timings",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_dv_timings_signal_mode = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_DV_TIMINGS_SIGNAL_MODE,
- .name = "DV Timings Signal Mode",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = 5,
- .qmenu = vivid_ctrl_dv_timings_signal_mode_strings,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_dv_timings_aspect_ratio = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_DV_TIMINGS_ASPECT_RATIO,
- .name = "DV Timings Aspect Ratio",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = 3,
- .qmenu = tpg_aspect_strings,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_max_edid_blocks = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_MAX_EDID_BLOCKS,
- .name = "Maximum EDID Blocks",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 1,
- .max = 256,
- .def = 2,
- .step = 1,
-};
-
-static const char * const vivid_ctrl_colorspace_strings[] = {
- "SMPTE 170M",
- "Rec. 709",
- "sRGB",
- "opRGB",
- "BT.2020",
- "DCI-P3",
- "SMPTE 240M",
- "470 System M",
- "470 System BG",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_colorspace = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_COLORSPACE,
- .name = "Colorspace",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = ARRAY_SIZE(vivid_ctrl_colorspace_strings) - 2,
- .def = 2,
- .qmenu = vivid_ctrl_colorspace_strings,
-};
-
-static const char * const vivid_ctrl_xfer_func_strings[] = {
- "Default",
- "Rec. 709",
- "sRGB",
- "opRGB",
- "SMPTE 240M",
- "None",
- "DCI-P3",
- "SMPTE 2084",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_xfer_func = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_XFER_FUNC,
- .name = "Transfer Function",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = ARRAY_SIZE(vivid_ctrl_xfer_func_strings) - 2,
- .qmenu = vivid_ctrl_xfer_func_strings,
-};
-
-static const char * const vivid_ctrl_ycbcr_enc_strings[] = {
- "Default",
- "ITU-R 601",
- "Rec. 709",
- "xvYCC 601",
- "xvYCC 709",
- "",
- "BT.2020",
- "BT.2020 Constant Luminance",
- "SMPTE 240M",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_YCBCR_ENC,
- .name = "Y'CbCr Encoding",
- .type = V4L2_CTRL_TYPE_MENU,
- .menu_skip_mask = 1 << 5,
- .max = ARRAY_SIZE(vivid_ctrl_ycbcr_enc_strings) - 2,
- .qmenu = vivid_ctrl_ycbcr_enc_strings,
-};
-
-static const char * const vivid_ctrl_hsv_enc_strings[] = {
- "Hue 0-179",
- "Hue 0-256",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_hsv_enc = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_HSV_ENC,
- .name = "HSV Encoding",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = ARRAY_SIZE(vivid_ctrl_hsv_enc_strings) - 2,
- .qmenu = vivid_ctrl_hsv_enc_strings,
-};
-
-static const char * const vivid_ctrl_quantization_strings[] = {
- "Default",
- "Full Range",
- "Limited Range",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_quantization = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_QUANTIZATION,
- .name = "Quantization",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = ARRAY_SIZE(vivid_ctrl_quantization_strings) - 2,
- .qmenu = vivid_ctrl_quantization_strings,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_ALPHA_MODE,
- .name = "Apply Alpha To Red Only",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_limited_rgb_range = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_LIMITED_RGB_RANGE,
- .name = "Limited RGB Range (16-235)",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-
-/* Video Loop Control */
-
-static int vivid_loop_cap_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_loop_cap);
-
- switch (ctrl->id) {
- case VIVID_CID_LOOP_VIDEO:
- dev->loop_video = ctrl->val;
- vivid_update_quality(dev);
- vivid_send_source_change(dev, SVID);
- vivid_send_source_change(dev, HDMI);
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_loop_cap_ctrl_ops = {
- .s_ctrl = vivid_loop_cap_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_loop_video = {
- .ops = &vivid_loop_cap_ctrl_ops,
- .id = VIVID_CID_LOOP_VIDEO,
- .name = "Loop Video",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-
-/* VBI Capture Control */
-
-static int vivid_vbi_cap_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vbi_cap);
-
- switch (ctrl->id) {
- case VIVID_CID_VBI_CAP_INTERLACED:
- dev->vbi_cap_interlaced = ctrl->val;
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_vbi_cap_ctrl_ops = {
- .s_ctrl = vivid_vbi_cap_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_vbi_cap_interlaced = {
- .ops = &vivid_vbi_cap_ctrl_ops,
- .id = VIVID_CID_VBI_CAP_INTERLACED,
- .name = "Interlaced VBI Format",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-
-/* Video Output Controls */
-
-static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
- struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
- u32 display_present = 0;
- unsigned int i, j, bus_idx;
-
- switch (ctrl->id) {
- case VIVID_CID_HAS_CROP_OUT:
- dev->has_crop_out = ctrl->val;
- vivid_update_format_out(dev);
- break;
- case VIVID_CID_HAS_COMPOSE_OUT:
- dev->has_compose_out = ctrl->val;
- vivid_update_format_out(dev);
- break;
- case VIVID_CID_HAS_SCALER_OUT:
- dev->has_scaler_out = ctrl->val;
- vivid_update_format_out(dev);
- break;
- case V4L2_CID_DV_TX_MODE:
- dev->dvi_d_out = ctrl->val == V4L2_DV_TX_MODE_DVI_D;
- if (!vivid_is_hdmi_out(dev))
- break;
- if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
- if (bt->width == 720 && bt->height <= 576)
- dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
- else
- dev->colorspace_out = V4L2_COLORSPACE_REC709;
- dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
- } else {
- dev->colorspace_out = V4L2_COLORSPACE_SRGB;
- dev->quantization_out = dev->dvi_d_out ?
- V4L2_QUANTIZATION_LIM_RANGE :
- V4L2_QUANTIZATION_DEFAULT;
- }
- if (dev->loop_video)
- vivid_send_source_change(dev, HDMI);
- break;
- case VIVID_CID_DISPLAY_PRESENT:
- if (dev->output_type[dev->output] != HDMI)
- break;
-
- dev->display_present[dev->output] = ctrl->val;
- for (i = 0, j = 0; i < dev->num_outputs; i++)
- if (dev->output_type[i] == HDMI)
- display_present |=
- dev->display_present[i] << j++;
-
- __v4l2_ctrl_s_ctrl(dev->ctrl_tx_rxsense, display_present);
-
- if (dev->edid_blocks) {
- __v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present,
- display_present);
- __v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug,
- display_present);
- }
-
- bus_idx = dev->cec_output2bus_map[dev->output];
- if (!dev->cec_tx_adap[bus_idx])
- break;
-
- if (ctrl->val && dev->edid_blocks)
- cec_s_phys_addr(dev->cec_tx_adap[bus_idx],
- dev->cec_tx_adap[bus_idx]->phys_addr,
- false);
- else
- cec_phys_addr_invalidate(dev->cec_tx_adap[bus_idx]);
-
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_vid_out_ctrl_ops = {
- .s_ctrl = vivid_vid_out_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_has_crop_out = {
- .ops = &vivid_vid_out_ctrl_ops,
- .id = VIVID_CID_HAS_CROP_OUT,
- .name = "Enable Output Cropping",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .def = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_has_compose_out = {
- .ops = &vivid_vid_out_ctrl_ops,
- .id = VIVID_CID_HAS_COMPOSE_OUT,
- .name = "Enable Output Composing",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .def = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = {
- .ops = &vivid_vid_out_ctrl_ops,
- .id = VIVID_CID_HAS_SCALER_OUT,
- .name = "Enable Output Scaler",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .def = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_display_present = {
- .ops = &vivid_vid_out_ctrl_ops,
- .id = VIVID_CID_DISPLAY_PRESENT,
- .name = "Display Present",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .def = 1,
- .step = 1,
-};
-
-/* Streaming Controls */
-
-static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
- u64 rem;
-
- switch (ctrl->id) {
- case VIVID_CID_DQBUF_ERROR:
- dev->dqbuf_error = true;
- break;
- case VIVID_CID_PERC_DROPPED:
- dev->perc_dropped_buffers = ctrl->val;
- break;
- case VIVID_CID_QUEUE_SETUP_ERROR:
- dev->queue_setup_error = true;
- break;
- case VIVID_CID_BUF_PREPARE_ERROR:
- dev->buf_prepare_error = true;
- break;
- case VIVID_CID_START_STR_ERROR:
- dev->start_streaming_error = true;
- break;
- case VIVID_CID_REQ_VALIDATE_ERROR:
- dev->req_validate_error = true;
- break;
- case VIVID_CID_QUEUE_ERROR:
- if (vb2_start_streaming_called(&dev->vb_vid_cap_q))
- vb2_queue_error(&dev->vb_vid_cap_q);
- if (vb2_start_streaming_called(&dev->vb_vbi_cap_q))
- vb2_queue_error(&dev->vb_vbi_cap_q);
- if (vb2_start_streaming_called(&dev->vb_vid_out_q))
- vb2_queue_error(&dev->vb_vid_out_q);
- if (vb2_start_streaming_called(&dev->vb_vbi_out_q))
- vb2_queue_error(&dev->vb_vbi_out_q);
- if (vb2_start_streaming_called(&dev->vb_sdr_cap_q))
- vb2_queue_error(&dev->vb_sdr_cap_q);
- break;
- case VIVID_CID_SEQ_WRAP:
- dev->seq_wrap = ctrl->val;
- break;
- case VIVID_CID_TIME_WRAP:
- dev->time_wrap = ctrl->val;
- if (ctrl->val == 0) {
- dev->time_wrap_offset = 0;
- break;
- }
- /*
- * We want to set the time 16 seconds before the 32 bit tv_sec
- * value of struct timeval would wrap around. So first we
- * calculate ktime_get_ns() % ((1 << 32) * NSEC_PER_SEC), and
- * then we set the offset to ((1 << 32) - 16) * NSEC_PER_SEC).
- */
- div64_u64_rem(ktime_get_ns(),
- 0x100000000ULL * NSEC_PER_SEC, &rem);
- dev->time_wrap_offset =
- (0x100000000ULL - 16) * NSEC_PER_SEC - rem;
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_streaming_ctrl_ops = {
- .s_ctrl = vivid_streaming_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_dqbuf_error = {
- .ops = &vivid_streaming_ctrl_ops,
- .id = VIVID_CID_DQBUF_ERROR,
- .name = "Inject V4L2_BUF_FLAG_ERROR",
- .type = V4L2_CTRL_TYPE_BUTTON,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_perc_dropped = {
- .ops = &vivid_streaming_ctrl_ops,
- .id = VIVID_CID_PERC_DROPPED,
- .name = "Percentage of Dropped Buffers",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 0,
- .max = 100,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_queue_setup_error = {
- .ops = &vivid_streaming_ctrl_ops,
- .id = VIVID_CID_QUEUE_SETUP_ERROR,
- .name = "Inject VIDIOC_REQBUFS Error",
- .type = V4L2_CTRL_TYPE_BUTTON,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_buf_prepare_error = {
- .ops = &vivid_streaming_ctrl_ops,
- .id = VIVID_CID_BUF_PREPARE_ERROR,
- .name = "Inject VIDIOC_QBUF Error",
- .type = V4L2_CTRL_TYPE_BUTTON,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_start_streaming_error = {
- .ops = &vivid_streaming_ctrl_ops,
- .id = VIVID_CID_START_STR_ERROR,
- .name = "Inject VIDIOC_STREAMON Error",
- .type = V4L2_CTRL_TYPE_BUTTON,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_queue_error = {
- .ops = &vivid_streaming_ctrl_ops,
- .id = VIVID_CID_QUEUE_ERROR,
- .name = "Inject Fatal Streaming Error",
- .type = V4L2_CTRL_TYPE_BUTTON,
-};
-
-#ifdef CONFIG_MEDIA_CONTROLLER
-static const struct v4l2_ctrl_config vivid_ctrl_req_validate_error = {
- .ops = &vivid_streaming_ctrl_ops,
- .id = VIVID_CID_REQ_VALIDATE_ERROR,
- .name = "Inject req_validate() Error",
- .type = V4L2_CTRL_TYPE_BUTTON,
-};
-#endif
-
-static const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = {
- .ops = &vivid_streaming_ctrl_ops,
- .id = VIVID_CID_SEQ_WRAP,
- .name = "Wrap Sequence Number",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_time_wrap = {
- .ops = &vivid_streaming_ctrl_ops,
- .id = VIVID_CID_TIME_WRAP,
- .name = "Wrap Timestamp",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-
-/* SDTV Capture Controls */
-
-static int vivid_sdtv_cap_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdtv_cap);
-
- switch (ctrl->id) {
- case VIVID_CID_STD_SIGNAL_MODE:
- dev->std_signal_mode[dev->input] =
- dev->ctrl_std_signal_mode->val;
- if (dev->std_signal_mode[dev->input] == SELECTED_STD)
- dev->query_std[dev->input] =
- vivid_standard[dev->ctrl_standard->val];
- v4l2_ctrl_activate(dev->ctrl_standard,
- dev->std_signal_mode[dev->input] ==
- SELECTED_STD);
- vivid_update_quality(dev);
- vivid_send_source_change(dev, TV);
- vivid_send_source_change(dev, SVID);
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_sdtv_cap_ctrl_ops = {
- .s_ctrl = vivid_sdtv_cap_s_ctrl,
-};
-
-static const char * const vivid_ctrl_std_signal_mode_strings[] = {
- "Current Standard",
- "No Signal",
- "No Lock",
- "",
- "Selected Standard",
- "Cycle Through All Standards",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_std_signal_mode = {
- .ops = &vivid_sdtv_cap_ctrl_ops,
- .id = VIVID_CID_STD_SIGNAL_MODE,
- .name = "Standard Signal Mode",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = ARRAY_SIZE(vivid_ctrl_std_signal_mode_strings) - 2,
- .menu_skip_mask = 1 << 3,
- .qmenu = vivid_ctrl_std_signal_mode_strings,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_standard = {
- .ops = &vivid_sdtv_cap_ctrl_ops,
- .id = VIVID_CID_STANDARD,
- .name = "Standard",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = 14,
- .qmenu = vivid_ctrl_standard_strings,
-};
-
-
-
-/* Radio Receiver Controls */
-
-static int vivid_radio_rx_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_rx);
-
- switch (ctrl->id) {
- case VIVID_CID_RADIO_SEEK_MODE:
- dev->radio_rx_hw_seek_mode = ctrl->val;
- break;
- case VIVID_CID_RADIO_SEEK_PROG_LIM:
- dev->radio_rx_hw_seek_prog_lim = ctrl->val;
- break;
- case VIVID_CID_RADIO_RX_RDS_RBDS:
- dev->rds_gen.use_rbds = ctrl->val;
- break;
- case VIVID_CID_RADIO_RX_RDS_BLOCKIO:
- dev->radio_rx_rds_controls = ctrl->val;
- dev->radio_rx_caps &= ~V4L2_CAP_READWRITE;
- dev->radio_rx_rds_use_alternates = false;
- if (!dev->radio_rx_rds_controls) {
- dev->radio_rx_caps |= V4L2_CAP_READWRITE;
- __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, 0);
- __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, 0);
- __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, 0);
- __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, 0);
- __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, "");
- __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, "");
- }
- v4l2_ctrl_activate(dev->radio_rx_rds_pty, dev->radio_rx_rds_controls);
- v4l2_ctrl_activate(dev->radio_rx_rds_psname, dev->radio_rx_rds_controls);
- v4l2_ctrl_activate(dev->radio_rx_rds_radiotext, dev->radio_rx_rds_controls);
- v4l2_ctrl_activate(dev->radio_rx_rds_ta, dev->radio_rx_rds_controls);
- v4l2_ctrl_activate(dev->radio_rx_rds_tp, dev->radio_rx_rds_controls);
- v4l2_ctrl_activate(dev->radio_rx_rds_ms, dev->radio_rx_rds_controls);
- dev->radio_rx_dev.device_caps = dev->radio_rx_caps;
- break;
- case V4L2_CID_RDS_RECEPTION:
- dev->radio_rx_rds_enabled = ctrl->val;
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_radio_rx_ctrl_ops = {
- .s_ctrl = vivid_radio_rx_s_ctrl,
-};
-
-static const char * const vivid_ctrl_radio_rds_mode_strings[] = {
- "Block I/O",
- "Controls",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_blockio = {
- .ops = &vivid_radio_rx_ctrl_ops,
- .id = VIVID_CID_RADIO_RX_RDS_BLOCKIO,
- .name = "RDS Rx I/O Mode",
- .type = V4L2_CTRL_TYPE_MENU,
- .qmenu = vivid_ctrl_radio_rds_mode_strings,
- .max = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_rbds = {
- .ops = &vivid_radio_rx_ctrl_ops,
- .id = VIVID_CID_RADIO_RX_RDS_RBDS,
- .name = "Generate RBDS Instead of RDS",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-static const char * const vivid_ctrl_radio_hw_seek_mode_strings[] = {
- "Bounded",
- "Wrap Around",
- "Both",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_mode = {
- .ops = &vivid_radio_rx_ctrl_ops,
- .id = VIVID_CID_RADIO_SEEK_MODE,
- .name = "Radio HW Seek Mode",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = 2,
- .qmenu = vivid_ctrl_radio_hw_seek_mode_strings,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_prog_lim = {
- .ops = &vivid_radio_rx_ctrl_ops,
- .id = VIVID_CID_RADIO_SEEK_PROG_LIM,
- .name = "Radio Programmable HW Seek",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .step = 1,
-};
-
-
-/* Radio Transmitter Controls */
-
-static int vivid_radio_tx_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_tx);
-
- switch (ctrl->id) {
- case VIVID_CID_RADIO_TX_RDS_BLOCKIO:
- dev->radio_tx_rds_controls = ctrl->val;
- dev->radio_tx_caps &= ~V4L2_CAP_READWRITE;
- if (!dev->radio_tx_rds_controls)
- dev->radio_tx_caps |= V4L2_CAP_READWRITE;
- dev->radio_tx_dev.device_caps = dev->radio_tx_caps;
- break;
- case V4L2_CID_RDS_TX_PTY:
- if (dev->radio_rx_rds_controls)
- v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, ctrl->val);
- break;
- case V4L2_CID_RDS_TX_PS_NAME:
- if (dev->radio_rx_rds_controls)
- v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, ctrl->p_new.p_char);
- break;
- case V4L2_CID_RDS_TX_RADIO_TEXT:
- if (dev->radio_rx_rds_controls)
- v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, ctrl->p_new.p_char);
- break;
- case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
- if (dev->radio_rx_rds_controls)
- v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, ctrl->val);
- break;
- case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
- if (dev->radio_rx_rds_controls)
- v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, ctrl->val);
- break;
- case V4L2_CID_RDS_TX_MUSIC_SPEECH:
- if (dev->radio_rx_rds_controls)
- v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, ctrl->val);
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_radio_tx_ctrl_ops = {
- .s_ctrl = vivid_radio_tx_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = {
- .ops = &vivid_radio_tx_ctrl_ops,
- .id = VIVID_CID_RADIO_TX_RDS_BLOCKIO,
- .name = "RDS Tx I/O Mode",
- .type = V4L2_CTRL_TYPE_MENU,
- .qmenu = vivid_ctrl_radio_rds_mode_strings,
- .max = 1,
- .def = 1,
-};
-
-
-/* SDR Capture Controls */
-
-static int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap);
-
- switch (ctrl->id) {
- case VIVID_CID_SDR_CAP_FM_DEVIATION:
- dev->sdr_fm_deviation = ctrl->val;
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = {
- .s_ctrl = vivid_sdr_cap_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = {
- .ops = &vivid_sdr_cap_ctrl_ops,
- .id = VIVID_CID_SDR_CAP_FM_DEVIATION,
- .name = "FM Deviation",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 100,
- .max = 200000,
- .def = 75000,
- .step = 1,
-};
-
-/* Metadata Capture Control */
-
-static int vivid_meta_cap_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev,
- ctrl_hdl_meta_cap);
-
- switch (ctrl->id) {
- case VIVID_CID_META_CAP_GENERATE_PTS:
- dev->meta_pts = ctrl->val;
- break;
- case VIVID_CID_META_CAP_GENERATE_SCR:
- dev->meta_scr = ctrl->val;
- break;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops vivid_meta_cap_ctrl_ops = {
- .s_ctrl = vivid_meta_cap_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_meta_has_pts = {
- .ops = &vivid_meta_cap_ctrl_ops,
- .id = VIVID_CID_META_CAP_GENERATE_PTS,
- .name = "Generate PTS",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .def = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_meta_has_src_clk = {
- .ops = &vivid_meta_cap_ctrl_ops,
- .id = VIVID_CID_META_CAP_GENERATE_SCR,
- .name = "Generate SCR",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .max = 1,
- .def = 1,
- .step = 1,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_class = {
- .ops = &vivid_user_gen_ctrl_ops,
- .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
- .id = VIVID_CID_VIVID_CLASS,
- .name = "Vivid Controls",
- .type = V4L2_CTRL_TYPE_CTRL_CLASS,
-};
-
-int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
- bool show_ccs_out, bool no_error_inj,
- bool has_sdtv, bool has_hdmi)
-{
- struct v4l2_ctrl_handler *hdl_user_gen = &dev->ctrl_hdl_user_gen;
- struct v4l2_ctrl_handler *hdl_user_vid = &dev->ctrl_hdl_user_vid;
- struct v4l2_ctrl_handler *hdl_user_aud = &dev->ctrl_hdl_user_aud;
- struct v4l2_ctrl_handler *hdl_streaming = &dev->ctrl_hdl_streaming;
- struct v4l2_ctrl_handler *hdl_sdtv_cap = &dev->ctrl_hdl_sdtv_cap;
- struct v4l2_ctrl_handler *hdl_loop_cap = &dev->ctrl_hdl_loop_cap;
- struct v4l2_ctrl_handler *hdl_fb = &dev->ctrl_hdl_fb;
- struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap;
- struct v4l2_ctrl_handler *hdl_vid_out = &dev->ctrl_hdl_vid_out;
- struct v4l2_ctrl_handler *hdl_vbi_cap = &dev->ctrl_hdl_vbi_cap;
- struct v4l2_ctrl_handler *hdl_vbi_out = &dev->ctrl_hdl_vbi_out;
- struct v4l2_ctrl_handler *hdl_radio_rx = &dev->ctrl_hdl_radio_rx;
- struct v4l2_ctrl_handler *hdl_radio_tx = &dev->ctrl_hdl_radio_tx;
- struct v4l2_ctrl_handler *hdl_sdr_cap = &dev->ctrl_hdl_sdr_cap;
- struct v4l2_ctrl_handler *hdl_meta_cap = &dev->ctrl_hdl_meta_cap;
- struct v4l2_ctrl_handler *hdl_meta_out = &dev->ctrl_hdl_meta_out;
- struct v4l2_ctrl_handler *hdl_tch_cap = &dev->ctrl_hdl_touch_cap;
-
- struct v4l2_ctrl_config vivid_ctrl_dv_timings = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_DV_TIMINGS,
- .name = "DV Timings",
- .type = V4L2_CTRL_TYPE_MENU,
- };
- int i;
-
- v4l2_ctrl_handler_init(hdl_user_gen, 10);
- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_user_vid, 9);
- v4l2_ctrl_new_custom(hdl_user_vid, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_user_aud, 2);
- v4l2_ctrl_new_custom(hdl_user_aud, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_streaming, 8);
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_sdtv_cap, 2);
- v4l2_ctrl_new_custom(hdl_sdtv_cap, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_loop_cap, 1);
- v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_fb, 1);
- v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_vid_cap, 55);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_vid_out, 26);
- if (!no_error_inj || dev->has_fb || dev->num_hdmi_outputs)
- v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_vbi_cap, 21);
- v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_vbi_out, 19);
- if (!no_error_inj)
- v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_radio_rx, 17);
- v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_radio_tx, 17);
- v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_sdr_cap, 19);
- v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_meta_cap, 2);
- v4l2_ctrl_new_custom(hdl_meta_cap, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_meta_out, 2);
- v4l2_ctrl_new_custom(hdl_meta_out, &vivid_ctrl_class, NULL);
- v4l2_ctrl_handler_init(hdl_tch_cap, 2);
- v4l2_ctrl_new_custom(hdl_tch_cap, &vivid_ctrl_class, NULL);
-
- /* User Controls */
- dev->volume = v4l2_ctrl_new_std(hdl_user_aud, NULL,
- V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
- dev->mute = v4l2_ctrl_new_std(hdl_user_aud, NULL,
- V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
- if (dev->has_vid_cap) {
- dev->brightness = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
- V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
- for (i = 0; i < MAX_INPUTS; i++)
- dev->input_brightness[i] = 128;
- dev->contrast = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
- V4L2_CID_CONTRAST, 0, 255, 1, 128);
- dev->saturation = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
- V4L2_CID_SATURATION, 0, 255, 1, 128);
- dev->hue = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
- V4L2_CID_HUE, -128, 128, 1, 0);
- v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
- V4L2_CID_HFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
- V4L2_CID_VFLIP, 0, 1, 1, 0);
- dev->autogain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
- V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
- dev->gain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
- V4L2_CID_GAIN, 0, 255, 1, 100);
- dev->alpha = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
- V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
- }
- dev->button = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_button, NULL);
- dev->int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int32, NULL);
- dev->int64 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int64, NULL);
- dev->boolean = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_boolean, NULL);
- dev->menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_menu, NULL);
- dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL);
- dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL);
- dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL);
- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_area, NULL);
- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL);
- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL);
- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);
-
- if (dev->has_vid_cap) {
- /* Image Processing Controls */
- struct v4l2_ctrl_config vivid_ctrl_test_pattern = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_TEST_PATTERN,
- .name = "Test Pattern",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = TPG_PAT_NOISE,
- .qmenu = tpg_pattern_strings,
- };
-
- dev->test_pattern = v4l2_ctrl_new_custom(hdl_vid_cap,
- &vivid_ctrl_test_pattern, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_perc_fill, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hor_movement, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vert_movement, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_osd_mode, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_border, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_square, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hflip, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vflip, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_sav, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_eav, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_reduced_fps, NULL);
- if (show_ccs_cap) {
- dev->ctrl_has_crop_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
- &vivid_ctrl_has_crop_cap, NULL);
- dev->ctrl_has_compose_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
- &vivid_ctrl_has_compose_cap, NULL);
- dev->ctrl_has_scaler_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
- &vivid_ctrl_has_scaler_cap, NULL);
- }
-
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
- dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
- &vivid_ctrl_colorspace, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hsv_enc, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
- }
-
- if (dev->has_vid_out && show_ccs_out) {
- dev->ctrl_has_crop_out = v4l2_ctrl_new_custom(hdl_vid_out,
- &vivid_ctrl_has_crop_out, NULL);
- dev->ctrl_has_compose_out = v4l2_ctrl_new_custom(hdl_vid_out,
- &vivid_ctrl_has_compose_out, NULL);
- dev->ctrl_has_scaler_out = v4l2_ctrl_new_custom(hdl_vid_out,
- &vivid_ctrl_has_scaler_out, NULL);
- }
-
- /*
- * Testing this driver with v4l2-compliance will trigger the error
- * injection controls, and after that nothing will work as expected.
- * So we have a module option to drop these error injecting controls
- * allowing us to run v4l2_compliance again.
- */
- if (!no_error_inj) {
- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_disconnect, NULL);
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_dqbuf_error, NULL);
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_perc_dropped, NULL);
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_setup_error, NULL);
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_buf_prepare_error, NULL);
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_start_streaming_error, NULL);
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_error, NULL);
-#ifdef CONFIG_MEDIA_CONTROLLER
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_req_validate_error, NULL);
-#endif
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_seq_wrap, NULL);
- v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_time_wrap, NULL);
- }
-
- if (has_sdtv && (dev->has_vid_cap || dev->has_vbi_cap)) {
- if (dev->has_vid_cap)
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_std_aspect_ratio, NULL);
- dev->ctrl_std_signal_mode = v4l2_ctrl_new_custom(hdl_sdtv_cap,
- &vivid_ctrl_std_signal_mode, NULL);
- dev->ctrl_standard = v4l2_ctrl_new_custom(hdl_sdtv_cap,
- &vivid_ctrl_standard, NULL);
- if (dev->ctrl_std_signal_mode)
- v4l2_ctrl_cluster(2, &dev->ctrl_std_signal_mode);
- if (dev->has_raw_vbi_cap)
- v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_vbi_cap_interlaced, NULL);
- }
-
- if (dev->num_hdmi_inputs) {
- s64 hdmi_input_mask = GENMASK(dev->num_hdmi_inputs - 1, 0);
-
- dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap,
- &vivid_ctrl_dv_timings_signal_mode, NULL);
-
- vivid_ctrl_dv_timings.max = dev->query_dv_timings_size - 1;
- vivid_ctrl_dv_timings.qmenu =
- (const char * const *)dev->query_dv_timings_qmenu;
- dev->ctrl_dv_timings = v4l2_ctrl_new_custom(hdl_vid_cap,
- &vivid_ctrl_dv_timings, NULL);
- if (dev->ctrl_dv_timings_signal_mode)
- v4l2_ctrl_cluster(2, &dev->ctrl_dv_timings_signal_mode);
-
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_dv_timings_aspect_ratio, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_max_edid_blocks, NULL);
- dev->real_rgb_range_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
- &vivid_ctrl_limited_rgb_range, NULL);
- dev->rgb_range_cap = v4l2_ctrl_new_std_menu(hdl_vid_cap,
- &vivid_vid_cap_ctrl_ops,
- V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
- 0, V4L2_DV_RGB_RANGE_AUTO);
- dev->ctrl_rx_power_present = v4l2_ctrl_new_std(hdl_vid_cap,
- NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, hdmi_input_mask,
- 0, hdmi_input_mask);
-
- }
- if (dev->num_hdmi_outputs) {
- s64 hdmi_output_mask = GENMASK(dev->num_hdmi_outputs - 1, 0);
-
- /*
- * We aren't doing anything with this at the moment, but
- * HDMI outputs typically have this controls.
- */
- dev->ctrl_tx_rgb_range = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
- V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
- 0, V4L2_DV_RGB_RANGE_AUTO);
- dev->ctrl_tx_mode = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
- V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
- 0, V4L2_DV_TX_MODE_HDMI);
- dev->ctrl_display_present = v4l2_ctrl_new_custom(hdl_vid_out,
- &vivid_ctrl_display_present, NULL);
- dev->ctrl_tx_hotplug = v4l2_ctrl_new_std(hdl_vid_out,
- NULL, V4L2_CID_DV_TX_HOTPLUG, 0, hdmi_output_mask,
- 0, hdmi_output_mask);
- dev->ctrl_tx_rxsense = v4l2_ctrl_new_std(hdl_vid_out,
- NULL, V4L2_CID_DV_TX_RXSENSE, 0, hdmi_output_mask,
- 0, hdmi_output_mask);
- dev->ctrl_tx_edid_present = v4l2_ctrl_new_std(hdl_vid_out,
- NULL, V4L2_CID_DV_TX_EDID_PRESENT, 0, hdmi_output_mask,
- 0, hdmi_output_mask);
- }
- if ((dev->has_vid_cap && dev->has_vid_out) ||
- (dev->has_vbi_cap && dev->has_vbi_out))
- v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_loop_video, NULL);
-
- if (dev->has_fb)
- v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_clear_fb, NULL);
-
- if (dev->has_radio_rx) {
- v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_mode, NULL);
- v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_prog_lim, NULL);
- v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_blockio, NULL);
- v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_rbds, NULL);
- v4l2_ctrl_new_std(hdl_radio_rx, &vivid_radio_rx_ctrl_ops,
- V4L2_CID_RDS_RECEPTION, 0, 1, 1, 1);
- dev->radio_rx_rds_pty = v4l2_ctrl_new_std(hdl_radio_rx,
- &vivid_radio_rx_ctrl_ops,
- V4L2_CID_RDS_RX_PTY, 0, 31, 1, 0);
- dev->radio_rx_rds_psname = v4l2_ctrl_new_std(hdl_radio_rx,
- &vivid_radio_rx_ctrl_ops,
- V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0);
- dev->radio_rx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_rx,
- &vivid_radio_rx_ctrl_ops,
- V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0);
- dev->radio_rx_rds_ta = v4l2_ctrl_new_std(hdl_radio_rx,
- &vivid_radio_rx_ctrl_ops,
- V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
- dev->radio_rx_rds_tp = v4l2_ctrl_new_std(hdl_radio_rx,
- &vivid_radio_rx_ctrl_ops,
- V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
- dev->radio_rx_rds_ms = v4l2_ctrl_new_std(hdl_radio_rx,
- &vivid_radio_rx_ctrl_ops,
- V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1);
- }
- if (dev->has_radio_tx) {
- v4l2_ctrl_new_custom(hdl_radio_tx,
- &vivid_ctrl_radio_tx_rds_blockio, NULL);
- dev->radio_tx_rds_pi = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, 0x8088);
- dev->radio_tx_rds_pty = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_PTY, 0, 31, 1, 3);
- dev->radio_tx_rds_psname = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_PS_NAME, 0, 8, 8, 0);
- if (dev->radio_tx_rds_psname)
- v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_psname, "VIVID-TX");
- dev->radio_tx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_RADIO_TEXT, 0, 64 * 2, 64, 0);
- if (dev->radio_tx_rds_radiotext)
- v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_radiotext,
- "This is a VIVID default Radio Text template text, change at will");
- dev->radio_tx_rds_mono_stereo = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
- dev->radio_tx_rds_art_head = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
- dev->radio_tx_rds_compressed = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
- dev->radio_tx_rds_dyn_pty = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
- dev->radio_tx_rds_ta = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
- dev->radio_tx_rds_tp = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 1);
- dev->radio_tx_rds_ms = v4l2_ctrl_new_std(hdl_radio_tx,
- &vivid_radio_tx_ctrl_ops,
- V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
- }
- if (dev->has_sdr_cap) {
- v4l2_ctrl_new_custom(hdl_sdr_cap,
- &vivid_ctrl_sdr_cap_fm_deviation, NULL);
- }
- if (dev->has_meta_cap) {
- v4l2_ctrl_new_custom(hdl_meta_cap,
- &vivid_ctrl_meta_has_pts, NULL);
- v4l2_ctrl_new_custom(hdl_meta_cap,
- &vivid_ctrl_meta_has_src_clk, NULL);
- }
-
- if (hdl_user_gen->error)
- return hdl_user_gen->error;
- if (hdl_user_vid->error)
- return hdl_user_vid->error;
- if (hdl_user_aud->error)
- return hdl_user_aud->error;
- if (hdl_streaming->error)
- return hdl_streaming->error;
- if (hdl_sdr_cap->error)
- return hdl_sdr_cap->error;
- if (hdl_loop_cap->error)
- return hdl_loop_cap->error;
-
- if (dev->autogain)
- v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
-
- if (dev->has_vid_cap) {
- v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_vid, NULL, false);
- v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_aud, NULL, false);
- v4l2_ctrl_add_handler(hdl_vid_cap, hdl_streaming, NULL, false);
- v4l2_ctrl_add_handler(hdl_vid_cap, hdl_sdtv_cap, NULL, false);
- v4l2_ctrl_add_handler(hdl_vid_cap, hdl_loop_cap, NULL, false);
- v4l2_ctrl_add_handler(hdl_vid_cap, hdl_fb, NULL, false);
- if (hdl_vid_cap->error)
- return hdl_vid_cap->error;
- dev->vid_cap_dev.ctrl_handler = hdl_vid_cap;
- }
- if (dev->has_vid_out) {
- v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_aud, NULL, false);
- v4l2_ctrl_add_handler(hdl_vid_out, hdl_streaming, NULL, false);
- v4l2_ctrl_add_handler(hdl_vid_out, hdl_fb, NULL, false);
- if (hdl_vid_out->error)
- return hdl_vid_out->error;
- dev->vid_out_dev.ctrl_handler = hdl_vid_out;
- }
- if (dev->has_vbi_cap) {
- v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_streaming, NULL, false);
- v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_sdtv_cap, NULL, false);
- v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_loop_cap, NULL, false);
- if (hdl_vbi_cap->error)
- return hdl_vbi_cap->error;
- dev->vbi_cap_dev.ctrl_handler = hdl_vbi_cap;
- }
- if (dev->has_vbi_out) {
- v4l2_ctrl_add_handler(hdl_vbi_out, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_vbi_out, hdl_streaming, NULL, false);
- if (hdl_vbi_out->error)
- return hdl_vbi_out->error;
- dev->vbi_out_dev.ctrl_handler = hdl_vbi_out;
- }
- if (dev->has_radio_rx) {
- v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_aud, NULL, false);
- if (hdl_radio_rx->error)
- return hdl_radio_rx->error;
- dev->radio_rx_dev.ctrl_handler = hdl_radio_rx;
- }
- if (dev->has_radio_tx) {
- v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_aud, NULL, false);
- if (hdl_radio_tx->error)
- return hdl_radio_tx->error;
- dev->radio_tx_dev.ctrl_handler = hdl_radio_tx;
- }
- if (dev->has_sdr_cap) {
- v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_streaming, NULL, false);
- if (hdl_sdr_cap->error)
- return hdl_sdr_cap->error;
- dev->sdr_cap_dev.ctrl_handler = hdl_sdr_cap;
- }
- if (dev->has_meta_cap) {
- v4l2_ctrl_add_handler(hdl_meta_cap, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_meta_cap, hdl_streaming, NULL, false);
- if (hdl_meta_cap->error)
- return hdl_meta_cap->error;
- dev->meta_cap_dev.ctrl_handler = hdl_meta_cap;
- }
- if (dev->has_meta_out) {
- v4l2_ctrl_add_handler(hdl_meta_out, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_meta_out, hdl_streaming, NULL, false);
- if (hdl_meta_out->error)
- return hdl_meta_out->error;
- dev->meta_out_dev.ctrl_handler = hdl_meta_out;
- }
- if (dev->has_touch_cap) {
- v4l2_ctrl_add_handler(hdl_tch_cap, hdl_user_gen, NULL, false);
- v4l2_ctrl_add_handler(hdl_tch_cap, hdl_streaming, NULL, false);
- if (hdl_tch_cap->error)
- return hdl_tch_cap->error;
- dev->touch_cap_dev.ctrl_handler = hdl_tch_cap;
- }
- return 0;
-}
-
-void vivid_free_controls(struct vivid_dev *dev)
-{
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_cap);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_out);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_cap);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_out);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_rx);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_tx);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdr_cap);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_gen);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_vid);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_aud);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_streaming);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdtv_cap);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_loop_cap);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_fb);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_meta_cap);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_meta_out);
- v4l2_ctrl_handler_free(&dev->ctrl_hdl_touch_cap);
-}
diff --git a/drivers/media/platform/vivid/vivid-ctrls.h b/drivers/media/platform/vivid/vivid-ctrls.h
deleted file mode 100644
index 6fad5f5d0054..000000000000
--- a/drivers/media/platform/vivid/vivid-ctrls.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-ctrls.h - control support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_CTRLS_H_
-#define _VIVID_CTRLS_H_
-
-enum vivid_hw_seek_modes {
- VIVID_HW_SEEK_BOUNDED,
- VIVID_HW_SEEK_WRAP,
- VIVID_HW_SEEK_BOTH,
-};
-
-int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
- bool show_ccs_out, bool no_error_inj,
- bool has_sdtv, bool has_hdmi);
-void vivid_free_controls(struct vivid_dev *dev);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
deleted file mode 100644
index 01a9d671b947..000000000000
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-kthread-cap.h - video/vbi capture thread support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/font.h>
-#include <linux/mutex.h>
-#include <linux/videodev2.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/random.h>
-#include <linux/v4l2-dv-timings.h>
-#include <asm/div64.h>
-#include <media/videobuf2-vmalloc.h>
-#include <media/v4l2-dv-timings.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-rect.h>
-
-#include "vivid-core.h"
-#include "vivid-vid-common.h"
-#include "vivid-vid-cap.h"
-#include "vivid-vid-out.h"
-#include "vivid-radio-common.h"
-#include "vivid-radio-rx.h"
-#include "vivid-radio-tx.h"
-#include "vivid-sdr-cap.h"
-#include "vivid-vbi-cap.h"
-#include "vivid-vbi-out.h"
-#include "vivid-osd.h"
-#include "vivid-ctrls.h"
-#include "vivid-kthread-cap.h"
-#include "vivid-meta-cap.h"
-
-static inline v4l2_std_id vivid_get_std_cap(const struct vivid_dev *dev)
-{
- if (vivid_is_sdtv_cap(dev))
- return dev->std_cap[dev->input];
- return 0;
-}
-
-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;
- if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) &&
- out == dev->chromakey_out)
- return;
- if (dev->fmt_cap->alpha_mask) {
- if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) &&
- dev->global_alpha_out)
- return;
- if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) &&
- *cap & dev->fmt_cap->alpha_mask)
- return;
- if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_LOCAL_INV_ALPHA) &&
- !(*cap & dev->fmt_cap->alpha_mask))
- return;
- }
- *cap = out;
-}
-
-static void blend_line(struct vivid_dev *dev, unsigned y_offset, unsigned x_offset,
- u8 *vcapbuf, const u8 *vosdbuf,
- unsigned width, unsigned pixsize)
-{
- unsigned x;
-
- for (x = 0; x < width; x++, vcapbuf += pixsize, vosdbuf += pixsize) {
- copy_pix(dev, y_offset, x_offset + x,
- (u16 *)vcapbuf, (const u16 *)vosdbuf);
- }
-}
-
-static void scale_line(const u8 *src, u8 *dst, unsigned srcw, unsigned dstw, unsigned twopixsize)
-{
- /* Coarse scaling with Bresenham */
- unsigned int_part;
- unsigned fract_part;
- unsigned src_x = 0;
- unsigned error = 0;
- unsigned x;
-
- /*
- * We always combine two pixels to prevent color bleed in the packed
- * yuv case.
- */
- srcw /= 2;
- dstw /= 2;
- int_part = srcw / dstw;
- fract_part = srcw % dstw;
- for (x = 0; x < dstw; x++, dst += twopixsize) {
- memcpy(dst, src + src_x * twopixsize, twopixsize);
- src_x += int_part;
- error += fract_part;
- if (error >= dstw) {
- error -= dstw;
- src_x++;
- }
- }
-}
-
-/*
- * Precalculate the rectangles needed to perform video looping:
- *
- * The nominal pipeline is that the video output buffer is cropped by
- * crop_out, scaled to compose_out, overlaid with the output overlay,
- * cropped on the capture side by crop_cap and scaled again to the video
- * capture buffer using compose_cap.
- *
- * To keep things efficient we calculate the intersection of compose_out
- * and crop_cap (since that's the only part of the video that will
- * actually end up in the capture buffer), determine which part of the
- * video output buffer that is and which part of the video capture buffer
- * so we can scale the video straight from the output buffer to the capture
- * buffer without any intermediate steps.
- *
- * If we need to deal with an output overlay, then there is no choice and
- * that intermediate step still has to be taken. For the output overlay
- * support we calculate the intersection of the framebuffer and the overlay
- * window (which may be partially or wholly outside of the framebuffer
- * itself) and the intersection of that with loop_vid_copy (i.e. the part of
- * the actual looped video that will be overlaid). The result is calculated
- * both in framebuffer coordinates (loop_fb_copy) and compose_out coordinates
- * (loop_vid_overlay). Finally calculate the part of the capture buffer that
- * will receive that overlaid video.
- */
-static void vivid_precalc_copy_rects(struct vivid_dev *dev)
-{
- /* Framebuffer rectangle */
- struct v4l2_rect r_fb = {
- 0, 0, dev->display_width, dev->display_height
- };
- /* Overlay window rectangle in framebuffer coordinates */
- struct v4l2_rect r_overlay = {
- dev->overlay_out_left, dev->overlay_out_top,
- dev->compose_out.width, dev->compose_out.height
- };
-
- v4l2_rect_intersect(&dev->loop_vid_copy, &dev->crop_cap, &dev->compose_out);
-
- dev->loop_vid_out = dev->loop_vid_copy;
- v4l2_rect_scale(&dev->loop_vid_out, &dev->compose_out, &dev->crop_out);
- dev->loop_vid_out.left += dev->crop_out.left;
- dev->loop_vid_out.top += dev->crop_out.top;
-
- dev->loop_vid_cap = dev->loop_vid_copy;
- v4l2_rect_scale(&dev->loop_vid_cap, &dev->crop_cap, &dev->compose_cap);
-
- dprintk(dev, 1,
- "loop_vid_copy: %dx%d@%dx%d loop_vid_out: %dx%d@%dx%d loop_vid_cap: %dx%d@%dx%d\n",
- dev->loop_vid_copy.width, dev->loop_vid_copy.height,
- dev->loop_vid_copy.left, dev->loop_vid_copy.top,
- dev->loop_vid_out.width, dev->loop_vid_out.height,
- dev->loop_vid_out.left, dev->loop_vid_out.top,
- dev->loop_vid_cap.width, dev->loop_vid_cap.height,
- dev->loop_vid_cap.left, dev->loop_vid_cap.top);
-
- v4l2_rect_intersect(&r_overlay, &r_fb, &r_overlay);
-
- /* shift r_overlay to the same origin as compose_out */
- r_overlay.left += dev->compose_out.left - dev->overlay_out_left;
- r_overlay.top += dev->compose_out.top - dev->overlay_out_top;
-
- v4l2_rect_intersect(&dev->loop_vid_overlay, &r_overlay, &dev->loop_vid_copy);
- dev->loop_fb_copy = dev->loop_vid_overlay;
-
- /* shift dev->loop_fb_copy back again to the fb origin */
- dev->loop_fb_copy.left -= dev->compose_out.left - dev->overlay_out_left;
- dev->loop_fb_copy.top -= dev->compose_out.top - dev->overlay_out_top;
-
- dev->loop_vid_overlay_cap = dev->loop_vid_overlay;
- v4l2_rect_scale(&dev->loop_vid_overlay_cap, &dev->crop_cap, &dev->compose_cap);
-
- dprintk(dev, 1,
- "loop_fb_copy: %dx%d@%dx%d loop_vid_overlay: %dx%d@%dx%d loop_vid_overlay_cap: %dx%d@%dx%d\n",
- dev->loop_fb_copy.width, dev->loop_fb_copy.height,
- dev->loop_fb_copy.left, dev->loop_fb_copy.top,
- dev->loop_vid_overlay.width, dev->loop_vid_overlay.height,
- dev->loop_vid_overlay.left, dev->loop_vid_overlay.top,
- dev->loop_vid_overlay_cap.width, dev->loop_vid_overlay_cap.height,
- dev->loop_vid_overlay_cap.left, dev->loop_vid_overlay_cap.top);
-}
-
-static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf,
- unsigned p, unsigned bpl[TPG_MAX_PLANES], unsigned h)
-{
- unsigned i;
- void *vbuf;
-
- if (p == 0 || tpg_g_buffers(tpg) > 1)
- return vb2_plane_vaddr(&buf->vb.vb2_buf, p);
- vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
- for (i = 0; i < p; i++)
- vbuf += bpl[i] * h / tpg->vdownsampling[i];
- return vbuf;
-}
-
-static noinline_for_stack int vivid_copy_buffer(struct vivid_dev *dev, unsigned p,
- u8 *vcapbuf, struct vivid_buffer *vid_cap_buf)
-{
- bool blank = dev->must_blank[vid_cap_buf->vb.vb2_buf.index];
- struct tpg_data *tpg = &dev->tpg;
- struct vivid_buffer *vid_out_buf = NULL;
- unsigned vdiv = dev->fmt_out->vdownsampling[p];
- unsigned twopixsize = tpg_g_twopixelsize(tpg, p);
- unsigned img_width = tpg_hdiv(tpg, p, dev->compose_cap.width);
- unsigned img_height = dev->compose_cap.height;
- unsigned stride_cap = tpg->bytesperline[p];
- unsigned stride_out = dev->bytesperline_out[p];
- unsigned stride_osd = dev->display_byte_stride;
- unsigned hmax = (img_height * tpg->perc_fill) / 100;
- u8 *voutbuf;
- u8 *vosdbuf = NULL;
- unsigned y;
- bool blend = dev->bitmap_out || dev->clipcount_out || dev->fbuf_out_flags;
- /* Coarse scaling with Bresenham */
- unsigned vid_out_int_part;
- unsigned vid_out_fract_part;
- unsigned vid_out_y = 0;
- unsigned vid_out_error = 0;
- unsigned vid_overlay_int_part = 0;
- unsigned vid_overlay_fract_part = 0;
- unsigned vid_overlay_y = 0;
- unsigned vid_overlay_error = 0;
- unsigned vid_cap_left = tpg_hdiv(tpg, p, dev->loop_vid_cap.left);
- unsigned vid_cap_right;
- bool quick;
-
- vid_out_int_part = dev->loop_vid_out.height / dev->loop_vid_cap.height;
- vid_out_fract_part = dev->loop_vid_out.height % dev->loop_vid_cap.height;
-
- if (!list_empty(&dev->vid_out_active))
- vid_out_buf = list_entry(dev->vid_out_active.next,
- struct vivid_buffer, list);
- if (vid_out_buf == NULL)
- return -ENODATA;
-
- vid_cap_buf->vb.field = vid_out_buf->vb.field;
-
- voutbuf = plane_vaddr(tpg, vid_out_buf, p,
- dev->bytesperline_out, dev->fmt_out_rect.height);
- if (p < dev->fmt_out->buffers)
- voutbuf += vid_out_buf->vb.vb2_buf.planes[p].data_offset;
- voutbuf += tpg_hdiv(tpg, p, dev->loop_vid_out.left) +
- (dev->loop_vid_out.top / vdiv) * stride_out;
- vcapbuf += tpg_hdiv(tpg, p, dev->compose_cap.left) +
- (dev->compose_cap.top / vdiv) * stride_cap;
-
- if (dev->loop_vid_copy.width == 0 || dev->loop_vid_copy.height == 0) {
- /*
- * If there is nothing to copy, then just fill the capture window
- * with black.
- */
- for (y = 0; y < hmax / vdiv; y++, vcapbuf += stride_cap)
- memcpy(vcapbuf, tpg->black_line[p], img_width);
- return 0;
- }
-
- if (dev->overlay_out_enabled &&
- dev->loop_vid_overlay.width && dev->loop_vid_overlay.height) {
- vosdbuf = dev->video_vbase;
- vosdbuf += (dev->loop_fb_copy.left * twopixsize) / 2 +
- dev->loop_fb_copy.top * stride_osd;
- vid_overlay_int_part = dev->loop_vid_overlay.height /
- dev->loop_vid_overlay_cap.height;
- vid_overlay_fract_part = dev->loop_vid_overlay.height %
- dev->loop_vid_overlay_cap.height;
- }
-
- vid_cap_right = tpg_hdiv(tpg, p, dev->loop_vid_cap.left + dev->loop_vid_cap.width);
- /* quick is true if no video scaling is needed */
- quick = dev->loop_vid_out.width == dev->loop_vid_cap.width;
-
- dev->cur_scaled_line = dev->loop_vid_out.height;
- for (y = 0; y < hmax; y += vdiv, vcapbuf += stride_cap) {
- /* osdline is true if this line requires overlay blending */
- bool osdline = vosdbuf && y >= dev->loop_vid_overlay_cap.top &&
- y < dev->loop_vid_overlay_cap.top + dev->loop_vid_overlay_cap.height;
-
- /*
- * If this line of the capture buffer doesn't get any video, then
- * just fill with black.
- */
- if (y < dev->loop_vid_cap.top ||
- y >= dev->loop_vid_cap.top + dev->loop_vid_cap.height) {
- memcpy(vcapbuf, tpg->black_line[p], img_width);
- continue;
- }
-
- /* fill the left border with black */
- if (dev->loop_vid_cap.left)
- memcpy(vcapbuf, tpg->black_line[p], vid_cap_left);
-
- /* fill the right border with black */
- if (vid_cap_right < img_width)
- memcpy(vcapbuf + vid_cap_right, tpg->black_line[p],
- img_width - vid_cap_right);
-
- if (quick && !osdline) {
- memcpy(vcapbuf + vid_cap_left,
- voutbuf + vid_out_y * stride_out,
- tpg_hdiv(tpg, p, dev->loop_vid_cap.width));
- goto update_vid_out_y;
- }
- if (dev->cur_scaled_line == vid_out_y) {
- memcpy(vcapbuf + vid_cap_left, dev->scaled_line,
- tpg_hdiv(tpg, p, dev->loop_vid_cap.width));
- goto update_vid_out_y;
- }
- if (!osdline) {
- scale_line(voutbuf + vid_out_y * stride_out, dev->scaled_line,
- tpg_hdiv(tpg, p, dev->loop_vid_out.width),
- tpg_hdiv(tpg, p, dev->loop_vid_cap.width),
- tpg_g_twopixelsize(tpg, p));
- } else {
- /*
- * Offset in bytes within loop_vid_copy to the start of the
- * loop_vid_overlay rectangle.
- */
- unsigned offset =
- ((dev->loop_vid_overlay.left - dev->loop_vid_copy.left) *
- twopixsize) / 2;
- u8 *osd = vosdbuf + vid_overlay_y * stride_osd;
-
- scale_line(voutbuf + vid_out_y * stride_out, dev->blended_line,
- dev->loop_vid_out.width, dev->loop_vid_copy.width,
- tpg_g_twopixelsize(tpg, p));
- if (blend)
- blend_line(dev, vid_overlay_y + dev->loop_vid_overlay.top,
- dev->loop_vid_overlay.left,
- dev->blended_line + offset, osd,
- dev->loop_vid_overlay.width, twopixsize / 2);
- else
- memcpy(dev->blended_line + offset,
- osd, (dev->loop_vid_overlay.width * twopixsize) / 2);
- scale_line(dev->blended_line, dev->scaled_line,
- dev->loop_vid_copy.width, dev->loop_vid_cap.width,
- tpg_g_twopixelsize(tpg, p));
- }
- dev->cur_scaled_line = vid_out_y;
- memcpy(vcapbuf + vid_cap_left, dev->scaled_line,
- tpg_hdiv(tpg, p, dev->loop_vid_cap.width));
-
-update_vid_out_y:
- if (osdline) {
- vid_overlay_y += vid_overlay_int_part;
- vid_overlay_error += vid_overlay_fract_part;
- if (vid_overlay_error >= dev->loop_vid_overlay_cap.height) {
- vid_overlay_error -= dev->loop_vid_overlay_cap.height;
- vid_overlay_y++;
- }
- }
- vid_out_y += vid_out_int_part;
- vid_out_error += vid_out_fract_part;
- if (vid_out_error >= dev->loop_vid_cap.height / vdiv) {
- vid_out_error -= dev->loop_vid_cap.height / vdiv;
- vid_out_y++;
- }
- }
-
- if (!blank)
- return 0;
- for (; y < img_height; y += vdiv, vcapbuf += stride_cap)
- memcpy(vcapbuf, tpg->contrast_line[p], img_width);
- return 0;
-}
-
-static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
-{
- struct tpg_data *tpg = &dev->tpg;
- unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
- unsigned line_height = 16 / factor;
- bool is_tv = vivid_is_sdtv_cap(dev);
- bool is_60hz = is_tv && (dev->std_cap[dev->input] & V4L2_STD_525_60);
- unsigned p;
- int line = 1;
- u8 *basep[TPG_MAX_PLANES][2];
- unsigned ms;
- char str[100];
- s32 gain;
- bool is_loop = false;
-
- if (dev->loop_video && dev->can_loop_video &&
- ((vivid_is_svid_cap(dev) &&
- !VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input])) ||
- (vivid_is_hdmi_cap(dev) &&
- !VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode[dev->input]))))
- is_loop = true;
-
- buf->vb.sequence = dev->vid_cap_seq_count;
- if (dev->field_cap == V4L2_FIELD_ALTERNATE) {
- /*
- * 60 Hz standards start with the bottom field, 50 Hz standards
- * with the top field. So if the 0-based seq_count is even,
- * then the field is TOP for 50 Hz and BOTTOM for 60 Hz
- * standards.
- */
- buf->vb.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ?
- V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP;
- /*
- * The sequence counter counts frames, not fields. So divide
- * by two.
- */
- buf->vb.sequence /= 2;
- } else {
- buf->vb.field = dev->field_cap;
- }
- tpg_s_field(tpg, buf->vb.field,
- dev->field_cap == V4L2_FIELD_ALTERNATE);
- tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.vb2_buf.index]);
-
- vivid_precalc_copy_rects(dev);
-
- for (p = 0; p < tpg_g_planes(tpg); p++) {
- void *vbuf = plane_vaddr(tpg, buf, p,
- tpg->bytesperline, tpg->buf_height);
-
- /*
- * The first plane of a multiplanar format has a non-zero
- * data_offset. This helps testing whether the application
- * correctly supports non-zero data offsets.
- */
- if (p < tpg_g_buffers(tpg) && dev->fmt_cap->data_offset[p]) {
- memset(vbuf, dev->fmt_cap->data_offset[p] & 0xff,
- dev->fmt_cap->data_offset[p]);
- vbuf += dev->fmt_cap->data_offset[p];
- }
- tpg_calc_text_basep(tpg, basep, p, vbuf);
- if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf))
- tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev),
- p, vbuf);
- }
- dev->must_blank[buf->vb.vb2_buf.index] = false;
-
- /* Updates stream time, only update at the start of a new frame. */
- if (dev->field_cap != V4L2_FIELD_ALTERNATE ||
- (dev->vid_cap_seq_count & 1) == 0)
- dev->ms_vid_cap =
- jiffies_to_msecs(jiffies - dev->jiffies_vid_cap);
-
- ms = dev->ms_vid_cap;
- if (dev->osd_mode <= 1) {
- snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d %u%s",
- (ms / (60 * 60 * 1000)) % 24,
- (ms / (60 * 1000)) % 60,
- (ms / 1000) % 60,
- ms % 1000,
- buf->vb.sequence,
- (dev->field_cap == V4L2_FIELD_ALTERNATE) ?
- (buf->vb.field == V4L2_FIELD_TOP ?
- " top" : " bottom") : "");
- tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
- }
- if (dev->osd_mode == 0) {
- snprintf(str, sizeof(str), " %dx%d, input %d ",
- dev->src_rect.width, dev->src_rect.height, dev->input);
- tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
-
- gain = v4l2_ctrl_g_ctrl(dev->gain);
- mutex_lock(dev->ctrl_hdl_user_vid.lock);
- snprintf(str, sizeof(str),
- " brightness %3d, contrast %3d, saturation %3d, hue %d ",
- dev->brightness->cur.val,
- dev->contrast->cur.val,
- dev->saturation->cur.val,
- dev->hue->cur.val);
- tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
- snprintf(str, sizeof(str),
- " autogain %d, gain %3d, alpha 0x%02x ",
- dev->autogain->cur.val, gain, dev->alpha->cur.val);
- mutex_unlock(dev->ctrl_hdl_user_vid.lock);
- tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
- mutex_lock(dev->ctrl_hdl_user_aud.lock);
- snprintf(str, sizeof(str),
- " volume %3d, mute %d ",
- dev->volume->cur.val, dev->mute->cur.val);
- mutex_unlock(dev->ctrl_hdl_user_aud.lock);
- tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
- mutex_lock(dev->ctrl_hdl_user_gen.lock);
- snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
- dev->int32->cur.val,
- *dev->int64->p_cur.p_s64,
- dev->bitmask->cur.val);
- tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
- snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
- dev->boolean->cur.val,
- dev->menu->qmenu[dev->menu->cur.val],
- dev->string->p_cur.p_char);
- tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
- snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
- dev->int_menu->qmenu_int[dev->int_menu->cur.val],
- dev->int_menu->cur.val);
- mutex_unlock(dev->ctrl_hdl_user_gen.lock);
- tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
- if (dev->button_pressed) {
- dev->button_pressed--;
- snprintf(str, sizeof(str), " button pressed!");
- tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
- }
- if (dev->osd[0]) {
- if (vivid_is_hdmi_cap(dev)) {
- snprintf(str, sizeof(str),
- " OSD \"%s\"", dev->osd);
- tpg_gen_text(tpg, basep, line++ * line_height,
- 16, str);
- }
- if (dev->osd_jiffies &&
- time_is_before_jiffies(dev->osd_jiffies + 5 * HZ)) {
- dev->osd[0] = 0;
- dev->osd_jiffies = 0;
- }
- }
- }
-}
-
-/*
- * 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;
-
- f_period = (u64)dev->timeperframe_vid_cap.numerator * 1000000000;
- if (WARN_ON(dev->timeperframe_vid_cap.denominator == 0))
- dev->timeperframe_vid_cap.denominator = 1;
- do_div(f_period, dev->timeperframe_vid_cap.denominator);
- if (dev->field_cap == V4L2_FIELD_ALTERNATE)
- f_period >>= 1;
- /*
- * If "End of Frame", then offset the exposure time by 0.9
- * of the frame period.
- */
- dev->cap_frame_eof_offset = f_period * 9;
- do_div(dev->cap_frame_eof_offset, 10);
- dev->cap_frame_period = f_period;
-}
-
-static noinline_for_stack void vivid_thread_vid_cap_tick(struct vivid_dev *dev,
- int dropped_bufs)
-{
- struct vivid_buffer *vid_cap_buf = NULL;
- struct vivid_buffer *vbi_cap_buf = NULL;
- struct vivid_buffer *meta_cap_buf = NULL;
- u64 f_time = 0;
-
- dprintk(dev, 1, "Video Capture Thread Tick\n");
-
- while (dropped_bufs-- > 1)
- tpg_update_mv_count(&dev->tpg,
- dev->field_cap == V4L2_FIELD_NONE ||
- dev->field_cap == V4L2_FIELD_ALTERNATE);
-
- /* Drop a certain percentage of buffers. */
- if (dev->perc_dropped_buffers &&
- prandom_u32_max(100) < dev->perc_dropped_buffers)
- goto update_mv;
-
- spin_lock(&dev->slock);
- if (!list_empty(&dev->vid_cap_active)) {
- vid_cap_buf = list_entry(dev->vid_cap_active.next, struct vivid_buffer, list);
- list_del(&vid_cap_buf->list);
- }
- if (!list_empty(&dev->vbi_cap_active)) {
- if (dev->field_cap != V4L2_FIELD_ALTERNATE ||
- (dev->vbi_cap_seq_count & 1)) {
- vbi_cap_buf = list_entry(dev->vbi_cap_active.next,
- struct vivid_buffer, list);
- list_del(&vbi_cap_buf->list);
- }
- }
- if (!list_empty(&dev->meta_cap_active)) {
- meta_cap_buf = list_entry(dev->meta_cap_active.next,
- struct vivid_buffer, list);
- list_del(&meta_cap_buf->list);
- }
-
- spin_unlock(&dev->slock);
-
- if (!vid_cap_buf && !vbi_cap_buf && !meta_cap_buf)
- goto update_mv;
-
- f_time = dev->cap_frame_period * dev->vid_cap_seq_count +
- dev->cap_stream_start + dev->time_wrap_offset;
-
- if (vid_cap_buf) {
- v4l2_ctrl_request_setup(vid_cap_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vid_cap);
- /* Fill buffer */
- vivid_fillbuff(dev, vid_cap_buf);
- 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 ?
- VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
- dprintk(dev, 2, "vid_cap buffer %d done\n",
- vid_cap_buf->vb.vb2_buf.index);
-
- vid_cap_buf->vb.vb2_buf.timestamp = f_time;
- if (!dev->tstamp_src_is_soe)
- vid_cap_buf->vb.vb2_buf.timestamp += dev->cap_frame_eof_offset;
- }
-
- if (vbi_cap_buf) {
- u64 vbi_period;
-
- v4l2_ctrl_request_setup(vbi_cap_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vbi_cap);
- if (dev->stream_sliced_vbi_cap)
- vivid_sliced_vbi_cap_process(dev, vbi_cap_buf);
- else
- vivid_raw_vbi_cap_process(dev, vbi_cap_buf);
- v4l2_ctrl_request_complete(vbi_cap_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vbi_cap);
- vb2_buffer_done(&vbi_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
- VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
- dprintk(dev, 2, "vbi_cap %d done\n",
- vbi_cap_buf->vb.vb2_buf.index);
-
- /* If capturing a VBI, offset by 0.05 */
- vbi_period = dev->cap_frame_period * 5;
- do_div(vbi_period, 100);
- vbi_cap_buf->vb.vb2_buf.timestamp = f_time + dev->cap_frame_eof_offset + vbi_period;
- }
-
- if (meta_cap_buf) {
- v4l2_ctrl_request_setup(meta_cap_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_meta_cap);
- vivid_meta_cap_fillbuff(dev, meta_cap_buf, f_time);
- v4l2_ctrl_request_complete(meta_cap_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_meta_cap);
- vb2_buffer_done(&meta_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
- VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
- dprintk(dev, 2, "meta_cap %d done\n",
- meta_cap_buf->vb.vb2_buf.index);
- meta_cap_buf->vb.vb2_buf.timestamp = f_time + dev->cap_frame_eof_offset;
- }
-
- dev->dqbuf_error = false;
-
-update_mv:
- /* Update the test pattern movement counters */
- tpg_update_mv_count(&dev->tpg, dev->field_cap == V4L2_FIELD_NONE ||
- dev->field_cap == V4L2_FIELD_ALTERNATE);
-}
-
-static int vivid_thread_vid_cap(void *data)
-{
- struct vivid_dev *dev = data;
- u64 numerators_since_start;
- u64 buffers_since_start;
- u64 next_jiffies_since_start;
- unsigned long jiffies_since_start;
- unsigned long cur_jiffies;
- unsigned wait_jiffies;
- unsigned numerator;
- unsigned denominator;
- int dropped_bufs;
-
- dprintk(dev, 1, "Video Capture Thread Start\n");
-
- set_freezable();
-
- /* Resets frame counters */
- dev->cap_seq_offset = 0;
- dev->cap_seq_count = 0;
- dev->cap_seq_resync = false;
- dev->jiffies_vid_cap = jiffies;
- dev->cap_stream_start = ktime_get_ns();
- vivid_cap_update_frame_period(dev);
-
- for (;;) {
- try_to_freeze();
- if (kthread_should_stop())
- break;
-
- if (!mutex_trylock(&dev->mutex)) {
- schedule_timeout_uninterruptible(1);
- continue;
- }
-
- cur_jiffies = jiffies;
- if (dev->cap_seq_resync) {
- dev->jiffies_vid_cap = cur_jiffies;
- dev->cap_seq_offset = dev->cap_seq_count + 1;
- dev->cap_seq_count = 0;
- dev->cap_stream_start += dev->cap_frame_period *
- dev->cap_seq_offset;
- vivid_cap_update_frame_period(dev);
- dev->cap_seq_resync = false;
- }
- numerator = dev->timeperframe_vid_cap.numerator;
- denominator = dev->timeperframe_vid_cap.denominator;
-
- if (dev->field_cap == V4L2_FIELD_ALTERNATE)
- denominator *= 2;
-
- /* Calculate the number of jiffies since we started streaming */
- jiffies_since_start = cur_jiffies - dev->jiffies_vid_cap;
- /* Get the number of buffers streamed since the start */
- buffers_since_start = (u64)jiffies_since_start * denominator +
- (HZ * numerator) / 2;
- do_div(buffers_since_start, HZ * numerator);
-
- /*
- * After more than 0xf0000000 (rounded down to a multiple of
- * 'jiffies-per-day' to ease jiffies_to_msecs calculation)
- * jiffies have passed since we started streaming reset the
- * counters and keep track of the sequence offset.
- */
- if (jiffies_since_start > JIFFIES_RESYNC) {
- dev->jiffies_vid_cap = cur_jiffies;
- dev->cap_seq_offset = buffers_since_start;
- buffers_since_start = 0;
- }
- dropped_bufs = buffers_since_start + dev->cap_seq_offset - dev->cap_seq_count;
- dev->cap_seq_count = buffers_since_start + dev->cap_seq_offset;
- dev->vid_cap_seq_count = dev->cap_seq_count - dev->vid_cap_seq_start;
- dev->vbi_cap_seq_count = dev->cap_seq_count - dev->vbi_cap_seq_start;
- dev->meta_cap_seq_count = dev->cap_seq_count - dev->meta_cap_seq_start;
-
- vivid_thread_vid_cap_tick(dev, dropped_bufs);
-
- /*
- * Calculate the number of 'numerators' streamed since we started,
- * including the current buffer.
- */
- numerators_since_start = ++buffers_since_start * numerator;
-
- /* And the number of jiffies since we started */
- jiffies_since_start = jiffies - dev->jiffies_vid_cap;
-
- mutex_unlock(&dev->mutex);
-
- /*
- * Calculate when that next buffer is supposed to start
- * in jiffies since we started streaming.
- */
- next_jiffies_since_start = numerators_since_start * HZ +
- denominator / 2;
- do_div(next_jiffies_since_start, denominator);
- /* If it is in the past, then just schedule asap */
- if (next_jiffies_since_start < jiffies_since_start)
- next_jiffies_since_start = jiffies_since_start;
-
- wait_jiffies = next_jiffies_since_start - jiffies_since_start;
- schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
- }
- dprintk(dev, 1, "Video Capture Thread End\n");
- return 0;
-}
-
-static void vivid_grab_controls(struct vivid_dev *dev, bool grab)
-{
- v4l2_ctrl_grab(dev->ctrl_has_crop_cap, grab);
- v4l2_ctrl_grab(dev->ctrl_has_compose_cap, grab);
- v4l2_ctrl_grab(dev->ctrl_has_scaler_cap, grab);
-}
-
-int vivid_start_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming)
-{
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->kthread_vid_cap) {
- u32 seq_count = dev->cap_seq_count + dev->seq_wrap * 128;
-
- if (pstreaming == &dev->vid_cap_streaming)
- dev->vid_cap_seq_start = seq_count;
- else if (pstreaming == &dev->vbi_cap_streaming)
- dev->vbi_cap_seq_start = seq_count;
- else
- dev->meta_cap_seq_start = seq_count;
- *pstreaming = true;
- return 0;
- }
-
- /* Resets frame counters */
- tpg_init_mv_count(&dev->tpg);
-
- dev->vid_cap_seq_start = dev->seq_wrap * 128;
- dev->vbi_cap_seq_start = dev->seq_wrap * 128;
- dev->meta_cap_seq_start = dev->seq_wrap * 128;
-
- dev->kthread_vid_cap = kthread_run(vivid_thread_vid_cap, dev,
- "%s-vid-cap", dev->v4l2_dev.name);
-
- if (IS_ERR(dev->kthread_vid_cap)) {
- int err = PTR_ERR(dev->kthread_vid_cap);
-
- dev->kthread_vid_cap = NULL;
- v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
- return err;
- }
- *pstreaming = true;
- vivid_grab_controls(dev, true);
-
- dprintk(dev, 1, "returning from %s\n", __func__);
- return 0;
-}
-
-void vivid_stop_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming)
-{
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->kthread_vid_cap == NULL)
- return;
-
- *pstreaming = false;
- if (pstreaming == &dev->vid_cap_streaming) {
- /* Release all active buffers */
- while (!list_empty(&dev->vid_cap_active)) {
- struct vivid_buffer *buf;
-
- buf = list_entry(dev->vid_cap_active.next,
- struct vivid_buffer, list);
- list_del(&buf->list);
- v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vid_cap);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- dprintk(dev, 2, "vid_cap buffer %d done\n",
- buf->vb.vb2_buf.index);
- }
- }
-
- if (pstreaming == &dev->vbi_cap_streaming) {
- while (!list_empty(&dev->vbi_cap_active)) {
- struct vivid_buffer *buf;
-
- buf = list_entry(dev->vbi_cap_active.next,
- struct vivid_buffer, list);
- list_del(&buf->list);
- v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vbi_cap);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- dprintk(dev, 2, "vbi_cap buffer %d done\n",
- buf->vb.vb2_buf.index);
- }
- }
-
- if (pstreaming == &dev->meta_cap_streaming) {
- while (!list_empty(&dev->meta_cap_active)) {
- struct vivid_buffer *buf;
-
- buf = list_entry(dev->meta_cap_active.next,
- struct vivid_buffer, list);
- list_del(&buf->list);
- v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_meta_cap);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- dprintk(dev, 2, "meta_cap buffer %d done\n",
- buf->vb.vb2_buf.index);
- }
- }
-
- if (dev->vid_cap_streaming || dev->vbi_cap_streaming ||
- dev->meta_cap_streaming)
- return;
-
- /* shutdown control thread */
- vivid_grab_controls(dev, false);
- kthread_stop(dev->kthread_vid_cap);
- dev->kthread_vid_cap = NULL;
-}
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.h b/drivers/media/platform/vivid/vivid-kthread-cap.h
deleted file mode 100644
index 0f43015306d6..000000000000
--- a/drivers/media/platform/vivid/vivid-kthread-cap.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-kthread-cap.h - video/vbi capture thread support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_KTHREAD_CAP_H_
-#define _VIVID_KTHREAD_CAP_H_
-
-int vivid_start_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming);
-void vivid_stop_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c
deleted file mode 100644
index 6780687978f9..000000000000
--- a/drivers/media/platform/vivid/vivid-kthread-out.c
+++ /dev/null
@@ -1,353 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-kthread-out.h - video/vbi output thread support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/font.h>
-#include <linux/mutex.h>
-#include <linux/videodev2.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/random.h>
-#include <linux/v4l2-dv-timings.h>
-#include <asm/div64.h>
-#include <media/videobuf2-vmalloc.h>
-#include <media/v4l2-dv-timings.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-
-#include "vivid-core.h"
-#include "vivid-vid-common.h"
-#include "vivid-vid-cap.h"
-#include "vivid-vid-out.h"
-#include "vivid-radio-common.h"
-#include "vivid-radio-rx.h"
-#include "vivid-radio-tx.h"
-#include "vivid-sdr-cap.h"
-#include "vivid-vbi-cap.h"
-#include "vivid-vbi-out.h"
-#include "vivid-osd.h"
-#include "vivid-ctrls.h"
-#include "vivid-kthread-out.h"
-#include "vivid-meta-out.h"
-
-static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
-{
- struct vivid_buffer *vid_out_buf = NULL;
- struct vivid_buffer *vbi_out_buf = NULL;
- struct vivid_buffer *meta_out_buf = NULL;
-
- dprintk(dev, 1, "Video Output Thread Tick\n");
-
- /* Drop a certain percentage of buffers. */
- if (dev->perc_dropped_buffers &&
- prandom_u32_max(100) < dev->perc_dropped_buffers)
- return;
-
- spin_lock(&dev->slock);
- /*
- * Only dequeue buffer if there is at least one more pending.
- * This makes video loopback possible.
- */
- if (!list_empty(&dev->vid_out_active) &&
- !list_is_singular(&dev->vid_out_active)) {
- vid_out_buf = list_entry(dev->vid_out_active.next,
- struct vivid_buffer, list);
- list_del(&vid_out_buf->list);
- }
- if (!list_empty(&dev->vbi_out_active) &&
- (dev->field_out != V4L2_FIELD_ALTERNATE ||
- (dev->vbi_out_seq_count & 1))) {
- vbi_out_buf = list_entry(dev->vbi_out_active.next,
- struct vivid_buffer, list);
- list_del(&vbi_out_buf->list);
- }
- if (!list_empty(&dev->meta_out_active)) {
- meta_out_buf = list_entry(dev->meta_out_active.next,
- struct vivid_buffer, list);
- list_del(&meta_out_buf->list);
- }
- spin_unlock(&dev->slock);
-
- if (!vid_out_buf && !vbi_out_buf && !meta_out_buf)
- return;
-
- if (vid_out_buf) {
- v4l2_ctrl_request_setup(vid_out_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vid_out);
- v4l2_ctrl_request_complete(vid_out_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vid_out);
- vid_out_buf->vb.sequence = dev->vid_out_seq_count;
- if (dev->field_out == V4L2_FIELD_ALTERNATE) {
- /*
- * The sequence counter counts frames, not fields.
- * So divide by two.
- */
- vid_out_buf->vb.sequence /= 2;
- }
- vid_out_buf->vb.vb2_buf.timestamp =
- ktime_get_ns() + dev->time_wrap_offset;
- vb2_buffer_done(&vid_out_buf->vb.vb2_buf, dev->dqbuf_error ?
- VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
- dprintk(dev, 2, "vid_out buffer %d done\n",
- vid_out_buf->vb.vb2_buf.index);
- }
-
- if (vbi_out_buf) {
- v4l2_ctrl_request_setup(vbi_out_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vbi_out);
- v4l2_ctrl_request_complete(vbi_out_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vbi_out);
- if (dev->stream_sliced_vbi_out)
- vivid_sliced_vbi_out_process(dev, vbi_out_buf);
-
- vbi_out_buf->vb.sequence = dev->vbi_out_seq_count;
- vbi_out_buf->vb.vb2_buf.timestamp =
- ktime_get_ns() + dev->time_wrap_offset;
- vb2_buffer_done(&vbi_out_buf->vb.vb2_buf, dev->dqbuf_error ?
- VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
- dprintk(dev, 2, "vbi_out buffer %d done\n",
- vbi_out_buf->vb.vb2_buf.index);
- }
- if (meta_out_buf) {
- v4l2_ctrl_request_setup(meta_out_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_meta_out);
- v4l2_ctrl_request_complete(meta_out_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_meta_out);
- vivid_meta_out_process(dev, meta_out_buf);
- meta_out_buf->vb.sequence = dev->meta_out_seq_count;
- meta_out_buf->vb.vb2_buf.timestamp =
- ktime_get_ns() + dev->time_wrap_offset;
- vb2_buffer_done(&meta_out_buf->vb.vb2_buf, dev->dqbuf_error ?
- VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
- dprintk(dev, 2, "meta_out buffer %d done\n",
- meta_out_buf->vb.vb2_buf.index);
- }
-
- dev->dqbuf_error = false;
-}
-
-static int vivid_thread_vid_out(void *data)
-{
- struct vivid_dev *dev = data;
- u64 numerators_since_start;
- u64 buffers_since_start;
- u64 next_jiffies_since_start;
- unsigned long jiffies_since_start;
- unsigned long cur_jiffies;
- unsigned wait_jiffies;
- unsigned numerator;
- unsigned denominator;
-
- dprintk(dev, 1, "Video Output Thread Start\n");
-
- set_freezable();
-
- /* Resets frame counters */
- dev->out_seq_offset = 0;
- if (dev->seq_wrap)
- dev->out_seq_count = 0xffffff80U;
- dev->jiffies_vid_out = jiffies;
- dev->vid_out_seq_start = dev->vbi_out_seq_start = 0;
- dev->meta_out_seq_start = 0;
- dev->out_seq_resync = false;
-
- for (;;) {
- try_to_freeze();
- if (kthread_should_stop())
- break;
-
- if (!mutex_trylock(&dev->mutex)) {
- schedule_timeout_uninterruptible(1);
- continue;
- }
-
- cur_jiffies = jiffies;
- if (dev->out_seq_resync) {
- dev->jiffies_vid_out = cur_jiffies;
- dev->out_seq_offset = dev->out_seq_count + 1;
- dev->out_seq_count = 0;
- dev->out_seq_resync = false;
- }
- numerator = dev->timeperframe_vid_out.numerator;
- denominator = dev->timeperframe_vid_out.denominator;
-
- if (dev->field_out == V4L2_FIELD_ALTERNATE)
- denominator *= 2;
-
- /* Calculate the number of jiffies since we started streaming */
- jiffies_since_start = cur_jiffies - dev->jiffies_vid_out;
- /* Get the number of buffers streamed since the start */
- buffers_since_start = (u64)jiffies_since_start * denominator +
- (HZ * numerator) / 2;
- do_div(buffers_since_start, HZ * numerator);
-
- /*
- * After more than 0xf0000000 (rounded down to a multiple of
- * 'jiffies-per-day' to ease jiffies_to_msecs calculation)
- * jiffies have passed since we started streaming reset the
- * counters and keep track of the sequence offset.
- */
- if (jiffies_since_start > JIFFIES_RESYNC) {
- dev->jiffies_vid_out = cur_jiffies;
- dev->out_seq_offset = buffers_since_start;
- buffers_since_start = 0;
- }
- dev->out_seq_count = buffers_since_start + dev->out_seq_offset;
- dev->vid_out_seq_count = dev->out_seq_count - dev->vid_out_seq_start;
- dev->vbi_out_seq_count = dev->out_seq_count - dev->vbi_out_seq_start;
- dev->meta_out_seq_count = dev->out_seq_count - dev->meta_out_seq_start;
-
- vivid_thread_vid_out_tick(dev);
- mutex_unlock(&dev->mutex);
-
- /*
- * Calculate the number of 'numerators' streamed since we started,
- * not including the current buffer.
- */
- numerators_since_start = buffers_since_start * numerator;
-
- /* And the number of jiffies since we started */
- jiffies_since_start = jiffies - dev->jiffies_vid_out;
-
- /* Increase by the 'numerator' of one buffer */
- numerators_since_start += numerator;
- /*
- * Calculate when that next buffer is supposed to start
- * in jiffies since we started streaming.
- */
- next_jiffies_since_start = numerators_since_start * HZ +
- denominator / 2;
- do_div(next_jiffies_since_start, denominator);
- /* If it is in the past, then just schedule asap */
- if (next_jiffies_since_start < jiffies_since_start)
- next_jiffies_since_start = jiffies_since_start;
-
- wait_jiffies = next_jiffies_since_start - jiffies_since_start;
- schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
- }
- dprintk(dev, 1, "Video Output Thread End\n");
- return 0;
-}
-
-static void vivid_grab_controls(struct vivid_dev *dev, bool grab)
-{
- v4l2_ctrl_grab(dev->ctrl_has_crop_out, grab);
- v4l2_ctrl_grab(dev->ctrl_has_compose_out, grab);
- v4l2_ctrl_grab(dev->ctrl_has_scaler_out, grab);
- v4l2_ctrl_grab(dev->ctrl_tx_mode, grab);
- v4l2_ctrl_grab(dev->ctrl_tx_rgb_range, grab);
-}
-
-int vivid_start_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
-{
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->kthread_vid_out) {
- u32 seq_count = dev->out_seq_count + dev->seq_wrap * 128;
-
- if (pstreaming == &dev->vid_out_streaming)
- dev->vid_out_seq_start = seq_count;
- else if (pstreaming == &dev->vbi_out_streaming)
- dev->vbi_out_seq_start = seq_count;
- else
- dev->meta_out_seq_start = seq_count;
- *pstreaming = true;
- return 0;
- }
-
- /* Resets frame counters */
- dev->jiffies_vid_out = jiffies;
- dev->vid_out_seq_start = dev->seq_wrap * 128;
- dev->vbi_out_seq_start = dev->seq_wrap * 128;
- dev->meta_out_seq_start = dev->seq_wrap * 128;
-
- dev->kthread_vid_out = kthread_run(vivid_thread_vid_out, dev,
- "%s-vid-out", dev->v4l2_dev.name);
-
- if (IS_ERR(dev->kthread_vid_out)) {
- int err = PTR_ERR(dev->kthread_vid_out);
-
- dev->kthread_vid_out = NULL;
- v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
- return err;
- }
- *pstreaming = true;
- vivid_grab_controls(dev, true);
-
- dprintk(dev, 1, "returning from %s\n", __func__);
- return 0;
-}
-
-void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
-{
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->kthread_vid_out == NULL)
- return;
-
- *pstreaming = false;
- if (pstreaming == &dev->vid_out_streaming) {
- /* Release all active buffers */
- while (!list_empty(&dev->vid_out_active)) {
- struct vivid_buffer *buf;
-
- buf = list_entry(dev->vid_out_active.next,
- struct vivid_buffer, list);
- list_del(&buf->list);
- v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vid_out);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- dprintk(dev, 2, "vid_out buffer %d done\n",
- buf->vb.vb2_buf.index);
- }
- }
-
- if (pstreaming == &dev->vbi_out_streaming) {
- while (!list_empty(&dev->vbi_out_active)) {
- struct vivid_buffer *buf;
-
- buf = list_entry(dev->vbi_out_active.next,
- struct vivid_buffer, list);
- list_del(&buf->list);
- v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_vbi_out);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- dprintk(dev, 2, "vbi_out buffer %d done\n",
- buf->vb.vb2_buf.index);
- }
- }
-
- if (pstreaming == &dev->meta_out_streaming) {
- while (!list_empty(&dev->meta_out_active)) {
- struct vivid_buffer *buf;
-
- buf = list_entry(dev->meta_out_active.next,
- struct vivid_buffer, list);
- list_del(&buf->list);
- v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_meta_out);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- dprintk(dev, 2, "meta_out buffer %d done\n",
- buf->vb.vb2_buf.index);
- }
- }
-
- if (dev->vid_out_streaming || dev->vbi_out_streaming ||
- dev->meta_out_streaming)
- return;
-
- /* shutdown control thread */
- vivid_grab_controls(dev, false);
- kthread_stop(dev->kthread_vid_out);
- dev->kthread_vid_out = NULL;
-}
diff --git a/drivers/media/platform/vivid/vivid-kthread-out.h b/drivers/media/platform/vivid/vivid-kthread-out.h
deleted file mode 100644
index d5bcf44bbaca..000000000000
--- a/drivers/media/platform/vivid/vivid-kthread-out.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-kthread-out.h - video/vbi output thread support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_KTHREAD_OUT_H_
-#define _VIVID_KTHREAD_OUT_H_
-
-int vivid_start_generating_vid_out(struct vivid_dev *dev, bool *pstreaming);
-void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-kthread-touch.c b/drivers/media/platform/vivid/vivid-kthread-touch.c
deleted file mode 100644
index 674507b5ccb5..000000000000
--- a/drivers/media/platform/vivid/vivid-kthread-touch.c
+++ /dev/null
@@ -1,181 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-kthread-touch.c - touch capture thread support functions.
- *
- */
-
-#include <linux/freezer.h>
-#include "vivid-core.h"
-#include "vivid-kthread-touch.h"
-#include "vivid-touch-cap.h"
-
-static noinline_for_stack void vivid_thread_tch_cap_tick(struct vivid_dev *dev,
- int dropped_bufs)
-{
- struct vivid_buffer *tch_cap_buf = NULL;
-
- spin_lock(&dev->slock);
- if (!list_empty(&dev->touch_cap_active)) {
- tch_cap_buf = list_entry(dev->touch_cap_active.next,
- struct vivid_buffer, list);
- list_del(&tch_cap_buf->list);
- }
-
- spin_unlock(&dev->slock);
-
- if (tch_cap_buf) {
- v4l2_ctrl_request_setup(tch_cap_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_touch_cap);
-
- vivid_fillbuff_tch(dev, tch_cap_buf);
- v4l2_ctrl_request_complete(tch_cap_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_touch_cap);
- vb2_buffer_done(&tch_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
- VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
- dprintk(dev, 2, "touch_cap buffer %d done\n",
- tch_cap_buf->vb.vb2_buf.index);
-
- tch_cap_buf->vb.vb2_buf.timestamp = ktime_get_ns() + dev->time_wrap_offset;
- }
- dev->dqbuf_error = false;
-}
-
-static int vivid_thread_touch_cap(void *data)
-{
- struct vivid_dev *dev = data;
- u64 numerators_since_start;
- u64 buffers_since_start;
- u64 next_jiffies_since_start;
- unsigned long jiffies_since_start;
- unsigned long cur_jiffies;
- unsigned int wait_jiffies;
- unsigned int numerator;
- unsigned int denominator;
- int dropped_bufs;
-
- dprintk(dev, 1, "Touch Capture Thread Start\n");
-
- set_freezable();
-
- /* Resets frame counters */
- dev->touch_cap_seq_offset = 0;
- dev->touch_cap_seq_count = 0;
- dev->touch_cap_seq_resync = false;
- dev->jiffies_touch_cap = jiffies;
-
- for (;;) {
- try_to_freeze();
- if (kthread_should_stop())
- break;
-
- if (!mutex_trylock(&dev->mutex)) {
- schedule_timeout_uninterruptible(1);
- continue;
- }
- cur_jiffies = jiffies;
- if (dev->touch_cap_seq_resync) {
- dev->jiffies_touch_cap = cur_jiffies;
- dev->touch_cap_seq_offset = dev->touch_cap_seq_count + 1;
- dev->touch_cap_seq_count = 0;
- dev->cap_seq_resync = false;
- }
- denominator = dev->timeperframe_tch_cap.denominator;
- numerator = dev->timeperframe_tch_cap.numerator;
-
- /* Calculate the number of jiffies since we started streaming */
- jiffies_since_start = cur_jiffies - dev->jiffies_touch_cap;
- /* Get the number of buffers streamed since the start */
- buffers_since_start = (u64)jiffies_since_start * denominator +
- (HZ * numerator) / 2;
- do_div(buffers_since_start, HZ * numerator);
-
- /*
- * After more than 0xf0000000 (rounded down to a multiple of
- * 'jiffies-per-day' to ease jiffies_to_msecs calculation)
- * jiffies have passed since we started streaming reset the
- * counters and keep track of the sequence offset.
- */
- if (jiffies_since_start > JIFFIES_RESYNC) {
- dev->jiffies_touch_cap = cur_jiffies;
- dev->cap_seq_offset = buffers_since_start;
- buffers_since_start = 0;
- }
- dropped_bufs = buffers_since_start + dev->touch_cap_seq_offset - dev->touch_cap_seq_count;
- dev->touch_cap_seq_count = buffers_since_start + dev->touch_cap_seq_offset;
-
- vivid_thread_tch_cap_tick(dev, dropped_bufs);
-
- /*
- * Calculate the number of 'numerators' streamed
- * since we started, including the current buffer.
- */
- numerators_since_start = ++buffers_since_start * numerator;
-
- /* And the number of jiffies since we started */
- jiffies_since_start = jiffies - dev->jiffies_touch_cap;
-
- mutex_unlock(&dev->mutex);
-
- /*
- * Calculate when that next buffer is supposed to start
- * in jiffies since we started streaming.
- */
- next_jiffies_since_start = numerators_since_start * HZ +
- denominator / 2;
- do_div(next_jiffies_since_start, denominator);
- /* If it is in the past, then just schedule asap */
- if (next_jiffies_since_start < jiffies_since_start)
- next_jiffies_since_start = jiffies_since_start;
-
- wait_jiffies = next_jiffies_since_start - jiffies_since_start;
- schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
- }
- dprintk(dev, 1, "Touch Capture Thread End\n");
- return 0;
-}
-
-int vivid_start_generating_touch_cap(struct vivid_dev *dev)
-{
- if (dev->kthread_touch_cap) {
- dev->touch_cap_streaming = true;
- return 0;
- }
-
- dev->kthread_touch_cap = kthread_run(vivid_thread_touch_cap, dev,
- "%s-tch-cap", dev->v4l2_dev.name);
-
- if (IS_ERR(dev->kthread_touch_cap)) {
- int err = PTR_ERR(dev->kthread_touch_cap);
-
- dev->kthread_touch_cap = NULL;
- v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
- return err;
- }
- dev->touch_cap_streaming = true;
- dprintk(dev, 1, "returning from %s\n", __func__);
- return 0;
-}
-
-void vivid_stop_generating_touch_cap(struct vivid_dev *dev)
-{
- if (!dev->kthread_touch_cap)
- return;
-
- dev->touch_cap_streaming = false;
-
- while (!list_empty(&dev->touch_cap_active)) {
- struct vivid_buffer *buf;
-
- buf = list_entry(dev->touch_cap_active.next,
- struct vivid_buffer, list);
- list_del(&buf->list);
- v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_touch_cap);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- dprintk(dev, 2, "touch_cap buffer %d done\n",
- buf->vb.vb2_buf.index);
- }
-
- kthread_stop(dev->kthread_touch_cap);
- dev->kthread_touch_cap = NULL;
-}
diff --git a/drivers/media/platform/vivid/vivid-kthread-touch.h b/drivers/media/platform/vivid/vivid-kthread-touch.h
deleted file mode 100644
index ecf79b46209e..000000000000
--- a/drivers/media/platform/vivid/vivid-kthread-touch.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-kthread-cap.h - video/vbi capture thread support functions.
- *
- */
-
-#ifndef _VIVID_KTHREAD_CAP_H_
-#define _VIVID_KTHREAD_CAP_H_
-
-int vivid_start_generating_touch_cap(struct vivid_dev *dev);
-void vivid_stop_generating_touch_cap(struct vivid_dev *dev);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-meta-cap.c b/drivers/media/platform/vivid/vivid-meta-cap.c
deleted file mode 100644
index 780f96860a6d..000000000000
--- a/drivers/media/platform/vivid/vivid-meta-cap.c
+++ /dev/null
@@ -1,201 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-meta-cap.c - meta capture support functions.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <linux/usb/video.h>
-
-#include "vivid-core.h"
-#include "vivid-kthread-cap.h"
-#include "vivid-meta-cap.h"
-
-static int meta_cap_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned int sizes[],
- struct device *alloc_devs[])
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- unsigned int size = sizeof(struct vivid_uvc_meta_buf);
-
- if (!vivid_is_webcam(dev))
- return -EINVAL;
-
- if (*nplanes) {
- if (sizes[0] < size)
- return -EINVAL;
- } else {
- sizes[0] = size;
- }
-
- if (vq->num_buffers + *nbuffers < 2)
- *nbuffers = 2 - vq->num_buffers;
-
- *nplanes = 1;
- return 0;
-}
-
-static int meta_cap_buf_prepare(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- unsigned int size = sizeof(struct vivid_uvc_meta_buf);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->buf_prepare_error) {
- /*
- * Error injection: test what happens if buf_prepare() returns
- * an error.
- */
- dev->buf_prepare_error = false;
- return -EINVAL;
- }
- if (vb2_plane_size(vb, 0) < size) {
- dprintk(dev, 1, "%s data will not fit into plane (%lu < %u)\n",
- __func__, vb2_plane_size(vb, 0), size);
- return -EINVAL;
- }
- vb2_set_plane_payload(vb, 0, size);
-
- return 0;
-}
-
-static void meta_cap_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- spin_lock(&dev->slock);
- list_add_tail(&buf->list, &dev->meta_cap_active);
- spin_unlock(&dev->slock);
-}
-
-static int meta_cap_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- int err;
-
- dprintk(dev, 1, "%s\n", __func__);
- dev->meta_cap_seq_count = 0;
- if (dev->start_streaming_error) {
- dev->start_streaming_error = false;
- err = -EINVAL;
- } else {
- err = vivid_start_generating_vid_cap(dev,
- &dev->meta_cap_streaming);
- }
- if (err) {
- struct vivid_buffer *buf, *tmp;
-
- list_for_each_entry_safe(buf, tmp,
- &dev->meta_cap_active, list) {
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf,
- VB2_BUF_STATE_QUEUED);
- }
- }
- return err;
-}
-
-/* abort streaming and wait for last buffer */
-static void meta_cap_stop_streaming(struct vb2_queue *vq)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
-
- dprintk(dev, 1, "%s\n", __func__);
- vivid_stop_generating_vid_cap(dev, &dev->meta_cap_streaming);
-}
-
-static void meta_cap_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_meta_cap);
-}
-
-const struct vb2_ops vivid_meta_cap_qops = {
- .queue_setup = meta_cap_queue_setup,
- .buf_prepare = meta_cap_buf_prepare,
- .buf_queue = meta_cap_buf_queue,
- .start_streaming = meta_cap_start_streaming,
- .stop_streaming = meta_cap_stop_streaming,
- .buf_request_complete = meta_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-int vidioc_enum_fmt_meta_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_webcam(dev))
- return -EINVAL;
-
- if (f->index > 0)
- return -EINVAL;
-
- f->type = V4L2_BUF_TYPE_META_CAPTURE;
- f->pixelformat = V4L2_META_FMT_UVC;
- return 0;
-}
-
-int vidioc_g_fmt_meta_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_meta_format *meta = &f->fmt.meta;
-
- if (!vivid_is_webcam(dev) || !dev->has_meta_cap)
- return -EINVAL;
-
- meta->dataformat = V4L2_META_FMT_UVC;
- meta->buffersize = sizeof(struct vivid_uvc_meta_buf);
- return 0;
-}
-
-void vivid_meta_cap_fillbuff(struct vivid_dev *dev,
- struct vivid_buffer *buf, u64 soe)
-{
- struct vivid_uvc_meta_buf *meta = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
- int buf_off = 0;
-
- buf->vb.sequence = dev->meta_cap_seq_count;
- if (dev->field_cap == V4L2_FIELD_ALTERNATE)
- buf->vb.sequence /= 2;
- memset(meta, 1, vb2_plane_size(&buf->vb.vb2_buf, 0));
-
- meta->ns = ktime_get_ns();
- meta->sof = buf->vb.sequence * 30;
- meta->length = sizeof(*meta) - offsetof(struct vivid_uvc_meta_buf, length);
- meta->flags = UVC_STREAM_EOH | UVC_STREAM_EOF;
-
- if ((buf->vb.sequence % 2) == 0)
- meta->flags |= UVC_STREAM_FID;
-
- dprintk(dev, 2, "%s ns:%llu sof:%4d len:%u flags: 0x%02x",
- __func__, meta->ns, meta->sof, meta->length, meta->flags);
- if (dev->meta_pts) {
- meta->flags |= UVC_STREAM_PTS;
- meta->buf[0] = div_u64(soe, VIVID_META_CLOCK_UNIT);
- buf_off = 4;
- dprintk(dev, 2, " pts: %u\n", *(__u32 *)(meta->buf));
- }
-
- if (dev->meta_scr) {
- meta->flags |= UVC_STREAM_SCR;
- meta->buf[buf_off] = div_u64((soe + dev->cap_frame_eof_offset),
- VIVID_META_CLOCK_UNIT);
-
- meta->buf[buf_off + 4] = (buf->vb.sequence * 30) % 1000;
- dprintk(dev, 2, " stc: %u, sof counter: %u\n",
- *(__u32 *)(meta->buf + buf_off),
- *(__u16 *)(meta->buf + buf_off + 4));
- }
- dprintk(dev, 2, "\n");
-}
diff --git a/drivers/media/platform/vivid/vivid-meta-cap.h b/drivers/media/platform/vivid/vivid-meta-cap.h
deleted file mode 100644
index 4670d00d1576..000000000000
--- a/drivers/media/platform/vivid/vivid-meta-cap.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-meta-cap.h - meta capture support functions.
- */
-#ifndef _VIVID_META_CAP_H_
-#define _VIVID_META_CAP_H_
-
-#define VIVID_META_CLOCK_UNIT 10 /* 100 MHz */
-
-struct vivid_uvc_meta_buf {
- __u64 ns;
- __u16 sof;
- __u8 length;
- __u8 flags;
- __u8 buf[10]; /* PTS(4)+STC(4)+SOF(2) */
-} __packed;
-
-void vivid_meta_cap_fillbuff(struct vivid_dev *dev,
- struct vivid_buffer *buf, u64 soe);
-
-int vidioc_enum_fmt_meta_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f);
-
-int vidioc_g_fmt_meta_cap(struct file *file, void *priv,
- struct v4l2_format *f);
-
-extern const struct vb2_ops vivid_meta_cap_qops;
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-meta-out.c b/drivers/media/platform/vivid/vivid-meta-out.c
deleted file mode 100644
index ff8a039aba72..000000000000
--- a/drivers/media/platform/vivid/vivid-meta-out.c
+++ /dev/null
@@ -1,174 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-meta-out.c - meta output support functions.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <linux/usb/video.h>
-
-#include "vivid-core.h"
-#include "vivid-kthread-out.h"
-#include "vivid-meta-out.h"
-
-static int meta_out_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned int sizes[],
- struct device *alloc_devs[])
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- unsigned int size = sizeof(struct vivid_meta_out_buf);
-
- if (!vivid_is_webcam(dev))
- return -EINVAL;
-
- if (*nplanes) {
- if (sizes[0] < size)
- return -EINVAL;
- } else {
- sizes[0] = size;
- }
-
- if (vq->num_buffers + *nbuffers < 2)
- *nbuffers = 2 - vq->num_buffers;
-
- *nplanes = 1;
- return 0;
-}
-
-static int meta_out_buf_prepare(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- unsigned int size = sizeof(struct vivid_meta_out_buf);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->buf_prepare_error) {
- /*
- * Error injection: test what happens if buf_prepare() returns
- * an error.
- */
- dev->buf_prepare_error = false;
- return -EINVAL;
- }
- if (vb2_plane_size(vb, 0) < size) {
- dprintk(dev, 1, "%s data will not fit into plane (%lu < %u)\n",
- __func__, vb2_plane_size(vb, 0), size);
- return -EINVAL;
- }
- vb2_set_plane_payload(vb, 0, size);
-
- return 0;
-}
-
-static void meta_out_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- spin_lock(&dev->slock);
- list_add_tail(&buf->list, &dev->meta_out_active);
- spin_unlock(&dev->slock);
-}
-
-static int meta_out_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- int err;
-
- dprintk(dev, 1, "%s\n", __func__);
- dev->meta_out_seq_count = 0;
- if (dev->start_streaming_error) {
- dev->start_streaming_error = false;
- err = -EINVAL;
- } else {
- err = vivid_start_generating_vid_out(dev,
- &dev->meta_out_streaming);
- }
- if (err) {
- struct vivid_buffer *buf, *tmp;
-
- list_for_each_entry_safe(buf, tmp,
- &dev->meta_out_active, list) {
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf,
- VB2_BUF_STATE_QUEUED);
- }
- }
- return err;
-}
-
-/* abort streaming and wait for last buffer */
-static void meta_out_stop_streaming(struct vb2_queue *vq)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
-
- dprintk(dev, 1, "%s\n", __func__);
- vivid_stop_generating_vid_out(dev, &dev->meta_out_streaming);
-}
-
-static void meta_out_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_meta_out);
-}
-
-const struct vb2_ops vivid_meta_out_qops = {
- .queue_setup = meta_out_queue_setup,
- .buf_prepare = meta_out_buf_prepare,
- .buf_queue = meta_out_buf_queue,
- .start_streaming = meta_out_start_streaming,
- .stop_streaming = meta_out_stop_streaming,
- .buf_request_complete = meta_out_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-int vidioc_enum_fmt_meta_out(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_webcam(dev))
- return -EINVAL;
-
- if (f->index > 0)
- return -EINVAL;
-
- f->type = V4L2_BUF_TYPE_META_OUTPUT;
- f->pixelformat = V4L2_META_FMT_VIVID;
- return 0;
-}
-
-int vidioc_g_fmt_meta_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_meta_format *meta = &f->fmt.meta;
-
- if (!vivid_is_webcam(dev) || !dev->has_meta_out)
- return -EINVAL;
-
- meta->dataformat = V4L2_META_FMT_VIVID;
- meta->buffersize = sizeof(struct vivid_meta_out_buf);
- return 0;
-}
-
-void vivid_meta_out_process(struct vivid_dev *dev,
- struct vivid_buffer *buf)
-{
- struct vivid_meta_out_buf *meta = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
-
- tpg_s_brightness(&dev->tpg, meta->brightness);
- tpg_s_contrast(&dev->tpg, meta->contrast);
- tpg_s_saturation(&dev->tpg, meta->saturation);
- tpg_s_hue(&dev->tpg, meta->hue);
- dprintk(dev, 2, " %s brightness %u contrast %u saturation %u hue %d\n",
- __func__, meta->brightness, meta->contrast,
- meta->saturation, meta->hue);
-}
diff --git a/drivers/media/platform/vivid/vivid-meta-out.h b/drivers/media/platform/vivid/vivid-meta-out.h
deleted file mode 100644
index 0c639b7c2842..000000000000
--- a/drivers/media/platform/vivid/vivid-meta-out.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-meta-out.h - meta output support functions.
- */
-#ifndef _VIVID_META_OUT_H_
-#define _VIVID_META_OUT_H_
-
-struct vivid_meta_out_buf {
- u16 brightness;
- u16 contrast;
- u16 saturation;
- s16 hue;
-};
-
-void vivid_meta_out_process(struct vivid_dev *dev, struct vivid_buffer *buf);
-int vidioc_enum_fmt_meta_out(struct file *file, void *priv,
- struct v4l2_fmtdesc *f);
-int vidioc_g_fmt_meta_out(struct file *file, void *priv,
- struct v4l2_format *f);
-int vidioc_s_fmt_meta_out(struct file *file, void *priv,
- struct v4l2_format *f);
-
-extern const struct vb2_ops vivid_meta_out_qops;
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c
deleted file mode 100644
index fbaec8acc161..000000000000
--- a/drivers/media/platform/vivid/vivid-osd.c
+++ /dev/null
@@ -1,388 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-osd.c - osd support for testing overlays.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/font.h>
-#include <linux/mutex.h>
-#include <linux/videodev2.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/fb.h>
-#include <media/videobuf2-vmalloc.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-common.h>
-
-#include "vivid-core.h"
-#include "vivid-osd.h"
-
-#define MAX_OSD_WIDTH 720
-#define MAX_OSD_HEIGHT 576
-
-/*
- * Order: white, yellow, cyan, green, magenta, red, blue, black,
- * and same again with the alpha bit set (if any)
- */
-static const u16 rgb555[16] = {
- 0x7fff, 0x7fe0, 0x03ff, 0x03e0, 0x7c1f, 0x7c00, 0x001f, 0x0000,
- 0xffff, 0xffe0, 0x83ff, 0x83e0, 0xfc1f, 0xfc00, 0x801f, 0x8000
-};
-
-static const u16 rgb565[16] = {
- 0xffff, 0xffe0, 0x07ff, 0x07e0, 0xf81f, 0xf800, 0x001f, 0x0000,
- 0xffff, 0xffe0, 0x07ff, 0x07e0, 0xf81f, 0xf800, 0x001f, 0x0000
-};
-
-void vivid_clear_fb(struct vivid_dev *dev)
-{
- void *p = dev->video_vbase;
- const u16 *rgb = rgb555;
- unsigned x, y;
-
- if (dev->fb_defined.green.length == 6)
- rgb = rgb565;
-
- for (y = 0; y < dev->display_height; y++) {
- u16 *d = p;
-
- for (x = 0; x < dev->display_width; x++)
- d[x] = rgb[(y / 16 + x / 16) % 16];
- p += dev->display_byte_stride;
- }
-}
-
-/* --------------------------------------------------------------------- */
-
-static int vivid_fb_ioctl(struct fb_info *info, unsigned cmd, unsigned long arg)
-{
- struct vivid_dev *dev = (struct vivid_dev *)info->par;
-
- switch (cmd) {
- case FBIOGET_VBLANK: {
- struct fb_vblank vblank;
-
- memset(&vblank, 0, sizeof(vblank));
- vblank.flags = FB_VBLANK_HAVE_COUNT | FB_VBLANK_HAVE_VCOUNT |
- FB_VBLANK_HAVE_VSYNC;
- vblank.count = 0;
- vblank.vcount = 0;
- vblank.hcount = 0;
- if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
- return -EFAULT;
- return 0;
- }
-
- default:
- dprintk(dev, 1, "Unknown ioctl %08x\n", cmd);
- return -EINVAL;
- }
- return 0;
-}
-
-/* Framebuffer device handling */
-
-static int vivid_fb_set_var(struct vivid_dev *dev, struct fb_var_screeninfo *var)
-{
- dprintk(dev, 1, "vivid_fb_set_var\n");
-
- if (var->bits_per_pixel != 16) {
- dprintk(dev, 1, "vivid_fb_set_var - Invalid bpp\n");
- return -EINVAL;
- }
- dev->display_byte_stride = var->xres * dev->bytes_per_pixel;
-
- return 0;
-}
-
-static int vivid_fb_get_fix(struct vivid_dev *dev, struct fb_fix_screeninfo *fix)
-{
- dprintk(dev, 1, "vivid_fb_get_fix\n");
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strscpy(fix->id, "vioverlay fb", sizeof(fix->id));
- fix->smem_start = dev->video_pbase;
- fix->smem_len = dev->video_buffer_size;
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->visual = FB_VISUAL_TRUECOLOR;
- fix->xpanstep = 1;
- fix->ypanstep = 1;
- fix->ywrapstep = 0;
- fix->line_length = dev->display_byte_stride;
- fix->accel = FB_ACCEL_NONE;
- return 0;
-}
-
-/* Check the requested display mode, returning -EINVAL if we can't
- handle it. */
-
-static int _vivid_fb_check_var(struct fb_var_screeninfo *var, struct vivid_dev *dev)
-{
- dprintk(dev, 1, "vivid_fb_check_var\n");
-
- var->bits_per_pixel = 16;
- if (var->green.length == 5) {
- var->red.offset = 10;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 5;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 15;
- var->transp.length = 1;
- } else {
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- }
- var->xoffset = var->yoffset = 0;
- var->left_margin = var->upper_margin = 0;
- var->nonstd = 0;
-
- var->vmode &= ~FB_VMODE_MASK;
- var->vmode |= FB_VMODE_NONINTERLACED;
-
- /* Dummy values */
- var->hsync_len = 24;
- var->vsync_len = 2;
- var->pixclock = 84316;
- var->right_margin = 776;
- var->lower_margin = 591;
- return 0;
-}
-
-static int vivid_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct vivid_dev *dev = (struct vivid_dev *) info->par;
-
- dprintk(dev, 1, "vivid_fb_check_var\n");
- return _vivid_fb_check_var(var, dev);
-}
-
-static int vivid_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- return 0;
-}
-
-static int vivid_fb_set_par(struct fb_info *info)
-{
- int rc = 0;
- struct vivid_dev *dev = (struct vivid_dev *) info->par;
-
- dprintk(dev, 1, "vivid_fb_set_par\n");
-
- rc = vivid_fb_set_var(dev, &info->var);
- vivid_fb_get_fix(dev, &info->fix);
- return rc;
-}
-
-static int vivid_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
- u32 color, *palette;
-
- if (regno >= info->cmap.len)
- return -EINVAL;
-
- color = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) |
- (green & 0xFF00) | ((blue & 0xFF00) >> 8);
- if (regno >= 16)
- return -EINVAL;
-
- palette = info->pseudo_palette;
- if (info->var.bits_per_pixel == 16) {
- switch (info->var.green.length) {
- case 6:
- color = (red & 0xf800) |
- ((green & 0xfc00) >> 5) |
- ((blue & 0xf800) >> 11);
- break;
- case 5:
- color = ((red & 0xf800) >> 1) |
- ((green & 0xf800) >> 6) |
- ((blue & 0xf800) >> 11) |
- (transp ? 0x8000 : 0);
- break;
- }
- }
- palette[regno] = color;
- return 0;
-}
-
-/* We don't really support blanking. All this does is enable or
- disable the OSD. */
-static int vivid_fb_blank(int blank_mode, struct fb_info *info)
-{
- struct vivid_dev *dev = (struct vivid_dev *)info->par;
-
- dprintk(dev, 1, "Set blanking mode : %d\n", blank_mode);
- switch (blank_mode) {
- case FB_BLANK_UNBLANK:
- break;
- case FB_BLANK_NORMAL:
- case FB_BLANK_HSYNC_SUSPEND:
- case FB_BLANK_VSYNC_SUSPEND:
- case FB_BLANK_POWERDOWN:
- break;
- }
- return 0;
-}
-
-static const struct fb_ops vivid_fb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = vivid_fb_check_var,
- .fb_set_par = vivid_fb_set_par,
- .fb_setcolreg = vivid_fb_setcolreg,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_cursor = NULL,
- .fb_ioctl = vivid_fb_ioctl,
- .fb_pan_display = vivid_fb_pan_display,
- .fb_blank = vivid_fb_blank,
-};
-
-/* Initialization */
-
-
-/* Setup our initial video mode */
-static int vivid_fb_init_vidmode(struct vivid_dev *dev)
-{
- struct v4l2_rect start_window;
-
- /* Color mode */
-
- dev->bits_per_pixel = 16;
- dev->bytes_per_pixel = dev->bits_per_pixel / 8;
-
- start_window.width = MAX_OSD_WIDTH;
- start_window.left = 0;
-
- dev->display_byte_stride = start_window.width * dev->bytes_per_pixel;
-
- /* Vertical size & position */
-
- start_window.height = MAX_OSD_HEIGHT;
- start_window.top = 0;
-
- dev->display_width = start_window.width;
- dev->display_height = start_window.height;
-
- /* Generate a valid fb_var_screeninfo */
-
- dev->fb_defined.xres = dev->display_width;
- dev->fb_defined.yres = dev->display_height;
- dev->fb_defined.xres_virtual = dev->display_width;
- dev->fb_defined.yres_virtual = dev->display_height;
- dev->fb_defined.bits_per_pixel = dev->bits_per_pixel;
- dev->fb_defined.vmode = FB_VMODE_NONINTERLACED;
- dev->fb_defined.left_margin = start_window.left + 1;
- dev->fb_defined.upper_margin = start_window.top + 1;
- dev->fb_defined.accel_flags = FB_ACCEL_NONE;
- dev->fb_defined.nonstd = 0;
- /* set default to 1:5:5:5 */
- dev->fb_defined.green.length = 5;
-
- /* We've filled in the most data, let the usual mode check
- routine fill in the rest. */
- _vivid_fb_check_var(&dev->fb_defined, dev);
-
- /* Generate valid fb_fix_screeninfo */
-
- vivid_fb_get_fix(dev, &dev->fb_fix);
-
- /* Generate valid fb_info */
-
- dev->fb_info.node = -1;
- dev->fb_info.flags = FBINFO_FLAG_DEFAULT;
- dev->fb_info.par = dev;
- dev->fb_info.var = dev->fb_defined;
- dev->fb_info.fix = dev->fb_fix;
- dev->fb_info.screen_base = (u8 __iomem *)dev->video_vbase;
- dev->fb_info.fbops = &vivid_fb_ops;
-
- /* Supply some monitor specs. Bogus values will do for now */
- dev->fb_info.monspecs.hfmin = 8000;
- dev->fb_info.monspecs.hfmax = 70000;
- dev->fb_info.monspecs.vfmin = 10;
- dev->fb_info.monspecs.vfmax = 100;
-
- /* Allocate color map */
- if (fb_alloc_cmap(&dev->fb_info.cmap, 256, 1)) {
- pr_err("abort, unable to alloc cmap\n");
- return -ENOMEM;
- }
-
- /* Allocate the pseudo palette */
- dev->fb_info.pseudo_palette = kmalloc_array(16, sizeof(u32), GFP_KERNEL);
-
- return dev->fb_info.pseudo_palette ? 0 : -ENOMEM;
-}
-
-/* Release any memory we've grabbed */
-void vivid_fb_release_buffers(struct vivid_dev *dev)
-{
- if (dev->video_vbase == NULL)
- return;
-
- /* Release cmap */
- if (dev->fb_info.cmap.len)
- fb_dealloc_cmap(&dev->fb_info.cmap);
-
- /* Release pseudo palette */
- kfree(dev->fb_info.pseudo_palette);
- kfree(dev->video_vbase);
-}
-
-/* Initialize the specified card */
-
-int vivid_fb_init(struct vivid_dev *dev)
-{
- int ret;
-
- dev->video_buffer_size = MAX_OSD_HEIGHT * MAX_OSD_WIDTH * 2;
- dev->video_vbase = kzalloc(dev->video_buffer_size, GFP_KERNEL | GFP_DMA32);
- if (dev->video_vbase == NULL)
- return -ENOMEM;
- dev->video_pbase = virt_to_phys(dev->video_vbase);
-
- pr_info("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
- dev->video_pbase, dev->video_vbase,
- dev->video_buffer_size / 1024);
-
- /* Set the startup video mode information */
- ret = vivid_fb_init_vidmode(dev);
- if (ret) {
- vivid_fb_release_buffers(dev);
- return ret;
- }
-
- vivid_clear_fb(dev);
-
- /* Register the framebuffer */
- if (register_framebuffer(&dev->fb_info) < 0) {
- vivid_fb_release_buffers(dev);
- return -EINVAL;
- }
-
- /* Set the card to the requested mode */
- vivid_fb_set_par(&dev->fb_info);
- return 0;
-
-}
diff --git a/drivers/media/platform/vivid/vivid-osd.h b/drivers/media/platform/vivid/vivid-osd.h
deleted file mode 100644
index f9ac1af25dd3..000000000000
--- a/drivers/media/platform/vivid/vivid-osd.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-osd.h - output overlay support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_OSD_H_
-#define _VIVID_OSD_H_
-
-int vivid_fb_init(struct vivid_dev *dev);
-void vivid_fb_release_buffers(struct vivid_dev *dev);
-void vivid_clear_fb(struct vivid_dev *dev);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-radio-common.c b/drivers/media/platform/vivid/vivid-radio-common.c
deleted file mode 100644
index 138c7bce68b1..000000000000
--- a/drivers/media/platform/vivid/vivid-radio-common.c
+++ /dev/null
@@ -1,177 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-radio-common.c - common radio rx/tx support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-
-#include "vivid-core.h"
-#include "vivid-ctrls.h"
-#include "vivid-radio-common.h"
-#include "vivid-rds-gen.h"
-
-/*
- * These functions are shared between the vivid receiver and transmitter
- * since both use the same frequency bands.
- */
-
-const struct v4l2_frequency_band vivid_radio_bands[TOT_BANDS] = {
- /* Band FM */
- {
- .type = V4L2_TUNER_RADIO,
- .index = 0,
- .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
- V4L2_TUNER_CAP_FREQ_BANDS,
- .rangelow = FM_FREQ_RANGE_LOW,
- .rangehigh = FM_FREQ_RANGE_HIGH,
- .modulation = V4L2_BAND_MODULATION_FM,
- },
- /* Band AM */
- {
- .type = V4L2_TUNER_RADIO,
- .index = 1,
- .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
- .rangelow = AM_FREQ_RANGE_LOW,
- .rangehigh = AM_FREQ_RANGE_HIGH,
- .modulation = V4L2_BAND_MODULATION_AM,
- },
- /* Band SW */
- {
- .type = V4L2_TUNER_RADIO,
- .index = 2,
- .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
- .rangelow = SW_FREQ_RANGE_LOW,
- .rangehigh = SW_FREQ_RANGE_HIGH,
- .modulation = V4L2_BAND_MODULATION_AM,
- },
-};
-
-/*
- * Initialize the RDS generator. If we can loop, then the RDS generator
- * is set up with the values from the RDS TX controls, otherwise it
- * will fill in standard values using one of two alternates.
- */
-void vivid_radio_rds_init(struct vivid_dev *dev)
-{
- struct vivid_rds_gen *rds = &dev->rds_gen;
- bool alt = dev->radio_rx_rds_use_alternates;
-
- /* Do nothing, blocks will be filled by the transmitter */
- if (dev->radio_rds_loop && !dev->radio_tx_rds_controls)
- return;
-
- if (dev->radio_rds_loop) {
- v4l2_ctrl_lock(dev->radio_tx_rds_pi);
- rds->picode = dev->radio_tx_rds_pi->cur.val;
- rds->pty = dev->radio_tx_rds_pty->cur.val;
- rds->mono_stereo = dev->radio_tx_rds_mono_stereo->cur.val;
- rds->art_head = dev->radio_tx_rds_art_head->cur.val;
- rds->compressed = dev->radio_tx_rds_compressed->cur.val;
- rds->dyn_pty = dev->radio_tx_rds_dyn_pty->cur.val;
- rds->ta = dev->radio_tx_rds_ta->cur.val;
- rds->tp = dev->radio_tx_rds_tp->cur.val;
- rds->ms = dev->radio_tx_rds_ms->cur.val;
- strscpy(rds->psname,
- dev->radio_tx_rds_psname->p_cur.p_char,
- sizeof(rds->psname));
- strscpy(rds->radiotext,
- dev->radio_tx_rds_radiotext->p_cur.p_char + alt * 64,
- sizeof(rds->radiotext));
- v4l2_ctrl_unlock(dev->radio_tx_rds_pi);
- } else {
- vivid_rds_gen_fill(rds, dev->radio_rx_freq, alt);
- }
- if (dev->radio_rx_rds_controls) {
- v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, rds->pty);
- v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, rds->ta);
- v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, rds->tp);
- v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, rds->ms);
- v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, rds->psname);
- v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, rds->radiotext);
- if (!dev->radio_rds_loop)
- dev->radio_rx_rds_use_alternates = !dev->radio_rx_rds_use_alternates;
- }
- vivid_rds_generate(rds);
-}
-
-/*
- * Calculate the emulated signal quality taking into account the frequency
- * the transmitter is using.
- */
-static void vivid_radio_calc_sig_qual(struct vivid_dev *dev)
-{
- int mod = 16000;
- int delta = 800;
- int sig_qual, sig_qual_tx = mod;
-
- /*
- * For SW and FM there is a channel every 1000 kHz, for AM there is one
- * every 100 kHz.
- */
- if (dev->radio_rx_freq <= AM_FREQ_RANGE_HIGH) {
- mod /= 10;
- delta /= 10;
- }
- sig_qual = (dev->radio_rx_freq + delta) % mod - delta;
- if (dev->has_radio_tx)
- sig_qual_tx = dev->radio_rx_freq - dev->radio_tx_freq;
- if (abs(sig_qual_tx) <= abs(sig_qual)) {
- sig_qual = sig_qual_tx;
- /*
- * Zero the internal rds buffer if we are going to loop
- * rds blocks.
- */
- if (!dev->radio_rds_loop && !dev->radio_tx_rds_controls)
- memset(dev->rds_gen.data, 0,
- sizeof(dev->rds_gen.data));
- dev->radio_rds_loop = dev->radio_rx_freq >= FM_FREQ_RANGE_LOW;
- } else {
- dev->radio_rds_loop = false;
- }
- if (dev->radio_rx_freq <= AM_FREQ_RANGE_HIGH)
- sig_qual *= 10;
- dev->radio_rx_sig_qual = sig_qual;
-}
-
-int vivid_radio_g_frequency(struct file *file, const unsigned *pfreq, struct v4l2_frequency *vf)
-{
- if (vf->tuner != 0)
- return -EINVAL;
- vf->frequency = *pfreq;
- return 0;
-}
-
-int vivid_radio_s_frequency(struct file *file, unsigned *pfreq, const struct v4l2_frequency *vf)
-{
- struct vivid_dev *dev = video_drvdata(file);
- unsigned freq;
- unsigned band;
-
- if (vf->tuner != 0)
- return -EINVAL;
-
- if (vf->frequency >= (FM_FREQ_RANGE_LOW + SW_FREQ_RANGE_HIGH) / 2)
- band = BAND_FM;
- else if (vf->frequency <= (AM_FREQ_RANGE_HIGH + SW_FREQ_RANGE_LOW) / 2)
- band = BAND_AM;
- else
- band = BAND_SW;
-
- freq = clamp_t(u32, vf->frequency, vivid_radio_bands[band].rangelow,
- vivid_radio_bands[band].rangehigh);
- *pfreq = freq;
-
- /*
- * For both receiver and transmitter recalculate the signal quality
- * (since that depends on both frequencies) and re-init the rds
- * generator.
- */
- vivid_radio_calc_sig_qual(dev);
- vivid_radio_rds_init(dev);
- return 0;
-}
diff --git a/drivers/media/platform/vivid/vivid-radio-common.h b/drivers/media/platform/vivid/vivid-radio-common.h
deleted file mode 100644
index 30a9900e5b2b..000000000000
--- a/drivers/media/platform/vivid/vivid-radio-common.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-radio-common.h - common radio rx/tx support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_RADIO_COMMON_H_
-#define _VIVID_RADIO_COMMON_H_
-
-/* The supported radio frequency ranges in kHz */
-#define FM_FREQ_RANGE_LOW (64000U * 16U)
-#define FM_FREQ_RANGE_HIGH (108000U * 16U)
-#define AM_FREQ_RANGE_LOW (520U * 16U)
-#define AM_FREQ_RANGE_HIGH (1710U * 16U)
-#define SW_FREQ_RANGE_LOW (2300U * 16U)
-#define SW_FREQ_RANGE_HIGH (26100U * 16U)
-
-enum { BAND_FM, BAND_AM, BAND_SW, TOT_BANDS };
-
-extern const struct v4l2_frequency_band vivid_radio_bands[TOT_BANDS];
-
-int vivid_radio_g_frequency(struct file *file, const unsigned *freq, struct v4l2_frequency *vf);
-int vivid_radio_s_frequency(struct file *file, unsigned *freq, const struct v4l2_frequency *vf);
-
-void vivid_radio_rds_init(struct vivid_dev *dev);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-radio-rx.c b/drivers/media/platform/vivid/vivid-radio-rx.c
deleted file mode 100644
index 232cab508f48..000000000000
--- a/drivers/media/platform/vivid/vivid-radio-rx.c
+++ /dev/null
@@ -1,278 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-radio-rx.c - radio receiver support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <linux/v4l2-dv-timings.h>
-#include <linux/sched/signal.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-dv-timings.h>
-
-#include "vivid-core.h"
-#include "vivid-ctrls.h"
-#include "vivid-radio-common.h"
-#include "vivid-rds-gen.h"
-#include "vivid-radio-rx.h"
-
-ssize_t vivid_radio_rx_read(struct file *file, char __user *buf,
- size_t size, loff_t *offset)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_rds_data *data = dev->rds_gen.data;
- bool use_alternates;
- ktime_t timestamp;
- unsigned blk;
- int perc;
- int i;
-
- if (dev->radio_rx_rds_controls)
- return -EINVAL;
- if (size < sizeof(*data))
- return 0;
- size = sizeof(*data) * (size / sizeof(*data));
-
- if (mutex_lock_interruptible(&dev->mutex))
- return -ERESTARTSYS;
- if (dev->radio_rx_rds_owner &&
- file->private_data != dev->radio_rx_rds_owner) {
- mutex_unlock(&dev->mutex);
- return -EBUSY;
- }
- if (dev->radio_rx_rds_owner == NULL) {
- vivid_radio_rds_init(dev);
- dev->radio_rx_rds_owner = file->private_data;
- }
-
-retry:
- timestamp = ktime_sub(ktime_get(), dev->radio_rds_init_time);
- blk = ktime_divns(timestamp, VIVID_RDS_NSEC_PER_BLK);
- use_alternates = (blk % VIVID_RDS_GEN_BLOCKS) & 1;
-
- if (dev->radio_rx_rds_last_block == 0 ||
- dev->radio_rx_rds_use_alternates != use_alternates) {
- dev->radio_rx_rds_use_alternates = use_alternates;
- /* Re-init the RDS generator */
- vivid_radio_rds_init(dev);
- }
- if (blk >= dev->radio_rx_rds_last_block + VIVID_RDS_GEN_BLOCKS)
- dev->radio_rx_rds_last_block = blk - VIVID_RDS_GEN_BLOCKS + 1;
-
- /*
- * No data is available if there hasn't been time to get new data,
- * or if the RDS receiver has been disabled, or if we use the data
- * from the RDS transmitter and that RDS transmitter has been disabled,
- * or if the signal quality is too weak.
- */
- if (blk == dev->radio_rx_rds_last_block || !dev->radio_rx_rds_enabled ||
- (dev->radio_rds_loop && !(dev->radio_tx_subchans & V4L2_TUNER_SUB_RDS)) ||
- abs(dev->radio_rx_sig_qual) > 200) {
- mutex_unlock(&dev->mutex);
- if (file->f_flags & O_NONBLOCK)
- return -EWOULDBLOCK;
- if (msleep_interruptible(20) && signal_pending(current))
- return -EINTR;
- if (mutex_lock_interruptible(&dev->mutex))
- return -ERESTARTSYS;
- goto retry;
- }
-
- /* abs(dev->radio_rx_sig_qual) <= 200, map that to a 0-50% range */
- perc = abs(dev->radio_rx_sig_qual) / 4;
-
- for (i = 0; i < size && blk > dev->radio_rx_rds_last_block;
- dev->radio_rx_rds_last_block++) {
- unsigned data_blk = dev->radio_rx_rds_last_block % VIVID_RDS_GEN_BLOCKS;
- struct v4l2_rds_data rds = data[data_blk];
-
- if (data_blk == 0 && dev->radio_rds_loop)
- vivid_radio_rds_init(dev);
- if (perc && prandom_u32_max(100) < perc) {
- switch (prandom_u32_max(4)) {
- case 0:
- rds.block |= V4L2_RDS_BLOCK_CORRECTED;
- break;
- case 1:
- rds.block |= V4L2_RDS_BLOCK_INVALID;
- break;
- case 2:
- rds.block |= V4L2_RDS_BLOCK_ERROR;
- rds.lsb = prandom_u32_max(256);
- rds.msb = prandom_u32_max(256);
- break;
- case 3: /* Skip block altogether */
- if (i)
- continue;
- /*
- * Must make sure at least one block is
- * returned, otherwise the application
- * might think that end-of-file occurred.
- */
- break;
- }
- }
- if (copy_to_user(buf + i, &rds, sizeof(rds))) {
- i = -EFAULT;
- break;
- }
- i += sizeof(rds);
- }
- mutex_unlock(&dev->mutex);
- return i;
-}
-
-__poll_t vivid_radio_rx_poll(struct file *file, struct poll_table_struct *wait)
-{
- return EPOLLIN | EPOLLRDNORM | v4l2_ctrl_poll(file, wait);
-}
-
-int vivid_radio_rx_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band)
-{
- if (band->tuner != 0)
- return -EINVAL;
-
- if (band->index >= TOT_BANDS)
- return -EINVAL;
-
- *band = vivid_radio_bands[band->index];
- return 0;
-}
-
-int vivid_radio_rx_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2_hw_freq_seek *a)
-{
- struct vivid_dev *dev = video_drvdata(file);
- unsigned low, high;
- unsigned freq;
- unsigned spacing;
- unsigned band;
-
- if (a->tuner)
- return -EINVAL;
- if (a->wrap_around && dev->radio_rx_hw_seek_mode == VIVID_HW_SEEK_BOUNDED)
- return -EINVAL;
-
- if (!a->wrap_around && dev->radio_rx_hw_seek_mode == VIVID_HW_SEEK_WRAP)
- return -EINVAL;
- if (!a->rangelow ^ !a->rangehigh)
- return -EINVAL;
-
- if (file->f_flags & O_NONBLOCK)
- return -EWOULDBLOCK;
-
- if (a->rangelow) {
- for (band = 0; band < TOT_BANDS; band++)
- if (a->rangelow >= vivid_radio_bands[band].rangelow &&
- a->rangehigh <= vivid_radio_bands[band].rangehigh)
- break;
- if (band == TOT_BANDS)
- return -EINVAL;
- if (!dev->radio_rx_hw_seek_prog_lim &&
- (a->rangelow != vivid_radio_bands[band].rangelow ||
- a->rangehigh != vivid_radio_bands[band].rangehigh))
- return -EINVAL;
- low = a->rangelow;
- high = a->rangehigh;
- } else {
- for (band = 0; band < TOT_BANDS; band++)
- if (dev->radio_rx_freq >= vivid_radio_bands[band].rangelow &&
- dev->radio_rx_freq <= vivid_radio_bands[band].rangehigh)
- break;
- if (band == TOT_BANDS)
- return -EINVAL;
- low = vivid_radio_bands[band].rangelow;
- high = vivid_radio_bands[band].rangehigh;
- }
- spacing = band == BAND_AM ? 1600 : 16000;
- freq = clamp(dev->radio_rx_freq, low, high);
-
- if (a->seek_upward) {
- freq = spacing * (freq / spacing) + spacing;
- if (freq > high) {
- if (!a->wrap_around)
- return -ENODATA;
- freq = spacing * (low / spacing) + spacing;
- if (freq >= dev->radio_rx_freq)
- return -ENODATA;
- }
- } else {
- freq = spacing * ((freq + spacing - 1) / spacing) - spacing;
- if (freq < low) {
- if (!a->wrap_around)
- return -ENODATA;
- freq = spacing * ((high + spacing - 1) / spacing) - spacing;
- if (freq <= dev->radio_rx_freq)
- return -ENODATA;
- }
- }
- return 0;
-}
-
-int vivid_radio_rx_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
-{
- struct vivid_dev *dev = video_drvdata(file);
- int delta = 800;
- int sig_qual;
-
- if (vt->index > 0)
- return -EINVAL;
-
- strscpy(vt->name, "AM/FM/SW Receiver", sizeof(vt->name));
- vt->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
- V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_RDS |
- (dev->radio_rx_rds_controls ?
- V4L2_TUNER_CAP_RDS_CONTROLS :
- V4L2_TUNER_CAP_RDS_BLOCK_IO) |
- (dev->radio_rx_hw_seek_prog_lim ?
- V4L2_TUNER_CAP_HWSEEK_PROG_LIM : 0);
- switch (dev->radio_rx_hw_seek_mode) {
- case VIVID_HW_SEEK_BOUNDED:
- vt->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED;
- break;
- case VIVID_HW_SEEK_WRAP:
- vt->capability |= V4L2_TUNER_CAP_HWSEEK_WRAP;
- break;
- case VIVID_HW_SEEK_BOTH:
- vt->capability |= V4L2_TUNER_CAP_HWSEEK_WRAP |
- V4L2_TUNER_CAP_HWSEEK_BOUNDED;
- break;
- }
- vt->rangelow = AM_FREQ_RANGE_LOW;
- vt->rangehigh = FM_FREQ_RANGE_HIGH;
- sig_qual = dev->radio_rx_sig_qual;
- vt->signal = abs(sig_qual) > delta ? 0 :
- 0xffff - ((unsigned)abs(sig_qual) * 0xffff) / delta;
- vt->afc = sig_qual > delta ? 0 : sig_qual;
- if (abs(sig_qual) > delta)
- vt->rxsubchans = 0;
- else if (dev->radio_rx_freq < FM_FREQ_RANGE_LOW || vt->signal < 0x8000)
- vt->rxsubchans = V4L2_TUNER_SUB_MONO;
- else if (dev->radio_rds_loop && !(dev->radio_tx_subchans & V4L2_TUNER_SUB_STEREO))
- vt->rxsubchans = V4L2_TUNER_SUB_MONO;
- else
- vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
- if (dev->radio_rx_rds_enabled &&
- (!dev->radio_rds_loop || (dev->radio_tx_subchans & V4L2_TUNER_SUB_RDS)) &&
- dev->radio_rx_freq >= FM_FREQ_RANGE_LOW && vt->signal >= 0xc000)
- vt->rxsubchans |= V4L2_TUNER_SUB_RDS;
- if (dev->radio_rx_rds_controls)
- vivid_radio_rds_init(dev);
- vt->audmode = dev->radio_rx_audmode;
- return 0;
-}
-
-int vivid_radio_rx_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (vt->index)
- return -EINVAL;
- dev->radio_rx_audmode = vt->audmode >= V4L2_TUNER_MODE_STEREO;
- return 0;
-}
diff --git a/drivers/media/platform/vivid/vivid-radio-rx.h b/drivers/media/platform/vivid/vivid-radio-rx.h
deleted file mode 100644
index c9c7849f6f99..000000000000
--- a/drivers/media/platform/vivid/vivid-radio-rx.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-radio-rx.h - radio receiver support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_RADIO_RX_H_
-#define _VIVID_RADIO_RX_H_
-
-ssize_t vivid_radio_rx_read(struct file *, char __user *, size_t, loff_t *);
-__poll_t vivid_radio_rx_poll(struct file *file, struct poll_table_struct *wait);
-
-int vivid_radio_rx_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band);
-int vivid_radio_rx_s_hw_freq_seek(struct file *file, void *fh, const struct v4l2_hw_freq_seek *a);
-int vivid_radio_rx_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt);
-int vivid_radio_rx_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-radio-tx.c b/drivers/media/platform/vivid/vivid-radio-tx.c
deleted file mode 100644
index 049d40b948bb..000000000000
--- a/drivers/media/platform/vivid/vivid-radio-tx.c
+++ /dev/null
@@ -1,128 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-radio-tx.c - radio transmitter support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched/signal.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-dv-timings.h>
-
-#include "vivid-core.h"
-#include "vivid-ctrls.h"
-#include "vivid-radio-common.h"
-#include "vivid-radio-tx.h"
-
-ssize_t vivid_radio_tx_write(struct file *file, const char __user *buf,
- size_t size, loff_t *offset)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_rds_data *data = dev->rds_gen.data;
- ktime_t timestamp;
- unsigned blk;
- int i;
-
- if (dev->radio_tx_rds_controls)
- return -EINVAL;
-
- if (size < sizeof(*data))
- return -EINVAL;
- size = sizeof(*data) * (size / sizeof(*data));
-
- if (mutex_lock_interruptible(&dev->mutex))
- return -ERESTARTSYS;
- if (dev->radio_tx_rds_owner &&
- file->private_data != dev->radio_tx_rds_owner) {
- mutex_unlock(&dev->mutex);
- return -EBUSY;
- }
- dev->radio_tx_rds_owner = file->private_data;
-
-retry:
- timestamp = ktime_sub(ktime_get(), dev->radio_rds_init_time);
- blk = ktime_divns(timestamp, VIVID_RDS_NSEC_PER_BLK);
- if (blk - VIVID_RDS_GEN_BLOCKS >= dev->radio_tx_rds_last_block)
- dev->radio_tx_rds_last_block = blk - VIVID_RDS_GEN_BLOCKS + 1;
-
- /*
- * No data is available if there hasn't been time to get new data,
- * or if the RDS receiver has been disabled, or if we use the data
- * from the RDS transmitter and that RDS transmitter has been disabled,
- * or if the signal quality is too weak.
- */
- if (blk == dev->radio_tx_rds_last_block ||
- !(dev->radio_tx_subchans & V4L2_TUNER_SUB_RDS)) {
- mutex_unlock(&dev->mutex);
- if (file->f_flags & O_NONBLOCK)
- return -EWOULDBLOCK;
- if (msleep_interruptible(20) && signal_pending(current))
- return -EINTR;
- if (mutex_lock_interruptible(&dev->mutex))
- return -ERESTARTSYS;
- goto retry;
- }
-
- for (i = 0; i < size && blk > dev->radio_tx_rds_last_block;
- dev->radio_tx_rds_last_block++) {
- unsigned data_blk = dev->radio_tx_rds_last_block % VIVID_RDS_GEN_BLOCKS;
- struct v4l2_rds_data rds;
-
- if (copy_from_user(&rds, buf + i, sizeof(rds))) {
- i = -EFAULT;
- break;
- }
- i += sizeof(rds);
- if (!dev->radio_rds_loop)
- continue;
- if ((rds.block & V4L2_RDS_BLOCK_MSK) == V4L2_RDS_BLOCK_INVALID ||
- (rds.block & V4L2_RDS_BLOCK_ERROR))
- continue;
- rds.block &= V4L2_RDS_BLOCK_MSK;
- data[data_blk] = rds;
- }
- mutex_unlock(&dev->mutex);
- return i;
-}
-
-__poll_t vivid_radio_tx_poll(struct file *file, struct poll_table_struct *wait)
-{
- return EPOLLOUT | EPOLLWRNORM | v4l2_ctrl_poll(file, wait);
-}
-
-int vidioc_g_modulator(struct file *file, void *fh, struct v4l2_modulator *a)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (a->index > 0)
- return -EINVAL;
-
- strscpy(a->name, "AM/FM/SW Transmitter", sizeof(a->name));
- a->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
- V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_RDS |
- (dev->radio_tx_rds_controls ?
- V4L2_TUNER_CAP_RDS_CONTROLS :
- V4L2_TUNER_CAP_RDS_BLOCK_IO);
- a->rangelow = AM_FREQ_RANGE_LOW;
- a->rangehigh = FM_FREQ_RANGE_HIGH;
- a->txsubchans = dev->radio_tx_subchans;
- return 0;
-}
-
-int vidioc_s_modulator(struct file *file, void *fh, const struct v4l2_modulator *a)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (a->index)
- return -EINVAL;
- if (a->txsubchans & ~0x13)
- return -EINVAL;
- dev->radio_tx_subchans = a->txsubchans;
- return 0;
-}
diff --git a/drivers/media/platform/vivid/vivid-radio-tx.h b/drivers/media/platform/vivid/vivid-radio-tx.h
deleted file mode 100644
index c2bf1e7e634a..000000000000
--- a/drivers/media/platform/vivid/vivid-radio-tx.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-radio-tx.h - radio transmitter support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_RADIO_TX_H_
-#define _VIVID_RADIO_TX_H_
-
-ssize_t vivid_radio_tx_write(struct file *, const char __user *, size_t, loff_t *);
-__poll_t vivid_radio_tx_poll(struct file *file, struct poll_table_struct *wait);
-
-int vidioc_g_modulator(struct file *file, void *fh, struct v4l2_modulator *a);
-int vidioc_s_modulator(struct file *file, void *fh, const struct v4l2_modulator *a);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-rds-gen.c b/drivers/media/platform/vivid/vivid-rds-gen.c
deleted file mode 100644
index b5b104ee64c9..000000000000
--- a/drivers/media/platform/vivid/vivid-rds-gen.c
+++ /dev/null
@@ -1,157 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-rds-gen.c - rds (radio data system) generator support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/kernel.h>
-#include <linux/ktime.h>
-#include <linux/string.h>
-#include <linux/videodev2.h>
-
-#include "vivid-rds-gen.h"
-
-static u8 vivid_get_di(const struct vivid_rds_gen *rds, unsigned grp)
-{
- switch (grp) {
- case 0:
- return (rds->dyn_pty << 2) | (grp & 3);
- case 1:
- return (rds->compressed << 2) | (grp & 3);
- case 2:
- return (rds->art_head << 2) | (grp & 3);
- case 3:
- return (rds->mono_stereo << 2) | (grp & 3);
- }
- return 0;
-}
-
-/*
- * This RDS generator creates 57 RDS groups (one group == four RDS blocks).
- * Groups 0-3, 22-25 and 44-47 (spaced 22 groups apart) are filled with a
- * standard 0B group containing the PI code and PS name.
- *
- * Groups 4-19 and 26-41 use group 2A for the radio text.
- *
- * Group 56 contains the time (group 4A).
- *
- * All remaining groups use a filler group 15B block that just repeats
- * the PI and PTY codes.
- */
-void vivid_rds_generate(struct vivid_rds_gen *rds)
-{
- struct v4l2_rds_data *data = rds->data;
- unsigned grp;
- unsigned idx;
- struct tm tm;
- unsigned date;
- unsigned time;
- int l;
-
- for (grp = 0; grp < VIVID_RDS_GEN_GROUPS; grp++, data += VIVID_RDS_GEN_BLKS_PER_GRP) {
- data[0].lsb = rds->picode & 0xff;
- data[0].msb = rds->picode >> 8;
- data[0].block = V4L2_RDS_BLOCK_A | (V4L2_RDS_BLOCK_A << 3);
- data[1].lsb = rds->pty << 5;
- data[1].msb = (rds->pty >> 3) | (rds->tp << 2);
- data[1].block = V4L2_RDS_BLOCK_B | (V4L2_RDS_BLOCK_B << 3);
- data[3].block = V4L2_RDS_BLOCK_D | (V4L2_RDS_BLOCK_D << 3);
-
- switch (grp) {
- case 0 ... 3:
- case 22 ... 25:
- case 44 ... 47: /* Group 0B */
- idx = (grp % 22) % 4;
- data[1].lsb |= (rds->ta << 4) | (rds->ms << 3);
- data[1].lsb |= vivid_get_di(rds, idx);
- data[1].msb |= 1 << 3;
- data[2].lsb = rds->picode & 0xff;
- data[2].msb = rds->picode >> 8;
- data[2].block = V4L2_RDS_BLOCK_C_ALT | (V4L2_RDS_BLOCK_C_ALT << 3);
- data[3].lsb = rds->psname[2 * idx + 1];
- data[3].msb = rds->psname[2 * idx];
- break;
- case 4 ... 19:
- case 26 ... 41: /* Group 2A */
- idx = ((grp - 4) % 22) % 16;
- data[1].lsb |= idx;
- data[1].msb |= 4 << 3;
- data[2].msb = rds->radiotext[4 * idx];
- data[2].lsb = rds->radiotext[4 * idx + 1];
- data[2].block = V4L2_RDS_BLOCK_C | (V4L2_RDS_BLOCK_C << 3);
- data[3].msb = rds->radiotext[4 * idx + 2];
- data[3].lsb = rds->radiotext[4 * idx + 3];
- break;
- case 56:
- /*
- * Group 4A
- *
- * Uses the algorithm from Annex G of the RDS standard
- * EN 50067:1998 to convert a UTC date to an RDS Modified
- * Julian Day.
- */
- time64_to_tm(ktime_get_real_seconds(), 0, &tm);
- l = tm.tm_mon <= 1;
- date = 14956 + tm.tm_mday + ((tm.tm_year - l) * 1461) / 4 +
- ((tm.tm_mon + 2 + l * 12) * 306001) / 10000;
- time = (tm.tm_hour << 12) |
- (tm.tm_min << 6) |
- (sys_tz.tz_minuteswest >= 0 ? 0x20 : 0) |
- (abs(sys_tz.tz_minuteswest) / 30);
- data[1].lsb &= ~3;
- data[1].lsb |= date >> 15;
- data[1].msb |= 8 << 3;
- data[2].lsb = (date << 1) & 0xfe;
- data[2].lsb |= (time >> 16) & 1;
- data[2].msb = (date >> 7) & 0xff;
- data[2].block = V4L2_RDS_BLOCK_C | (V4L2_RDS_BLOCK_C << 3);
- data[3].lsb = time & 0xff;
- data[3].msb = (time >> 8) & 0xff;
- break;
- default: /* Group 15B */
- data[1].lsb |= (rds->ta << 4) | (rds->ms << 3);
- data[1].lsb |= vivid_get_di(rds, grp % 22);
- data[1].msb |= 0x1f << 3;
- data[2].lsb = rds->picode & 0xff;
- data[2].msb = rds->picode >> 8;
- data[2].block = V4L2_RDS_BLOCK_C_ALT | (V4L2_RDS_BLOCK_C_ALT << 3);
- data[3].lsb = rds->pty << 5;
- data[3].lsb |= (rds->ta << 4) | (rds->ms << 3);
- data[3].lsb |= vivid_get_di(rds, grp % 22);
- data[3].msb |= rds->pty >> 3;
- data[3].msb |= 0x1f << 3;
- break;
- }
- }
-}
-
-void vivid_rds_gen_fill(struct vivid_rds_gen *rds, unsigned freq,
- bool alt)
-{
- /* Alternate PTY between Info and Weather */
- if (rds->use_rbds) {
- rds->picode = 0x2e75; /* 'KLNX' call sign */
- rds->pty = alt ? 29 : 2;
- } else {
- rds->picode = 0x8088;
- rds->pty = alt ? 16 : 3;
- }
- rds->mono_stereo = true;
- rds->art_head = false;
- rds->compressed = false;
- rds->dyn_pty = false;
- rds->tp = true;
- rds->ta = alt;
- rds->ms = true;
- snprintf(rds->psname, sizeof(rds->psname), "%6d.%1d",
- freq / 16, ((freq & 0xf) * 10) / 16);
- if (alt)
- strscpy(rds->radiotext,
- " The Radio Data System can switch between different Radio Texts ",
- sizeof(rds->radiotext));
- else
- strscpy(rds->radiotext,
- "An example of Radio Text as transmitted by the Radio Data System",
- sizeof(rds->radiotext));
-}
diff --git a/drivers/media/platform/vivid/vivid-rds-gen.h b/drivers/media/platform/vivid/vivid-rds-gen.h
deleted file mode 100644
index 35ac5742302b..000000000000
--- a/drivers/media/platform/vivid/vivid-rds-gen.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-rds-gen.h - rds (radio data system) generator support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_RDS_GEN_H_
-#define _VIVID_RDS_GEN_H_
-
-/*
- * It takes almost exactly 5 seconds to transmit 57 RDS groups.
- * Each group has 4 blocks and each block has a payload of 16 bits + a
- * block identification. The driver will generate the contents of these
- * 57 groups only when necessary and it will just be played continuously.
- */
-#define VIVID_RDS_GEN_GROUPS 57
-#define VIVID_RDS_GEN_BLKS_PER_GRP 4
-#define VIVID_RDS_GEN_BLOCKS (VIVID_RDS_GEN_BLKS_PER_GRP * VIVID_RDS_GEN_GROUPS)
-#define VIVID_RDS_NSEC_PER_BLK (u32)(5ull * NSEC_PER_SEC / VIVID_RDS_GEN_BLOCKS)
-
-struct vivid_rds_gen {
- struct v4l2_rds_data data[VIVID_RDS_GEN_BLOCKS];
- bool use_rbds;
- u16 picode;
- u8 pty;
- bool mono_stereo;
- bool art_head;
- bool compressed;
- bool dyn_pty;
- bool ta;
- bool tp;
- bool ms;
- char psname[8 + 1];
- char radiotext[64 + 1];
-};
-
-void vivid_rds_gen_fill(struct vivid_rds_gen *rds, unsigned freq,
- bool use_alternate);
-void vivid_rds_generate(struct vivid_rds_gen *rds);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
deleted file mode 100644
index 2b7522e16efc..000000000000
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ /dev/null
@@ -1,570 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-sdr-cap.c - software defined radio support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/math64.h>
-#include <linux/videodev2.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-dv-timings.h>
-#include <linux/fixp-arith.h>
-
-#include "vivid-core.h"
-#include "vivid-ctrls.h"
-#include "vivid-sdr-cap.h"
-
-/* stream formats */
-struct vivid_format {
- u32 pixelformat;
- u32 buffersize;
-};
-
-/* format descriptions for capture and preview */
-static const struct vivid_format formats[] = {
- {
- .pixelformat = V4L2_SDR_FMT_CU8,
- .buffersize = SDR_CAP_SAMPLES_PER_BUF * 2,
- }, {
- .pixelformat = V4L2_SDR_FMT_CS8,
- .buffersize = SDR_CAP_SAMPLES_PER_BUF * 2,
- },
-};
-
-static const struct v4l2_frequency_band bands_adc[] = {
- {
- .tuner = 0,
- .type = V4L2_TUNER_ADC,
- .index = 0,
- .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
- .rangelow = 300000,
- .rangehigh = 300000,
- },
- {
- .tuner = 0,
- .type = V4L2_TUNER_ADC,
- .index = 1,
- .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
- .rangelow = 900001,
- .rangehigh = 2800000,
- },
- {
- .tuner = 0,
- .type = V4L2_TUNER_ADC,
- .index = 2,
- .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
- .rangelow = 3200000,
- .rangehigh = 3200000,
- },
-};
-
-/* ADC band midpoints */
-#define BAND_ADC_0 ((bands_adc[0].rangehigh + bands_adc[1].rangelow) / 2)
-#define BAND_ADC_1 ((bands_adc[1].rangehigh + bands_adc[2].rangelow) / 2)
-
-static const struct v4l2_frequency_band bands_fm[] = {
- {
- .tuner = 1,
- .type = V4L2_TUNER_RF,
- .index = 0,
- .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
- .rangelow = 50000000,
- .rangehigh = 2000000000,
- },
-};
-
-static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev)
-{
- struct vivid_buffer *sdr_cap_buf = NULL;
-
- dprintk(dev, 1, "SDR Capture Thread Tick\n");
-
- /* Drop a certain percentage of buffers. */
- if (dev->perc_dropped_buffers &&
- prandom_u32_max(100) < dev->perc_dropped_buffers)
- return;
-
- spin_lock(&dev->slock);
- if (!list_empty(&dev->sdr_cap_active)) {
- sdr_cap_buf = list_entry(dev->sdr_cap_active.next,
- struct vivid_buffer, list);
- list_del(&sdr_cap_buf->list);
- }
- spin_unlock(&dev->slock);
-
- if (sdr_cap_buf) {
- sdr_cap_buf->vb.sequence = dev->sdr_cap_seq_count;
- v4l2_ctrl_request_setup(sdr_cap_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_sdr_cap);
- v4l2_ctrl_request_complete(sdr_cap_buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_sdr_cap);
- vivid_sdr_cap_process(dev, sdr_cap_buf);
- sdr_cap_buf->vb.vb2_buf.timestamp =
- ktime_get_ns() + dev->time_wrap_offset;
- vb2_buffer_done(&sdr_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
- VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
- dev->dqbuf_error = false;
- }
-}
-
-static int vivid_thread_sdr_cap(void *data)
-{
- struct vivid_dev *dev = data;
- u64 samples_since_start;
- u64 buffers_since_start;
- u64 next_jiffies_since_start;
- unsigned long jiffies_since_start;
- unsigned long cur_jiffies;
- unsigned wait_jiffies;
-
- dprintk(dev, 1, "SDR Capture Thread Start\n");
-
- set_freezable();
-
- /* Resets frame counters */
- dev->sdr_cap_seq_offset = 0;
- if (dev->seq_wrap)
- dev->sdr_cap_seq_offset = 0xffffff80U;
- dev->jiffies_sdr_cap = jiffies;
- dev->sdr_cap_seq_resync = false;
-
- for (;;) {
- try_to_freeze();
- if (kthread_should_stop())
- break;
-
- if (!mutex_trylock(&dev->mutex)) {
- schedule_timeout_uninterruptible(1);
- continue;
- }
-
- cur_jiffies = jiffies;
- if (dev->sdr_cap_seq_resync) {
- dev->jiffies_sdr_cap = cur_jiffies;
- dev->sdr_cap_seq_offset = dev->sdr_cap_seq_count + 1;
- dev->sdr_cap_seq_count = 0;
- dev->sdr_cap_seq_resync = false;
- }
- /* Calculate the number of jiffies since we started streaming */
- jiffies_since_start = cur_jiffies - dev->jiffies_sdr_cap;
- /* Get the number of buffers streamed since the start */
- buffers_since_start =
- (u64)jiffies_since_start * dev->sdr_adc_freq +
- (HZ * SDR_CAP_SAMPLES_PER_BUF) / 2;
- do_div(buffers_since_start, HZ * SDR_CAP_SAMPLES_PER_BUF);
-
- /*
- * After more than 0xf0000000 (rounded down to a multiple of
- * 'jiffies-per-day' to ease jiffies_to_msecs calculation)
- * jiffies have passed since we started streaming reset the
- * counters and keep track of the sequence offset.
- */
- if (jiffies_since_start > JIFFIES_RESYNC) {
- dev->jiffies_sdr_cap = cur_jiffies;
- dev->sdr_cap_seq_offset = buffers_since_start;
- buffers_since_start = 0;
- }
- dev->sdr_cap_seq_count =
- buffers_since_start + dev->sdr_cap_seq_offset;
-
- vivid_thread_sdr_cap_tick(dev);
- mutex_unlock(&dev->mutex);
-
- /*
- * Calculate the number of samples streamed since we started,
- * not including the current buffer.
- */
- samples_since_start = buffers_since_start * SDR_CAP_SAMPLES_PER_BUF;
-
- /* And the number of jiffies since we started */
- jiffies_since_start = jiffies - dev->jiffies_sdr_cap;
-
- /* Increase by the number of samples in one buffer */
- samples_since_start += SDR_CAP_SAMPLES_PER_BUF;
- /*
- * Calculate when that next buffer is supposed to start
- * in jiffies since we started streaming.
- */
- next_jiffies_since_start = samples_since_start * HZ +
- dev->sdr_adc_freq / 2;
- do_div(next_jiffies_since_start, dev->sdr_adc_freq);
- /* If it is in the past, then just schedule asap */
- if (next_jiffies_since_start < jiffies_since_start)
- next_jiffies_since_start = jiffies_since_start;
-
- wait_jiffies = next_jiffies_since_start - jiffies_since_start;
- schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
- }
- dprintk(dev, 1, "SDR Capture Thread End\n");
- return 0;
-}
-
-static int sdr_cap_queue_setup(struct vb2_queue *vq,
- unsigned *nbuffers, unsigned *nplanes,
- unsigned sizes[], struct device *alloc_devs[])
-{
- /* 2 = max 16-bit sample returned */
- sizes[0] = SDR_CAP_SAMPLES_PER_BUF * 2;
- *nplanes = 1;
- return 0;
-}
-
-static int sdr_cap_buf_prepare(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- unsigned size = SDR_CAP_SAMPLES_PER_BUF * 2;
-
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->buf_prepare_error) {
- /*
- * Error injection: test what happens if buf_prepare() returns
- * an error.
- */
- dev->buf_prepare_error = false;
- return -EINVAL;
- }
- if (vb2_plane_size(vb, 0) < size) {
- dprintk(dev, 1, "%s data will not fit into plane (%lu < %u)\n",
- __func__, vb2_plane_size(vb, 0), size);
- return -EINVAL;
- }
- vb2_set_plane_payload(vb, 0, size);
-
- return 0;
-}
-
-static void sdr_cap_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- spin_lock(&dev->slock);
- list_add_tail(&buf->list, &dev->sdr_cap_active);
- spin_unlock(&dev->slock);
-}
-
-static int sdr_cap_start_streaming(struct vb2_queue *vq, unsigned count)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- int err = 0;
-
- dprintk(dev, 1, "%s\n", __func__);
- dev->sdr_cap_seq_count = 0;
- if (dev->start_streaming_error) {
- dev->start_streaming_error = false;
- err = -EINVAL;
- } else if (dev->kthread_sdr_cap == NULL) {
- dev->kthread_sdr_cap = kthread_run(vivid_thread_sdr_cap, dev,
- "%s-sdr-cap", dev->v4l2_dev.name);
-
- if (IS_ERR(dev->kthread_sdr_cap)) {
- v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
- err = PTR_ERR(dev->kthread_sdr_cap);
- dev->kthread_sdr_cap = NULL;
- }
- }
- if (err) {
- struct vivid_buffer *buf, *tmp;
-
- list_for_each_entry_safe(buf, tmp, &dev->sdr_cap_active, list) {
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf,
- VB2_BUF_STATE_QUEUED);
- }
- }
- return err;
-}
-
-/* abort streaming and wait for last buffer */
-static void sdr_cap_stop_streaming(struct vb2_queue *vq)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
-
- if (dev->kthread_sdr_cap == NULL)
- return;
-
- while (!list_empty(&dev->sdr_cap_active)) {
- struct vivid_buffer *buf;
-
- buf = list_entry(dev->sdr_cap_active.next,
- struct vivid_buffer, list);
- list_del(&buf->list);
- v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
- &dev->ctrl_hdl_sdr_cap);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- }
-
- /* shutdown control thread */
- kthread_stop(dev->kthread_sdr_cap);
- dev->kthread_sdr_cap = NULL;
-}
-
-static void sdr_cap_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_sdr_cap);
-}
-
-const struct vb2_ops vivid_sdr_cap_qops = {
- .queue_setup = sdr_cap_queue_setup,
- .buf_prepare = sdr_cap_buf_prepare,
- .buf_queue = sdr_cap_buf_queue,
- .start_streaming = sdr_cap_start_streaming,
- .stop_streaming = sdr_cap_stop_streaming,
- .buf_request_complete = sdr_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-int vivid_sdr_enum_freq_bands(struct file *file, void *fh,
- struct v4l2_frequency_band *band)
-{
- switch (band->tuner) {
- case 0:
- if (band->index >= ARRAY_SIZE(bands_adc))
- return -EINVAL;
- *band = bands_adc[band->index];
- return 0;
- case 1:
- if (band->index >= ARRAY_SIZE(bands_fm))
- return -EINVAL;
- *band = bands_fm[band->index];
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-int vivid_sdr_g_frequency(struct file *file, void *fh,
- struct v4l2_frequency *vf)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- switch (vf->tuner) {
- case 0:
- vf->frequency = dev->sdr_adc_freq;
- vf->type = V4L2_TUNER_ADC;
- return 0;
- case 1:
- vf->frequency = dev->sdr_fm_freq;
- vf->type = V4L2_TUNER_RF;
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-int vivid_sdr_s_frequency(struct file *file, void *fh,
- const struct v4l2_frequency *vf)
-{
- struct vivid_dev *dev = video_drvdata(file);
- unsigned freq = vf->frequency;
- unsigned band;
-
- switch (vf->tuner) {
- case 0:
- if (vf->type != V4L2_TUNER_ADC)
- return -EINVAL;
- if (freq < BAND_ADC_0)
- band = 0;
- else if (freq < BAND_ADC_1)
- band = 1;
- else
- band = 2;
-
- freq = clamp_t(unsigned, freq,
- bands_adc[band].rangelow,
- bands_adc[band].rangehigh);
-
- if (vb2_is_streaming(&dev->vb_sdr_cap_q) &&
- freq != dev->sdr_adc_freq) {
- /* resync the thread's timings */
- dev->sdr_cap_seq_resync = true;
- }
- dev->sdr_adc_freq = freq;
- return 0;
- case 1:
- if (vf->type != V4L2_TUNER_RF)
- return -EINVAL;
- dev->sdr_fm_freq = clamp_t(unsigned, freq,
- bands_fm[0].rangelow,
- bands_fm[0].rangehigh);
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
-{
- switch (vt->index) {
- case 0:
- strscpy(vt->name, "ADC", sizeof(vt->name));
- vt->type = V4L2_TUNER_ADC;
- vt->capability =
- V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
- vt->rangelow = bands_adc[0].rangelow;
- vt->rangehigh = bands_adc[2].rangehigh;
- return 0;
- case 1:
- strscpy(vt->name, "RF", sizeof(vt->name));
- vt->type = V4L2_TUNER_RF;
- vt->capability =
- V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
- vt->rangelow = bands_fm[0].rangelow;
- vt->rangehigh = bands_fm[0].rangehigh;
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-int vivid_sdr_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt)
-{
- if (vt->index > 1)
- return -EINVAL;
- return 0;
-}
-
-int vidioc_enum_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
-{
- if (f->index >= ARRAY_SIZE(formats))
- return -EINVAL;
- f->pixelformat = formats[f->index].pixelformat;
- return 0;
-}
-
-int vidioc_g_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- f->fmt.sdr.pixelformat = dev->sdr_pixelformat;
- f->fmt.sdr.buffersize = dev->sdr_buffersize;
- memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- return 0;
-}
-
-int vidioc_s_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct vb2_queue *q = &dev->vb_sdr_cap_q;
- int i;
-
- if (vb2_is_busy(q))
- return -EBUSY;
-
- memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < ARRAY_SIZE(formats); i++) {
- if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
- dev->sdr_pixelformat = formats[i].pixelformat;
- dev->sdr_buffersize = formats[i].buffersize;
- f->fmt.sdr.buffersize = formats[i].buffersize;
- return 0;
- }
- }
- dev->sdr_pixelformat = formats[0].pixelformat;
- dev->sdr_buffersize = formats[0].buffersize;
- f->fmt.sdr.pixelformat = formats[0].pixelformat;
- f->fmt.sdr.buffersize = formats[0].buffersize;
- return 0;
-}
-
-int vidioc_try_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f)
-{
- int i;
-
- memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < ARRAY_SIZE(formats); i++) {
- if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
- f->fmt.sdr.buffersize = formats[i].buffersize;
- return 0;
- }
- }
- f->fmt.sdr.pixelformat = formats[0].pixelformat;
- f->fmt.sdr.buffersize = formats[0].buffersize;
- return 0;
-}
-
-#define FIXP_N (15)
-#define FIXP_FRAC (1 << FIXP_N)
-#define FIXP_2PI ((int)(2 * 3.141592653589 * FIXP_FRAC))
-#define M_100000PI (3.14159 * 100000)
-
-void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
-{
- u8 *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
- unsigned long i;
- unsigned long plane_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
- s64 s64tmp;
- s32 src_phase_step;
- s32 mod_phase_step;
- s32 fixp_i;
- s32 fixp_q;
-
- /* calculate phase step */
- #define BEEP_FREQ 1000 /* 1kHz beep */
- src_phase_step = DIV_ROUND_CLOSEST(FIXP_2PI * BEEP_FREQ,
- dev->sdr_adc_freq);
-
- for (i = 0; i < plane_size; i += 2) {
- mod_phase_step = fixp_cos32_rad(dev->sdr_fixp_src_phase,
- FIXP_2PI) >> (31 - FIXP_N);
-
- dev->sdr_fixp_src_phase += src_phase_step;
- s64tmp = (s64) mod_phase_step * dev->sdr_fm_deviation;
- dev->sdr_fixp_mod_phase += div_s64(s64tmp, M_100000PI);
-
- /*
- * Transfer phase angle to [0, 2xPI] in order to avoid variable
- * overflow and make it suitable for cosine implementation
- * used, which does not support negative angles.
- */
- dev->sdr_fixp_src_phase %= FIXP_2PI;
- dev->sdr_fixp_mod_phase %= FIXP_2PI;
-
- if (dev->sdr_fixp_mod_phase < 0)
- dev->sdr_fixp_mod_phase += FIXP_2PI;
-
- fixp_i = fixp_cos32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI);
- fixp_q = fixp_sin32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI);
-
- /* Normalize fraction values represented with 32 bit precision
- * to fixed point representation with FIXP_N bits */
- fixp_i >>= (31 - FIXP_N);
- fixp_q >>= (31 - FIXP_N);
-
- switch (dev->sdr_pixelformat) {
- case V4L2_SDR_FMT_CU8:
- /* convert 'fixp float' to u8 [0, +255] */
- /* u8 = X * 127.5 + 127.5; X is float [-1.0, +1.0] */
- fixp_i = fixp_i * 1275 + FIXP_FRAC * 1275;
- fixp_q = fixp_q * 1275 + FIXP_FRAC * 1275;
- *vbuf++ = DIV_ROUND_CLOSEST(fixp_i, FIXP_FRAC * 10);
- *vbuf++ = DIV_ROUND_CLOSEST(fixp_q, FIXP_FRAC * 10);
- break;
- case V4L2_SDR_FMT_CS8:
- /* convert 'fixp float' to s8 [-128, +127] */
- /* s8 = X * 127.5 - 0.5; X is float [-1.0, +1.0] */
- fixp_i = fixp_i * 1275 - FIXP_FRAC * 5;
- fixp_q = fixp_q * 1275 - FIXP_FRAC * 5;
- *vbuf++ = DIV_ROUND_CLOSEST(fixp_i, FIXP_FRAC * 10);
- *vbuf++ = DIV_ROUND_CLOSEST(fixp_q, FIXP_FRAC * 10);
- break;
- default:
- break;
- }
- }
-}
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.h b/drivers/media/platform/vivid/vivid-sdr-cap.h
deleted file mode 100644
index 813c9248e5a7..000000000000
--- a/drivers/media/platform/vivid/vivid-sdr-cap.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-sdr-cap.h - software defined radio support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_SDR_CAP_H_
-#define _VIVID_SDR_CAP_H_
-
-int vivid_sdr_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band);
-int vivid_sdr_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
-int vivid_sdr_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf);
-int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt);
-int vivid_sdr_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt);
-int vidioc_enum_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f);
-int vidioc_g_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f);
-int vidioc_s_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f);
-int vidioc_try_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f);
-void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf);
-
-extern const struct vb2_ops vivid_sdr_cap_qops;
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-touch-cap.c b/drivers/media/platform/vivid/vivid-touch-cap.c
deleted file mode 100644
index ebb00b128030..000000000000
--- a/drivers/media/platform/vivid/vivid-touch-cap.c
+++ /dev/null
@@ -1,341 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-touch-cap.c - touch support functions.
- */
-
-#include "vivid-core.h"
-#include "vivid-kthread-touch.h"
-#include "vivid-vid-common.h"
-#include "vivid-touch-cap.h"
-
-static int touch_cap_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
- unsigned int *nplanes, unsigned int sizes[],
- struct device *alloc_devs[])
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- struct v4l2_pix_format *f = &dev->tch_format;
- unsigned int size = f->sizeimage;
-
- if (*nplanes) {
- if (sizes[0] < size)
- return -EINVAL;
- } else {
- sizes[0] = size;
- }
-
- if (vq->num_buffers + *nbuffers < 2)
- *nbuffers = 2 - vq->num_buffers;
-
- *nplanes = 1;
- return 0;
-}
-
-static int touch_cap_buf_prepare(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct v4l2_pix_format *f = &dev->tch_format;
- unsigned int size = f->sizeimage;
-
- if (dev->buf_prepare_error) {
- /*
- * Error injection: test what happens if buf_prepare() returns
- * an error.
- */
- dev->buf_prepare_error = false;
- return -EINVAL;
- }
- if (vb2_plane_size(vb, 0) < size) {
- dprintk(dev, 1, "%s data will not fit into plane (%lu < %u)\n",
- __func__, vb2_plane_size(vb, 0), size);
- return -EINVAL;
- }
- vb2_set_plane_payload(vb, 0, size);
-
- return 0;
-}
-
-static void touch_cap_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
-
- vbuf->field = V4L2_FIELD_NONE;
- spin_lock(&dev->slock);
- list_add_tail(&buf->list, &dev->touch_cap_active);
- spin_unlock(&dev->slock);
-}
-
-static int touch_cap_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- int err;
-
- dev->touch_cap_seq_count = 0;
- if (dev->start_streaming_error) {
- dev->start_streaming_error = false;
- err = -EINVAL;
- } else {
- err = vivid_start_generating_touch_cap(dev);
- }
- if (err) {
- struct vivid_buffer *buf, *tmp;
-
- list_for_each_entry_safe(buf, tmp,
- &dev->touch_cap_active, list) {
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf,
- VB2_BUF_STATE_QUEUED);
- }
- }
- return err;
-}
-
-/* abort streaming and wait for last buffer */
-static void touch_cap_stop_streaming(struct vb2_queue *vq)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
-
- vivid_stop_generating_touch_cap(dev);
-}
-
-static void touch_cap_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_touch_cap);
-}
-
-const struct vb2_ops vivid_touch_cap_qops = {
- .queue_setup = touch_cap_queue_setup,
- .buf_prepare = touch_cap_buf_prepare,
- .buf_queue = touch_cap_buf_queue,
- .start_streaming = touch_cap_start_streaming,
- .stop_streaming = touch_cap_stop_streaming,
- .buf_request_complete = touch_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-int vivid_enum_fmt_tch(struct file *file, void *priv, struct v4l2_fmtdesc *f)
-{
- if (f->index)
- return -EINVAL;
-
- f->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
- return 0;
-}
-
-int vivid_g_fmt_tch(struct file *file, void *priv, struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (dev->multiplanar)
- return -ENOTTY;
- f->fmt.pix = dev->tch_format;
- return 0;
-}
-
-int vivid_g_fmt_tch_mplane(struct file *file, void *priv, struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_format sp_fmt;
-
- if (!dev->multiplanar)
- return -ENOTTY;
- sp_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- sp_fmt.fmt.pix = dev->tch_format;
- fmt_sp2mp(&sp_fmt, f);
- return 0;
-}
-
-int vivid_g_parm_tch(struct file *file, void *priv,
- struct v4l2_streamparm *parm)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (parm->type != (dev->multiplanar ?
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
- V4L2_BUF_TYPE_VIDEO_CAPTURE))
- return -EINVAL;
-
- parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- parm->parm.capture.timeperframe = dev->timeperframe_tch_cap;
- parm->parm.capture.readbuffers = 1;
- return 0;
-}
-
-int vivid_enum_input_tch(struct file *file, void *priv, struct v4l2_input *inp)
-{
- if (inp->index)
- return -EINVAL;
-
- inp->type = V4L2_INPUT_TYPE_TOUCH;
- strscpy(inp->name, "Vivid Touch", sizeof(inp->name));
- inp->capabilities = 0;
- return 0;
-}
-
-int vivid_g_input_tch(struct file *file, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-int vivid_set_touch(struct vivid_dev *dev, unsigned int i)
-{
- struct v4l2_pix_format *f = &dev->tch_format;
-
- if (i)
- return -EINVAL;
-
- f->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
- f->width = VIVID_TCH_WIDTH;
- f->height = VIVID_TCH_HEIGHT;
- f->field = V4L2_FIELD_NONE;
- f->colorspace = V4L2_COLORSPACE_RAW;
- f->bytesperline = f->width * sizeof(s16);
- f->sizeimage = f->width * f->height * sizeof(s16);
- return 0;
-}
-
-int vivid_s_input_tch(struct file *file, void *priv, unsigned int i)
-{
- return vivid_set_touch(video_drvdata(file), i);
-}
-
-static void vivid_fill_buff_noise(__s16 *tch_buf, int size)
-{
- int i;
-
- /* Fill 10% of the values within range -3 and 3, zero the others */
- for (i = 0; i < size; i++) {
- unsigned int rand = get_random_int();
-
- if (rand % 10)
- tch_buf[i] = 0;
- else
- tch_buf[i] = (rand / 10) % 7 - 3;
- }
-}
-
-static inline int get_random_pressure(void)
-{
- return get_random_int() % VIVID_PRESSURE_LIMIT;
-}
-
-static void vivid_tch_buf_set(struct v4l2_pix_format *f,
- __s16 *tch_buf,
- int index)
-{
- unsigned int x = index % f->width;
- unsigned int y = index / f->width;
- unsigned int offset = VIVID_MIN_PRESSURE;
-
- tch_buf[index] = offset + get_random_pressure();
- offset /= 2;
- if (x)
- tch_buf[index - 1] = offset + get_random_pressure();
- if (x < f->width - 1)
- tch_buf[index + 1] = offset + get_random_pressure();
- if (y)
- tch_buf[index - f->width] = offset + get_random_pressure();
- if (y < f->height - 1)
- tch_buf[index + f->width] = offset + get_random_pressure();
- offset /= 2;
- if (x && y)
- tch_buf[index - 1 - f->width] = offset + get_random_pressure();
- if (x < f->width - 1 && y)
- tch_buf[index + 1 - f->width] = offset + get_random_pressure();
- if (x && y < f->height - 1)
- tch_buf[index - 1 + f->width] = offset + get_random_pressure();
- if (x < f->width - 1 && y < f->height - 1)
- tch_buf[index + 1 + f->width] = offset + get_random_pressure();
-}
-
-void vivid_fillbuff_tch(struct vivid_dev *dev, struct vivid_buffer *buf)
-{
- struct v4l2_pix_format *f = &dev->tch_format;
- int size = f->width * f->height;
- int x, y, xstart, ystart, offset_x, offset_y;
- unsigned int test_pattern, test_pat_idx, rand;
-
- __s16 *tch_buf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
-
- buf->vb.sequence = dev->touch_cap_seq_count;
- test_pattern = (buf->vb.sequence / TCH_SEQ_COUNT) % TEST_CASE_MAX;
- test_pat_idx = buf->vb.sequence % TCH_SEQ_COUNT;
-
- vivid_fill_buff_noise(tch_buf, size);
-
- if (test_pat_idx >= TCH_PATTERN_COUNT)
- return;
-
- if (test_pat_idx == 0)
- dev->tch_pat_random = get_random_int();
- rand = dev->tch_pat_random;
-
- switch (test_pattern) {
- case SINGLE_TAP:
- if (test_pat_idx == 2)
- vivid_tch_buf_set(f, tch_buf, rand % size);
- break;
- case DOUBLE_TAP:
- if (test_pat_idx == 2 || test_pat_idx == 4)
- vivid_tch_buf_set(f, tch_buf, rand % size);
- break;
- case TRIPLE_TAP:
- if (test_pat_idx == 2 || test_pat_idx == 4 || test_pat_idx == 6)
- vivid_tch_buf_set(f, tch_buf, rand % size);
- break;
- case MOVE_LEFT_TO_RIGHT:
- vivid_tch_buf_set(f, tch_buf,
- (rand % f->height) * f->width +
- test_pat_idx *
- (f->width / TCH_PATTERN_COUNT));
- break;
- case ZOOM_IN:
- x = f->width / 2;
- y = f->height / 2;
- offset_x = ((TCH_PATTERN_COUNT - 1 - test_pat_idx) * x) /
- TCH_PATTERN_COUNT;
- offset_y = ((TCH_PATTERN_COUNT - 1 - test_pat_idx) * y) /
- TCH_PATTERN_COUNT;
- vivid_tch_buf_set(f, tch_buf,
- (x - offset_x) + f->width * (y - offset_y));
- vivid_tch_buf_set(f, tch_buf,
- (x + offset_x) + f->width * (y + offset_y));
- break;
- case ZOOM_OUT:
- x = f->width / 2;
- y = f->height / 2;
- offset_x = (test_pat_idx * x) / TCH_PATTERN_COUNT;
- offset_y = (test_pat_idx * y) / TCH_PATTERN_COUNT;
- vivid_tch_buf_set(f, tch_buf,
- (x - offset_x) + f->width * (y - offset_y));
- vivid_tch_buf_set(f, tch_buf,
- (x + offset_x) + f->width * (y + offset_y));
- break;
- case PALM_PRESS:
- for (x = 0; x < f->width; x++)
- for (y = f->height / 2; y < f->height; y++)
- tch_buf[x + f->width * y] = VIVID_MIN_PRESSURE +
- get_random_pressure();
- break;
- case MULTIPLE_PRESS:
- /* 16 pressure points */
- for (y = 0; y < 4; y++) {
- for (x = 0; x < 4; x++) {
- ystart = (y * f->height) / 4 + f->height / 8;
- xstart = (x * f->width) / 4 + f->width / 8;
- vivid_tch_buf_set(f, tch_buf,
- ystart * f->width + xstart);
- }
- }
- break;
- }
-#ifdef __BIG_ENDIAN__
- for (x = 0; x < size; x++)
- tch_buf[x] = (__force s16)__cpu_to_le16((u16)tch_buf[x]);
-#endif
-}
diff --git a/drivers/media/platform/vivid/vivid-touch-cap.h b/drivers/media/platform/vivid/vivid-touch-cap.h
deleted file mode 100644
index 07e514046ae8..000000000000
--- a/drivers/media/platform/vivid/vivid-touch-cap.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-touch-cap.h - touch support functions.
- */
-#ifndef _VIVID_TOUCH_CAP_H_
-#define _VIVID_TOUCH_CAP_H_
-
-#define VIVID_TCH_HEIGHT 12
-#define VIVID_TCH_WIDTH 21
-#define VIVID_MIN_PRESSURE 180
-#define VIVID_PRESSURE_LIMIT 40
-#define TCH_SEQ_COUNT 16
-#define TCH_PATTERN_COUNT 12
-
-enum vivid_tch_test {
- SINGLE_TAP,
- DOUBLE_TAP,
- TRIPLE_TAP,
- MOVE_LEFT_TO_RIGHT,
- ZOOM_IN,
- ZOOM_OUT,
- PALM_PRESS,
- MULTIPLE_PRESS,
- TEST_CASE_MAX
-};
-
-extern const struct vb2_ops vivid_touch_cap_qops;
-
-int vivid_enum_fmt_tch(struct file *file, void *priv, struct v4l2_fmtdesc *f);
-int vivid_g_fmt_tch(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_g_fmt_tch_mplane(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_enum_input_tch(struct file *file, void *priv, struct v4l2_input *inp);
-int vivid_g_input_tch(struct file *file, void *priv, unsigned int *i);
-int vivid_s_input_tch(struct file *file, void *priv, unsigned int i);
-void vivid_fillbuff_tch(struct vivid_dev *dev, struct vivid_buffer *buf);
-int vivid_set_touch(struct vivid_dev *dev, unsigned int i);
-int vivid_g_parm_tch(struct file *file, void *priv,
- struct v4l2_streamparm *parm);
-#endif
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
deleted file mode 100644
index 1a9348eea781..000000000000
--- a/drivers/media/platform/vivid/vivid-vbi-cap.c
+++ /dev/null
@@ -1,365 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-vbi-cap.c - vbi capture support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-
-#include "vivid-core.h"
-#include "vivid-kthread-cap.h"
-#include "vivid-vbi-cap.h"
-#include "vivid-vbi-gen.h"
-
-static void vivid_sliced_vbi_cap_fill(struct vivid_dev *dev, unsigned seqnr)
-{
- struct vivid_vbi_gen_data *vbi_gen = &dev->vbi_gen;
- bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
-
- vivid_vbi_gen_sliced(vbi_gen, is_60hz, seqnr);
-
- if (!is_60hz) {
- if (dev->loop_video) {
- if (dev->vbi_out_have_wss) {
- vbi_gen->data[12].data[0] = dev->vbi_out_wss[0];
- vbi_gen->data[12].data[1] = dev->vbi_out_wss[1];
- } else {
- vbi_gen->data[12].id = 0;
- }
- } else {
- switch (tpg_g_video_aspect(&dev->tpg)) {
- case TPG_VIDEO_ASPECT_14X9_CENTRE:
- vbi_gen->data[12].data[0] = 0x01;
- break;
- case TPG_VIDEO_ASPECT_16X9_CENTRE:
- vbi_gen->data[12].data[0] = 0x0b;
- break;
- case TPG_VIDEO_ASPECT_16X9_ANAMORPHIC:
- vbi_gen->data[12].data[0] = 0x07;
- break;
- case TPG_VIDEO_ASPECT_4X3:
- default:
- vbi_gen->data[12].data[0] = 0x08;
- break;
- }
- }
- } else if (dev->loop_video && is_60hz) {
- if (dev->vbi_out_have_cc[0]) {
- vbi_gen->data[0].data[0] = dev->vbi_out_cc[0][0];
- vbi_gen->data[0].data[1] = dev->vbi_out_cc[0][1];
- } else {
- vbi_gen->data[0].id = 0;
- }
- if (dev->vbi_out_have_cc[1]) {
- vbi_gen->data[1].data[0] = dev->vbi_out_cc[1][0];
- vbi_gen->data[1].data[1] = dev->vbi_out_cc[1][1];
- } else {
- vbi_gen->data[1].id = 0;
- }
- }
-}
-
-static void vivid_g_fmt_vbi_cap(struct vivid_dev *dev, struct v4l2_vbi_format *vbi)
-{
- bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
-
- vbi->sampling_rate = 27000000;
- vbi->offset = 24;
- vbi->samples_per_line = 1440;
- vbi->sample_format = V4L2_PIX_FMT_GREY;
- vbi->start[0] = is_60hz ? V4L2_VBI_ITU_525_F1_START + 9 : V4L2_VBI_ITU_625_F1_START + 5;
- vbi->start[1] = is_60hz ? V4L2_VBI_ITU_525_F2_START + 9 : V4L2_VBI_ITU_625_F2_START + 5;
- vbi->count[0] = vbi->count[1] = is_60hz ? 12 : 18;
- vbi->flags = dev->vbi_cap_interlaced ? V4L2_VBI_INTERLACED : 0;
- vbi->reserved[0] = 0;
- vbi->reserved[1] = 0;
-}
-
-void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
-{
- struct v4l2_vbi_format vbi;
- u8 *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
-
- vivid_g_fmt_vbi_cap(dev, &vbi);
- buf->vb.sequence = dev->vbi_cap_seq_count;
- if (dev->field_cap == V4L2_FIELD_ALTERNATE)
- buf->vb.sequence /= 2;
-
- vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence);
-
- memset(vbuf, 0x10, vb2_plane_size(&buf->vb.vb2_buf, 0));
-
- if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input]))
- vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf);
-}
-
-
-void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,
- struct vivid_buffer *buf)
-{
- struct v4l2_sliced_vbi_data *vbuf =
- vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
-
- buf->vb.sequence = dev->vbi_cap_seq_count;
- if (dev->field_cap == V4L2_FIELD_ALTERNATE)
- buf->vb.sequence /= 2;
-
- vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence);
-
- memset(vbuf, 0, vb2_plane_size(&buf->vb.vb2_buf, 0));
- if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input])) {
- unsigned i;
-
- for (i = 0; i < 25; i++)
- vbuf[i] = dev->vbi_gen.data[i];
- }
-}
-
-static int vbi_cap_queue_setup(struct vb2_queue *vq,
- unsigned *nbuffers, unsigned *nplanes,
- unsigned sizes[], struct device *alloc_devs[])
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
- unsigned size = vq->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ?
- 36 * sizeof(struct v4l2_sliced_vbi_data) :
- 1440 * 2 * (is_60hz ? 12 : 18);
-
- if (!vivid_is_sdtv_cap(dev))
- return -EINVAL;
-
- sizes[0] = size;
-
- if (vq->num_buffers + *nbuffers < 2)
- *nbuffers = 2 - vq->num_buffers;
-
- *nplanes = 1;
- return 0;
-}
-
-static int vbi_cap_buf_prepare(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
- unsigned size = vb->vb2_queue->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ?
- 36 * sizeof(struct v4l2_sliced_vbi_data) :
- 1440 * 2 * (is_60hz ? 12 : 18);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->buf_prepare_error) {
- /*
- * Error injection: test what happens if buf_prepare() returns
- * an error.
- */
- dev->buf_prepare_error = false;
- return -EINVAL;
- }
- if (vb2_plane_size(vb, 0) < size) {
- dprintk(dev, 1, "%s data will not fit into plane (%lu < %u)\n",
- __func__, vb2_plane_size(vb, 0), size);
- return -EINVAL;
- }
- vb2_set_plane_payload(vb, 0, size);
-
- return 0;
-}
-
-static void vbi_cap_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- spin_lock(&dev->slock);
- list_add_tail(&buf->list, &dev->vbi_cap_active);
- spin_unlock(&dev->slock);
-}
-
-static int vbi_cap_start_streaming(struct vb2_queue *vq, unsigned count)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- int err;
-
- dprintk(dev, 1, "%s\n", __func__);
- dev->vbi_cap_seq_count = 0;
- if (dev->start_streaming_error) {
- dev->start_streaming_error = false;
- err = -EINVAL;
- } else {
- err = vivid_start_generating_vid_cap(dev, &dev->vbi_cap_streaming);
- }
- if (err) {
- struct vivid_buffer *buf, *tmp;
-
- list_for_each_entry_safe(buf, tmp, &dev->vbi_cap_active, list) {
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf,
- VB2_BUF_STATE_QUEUED);
- }
- }
- return err;
-}
-
-/* abort streaming and wait for last buffer */
-static void vbi_cap_stop_streaming(struct vb2_queue *vq)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
-
- dprintk(dev, 1, "%s\n", __func__);
- vivid_stop_generating_vid_cap(dev, &dev->vbi_cap_streaming);
-}
-
-static void vbi_cap_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_vbi_cap);
-}
-
-const struct vb2_ops vivid_vbi_cap_qops = {
- .queue_setup = vbi_cap_queue_setup,
- .buf_prepare = vbi_cap_buf_prepare,
- .buf_queue = vbi_cap_buf_queue,
- .start_streaming = vbi_cap_start_streaming,
- .stop_streaming = vbi_cap_stop_streaming,
- .buf_request_complete = vbi_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_vbi_format *vbi = &f->fmt.vbi;
-
- if (!vivid_is_sdtv_cap(dev) || !dev->has_raw_vbi_cap)
- return -EINVAL;
-
- vivid_g_fmt_vbi_cap(dev, vbi);
- return 0;
-}
-
-int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- int ret = vidioc_g_fmt_vbi_cap(file, priv, f);
-
- if (ret)
- return ret;
- if (dev->stream_sliced_vbi_cap && vb2_is_busy(&dev->vb_vbi_cap_q))
- return -EBUSY;
- dev->stream_sliced_vbi_cap = false;
- dev->vbi_cap_dev.queue->type = V4L2_BUF_TYPE_VBI_CAPTURE;
- return 0;
-}
-
-void vivid_fill_service_lines(struct v4l2_sliced_vbi_format *vbi, u32 service_set)
-{
- vbi->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
- vbi->service_set = service_set;
- memset(vbi->service_lines, 0, sizeof(vbi->service_lines));
- memset(vbi->reserved, 0, sizeof(vbi->reserved));
-
- if (vbi->service_set == 0)
- return;
-
- if (vbi->service_set & V4L2_SLICED_CAPTION_525) {
- vbi->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
- vbi->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
- }
- if (vbi->service_set & V4L2_SLICED_WSS_625) {
- unsigned i;
-
- for (i = 7; i <= 18; i++)
- vbi->service_lines[0][i] =
- vbi->service_lines[1][i] = V4L2_SLICED_TELETEXT_B;
- vbi->service_lines[0][23] = V4L2_SLICED_WSS_625;
- }
-}
-
-int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
-
- if (!vivid_is_sdtv_cap(dev) || !dev->has_sliced_vbi_cap)
- return -EINVAL;
-
- vivid_fill_service_lines(vbi, dev->service_set_cap);
- return 0;
-}
-
-int vidioc_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
- bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
- u32 service_set = vbi->service_set;
-
- if (!vivid_is_sdtv_cap(dev) || !dev->has_sliced_vbi_cap)
- return -EINVAL;
-
- service_set &= is_60hz ? V4L2_SLICED_CAPTION_525 :
- V4L2_SLICED_WSS_625 | V4L2_SLICED_TELETEXT_B;
- vivid_fill_service_lines(vbi, service_set);
- return 0;
-}
-
-int vidioc_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
- int ret = vidioc_try_fmt_sliced_vbi_cap(file, fh, fmt);
-
- if (ret)
- return ret;
- if (!dev->stream_sliced_vbi_cap && vb2_is_busy(&dev->vb_vbi_cap_q))
- return -EBUSY;
- dev->service_set_cap = vbi->service_set;
- dev->stream_sliced_vbi_cap = true;
- dev->vbi_cap_dev.queue->type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
- return 0;
-}
-
-int vidioc_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
- bool is_60hz;
-
- if (vdev->vfl_dir == VFL_DIR_RX) {
- is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
- if (!vivid_is_sdtv_cap(dev) || !dev->has_sliced_vbi_cap ||
- cap->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
- return -EINVAL;
- } else {
- is_60hz = dev->std_out & V4L2_STD_525_60;
- if (!vivid_is_svid_out(dev) || !dev->has_sliced_vbi_out ||
- cap->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
- return -EINVAL;
- }
-
- cap->service_set = is_60hz ? V4L2_SLICED_CAPTION_525 :
- V4L2_SLICED_WSS_625 | V4L2_SLICED_TELETEXT_B;
- if (is_60hz) {
- cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
- cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
- } else {
- unsigned i;
-
- for (i = 7; i <= 18; i++)
- cap->service_lines[0][i] =
- cap->service_lines[1][i] = V4L2_SLICED_TELETEXT_B;
- cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
- }
- return 0;
-}
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.h b/drivers/media/platform/vivid/vivid-vbi-cap.h
deleted file mode 100644
index 91d2de01381c..000000000000
--- a/drivers/media/platform/vivid/vivid-vbi-cap.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-vbi-cap.h - vbi capture support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_VBI_CAP_H_
-#define _VIVID_VBI_CAP_H_
-
-void vivid_fill_time_of_day_packet(u8 *packet);
-void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf);
-void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf);
-void vivid_sliced_vbi_out_process(struct vivid_dev *dev, struct vivid_buffer *buf);
-int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
- struct v4l2_format *f);
-int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
- struct v4l2_format *f);
-int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt);
-int vidioc_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt);
-int vidioc_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt);
-int vidioc_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap);
-
-void vivid_fill_service_lines(struct v4l2_sliced_vbi_format *vbi, u32 service_set);
-
-extern const struct vb2_ops vivid_vbi_cap_qops;
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-vbi-gen.c b/drivers/media/platform/vivid/vivid-vbi-gen.c
deleted file mode 100644
index acc98445a1fa..000000000000
--- a/drivers/media/platform/vivid/vivid-vbi-gen.c
+++ /dev/null
@@ -1,311 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-vbi-gen.c - vbi generator support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/ktime.h>
-#include <linux/string.h>
-#include <linux/videodev2.h>
-
-#include "vivid-vbi-gen.h"
-
-static void wss_insert(u8 *wss, u32 val, unsigned size)
-{
- while (size--)
- *wss++ = (val & (1 << size)) ? 0xc0 : 0x10;
-}
-
-static void vivid_vbi_gen_wss_raw(const struct v4l2_sliced_vbi_data *data,
- u8 *buf, unsigned sampling_rate)
-{
- const unsigned rate = 5000000; /* WSS has a 5 MHz transmission rate */
- u8 wss[29 + 24 + 24 + 24 + 18 + 18] = { 0 };
- const unsigned zero = 0x07;
- const unsigned one = 0x38;
- unsigned bit = 0;
- u16 wss_data;
- int i;
-
- wss_insert(wss + bit, 0x1f1c71c7, 29); bit += 29;
- wss_insert(wss + bit, 0x1e3c1f, 24); bit += 24;
-
- wss_data = (data->data[1] << 8) | data->data[0];
- for (i = 0; i <= 13; i++, bit += 6)
- wss_insert(wss + bit, (wss_data & (1 << i)) ? one : zero, 6);
-
- for (i = 0, bit = 0; bit < sizeof(wss); bit++) {
- unsigned n = ((bit + 1) * sampling_rate) / rate;
-
- while (i < n)
- buf[i++] = wss[bit];
- }
-}
-
-static void vivid_vbi_gen_teletext_raw(const struct v4l2_sliced_vbi_data *data,
- u8 *buf, unsigned sampling_rate)
-{
- const unsigned rate = 6937500 / 10; /* Teletext has a 6.9375 MHz transmission rate */
- u8 teletext[45] = { 0x55, 0x55, 0x27 };
- unsigned bit = 0;
- int i;
-
- memcpy(teletext + 3, data->data, sizeof(teletext) - 3);
- /* prevents 32 bit overflow */
- sampling_rate /= 10;
-
- for (i = 0, bit = 0; bit < sizeof(teletext) * 8; bit++) {
- unsigned n = ((bit + 1) * sampling_rate) / rate;
- u8 val = (teletext[bit / 8] & (1 << (bit & 7))) ? 0xc0 : 0x10;
-
- while (i < n)
- buf[i++] = val;
- }
-}
-
-static void cc_insert(u8 *cc, u8 ch)
-{
- unsigned tot = 0;
- unsigned i;
-
- for (i = 0; i < 7; i++) {
- cc[2 * i] = cc[2 * i + 1] = (ch & (1 << i)) ? 1 : 0;
- tot += cc[2 * i];
- }
- cc[14] = cc[15] = !(tot & 1);
-}
-
-#define CC_PREAMBLE_BITS (14 + 4 + 2)
-
-static void vivid_vbi_gen_cc_raw(const struct v4l2_sliced_vbi_data *data,
- u8 *buf, unsigned sampling_rate)
-{
- const unsigned rate = 1000000; /* CC has a 1 MHz transmission rate */
-
- u8 cc[CC_PREAMBLE_BITS + 2 * 16] = {
- /* Clock run-in: 7 cycles */
- 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
- /* 2 cycles of 0 */
- 0, 0, 0, 0,
- /* Start bit of 1 (each bit is two cycles) */
- 1, 1
- };
- unsigned bit, i;
-
- cc_insert(cc + CC_PREAMBLE_BITS, data->data[0]);
- cc_insert(cc + CC_PREAMBLE_BITS + 16, data->data[1]);
-
- for (i = 0, bit = 0; bit < sizeof(cc); bit++) {
- unsigned n = ((bit + 1) * sampling_rate) / rate;
-
- while (i < n)
- buf[i++] = cc[bit] ? 0xc0 : 0x10;
- }
-}
-
-void vivid_vbi_gen_raw(const struct vivid_vbi_gen_data *vbi,
- const struct v4l2_vbi_format *vbi_fmt, u8 *buf)
-{
- unsigned idx;
-
- for (idx = 0; idx < 25; idx++) {
- const struct v4l2_sliced_vbi_data *data = vbi->data + idx;
- unsigned start_2nd_field;
- unsigned line = data->line;
- u8 *linebuf = buf;
-
- start_2nd_field = (data->id & V4L2_SLICED_VBI_525) ? 263 : 313;
- if (data->field)
- line += start_2nd_field;
- line -= vbi_fmt->start[data->field];
-
- if (vbi_fmt->flags & V4L2_VBI_INTERLACED)
- linebuf += (line * 2 + data->field) *
- vbi_fmt->samples_per_line;
- else
- linebuf += (line + data->field * vbi_fmt->count[0]) *
- vbi_fmt->samples_per_line;
- if (data->id == V4L2_SLICED_CAPTION_525)
- vivid_vbi_gen_cc_raw(data, linebuf, vbi_fmt->sampling_rate);
- else if (data->id == V4L2_SLICED_WSS_625)
- vivid_vbi_gen_wss_raw(data, linebuf, vbi_fmt->sampling_rate);
- else if (data->id == V4L2_SLICED_TELETEXT_B)
- vivid_vbi_gen_teletext_raw(data, linebuf, vbi_fmt->sampling_rate);
- }
-}
-
-static const u8 vivid_cc_sequence1[30] = {
- 0x14, 0x20, /* Resume Caption Loading */
- 'H', 'e',
- 'l', 'l',
- 'o', ' ',
- 'w', 'o',
- 'r', 'l',
- 'd', '!',
- 0x14, 0x2f, /* End of Caption */
-};
-
-static const u8 vivid_cc_sequence2[30] = {
- 0x14, 0x20, /* Resume Caption Loading */
- 'C', 'l',
- 'o', 's',
- 'e', 'd',
- ' ', 'c',
- 'a', 'p',
- 't', 'i',
- 'o', 'n',
- 's', ' ',
- 't', 'e',
- 's', 't',
- 0x14, 0x2f, /* End of Caption */
-};
-
-static u8 calc_parity(u8 val)
-{
- unsigned i;
- unsigned tot = 0;
-
- for (i = 0; i < 7; i++)
- tot += (val & (1 << i)) ? 1 : 0;
- return val | ((tot & 1) ? 0 : 0x80);
-}
-
-static void vivid_vbi_gen_set_time_of_day(u8 *packet)
-{
- struct tm tm;
- u8 checksum, i;
-
- time64_to_tm(ktime_get_real_seconds(), 0, &tm);
- packet[0] = calc_parity(0x07);
- packet[1] = calc_parity(0x01);
- packet[2] = calc_parity(0x40 | tm.tm_min);
- packet[3] = calc_parity(0x40 | tm.tm_hour);
- packet[4] = calc_parity(0x40 | tm.tm_mday);
- if (tm.tm_mday == 1 && tm.tm_mon == 2 &&
- sys_tz.tz_minuteswest > tm.tm_min + tm.tm_hour * 60)
- packet[4] = calc_parity(0x60 | tm.tm_mday);
- packet[5] = calc_parity(0x40 | (1 + tm.tm_mon));
- packet[6] = calc_parity(0x40 | (1 + tm.tm_wday));
- packet[7] = calc_parity(0x40 | ((tm.tm_year - 90) & 0x3f));
- packet[8] = calc_parity(0x0f);
- for (checksum = i = 0; i <= 8; i++)
- checksum += packet[i] & 0x7f;
- packet[9] = calc_parity(0x100 - checksum);
- checksum = 0;
- packet[10] = calc_parity(0x07);
- packet[11] = calc_parity(0x04);
- if (sys_tz.tz_minuteswest >= 0)
- packet[12] = calc_parity(0x40 | ((sys_tz.tz_minuteswest / 60) & 0x1f));
- else
- packet[12] = calc_parity(0x40 | ((24 + sys_tz.tz_minuteswest / 60) & 0x1f));
- packet[13] = calc_parity(0);
- packet[14] = calc_parity(0x0f);
- for (checksum = 0, i = 10; i <= 14; i++)
- checksum += packet[i] & 0x7f;
- packet[15] = calc_parity(0x100 - checksum);
-}
-
-static const u8 hamming[16] = {
- 0x15, 0x02, 0x49, 0x5e, 0x64, 0x73, 0x38, 0x2f,
- 0xd0, 0xc7, 0x8c, 0x9b, 0xa1, 0xb6, 0xfd, 0xea
-};
-
-static void vivid_vbi_gen_teletext(u8 *packet, unsigned line, unsigned frame)
-{
- unsigned offset = 2;
- unsigned i;
-
- packet[0] = hamming[1 + ((line & 1) << 3)];
- packet[1] = hamming[line >> 1];
- memset(packet + 2, 0x20, 40);
- if (line == 0) {
- /* subcode */
- packet[2] = hamming[frame % 10];
- packet[3] = hamming[frame / 10];
- packet[4] = hamming[0];
- packet[5] = hamming[0];
- packet[6] = hamming[0];
- packet[7] = hamming[0];
- packet[8] = hamming[0];
- packet[9] = hamming[1];
- offset = 10;
- }
- packet += offset;
- memcpy(packet, "Page: 100 Row: 10", 17);
- packet[7] = '0' + frame / 10;
- packet[8] = '0' + frame % 10;
- packet[15] = '0' + line / 10;
- packet[16] = '0' + line % 10;
- for (i = 0; i < 42 - offset; i++)
- packet[i] = calc_parity(packet[i]);
-}
-
-void vivid_vbi_gen_sliced(struct vivid_vbi_gen_data *vbi,
- bool is_60hz, unsigned seqnr)
-{
- struct v4l2_sliced_vbi_data *data0 = vbi->data;
- struct v4l2_sliced_vbi_data *data1 = vbi->data + 1;
- unsigned frame = seqnr % 60;
-
- memset(vbi->data, 0, sizeof(vbi->data));
-
- if (!is_60hz) {
- unsigned i;
-
- for (i = 0; i <= 11; i++) {
- data0->id = V4L2_SLICED_TELETEXT_B;
- data0->line = 7 + i;
- vivid_vbi_gen_teletext(data0->data, i, frame);
- data0++;
- }
- data0->id = V4L2_SLICED_WSS_625;
- data0->line = 23;
- /* 4x3 video aspect ratio */
- data0->data[0] = 0x08;
- data0++;
- for (i = 0; i <= 11; i++) {
- data0->id = V4L2_SLICED_TELETEXT_B;
- data0->field = 1;
- data0->line = 7 + i;
- vivid_vbi_gen_teletext(data0->data, 12 + i, frame);
- data0++;
- }
- return;
- }
-
- data0->id = V4L2_SLICED_CAPTION_525;
- data0->line = 21;
- data1->id = V4L2_SLICED_CAPTION_525;
- data1->field = 1;
- data1->line = 21;
-
- if (frame < 15) {
- data0->data[0] = calc_parity(vivid_cc_sequence1[2 * frame]);
- data0->data[1] = calc_parity(vivid_cc_sequence1[2 * frame + 1]);
- } else if (frame >= 30 && frame < 45) {
- frame -= 30;
- data0->data[0] = calc_parity(vivid_cc_sequence2[2 * frame]);
- data0->data[1] = calc_parity(vivid_cc_sequence2[2 * frame + 1]);
- } else {
- data0->data[0] = calc_parity(0);
- data0->data[1] = calc_parity(0);
- }
-
- frame = seqnr % (30 * 60);
- switch (frame) {
- case 0:
- vivid_vbi_gen_set_time_of_day(vbi->time_of_day_packet);
- /* fall through */
- case 1 ... 7:
- data1->data[0] = vbi->time_of_day_packet[frame * 2];
- data1->data[1] = vbi->time_of_day_packet[frame * 2 + 1];
- break;
- default:
- data1->data[0] = calc_parity(0);
- data1->data[1] = calc_parity(0);
- break;
- }
-}
diff --git a/drivers/media/platform/vivid/vivid-vbi-gen.h b/drivers/media/platform/vivid/vivid-vbi-gen.h
deleted file mode 100644
index 2657a7f5571c..000000000000
--- a/drivers/media/platform/vivid/vivid-vbi-gen.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-vbi-gen.h - vbi generator support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_VBI_GEN_H_
-#define _VIVID_VBI_GEN_H_
-
-struct vivid_vbi_gen_data {
- struct v4l2_sliced_vbi_data data[25];
- u8 time_of_day_packet[16];
-};
-
-void vivid_vbi_gen_sliced(struct vivid_vbi_gen_data *vbi,
- bool is_60hz, unsigned seqnr);
-void vivid_vbi_gen_raw(const struct vivid_vbi_gen_data *vbi,
- const struct v4l2_vbi_format *vbi_fmt, u8 *buf);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c
deleted file mode 100644
index cd56476902a2..000000000000
--- a/drivers/media/platform/vivid/vivid-vbi-out.c
+++ /dev/null
@@ -1,250 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-vbi-out.c - vbi output support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-
-#include "vivid-core.h"
-#include "vivid-kthread-out.h"
-#include "vivid-vbi-out.h"
-#include "vivid-vbi-cap.h"
-
-static int vbi_out_queue_setup(struct vb2_queue *vq,
- unsigned *nbuffers, unsigned *nplanes,
- unsigned sizes[], struct device *alloc_devs[])
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- bool is_60hz = dev->std_out & V4L2_STD_525_60;
- unsigned size = vq->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ?
- 36 * sizeof(struct v4l2_sliced_vbi_data) :
- 1440 * 2 * (is_60hz ? 12 : 18);
-
- if (!vivid_is_svid_out(dev))
- return -EINVAL;
-
- sizes[0] = size;
-
- if (vq->num_buffers + *nbuffers < 2)
- *nbuffers = 2 - vq->num_buffers;
-
- *nplanes = 1;
- return 0;
-}
-
-static int vbi_out_buf_prepare(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- bool is_60hz = dev->std_out & V4L2_STD_525_60;
- unsigned size = vb->vb2_queue->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ?
- 36 * sizeof(struct v4l2_sliced_vbi_data) :
- 1440 * 2 * (is_60hz ? 12 : 18);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->buf_prepare_error) {
- /*
- * Error injection: test what happens if buf_prepare() returns
- * an error.
- */
- dev->buf_prepare_error = false;
- return -EINVAL;
- }
- if (vb2_plane_size(vb, 0) < size) {
- dprintk(dev, 1, "%s data will not fit into plane (%lu < %u)\n",
- __func__, vb2_plane_size(vb, 0), size);
- return -EINVAL;
- }
- vb2_set_plane_payload(vb, 0, size);
-
- return 0;
-}
-
-static void vbi_out_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- spin_lock(&dev->slock);
- list_add_tail(&buf->list, &dev->vbi_out_active);
- spin_unlock(&dev->slock);
-}
-
-static int vbi_out_start_streaming(struct vb2_queue *vq, unsigned count)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- int err;
-
- dprintk(dev, 1, "%s\n", __func__);
- dev->vbi_out_seq_count = 0;
- if (dev->start_streaming_error) {
- dev->start_streaming_error = false;
- err = -EINVAL;
- } else {
- err = vivid_start_generating_vid_out(dev, &dev->vbi_out_streaming);
- }
- if (err) {
- struct vivid_buffer *buf, *tmp;
-
- list_for_each_entry_safe(buf, tmp, &dev->vbi_out_active, list) {
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf,
- VB2_BUF_STATE_QUEUED);
- }
- }
- return err;
-}
-
-/* abort streaming and wait for last buffer */
-static void vbi_out_stop_streaming(struct vb2_queue *vq)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
-
- dprintk(dev, 1, "%s\n", __func__);
- vivid_stop_generating_vid_out(dev, &dev->vbi_out_streaming);
- dev->vbi_out_have_wss = false;
- dev->vbi_out_have_cc[0] = false;
- dev->vbi_out_have_cc[1] = false;
-}
-
-static void vbi_out_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_vbi_out);
-}
-
-const struct vb2_ops vivid_vbi_out_qops = {
- .queue_setup = vbi_out_queue_setup,
- .buf_prepare = vbi_out_buf_prepare,
- .buf_queue = vbi_out_buf_queue,
- .start_streaming = vbi_out_start_streaming,
- .stop_streaming = vbi_out_stop_streaming,
- .buf_request_complete = vbi_out_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-int vidioc_g_fmt_vbi_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_vbi_format *vbi = &f->fmt.vbi;
- bool is_60hz = dev->std_out & V4L2_STD_525_60;
-
- if (!vivid_is_svid_out(dev) || !dev->has_raw_vbi_out)
- return -EINVAL;
-
- vbi->sampling_rate = 25000000;
- vbi->offset = 24;
- vbi->samples_per_line = 1440;
- vbi->sample_format = V4L2_PIX_FMT_GREY;
- vbi->start[0] = is_60hz ? V4L2_VBI_ITU_525_F1_START + 9 : V4L2_VBI_ITU_625_F1_START + 5;
- vbi->start[1] = is_60hz ? V4L2_VBI_ITU_525_F2_START + 9 : V4L2_VBI_ITU_625_F2_START + 5;
- vbi->count[0] = vbi->count[1] = is_60hz ? 12 : 18;
- vbi->flags = dev->vbi_cap_interlaced ? V4L2_VBI_INTERLACED : 0;
- vbi->reserved[0] = 0;
- vbi->reserved[1] = 0;
- return 0;
-}
-
-int vidioc_s_fmt_vbi_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- int ret = vidioc_g_fmt_vbi_out(file, priv, f);
-
- if (ret)
- return ret;
- if (vb2_is_busy(&dev->vb_vbi_out_q))
- return -EBUSY;
- dev->stream_sliced_vbi_out = false;
- dev->vbi_out_dev.queue->type = V4L2_BUF_TYPE_VBI_OUTPUT;
- return 0;
-}
-
-int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
-
- if (!vivid_is_svid_out(dev) || !dev->has_sliced_vbi_out)
- return -EINVAL;
-
- vivid_fill_service_lines(vbi, dev->service_set_out);
- return 0;
-}
-
-int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
- bool is_60hz = dev->std_out & V4L2_STD_525_60;
- u32 service_set = vbi->service_set;
-
- if (!vivid_is_svid_out(dev) || !dev->has_sliced_vbi_out)
- return -EINVAL;
-
- service_set &= is_60hz ? V4L2_SLICED_CAPTION_525 :
- V4L2_SLICED_WSS_625 | V4L2_SLICED_TELETEXT_B;
- vivid_fill_service_lines(vbi, service_set);
- return 0;
-}
-
-int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh,
- struct v4l2_format *fmt)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
- int ret = vidioc_try_fmt_sliced_vbi_out(file, fh, fmt);
-
- if (ret)
- return ret;
- if (vb2_is_busy(&dev->vb_vbi_out_q))
- return -EBUSY;
- dev->service_set_out = vbi->service_set;
- dev->stream_sliced_vbi_out = true;
- dev->vbi_out_dev.queue->type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
- return 0;
-}
-
-void vivid_sliced_vbi_out_process(struct vivid_dev *dev,
- struct vivid_buffer *buf)
-{
- struct v4l2_sliced_vbi_data *vbi =
- vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
- unsigned elems =
- vb2_get_plane_payload(&buf->vb.vb2_buf, 0) / sizeof(*vbi);
-
- dev->vbi_out_have_cc[0] = false;
- dev->vbi_out_have_cc[1] = false;
- dev->vbi_out_have_wss = false;
- while (elems--) {
- switch (vbi->id) {
- case V4L2_SLICED_CAPTION_525:
- if ((dev->std_out & V4L2_STD_525_60) && vbi->line == 21) {
- dev->vbi_out_have_cc[!!vbi->field] = true;
- dev->vbi_out_cc[!!vbi->field][0] = vbi->data[0];
- dev->vbi_out_cc[!!vbi->field][1] = vbi->data[1];
- }
- break;
- case V4L2_SLICED_WSS_625:
- if ((dev->std_out & V4L2_STD_625_50) &&
- vbi->field == 0 && vbi->line == 23) {
- dev->vbi_out_have_wss = true;
- dev->vbi_out_wss[0] = vbi->data[0];
- dev->vbi_out_wss[1] = vbi->data[1];
- }
- break;
- }
- vbi++;
- }
-}
diff --git a/drivers/media/platform/vivid/vivid-vbi-out.h b/drivers/media/platform/vivid/vivid-vbi-out.h
deleted file mode 100644
index 76584940cdaf..000000000000
--- a/drivers/media/platform/vivid/vivid-vbi-out.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-vbi-out.h - vbi output support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_VBI_OUT_H_
-#define _VIVID_VBI_OUT_H_
-
-void vivid_sliced_vbi_out_process(struct vivid_dev *dev, struct vivid_buffer *buf);
-int vidioc_g_fmt_vbi_out(struct file *file, void *priv,
- struct v4l2_format *f);
-int vidioc_s_fmt_vbi_out(struct file *file, void *priv,
- struct v4l2_format *f);
-int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt);
-int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt);
-int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt);
-
-extern const struct vb2_ops vivid_vbi_out_qops;
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
deleted file mode 100644
index e94beef008c8..000000000000
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ /dev/null
@@ -1,1918 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-vid-cap.c - video capture support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-#include <linux/videodev2.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-dv-timings.h>
-#include <media/v4l2-rect.h>
-
-#include "vivid-core.h"
-#include "vivid-vid-common.h"
-#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 */
-#define VIVID_WEBCAM_IVALS (VIVID_WEBCAM_SIZES * 2)
-
-/* Sizes must be in increasing order */
-static const struct v4l2_frmsize_discrete webcam_sizes[VIVID_WEBCAM_SIZES] = {
- { 320, 180 },
- { 640, 360 },
- { 640, 480 },
- { 1280, 720 },
- { 1920, 1080 },
- { 3840, 2160 },
-};
-
-/*
- * Intervals must be in increasing order and there must be twice as many
- * elements in this array as there are in webcam_sizes.
- */
-static const struct v4l2_fract webcam_intervals[VIVID_WEBCAM_IVALS] = {
- { 1, 1 },
- { 1, 2 },
- { 1, 4 },
- { 1, 5 },
- { 1, 10 },
- { 2, 25 },
- { 1, 15 },
- { 1, 25 },
- { 1, 30 },
- { 1, 40 },
- { 1, 50 },
- { 1, 60 },
-};
-
-static int vid_cap_queue_setup(struct vb2_queue *vq,
- unsigned *nbuffers, unsigned *nplanes,
- unsigned sizes[], struct device *alloc_devs[])
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- unsigned buffers = tpg_g_buffers(&dev->tpg);
- unsigned h = dev->fmt_cap_rect.height;
- unsigned p;
-
- if (dev->field_cap == V4L2_FIELD_ALTERNATE) {
- /*
- * You cannot use read() with FIELD_ALTERNATE since the field
- * information (TOP/BOTTOM) cannot be passed back to the user.
- */
- if (vb2_fileio_is_active(vq))
- return -EINVAL;
- }
-
- if (dev->queue_setup_error) {
- /*
- * Error injection: test what happens if queue_setup() returns
- * an error.
- */
- dev->queue_setup_error = false;
- return -EINVAL;
- }
- if (*nplanes) {
- /*
- * Check if the number of requested planes match
- * the number of buffers in the current format. You can't mix that.
- */
- if (*nplanes != buffers)
- return -EINVAL;
- for (p = 0; p < buffers; p++) {
- if (sizes[p] < tpg_g_line_width(&dev->tpg, p) * h +
- dev->fmt_cap->data_offset[p])
- return -EINVAL;
- }
- } else {
- for (p = 0; p < buffers; p++)
- sizes[p] = (tpg_g_line_width(&dev->tpg, p) * h) /
- dev->fmt_cap->vdownsampling[p] +
- dev->fmt_cap->data_offset[p];
- }
-
- if (vq->num_buffers + *nbuffers < 2)
- *nbuffers = 2 - vq->num_buffers;
-
- *nplanes = buffers;
-
- dprintk(dev, 1, "%s: count=%d\n", __func__, *nbuffers);
- for (p = 0; p < buffers; p++)
- dprintk(dev, 1, "%s: size[%u]=%u\n", __func__, p, sizes[p]);
-
- return 0;
-}
-
-static int vid_cap_buf_prepare(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- unsigned long size;
- unsigned buffers = tpg_g_buffers(&dev->tpg);
- unsigned p;
-
- dprintk(dev, 1, "%s\n", __func__);
-
- if (WARN_ON(NULL == dev->fmt_cap))
- return -EINVAL;
-
- if (dev->buf_prepare_error) {
- /*
- * Error injection: test what happens if buf_prepare() returns
- * an error.
- */
- dev->buf_prepare_error = false;
- return -EINVAL;
- }
- for (p = 0; p < buffers; p++) {
- size = (tpg_g_line_width(&dev->tpg, p) *
- dev->fmt_cap_rect.height) /
- dev->fmt_cap->vdownsampling[p] +
- dev->fmt_cap->data_offset[p];
-
- if (vb2_plane_size(vb, p) < size) {
- dprintk(dev, 1, "%s data will not fit into plane %u (%lu < %lu)\n",
- __func__, p, vb2_plane_size(vb, p), size);
- return -EINVAL;
- }
-
- vb2_set_plane_payload(vb, p, size);
- vb->planes[p].data_offset = dev->fmt_cap->data_offset[p];
- }
-
- return 0;
-}
-
-static void vid_cap_buf_finish(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct v4l2_timecode *tc = &vbuf->timecode;
- unsigned fps = 25;
- unsigned seq = vbuf->sequence;
-
- if (!vivid_is_sdtv_cap(dev))
- return;
-
- /*
- * Set the timecode. Rarely used, so it is interesting to
- * test this.
- */
- vbuf->flags |= V4L2_BUF_FLAG_TIMECODE;
- if (dev->std_cap[dev->input] & V4L2_STD_525_60)
- fps = 30;
- tc->type = (fps == 30) ? V4L2_TC_TYPE_30FPS : V4L2_TC_TYPE_25FPS;
- tc->flags = 0;
- tc->frames = seq % fps;
- tc->seconds = (seq / fps) % 60;
- tc->minutes = (seq / (60 * fps)) % 60;
- tc->hours = (seq / (60 * 60 * fps)) % 24;
-}
-
-static void vid_cap_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- spin_lock(&dev->slock);
- list_add_tail(&buf->list, &dev->vid_cap_active);
- spin_unlock(&dev->slock);
-}
-
-static int vid_cap_start_streaming(struct vb2_queue *vq, unsigned count)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- unsigned i;
- int err;
-
- if (vb2_is_streaming(&dev->vb_vid_out_q))
- dev->can_loop_video = vivid_vid_can_loop(dev);
-
- dev->vid_cap_seq_count = 0;
- dprintk(dev, 1, "%s\n", __func__);
- for (i = 0; i < VIDEO_MAX_FRAME; i++)
- dev->must_blank[i] = tpg_g_perc_fill(&dev->tpg) < 100;
- if (dev->start_streaming_error) {
- dev->start_streaming_error = false;
- err = -EINVAL;
- } else {
- err = vivid_start_generating_vid_cap(dev, &dev->vid_cap_streaming);
- }
- if (err) {
- struct vivid_buffer *buf, *tmp;
-
- list_for_each_entry_safe(buf, tmp, &dev->vid_cap_active, list) {
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf,
- VB2_BUF_STATE_QUEUED);
- }
- }
- return err;
-}
-
-/* abort streaming and wait for last buffer */
-static void vid_cap_stop_streaming(struct vb2_queue *vq)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
-
- dprintk(dev, 1, "%s\n", __func__);
- vivid_stop_generating_vid_cap(dev, &dev->vid_cap_streaming);
- dev->can_loop_video = false;
-}
-
-static void vid_cap_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_vid_cap);
-}
-
-const struct vb2_ops vivid_vid_cap_qops = {
- .queue_setup = vid_cap_queue_setup,
- .buf_prepare = vid_cap_buf_prepare,
- .buf_finish = vid_cap_buf_finish,
- .buf_queue = vid_cap_buf_queue,
- .start_streaming = vid_cap_start_streaming,
- .stop_streaming = vid_cap_stop_streaming,
- .buf_request_complete = vid_cap_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-/*
- * Determine the 'picture' quality based on the current TV frequency: either
- * COLOR for a good 'signal', GRAY (grayscale picture) for a slightly off
- * signal or NOISE for no signal.
- */
-void vivid_update_quality(struct vivid_dev *dev)
-{
- unsigned freq_modulus;
-
- if (dev->loop_video && (vivid_is_svid_cap(dev) || vivid_is_hdmi_cap(dev))) {
- /*
- * The 'noise' will only be replaced by the actual video
- * if the output video matches the input video settings.
- */
- tpg_s_quality(&dev->tpg, TPG_QUAL_NOISE, 0);
- return;
- }
- if (vivid_is_hdmi_cap(dev) &&
- VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode[dev->input])) {
- tpg_s_quality(&dev->tpg, TPG_QUAL_NOISE, 0);
- return;
- }
- if (vivid_is_sdtv_cap(dev) &&
- VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input])) {
- tpg_s_quality(&dev->tpg, TPG_QUAL_NOISE, 0);
- return;
- }
- if (!vivid_is_tv_cap(dev)) {
- tpg_s_quality(&dev->tpg, TPG_QUAL_COLOR, 0);
- return;
- }
-
- /*
- * There is a fake channel every 6 MHz at 49.25, 55.25, etc.
- * From +/- 0.25 MHz around the channel there is color, and from
- * +/- 1 MHz there is grayscale (chroma is lost).
- * Everywhere else it is just noise.
- */
- freq_modulus = (dev->tv_freq - 676 /* (43.25-1) * 16 */) % (6 * 16);
- if (freq_modulus > 2 * 16) {
- tpg_s_quality(&dev->tpg, TPG_QUAL_NOISE,
- next_pseudo_random32(dev->tv_freq ^ 0x55) & 0x3f);
- return;
- }
- if (freq_modulus < 12 /*0.75 * 16*/ || freq_modulus > 20 /*1.25 * 16*/)
- tpg_s_quality(&dev->tpg, TPG_QUAL_GRAY, 0);
- else
- tpg_s_quality(&dev->tpg, TPG_QUAL_COLOR, 0);
-}
-
-/*
- * Get the current picture quality and the associated afc value.
- */
-static enum tpg_quality vivid_get_quality(struct vivid_dev *dev, s32 *afc)
-{
- unsigned freq_modulus;
-
- if (afc)
- *afc = 0;
- if (tpg_g_quality(&dev->tpg) == TPG_QUAL_COLOR ||
- tpg_g_quality(&dev->tpg) == TPG_QUAL_NOISE)
- return tpg_g_quality(&dev->tpg);
-
- /*
- * There is a fake channel every 6 MHz at 49.25, 55.25, etc.
- * From +/- 0.25 MHz around the channel there is color, and from
- * +/- 1 MHz there is grayscale (chroma is lost).
- * Everywhere else it is just gray.
- */
- freq_modulus = (dev->tv_freq - 676 /* (43.25-1) * 16 */) % (6 * 16);
- if (afc)
- *afc = freq_modulus - 1 * 16;
- return TPG_QUAL_GRAY;
-}
-
-enum tpg_video_aspect vivid_get_video_aspect(const struct vivid_dev *dev)
-{
- if (vivid_is_sdtv_cap(dev))
- return dev->std_aspect_ratio[dev->input];
-
- if (vivid_is_hdmi_cap(dev))
- return dev->dv_timings_aspect_ratio[dev->input];
-
- return TPG_VIDEO_ASPECT_IMAGE;
-}
-
-static enum tpg_pixel_aspect vivid_get_pixel_aspect(const struct vivid_dev *dev)
-{
- if (vivid_is_sdtv_cap(dev))
- return (dev->std_cap[dev->input] & V4L2_STD_525_60) ?
- TPG_PIXEL_ASPECT_NTSC : TPG_PIXEL_ASPECT_PAL;
-
- if (vivid_is_hdmi_cap(dev) &&
- dev->src_rect.width == 720 && dev->src_rect.height <= 576)
- return dev->src_rect.height == 480 ?
- TPG_PIXEL_ASPECT_NTSC : TPG_PIXEL_ASPECT_PAL;
-
- return TPG_PIXEL_ASPECT_SQUARE;
-}
-
-/*
- * Called whenever the format has to be reset which can occur when
- * changing inputs, standard, timings, etc.
- */
-void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
-{
- struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
- unsigned size;
- u64 pixelclock;
-
- switch (dev->input_type[dev->input]) {
- case WEBCAM:
- default:
- dev->src_rect.width = webcam_sizes[dev->webcam_size_idx].width;
- dev->src_rect.height = webcam_sizes[dev->webcam_size_idx].height;
- dev->timeperframe_vid_cap = webcam_intervals[dev->webcam_ival_idx];
- dev->field_cap = V4L2_FIELD_NONE;
- tpg_s_rgb_range(&dev->tpg, V4L2_DV_RGB_RANGE_AUTO);
- break;
- case TV:
- case SVID:
- dev->field_cap = dev->tv_field_cap;
- dev->src_rect.width = 720;
- if (dev->std_cap[dev->input] & V4L2_STD_525_60) {
- dev->src_rect.height = 480;
- dev->timeperframe_vid_cap = (struct v4l2_fract) { 1001, 30000 };
- dev->service_set_cap = V4L2_SLICED_CAPTION_525;
- } else {
- dev->src_rect.height = 576;
- dev->timeperframe_vid_cap = (struct v4l2_fract) { 1000, 25000 };
- dev->service_set_cap = V4L2_SLICED_WSS_625 | V4L2_SLICED_TELETEXT_B;
- }
- tpg_s_rgb_range(&dev->tpg, V4L2_DV_RGB_RANGE_AUTO);
- break;
- case HDMI:
- dev->src_rect.width = bt->width;
- dev->src_rect.height = bt->height;
- size = V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt);
- if (dev->reduced_fps && can_reduce_fps(bt)) {
- pixelclock = div_u64(bt->pixelclock * 1000, 1001);
- bt->flags |= V4L2_DV_FL_REDUCED_FPS;
- } else {
- pixelclock = bt->pixelclock;
- bt->flags &= ~V4L2_DV_FL_REDUCED_FPS;
- }
- dev->timeperframe_vid_cap = (struct v4l2_fract) {
- size / 100, (u32)pixelclock / 100
- };
- if (bt->interlaced)
- dev->field_cap = V4L2_FIELD_ALTERNATE;
- else
- dev->field_cap = V4L2_FIELD_NONE;
-
- /*
- * We can be called from within s_ctrl, in that case we can't
- * set/get controls. Luckily we don't need to in that case.
- */
- if (keep_controls || !dev->colorspace)
- break;
- if (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) {
- if (bt->width == 720 && bt->height <= 576)
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
- else
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_709);
- v4l2_ctrl_s_ctrl(dev->real_rgb_range_cap, 1);
- } else {
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_SRGB);
- v4l2_ctrl_s_ctrl(dev->real_rgb_range_cap, 0);
- }
- 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;
- dev->compose_cap = dev->crop_cap;
- if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap))
- dev->compose_cap.height /= 2;
- dev->fmt_cap_rect = dev->compose_cap;
- tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
- tpg_s_pixel_aspect(&dev->tpg, vivid_get_pixel_aspect(dev));
- tpg_update_mv_step(&dev->tpg);
-}
-
-/* Map the field to something that is valid for the current input */
-static enum v4l2_field vivid_field_cap(struct vivid_dev *dev, enum v4l2_field field)
-{
- if (vivid_is_sdtv_cap(dev)) {
- switch (field) {
- case V4L2_FIELD_INTERLACED_TB:
- case V4L2_FIELD_INTERLACED_BT:
- case V4L2_FIELD_SEQ_TB:
- case V4L2_FIELD_SEQ_BT:
- case V4L2_FIELD_TOP:
- case V4L2_FIELD_BOTTOM:
- case V4L2_FIELD_ALTERNATE:
- return field;
- case V4L2_FIELD_INTERLACED:
- default:
- return V4L2_FIELD_INTERLACED;
- }
- }
- if (vivid_is_hdmi_cap(dev))
- return dev->dv_timings_cap[dev->input].bt.interlaced ?
- V4L2_FIELD_ALTERNATE : V4L2_FIELD_NONE;
- return V4L2_FIELD_NONE;
-}
-
-static unsigned vivid_colorspace_cap(struct vivid_dev *dev)
-{
- if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
- return tpg_g_colorspace(&dev->tpg);
- return dev->colorspace_out;
-}
-
-static unsigned vivid_xfer_func_cap(struct vivid_dev *dev)
-{
- if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
- return tpg_g_xfer_func(&dev->tpg);
- return dev->xfer_func_out;
-}
-
-static unsigned vivid_ycbcr_enc_cap(struct vivid_dev *dev)
-{
- if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
- return tpg_g_ycbcr_enc(&dev->tpg);
- return dev->ycbcr_enc_out;
-}
-
-static unsigned int vivid_hsv_enc_cap(struct vivid_dev *dev)
-{
- if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
- return tpg_g_hsv_enc(&dev->tpg);
- return dev->hsv_enc_out;
-}
-
-static unsigned vivid_quantization_cap(struct vivid_dev *dev)
-{
- if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
- return tpg_g_quantization(&dev->tpg);
- return dev->quantization_out;
-}
-
-int vivid_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
- unsigned p;
-
- mp->width = dev->fmt_cap_rect.width;
- mp->height = dev->fmt_cap_rect.height;
- mp->field = dev->field_cap;
- mp->pixelformat = dev->fmt_cap->fourcc;
- mp->colorspace = vivid_colorspace_cap(dev);
- mp->xfer_func = vivid_xfer_func_cap(dev);
- if (dev->fmt_cap->color_enc == TGP_COLOR_ENC_HSV)
- mp->hsv_enc = vivid_hsv_enc_cap(dev);
- else
- mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
- mp->quantization = vivid_quantization_cap(dev);
- mp->num_planes = dev->fmt_cap->buffers;
- for (p = 0; p < mp->num_planes; p++) {
- mp->plane_fmt[p].bytesperline = tpg_g_bytesperline(&dev->tpg, p);
- mp->plane_fmt[p].sizeimage =
- (tpg_g_line_width(&dev->tpg, p) * mp->height) /
- dev->fmt_cap->vdownsampling[p] +
- dev->fmt_cap->data_offset[p];
- }
- return 0;
-}
-
-int vivid_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
- struct v4l2_plane_pix_format *pfmt = mp->plane_fmt;
- struct vivid_dev *dev = video_drvdata(file);
- const struct vivid_fmt *fmt;
- unsigned bytesperline, max_bpl;
- unsigned factor = 1;
- unsigned w, h;
- unsigned p;
-
- fmt = vivid_get_format(dev, mp->pixelformat);
- if (!fmt) {
- dprintk(dev, 1, "Fourcc format (0x%08x) unknown.\n",
- mp->pixelformat);
- mp->pixelformat = V4L2_PIX_FMT_YUYV;
- fmt = vivid_get_format(dev, mp->pixelformat);
- }
-
- mp->field = vivid_field_cap(dev, mp->field);
- if (vivid_is_webcam(dev)) {
- const struct v4l2_frmsize_discrete *sz =
- v4l2_find_nearest_size(webcam_sizes,
- VIVID_WEBCAM_SIZES, width,
- height, mp->width, mp->height);
-
- w = sz->width;
- h = sz->height;
- } else if (vivid_is_sdtv_cap(dev)) {
- w = 720;
- h = (dev->std_cap[dev->input] & V4L2_STD_525_60) ? 480 : 576;
- } else {
- w = dev->src_rect.width;
- h = dev->src_rect.height;
- }
- if (V4L2_FIELD_HAS_T_OR_B(mp->field))
- factor = 2;
- if (vivid_is_webcam(dev) ||
- (!dev->has_scaler_cap && !dev->has_crop_cap && !dev->has_compose_cap)) {
- mp->width = w;
- mp->height = h / factor;
- } else {
- struct v4l2_rect r = { 0, 0, mp->width, mp->height * factor };
-
- v4l2_rect_set_min_size(&r, &vivid_min_rect);
- v4l2_rect_set_max_size(&r, &vivid_max_rect);
- if (dev->has_scaler_cap && !dev->has_compose_cap) {
- struct v4l2_rect max_r = { 0, 0, MAX_ZOOM * w, MAX_ZOOM * h };
-
- v4l2_rect_set_max_size(&r, &max_r);
- } else if (!dev->has_scaler_cap && dev->has_crop_cap && !dev->has_compose_cap) {
- v4l2_rect_set_max_size(&r, &dev->src_rect);
- } else if (!dev->has_scaler_cap && !dev->has_crop_cap) {
- v4l2_rect_set_min_size(&r, &dev->src_rect);
- }
- mp->width = r.width;
- mp->height = r.height / factor;
- }
-
- /* This driver supports custom bytesperline values */
-
- mp->num_planes = fmt->buffers;
- for (p = 0; p < fmt->buffers; p++) {
- /* Calculate the minimum supported bytesperline value */
- bytesperline = (mp->width * fmt->bit_depth[p]) >> 3;
- /* Calculate the maximum supported bytesperline value */
- max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[p]) >> 3;
-
- if (pfmt[p].bytesperline > max_bpl)
- pfmt[p].bytesperline = max_bpl;
- if (pfmt[p].bytesperline < bytesperline)
- pfmt[p].bytesperline = bytesperline;
-
- pfmt[p].sizeimage = (pfmt[p].bytesperline * mp->height) /
- fmt->vdownsampling[p] + fmt->data_offset[p];
-
- memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
- }
- for (p = fmt->buffers; p < fmt->planes; p++)
- pfmt[0].sizeimage += (pfmt[0].bytesperline * mp->height *
- (fmt->bit_depth[p] / fmt->vdownsampling[p])) /
- (fmt->bit_depth[0] / fmt->vdownsampling[0]);
-
- mp->colorspace = vivid_colorspace_cap(dev);
- if (fmt->color_enc == TGP_COLOR_ENC_HSV)
- mp->hsv_enc = vivid_hsv_enc_cap(dev);
- else
- mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
- mp->xfer_func = vivid_xfer_func_cap(dev);
- mp->quantization = vivid_quantization_cap(dev);
- memset(mp->reserved, 0, sizeof(mp->reserved));
- return 0;
-}
-
-int vivid_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_rect *crop = &dev->crop_cap;
- struct v4l2_rect *compose = &dev->compose_cap;
- struct vb2_queue *q = &dev->vb_vid_cap_q;
- int ret = vivid_try_fmt_vid_cap(file, priv, f);
- unsigned factor = 1;
- unsigned p;
- unsigned i;
-
- if (ret < 0)
- return ret;
-
- if (vb2_is_busy(q)) {
- dprintk(dev, 1, "%s device busy\n", __func__);
- 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;
-
- /* Note: the webcam input doesn't support scaling, cropping or composing */
-
- if (!vivid_is_webcam(dev) &&
- (dev->has_scaler_cap || dev->has_crop_cap || dev->has_compose_cap)) {
- struct v4l2_rect r = { 0, 0, mp->width, mp->height };
-
- if (dev->has_scaler_cap) {
- if (dev->has_compose_cap)
- v4l2_rect_map_inside(compose, &r);
- else
- *compose = r;
- if (dev->has_crop_cap && !dev->has_compose_cap) {
- struct v4l2_rect min_r = {
- 0, 0,
- r.width / MAX_ZOOM,
- factor * r.height / MAX_ZOOM
- };
- struct v4l2_rect max_r = {
- 0, 0,
- r.width * MAX_ZOOM,
- factor * r.height * MAX_ZOOM
- };
-
- v4l2_rect_set_min_size(crop, &min_r);
- v4l2_rect_set_max_size(crop, &max_r);
- v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
- } else if (dev->has_crop_cap) {
- struct v4l2_rect min_r = {
- 0, 0,
- compose->width / MAX_ZOOM,
- factor * compose->height / MAX_ZOOM
- };
- struct v4l2_rect max_r = {
- 0, 0,
- compose->width * MAX_ZOOM,
- factor * compose->height * MAX_ZOOM
- };
-
- v4l2_rect_set_min_size(crop, &min_r);
- v4l2_rect_set_max_size(crop, &max_r);
- v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
- }
- } else if (dev->has_crop_cap && !dev->has_compose_cap) {
- r.height *= factor;
- v4l2_rect_set_size_to(crop, &r);
- v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
- r = *crop;
- r.height /= factor;
- v4l2_rect_set_size_to(compose, &r);
- } else if (!dev->has_crop_cap) {
- v4l2_rect_map_inside(compose, &r);
- } else {
- r.height *= factor;
- v4l2_rect_set_max_size(crop, &r);
- v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
- compose->top *= factor;
- compose->height *= factor;
- v4l2_rect_set_size_to(compose, crop);
- v4l2_rect_map_inside(compose, &r);
- compose->top /= factor;
- compose->height /= factor;
- }
- } else if (vivid_is_webcam(dev)) {
- /* Guaranteed to be a match */
- for (i = 0; i < ARRAY_SIZE(webcam_sizes); i++)
- if (webcam_sizes[i].width == mp->width &&
- webcam_sizes[i].height == mp->height)
- break;
- dev->webcam_size_idx = i;
- if (dev->webcam_ival_idx >= 2 * (VIVID_WEBCAM_SIZES - i))
- dev->webcam_ival_idx = 2 * (VIVID_WEBCAM_SIZES - i) - 1;
- vivid_update_format_cap(dev, false);
- } else {
- struct v4l2_rect r = { 0, 0, mp->width, mp->height };
-
- v4l2_rect_set_size_to(compose, &r);
- r.height *= factor;
- v4l2_rect_set_size_to(crop, &r);
- }
-
- dev->fmt_cap_rect.width = mp->width;
- dev->fmt_cap_rect.height = mp->height;
- tpg_s_buf_height(&dev->tpg, mp->height);
- tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
- for (p = 0; p < tpg_g_buffers(&dev->tpg); p++)
- tpg_s_bytesperline(&dev->tpg, p, mp->plane_fmt[p].bytesperline);
- dev->field_cap = mp->field;
- if (dev->field_cap == V4L2_FIELD_ALTERNATE)
- tpg_s_field(&dev->tpg, V4L2_FIELD_TOP, true);
- else
- tpg_s_field(&dev->tpg, dev->field_cap, false);
- tpg_s_crop_compose(&dev->tpg, &dev->crop_cap, &dev->compose_cap);
- if (vivid_is_sdtv_cap(dev))
- dev->tv_field_cap = mp->field;
- tpg_update_mv_step(&dev->tpg);
- return 0;
-}
-
-int vidioc_g_fmt_vid_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!dev->multiplanar)
- return -ENOTTY;
- return vivid_g_fmt_vid_cap(file, priv, f);
-}
-
-int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!dev->multiplanar)
- return -ENOTTY;
- return vivid_try_fmt_vid_cap(file, priv, f);
-}
-
-int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!dev->multiplanar)
- return -ENOTTY;
- return vivid_s_fmt_vid_cap(file, priv, f);
-}
-
-int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (dev->multiplanar)
- return -ENOTTY;
- return fmt_sp2mp_func(file, priv, f, vivid_g_fmt_vid_cap);
-}
-
-int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (dev->multiplanar)
- return -ENOTTY;
- return fmt_sp2mp_func(file, priv, f, vivid_try_fmt_vid_cap);
-}
-
-int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (dev->multiplanar)
- return -ENOTTY;
- return fmt_sp2mp_func(file, priv, f, vivid_s_fmt_vid_cap);
-}
-
-int vivid_vid_cap_g_selection(struct file *file, void *priv,
- struct v4l2_selection *sel)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!dev->has_crop_cap && !dev->has_compose_cap)
- return -ENOTTY;
- if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (vivid_is_webcam(dev))
- return -ENODATA;
-
- sel->r.left = sel->r.top = 0;
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP:
- if (!dev->has_crop_cap)
- return -EINVAL;
- sel->r = dev->crop_cap;
- break;
- case V4L2_SEL_TGT_CROP_DEFAULT:
- case V4L2_SEL_TGT_CROP_BOUNDS:
- if (!dev->has_crop_cap)
- return -EINVAL;
- sel->r = dev->src_rect;
- break;
- case V4L2_SEL_TGT_COMPOSE_BOUNDS:
- if (!dev->has_compose_cap)
- return -EINVAL;
- sel->r = vivid_max_rect;
- break;
- case V4L2_SEL_TGT_COMPOSE:
- if (!dev->has_compose_cap)
- return -EINVAL;
- sel->r = dev->compose_cap;
- break;
- case V4L2_SEL_TGT_COMPOSE_DEFAULT:
- if (!dev->has_compose_cap)
- return -EINVAL;
- sel->r = dev->fmt_cap_rect;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_rect *crop = &dev->crop_cap;
- struct v4l2_rect *compose = &dev->compose_cap;
- unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
- int ret;
-
- if (!dev->has_crop_cap && !dev->has_compose_cap)
- return -ENOTTY;
- if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (vivid_is_webcam(dev))
- return -ENODATA;
-
- switch (s->target) {
- case V4L2_SEL_TGT_CROP:
- if (!dev->has_crop_cap)
- return -EINVAL;
- ret = vivid_vid_adjust_sel(s->flags, &s->r);
- if (ret)
- return ret;
- v4l2_rect_set_min_size(&s->r, &vivid_min_rect);
- v4l2_rect_set_max_size(&s->r, &dev->src_rect);
- v4l2_rect_map_inside(&s->r, &dev->crop_bounds_cap);
- s->r.top /= factor;
- s->r.height /= factor;
- if (dev->has_scaler_cap) {
- struct v4l2_rect fmt = dev->fmt_cap_rect;
- struct v4l2_rect max_rect = {
- 0, 0,
- s->r.width * MAX_ZOOM,
- s->r.height * MAX_ZOOM
- };
- struct v4l2_rect min_rect = {
- 0, 0,
- s->r.width / MAX_ZOOM,
- s->r.height / MAX_ZOOM
- };
-
- v4l2_rect_set_min_size(&fmt, &min_rect);
- if (!dev->has_compose_cap)
- v4l2_rect_set_max_size(&fmt, &max_rect);
- if (!v4l2_rect_same_size(&dev->fmt_cap_rect, &fmt) &&
- vb2_is_busy(&dev->vb_vid_cap_q))
- return -EBUSY;
- if (dev->has_compose_cap) {
- v4l2_rect_set_min_size(compose, &min_rect);
- v4l2_rect_set_max_size(compose, &max_rect);
- }
- dev->fmt_cap_rect = fmt;
- tpg_s_buf_height(&dev->tpg, fmt.height);
- } else if (dev->has_compose_cap) {
- struct v4l2_rect fmt = dev->fmt_cap_rect;
-
- v4l2_rect_set_min_size(&fmt, &s->r);
- if (!v4l2_rect_same_size(&dev->fmt_cap_rect, &fmt) &&
- vb2_is_busy(&dev->vb_vid_cap_q))
- return -EBUSY;
- dev->fmt_cap_rect = fmt;
- tpg_s_buf_height(&dev->tpg, fmt.height);
- v4l2_rect_set_size_to(compose, &s->r);
- v4l2_rect_map_inside(compose, &dev->fmt_cap_rect);
- } else {
- if (!v4l2_rect_same_size(&s->r, &dev->fmt_cap_rect) &&
- vb2_is_busy(&dev->vb_vid_cap_q))
- return -EBUSY;
- v4l2_rect_set_size_to(&dev->fmt_cap_rect, &s->r);
- v4l2_rect_set_size_to(compose, &s->r);
- v4l2_rect_map_inside(compose, &dev->fmt_cap_rect);
- tpg_s_buf_height(&dev->tpg, dev->fmt_cap_rect.height);
- }
- s->r.top *= factor;
- s->r.height *= factor;
- *crop = s->r;
- break;
- case V4L2_SEL_TGT_COMPOSE:
- if (!dev->has_compose_cap)
- return -EINVAL;
- ret = vivid_vid_adjust_sel(s->flags, &s->r);
- if (ret)
- return ret;
- v4l2_rect_set_min_size(&s->r, &vivid_min_rect);
- v4l2_rect_set_max_size(&s->r, &dev->fmt_cap_rect);
- if (dev->has_scaler_cap) {
- struct v4l2_rect max_rect = {
- 0, 0,
- dev->src_rect.width * MAX_ZOOM,
- (dev->src_rect.height / factor) * MAX_ZOOM
- };
-
- v4l2_rect_set_max_size(&s->r, &max_rect);
- if (dev->has_crop_cap) {
- struct v4l2_rect min_rect = {
- 0, 0,
- s->r.width / MAX_ZOOM,
- (s->r.height * factor) / MAX_ZOOM
- };
- struct v4l2_rect max_rect = {
- 0, 0,
- s->r.width * MAX_ZOOM,
- (s->r.height * factor) * MAX_ZOOM
- };
-
- v4l2_rect_set_min_size(crop, &min_rect);
- v4l2_rect_set_max_size(crop, &max_rect);
- v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
- }
- } else if (dev->has_crop_cap) {
- s->r.top *= factor;
- s->r.height *= factor;
- v4l2_rect_set_max_size(&s->r, &dev->src_rect);
- v4l2_rect_set_size_to(crop, &s->r);
- v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
- s->r.top /= factor;
- s->r.height /= factor;
- } else {
- v4l2_rect_set_size_to(&s->r, &dev->src_rect);
- s->r.height /= factor;
- }
- v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect);
- if (dev->bitmap_cap && (compose->width != s->r.width ||
- compose->height != s->r.height)) {
- vfree(dev->bitmap_cap);
- dev->bitmap_cap = NULL;
- }
- *compose = s->r;
- break;
- default:
- return -EINVAL;
- }
-
- tpg_s_crop_compose(&dev->tpg, crop, compose);
- return 0;
-}
-
-int vivid_vid_cap_g_pixelaspect(struct file *file, void *priv,
- int type, struct v4l2_fract *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- switch (vivid_get_pixel_aspect(dev)) {
- case TPG_PIXEL_ASPECT_NTSC:
- f->numerator = 11;
- f->denominator = 10;
- break;
- case TPG_PIXEL_ASPECT_PAL:
- f->numerator = 54;
- f->denominator = 59;
- break;
- default:
- break;
- }
- 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) {
- if (copy_to_user(win->clips, dev->clips_cap,
- clipcount * sizeof(dev->clips_cap[0])))
- return -EFAULT;
- }
- 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) {
- if (copy_from_user(dev->try_clips_cap, win->clips,
- win->clipcount * sizeof(dev->clips_cap[0])))
- return -EFAULT;
- 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;
- }
- }
- if (copy_to_user(win->clips, dev->try_clips_cap,
- win->clipcount * sizeof(dev->clips_cap[0])))
- return -EFAULT;
- }
- 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.height * a->fmt.bytesperline < a->fmt.sizeimage)
- 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 },
-};
-
-int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *inp)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (inp->index >= dev->num_inputs)
- return -EINVAL;
-
- inp->type = V4L2_INPUT_TYPE_CAMERA;
- switch (dev->input_type[inp->index]) {
- case WEBCAM:
- snprintf(inp->name, sizeof(inp->name), "Webcam %u",
- dev->input_name_counter[inp->index]);
- inp->capabilities = 0;
- break;
- case TV:
- snprintf(inp->name, sizeof(inp->name), "TV %u",
- dev->input_name_counter[inp->index]);
- inp->type = V4L2_INPUT_TYPE_TUNER;
- inp->std = V4L2_STD_ALL;
- if (dev->has_audio_inputs)
- inp->audioset = (1 << ARRAY_SIZE(vivid_audio_inputs)) - 1;
- inp->capabilities = V4L2_IN_CAP_STD;
- break;
- case SVID:
- snprintf(inp->name, sizeof(inp->name), "S-Video %u",
- dev->input_name_counter[inp->index]);
- inp->std = V4L2_STD_ALL;
- if (dev->has_audio_inputs)
- inp->audioset = (1 << ARRAY_SIZE(vivid_audio_inputs)) - 1;
- inp->capabilities = V4L2_IN_CAP_STD;
- break;
- case HDMI:
- snprintf(inp->name, sizeof(inp->name), "HDMI %u",
- dev->input_name_counter[inp->index]);
- inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
- if (dev->edid_blocks == 0 ||
- dev->dv_timings_signal_mode[dev->input] == NO_SIGNAL)
- inp->status |= V4L2_IN_ST_NO_SIGNAL;
- else if (dev->dv_timings_signal_mode[dev->input] == NO_LOCK ||
- dev->dv_timings_signal_mode[dev->input] == OUT_OF_RANGE)
- inp->status |= V4L2_IN_ST_NO_H_LOCK;
- break;
- }
- if (dev->sensor_hflip)
- inp->status |= V4L2_IN_ST_HFLIP;
- if (dev->sensor_vflip)
- inp->status |= V4L2_IN_ST_VFLIP;
- if (dev->input == inp->index && vivid_is_sdtv_cap(dev)) {
- if (dev->std_signal_mode[dev->input] == NO_SIGNAL) {
- inp->status |= V4L2_IN_ST_NO_SIGNAL;
- } else if (dev->std_signal_mode[dev->input] == NO_LOCK) {
- inp->status |= V4L2_IN_ST_NO_H_LOCK;
- } else if (vivid_is_tv_cap(dev)) {
- switch (tpg_g_quality(&dev->tpg)) {
- case TPG_QUAL_GRAY:
- inp->status |= V4L2_IN_ST_COLOR_KILL;
- break;
- case TPG_QUAL_NOISE:
- inp->status |= V4L2_IN_ST_NO_H_LOCK;
- break;
- default:
- break;
- }
- }
- }
- return 0;
-}
-
-int vidioc_g_input(struct file *file, void *priv, unsigned *i)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- *i = dev->input;
- return 0;
-}
-
-int vidioc_s_input(struct file *file, void *priv, unsigned i)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
- unsigned brightness;
-
- if (i >= dev->num_inputs)
- return -EINVAL;
-
- if (i == dev->input)
- return 0;
-
- if (vb2_is_busy(&dev->vb_vid_cap_q) ||
- vb2_is_busy(&dev->vb_vbi_cap_q) ||
- vb2_is_busy(&dev->vb_meta_cap_q))
- return -EBUSY;
-
- dev->input = i;
- dev->vid_cap_dev.tvnorms = 0;
- if (dev->input_type[i] == TV || dev->input_type[i] == SVID) {
- dev->tv_audio_input = (dev->input_type[i] == TV) ? 0 : 1;
- dev->vid_cap_dev.tvnorms = V4L2_STD_ALL;
- }
- dev->vbi_cap_dev.tvnorms = dev->vid_cap_dev.tvnorms;
- dev->meta_cap_dev.tvnorms = dev->vid_cap_dev.tvnorms;
- vivid_update_format_cap(dev, false);
-
- if (dev->colorspace) {
- switch (dev->input_type[i]) {
- case WEBCAM:
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_SRGB);
- break;
- case TV:
- case SVID:
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
- break;
- case HDMI:
- if (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) {
- if (dev->src_rect.width == 720 && dev->src_rect.height <= 576)
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
- else
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_709);
- } else {
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_SRGB);
- }
- break;
- }
- }
-
- /*
- * Modify the brightness range depending on the input.
- * This makes it easy to use vivid to test if applications can
- * handle control range modifications and is also how this is
- * typically used in practice as different inputs may be hooked
- * up to different receivers with different control ranges.
- */
- brightness = 128 * i + dev->input_brightness[i];
- v4l2_ctrl_modify_range(dev->brightness,
- 128 * i, 255 + 128 * i, 1, 128 + 128 * i);
- v4l2_ctrl_s_ctrl(dev->brightness, brightness);
-
- /* Restore per-input states. */
- v4l2_ctrl_activate(dev->ctrl_dv_timings_signal_mode,
- vivid_is_hdmi_cap(dev));
- v4l2_ctrl_activate(dev->ctrl_dv_timings, vivid_is_hdmi_cap(dev) &&
- dev->dv_timings_signal_mode[dev->input] ==
- SELECTED_DV_TIMINGS);
- v4l2_ctrl_activate(dev->ctrl_std_signal_mode, vivid_is_sdtv_cap(dev));
- v4l2_ctrl_activate(dev->ctrl_standard, vivid_is_sdtv_cap(dev) &&
- dev->std_signal_mode[dev->input]);
-
- if (vivid_is_hdmi_cap(dev)) {
- v4l2_ctrl_s_ctrl(dev->ctrl_dv_timings_signal_mode,
- dev->dv_timings_signal_mode[dev->input]);
- v4l2_ctrl_s_ctrl(dev->ctrl_dv_timings,
- dev->query_dv_timings[dev->input]);
- } else if (vivid_is_sdtv_cap(dev)) {
- v4l2_ctrl_s_ctrl(dev->ctrl_std_signal_mode,
- dev->std_signal_mode[dev->input]);
- v4l2_ctrl_s_ctrl(dev->ctrl_standard,
- dev->std_signal_mode[dev->input]);
- }
-
- return 0;
-}
-
-int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
-{
- if (vin->index >= ARRAY_SIZE(vivid_audio_inputs))
- return -EINVAL;
- *vin = vivid_audio_inputs[vin->index];
- return 0;
-}
-
-int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_sdtv_cap(dev))
- return -EINVAL;
- *vin = vivid_audio_inputs[dev->tv_audio_input];
- return 0;
-}
-
-int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *vin)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_sdtv_cap(dev))
- return -EINVAL;
- if (vin->index >= ARRAY_SIZE(vivid_audio_inputs))
- return -EINVAL;
- dev->tv_audio_input = vin->index;
- return 0;
-}
-
-int vivid_video_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (vf->tuner != 0)
- return -EINVAL;
- vf->frequency = dev->tv_freq;
- return 0;
-}
-
-int vivid_video_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (vf->tuner != 0)
- return -EINVAL;
- dev->tv_freq = clamp_t(unsigned, vf->frequency, MIN_TV_FREQ, MAX_TV_FREQ);
- if (vivid_is_tv_cap(dev))
- vivid_update_quality(dev);
- return 0;
-}
-
-int vivid_video_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (vt->index != 0)
- return -EINVAL;
- if (vt->audmode > V4L2_TUNER_MODE_LANG1_LANG2)
- return -EINVAL;
- dev->tv_audmode = vt->audmode;
- return 0;
-}
-
-int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
-{
- struct vivid_dev *dev = video_drvdata(file);
- enum tpg_quality qual;
-
- if (vt->index != 0)
- return -EINVAL;
-
- vt->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
- V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
- vt->audmode = dev->tv_audmode;
- vt->rangelow = MIN_TV_FREQ;
- vt->rangehigh = MAX_TV_FREQ;
- qual = vivid_get_quality(dev, &vt->afc);
- if (qual == TPG_QUAL_COLOR)
- vt->signal = 0xffff;
- else if (qual == TPG_QUAL_GRAY)
- vt->signal = 0x8000;
- else
- vt->signal = 0;
- if (qual == TPG_QUAL_NOISE) {
- vt->rxsubchans = 0;
- } else if (qual == TPG_QUAL_GRAY) {
- vt->rxsubchans = V4L2_TUNER_SUB_MONO;
- } else {
- unsigned int channel_nr = dev->tv_freq / (6 * 16);
- unsigned int options =
- (dev->std_cap[dev->input] & V4L2_STD_NTSC_M) ? 4 : 3;
-
- switch (channel_nr % options) {
- case 0:
- vt->rxsubchans = V4L2_TUNER_SUB_MONO;
- break;
- case 1:
- vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
- break;
- case 2:
- if (dev->std_cap[dev->input] & V4L2_STD_NTSC_M)
- vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_SAP;
- else
- vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
- break;
- case 3:
- vt->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_SAP;
- break;
- }
- }
- strscpy(vt->name, "TV Tuner", sizeof(vt->name));
- return 0;
-}
-
-/* Must remain in sync with the vivid_ctrl_standard_strings array */
-const v4l2_std_id vivid_standard[] = {
- V4L2_STD_NTSC_M,
- V4L2_STD_NTSC_M_JP,
- V4L2_STD_NTSC_M_KR,
- V4L2_STD_NTSC_443,
- V4L2_STD_PAL_BG | V4L2_STD_PAL_H,
- V4L2_STD_PAL_I,
- V4L2_STD_PAL_DK,
- V4L2_STD_PAL_M,
- V4L2_STD_PAL_N,
- V4L2_STD_PAL_Nc,
- V4L2_STD_PAL_60,
- V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
- V4L2_STD_SECAM_DK,
- V4L2_STD_SECAM_L,
- V4L2_STD_SECAM_LC,
- V4L2_STD_UNKNOWN
-};
-
-/* Must remain in sync with the vivid_standard array */
-const char * const vivid_ctrl_standard_strings[] = {
- "NTSC-M",
- "NTSC-M-JP",
- "NTSC-M-KR",
- "NTSC-443",
- "PAL-BGH",
- "PAL-I",
- "PAL-DK",
- "PAL-M",
- "PAL-N",
- "PAL-Nc",
- "PAL-60",
- "SECAM-BGH",
- "SECAM-DK",
- "SECAM-L",
- "SECAM-Lc",
- NULL,
-};
-
-int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *id)
-{
- struct vivid_dev *dev = video_drvdata(file);
- unsigned int last = dev->query_std_last[dev->input];
-
- if (!vivid_is_sdtv_cap(dev))
- return -ENODATA;
- if (dev->std_signal_mode[dev->input] == NO_SIGNAL ||
- dev->std_signal_mode[dev->input] == NO_LOCK) {
- *id = V4L2_STD_UNKNOWN;
- return 0;
- }
- if (vivid_is_tv_cap(dev) && tpg_g_quality(&dev->tpg) == TPG_QUAL_NOISE) {
- *id = V4L2_STD_UNKNOWN;
- } else if (dev->std_signal_mode[dev->input] == CURRENT_STD) {
- *id = dev->std_cap[dev->input];
- } else if (dev->std_signal_mode[dev->input] == SELECTED_STD) {
- *id = dev->query_std[dev->input];
- } else {
- *id = vivid_standard[last];
- dev->query_std_last[dev->input] =
- (last + 1) % ARRAY_SIZE(vivid_standard);
- }
-
- return 0;
-}
-
-int vivid_vid_cap_s_std(struct file *file, void *priv, v4l2_std_id id)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_sdtv_cap(dev))
- return -ENODATA;
- if (dev->std_cap[dev->input] == id)
- return 0;
- if (vb2_is_busy(&dev->vb_vid_cap_q) || vb2_is_busy(&dev->vb_vbi_cap_q))
- return -EBUSY;
- dev->std_cap[dev->input] = id;
- vivid_update_format_cap(dev, false);
- return 0;
-}
-
-static void find_aspect_ratio(u32 width, u32 height,
- u32 *num, u32 *denom)
-{
- if (!(height % 3) && ((height * 4 / 3) == width)) {
- *num = 4;
- *denom = 3;
- } else if (!(height % 9) && ((height * 16 / 9) == width)) {
- *num = 16;
- *denom = 9;
- } else if (!(height % 10) && ((height * 16 / 10) == width)) {
- *num = 16;
- *denom = 10;
- } else if (!(height % 4) && ((height * 5 / 4) == width)) {
- *num = 5;
- *denom = 4;
- } else if (!(height % 9) && ((height * 15 / 9) == width)) {
- *num = 15;
- *denom = 9;
- } else { /* default to 16:9 */
- *num = 16;
- *denom = 9;
- }
-}
-
-static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings)
-{
- struct v4l2_bt_timings *bt = &timings->bt;
- u32 total_h_pixel;
- u32 total_v_lines;
- u32 h_freq;
-
- if (!v4l2_valid_dv_timings(timings, &vivid_dv_timings_cap,
- NULL, NULL))
- return false;
-
- total_h_pixel = V4L2_DV_BT_FRAME_WIDTH(bt);
- total_v_lines = V4L2_DV_BT_FRAME_HEIGHT(bt);
-
- h_freq = (u32)bt->pixelclock / total_h_pixel;
-
- if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_CVT)) {
- if (v4l2_detect_cvt(total_v_lines, h_freq, bt->vsync, bt->width,
- bt->polarities, bt->interlaced, timings))
- return true;
- }
-
- if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_GTF)) {
- struct v4l2_fract aspect_ratio;
-
- find_aspect_ratio(bt->width, bt->height,
- &aspect_ratio.numerator,
- &aspect_ratio.denominator);
- if (v4l2_detect_gtf(total_v_lines, h_freq, bt->vsync,
- bt->polarities, bt->interlaced,
- aspect_ratio, timings))
- return true;
- }
- return false;
-}
-
-int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh,
- struct v4l2_dv_timings *timings)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_hdmi_cap(dev))
- return -ENODATA;
- if (!v4l2_find_dv_timings_cap(timings, &vivid_dv_timings_cap,
- 0, NULL, NULL) &&
- !valid_cvt_gtf_timings(timings))
- return -EINVAL;
-
- if (v4l2_match_dv_timings(timings, &dev->dv_timings_cap[dev->input],
- 0, false))
- return 0;
- if (vb2_is_busy(&dev->vb_vid_cap_q))
- return -EBUSY;
-
- dev->dv_timings_cap[dev->input] = *timings;
- vivid_update_format_cap(dev, false);
- return 0;
-}
-
-int vidioc_query_dv_timings(struct file *file, void *_fh,
- struct v4l2_dv_timings *timings)
-{
- struct vivid_dev *dev = video_drvdata(file);
- unsigned int input = dev->input;
- unsigned int last = dev->query_dv_timings_last[input];
-
- if (!vivid_is_hdmi_cap(dev))
- return -ENODATA;
- if (dev->dv_timings_signal_mode[input] == NO_SIGNAL ||
- dev->edid_blocks == 0)
- return -ENOLINK;
- if (dev->dv_timings_signal_mode[input] == NO_LOCK)
- return -ENOLCK;
- if (dev->dv_timings_signal_mode[input] == OUT_OF_RANGE) {
- timings->bt.pixelclock = vivid_dv_timings_cap.bt.max_pixelclock * 2;
- return -ERANGE;
- }
- if (dev->dv_timings_signal_mode[input] == CURRENT_DV_TIMINGS) {
- *timings = dev->dv_timings_cap[input];
- } else if (dev->dv_timings_signal_mode[input] ==
- SELECTED_DV_TIMINGS) {
- *timings =
- v4l2_dv_timings_presets[dev->query_dv_timings[input]];
- } else {
- *timings =
- v4l2_dv_timings_presets[last];
- dev->query_dv_timings_last[input] =
- (last + 1) % dev->query_dv_timings_size;
- }
- return 0;
-}
-
-int vidioc_s_edid(struct file *file, void *_fh,
- struct v4l2_edid *edid)
-{
- struct vivid_dev *dev = video_drvdata(file);
- u16 phys_addr;
- u32 display_present = 0;
- unsigned int i, j;
- int ret;
-
- memset(edid->reserved, 0, sizeof(edid->reserved));
- if (edid->pad >= dev->num_inputs)
- return -EINVAL;
- if (dev->input_type[edid->pad] != HDMI || edid->start_block)
- return -EINVAL;
- if (edid->blocks == 0) {
- dev->edid_blocks = 0;
- v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, 0);
- v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug, 0);
- phys_addr = CEC_PHYS_ADDR_INVALID;
- goto set_phys_addr;
- }
- if (edid->blocks > dev->edid_max_blocks) {
- edid->blocks = dev->edid_max_blocks;
- return -E2BIG;
- }
- phys_addr = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, NULL);
- ret = v4l2_phys_addr_validate(phys_addr, &phys_addr, NULL);
- if (ret)
- return ret;
-
- if (vb2_is_busy(&dev->vb_vid_cap_q))
- return -EBUSY;
-
- dev->edid_blocks = edid->blocks;
- memcpy(dev->edid, edid->edid, edid->blocks * 128);
-
- for (i = 0, j = 0; i < dev->num_outputs; i++)
- if (dev->output_type[i] == HDMI)
- display_present |=
- dev->display_present[i] << j++;
-
- v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, display_present);
- v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug, display_present);
-
-set_phys_addr:
- /* TODO: a proper hotplug detect cycle should be emulated here */
- cec_s_phys_addr(dev->cec_rx_adap, phys_addr, false);
-
- for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
- cec_s_phys_addr(dev->cec_tx_adap[i],
- dev->display_present[i] ?
- v4l2_phys_addr_for_input(phys_addr, i + 1) :
- CEC_PHYS_ADDR_INVALID,
- false);
- return 0;
-}
-
-int vidioc_enum_framesizes(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_webcam(dev) && !dev->has_scaler_cap)
- return -EINVAL;
- if (vivid_get_format(dev, fsize->pixel_format) == NULL)
- return -EINVAL;
- if (vivid_is_webcam(dev)) {
- if (fsize->index >= ARRAY_SIZE(webcam_sizes))
- return -EINVAL;
- fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
- fsize->discrete = webcam_sizes[fsize->index];
- return 0;
- }
- if (fsize->index)
- return -EINVAL;
- fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
- fsize->stepwise.min_width = MIN_WIDTH;
- fsize->stepwise.max_width = MAX_WIDTH * MAX_ZOOM;
- fsize->stepwise.step_width = 2;
- fsize->stepwise.min_height = MIN_HEIGHT;
- fsize->stepwise.max_height = MAX_HEIGHT * MAX_ZOOM;
- fsize->stepwise.step_height = 2;
- return 0;
-}
-
-/* timeperframe is arbitrary and continuous */
-int vidioc_enum_frameintervals(struct file *file, void *priv,
- struct v4l2_frmivalenum *fival)
-{
- struct vivid_dev *dev = video_drvdata(file);
- const struct vivid_fmt *fmt;
- int i;
-
- fmt = vivid_get_format(dev, fival->pixel_format);
- if (!fmt)
- return -EINVAL;
-
- if (!vivid_is_webcam(dev)) {
- if (fival->index)
- return -EINVAL;
- if (fival->width < MIN_WIDTH || fival->width > MAX_WIDTH * MAX_ZOOM)
- return -EINVAL;
- if (fival->height < MIN_HEIGHT || fival->height > MAX_HEIGHT * MAX_ZOOM)
- return -EINVAL;
- fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
- fival->discrete = dev->timeperframe_vid_cap;
- return 0;
- }
-
- for (i = 0; i < ARRAY_SIZE(webcam_sizes); i++)
- if (fival->width == webcam_sizes[i].width &&
- fival->height == webcam_sizes[i].height)
- break;
- if (i == ARRAY_SIZE(webcam_sizes))
- return -EINVAL;
- if (fival->index >= 2 * (VIVID_WEBCAM_SIZES - i))
- return -EINVAL;
- fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
- fival->discrete = webcam_intervals[fival->index];
- return 0;
-}
-
-int vivid_vid_cap_g_parm(struct file *file, void *priv,
- struct v4l2_streamparm *parm)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (parm->type != (dev->multiplanar ?
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
- V4L2_BUF_TYPE_VIDEO_CAPTURE))
- return -EINVAL;
-
- parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- parm->parm.capture.timeperframe = dev->timeperframe_vid_cap;
- parm->parm.capture.readbuffers = 1;
- return 0;
-}
-
-int vivid_vid_cap_s_parm(struct file *file, void *priv,
- struct v4l2_streamparm *parm)
-{
- struct vivid_dev *dev = video_drvdata(file);
- unsigned ival_sz = 2 * (VIVID_WEBCAM_SIZES - dev->webcam_size_idx);
- struct v4l2_fract tpf;
- unsigned i;
-
- if (parm->type != (dev->multiplanar ?
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
- V4L2_BUF_TYPE_VIDEO_CAPTURE))
- return -EINVAL;
- if (!vivid_is_webcam(dev))
- return vivid_vid_cap_g_parm(file, priv, parm);
-
- tpf = parm->parm.capture.timeperframe;
-
- if (tpf.denominator == 0)
- tpf = webcam_intervals[ival_sz - 1];
- for (i = 0; i < ival_sz; i++)
- if (V4L2_FRACT_COMPARE(tpf, >=, webcam_intervals[i]))
- break;
- if (i == ival_sz)
- i = ival_sz - 1;
- dev->webcam_ival_idx = i;
- tpf = webcam_intervals[dev->webcam_ival_idx];
-
- /* resync the thread's timings */
- dev->cap_seq_resync = true;
- dev->timeperframe_vid_cap = tpf;
- parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- parm->parm.capture.timeperframe = tpf;
- parm->parm.capture.readbuffers = 1;
- return 0;
-}
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.h b/drivers/media/platform/vivid/vivid-vid-cap.h
deleted file mode 100644
index 1e422a59eeab..000000000000
--- a/drivers/media/platform/vivid/vivid-vid-cap.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-vid-cap.h - video capture support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_VID_CAP_H_
-#define _VIVID_VID_CAP_H_
-
-void vivid_update_quality(struct vivid_dev *dev);
-void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls);
-enum tpg_video_aspect vivid_get_video_aspect(const struct vivid_dev *dev);
-
-extern const v4l2_std_id vivid_standard[];
-extern const char * const vivid_ctrl_standard_strings[];
-
-extern const struct vb2_ops vivid_vid_cap_qops;
-
-int vivid_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_g_fmt_vid_cap_mplane(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_vid_cap_g_selection(struct file *file, void *priv, struct v4l2_selection *sel);
-int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection *s);
-int vivid_vid_cap_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f);
-int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_fmtdesc *f);
-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);
-int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin);
-int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *vin);
-int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *vin);
-int vivid_video_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
-int vivid_video_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf);
-int vivid_video_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *vt);
-int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt);
-int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *id);
-int vivid_vid_cap_s_std(struct file *file, void *priv, v4l2_std_id id);
-int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh, struct v4l2_dv_timings *timings);
-int vidioc_query_dv_timings(struct file *file, void *_fh, struct v4l2_dv_timings *timings);
-int vidioc_s_edid(struct file *file, void *_fh, struct v4l2_edid *edid);
-int vidioc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize);
-int vidioc_enum_frameintervals(struct file *file, void *priv, struct v4l2_frmivalenum *fival);
-int vivid_vid_cap_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parm);
-int vivid_vid_cap_s_parm(struct file *file, void *priv, struct v4l2_streamparm *parm);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
deleted file mode 100644
index 76b0be670ebb..000000000000
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ /dev/null
@@ -1,1035 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-vid-common.c - common video support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/videodev2.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-dv-timings.h>
-
-#include "vivid-core.h"
-#include "vivid-vid-common.h"
-
-const struct v4l2_dv_timings_cap vivid_dv_timings_cap = {
- .type = V4L2_DV_BT_656_1120,
- /* keep this initialization for compatibility with GCC < 4.4.6 */
- .reserved = { 0 },
- V4L2_INIT_BT_TIMINGS(16, MAX_WIDTH, 16, MAX_HEIGHT, 14000000, 775000000,
- V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
- V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF,
- V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED)
-};
-
-/* ------------------------------------------------------------------
- Basic structures
- ------------------------------------------------------------------*/
-
-struct vivid_fmt vivid_formats[] = {
- {
- .fourcc = V4L2_PIX_FMT_YUYV,
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 1,
- .buffers = 1,
- .data_offset = { PLANE0_DATA_OFFSET },
- },
- {
- .fourcc = V4L2_PIX_FMT_UYVY,
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_YVYU,
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_VYUY,
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV422P,
- .vdownsampling = { 1, 1, 1 },
- .bit_depth = { 8, 4, 4 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 3,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV420,
- .vdownsampling = { 1, 2, 2 },
- .bit_depth = { 8, 4, 4 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 3,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_YVU420,
- .vdownsampling = { 1, 2, 2 },
- .bit_depth = { 8, 4, 4 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 3,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV12,
- .vdownsampling = { 1, 2 },
- .bit_depth = { 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV21,
- .vdownsampling = { 1, 2 },
- .bit_depth = { 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV16,
- .vdownsampling = { 1, 1 },
- .bit_depth = { 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV61,
- .vdownsampling = { 1, 1 },
- .bit_depth = { 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV24,
- .vdownsampling = { 1, 1 },
- .bit_depth = { 8, 16 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV42,
- .vdownsampling = { 1, 1 },
- .bit_depth = { 8, 16 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV555, /* uuuvvvvv ayyyyyuu */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x8000,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV565, /* uuuvvvvv yyyyyuuu */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV444, /* uuuuvvvv aaaayyyy */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0xf000,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV32, /* ayuv */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x000000ff,
- },
- {
- .fourcc = V4L2_PIX_FMT_AYUV32,
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x000000ff,
- },
- {
- .fourcc = V4L2_PIX_FMT_XYUV32,
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_VUYA32,
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0xff000000,
- },
- {
- .fourcc = V4L2_PIX_FMT_VUYX32,
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_GREY,
- .vdownsampling = { 1 },
- .bit_depth = { 8 },
- .color_enc = TGP_COLOR_ENC_LUMA,
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_Y10,
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .color_enc = TGP_COLOR_ENC_LUMA,
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_Y12,
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .color_enc = TGP_COLOR_ENC_LUMA,
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_Y16,
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .color_enc = TGP_COLOR_ENC_LUMA,
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_Y16_BE,
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .color_enc = TGP_COLOR_ENC_LUMA,
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB332, /* rrrgggbb */
- .vdownsampling = { 1 },
- .bit_depth = { 8 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB444, /* ggggbbbb xxxxrrrr */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_XRGB444, /* ggggbbbb xxxxrrrr */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_ARGB444, /* ggggbbbb aaaarrrr */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x00f0,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGBX444, /* bbbbxxxx rrrrgggg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGBA444, /* bbbbaaaa rrrrgggg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x00f0,
- },
- {
- .fourcc = V4L2_PIX_FMT_XBGR444, /* ggggrrrr xxxxbbbb */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_ABGR444, /* ggggrrrr aaaabbbb */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x00f0,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGRX444, /* rrrrxxxx bbbbgggg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGRA444, /* rrrraaaa bbbbgggg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x00f0,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb xrrrrrgg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- },
- {
- .fourcc = V4L2_PIX_FMT_XRGB555, /* gggbbbbb xrrrrrgg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- },
- {
- .fourcc = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- .alpha_mask = 0x8000,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGBX555, /* ggbbbbbx rrrrrggg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGBA555, /* ggbbbbba rrrrrggg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- .alpha_mask = 0x8000,
- },
- {
- .fourcc = V4L2_PIX_FMT_XBGR555, /* gggrrrrr xbbbbbgg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- },
- {
- .fourcc = V4L2_PIX_FMT_ABGR555, /* gggrrrrr abbbbbgg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- .alpha_mask = 0x8000,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGRX555, /* ggrrrrrx bbbbbggg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGRA555, /* ggrrrrra bbbbbggg */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .can_do_overlay = true,
- .alpha_mask = 0x8000,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB555X, /* xrrrrrgg gggbbbbb */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_XRGB555X, /* xrrrrrgg gggbbbbb */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_ARGB555X, /* arrrrrgg gggbbbbb */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x0080,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
- .vdownsampling = { 1 },
- .bit_depth = { 24 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
- .vdownsampling = { 1 },
- .bit_depth = { 24 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGR666, /* bbbbbbgg ggggrrrr rrxxxxxx */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGB32, /* xrgb */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGR32, /* bgrx */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_XRGB32, /* xrgb */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_XBGR32, /* bgrx */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_ARGB32, /* argb */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x000000ff,
- },
- {
- .fourcc = V4L2_PIX_FMT_ABGR32, /* bgra */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0xff000000,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGBX32, /* rgbx */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGRX32, /* xbgr */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_RGBA32, /* rgba */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0x000000ff,
- },
- {
- .fourcc = V4L2_PIX_FMT_BGRA32, /* abgr */
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- .alpha_mask = 0xff000000,
- },
- {
- .fourcc = V4L2_PIX_FMT_SBGGR8, /* Bayer BG/GR */
- .vdownsampling = { 1 },
- .bit_depth = { 8 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SGBRG8, /* Bayer GB/RG */
- .vdownsampling = { 1 },
- .bit_depth = { 8 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SGRBG8, /* Bayer GR/BG */
- .vdownsampling = { 1 },
- .bit_depth = { 8 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SRGGB8, /* Bayer RG/GB */
- .vdownsampling = { 1 },
- .bit_depth = { 8 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SBGGR10, /* Bayer BG/GR */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SGBRG10, /* Bayer GB/RG */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SGRBG10, /* Bayer GR/BG */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SRGGB10, /* Bayer RG/GB */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SBGGR12, /* Bayer BG/GR */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SGBRG12, /* Bayer GB/RG */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SGRBG12, /* Bayer GR/BG */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SRGGB12, /* Bayer RG/GB */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SBGGR16, /* Bayer BG/GR */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SGBRG16, /* Bayer GB/RG */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SGRBG16, /* Bayer GR/BG */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_SRGGB16, /* Bayer RG/GB */
- .vdownsampling = { 1 },
- .bit_depth = { 16 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_HSV24, /* HSV 24bits */
- .color_enc = TGP_COLOR_ENC_HSV,
- .vdownsampling = { 1 },
- .bit_depth = { 24 },
- .planes = 1,
- .buffers = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_HSV32, /* HSV 32bits */
- .color_enc = TGP_COLOR_ENC_HSV,
- .vdownsampling = { 1 },
- .bit_depth = { 32 },
- .planes = 1,
- .buffers = 1,
- },
-
- /* Multiplanar formats */
-
- {
- .fourcc = V4L2_PIX_FMT_NV16M,
- .vdownsampling = { 1, 1 },
- .bit_depth = { 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 2,
- .data_offset = { PLANE0_DATA_OFFSET, 0 },
- },
- {
- .fourcc = V4L2_PIX_FMT_NV61M,
- .vdownsampling = { 1, 1 },
- .bit_depth = { 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 2,
- .data_offset = { 0, PLANE0_DATA_OFFSET },
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV420M,
- .vdownsampling = { 1, 2, 2 },
- .bit_depth = { 8, 4, 4 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 3,
- .buffers = 3,
- },
- {
- .fourcc = V4L2_PIX_FMT_YVU420M,
- .vdownsampling = { 1, 2, 2 },
- .bit_depth = { 8, 4, 4 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 3,
- .buffers = 3,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV12M,
- .vdownsampling = { 1, 2 },
- .bit_depth = { 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 2,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV21M,
- .vdownsampling = { 1, 2 },
- .bit_depth = { 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 2,
- .buffers = 2,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV422M,
- .vdownsampling = { 1, 1, 1 },
- .bit_depth = { 8, 4, 4 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 3,
- .buffers = 3,
- },
- {
- .fourcc = V4L2_PIX_FMT_YVU422M,
- .vdownsampling = { 1, 1, 1 },
- .bit_depth = { 8, 4, 4 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 3,
- .buffers = 3,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV444M,
- .vdownsampling = { 1, 1, 1 },
- .bit_depth = { 8, 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 3,
- .buffers = 3,
- },
- {
- .fourcc = V4L2_PIX_FMT_YVU444M,
- .vdownsampling = { 1, 1, 1 },
- .bit_depth = { 8, 8, 8 },
- .color_enc = TGP_COLOR_ENC_YCBCR,
- .planes = 3,
- .buffers = 3,
- },
-};
-
-/* There are this many multiplanar formats in the list */
-#define VIVID_MPLANAR_FORMATS 10
-
-const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
-{
- const struct vivid_fmt *fmt;
- unsigned k;
-
- for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
- fmt = &vivid_formats[k];
- if (fmt->fourcc == pixelformat)
- if (fmt->buffers == 1 || dev->multiplanar)
- return fmt;
- }
-
- return NULL;
-}
-
-bool vivid_vid_can_loop(struct vivid_dev *dev)
-{
- if (dev->src_rect.width != dev->sink_rect.width ||
- dev->src_rect.height != dev->sink_rect.height)
- return false;
- if (dev->fmt_cap->fourcc != dev->fmt_out->fourcc)
- return false;
- if (dev->field_cap != dev->field_out)
- return false;
- /*
- * While this can be supported, it is just too much work
- * to actually implement.
- */
- if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
- dev->field_cap == V4L2_FIELD_SEQ_BT)
- return false;
- if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
- if (!(dev->std_cap[dev->input] & V4L2_STD_525_60) !=
- !(dev->std_out & V4L2_STD_525_60))
- return false;
- return true;
- }
- if (vivid_is_hdmi_cap(dev) && vivid_is_hdmi_out(dev))
- return true;
- return false;
-}
-
-void vivid_send_source_change(struct vivid_dev *dev, unsigned type)
-{
- struct v4l2_event ev = {
- .type = V4L2_EVENT_SOURCE_CHANGE,
- .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
- };
- unsigned i;
-
- for (i = 0; i < dev->num_inputs; i++) {
- ev.id = i;
- if (dev->input_type[i] == type) {
- if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap)
- v4l2_event_queue(&dev->vid_cap_dev, &ev);
- if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap)
- v4l2_event_queue(&dev->vbi_cap_dev, &ev);
- }
- }
-}
-
-/*
- * Conversion function that converts a single-planar format to a
- * single-plane multiplanar format.
- */
-void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
-{
- struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp;
- struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
- const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix;
- bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
-
- memset(mp->reserved, 0, sizeof(mp->reserved));
- mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- mp->width = pix->width;
- mp->height = pix->height;
- mp->pixelformat = pix->pixelformat;
- mp->field = pix->field;
- mp->colorspace = pix->colorspace;
- mp->xfer_func = pix->xfer_func;
- /* Also copies hsv_enc */
- mp->ycbcr_enc = pix->ycbcr_enc;
- mp->quantization = pix->quantization;
- mp->num_planes = 1;
- mp->flags = pix->flags;
- ppix->sizeimage = pix->sizeimage;
- ppix->bytesperline = pix->bytesperline;
- memset(ppix->reserved, 0, sizeof(ppix->reserved));
-}
-
-int fmt_sp2mp_func(struct file *file, void *priv,
- struct v4l2_format *f, fmtfunc func)
-{
- struct v4l2_format fmt;
- struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp;
- struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
- struct v4l2_pix_format *pix = &f->fmt.pix;
- int ret;
-
- /* Converts to a mplane format */
- fmt_sp2mp(f, &fmt);
- /* Passes it to the generic mplane format function */
- ret = func(file, priv, &fmt);
- /* Copies back the mplane data to the single plane format */
- pix->width = mp->width;
- pix->height = mp->height;
- pix->pixelformat = mp->pixelformat;
- pix->field = mp->field;
- pix->colorspace = mp->colorspace;
- pix->xfer_func = mp->xfer_func;
- /* Also copies hsv_enc */
- pix->ycbcr_enc = mp->ycbcr_enc;
- pix->quantization = mp->quantization;
- pix->sizeimage = ppix->sizeimage;
- pix->bytesperline = ppix->bytesperline;
- pix->flags = mp->flags;
- return ret;
-}
-
-int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
-{
- unsigned w = r->width;
- unsigned h = r->height;
-
- /* sanitize w and h in case someone passes ~0 as the value */
- w &= 0xffff;
- h &= 0xffff;
- if (!(flags & V4L2_SEL_FLAG_LE)) {
- w++;
- h++;
- if (w < 2)
- w = 2;
- if (h < 2)
- h = 2;
- }
- if (!(flags & V4L2_SEL_FLAG_GE)) {
- if (w > MAX_WIDTH)
- w = MAX_WIDTH;
- if (h > MAX_HEIGHT)
- h = MAX_HEIGHT;
- }
- w = w & ~1;
- h = h & ~1;
- if (w < 2 || h < 2)
- return -ERANGE;
- if (w > MAX_WIDTH || h > MAX_HEIGHT)
- return -ERANGE;
- if (r->top < 0)
- r->top = 0;
- if (r->left < 0)
- r->left = 0;
- /* sanitize left and top in case someone passes ~0 as the value */
- r->left &= 0xfffe;
- r->top &= 0xfffe;
- if (r->left + w > MAX_WIDTH)
- r->left = MAX_WIDTH - w;
- if (r->top + h > MAX_HEIGHT)
- r->top = MAX_HEIGHT - h;
- if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) ==
- (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) &&
- (r->width != w || r->height != h))
- return -ERANGE;
- r->width = w;
- r->height = h;
- return 0;
-}
-
-int vivid_enum_fmt_vid(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- const struct vivid_fmt *fmt;
-
- if (f->index >= ARRAY_SIZE(vivid_formats) -
- (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS))
- return -EINVAL;
-
- fmt = &vivid_formats[f->index];
-
- f->pixelformat = fmt->fourcc;
- return 0;
-}
-
-int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX) {
- if (!vivid_is_sdtv_cap(dev))
- return -ENODATA;
- *id = dev->std_cap[dev->input];
- } else {
- if (!vivid_is_svid_out(dev))
- return -ENODATA;
- *id = dev->std_out;
- }
- return 0;
-}
-
-int vidioc_g_dv_timings(struct file *file, void *_fh,
- struct v4l2_dv_timings *timings)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX) {
- if (!vivid_is_hdmi_cap(dev))
- return -ENODATA;
- *timings = dev->dv_timings_cap[dev->input];
- } else {
- if (!vivid_is_hdmi_out(dev))
- return -ENODATA;
- *timings = dev->dv_timings_out;
- }
- return 0;
-}
-
-int vidioc_enum_dv_timings(struct file *file, void *_fh,
- struct v4l2_enum_dv_timings *timings)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX) {
- if (!vivid_is_hdmi_cap(dev))
- return -ENODATA;
- } else {
- if (!vivid_is_hdmi_out(dev))
- return -ENODATA;
- }
- return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap,
- NULL, NULL);
-}
-
-int vidioc_dv_timings_cap(struct file *file, void *_fh,
- struct v4l2_dv_timings_cap *cap)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_dir == VFL_DIR_RX) {
- if (!vivid_is_hdmi_cap(dev))
- return -ENODATA;
- } else {
- if (!vivid_is_hdmi_out(dev))
- return -ENODATA;
- }
- *cap = vivid_dv_timings_cap;
- return 0;
-}
-
-int vidioc_g_edid(struct file *file, void *_fh,
- struct v4l2_edid *edid)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct video_device *vdev = video_devdata(file);
- struct cec_adapter *adap;
-
- memset(edid->reserved, 0, sizeof(edid->reserved));
- if (vdev->vfl_dir == VFL_DIR_RX) {
- if (edid->pad >= dev->num_inputs)
- return -EINVAL;
- if (dev->input_type[edid->pad] != HDMI)
- return -EINVAL;
- adap = dev->cec_rx_adap;
- } else {
- unsigned int bus_idx;
-
- if (edid->pad >= dev->num_outputs)
- return -EINVAL;
- if (dev->output_type[edid->pad] != HDMI)
- return -EINVAL;
- if (!dev->display_present[edid->pad])
- return -ENODATA;
- bus_idx = dev->cec_output2bus_map[edid->pad];
- adap = dev->cec_tx_adap[bus_idx];
- }
- if (edid->start_block == 0 && edid->blocks == 0) {
- edid->blocks = dev->edid_blocks;
- return 0;
- }
- if (dev->edid_blocks == 0)
- return -ENODATA;
- if (edid->start_block >= dev->edid_blocks)
- return -EINVAL;
- if (edid->blocks > dev->edid_blocks - edid->start_block)
- edid->blocks = dev->edid_blocks - edid->start_block;
- if (adap)
- v4l2_set_edid_phys_addr(dev->edid, dev->edid_blocks * 128, adap->phys_addr);
- memcpy(edid->edid, dev->edid + edid->start_block * 128, edid->blocks * 128);
- return 0;
-}
diff --git a/drivers/media/platform/vivid/vivid-vid-common.h b/drivers/media/platform/vivid/vivid-vid-common.h
deleted file mode 100644
index d908d9725283..000000000000
--- a/drivers/media/platform/vivid/vivid-vid-common.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-vid-common.h - common video support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_VID_COMMON_H_
-#define _VIVID_VID_COMMON_H_
-
-typedef int (*fmtfunc)(struct file *file, void *priv, struct v4l2_format *f);
-
-/*
- * Conversion function that converts a single-planar format to a
- * single-plane multiplanar format.
- */
-void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt);
-int fmt_sp2mp_func(struct file *file, void *priv,
- struct v4l2_format *f, fmtfunc func);
-
-extern const struct v4l2_dv_timings_cap vivid_dv_timings_cap;
-
-const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat);
-
-bool vivid_vid_can_loop(struct vivid_dev *dev);
-void vivid_send_source_change(struct vivid_dev *dev, unsigned type);
-
-int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r);
-
-int vivid_enum_fmt_vid(struct file *file, void *priv, struct v4l2_fmtdesc *f);
-int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id);
-int vidioc_g_dv_timings(struct file *file, void *_fh, struct v4l2_dv_timings *timings);
-int vidioc_enum_dv_timings(struct file *file, void *_fh, struct v4l2_enum_dv_timings *timings);
-int vidioc_dv_timings_cap(struct file *file, void *_fh, struct v4l2_dv_timings_cap *cap);
-int vidioc_g_edid(struct file *file, void *_fh, struct v4l2_edid *edid);
-int vidioc_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub);
-
-#endif
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
deleted file mode 100644
index ee3446e3217c..000000000000
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ /dev/null
@@ -1,1210 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * vivid-vid-out.c - video output support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/videodev2.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-dv-timings.h>
-#include <media/v4l2-rect.h>
-
-#include "vivid-core.h"
-#include "vivid-vid-common.h"
-#include "vivid-kthread-out.h"
-#include "vivid-vid-out.h"
-
-static int vid_out_queue_setup(struct vb2_queue *vq,
- unsigned *nbuffers, unsigned *nplanes,
- unsigned sizes[], struct device *alloc_devs[])
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- const struct vivid_fmt *vfmt = dev->fmt_out;
- unsigned planes = vfmt->buffers;
- unsigned h = dev->fmt_out_rect.height;
- unsigned int size = dev->bytesperline_out[0] * h + vfmt->data_offset[0];
- unsigned p;
-
- for (p = vfmt->buffers; p < vfmt->planes; p++)
- size += dev->bytesperline_out[p] * h / vfmt->vdownsampling[p] +
- vfmt->data_offset[p];
-
- if (dev->field_out == V4L2_FIELD_ALTERNATE) {
- /*
- * You cannot use write() with FIELD_ALTERNATE since the field
- * information (TOP/BOTTOM) cannot be passed to the kernel.
- */
- if (vb2_fileio_is_active(vq))
- return -EINVAL;
- }
-
- if (dev->queue_setup_error) {
- /*
- * Error injection: test what happens if queue_setup() returns
- * an error.
- */
- dev->queue_setup_error = false;
- return -EINVAL;
- }
-
- if (*nplanes) {
- /*
- * Check if the number of requested planes match
- * the number of planes in the current format. You can't mix that.
- */
- if (*nplanes != planes)
- return -EINVAL;
- if (sizes[0] < size)
- return -EINVAL;
- for (p = 1; p < planes; p++) {
- if (sizes[p] < dev->bytesperline_out[p] * h +
- vfmt->data_offset[p])
- return -EINVAL;
- }
- } else {
- for (p = 0; p < planes; p++)
- sizes[p] = p ? dev->bytesperline_out[p] * h +
- vfmt->data_offset[p] : size;
- }
-
- if (vq->num_buffers + *nbuffers < 2)
- *nbuffers = 2 - vq->num_buffers;
-
- *nplanes = planes;
-
- dprintk(dev, 1, "%s: count=%d\n", __func__, *nbuffers);
- for (p = 0; p < planes; p++)
- dprintk(dev, 1, "%s: size[%u]=%u\n", __func__, p, sizes[p]);
- return 0;
-}
-
-static int vid_out_buf_out_validate(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- if (dev->field_out != V4L2_FIELD_ALTERNATE)
- vbuf->field = dev->field_out;
- else if (vbuf->field != V4L2_FIELD_TOP &&
- vbuf->field != V4L2_FIELD_BOTTOM)
- return -EINVAL;
- return 0;
-}
-
-static int vid_out_buf_prepare(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- const struct vivid_fmt *vfmt = dev->fmt_out;
- unsigned int planes = vfmt->buffers;
- unsigned int h = dev->fmt_out_rect.height;
- unsigned int size = dev->bytesperline_out[0] * h;
- unsigned p;
-
- for (p = vfmt->buffers; p < vfmt->planes; p++)
- size += dev->bytesperline_out[p] * h / vfmt->vdownsampling[p];
-
- dprintk(dev, 1, "%s\n", __func__);
-
- if (WARN_ON(NULL == dev->fmt_out))
- return -EINVAL;
-
- if (dev->buf_prepare_error) {
- /*
- * Error injection: test what happens if buf_prepare() returns
- * an error.
- */
- dev->buf_prepare_error = false;
- return -EINVAL;
- }
-
- for (p = 0; p < planes; p++) {
- if (p)
- size = dev->bytesperline_out[p] * h;
- size += vb->planes[p].data_offset;
-
- if (vb2_get_plane_payload(vb, p) < size) {
- dprintk(dev, 1, "%s the payload is too small for plane %u (%lu < %u)\n",
- __func__, p, vb2_get_plane_payload(vb, p), size);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static void vid_out_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
- struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
-
- dprintk(dev, 1, "%s\n", __func__);
-
- spin_lock(&dev->slock);
- list_add_tail(&buf->list, &dev->vid_out_active);
- spin_unlock(&dev->slock);
-}
-
-static int vid_out_start_streaming(struct vb2_queue *vq, unsigned count)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
- int err;
-
- if (vb2_is_streaming(&dev->vb_vid_cap_q))
- dev->can_loop_video = vivid_vid_can_loop(dev);
-
- dev->vid_out_seq_count = 0;
- dprintk(dev, 1, "%s\n", __func__);
- if (dev->start_streaming_error) {
- dev->start_streaming_error = false;
- err = -EINVAL;
- } else {
- err = vivid_start_generating_vid_out(dev, &dev->vid_out_streaming);
- }
- if (err) {
- struct vivid_buffer *buf, *tmp;
-
- list_for_each_entry_safe(buf, tmp, &dev->vid_out_active, list) {
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf,
- VB2_BUF_STATE_QUEUED);
- }
- }
- return err;
-}
-
-/* abort streaming and wait for last buffer */
-static void vid_out_stop_streaming(struct vb2_queue *vq)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vq);
-
- dprintk(dev, 1, "%s\n", __func__);
- vivid_stop_generating_vid_out(dev, &dev->vid_out_streaming);
- dev->can_loop_video = false;
-}
-
-static void vid_out_buf_request_complete(struct vb2_buffer *vb)
-{
- struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-
- v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_vid_out);
-}
-
-const struct vb2_ops vivid_vid_out_qops = {
- .queue_setup = vid_out_queue_setup,
- .buf_out_validate = vid_out_buf_out_validate,
- .buf_prepare = vid_out_buf_prepare,
- .buf_queue = vid_out_buf_queue,
- .start_streaming = vid_out_start_streaming,
- .stop_streaming = vid_out_stop_streaming,
- .buf_request_complete = vid_out_buf_request_complete,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
-};
-
-/*
- * Called whenever the format has to be reset which can occur when
- * changing outputs, standard, timings, etc.
- */
-void vivid_update_format_out(struct vivid_dev *dev)
-{
- struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
- unsigned size, p;
- u64 pixelclock;
-
- switch (dev->output_type[dev->output]) {
- case SVID:
- default:
- dev->field_out = dev->tv_field_out;
- dev->sink_rect.width = 720;
- if (dev->std_out & V4L2_STD_525_60) {
- dev->sink_rect.height = 480;
- dev->timeperframe_vid_out = (struct v4l2_fract) { 1001, 30000 };
- dev->service_set_out = V4L2_SLICED_CAPTION_525;
- } else {
- dev->sink_rect.height = 576;
- dev->timeperframe_vid_out = (struct v4l2_fract) { 1000, 25000 };
- dev->service_set_out = V4L2_SLICED_WSS_625 | V4L2_SLICED_TELETEXT_B;
- }
- dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
- break;
- case HDMI:
- dev->sink_rect.width = bt->width;
- dev->sink_rect.height = bt->height;
- size = V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt);
-
- if (can_reduce_fps(bt) && (bt->flags & V4L2_DV_FL_REDUCED_FPS))
- pixelclock = div_u64(bt->pixelclock * 1000, 1001);
- else
- pixelclock = bt->pixelclock;
-
- dev->timeperframe_vid_out = (struct v4l2_fract) {
- size / 100, (u32)pixelclock / 100
- };
- if (bt->interlaced)
- dev->field_out = V4L2_FIELD_ALTERNATE;
- else
- dev->field_out = V4L2_FIELD_NONE;
- if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
- if (bt->width == 720 && bt->height <= 576)
- dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
- else
- dev->colorspace_out = V4L2_COLORSPACE_REC709;
- } else {
- dev->colorspace_out = V4L2_COLORSPACE_SRGB;
- }
- break;
- }
- dev->xfer_func_out = V4L2_XFER_FUNC_DEFAULT;
- dev->ycbcr_enc_out = V4L2_YCBCR_ENC_DEFAULT;
- dev->hsv_enc_out = V4L2_HSV_ENC_180;
- dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
- dev->compose_out = dev->sink_rect;
- dev->compose_bounds_out = dev->sink_rect;
- dev->crop_out = dev->compose_out;
- if (V4L2_FIELD_HAS_T_OR_B(dev->field_out))
- dev->crop_out.height /= 2;
- dev->fmt_out_rect = dev->crop_out;
- for (p = 0; p < dev->fmt_out->planes; p++)
- dev->bytesperline_out[p] =
- (dev->sink_rect.width * dev->fmt_out->bit_depth[p]) / 8;
-}
-
-/* Map the field to something that is valid for the current output */
-static enum v4l2_field vivid_field_out(struct vivid_dev *dev, enum v4l2_field field)
-{
- if (vivid_is_svid_out(dev)) {
- switch (field) {
- case V4L2_FIELD_INTERLACED_TB:
- case V4L2_FIELD_INTERLACED_BT:
- case V4L2_FIELD_SEQ_TB:
- case V4L2_FIELD_SEQ_BT:
- case V4L2_FIELD_ALTERNATE:
- return field;
- case V4L2_FIELD_INTERLACED:
- default:
- return V4L2_FIELD_INTERLACED;
- }
- }
- if (vivid_is_hdmi_out(dev))
- return dev->dv_timings_out.bt.interlaced ? V4L2_FIELD_ALTERNATE :
- V4L2_FIELD_NONE;
- return V4L2_FIELD_NONE;
-}
-
-static enum tpg_pixel_aspect vivid_get_pixel_aspect(const struct vivid_dev *dev)
-{
- if (vivid_is_svid_out(dev))
- return (dev->std_out & V4L2_STD_525_60) ?
- TPG_PIXEL_ASPECT_NTSC : TPG_PIXEL_ASPECT_PAL;
-
- if (vivid_is_hdmi_out(dev) &&
- dev->sink_rect.width == 720 && dev->sink_rect.height <= 576)
- return dev->sink_rect.height == 480 ?
- TPG_PIXEL_ASPECT_NTSC : TPG_PIXEL_ASPECT_PAL;
-
- return TPG_PIXEL_ASPECT_SQUARE;
-}
-
-int vivid_g_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
- const struct vivid_fmt *fmt = dev->fmt_out;
- unsigned p;
-
- mp->width = dev->fmt_out_rect.width;
- mp->height = dev->fmt_out_rect.height;
- mp->field = dev->field_out;
- mp->pixelformat = fmt->fourcc;
- mp->colorspace = dev->colorspace_out;
- mp->xfer_func = dev->xfer_func_out;
- mp->ycbcr_enc = dev->ycbcr_enc_out;
- mp->quantization = dev->quantization_out;
- mp->num_planes = fmt->buffers;
- for (p = 0; p < mp->num_planes; p++) {
- mp->plane_fmt[p].bytesperline = dev->bytesperline_out[p];
- mp->plane_fmt[p].sizeimage =
- mp->plane_fmt[p].bytesperline * mp->height +
- fmt->data_offset[p];
- }
- for (p = fmt->buffers; p < fmt->planes; p++) {
- unsigned stride = dev->bytesperline_out[p];
-
- mp->plane_fmt[0].sizeimage +=
- (stride * mp->height) / fmt->vdownsampling[p];
- }
- return 0;
-}
-
-int vivid_try_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
- struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
- struct v4l2_plane_pix_format *pfmt = mp->plane_fmt;
- const struct vivid_fmt *fmt;
- unsigned bytesperline, max_bpl;
- unsigned factor = 1;
- unsigned w, h;
- unsigned p;
-
- fmt = vivid_get_format(dev, mp->pixelformat);
- if (!fmt) {
- dprintk(dev, 1, "Fourcc format (0x%08x) unknown.\n",
- mp->pixelformat);
- mp->pixelformat = V4L2_PIX_FMT_YUYV;
- fmt = vivid_get_format(dev, mp->pixelformat);
- }
-
- mp->field = vivid_field_out(dev, mp->field);
- if (vivid_is_svid_out(dev)) {
- w = 720;
- h = (dev->std_out & V4L2_STD_525_60) ? 480 : 576;
- } else {
- w = dev->sink_rect.width;
- h = dev->sink_rect.height;
- }
- if (V4L2_FIELD_HAS_T_OR_B(mp->field))
- factor = 2;
- if (!dev->has_scaler_out && !dev->has_crop_out && !dev->has_compose_out) {
- mp->width = w;
- mp->height = h / factor;
- } else {
- struct v4l2_rect r = { 0, 0, mp->width, mp->height * factor };
-
- v4l2_rect_set_min_size(&r, &vivid_min_rect);
- v4l2_rect_set_max_size(&r, &vivid_max_rect);
- if (dev->has_scaler_out && !dev->has_crop_out) {
- struct v4l2_rect max_r = { 0, 0, MAX_ZOOM * w, MAX_ZOOM * h };
-
- v4l2_rect_set_max_size(&r, &max_r);
- } else if (!dev->has_scaler_out && dev->has_compose_out && !dev->has_crop_out) {
- v4l2_rect_set_max_size(&r, &dev->sink_rect);
- } else if (!dev->has_scaler_out && !dev->has_compose_out) {
- v4l2_rect_set_min_size(&r, &dev->sink_rect);
- }
- mp->width = r.width;
- mp->height = r.height / factor;
- }
-
- /* This driver supports custom bytesperline values */
-
- mp->num_planes = fmt->buffers;
- for (p = 0; p < fmt->buffers; p++) {
- /* Calculate the minimum supported bytesperline value */
- bytesperline = (mp->width * fmt->bit_depth[p]) >> 3;
- /* Calculate the maximum supported bytesperline value */
- max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[p]) >> 3;
-
- if (pfmt[p].bytesperline > max_bpl)
- pfmt[p].bytesperline = max_bpl;
- if (pfmt[p].bytesperline < bytesperline)
- pfmt[p].bytesperline = bytesperline;
-
- pfmt[p].sizeimage = (pfmt[p].bytesperline * mp->height) /
- fmt->vdownsampling[p] + fmt->data_offset[p];
-
- memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
- }
- for (p = fmt->buffers; p < fmt->planes; p++)
- pfmt[0].sizeimage += (pfmt[0].bytesperline * mp->height *
- (fmt->bit_depth[p] / fmt->vdownsampling[p])) /
- (fmt->bit_depth[0] / fmt->vdownsampling[0]);
-
- mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
- mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
- mp->quantization = V4L2_QUANTIZATION_DEFAULT;
- if (vivid_is_svid_out(dev)) {
- mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
- } else if (dev->dvi_d_out || !(bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
- mp->colorspace = V4L2_COLORSPACE_SRGB;
- if (dev->dvi_d_out)
- mp->quantization = V4L2_QUANTIZATION_LIM_RANGE;
- } else if (bt->width == 720 && bt->height <= 576) {
- mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
- } else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M &&
- mp->colorspace != V4L2_COLORSPACE_REC709 &&
- mp->colorspace != V4L2_COLORSPACE_OPRGB &&
- mp->colorspace != V4L2_COLORSPACE_BT2020 &&
- mp->colorspace != V4L2_COLORSPACE_SRGB) {
- mp->colorspace = V4L2_COLORSPACE_REC709;
- }
- memset(mp->reserved, 0, sizeof(mp->reserved));
- return 0;
-}
-
-int vivid_s_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_rect *crop = &dev->crop_out;
- struct v4l2_rect *compose = &dev->compose_out;
- struct vb2_queue *q = &dev->vb_vid_out_q;
- int ret = vivid_try_fmt_vid_out(file, priv, f);
- unsigned factor = 1;
- unsigned p;
-
- if (ret < 0)
- return ret;
-
- if (vb2_is_busy(q) &&
- (vivid_is_svid_out(dev) ||
- mp->width != dev->fmt_out_rect.width ||
- mp->height != dev->fmt_out_rect.height ||
- mp->pixelformat != dev->fmt_out->fourcc ||
- mp->field != dev->field_out)) {
- dprintk(dev, 1, "%s device busy\n", __func__);
- return -EBUSY;
- }
-
- /*
- * Allow for changing the colorspace on the fly. Useful for testing
- * purposes, and it is something that HDMI transmitters are able
- * to do.
- */
- if (vb2_is_busy(q))
- goto set_colorspace;
-
- dev->fmt_out = vivid_get_format(dev, mp->pixelformat);
- if (V4L2_FIELD_HAS_T_OR_B(mp->field))
- factor = 2;
-
- if (dev->has_scaler_out || dev->has_crop_out || dev->has_compose_out) {
- struct v4l2_rect r = { 0, 0, mp->width, mp->height };
-
- if (dev->has_scaler_out) {
- if (dev->has_crop_out)
- v4l2_rect_map_inside(crop, &r);
- else
- *crop = r;
- if (dev->has_compose_out && !dev->has_crop_out) {
- struct v4l2_rect min_r = {
- 0, 0,
- r.width / MAX_ZOOM,
- factor * r.height / MAX_ZOOM
- };
- struct v4l2_rect max_r = {
- 0, 0,
- r.width * MAX_ZOOM,
- factor * r.height * MAX_ZOOM
- };
-
- v4l2_rect_set_min_size(compose, &min_r);
- v4l2_rect_set_max_size(compose, &max_r);
- v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
- } else if (dev->has_compose_out) {
- struct v4l2_rect min_r = {
- 0, 0,
- crop->width / MAX_ZOOM,
- factor * crop->height / MAX_ZOOM
- };
- struct v4l2_rect max_r = {
- 0, 0,
- crop->width * MAX_ZOOM,
- factor * crop->height * MAX_ZOOM
- };
-
- v4l2_rect_set_min_size(compose, &min_r);
- v4l2_rect_set_max_size(compose, &max_r);
- v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
- }
- } else if (dev->has_compose_out && !dev->has_crop_out) {
- v4l2_rect_set_size_to(crop, &r);
- r.height *= factor;
- v4l2_rect_set_size_to(compose, &r);
- v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
- } else if (!dev->has_compose_out) {
- v4l2_rect_map_inside(crop, &r);
- r.height /= factor;
- v4l2_rect_set_size_to(compose, &r);
- } else {
- r.height *= factor;
- v4l2_rect_set_max_size(compose, &r);
- v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
- crop->top *= factor;
- crop->height *= factor;
- v4l2_rect_set_size_to(crop, compose);
- v4l2_rect_map_inside(crop, &r);
- crop->top /= factor;
- crop->height /= factor;
- }
- } else {
- struct v4l2_rect r = { 0, 0, mp->width, mp->height };
-
- v4l2_rect_set_size_to(crop, &r);
- r.height /= factor;
- v4l2_rect_set_size_to(compose, &r);
- }
-
- dev->fmt_out_rect.width = mp->width;
- dev->fmt_out_rect.height = mp->height;
- for (p = 0; p < mp->num_planes; p++)
- dev->bytesperline_out[p] = mp->plane_fmt[p].bytesperline;
- for (p = dev->fmt_out->buffers; p < dev->fmt_out->planes; p++)
- dev->bytesperline_out[p] =
- (dev->bytesperline_out[0] * dev->fmt_out->bit_depth[p]) /
- dev->fmt_out->bit_depth[0];
- dev->field_out = mp->field;
- if (vivid_is_svid_out(dev))
- dev->tv_field_out = mp->field;
-
-set_colorspace:
- dev->colorspace_out = mp->colorspace;
- dev->xfer_func_out = mp->xfer_func;
- dev->ycbcr_enc_out = mp->ycbcr_enc;
- dev->quantization_out = mp->quantization;
- if (dev->loop_video) {
- vivid_send_source_change(dev, SVID);
- vivid_send_source_change(dev, HDMI);
- }
- return 0;
-}
-
-int vidioc_g_fmt_vid_out_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!dev->multiplanar)
- return -ENOTTY;
- return vivid_g_fmt_vid_out(file, priv, f);
-}
-
-int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!dev->multiplanar)
- return -ENOTTY;
- return vivid_try_fmt_vid_out(file, priv, f);
-}
-
-int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!dev->multiplanar)
- return -ENOTTY;
- return vivid_s_fmt_vid_out(file, priv, f);
-}
-
-int vidioc_g_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (dev->multiplanar)
- return -ENOTTY;
- return fmt_sp2mp_func(file, priv, f, vivid_g_fmt_vid_out);
-}
-
-int vidioc_try_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (dev->multiplanar)
- return -ENOTTY;
- return fmt_sp2mp_func(file, priv, f, vivid_try_fmt_vid_out);
-}
-
-int vidioc_s_fmt_vid_out(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (dev->multiplanar)
- return -ENOTTY;
- return fmt_sp2mp_func(file, priv, f, vivid_s_fmt_vid_out);
-}
-
-int vivid_vid_out_g_selection(struct file *file, void *priv,
- struct v4l2_selection *sel)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!dev->has_crop_out && !dev->has_compose_out)
- return -ENOTTY;
- if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
- return -EINVAL;
-
- sel->r.left = sel->r.top = 0;
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP:
- if (!dev->has_crop_out)
- return -EINVAL;
- sel->r = dev->crop_out;
- break;
- case V4L2_SEL_TGT_CROP_DEFAULT:
- if (!dev->has_crop_out)
- return -EINVAL;
- sel->r = dev->fmt_out_rect;
- break;
- case V4L2_SEL_TGT_CROP_BOUNDS:
- if (!dev->has_crop_out)
- return -EINVAL;
- sel->r = vivid_max_rect;
- break;
- case V4L2_SEL_TGT_COMPOSE:
- if (!dev->has_compose_out)
- return -EINVAL;
- sel->r = dev->compose_out;
- break;
- case V4L2_SEL_TGT_COMPOSE_DEFAULT:
- case V4L2_SEL_TGT_COMPOSE_BOUNDS:
- if (!dev->has_compose_out)
- return -EINVAL;
- sel->r = dev->sink_rect;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
-{
- struct vivid_dev *dev = video_drvdata(file);
- struct v4l2_rect *crop = &dev->crop_out;
- struct v4l2_rect *compose = &dev->compose_out;
- unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_out) ? 2 : 1;
- int ret;
-
- if (!dev->has_crop_out && !dev->has_compose_out)
- return -ENOTTY;
- if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
- return -EINVAL;
-
- switch (s->target) {
- case V4L2_SEL_TGT_CROP:
- if (!dev->has_crop_out)
- return -EINVAL;
- ret = vivid_vid_adjust_sel(s->flags, &s->r);
- if (ret)
- return ret;
- v4l2_rect_set_min_size(&s->r, &vivid_min_rect);
- v4l2_rect_set_max_size(&s->r, &dev->fmt_out_rect);
- if (dev->has_scaler_out) {
- struct v4l2_rect max_rect = {
- 0, 0,
- dev->sink_rect.width * MAX_ZOOM,
- (dev->sink_rect.height / factor) * MAX_ZOOM
- };
-
- v4l2_rect_set_max_size(&s->r, &max_rect);
- if (dev->has_compose_out) {
- struct v4l2_rect min_rect = {
- 0, 0,
- s->r.width / MAX_ZOOM,
- (s->r.height * factor) / MAX_ZOOM
- };
- struct v4l2_rect max_rect = {
- 0, 0,
- s->r.width * MAX_ZOOM,
- (s->r.height * factor) * MAX_ZOOM
- };
-
- v4l2_rect_set_min_size(compose, &min_rect);
- v4l2_rect_set_max_size(compose, &max_rect);
- v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
- }
- } else if (dev->has_compose_out) {
- s->r.top *= factor;
- s->r.height *= factor;
- v4l2_rect_set_max_size(&s->r, &dev->sink_rect);
- v4l2_rect_set_size_to(compose, &s->r);
- v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
- s->r.top /= factor;
- s->r.height /= factor;
- } else {
- v4l2_rect_set_size_to(&s->r, &dev->sink_rect);
- s->r.height /= factor;
- }
- v4l2_rect_map_inside(&s->r, &dev->fmt_out_rect);
- *crop = s->r;
- break;
- case V4L2_SEL_TGT_COMPOSE:
- if (!dev->has_compose_out)
- return -EINVAL;
- ret = vivid_vid_adjust_sel(s->flags, &s->r);
- if (ret)
- return ret;
- v4l2_rect_set_min_size(&s->r, &vivid_min_rect);
- v4l2_rect_set_max_size(&s->r, &dev->sink_rect);
- v4l2_rect_map_inside(&s->r, &dev->compose_bounds_out);
- s->r.top /= factor;
- s->r.height /= factor;
- if (dev->has_scaler_out) {
- struct v4l2_rect fmt = dev->fmt_out_rect;
- struct v4l2_rect max_rect = {
- 0, 0,
- s->r.width * MAX_ZOOM,
- s->r.height * MAX_ZOOM
- };
- struct v4l2_rect min_rect = {
- 0, 0,
- s->r.width / MAX_ZOOM,
- s->r.height / MAX_ZOOM
- };
-
- v4l2_rect_set_min_size(&fmt, &min_rect);
- if (!dev->has_crop_out)
- v4l2_rect_set_max_size(&fmt, &max_rect);
- if (!v4l2_rect_same_size(&dev->fmt_out_rect, &fmt) &&
- vb2_is_busy(&dev->vb_vid_out_q))
- return -EBUSY;
- if (dev->has_crop_out) {
- v4l2_rect_set_min_size(crop, &min_rect);
- v4l2_rect_set_max_size(crop, &max_rect);
- }
- dev->fmt_out_rect = fmt;
- } else if (dev->has_crop_out) {
- struct v4l2_rect fmt = dev->fmt_out_rect;
-
- v4l2_rect_set_min_size(&fmt, &s->r);
- if (!v4l2_rect_same_size(&dev->fmt_out_rect, &fmt) &&
- vb2_is_busy(&dev->vb_vid_out_q))
- return -EBUSY;
- dev->fmt_out_rect = fmt;
- v4l2_rect_set_size_to(crop, &s->r);
- v4l2_rect_map_inside(crop, &dev->fmt_out_rect);
- } else {
- if (!v4l2_rect_same_size(&s->r, &dev->fmt_out_rect) &&
- vb2_is_busy(&dev->vb_vid_out_q))
- return -EBUSY;
- v4l2_rect_set_size_to(&dev->fmt_out_rect, &s->r);
- v4l2_rect_set_size_to(crop, &s->r);
- crop->height /= factor;
- v4l2_rect_map_inside(crop, &dev->fmt_out_rect);
- }
- 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:
- return -EINVAL;
- }
-
- return 0;
-}
-
-int vivid_vid_out_g_pixelaspect(struct file *file, void *priv,
- int type, struct v4l2_fract *f)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
- return -EINVAL;
-
- switch (vivid_get_pixel_aspect(dev)) {
- case TPG_PIXEL_ASPECT_NTSC:
- f->numerator = 11;
- f->denominator = 10;
- break;
- case TPG_PIXEL_ASPECT_PAL:
- f->numerator = 54;
- f->denominator = 59;
- break;
- default:
- break;
- }
- return 0;
-}
-
-int vidioc_g_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;
- unsigned clipcount = win->clipcount;
-
- if (!dev->has_fb)
- return -EINVAL;
- win->w.top = dev->overlay_out_top;
- 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) {
- if (copy_to_user(win->clips, dev->clips_out,
- clipcount * sizeof(dev->clips_out[0])))
- return -EFAULT;
- }
- return 0;
-}
-
-int vidioc_try_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 i, j;
-
- if (!dev->has_fb)
- return -EINVAL;
- win->w.left = clamp_t(int, win->w.left,
- -dev->display_width, dev->display_width);
- win->w.top = clamp_t(int, win->w.top,
- -dev->display_height, dev->display_height);
- win->w.width = compose->width;
- win->w.height = compose->height;
- /*
- * It makes no sense for an OSD to overlay only top or bottom fields,
- * 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) {
- if (copy_from_user(dev->try_clips_out, win->clips,
- win->clipcount * sizeof(dev->clips_out[0])))
- return -EFAULT;
- 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;
- }
- }
- if (copy_to_user(win->clips, dev->try_clips_out,
- win->clipcount * sizeof(dev->clips_out[0])))
- return -EFAULT;
- }
- return 0;
-}
-
-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;
-}
-
-int vivid_vid_out_overlay(struct file *file, void *fh, unsigned i)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (i && !dev->fmt_out->can_do_overlay) {
- dprintk(dev, 1, "unsupported output format for output overlay\n");
- return -EINVAL;
- }
-
- dev->overlay_out_enabled = i;
- return 0;
-}
-
-int vivid_vid_out_g_fbuf(struct file *file, void *fh,
- struct v4l2_framebuffer *a)
-{
- 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 |
- V4L2_FBUF_CAP_LOCAL_ALPHA |
- V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
- a->flags = V4L2_FBUF_FLAG_OVERLAY | dev->fbuf_out_flags;
- a->base = (void *)dev->video_pbase;
- a->fmt.width = dev->display_width;
- a->fmt.height = dev->display_height;
- if (dev->fb_defined.green.length == 5)
- a->fmt.pixelformat = V4L2_PIX_FMT_ARGB555;
- else
- a->fmt.pixelformat = V4L2_PIX_FMT_RGB565;
- a->fmt.bytesperline = dev->display_byte_stride;
- a->fmt.sizeimage = a->fmt.height * a->fmt.bytesperline;
- a->fmt.field = V4L2_FIELD_NONE;
- a->fmt.colorspace = V4L2_COLORSPACE_SRGB;
- a->fmt.priv = 0;
- return 0;
-}
-
-int vivid_vid_out_s_fbuf(struct file *file, void *fh,
- const struct v4l2_framebuffer *a)
-{
- struct vivid_dev *dev = video_drvdata(file);
- const unsigned chroma_flags = V4L2_FBUF_FLAG_CHROMAKEY |
- V4L2_FBUF_FLAG_SRC_CHROMAKEY;
- const unsigned alpha_flags = V4L2_FBUF_FLAG_GLOBAL_ALPHA |
- V4L2_FBUF_FLAG_LOCAL_ALPHA |
- V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
-
-
- if ((a->flags & chroma_flags) == chroma_flags)
- return -EINVAL;
- switch (a->flags & alpha_flags) {
- case 0:
- case V4L2_FBUF_FLAG_GLOBAL_ALPHA:
- case V4L2_FBUF_FLAG_LOCAL_ALPHA:
- case V4L2_FBUF_FLAG_LOCAL_INV_ALPHA:
- break;
- default:
- return -EINVAL;
- }
- dev->fbuf_out_flags &= ~(chroma_flags | alpha_flags);
- dev->fbuf_out_flags = a->flags & (chroma_flags | alpha_flags);
- return 0;
-}
-
-static const struct v4l2_audioout vivid_audio_outputs[] = {
- { 0, "Line-Out 1" },
- { 1, "Line-Out 2" },
-};
-
-int vidioc_enum_output(struct file *file, void *priv,
- struct v4l2_output *out)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (out->index >= dev->num_outputs)
- return -EINVAL;
-
- out->type = V4L2_OUTPUT_TYPE_ANALOG;
- switch (dev->output_type[out->index]) {
- case SVID:
- snprintf(out->name, sizeof(out->name), "S-Video %u",
- dev->output_name_counter[out->index]);
- out->std = V4L2_STD_ALL;
- if (dev->has_audio_outputs)
- out->audioset = (1 << ARRAY_SIZE(vivid_audio_outputs)) - 1;
- out->capabilities = V4L2_OUT_CAP_STD;
- break;
- case HDMI:
- snprintf(out->name, sizeof(out->name), "HDMI %u",
- dev->output_name_counter[out->index]);
- out->capabilities = V4L2_OUT_CAP_DV_TIMINGS;
- break;
- }
- return 0;
-}
-
-int vidioc_g_output(struct file *file, void *priv, unsigned *o)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- *o = dev->output;
- return 0;
-}
-
-int vidioc_s_output(struct file *file, void *priv, unsigned o)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (o >= dev->num_outputs)
- return -EINVAL;
-
- if (o == dev->output)
- return 0;
-
- if (vb2_is_busy(&dev->vb_vid_out_q) ||
- vb2_is_busy(&dev->vb_vbi_out_q) ||
- vb2_is_busy(&dev->vb_meta_out_q))
- return -EBUSY;
-
- dev->output = o;
- dev->tv_audio_output = 0;
- if (dev->output_type[o] == SVID)
- dev->vid_out_dev.tvnorms = V4L2_STD_ALL;
- else
- dev->vid_out_dev.tvnorms = 0;
-
- dev->vbi_out_dev.tvnorms = dev->vid_out_dev.tvnorms;
- dev->meta_out_dev.tvnorms = dev->vid_out_dev.tvnorms;
- vivid_update_format_out(dev);
-
- v4l2_ctrl_activate(dev->ctrl_display_present, vivid_is_hdmi_out(dev));
- if (vivid_is_hdmi_out(dev))
- v4l2_ctrl_s_ctrl(dev->ctrl_display_present,
- dev->display_present[dev->output]);
-
- return 0;
-}
-
-int vidioc_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vout)
-{
- if (vout->index >= ARRAY_SIZE(vivid_audio_outputs))
- return -EINVAL;
- *vout = vivid_audio_outputs[vout->index];
- return 0;
-}
-
-int vidioc_g_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_svid_out(dev))
- return -EINVAL;
- *vout = vivid_audio_outputs[dev->tv_audio_output];
- return 0;
-}
-
-int vidioc_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_svid_out(dev))
- return -EINVAL;
- if (vout->index >= ARRAY_SIZE(vivid_audio_outputs))
- return -EINVAL;
- dev->tv_audio_output = vout->index;
- return 0;
-}
-
-int vivid_vid_out_s_std(struct file *file, void *priv, v4l2_std_id id)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (!vivid_is_svid_out(dev))
- return -ENODATA;
- if (dev->std_out == id)
- return 0;
- if (vb2_is_busy(&dev->vb_vid_out_q) || vb2_is_busy(&dev->vb_vbi_out_q))
- return -EBUSY;
- dev->std_out = id;
- vivid_update_format_out(dev);
- return 0;
-}
-
-static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings)
-{
- struct v4l2_bt_timings *bt = &timings->bt;
-
- if ((bt->standards & (V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF)) &&
- v4l2_valid_dv_timings(timings, &vivid_dv_timings_cap, NULL, NULL))
- return true;
-
- return false;
-}
-
-int vivid_vid_out_s_dv_timings(struct file *file, void *_fh,
- struct v4l2_dv_timings *timings)
-{
- struct vivid_dev *dev = video_drvdata(file);
- if (!vivid_is_hdmi_out(dev))
- return -ENODATA;
- if (!v4l2_find_dv_timings_cap(timings, &vivid_dv_timings_cap,
- 0, NULL, NULL) &&
- !valid_cvt_gtf_timings(timings))
- return -EINVAL;
- if (v4l2_match_dv_timings(timings, &dev->dv_timings_out, 0, true))
- return 0;
- if (vb2_is_busy(&dev->vb_vid_out_q))
- return -EBUSY;
- dev->dv_timings_out = *timings;
- vivid_update_format_out(dev);
- return 0;
-}
-
-int vivid_vid_out_g_parm(struct file *file, void *priv,
- struct v4l2_streamparm *parm)
-{
- struct vivid_dev *dev = video_drvdata(file);
-
- if (parm->type != (dev->multiplanar ?
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
- V4L2_BUF_TYPE_VIDEO_OUTPUT))
- return -EINVAL;
-
- parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
- parm->parm.output.timeperframe = dev->timeperframe_vid_out;
- parm->parm.output.writebuffers = 1;
-
- return 0;
-}
-
-int vidioc_subscribe_event(struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub)
-{
- switch (sub->type) {
- case V4L2_EVENT_SOURCE_CHANGE:
- if (fh->vdev->vfl_dir == VFL_DIR_RX)
- return v4l2_src_change_event_subscribe(fh, sub);
- break;
- default:
- return v4l2_ctrl_subscribe_event(fh, sub);
- }
- return -EINVAL;
-}
diff --git a/drivers/media/platform/vivid/vivid-vid-out.h b/drivers/media/platform/vivid/vivid-vid-out.h
deleted file mode 100644
index 8d56314f4ea1..000000000000
--- a/drivers/media/platform/vivid/vivid-vid-out.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * vivid-vid-out.h - video output support functions.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- */
-
-#ifndef _VIVID_VID_OUT_H_
-#define _VIVID_VID_OUT_H_
-
-extern const struct vb2_ops vivid_vid_out_qops;
-
-void vivid_update_format_out(struct vivid_dev *dev);
-
-int vivid_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_g_fmt_vid_out_mplane(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_vid_out_g_selection(struct file *file, void *priv, struct v4l2_selection *sel);
-int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection *s);
-int vivid_vid_out_g_pixelaspect(struct file *file, void *priv, int type, struct v4l2_fract *f);
-int vidioc_enum_fmt_vid_out_overlay(struct file *file, void *priv, struct v4l2_fmtdesc *f);
-int vidioc_g_fmt_vid_out_overlay(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv, struct v4l2_format *f);
-int vidioc_s_fmt_vid_out_overlay(struct file *file, void *priv, struct v4l2_format *f);
-int vivid_vid_out_overlay(struct file *file, void *fh, unsigned i);
-int vivid_vid_out_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a);
-int vivid_vid_out_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a);
-int vidioc_enum_output(struct file *file, void *priv, struct v4l2_output *out);
-int vidioc_g_output(struct file *file, void *priv, unsigned *i);
-int vidioc_s_output(struct file *file, void *priv, unsigned i);
-int vidioc_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vout);
-int vidioc_g_audout(struct file *file, void *fh, struct v4l2_audioout *vout);
-int vidioc_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout);
-int vivid_vid_out_s_std(struct file *file, void *priv, v4l2_std_id id);
-int vivid_vid_out_s_dv_timings(struct file *file, void *_fh, struct v4l2_dv_timings *timings);
-int vivid_vid_out_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parm);
-
-#endif
diff --git a/drivers/media/platform/xilinx/Kconfig b/drivers/media/platform/xilinx/Kconfig
index a2773ad7c185..01c96fb66414 100644
--- a/drivers/media/platform/xilinx/Kconfig
+++ b/drivers/media/platform/xilinx/Kconfig
@@ -2,7 +2,9 @@
config VIDEO_XILINX
tristate "Xilinx Video IP (EXPERIMENTAL)"
- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF && HAS_DMA
+ depends on VIDEO_V4L2 && OF && HAS_DMA
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
select VIDEOBUF2_DMA_CONTIG
select V4L2_FWNODE
help