From c9c9e2ab0375a8dd788a8f0587bff0133015290c Mon Sep 17 00:00:00 2001 From: Dillon Min Date: Tue, 19 Oct 2021 09:43:14 +0100 Subject: [PATCH 001/397] media: admin-guide: add stm32-dma2d description add stm32-dma2d description for dma2d driver Signed-off-by: Dillon Min Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/admin-guide/media/platform-cardlist.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/admin-guide/media/platform-cardlist.rst b/Documentation/admin-guide/media/platform-cardlist.rst index 261e7772eb3e..ac73c4166d1e 100644 --- a/Documentation/admin-guide/media/platform-cardlist.rst +++ b/Documentation/admin-guide/media/platform-cardlist.rst @@ -60,6 +60,7 @@ s5p-mfc Samsung S5P MFC Video Codec sh_veu SuperH VEU mem2mem video processing sh_vou SuperH VOU video output stm32-dcmi STM32 Digital Camera Memory Interface (DCMI) +stm32-dma2d STM32 Chrom-Art Accelerator Unit sun4i-csi Allwinner A10 CMOS Sensor Interface Support sun6i-csi Allwinner V3s Camera Sensor Interface sun8i-di Allwinner Deinterlace From 68dda3e02522aae867f4d526e44e1a87a6cec52a Mon Sep 17 00:00:00 2001 From: Dillon Min Date: Tue, 19 Oct 2021 09:43:15 +0100 Subject: [PATCH 002/397] media: dt-bindings: media: add document for STM32 DMA2d bindings This adds documentation of device tree bindings for the STM32 DMA2D Signed-off-by: Dillon Min Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../bindings/media/st,stm32-dma2d.yaml | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/st,stm32-dma2d.yaml diff --git a/Documentation/devicetree/bindings/media/st,stm32-dma2d.yaml b/Documentation/devicetree/bindings/media/st,stm32-dma2d.yaml new file mode 100644 index 000000000000..f97b4a246605 --- /dev/null +++ b/Documentation/devicetree/bindings/media/st,stm32-dma2d.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/st,stm32-dma2d.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 Chrom-Art Accelerator DMA2D binding + +description: + Chrom-ART Accelerator(DMA2D), graphical hardware accelerator + enabling enhanced graphical user interface with minimum CPU load + + It can perform the following operations. + + - Filling a part or the whole of a destination image with a specific color. + - Copying a part or the whole of a source image into a part or the whole of + a destination image. + - Copying a part or the whole of a source image into a part or the whole of + a destination image with a pixel format conversion. + - Blending a part and/or two complete source images with different pixel + format and copy the result into a part or the whole of a destination image + with a different color format. (TODO) + + +maintainers: + - Dillon Min + +properties: + compatible: + const: st,stm32-dma2d + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: dma2d + + resets: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + +additionalProperties: false + +examples: + - | + #include + #include + dma2d: dma2d@4002b000 { + compatible = "st,stm32-dma2d"; + reg = <0x4002b000 0xc00>; + interrupts = <90>; + resets = <&rcc STM32F4_AHB1_RESET(DMA2D)>; + clocks = <&rcc 0 STM32F4_AHB1_CLOCK(DMA2D)>; + clock-names = "dma2d"; + }; + +... From 0a08088f82c2db9cd6bce3258c79a76980c77651 Mon Sep 17 00:00:00 2001 From: Dillon Min Date: Tue, 19 Oct 2021 09:43:18 +0100 Subject: [PATCH 003/397] media: v4l2-mem2mem: add v4l2_m2m_get_unmapped_area for no-mmu platform For platforms without MMU the m2m provides a helper method v4l2_m2m_get_unmapped_area(), The mmap() routines will call this to get a proposed address for the mapping. More detailed information about get_unmapped_area can be found in Documentation/nommu-mmap.txt Signed-off-by: Dillon Min Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mem2mem.c | 21 +++++++++++++++++++++ include/media/v4l2-mem2mem.h | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index e7f4bf5bc8dd..e2654b422334 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -966,6 +966,27 @@ int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, } EXPORT_SYMBOL(v4l2_m2m_mmap); +#ifndef CONFIG_MMU +unsigned long v4l2_m2m_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct v4l2_fh *fh = file->private_data; + unsigned long offset = pgoff << PAGE_SHIFT; + struct vb2_queue *vq; + + if (offset < DST_QUEUE_OFF_BASE) { + vq = v4l2_m2m_get_src_vq(fh->m2m_ctx); + } else { + vq = v4l2_m2m_get_dst_vq(fh->m2m_ctx); + pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT); + } + + return vb2_get_unmapped_area(vq, addr, len, pgoff, flags); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_get_unmapped_area); +#endif + #if defined(CONFIG_MEDIA_CONTROLLER) void v4l2_m2m_unregister_media_controller(struct v4l2_m2m_dev *m2m_dev) { diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index 5a91b548ecc0..fdbd5257e020 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -495,6 +495,11 @@ __poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, struct vm_area_struct *vma); +#ifndef CONFIG_MMU +unsigned long v4l2_m2m_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags); +#endif /** * v4l2_m2m_init() - initialize per-driver m2m data * From c9ee220d76775e42f35d634479c978d9350077d3 Mon Sep 17 00:00:00 2001 From: Dillon Min Date: Tue, 19 Oct 2021 09:43:19 +0100 Subject: [PATCH 004/397] media: videobuf2: Fix the size printk format Since the type of parameter size is unsigned long, it should printk by %lu, instead of %ld, fix it. Fixes: 7952be9b6ece ("media: drivers/media/common/videobuf2: rename from videobuf") Signed-off-by: Dillon Min Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/videobuf2/videobuf2-dma-contig.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c index 556e42ba66e5..7c4096e62173 100644 --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c @@ -257,7 +257,7 @@ static void *vb2_dc_alloc(struct vb2_buffer *vb, ret = vb2_dc_alloc_coherent(buf); if (ret) { - dev_err(dev, "dma alloc of size %ld failed\n", size); + dev_err(dev, "dma alloc of size %lu failed\n", size); kfree(buf); return ERR_PTR(-ENOMEM); } @@ -298,9 +298,9 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma) vma->vm_ops->open(vma); - pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n", - __func__, (unsigned long)buf->dma_addr, vma->vm_start, - buf->size); + pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %lu\n", + __func__, (unsigned long)buf->dma_addr, vma->vm_start, + buf->size); return 0; } From ee4a929e0eb299491c53f3c6dc235048a3edcdc2 Mon Sep 17 00:00:00 2001 From: Dillon Min Date: Tue, 19 Oct 2021 09:43:20 +0100 Subject: [PATCH 005/397] media: v4l2-ctrls: Add V4L2_CID_COLORFX_CBCR max setting The max of V4L2_CID_COLORFX_CBCR is 0xffff, so add it to v4l2_ctrl_fill() to sure not beyond that. Signed-off-by: Dillon Min Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls-defs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index ebe82b6ba6e6..0cb6c0f18b39 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -1400,6 +1400,12 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, /* Max is calculated as RGB888 that is 2^24 */ *max = 0xFFFFFF; break; + case V4L2_CID_COLORFX_CBCR: + *type = V4L2_CTRL_TYPE_INTEGER; + *step = 1; + *min = 0; + *max = 0xffff; + break; case V4L2_CID_FLASH_FAULT: case V4L2_CID_JPEG_ACTIVE_MARKER: case V4L2_CID_3A_LOCK: From ef9f18a9e3a04126cf017216193166abe03dedef Mon Sep 17 00:00:00 2001 From: Dillon Min Date: Tue, 19 Oct 2021 09:43:21 +0100 Subject: [PATCH 006/397] media: v4l2-ctrls: Add RGB color effects control Add V4L2_COLORFX_SET_RGB color effects control, V4L2_CID_COLORFX_RGB for RGB color setting. with two mirror changes: - change 0xFFFFFF to 0xffffff - fix comments 2^24 to 2^24 - 1 [hverkuil: dropped spaces around + with V4L2_CID_BASE for consistency] Signed-off-by: Dillon Min Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/userspace-api/media/v4l/control.rst | 9 +++++++++ drivers/media/v4l2-core/v4l2-ctrls-defs.c | 6 ++++-- include/uapi/linux/v4l2-controls.h | 4 +++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Documentation/userspace-api/media/v4l/control.rst b/Documentation/userspace-api/media/v4l/control.rst index f8d0b923da20..3eec65174260 100644 --- a/Documentation/userspace-api/media/v4l/control.rst +++ b/Documentation/userspace-api/media/v4l/control.rst @@ -242,8 +242,17 @@ Control IDs * - ``V4L2_COLORFX_SET_CBCR`` - The Cb and Cr chroma components are replaced by fixed coefficients determined by ``V4L2_CID_COLORFX_CBCR`` control. + * - ``V4L2_COLORFX_SET_RGB`` + - The RGB components are replaced by the fixed RGB components determined + by ``V4L2_CID_COLORFX_RGB`` control. +``V4L2_CID_COLORFX_RGB`` ``(integer)`` + Determines the Red, Green, and Blue coefficients for + ``V4L2_COLORFX_SET_RGB`` color effect. + Bits [7:0] of the supplied 32 bit value are interpreted as Blue component, + bits [15:8] as Green component, bits [23:16] as Red component, and + bits [31:24] must be zero. ``V4L2_CID_COLORFX_CBCR`` ``(integer)`` Determines the Cb and Cr coefficients for ``V4L2_COLORFX_SET_CBCR`` diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index 0cb6c0f18b39..431f7ec17557 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -785,6 +785,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Min Number of Output Buffers"; case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr"; + case V4L2_CID_COLORFX_RGB: return "Color Effects, RGB"; /* * Codec controls @@ -1394,11 +1395,12 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, *min = *max = *step = *def = 0; break; case V4L2_CID_BG_COLOR: + case V4L2_CID_COLORFX_RGB: *type = V4L2_CTRL_TYPE_INTEGER; *step = 1; *min = 0; - /* Max is calculated as RGB888 that is 2^24 */ - *max = 0xFFFFFF; + /* Max is calculated as RGB888 that is 2^24 - 1 */ + *max = 0xffffff; break; case V4L2_CID_COLORFX_CBCR: *type = V4L2_CTRL_TYPE_INTEGER; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 5fea5feb0412..c9eea93a43a9 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -128,6 +128,7 @@ enum v4l2_colorfx { V4L2_COLORFX_SOLARIZATION = 13, V4L2_COLORFX_ANTIQUE = 14, V4L2_COLORFX_SET_CBCR = 15, + V4L2_COLORFX_SET_RGB = 16, }; #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) @@ -145,9 +146,10 @@ enum v4l2_colorfx { #define V4L2_CID_ALPHA_COMPONENT (V4L2_CID_BASE+41) #define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42) +#define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43) /* last CID + 1 */ -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+43) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44) /* USER-class private control IDs */ From 002e8f0d59277375154a054df15f925685c01a5c Mon Sep 17 00:00:00 2001 From: Dillon Min Date: Tue, 19 Oct 2021 09:43:23 +0100 Subject: [PATCH 007/397] media: stm32-dma2d: STM32 DMA2D driver This V4L2 subdev m2m driver enables Chrom-Art Accelerator unit of STMicroelectronics STM32 SoC series. Currently support r2m, m2m, m2m_pfc functions. - r2m, Filling a part or the whole of a destination image with a specific color. - m2m, Copying a part or the whole of a source image into a part or the whole of a destination. - m2m_pfc, Copying a part or the whole of a source image into a part or the whole of a destination image with a pixel format conversion. [hverkuil: fix typo in commit log] Signed-off-by: Dillon Min Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 11 + drivers/media/platform/Makefile | 1 + drivers/media/platform/stm32/Makefile | 2 + drivers/media/platform/stm32/dma2d/dma2d-hw.c | 143 ++++ .../media/platform/stm32/dma2d/dma2d-regs.h | 113 +++ drivers/media/platform/stm32/dma2d/dma2d.c | 739 ++++++++++++++++++ drivers/media/platform/stm32/dma2d/dma2d.h | 135 ++++ 7 files changed, 1144 insertions(+) create mode 100644 drivers/media/platform/stm32/dma2d/dma2d-hw.c create mode 100644 drivers/media/platform/stm32/dma2d/dma2d-regs.h create mode 100644 drivers/media/platform/stm32/dma2d/dma2d.c create mode 100644 drivers/media/platform/stm32/dma2d/dma2d.h diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index cf4adc64c953..68f16aef8754 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -492,6 +492,17 @@ config VIDEO_STI_DELTA_DRIVER endif # VIDEO_STI_DELTA +config VIDEO_STM32_DMA2D + tristate "STM32 Chrom-Art Accelerator (DMA2D)" + depends on (VIDEO_DEV && VIDEO_V4L2 && ARCH_STM32) || COMPILE_TEST + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + help + Enables DMA2D hardware support on stm32. + + The STM32 DMA2D is a memory-to-memory engine for pixel conversion + and specialized DMA dedicated to image manipulation. + config VIDEO_RENESAS_FDP1 tristate "Renesas Fine Display Processor" depends on VIDEO_DEV && VIDEO_V4L2 diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index a148553babfc..19bcbced7382 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel/ obj-$(CONFIG_VIDEO_ATMEL_XISC) += atmel/ obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32/ +obj-$(CONFIG_VIDEO_STM32_DMA2D) += stm32/ obj-$(CONFIG_VIDEO_MEDIATEK_VPU) += mtk-vpu/ diff --git a/drivers/media/platform/stm32/Makefile b/drivers/media/platform/stm32/Makefile index 48b36db2c2e2..896ef98a73ab 100644 --- a/drivers/media/platform/stm32/Makefile +++ b/drivers/media/platform/stm32/Makefile @@ -1,2 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32-dcmi.o +stm32-dma2d-objs := dma2d/dma2d.o dma2d/dma2d-hw.o +obj-$(CONFIG_VIDEO_STM32_DMA2D) += stm32-dma2d.o diff --git a/drivers/media/platform/stm32/dma2d/dma2d-hw.c b/drivers/media/platform/stm32/dma2d/dma2d-hw.c new file mode 100644 index 000000000000..8c1c664ab13b --- /dev/null +++ b/drivers/media/platform/stm32/dma2d/dma2d-hw.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * ST stm32 Chrom-Art - 2D Graphics Accelerator Driver + * + * Copyright (c) 2021 Dillon Min + * Dillon Min, + * + * based on s5p-g2d + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Kamil Debski, + */ + +#include + +#include "dma2d.h" +#include "dma2d-regs.h" + +static inline u32 reg_read(void __iomem *base, u32 reg) +{ + return readl_relaxed(base + reg); +} + +static inline void reg_write(void __iomem *base, u32 reg, u32 val) +{ + writel_relaxed(val, base + reg); +} + +static inline void reg_set(void __iomem *base, u32 reg, u32 mask) +{ + reg_write(base, reg, reg_read(base, reg) | mask); +} + +static inline void reg_clear(void __iomem *base, u32 reg, u32 mask) +{ + reg_write(base, reg, reg_read(base, reg) & ~mask); +} + +static inline void reg_update_bits(void __iomem *base, u32 reg, u32 mask, + u32 val) +{ + reg_write(base, reg, (reg_read(base, reg) & ~mask) | val); +} + +void dma2d_start(struct dma2d_dev *d) +{ + reg_update_bits(d->regs, DMA2D_CR_REG, CR_START, CR_START); +} + +u32 dma2d_get_int(struct dma2d_dev *d) +{ + return reg_read(d->regs, DMA2D_ISR_REG); +} + +void dma2d_clear_int(struct dma2d_dev *d) +{ + u32 isr_val = reg_read(d->regs, DMA2D_ISR_REG); + + reg_write(d->regs, DMA2D_IFCR_REG, isr_val & 0x003f); +} + +void dma2d_config_common(struct dma2d_dev *d, enum dma2d_op_mode op_mode, + u16 width, u16 height) +{ + reg_update_bits(d->regs, DMA2D_CR_REG, CR_MODE_MASK, + op_mode << CR_MODE_SHIFT); + + reg_write(d->regs, DMA2D_NLR_REG, (width << 16) | height); +} + +void dma2d_config_out(struct dma2d_dev *d, struct dma2d_frame *frm, + dma_addr_t o_addr) +{ + reg_update_bits(d->regs, DMA2D_CR_REG, CR_CEIE, CR_CEIE); + reg_update_bits(d->regs, DMA2D_CR_REG, CR_CTCIE, CR_CTCIE); + reg_update_bits(d->regs, DMA2D_CR_REG, CR_CAEIE, CR_CAEIE); + reg_update_bits(d->regs, DMA2D_CR_REG, CR_TCIE, CR_TCIE); + reg_update_bits(d->regs, DMA2D_CR_REG, CR_TEIE, CR_TEIE); + + if (frm->fmt->cmode >= CM_MODE_ARGB8888 && + frm->fmt->cmode <= CM_MODE_ARGB4444) + reg_update_bits(d->regs, DMA2D_OPFCCR_REG, OPFCCR_CM_MASK, + frm->fmt->cmode); + + reg_write(d->regs, DMA2D_OMAR_REG, o_addr); + + reg_write(d->regs, DMA2D_OCOLR_REG, + (frm->a_rgb[3] << 24) | + (frm->a_rgb[2] << 16) | + (frm->a_rgb[1] << 8) | + frm->a_rgb[0]); + + reg_update_bits(d->regs, DMA2D_OOR_REG, OOR_LO_MASK, + frm->line_offset & 0x3fff); +} + +void dma2d_config_fg(struct dma2d_dev *d, struct dma2d_frame *frm, + dma_addr_t f_addr) +{ + reg_write(d->regs, DMA2D_FGMAR_REG, f_addr); + reg_update_bits(d->regs, DMA2D_FGOR_REG, FGOR_LO_MASK, + frm->line_offset); + + if (frm->fmt->cmode >= CM_MODE_ARGB8888 && + frm->fmt->cmode <= CM_MODE_A4) + reg_update_bits(d->regs, DMA2D_FGPFCCR_REG, FGPFCCR_CM_MASK, + frm->fmt->cmode); + + reg_update_bits(d->regs, DMA2D_FGPFCCR_REG, FGPFCCR_AM_MASK, + (frm->a_mode << 16) & 0x03); + + reg_update_bits(d->regs, DMA2D_FGPFCCR_REG, FGPFCCR_ALPHA_MASK, + frm->a_rgb[3] << 24); + + reg_write(d->regs, DMA2D_FGCOLR_REG, + (frm->a_rgb[2] << 16) | + (frm->a_rgb[1] << 8) | + frm->a_rgb[0]); +} + +void dma2d_config_bg(struct dma2d_dev *d, struct dma2d_frame *frm, + dma_addr_t b_addr) +{ + reg_write(d->regs, DMA2D_BGMAR_REG, b_addr); + reg_update_bits(d->regs, DMA2D_BGOR_REG, BGOR_LO_MASK, + frm->line_offset); + + if (frm->fmt->cmode >= CM_MODE_ARGB8888 && + frm->fmt->cmode <= CM_MODE_A4) + reg_update_bits(d->regs, DMA2D_BGPFCCR_REG, BGPFCCR_CM_MASK, + frm->fmt->cmode); + + reg_update_bits(d->regs, DMA2D_BGPFCCR_REG, BGPFCCR_AM_MASK, + (frm->a_mode << 16) & 0x03); + + reg_update_bits(d->regs, DMA2D_BGPFCCR_REG, BGPFCCR_ALPHA_MASK, + frm->a_rgb[3] << 24); + + reg_write(d->regs, DMA2D_BGCOLR_REG, + (frm->a_rgb[2] << 16) | + (frm->a_rgb[1] << 8) | + frm->a_rgb[0]); +} diff --git a/drivers/media/platform/stm32/dma2d/dma2d-regs.h b/drivers/media/platform/stm32/dma2d/dma2d-regs.h new file mode 100644 index 000000000000..6444592d415b --- /dev/null +++ b/drivers/media/platform/stm32/dma2d/dma2d-regs.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * ST stm32 Chrom-Art - 2D Graphics Accelerator Driver + * + * Copyright (c) 2021 Dillon Min + * Dillon Min, + * + * based on s5p-g2d + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Kamil Debski, + */ + +#ifndef __DMA2D_REGS_H__ +#define __DMA2D_REGS_H__ + +#define DMA2D_CR_REG 0x0000 +#define CR_MODE_MASK GENMASK(17, 16) +#define CR_MODE_SHIFT 16 +#define CR_M2M 0x0000 +#define CR_M2M_PFC BIT(16) +#define CR_M2M_BLEND BIT(17) +#define CR_R2M (BIT(17) | BIT(16)) +#define CR_CEIE BIT(13) +#define CR_CTCIE BIT(12) +#define CR_CAEIE BIT(11) +#define CR_TWIE BIT(10) +#define CR_TCIE BIT(9) +#define CR_TEIE BIT(8) +#define CR_ABORT BIT(2) +#define CR_SUSP BIT(1) +#define CR_START BIT(0) + +#define DMA2D_ISR_REG 0x0004 +#define ISR_CEIF BIT(5) +#define ISR_CTCIF BIT(4) +#define ISR_CAEIF BIT(3) +#define ISR_TWIF BIT(2) +#define ISR_TCIF BIT(1) +#define ISR_TEIF BIT(0) + +#define DMA2D_IFCR_REG 0x0008 +#define IFCR_CCEIF BIT(5) +#define IFCR_CCTCIF BIT(4) +#define IFCR_CAECIF BIT(3) +#define IFCR_CTWIF BIT(2) +#define IFCR_CTCIF BIT(1) +#define IFCR_CTEIF BIT(0) + +#define DMA2D_FGMAR_REG 0x000c +#define DMA2D_FGOR_REG 0x0010 +#define FGOR_LO_MASK GENMASK(13, 0) + +#define DMA2D_BGMAR_REG 0x0014 +#define DMA2D_BGOR_REG 0x0018 +#define BGOR_LO_MASK GENMASK(13, 0) + +#define DMA2D_FGPFCCR_REG 0x001c +#define FGPFCCR_ALPHA_MASK GENMASK(31, 24) +#define FGPFCCR_AM_MASK GENMASK(17, 16) +#define FGPFCCR_CS_MASK GENMASK(15, 8) +#define FGPFCCR_START BIT(5) +#define FGPFCCR_CCM_RGB888 BIT(4) +#define FGPFCCR_CM_MASK GENMASK(3, 0) + +#define DMA2D_FGCOLR_REG 0x0020 +#define FGCOLR_REG_MASK GENMASK(23, 16) +#define FGCOLR_GREEN_MASK GENMASK(15, 8) +#define FGCOLR_BLUE_MASK GENMASK(7, 0) + +#define DMA2D_BGPFCCR_REG 0x0024 +#define BGPFCCR_ALPHA_MASK GENMASK(31, 24) +#define BGPFCCR_AM_MASK GENMASK(17, 16) +#define BGPFCCR_CS_MASK GENMASK(15, 8) +#define BGPFCCR_START BIT(5) +#define BGPFCCR_CCM_RGB888 BIT(4) +#define BGPFCCR_CM_MASK GENMASK(3, 0) + +#define DMA2D_BGCOLR_REG 0x0028 +#define BGCOLR_REG_MASK GENMASK(23, 16) +#define BGCOLR_GREEN_MASK GENMASK(15, 8) +#define BGCOLR_BLUE_MASK GENMASK(7, 0) + +#define DMA2D_OPFCCR_REG 0x0034 +#define OPFCCR_CM_MASK GENMASK(2, 0) + +#define DMA2D_OCOLR_REG 0x0038 +#define OCOLR_ALPHA_MASK GENMASK(31, 24) +#define OCOLR_RED_MASK GENMASK(23, 16) +#define OCOLR_GREEN_MASK GENMASK(15, 8) +#define OCOLR_BLUE_MASK GENMASK(7, 0) + +#define DMA2D_OMAR_REG 0x003c + +#define DMA2D_OOR_REG 0x0040 +#define OOR_LO_MASK GENMASK(13, 0) + +#define DMA2D_NLR_REG 0x0044 +#define NLR_PL_MASK GENMASK(29, 16) +#define NLR_NL_MASK GENMASK(15, 0) + +/* Hardware limits */ +#define MAX_WIDTH 2592 +#define MAX_HEIGHT 2592 + +#define DEFAULT_WIDTH 240 +#define DEFAULT_HEIGHT 320 +#define DEFAULT_SIZE 307200 + +#define CM_MODE_ARGB8888 0x00 +#define CM_MODE_ARGB4444 0x04 +#define CM_MODE_A4 0x0a +#endif /* __DMA2D_REGS_H__ */ diff --git a/drivers/media/platform/stm32/dma2d/dma2d.c b/drivers/media/platform/stm32/dma2d/dma2d.c new file mode 100644 index 000000000000..17af90d86898 --- /dev/null +++ b/drivers/media/platform/stm32/dma2d/dma2d.c @@ -0,0 +1,739 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * STM32 DMA2D - 2D Graphics Accelerator Driver + * + * Copyright (c) 2021 Dillon Min + * Dillon Min, + * + * based on s5p-g2d + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Kamil Debski, + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "dma2d.h" +#include "dma2d-regs.h" + +/* + * This V4L2 subdev m2m driver enables Chrom-Art Accelerator unit + * of STMicroelectronics STM32 SoC series. + * + * Currently support r2m, m2m, m2m_pfc. + * + * - r2m, Filling a part or the whole of a destination image with a specific + * color. + * - m2m, Copying a part or the whole of a source image into a part or the + * whole of a destination. + * - m2m_pfc, Copying a part or the whole of a source image into a part or the + * whole of a destination image with a pixel format conversion. + */ + +#define fh2ctx(__fh) container_of(__fh, struct dma2d_ctx, fh) + +static const struct dma2d_fmt formats[] = { + { + .fourcc = V4L2_PIX_FMT_ARGB32, + .cmode = DMA2D_CMODE_ARGB8888, + .depth = 32, + }, + { + .fourcc = V4L2_PIX_FMT_RGB24, + .cmode = DMA2D_CMODE_RGB888, + .depth = 24, + }, + { + .fourcc = V4L2_PIX_FMT_RGB565, + .cmode = DMA2D_CMODE_RGB565, + .depth = 16, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB555, + .cmode = DMA2D_CMODE_ARGB1555, + .depth = 16, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB444, + .cmode = DMA2D_CMODE_ARGB4444, + .depth = 16, + }, +}; + +#define NUM_FORMATS ARRAY_SIZE(formats) + +static const struct dma2d_frame def_frame = { + .width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + .line_offset = 0, + .a_rgb = {0x00, 0x00, 0x00, 0xff}, + .a_mode = DMA2D_ALPHA_MODE_NO_MODIF, + .fmt = (struct dma2d_fmt *)&formats[0], + .size = DEFAULT_SIZE, +}; + +static struct dma2d_fmt *find_fmt(int pixelformat) +{ + unsigned int i; + + for (i = 0; i < NUM_FORMATS; i++) { + if (formats[i].fourcc == pixelformat) + return (struct dma2d_fmt *)&formats[i]; + } + + return NULL; +} + +static struct dma2d_frame *get_frame(struct dma2d_ctx *ctx, + enum v4l2_buf_type type) +{ + return V4L2_TYPE_IS_OUTPUT(type) ? &ctx->cap : &ctx->out; +} + +static int dma2d_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) +{ + struct dma2d_ctx *ctx = vb2_get_drv_priv(vq); + struct dma2d_frame *f = get_frame(ctx, vq->type); + + if (*nplanes) + return sizes[0] < f->size ? -EINVAL : 0; + + sizes[0] = f->size; + *nplanes = 1; + + return 0; +} + +static int dma2d_buf_out_validate(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + + if (vbuf->field == V4L2_FIELD_ANY) + vbuf->field = V4L2_FIELD_NONE; + if (vbuf->field != V4L2_FIELD_NONE) + return -EINVAL; + + return 0; +} + +static int dma2d_buf_prepare(struct vb2_buffer *vb) +{ + struct dma2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct dma2d_frame *f = get_frame(ctx, vb->vb2_queue->type); + + if (vb2_plane_size(vb, 0) < f->size) + return -EINVAL; + + vb2_set_plane_payload(vb, 0, f->size); + + return 0; +} + +static void dma2d_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct dma2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); +} + +static int dma2d_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct dma2d_ctx *ctx = vb2_get_drv_priv(q); + struct dma2d_frame *f = get_frame(ctx, q->type); + + f->sequence = 0; + return 0; +} + +static void dma2d_stop_streaming(struct vb2_queue *q) +{ + struct dma2d_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) + return; + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); + } +} + +static const struct vb2_ops dma2d_qops = { + .queue_setup = dma2d_queue_setup, + .buf_out_validate = dma2d_buf_out_validate, + .buf_prepare = dma2d_buf_prepare, + .buf_queue = dma2d_buf_queue, + .start_streaming = dma2d_start_streaming, + .stop_streaming = dma2d_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 dma2d_ctx *ctx = priv; + int ret; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->drv_priv = ctx; + src_vq->ops = &dma2d_qops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->dev->mutex; + src_vq->dev = ctx->dev->v4l2_dev.dev; + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->drv_priv = ctx; + dst_vq->ops = &dma2d_qops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->dev->mutex; + dst_vq->dev = ctx->dev->v4l2_dev.dev; + + return vb2_queue_init(dst_vq); +} + +static int dma2d_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct dma2d_frame *frm; + struct dma2d_ctx *ctx = container_of(ctrl->handler, struct dma2d_ctx, + ctrl_handler); + unsigned long flags; + + spin_lock_irqsave(&ctx->dev->ctrl_lock, flags); + switch (ctrl->id) { + case V4L2_CID_COLORFX: + if (ctrl->val == V4L2_COLORFX_SET_RGB) + ctx->op_mode = DMA2D_MODE_R2M; + else if (ctrl->val == V4L2_COLORFX_NONE) + ctx->op_mode = DMA2D_MODE_M2M; + break; + case V4L2_CID_COLORFX_RGB: + frm = get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + frm->a_rgb[2] = (ctrl->val >> 16) & 0xff; + frm->a_rgb[1] = (ctrl->val >> 8) & 0xff; + frm->a_rgb[0] = (ctrl->val >> 0) & 0xff; + break; + default: + spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags); + return -EINVAL; + } + spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags); + + return 0; +} + +static const struct v4l2_ctrl_ops dma2d_ctrl_ops = { + .s_ctrl = dma2d_s_ctrl, +}; + +static int dma2d_setup_ctrls(struct dma2d_ctx *ctx) +{ + struct v4l2_ctrl_handler *handler = &ctx->ctrl_handler; + + v4l2_ctrl_handler_init(handler, 2); + + v4l2_ctrl_new_std_menu(handler, &dma2d_ctrl_ops, V4L2_CID_COLORFX, + V4L2_COLORFX_SET_RGB, ~0x10001, + V4L2_COLORFX_NONE); + + v4l2_ctrl_new_std(handler, &dma2d_ctrl_ops, V4L2_CID_COLORFX_RGB, 0, + 0xffffff, 1, 0); + + return 0; +} + +static int dma2d_open(struct file *file) +{ + struct dma2d_dev *dev = video_drvdata(file); + struct dma2d_ctx *ctx = NULL; + int ret = 0; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->dev = dev; + /* Set default formats */ + ctx->cap = def_frame; + ctx->bg = def_frame; + ctx->out = def_frame; + ctx->op_mode = DMA2D_MODE_M2M_FPC; + ctx->colorspace = V4L2_COLORSPACE_REC709; + if (mutex_lock_interruptible(&dev->mutex)) { + kfree(ctx); + return -ERESTARTSYS; + } + + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); + if (IS_ERR(ctx->fh.m2m_ctx)) { + ret = PTR_ERR(ctx->fh.m2m_ctx); + mutex_unlock(&dev->mutex); + kfree(ctx); + return ret; + } + + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; + v4l2_fh_add(&ctx->fh); + + dma2d_setup_ctrls(ctx); + + /* Write the default values to the ctx struct */ + v4l2_ctrl_handler_setup(&ctx->ctrl_handler); + + ctx->fh.ctrl_handler = &ctx->ctrl_handler; + mutex_unlock(&dev->mutex); + + return 0; +} + +static int dma2d_release(struct file *file) +{ + struct dma2d_dev *dev = video_drvdata(file); + struct dma2d_ctx *ctx = fh2ctx(file->private_data); + + mutex_lock(&dev->mutex); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); + mutex_unlock(&dev->mutex); + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + kfree(ctx); + + return 0; +} + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strscpy(cap->driver, DMA2D_NAME, sizeof(cap->driver)); + strscpy(cap->card, DMA2D_NAME, sizeof(cap->card)); + strscpy(cap->bus_info, BUS_INFO, sizeof(cap->bus_info)); + + return 0; +} + +static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) +{ + if (f->index >= NUM_FORMATS) + return -EINVAL; + + f->pixelformat = formats[f->index].fourcc; + return 0; +} + +static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) +{ + struct dma2d_ctx *ctx = prv; + struct vb2_queue *vq; + struct dma2d_frame *frm; + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + frm = get_frame(ctx, f->type); + f->fmt.pix.width = frm->width; + f->fmt.pix.height = frm->height; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.pixelformat = frm->fmt->fourcc; + f->fmt.pix.bytesperline = (frm->width * frm->fmt->depth) >> 3; + f->fmt.pix.sizeimage = frm->size; + 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_try_fmt(struct file *file, void *prv, struct v4l2_format *f) +{ + struct dma2d_ctx *ctx = prv; + struct dma2d_fmt *fmt; + enum v4l2_field *field; + u32 fourcc = f->fmt.pix.pixelformat; + + fmt = find_fmt(fourcc); + if (!fmt) { + f->fmt.pix.pixelformat = formats[0].fourcc; + fmt = find_fmt(f->fmt.pix.pixelformat); + } + + field = &f->fmt.pix.field; + if (*field == V4L2_FIELD_ANY) + *field = V4L2_FIELD_NONE; + else if (*field != V4L2_FIELD_NONE) + return -EINVAL; + + if (f->fmt.pix.width > MAX_WIDTH) + f->fmt.pix.width = MAX_WIDTH; + if (f->fmt.pix.height > MAX_HEIGHT) + f->fmt.pix.height = MAX_HEIGHT; + + if (f->fmt.pix.width < 1) + f->fmt.pix.width = 1; + if (f->fmt.pix.height < 1) + f->fmt.pix.height = 1; + + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && !f->fmt.pix.colorspace) { + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + 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; + } + f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) +{ + struct dma2d_ctx *ctx = prv; + struct vb2_queue *vq; + struct dma2d_frame *frm; + struct dma2d_fmt *fmt; + int ret = 0; + + /* Adjust all values accordingly to the hardware capabilities + * and chosen format. + */ + ret = vidioc_try_fmt(file, prv, f); + if (ret) + return ret; + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (vb2_is_busy(vq)) + return -EBUSY; + + fmt = find_fmt(f->fmt.pix.pixelformat); + if (!fmt) + return -EINVAL; + + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + 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; + } + + frm = get_frame(ctx, f->type); + frm->width = f->fmt.pix.width; + frm->height = f->fmt.pix.height; + frm->size = f->fmt.pix.sizeimage; + /* Reset crop settings */ + frm->o_width = 0; + frm->o_height = 0; + frm->c_width = frm->width; + frm->c_height = frm->height; + frm->right = frm->width; + frm->bottom = frm->height; + frm->fmt = fmt; + frm->line_offset = 0; + + return 0; +} + +static void device_run(void *prv) +{ + struct dma2d_ctx *ctx = prv; + struct dma2d_dev *dev = ctx->dev; + struct dma2d_frame *frm_out, *frm_cap; + struct vb2_v4l2_buffer *src, *dst; + unsigned long flags; + + spin_lock_irqsave(&dev->ctrl_lock, flags); + dev->curr = ctx; + + src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + if (!dst || !src) + goto end; + + frm_cap = get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + frm_out = get_frame(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + if (!frm_cap || !frm_out) + goto end; + + src->sequence = frm_out->sequence++; + dst->sequence = frm_cap->sequence++; + v4l2_m2m_buf_copy_metadata(src, dst, true); + + clk_enable(dev->gate); + + dma2d_config_fg(dev, frm_out, + vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0)); + + /* TODO: add M2M_BLEND handler here */ + + if (ctx->op_mode != DMA2D_MODE_R2M) { + if (frm_out->fmt->fourcc == frm_cap->fmt->fourcc) + ctx->op_mode = DMA2D_MODE_M2M; + else + ctx->op_mode = DMA2D_MODE_M2M_FPC; + } + + dma2d_config_out(dev, frm_cap, + vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0)); + dma2d_config_common(dev, ctx->op_mode, frm_cap->width, frm_cap->height); + + dma2d_start(dev); +end: + spin_unlock_irqrestore(&dev->ctrl_lock, flags); +} + +static irqreturn_t dma2d_isr(int irq, void *prv) +{ + struct dma2d_dev *dev = prv; + struct dma2d_ctx *ctx = dev->curr; + struct vb2_v4l2_buffer *src, *dst; + u32 s = dma2d_get_int(dev); + + dma2d_clear_int(dev); + if (s & ISR_TCIF || s == 0) { + clk_disable(dev->gate); + + WARN_ON(!ctx); + + src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + + WARN_ON(!dst); + WARN_ON(!src); + + v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); + v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); + v4l2_m2m_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx); + + dev->curr = NULL; + } + + return IRQ_HANDLED; +} + +static const struct v4l2_file_operations dma2d_fops = { + .owner = THIS_MODULE, + .open = dma2d_open, + .release = dma2d_release, + .poll = v4l2_m2m_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, +#ifndef CONFIG_MMU + .get_unmapped_area = v4l2_m2m_get_unmapped_area, +#endif +}; + +static const struct v4l2_ioctl_ops dma2d_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt, + + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt, + .vidioc_g_fmt_vid_out = vidioc_g_fmt, + .vidioc_try_fmt_vid_out = vidioc_try_fmt, + .vidioc_s_fmt_vid_out = vidioc_s_fmt, + + .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, +}; + +static const struct video_device dma2d_videodev = { + .name = DMA2D_NAME, + .fops = &dma2d_fops, + .ioctl_ops = &dma2d_ioctl_ops, + .minor = -1, + .release = video_device_release, + .vfl_dir = VFL_DIR_M2M, +}; + +static const struct v4l2_m2m_ops dma2d_m2m_ops = { + .device_run = device_run, +}; + +static const struct of_device_id stm32_dma2d_match[]; + +static int dma2d_probe(struct platform_device *pdev) +{ + struct dma2d_dev *dev; + struct video_device *vfd; + struct resource *res; + int ret = 0; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + spin_lock_init(&dev->ctrl_lock); + mutex_init(&dev->mutex); + atomic_set(&dev->num_inst, 0); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + dev->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->regs)) + return PTR_ERR(dev->regs); + + dev->gate = clk_get(&pdev->dev, "dma2d"); + if (IS_ERR(dev->gate)) { + dev_err(&pdev->dev, "failed to get dma2d clock gate\n"); + ret = -ENXIO; + return ret; + } + + ret = clk_prepare(dev->gate); + if (ret) { + dev_err(&pdev->dev, "failed to prepare dma2d clock gate\n"); + goto put_clk_gate; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "failed to find IRQ\n"); + ret = -ENXIO; + goto unprep_clk_gate; + } + + dev->irq = res->start; + + ret = devm_request_irq(&pdev->dev, dev->irq, dma2d_isr, + 0, pdev->name, dev); + if (ret) { + dev_err(&pdev->dev, "failed to install IRQ\n"); + goto unprep_clk_gate; + } + + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) + goto unprep_clk_gate; + + vfd = video_device_alloc(); + if (!vfd) { + v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n"); + ret = -ENOMEM; + goto unreg_v4l2_dev; + } + + *vfd = dma2d_videodev; + vfd->lock = &dev->mutex; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; + + platform_set_drvdata(pdev, dev); + dev->m2m_dev = v4l2_m2m_init(&dma2d_m2m_ops); + if (IS_ERR(dev->m2m_dev)) { + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); + ret = PTR_ERR(dev->m2m_dev); + goto rel_vdev; + } + + ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); + if (ret) { + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); + goto free_m2m; + } + + video_set_drvdata(vfd, dev); + dev->vfd = vfd; + v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n", + vfd->num); + return 0; + +free_m2m: + v4l2_m2m_release(dev->m2m_dev); +rel_vdev: + video_device_release(vfd); +unreg_v4l2_dev: + v4l2_device_unregister(&dev->v4l2_dev); +unprep_clk_gate: + clk_unprepare(dev->gate); +put_clk_gate: + clk_put(dev->gate); + + return ret; +} + +static int dma2d_remove(struct platform_device *pdev) +{ + struct dma2d_dev *dev = platform_get_drvdata(pdev); + + v4l2_info(&dev->v4l2_dev, "Removing " DMA2D_NAME); + v4l2_m2m_release(dev->m2m_dev); + video_unregister_device(dev->vfd); + v4l2_device_unregister(&dev->v4l2_dev); + vb2_dma_contig_clear_max_seg_size(&pdev->dev); + clk_unprepare(dev->gate); + clk_put(dev->gate); + + return 0; +} + +static const struct of_device_id stm32_dma2d_match[] = { + { + .compatible = "st,stm32-dma2d", + .data = NULL, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, stm32_dma2d_match); + +static struct platform_driver dma2d_pdrv = { + .probe = dma2d_probe, + .remove = dma2d_remove, + .driver = { + .name = DMA2D_NAME, + .of_match_table = stm32_dma2d_match, + }, +}; + +module_platform_driver(dma2d_pdrv); + +MODULE_AUTHOR("Dillon Min "); +MODULE_DESCRIPTION("STM32 Chrom-Art Accelerator DMA2D driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/stm32/dma2d/dma2d.h b/drivers/media/platform/stm32/dma2d/dma2d.h new file mode 100644 index 000000000000..3f03a7ca9ee3 --- /dev/null +++ b/drivers/media/platform/stm32/dma2d/dma2d.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * ST stm32 DMA2D - 2D Graphics Accelerator Driver + * + * Copyright (c) 2021 Dillon Min + * Dillon Min, + * + * based on s5p-g2d + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Kamil Debski, + */ + +#ifndef __DMA2D_H__ +#define __DMA2D_H__ + +#include +#include +#include + +#define DMA2D_NAME "stm-dma2d" +#define BUS_INFO "platform:stm-dma2d" +enum dma2d_op_mode { + DMA2D_MODE_M2M, + DMA2D_MODE_M2M_FPC, + DMA2D_MODE_M2M_BLEND, + DMA2D_MODE_R2M +}; + +enum dma2d_cmode { + /* output pfc cmode from ARGB888 to ARGB4444 */ + DMA2D_CMODE_ARGB8888, + DMA2D_CMODE_RGB888, + DMA2D_CMODE_RGB565, + DMA2D_CMODE_ARGB1555, + DMA2D_CMODE_ARGB4444, + /* bg or fg pfc cmode from L8 to A4 */ + DMA2D_CMODE_L8, + DMA2D_CMODE_AL44, + DMA2D_CMODE_AL88, + DMA2D_CMODE_L4, + DMA2D_CMODE_A8, + DMA2D_CMODE_A4 +}; + +enum dma2d_alpha_mode { + DMA2D_ALPHA_MODE_NO_MODIF, + DMA2D_ALPHA_MODE_REPLACE, + DMA2D_ALPHA_MODE_COMBINE +}; + +struct dma2d_fmt { + u32 fourcc; + int depth; + enum dma2d_cmode cmode; +}; + +struct dma2d_frame { + /* Original dimensions */ + u32 width; + u32 height; + /* Crop size */ + u32 c_width; + u32 c_height; + /* Offset */ + u32 o_width; + u32 o_height; + u32 bottom; + u32 right; + u16 line_offset; + /* Image format */ + struct dma2d_fmt *fmt; + /* [0]: blue + * [1]: green + * [2]: red + * [3]: alpha + */ + u8 a_rgb[4]; + /* + * AM[1:0] of DMA2D_FGPFCCR + */ + enum dma2d_alpha_mode a_mode; + u32 size; + unsigned int sequence; +}; + +struct dma2d_ctx { + struct v4l2_fh fh; + struct dma2d_dev *dev; + struct dma2d_frame cap; + struct dma2d_frame out; + struct dma2d_frame bg; + /* fb_buf always point to bg address */ + struct v4l2_framebuffer fb_buf; + /* + * MODE[17:16] of DMA2D_CR + */ + enum dma2d_op_mode op_mode; + struct v4l2_ctrl_handler ctrl_handler; + enum v4l2_colorspace colorspace; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_xfer_func xfer_func; + enum v4l2_quantization quant; +}; + +struct dma2d_dev { + struct v4l2_device v4l2_dev; + struct v4l2_m2m_dev *m2m_dev; + struct video_device *vfd; + /* for device open/close etc */ + struct mutex mutex; + /* to avoid the conflict with device running and user setting + * at the same time + */ + spinlock_t ctrl_lock; + atomic_t num_inst; + void __iomem *regs; + struct clk *gate; + struct dma2d_ctx *curr; + int irq; +}; + +void dma2d_start(struct dma2d_dev *d); +u32 dma2d_get_int(struct dma2d_dev *d); +void dma2d_clear_int(struct dma2d_dev *d); +void dma2d_config_out(struct dma2d_dev *d, struct dma2d_frame *frm, + dma_addr_t o_addr); +void dma2d_config_fg(struct dma2d_dev *d, struct dma2d_frame *frm, + dma_addr_t f_addr); +void dma2d_config_bg(struct dma2d_dev *d, struct dma2d_frame *frm, + dma_addr_t b_addr); +void dma2d_config_common(struct dma2d_dev *d, enum dma2d_op_mode op_mode, + u16 width, u16 height); + +#endif /* __DMA2D_H__ */ From cffd616086fd03a8e586fc863109697a2431567a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Oct 2021 10:24:09 +0100 Subject: [PATCH 008/397] media: atomisp: get rid of two unused functions Those cause build to break with -Werror with clang-12: drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gdc.c:121:24: error: unused function 'gdc_reg_load' [-Werror,-Wunused-function] drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c:33:1: error: unused function 'sh_css_elems_bytes_from_info' [-Werror,-Wunused-function] Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/hive_isp_css_common/host/gdc.c | 11 ----------- .../pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c | 6 ------ 2 files changed, 17 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gdc.c b/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gdc.c index 8ed1cffc5384..25e082d6a94a 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gdc.c +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gdc.c @@ -28,10 +28,6 @@ static inline void gdc_reg_store( const unsigned int reg, const hrt_data value); -static inline hrt_data gdc_reg_load( - const gdc_ID_t ID, - const unsigned int reg); - #ifndef __INLINE_GDC__ #include "gdc_private.h" #endif /* __INLINE_GDC__ */ @@ -117,10 +113,3 @@ static inline void gdc_reg_store( ia_css_device_store_uint32(GDC_BASE[ID] + reg * sizeof(hrt_data), value); return; } - -static inline hrt_data gdc_reg_load( - const gdc_ID_t ID, - const unsigned int reg) -{ - return ia_css_device_load_uint32(GDC_BASE[ID] + reg * sizeof(hrt_data)); -} diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c index c505c94a7241..f741beb9ed8a 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c @@ -29,12 +29,6 @@ static const struct ia_css_raw_configuration default_config = { .pipe = (struct sh_css_sp_pipeline *)NULL, }; -static inline unsigned -sh_css_elems_bytes_from_info(unsigned int raw_bit_depth) -{ - return CEIL_DIV(raw_bit_depth, 8); -} - /* MW: These areMIPI / ISYS properties, not camera function properties */ static enum sh_stream_format css2isp_stream_format(enum atomisp_input_format from) { From 9b005ce90628b6cb7702dcd7d4d512a8b3943519 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Mon, 18 Oct 2021 03:48:15 +0100 Subject: [PATCH 009/397] media: staging: ipu3-imgu: clarify the limitation of grid config There are some grid configuration limitations for ImgU, which was not described clearly in current uAPI header file, add the description to help user to set the grid configuration correctly. Signed-off-by: Bingbu Cao Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Jean-Michel Hautbois Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/ipu3/include/uapi/intel-ipu3.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h b/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h index 585f55981c86..a3ffd486d291 100644 --- a/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h +++ b/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h @@ -34,11 +34,17 @@ * struct ipu3_uapi_grid_config - Grid plane config * * @width: Grid horizontal dimensions, in number of grid blocks(cells). + * For AWB, the range is (16, 80). + * For AF/AE, the range is (16, 32). * @height: Grid vertical dimensions, in number of grid cells. + * For AWB, the range is (16, 60). + * For AF/AE, the range is (16, 24). * @block_width_log2: Log2 of the width of each cell in pixels. - * for (2^3, 2^4, 2^5, 2^6, 2^7), values [3, 7]. + * For AWB, the range is [3, 6]. + * For AF/AE, the range is [3, 7]. * @block_height_log2: Log2 of the height of each cell in pixels. - * for (2^3, 2^4, 2^5, 2^6, 2^7), values [3, 7]. + * For AWB, the range is [3, 6]. + * For AF/AE, the range is [3, 7]. * @height_per_slice: The number of blocks in vertical axis per slice. * Default 2. * @x_start: X value of top left corner of Region of Interest(ROI). From 85db29d22cc521d9d06de2f5c7832981a55df157 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Oct 2021 08:53:19 +0100 Subject: [PATCH 010/397] media: ipu3-cio2: fix error code in cio2_bridge_connect_sensor() Return -ENODEV if acpi_get_physical_device_location() fails. Don't return success. Fixes: 485aa3df0dff ("media: ipu3-cio2: Parse sensor orientation and rotation") Signed-off-by: Dan Carpenter Reviewed-by: Daniel Scally Reviewed-by: Kieran Bingham Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 67c467d3c81f..0b586b4e537e 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -238,8 +238,10 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, goto err_put_adev; status = acpi_get_physical_device_location(adev->handle, &sensor->pld); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + ret = -ENODEV; goto err_put_adev; + } if (sensor->ssdb.lanes > CIO2_MAX_LANES) { dev_err(&adev->dev, From 2a998392403f746e9320c3b836303f8720651e5c Mon Sep 17 00:00:00 2001 From: Qing Wang Date: Mon, 18 Oct 2021 09:00:36 +0100 Subject: [PATCH 011/397] media: i2c: ccs: replace snprintf in show functions with sysfs_emit show() should not use snprintf() when formatting the value to be returned to user space. Fix the following coccicheck warning: drivers/media/i2c/ccs/ccs-core.c:3761: WARNING: use scnprintf or sprintf. Signed-off-by: Qing Wang Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ccs/ccs-core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 5363f3bcafe3..9158d3ce45c0 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -2758,13 +2758,13 @@ ident_show(struct device *dev, struct device_attribute *attr, char *buf) struct ccs_module_info *minfo = &sensor->minfo; if (minfo->mipi_manufacturer_id) - return snprintf(buf, PAGE_SIZE, "%4.4x%4.4x%2.2x\n", - minfo->mipi_manufacturer_id, minfo->model_id, - minfo->revision_number) + 1; + return sysfs_emit(buf, "%4.4x%4.4x%2.2x\n", + minfo->mipi_manufacturer_id, minfo->model_id, + minfo->revision_number) + 1; else - return snprintf(buf, PAGE_SIZE, "%2.2x%4.4x%2.2x\n", - minfo->smia_manufacturer_id, minfo->model_id, - minfo->revision_number) + 1; + return sysfs_emit(buf, "%2.2x%4.4x%2.2x\n", + minfo->smia_manufacturer_id, minfo->model_id, + minfo->revision_number) + 1; } static DEVICE_ATTR_RO(ident); From c09d776eaa060534a1663e3b89d842db3e1d9076 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Fri, 15 Oct 2021 07:08:39 +0100 Subject: [PATCH 012/397] media: dw9768: activate runtime PM and turn off device When dw9768 working with ACPI systems, the dw9768 was turned by i2c-core during probe, driver need activate the PM runtime and ask runtime PM to turn off the device. Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/dw9768.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c index c086580efac7..65c6acf3ced9 100644 --- a/drivers/media/i2c/dw9768.c +++ b/drivers/media/i2c/dw9768.c @@ -469,6 +469,11 @@ static int dw9768_probe(struct i2c_client *client) dw9768->sd.entity.function = MEDIA_ENT_F_LENS; + /* + * Device is already turned on by i2c-core with ACPI domain PM. + * Attempt to turn off the device to satisfy the privacy LED concerns. + */ + pm_runtime_set_active(dev); pm_runtime_enable(dev); if (!pm_runtime_enabled(dev)) { ret = dw9768_runtime_resume(dev); @@ -483,6 +488,7 @@ static int dw9768_probe(struct i2c_client *client) dev_err(dev, "failed to register V4L2 subdev: %d", ret); goto err_power_off; } + pm_runtime_idle(dev); return 0; From ce3015b7212e96db426d0c36f80fd159c91155d1 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:41 +0900 Subject: [PATCH 013/397] media: atomisp: add missing media_device_cleanup() in atomisp_unregister_entities() After the commit 9832e155f1ed ("[media] media-device: split media initialization and registration"), calling media_device_cleanup() is needed it seems. However, currently it is missing for the module unload path. Note that for the probe failure path, it is already added in atomisp_register_entities(). This patch adds the missing call of media_device_cleanup() in atomisp_unregister_entities(). Fixes: a49d25364dfb ("staging/atomisp: Add support for the Intel IPU v2") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 1e324f1f656e..0511c454e769 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -1182,6 +1182,7 @@ static void atomisp_unregister_entities(struct atomisp_device *isp) v4l2_device_unregister(&isp->v4l2_dev); media_device_unregister(&isp->media_dev); + media_device_cleanup(&isp->media_dev); } static int atomisp_register_entities(struct atomisp_device *isp) From 5bfbf65fcca7325e4d89d289b3c286e11220e386 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:42 +0900 Subject: [PATCH 014/397] media: atomisp: fix punit_ddr_dvfs_enable() argument for mrfld_power up case When comparing with intel-aero atomisp [1], it looks like punit_ddr_dvfs_enable() should take `false` as an argument on mrfld_power up case. Code from the intel-aero kernel [1]: int atomisp_mrfld_power_down(struct atomisp_device *isp) { [...] /*WA:Enable DVFS*/ if (IS_CHT) punit_ddr_dvfs_enable(true); int atomisp_mrfld_power_up(struct atomisp_device *isp) { [...] /*WA for PUNIT, if DVFS enabled, ISP timeout observed*/ if (IS_CHT) punit_ddr_dvfs_enable(false); This patch fixes the inverted argument as per the intel-aero code, as well as its comment. While here, fix space issues for comments in atomisp_mrfld_power(). Note that it does not seem to be possible to unify the up/down cases for punit_ddr_dvfs_enable(), i.e., we can't do something like the following: if (IS_CHT) punit_ddr_dvfs_enable(!enable); because according to the intel-aero code [1], the DVFS is disabled before "writing 0x0 to ISPSSPM0 bit[1:0]" and the DVFS is enabled after "writing 0x3 to ISPSSPM0 bit[1:0]". [1] https://github.com/intel-aero/linux-kernel/blob/a1b673258feb915268377275130c5c5df0eafc82/drivers/media/pci/atomisp/atomisp_driver/atomisp_v4l2.c#L431-L514 Fixes: 0f441fd70b1e ("media: atomisp: simplify the power down/up code") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 0511c454e769..7982cc143374 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -711,15 +711,15 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable) dev_dbg(isp->dev, "IUNIT power-%s.\n", enable ? "on" : "off"); - /*WA:Enable DVFS*/ + /* WA for P-Unit, if DVFS enabled, ISP timeout observed */ if (IS_CHT && enable) - punit_ddr_dvfs_enable(true); + punit_ddr_dvfs_enable(false); /* * FIXME:WA for ECS28A, with this sleep, CTS * android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceAbort * PASS, no impact on other platforms - */ + */ if (IS_BYT && enable) msleep(10); @@ -727,7 +727,7 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable) iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, val, MRFLD_ISPSSPM0_ISPSSC_MASK); - /*WA:Enable DVFS*/ + /* WA:Enable DVFS */ if (IS_CHT && !enable) punit_ddr_dvfs_enable(true); From e1921cd14640f0f4d1fad5eb8e448c58a536415d Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:43 +0900 Subject: [PATCH 015/397] media: atomisp: fix inverted logic in buffers_needed() When config.mode is IA_CSS_INPUT_MODE_BUFFERED_SENSOR, it rather needs buffers. Fix it by inverting the return value. Fixes: 3c0538fbad9f ("media: atomisp: get rid of most checks for ISP2401 version") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css_mipi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index 75489f7d75ee..483d40a467c7 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -374,17 +374,17 @@ static bool buffers_needed(struct ia_css_pipe *pipe) { if (!IS_ISP2401) { if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) - return false; - else return true; + else + return false; } if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR || pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG || pipe->stream->config.mode == IA_CSS_INPUT_MODE_PRBS) - return false; + return true; - return true; + return false; } int From 9f6b4fa2d2dfbff4b8a57eeb39b1128a6094ee20 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:44 +0900 Subject: [PATCH 016/397] media: atomisp: do not use err var when checking port validity for ISP2400 Currently, the `port >= N_CSI_PORTS || err` checks for ISP2400 are always evaluated as true because the err variable is set to `-EINVAL` on declaration but the variable is never used until the evaluation. Looking at the diff of commit 3c0538fbad9f ("media: atomisp: get rid of most checks for ISP2401 version"), the `port >= N_CSI_PORTS` check is for ISP2400 and the err variable check is for ISP2401. Fix this issue by adding ISP version test there accordingly. Fixes: 3c0538fbad9f ("media: atomisp: get rid of most checks for ISP2401 version") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css_mipi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index 483d40a467c7..65fc93c5d56b 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -430,7 +430,8 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, assert(port < N_CSI_PORTS); - if (port >= N_CSI_PORTS || err) { + if ((!IS_ISP2401 && port >= N_CSI_PORTS) || + (IS_ISP2401 && err)) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: error: port is not correct (port=%d).\n", pipe, port); @@ -559,7 +560,8 @@ free_mipi_frames(struct ia_css_pipe *pipe) assert(port < N_CSI_PORTS); - if (port >= N_CSI_PORTS || err) { + if ((!IS_ISP2401 && port >= N_CSI_PORTS) || + (IS_ISP2401 && err)) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "free_mipi_frames(%p, %d) exit: error: pipe port is not correct.\n", pipe, port); @@ -670,7 +672,8 @@ send_mipi_frames(struct ia_css_pipe *pipe) assert(port < N_CSI_PORTS); - if (port >= N_CSI_PORTS || err) { + if ((!IS_ISP2401 && port >= N_CSI_PORTS) || + (IS_ISP2401 && err)) { IA_CSS_ERROR("send_mipi_frames(%p) exit: invalid port specified (port=%d).\n", pipe, port); return err; From d21ce8c2f7bf6d737b60c09f86db141b9e8e47f0 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:45 +0900 Subject: [PATCH 017/397] media: atomisp: fix inverted error check for ia_css_mipi_is_source_port_valid() The function ia_css_mipi_is_source_port_valid() returns true if the port is valid. So, we can't use the existing err variable as is. To fix this issue while reusing that variable, invert the return value when assigning it to the variable. Fixes: 3c0538fbad9f ("media: atomisp: get rid of most checks for ISP2401 version") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/sh_css_mipi.c | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index 65fc93c5d56b..c1f2f6151c5f 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -423,10 +423,12 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, return 0; /* AM TODO: Check */ } - if (!IS_ISP2401) + if (!IS_ISP2401) { port = (unsigned int)pipe->stream->config.source.port.port; - else - err = ia_css_mipi_is_source_port_valid(pipe, &port); + } else { + /* Returns true if port is valid. So, invert it */ + err = !ia_css_mipi_is_source_port_valid(pipe, &port); + } assert(port < N_CSI_PORTS); @@ -553,10 +555,12 @@ free_mipi_frames(struct ia_css_pipe *pipe) return err; } - if (!IS_ISP2401) + if (!IS_ISP2401) { port = (unsigned int)pipe->stream->config.source.port.port; - else - err = ia_css_mipi_is_source_port_valid(pipe, &port); + } else { + /* Returns true if port is valid. So, invert it */ + err = !ia_css_mipi_is_source_port_valid(pipe, &port); + } assert(port < N_CSI_PORTS); @@ -665,10 +669,12 @@ send_mipi_frames(struct ia_css_pipe *pipe) /* TODO: AM: maybe this should be returning an error. */ } - if (!IS_ISP2401) + if (!IS_ISP2401) { port = (unsigned int)pipe->stream->config.source.port.port; - else - err = ia_css_mipi_is_source_port_valid(pipe, &port); + } else { + /* Returns true if port is valid. So, invert it */ + err = !ia_css_mipi_is_source_port_valid(pipe, &port); + } assert(port < N_CSI_PORTS); From 6fb5d718b08c8bb9b60cfbf5a0a19fa4f77ca29d Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:46 +0900 Subject: [PATCH 018/397] media: atomisp: use IA_CSS_ERROR() for error messages in sh_css_mipi.c Some debug messages for error cases (messages contain "error: ") use IA_CSS_DEBUG_TRACE_PRIVATE debug level. This causes these error messages not to appear unless users raise debug output level to 7 or higher (using module parameter, dbg_level=7). So, use IA_CSS_DEBUG_ERROR debug level (dbg_level=1) instead considering that these are error messages. There is already a macro IA_CSS_ERROR() for this use case. Let's use it. It automatically appends "error: " at the beginning and a newline to a message. Therefore, we can remove them from these messages. While here, remove the unnecessary newline from one IA_CSS_ERROR() occurrence in the same file. Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/sh_css_mipi.c | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index c1f2f6151c5f..de56a1da754d 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -434,9 +434,8 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, if ((!IS_ISP2401 && port >= N_CSI_PORTS) || (IS_ISP2401 && err)) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "allocate_mipi_frames(%p) exit: error: port is not correct (port=%d).\n", - pipe, port); + IA_CSS_ERROR("allocate_mipi_frames(%p) exit: port is not correct (port=%d).", + pipe, port); return -EINVAL; } @@ -497,9 +496,8 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, my_css.mipi_frames[port][j] = NULL; } } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "allocate_mipi_frames(%p, %d) exit: error: allocation failed.\n", - pipe, port); + IA_CSS_ERROR("allocate_mipi_frames(%p, %d) exit: allocation failed.", + pipe, port); return err; } } @@ -542,16 +540,14 @@ free_mipi_frames(struct ia_css_pipe *pipe) if (pipe) { assert(pipe->stream); if ((!pipe) || (!pipe->stream)) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "free_mipi_frames(%p) exit: error: pipe or stream is null.\n", - pipe); + IA_CSS_ERROR("free_mipi_frames(%p) exit: pipe or stream is null.", + pipe); return -EINVAL; } if (!buffers_needed(pipe)) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "free_mipi_frames(%p) exit: error: wrong mode.\n", - pipe); + IA_CSS_ERROR("free_mipi_frames(%p) exit: wrong mode.", + pipe); return err; } @@ -566,9 +562,8 @@ free_mipi_frames(struct ia_css_pipe *pipe) if ((!IS_ISP2401 && port >= N_CSI_PORTS) || (IS_ISP2401 && err)) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "free_mipi_frames(%p, %d) exit: error: pipe port is not correct.\n", - pipe, port); + IA_CSS_ERROR("free_mipi_frames(%p, %d) exit: pipe port is not correct.", + pipe, port); return err; } @@ -576,9 +571,8 @@ free_mipi_frames(struct ia_css_pipe *pipe) #if !defined(ISP2401) assert(ref_count_mipi_allocation[port] == 1); if (ref_count_mipi_allocation[port] != 1) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "free_mipi_frames(%p) exit: error: wrong ref_count (ref_count=%d).\n", - pipe, ref_count_mipi_allocation[port]); + IA_CSS_ERROR("free_mipi_frames(%p) exit: wrong ref_count (ref_count=%d).", + pipe, ref_count_mipi_allocation[port]); return err; } #endif @@ -680,7 +674,7 @@ send_mipi_frames(struct ia_css_pipe *pipe) if ((!IS_ISP2401 && port >= N_CSI_PORTS) || (IS_ISP2401 && err)) { - IA_CSS_ERROR("send_mipi_frames(%p) exit: invalid port specified (port=%d).\n", + IA_CSS_ERROR("send_mipi_frames(%p) exit: invalid port specified (port=%d).", pipe, port); return err; } From 5a1b2725558f8a3b4cbf0504f53cffae8e163034 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:47 +0900 Subject: [PATCH 019/397] media: atomisp: fix ifdefs in sh_css.c ## `if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) {` case The intel-aero atomisp has `#if defined(IS_ISP_2400_SYSTEM)` [1]. It is to be defined in the following two places [2]: - css/hive_isp_css_common/system_global.h - css/css_2401_csi2p_system/system_global.h and the former file is to be included on ISP2400 devices, too. So, it is to be defined for both ISP2400 and ISP2401 devices. Because the upstreamed atomisp driver now supports only ISP2400 and ISP2401, just remove the ISP version test again. This matches the other upstream commits like 3c0538fbad9f ("media: atomisp: get rid of most checks for ISP2401 version"). While here, moved the comment for define GP_ISEL_TPG_MODE to the appropriate place. [1] https://github.com/intel-aero/linux-kernel/blob/a1b673258feb915268377275130c5c5df0eafc82/drivers/media/pci/atomisp/css/sh_css.c#L552-L558 [2] https://github.com/intel-aero/linux-kernel/search?q=IS_ISP_2400_SYSTEM ## `isys_stream_descr->polling_mode` case This does not exist on the intel-aero atomisp. This is because it is based on css version irci_stable_candrpv_0415_20150521_0458. On the other hand, the upstreamed atomisp is based on the following css version depending on the ISP version using ifdefs: - ISP2400: irci_stable_candrpv_0415_20150521_0458 - ISP2401: irci_master_20150911_0724 The `isys_stream_descr->polling_mode` usage was added on updating css version to irci_master_20150701_0213 [3]. So, it is not a ISP version specific thing, but css version specific thing. Because the upstreamed atomisp driver uses irci_master_20150911_0724 for ISP2401, re-add the ISP version check for now. I say "for now" because ISP2401 should eventually use the same css version with ISP2400 (i.e., irci_stable_candrpv_0415_20150521_0458) [3] https://raw.githubusercontent.com/intel/ProductionKernelQuilts/cht-m1stable-2016_ww31/uefi/cht-m1stable/patches/cam-0439-atomisp2-css2401-and-2401_legacy-irci_master_2015070.patch ("atomisp2: css2401 and 2401_legacy-irci_master_20150701_0213") Link to Intel's Android kernel patch. ## `coord = &me->config.internal_frame_origin_bqs_on_sctbl;` case it was added on commit 4f744a573db3 ("media: atomisp: make sh_css_sp_init_pipeline() ISP version independent") for ISP2401. Because the upstreamed atomisp for the ISP2401 part is based on irci_master_20150911_0724, hence the difference. Because the upstreamed atomisp driver uses irci_master_20150911_0724 for ISP2401, revert the test back to `if (IS_ISP2401)`. Fixes: 27333dadef57 ("media: atomisp: adjust some code at sh_css that could be broken") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 27 +++++++++------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index c4b35cbab373..ba25d0da8b81 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -522,6 +522,7 @@ ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream) return bpp; } +/* TODO: move define to proper file in tools */ #define GP_ISEL_TPG_MODE 0x90058 #if !defined(ISP2401) @@ -573,12 +574,8 @@ sh_css_config_input_network(struct ia_css_stream *stream) vblank_cycles = vblank_lines * (width + hblank_cycles); sh_css_sp_configure_sync_gen(width, height, hblank_cycles, vblank_cycles); - if (!IS_ISP2401) { - if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) { - /* TODO: move define to proper file in tools */ - ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0); - } - } + if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) + ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0); } ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_config_input_network() leave:\n"); @@ -1009,16 +1006,14 @@ static bool sh_css_translate_stream_cfg_to_isys_stream_descr( * ia_css_isys_stream_capture_indication() instead of * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of * capture takes longer than getting an ISYS frame - * - * Only 2401 relevant ?? */ -#if 0 // FIXME: NOT USED on Yocto Aero - isys_stream_descr->polling_mode - = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST - : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME; - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n"); -#endif + if (IS_ISP2401) { + isys_stream_descr->polling_mode + = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST + : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n"); + } return rc; } @@ -1433,7 +1428,7 @@ static void start_pipe( assert(me); /* all callers are in this file and call with non null argument */ - if (!IS_ISP2401) { + if (IS_ISP2401) { coord = &me->config.internal_frame_origin_bqs_on_sctbl; params = me->stream->isp_params_configs; } From fc3b36a783a49928c5f9c463f40cbb7715c91559 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:48 +0900 Subject: [PATCH 020/397] media: atomisp: drop luma_only, input_yuv and input_raw from ISP2401 This patch removes luma_only, input_yuv and input_raw from `struct ia_css_binary_info` as well as its usage [1]. Note that for input_yuv and input_raw, only the definitions were removed because these were not used anywhere. [1] added on updating css version to irci_master_20150701_0213 https://raw.githubusercontent.com/intel/ProductionKernelQuilts/cht-m1stable-2016_ww31/uefi/cht-m1stable/patches/cam-0439-atomisp2-css2401-and-2401_legacy-irci_master_2015070.patch ("atomisp2: css2401 and 2401_legacy-irci_master_20150701_0213") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../atomisp/pci/camera/pipe/src/pipe_binarydesc.c | 5 ----- .../staging/media/atomisp/pci/ia_css_acc_types.h | 5 ----- .../staging/media/atomisp/pci/ia_css_pipe_public.h | 3 --- .../pci/runtime/binary/interface/ia_css_binary.h | 1 - .../media/atomisp/pci/runtime/binary/src/binary.c | 14 -------------- 5 files changed, 28 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c b/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c index f20c9b02fbe0..3e3e5a4f8117 100644 --- a/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c +++ b/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c @@ -58,7 +58,6 @@ static void pipe_binarydesc_get_offline( descr->enable_dz = true; descr->enable_xnr = false; descr->enable_dpc = false; - descr->enable_luma_only = false; descr->enable_tnr = false; descr->enable_capture_pp_bli = false; descr->enable_fractional_ds = false; @@ -390,8 +389,6 @@ int ia_css_pipe_get_video_binarydesc( pipe->extra_config.enable_fractional_ds; video_descr->enable_dpc = pipe->config.enable_dpc; - video_descr->enable_luma_only = - pipe->config.enable_luma_only; video_descr->enable_tnr = pipe->config.enable_tnr; @@ -600,8 +597,6 @@ void ia_css_pipe_get_primary_binarydesc( prim_descr->isp_pipe_version = pipe->config.isp_pipe_version; prim_descr->enable_fractional_ds = pipe->extra_config.enable_fractional_ds; - prim_descr->enable_luma_only = - pipe->config.enable_luma_only; /* We have both striped and non-striped primary binaries, * if continuous viewfinder is required, then we must select * a striped one. Otherwise we prefer to use a non-striped diff --git a/drivers/staging/media/atomisp/pci/ia_css_acc_types.h b/drivers/staging/media/atomisp/pci/ia_css_acc_types.h index 36583ab12e3f..d0ce2f8ba653 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_acc_types.h +++ b/drivers/staging/media/atomisp/pci/ia_css_acc_types.h @@ -222,11 +222,6 @@ struct ia_css_binary_info { struct ia_css_isp_param_isp_segments mem_initializers; /* MW: Packing (related) bools in an integer ?? */ struct { - /* ISP2401 */ - u8 luma_only; - u8 input_yuv; - u8 input_raw; - u8 reduced_pipe; u8 vf_veceven; u8 dis; diff --git a/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h b/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h index 4affd21f9e3f..45e8fe36cb74 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h +++ b/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h @@ -123,9 +123,6 @@ struct ia_css_pipe_config { processing stages. */ /* ISP2401 */ - bool enable_luma_only; - /** Enabling of monochrome mode for a pipeline. If enabled only luma processing - will be done. */ bool enable_tnr; /** Enabling of TNR (temporal noise reduction). This is only applicable to video pipes. Non video-pipes should always set this parameter to false. */ diff --git a/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h b/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h index b44099dbdacd..6f110d241836 100644 --- a/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h +++ b/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h @@ -94,7 +94,6 @@ struct ia_css_binary_descr { bool enable_dpc; /* ISP2401 */ - bool enable_luma_only; bool enable_tnr; bool enable_capture_pp_bli; diff --git a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c index 060d38749570..8c0e02e4e1af 100644 --- a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c +++ b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c @@ -1394,9 +1394,6 @@ static int __ia_css_binary_find(struct ia_css_binary_descr *descr, bool enable_dvs_6axis; bool enable_reduced_pipe; bool enable_capture_pp_bli; -#ifdef ISP2401 - bool enable_luma_only; -#endif int err = -EINVAL; bool continuous; unsigned int isp_pipe_version; @@ -1450,9 +1447,6 @@ static int __ia_css_binary_find(struct ia_css_binary_descr *descr, enable_dvs_6axis = descr->enable_dvs_6axis; enable_reduced_pipe = descr->enable_reduced_pipe; enable_capture_pp_bli = descr->enable_capture_pp_bli; -#ifdef ISP2401 - enable_luma_only = descr->enable_luma_only; -#endif continuous = descr->continuous; striped = descr->striped; isp_pipe_version = descr->isp_pipe_version; @@ -1748,14 +1742,6 @@ static int __ia_css_binary_find(struct ia_css_binary_descr *descr, } #ifdef ISP2401 - if (candidate->enable.luma_only != enable_luma_only) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_binary_find() [%d] continue: %d != %d\n", - __LINE__, candidate->enable.luma_only, - descr->enable_luma_only); - continue; - } - if (!candidate->enable.tnr && need_tnr) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_binary_find() [%d] continue: !%d && %d\n", From 66262818195d906b154eef941441d347b8ef5f79 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:49 +0900 Subject: [PATCH 021/397] media: atomisp: remove struct ia_css_isp_parameter This patch removes `struct ia_css_isp_parameter sc` from `struct ia_css_config_memory_offsets` as well as its usage [1]. [1] added on updating css version to irci_master_20150701_0213 https://raw.githubusercontent.com/intel/ProductionKernelQuilts/cht-m1stable-2016_ww31/uefi/cht-m1stable/patches/cam-0439-atomisp2-css2401-and-2401_legacy-irci_master_2015070.patch ("atomisp2: css2401 and 2401_legacy-irci_master_20150701_0213") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/ia_css_isp_configs.h | 8 --- .../isp/kernels/sc/sc_1.0/ia_css_sc.host.c | 68 ------------------- .../isp/kernels/sc/sc_1.0/ia_css_sc.host.h | 33 --------- .../isp/kernels/sc/sc_1.0/ia_css_sc_types.h | 14 ---- drivers/staging/media/atomisp/pci/sh_css_sp.c | 4 -- 5 files changed, 127 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/ia_css_isp_configs.h b/drivers/staging/media/atomisp/pci/ia_css_isp_configs.h index 1abb2fd6a913..0364b932e79b 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_isp_configs.h +++ b/drivers/staging/media/atomisp/pci/ia_css_isp_configs.h @@ -23,10 +23,6 @@ #include "isp/kernels/raw/raw_1.0/ia_css_raw.host.h" #include "isp/kernels/ref/ref_1.0/ia_css_ref.host.h" #include "isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.h" - -/* ISP2401 */ -#include "isp/kernels/sc/sc_1.0/ia_css_sc.host.h" - #include "isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h" #include "isp/kernels/vf/vf_1.0/ia_css_vf.host.h" #include "isp/kernels/iterator/iterator_1.0/ia_css_iterator.host.h" @@ -73,10 +69,6 @@ struct ia_css_config_memory_offsets { struct ia_css_isp_parameter output0; struct ia_css_isp_parameter output1; struct ia_css_isp_parameter output; - - /* ISP2401 */ - struct ia_css_isp_parameter sc; - struct ia_css_isp_parameter raw; struct ia_css_isp_parameter tnr; struct ia_css_isp_parameter ref; diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.c index f3fb4b9b3c82..6974b3424d91 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.c @@ -23,35 +23,6 @@ #include "ia_css_sc.host.h" -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -/* ISP2401 */ -static void -ia_css_configure_sc( - const struct ia_css_binary *binary, - const struct ia_css_sc_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_sc() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.sc.size; - offset = binary->info->mem_offsets.offsets.config->dmem.sc.offset; - } - if (size) { - ia_css_sc_config((struct sh_css_isp_sc_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_sc() leave:\n"); -} - void ia_css_sc_encode( struct sh_css_isp_sc_params *to, @@ -73,45 +44,6 @@ ia_css_sc_dump( "sc_gain_shift", sc->gain_shift); } -/* ISP2401 */ -void -ia_css_sc_config( - struct sh_css_isp_sc_isp_config *to, - const struct ia_css_sc_configuration *from, - unsigned int size) -{ - u32 internal_org_x_bqs = from->internal_frame_origin_x_bqs_on_sctbl; - u32 internal_org_y_bqs = from->internal_frame_origin_y_bqs_on_sctbl; - u32 slice, rest, i; - - (void)size; - - /* The internal_frame_origin_x_bqs_on_sctbl is separated to 8 times of slice_vec. */ - rest = internal_org_x_bqs; - for (i = 0; i < SH_CSS_SC_INTERPED_GAIN_HOR_SLICE_TIMES; i++) { - slice = min(rest, ((uint32_t)ISP_SLICE_NELEMS)); - rest = rest - slice; - to->interped_gain_hor_slice_bqs[i] = slice; - } - - to->internal_frame_origin_y_bqs_on_sctbl = internal_org_y_bqs; -} - -/* ISP2401 */ -void -ia_css_sc_configure( - const struct ia_css_binary *binary, - u32 internal_frame_origin_x_bqs_on_sctbl, - uint32_t internal_frame_origin_y_bqs_on_sctbl) -{ - const struct ia_css_sc_configuration config = { - internal_frame_origin_x_bqs_on_sctbl, - internal_frame_origin_y_bqs_on_sctbl - }; - - ia_css_configure_sc(binary, &config); -} - /* ------ deprecated(bz675) : from ------ */ /* It looks like @parameter{} (in *.pipe) is used to generate the process/get/set functions, for parameters which should be used in the isp kernels. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.h index f1eb568f23d4..d103103c9a87 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc.host.h @@ -32,39 +32,6 @@ ia_css_sc_dump( const struct sh_css_isp_sc_params *sc, unsigned int level); -/* @brief Configure the shading correction. - * @param[out] to Parameters used in the shading correction kernel in the isp. - * @param[in] from Parameters passed from the host. - * @param[in] size Size of the sh_css_isp_sc_isp_config structure. - * - * This function passes the parameters for the shading correction from the host to the isp. - */ -/* ISP2401 */ -void -ia_css_sc_config( - struct sh_css_isp_sc_isp_config *to, - const struct ia_css_sc_configuration *from, - unsigned int size); - -/* @brief Configure the shading correction. - * @param[in] binary The binary, which has the shading correction. - * @param[in] internal_frame_origin_x_bqs_on_sctbl - * X coordinate (in bqs) of the origin of the internal frame on the shading table. - * @param[in] internal_frame_origin_y_bqs_on_sctbl - * Y coordinate (in bqs) of the origin of the internal frame on the shading table. - * - * This function calls the ia_css_configure_sc() function. - * (The ia_css_configure_sc() function is automatically generated in ia_css_isp.configs.c.) - * The ia_css_configure_sc() function calls the ia_css_sc_config() function - * to pass the parameters for the shading correction from the host to the isp. - */ -/* ISP2401 */ -void -ia_css_sc_configure( - const struct ia_css_binary *binary, - u32 internal_frame_origin_x_bqs_on_sctbl, - uint32_t internal_frame_origin_y_bqs_on_sctbl); - /* ------ deprecated(bz675) : from ------ */ void sh_css_get_shading_settings(const struct ia_css_isp_parameters *params, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc_types.h index aae534521b7b..1d70f6b9a0ec 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/sc/sc_1.0/ia_css_sc_types.h @@ -118,18 +118,4 @@ struct ia_css_shading_settings { /* ------ deprecated(bz675) : to ------ */ -/* Shading Correction configuration. - * - * NOTE: The shading table size is larger than or equal to the internal frame size. - */ -/* ISP2401 */ -struct ia_css_sc_configuration { - u32 internal_frame_origin_x_bqs_on_sctbl; /** Origin X (in bqs) of internal frame on shading table. */ - u32 internal_frame_origin_y_bqs_on_sctbl; /** Origin Y (in bqs) of internal frame on shading table. */ - /** NOTE: bqs = size in BQ(Bayer Quad) unit. - 1BQ means {Gr,R,B,Gb}(2x2 pixels). - Horizontal 1 bqs corresponds to horizontal 2 pixels. - Vertical 1 bqs corresponds to vertical 2 pixels. */ -}; - #endif /* __IA_CSS_SC_TYPES_H */ diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index a73e8ca1e225..13b15a5a33bc 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -827,10 +827,6 @@ configure_isp_from_args( ia_css_output1_configure(binary, &args->out_vf_frame->info); ia_css_copy_output_configure(binary, args->copy_output); ia_css_output0_configure(binary, &args->out_frame[0]->info); -#ifdef ISP2401 - ia_css_sc_configure(binary, pipeline->shading.internal_frame_origin_x_bqs_on_sctbl, - pipeline->shading.internal_frame_origin_y_bqs_on_sctbl); -#endif ia_css_iterator_configure(binary, &args->in_frame->info); ia_css_dvs_configure(binary, &args->out_frame[0]->info); ia_css_output_configure(binary, &args->out_frame[0]->info); From c665ccf1ffeaddb51d668e792ce443d08e01e65a Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:50 +0900 Subject: [PATCH 022/397] media: atomisp: remove struct ia_css_isp_parameter xnr3 This patch removes `struct ia_css_isp_parameter xnr3` from `struct ia_css_memory_offsets` as well as its usage [1]. [1] added on updating css version to irci_master_20150701_0213 https://raw.githubusercontent.com/intel/ProductionKernelQuilts/cht-m1stable-2016_ww31/uefi/cht-m1stable/patches/cam-0439-atomisp2-css2401-and-2401_legacy-irci_master_2015070.patch ("atomisp2: css2401 and 2401_legacy-irci_master_20150701_0213") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../css_2401_system/hive/ia_css_isp_params.c | 23 ------------------- .../media/atomisp/pci/ia_css_isp_params.h | 3 --- 2 files changed, 26 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_params.c b/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_params.c index d9c672d8904e..503ac65da69b 100644 --- a/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_params.c +++ b/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_params.c @@ -1721,29 +1721,6 @@ ia_css_process_xnr3( "ia_css_process_xnr3() leave:\n"); } } - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vmem.xnr3.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vmem.xnr3.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_xnr3() enter:\n"); - - ia_css_xnr3_vmem_encode((struct sh_css_isp_xnr3_vmem_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VMEM].address[offset], - ¶ms->xnr3_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_xnr3() leave:\n"); - } - } } /* Code generated by genparam/gencode.c:gen_param_process_table() */ diff --git a/drivers/staging/media/atomisp/pci/ia_css_isp_params.h b/drivers/staging/media/atomisp/pci/ia_css_isp_params.h index 6e3082b39ed6..c2de689877d1 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_isp_params.h +++ b/drivers/staging/media/atomisp/pci/ia_css_isp_params.h @@ -121,9 +121,6 @@ struct ia_css_memory_offsets { struct ia_css_isp_parameter sdis_vertcoef; struct ia_css_isp_parameter sdis2_horicoef; struct ia_css_isp_parameter sdis2_vertcoef; - - /* ISP2401 */ - struct ia_css_isp_parameter xnr3; } vmem; struct { struct ia_css_isp_parameter bh; From bbaa836b530101380f1a003c642b4a5fc92900aa Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:51 +0900 Subject: [PATCH 023/397] media: atomisp: remove polling_mode and subscr_index This patch removes polling_mode and subscr_index from `struct virtual_input_system_stream_s` as well as its usage [1]. Note that for subscr_index, only the definition were removed because it was not used anywhere. [1] added on updating css version to irci_master_20150701_0213 https://raw.githubusercontent.com/intel/ProductionKernelQuilts/cht-m1stable-2016_ww31/uefi/cht-m1stable/patches/cam-0439-atomisp2-css2401-and-2401_legacy-irci_master_2015070.patch ("atomisp2: css2401 and 2401_legacy-irci_master_20150701_0213") Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../atomisp/pci/isp2401_input_system_global.h | 12 ------------ .../atomisp/pci/runtime/isys/src/virtual_isys.c | 11 ----------- drivers/staging/media/atomisp/pci/sh_css.c | 14 ++------------ 3 files changed, 2 insertions(+), 35 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/isp2401_input_system_global.h b/drivers/staging/media/atomisp/pci/isp2401_input_system_global.h index f38773842646..e3c86069b390 100644 --- a/drivers/staging/media/atomisp/pci/isp2401_input_system_global.h +++ b/drivers/staging/media/atomisp/pci/isp2401_input_system_global.h @@ -44,11 +44,6 @@ typedef enum { N_INPUT_SYSTEM_SOURCE_TYPE } input_system_source_type_t; -typedef enum { - INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME, - INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST, -} input_system_polling_mode_t; - typedef struct input_system_channel_s input_system_channel_t; struct input_system_channel_s { stream2mmio_ID_t stream2mmio_id; @@ -111,9 +106,6 @@ struct isp2401_input_system_cfg_s { input_system_source_type_t mode; - /* ISP2401 */ - input_system_polling_mode_t polling_mode; - bool online; bool raw_packed; s8 linked_isys_stream_id; @@ -165,10 +157,6 @@ struct virtual_input_system_stream_s { u8 online; s8 linked_isys_stream_id; u8 valid; - - /* ISP2401 */ - input_system_polling_mode_t polling_mode; - s32 subscr_index; }; typedef struct virtual_input_system_stream_cfg_s diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c index 82f3c19dc455..8fc7746f8639 100644 --- a/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c @@ -189,17 +189,6 @@ ia_css_isys_error_t ia_css_isys_stream_create( return false; } -#ifdef ISP2401 - /* - * Early polling is required for timestamp accuracy in certain cause. - * The ISYS HW polling is started on - * ia_css_isys_stream_capture_indication() instead of - * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of - * capture takes longer than getting an ISYS frame - */ - isys_stream->polling_mode = isys_stream_descr->polling_mode; - -#endif /* create metadata channel */ if (isys_stream_descr->metadata.enable) { rc = create_input_system_channel(isys_stream_descr, true, diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index ba25d0da8b81..79003077f390 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -1000,20 +1000,10 @@ static bool sh_css_translate_stream_cfg_to_isys_stream_descr( isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels; isys_stream_descr->linked_isys_stream_id = (int8_t) stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id; - /* - * Early polling is required for timestamp accuracy in certain case. - * The ISYS HW polling is started on - * ia_css_isys_stream_capture_indication() instead of - * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of - * capture takes longer than getting an ISYS frame - */ - if (IS_ISP2401) { - isys_stream_descr->polling_mode - = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST - : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME; + + if (IS_ISP2401) ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n"); - } return rc; } From b37bca2eba67da5eb5f7a4a30279e9b464eebdc6 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:52 +0900 Subject: [PATCH 024/397] media: atomisp: make fw ver irci_stable_candrpv_0415_20150521_0458 work This patch removes the unnamed struct `shading` from `struct sh_css_sp_pipeline` as well as its usage [1]. [1] added on updating css version to irci_master_20150701_0213 https://raw.githubusercontent.com/intel/ProductionKernelQuilts/cht-m1stable-2016_ww31/uefi/cht-m1stable/patches/cam-0439-atomisp2-css2401-and-2401_legacy-irci_master_2015070.patch ("atomisp2: css2401 and 2401_legacy-irci_master_20150701_0213") This patch, together with the 4 patches applied before it revert incompatible changes in the current css version for ISP2401 (irci_ecr-master_20150911_0724) back to irci_stable_candrpv_0415_20150521_0458. Some `struct`s are `sizeof()`ed in sh_css_firmware.c file. So, I guess issues will happen if these sizes are changed. Therefore, keep them the same as css version irci_stable_candrpv_0415_20150521_0458 to make atomisp work for firmware made for such css version since we don't have firmware made for the current css version. Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/sh_css_internal.h | 8 -------- drivers/staging/media/atomisp/pci/sh_css_sp.c | 18 ------------------ 2 files changed, 26 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_internal.h b/drivers/staging/media/atomisp/pci/sh_css_internal.h index 496faa7297a5..92fb7e67610c 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_internal.h +++ b/drivers/staging/media/atomisp/pci/sh_css_internal.h @@ -551,14 +551,6 @@ struct sh_css_sp_pipeline { u32 raw_bit_depth; } raw; } copy; - -/* ISP2401 */ - - /* Parameters passed to Shading Correction kernel. */ - struct { - u32 internal_frame_origin_x_bqs_on_sctbl; /* Origin X (bqs) of internal frame on shading table */ - u32 internal_frame_origin_y_bqs_on_sctbl; /* Origin Y (bqs) of internal frame on shading table */ - } shading; }; /* diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index 13b15a5a33bc..fa74ac172f94 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -1308,24 +1308,6 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, } #endif - if (IS_ISP2401) { - /* For the shading correction type 1 (the legacy shading table conversion in css is not used), - * the parameters are passed to the isp for the shading table centering. - */ - if (internal_frame_origin_bqs_on_sctbl && - params && params->shading_settings.enable_shading_table_conversion == 0) { - sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl - = (uint32_t)internal_frame_origin_bqs_on_sctbl->x; - sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl - = (uint32_t)internal_frame_origin_bqs_on_sctbl->y; - } else { - sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl = - 0; - sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl = - 0; - } - } - IA_CSS_LOG("pipe_id %d port_config %08x", pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config); From bb4924c215f26c4bbb0008d1ae13f98066ed2952 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:53 +0900 Subject: [PATCH 025/397] media: atomisp: pci: release_version is now irci_stable_candrpv_0415_20150521_0458 Now that we made atomisp work with firmware version irci_stable_candrpv_0415_20150521_0458 also for ISP2401, the release_version for ISP2401 is not irci_ecr-master_20150911_0724 anymore. So, use the same release_version for both ISP2400 and ISP2401 (i.e., irci_stable_candrpv_0415_20150521_0458). Referred to the following diff to make this patch: - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/diff/drivers/staging/media/atomisp/pci/sh_css_firmware.c?id=3c0538fbad9f1d07d588f631e380256d941e3d3a ("media: atomisp: get rid of most checks for ISP2401 version") changes for file sh_css_firmware.c Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../pci/isp/kernels/hdr/ia_css_hdr.host.c | 1 - .../pci/isp/kernels/hdr/ia_css_hdr.host.h | 1 - .../pci/isp/kernels/hdr/ia_css_hdr_param.h | 1 - .../pci/isp/kernels/hdr/ia_css_hdr_types.h | 1 - .../staging/media/atomisp/pci/sh_css_firmware.c | 16 +--------------- 5 files changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.c index 698550cc2fcc..85a02b6adb52 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 /* Release Version: irci_stable_candrpv_0415_20150521_0458 */ -/* Release Version: irci_ecr-master_20150911_0724 */ /* * Support for Intel Camera Imaging ISP subsystem. * Copyright (c) 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.h index 04599ab590cd..83277b683c47 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr.host.h @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Release Version: irci_stable_candrpv_0415_20150521_0458 */ -/* Release Version: irci_ecr-master_20150911_0724 */ /* * Support for Intel Camera Imaging ISP subsystem. * Copyright (c) 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_param.h b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_param.h index 97a89fd3cfda..998c6d801756 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_param.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_param.h @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Release Version: irci_stable_candrpv_0415_20150521_0458 */ -/* Release Version: irci_ecr-master_20150911_0724 */ /* * Support for Intel Camera Imaging ISP subsystem. * Copyright (c) 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_types.h index 1b4090880201..175c301ee96a 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_types.h @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Release Version: irci_stable_candrpv_0415_20150521_0458 */ -/* Release Version: irci_ecr-master_20150911_0724 */ /* * Support for Intel Camera Imaging ISP subsystem. * Copyright (c) 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/sh_css_firmware.c index e1a16a50e588..94149647b98b 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_firmware.c +++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.c @@ -56,8 +56,7 @@ static struct firmware_header *firmware_header; * which will be replaced with the actual RELEASE_VERSION * during package generation. Please do not modify */ -static const char *isp2400_release_version = STR(irci_stable_candrpv_0415_20150521_0458); -static const char *isp2401_release_version = STR(irci_ecr - master_20150911_0724); +static const char *release_version = STR(irci_stable_candrpv_0415_20150521_0458); #define MAX_FW_REL_VER_NAME 300 static char FW_rel_ver_name[MAX_FW_REL_VER_NAME] = "---"; @@ -190,13 +189,6 @@ sh_css_check_firmware_version(struct device *dev, const char *fw_data) { struct sh_css_fw_bi_file_h *file_header; - const char *release_version; - - if (!IS_ISP2401) - release_version = isp2400_release_version; - else - release_version = isp2401_release_version; - firmware_header = (struct firmware_header *)fw_data; file_header = &firmware_header->file_header; @@ -232,12 +224,6 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, struct ia_css_fw_info *binaries; struct sh_css_fw_bi_file_h *file_header; int ret; - const char *release_version; - - if (!IS_ISP2401) - release_version = isp2400_release_version; - else - release_version = isp2401_release_version; firmware_header = (struct firmware_header *)fw_data; file_header = &firmware_header->file_header; From 634557be5aead60c87af3eb0a922e22d10bb44fb Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:19:55 +0900 Subject: [PATCH 026/397] media: atomisp: add Microsoft Surface 3 ACPI vars Microsoft Surface 3 does not describe CsiPort/CsiLanes in DSDT [1] or EFI, or at least not desctibed in the forms the current atomisp driver expects. This results in the default values (port: 0 lanes: 1) to be used, which does not work. So, define them ourselves in the driver. The user-facing camera is AR0330 (2-lane) and the world-facing camera is OV8835 (4-lane). According to the portconfigs definition in atomisp_csi_lane_config() [atomisp_v4l2.c]: } portconfigs[] = { /* Tangier/Merrifield available lane configurations */ { 0x00, { 4, 1, 0 } }, /* 00000 */ { 0x01, { 3, 1, 0 } }, /* 00001 */ { 0x02, { 2, 1, 0 } }, /* 00010 */ { 0x03, { 1, 1, 0 } }, /* 00011 */ { 0x04, { 2, 1, 2 } }, /* 00100 */ { 0x08, { 3, 1, 1 } }, /* 01000 */ { 0x09, { 2, 1, 1 } }, /* 01001 */ { 0x0a, { 1, 1, 1 } }, /* 01010 */ /* Anniedale/Moorefield only configurations */ { 0x10, { 4, 2, 0 } }, /* 10000 */ { 0x11, { 3, 2, 0 } }, /* 10001 */ { 0x12, { 2, 2, 0 } }, /* 10010 */ { 0x13, { 1, 2, 0 } }, /* 10011 */ { 0x14, { 2, 2, 2 } }, /* 10100 */ { 0x18, { 3, 2, 1 } }, /* 11000 */ { 0x19, { 2, 2, 1 } }, /* 11001 */ { 0x1a, { 1, 2, 1 } }, /* 11010 */ }; 4-lane camera is always connected to the PRIMARY (port1) port [2]. In this case, 2-lane camera can be connected to the only SECONDARY (port0) port. So, add these data accordingly as the gmin_cfg_var ACPI variables for Surface 3. [1] https://github.com/linux-surface/acpidumps/blob/7da48a392b4085c2021952290def1fc28505a643/surface_3/dsdt.dsl#L5879-L6278 [2] Yes, the PRIMARY port is port1 according to atomisp_camera_port [atomisp.h]: enum atomisp_camera_port { ATOMISP_CAMERA_PORT_SECONDARY, ATOMISP_CAMERA_PORT_PRIMARY, ATOMISP_CAMERA_PORT_TERTIARY, ATOMISP_CAMERA_NR_PORTS }; Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_gmin_platform.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index d8c9e31314b2..948eb6f809f5 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -321,6 +321,18 @@ static struct gmin_cfg_var i8880_vars[] = { {}, }; +/* + * Surface 3 does not describe CsiPort/CsiLanes in both DSDT and EFI. + */ +static struct gmin_cfg_var surface3_vars[] = { + {"APTA0330:00_CsiPort", "0"}, + {"APTA0330:00_CsiLanes", "2"}, + + {"OVTI8835:00_CsiPort", "1"}, + {"OVTI8835:00_CsiLanes", "4"}, + {}, +}; + static const struct dmi_system_id gmin_vars[] = { { .ident = "BYT-T FFD8", @@ -358,6 +370,13 @@ static const struct dmi_system_id gmin_vars[] = { }, .driver_data = i8880_vars, }, + { + .ident = "Surface 3", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "Surface 3"), + }, + .driver_data = surface3_vars, + }, {} }; From 59a27d5c98f7f6702c4d9d176eb6019a4d28fdac Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 6 Nov 2017 23:36:36 +0000 Subject: [PATCH 027/397] media: atomisp: Fix up the open v load race Date: Mon, 06 Nov 2017 23:36:36 +0000 This isn't the ideal final solution but it stops the main problem for now where an open (often from udev) races the device initialization and we try and load the firmware twice at the same time. This needless to say doesn't usually end well. [kitakar: ported to upstream Kernel] [mchehab: make comments to use our coding style] Signed-off-by: Alan Cox Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_fops.c | 16 ++++++++++++++++ .../staging/media/atomisp/pci/atomisp_internal.h | 7 +++++++ drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 6 ++++++ 3 files changed, 29 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index f82bf082aa79..0732c9c0ed06 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -772,6 +772,22 @@ static int atomisp_open(struct file *file) dev_dbg(isp->dev, "open device %s\n", vdev->name); + /* + * Ensure that if we are still loading we block. Once the loading + * is over we can proceed. We can't blindly hold the lock until + * that occurs as if the load fails we'll deadlock the unload + */ + rt_mutex_lock(&isp->loading); + /* + * FIXME: revisit this with a better check once the code structure + * is cleaned up a bit more + */ + if (!isp->ready) { + rt_mutex_unlock(&isp->loading); + return -ENXIO; + } + rt_mutex_unlock(&isp->loading); + rt_mutex_lock(&isp->mutex); acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC"); diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index c01db10bb735..f71ab1ee6e19 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -246,6 +246,13 @@ struct atomisp_device { /* Purpose of mutex is to protect and serialize use of isp data * structures and css API calls. */ struct rt_mutex mutex; + /* + * This mutex ensures that we don't allow an open to succeed while + * the initialization process is incomplete + */ + struct rt_mutex loading; + /* Set once the ISP is ready to allow opens */ + bool ready; /* * Serialise streamoff: mutex is dropped during streamoff to * cancel the watchdog queue. MUST be acquired BEFORE diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 7982cc143374..bbef485ee15c 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -1567,6 +1567,7 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i dev_dbg(&pdev->dev, "atomisp mmio base: %p\n", isp->base); rt_mutex_init(&isp->mutex); + rt_mutex_init(&isp->loading); mutex_init(&isp->streamoff_mutex); spin_lock_init(&isp->lock); @@ -1749,6 +1750,8 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, csi_afe_trim); } + rt_mutex_lock(&isp->loading); + err = atomisp_initialize_modules(isp); if (err < 0) { dev_err(&pdev->dev, "atomisp_initialize_modules (%d)\n", err); @@ -1806,6 +1809,8 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i release_firmware(isp->firmware); isp->firmware = NULL; isp->css_env.isp_css_fw.data = NULL; + isp->ready = true; + rt_mutex_unlock(&isp->loading); atomisp_drvfs_init(isp); @@ -1825,6 +1830,7 @@ wdt_work_queue_fail: register_entities_fail: atomisp_uninitialize_modules(isp); initialize_modules_fail: + rt_mutex_unlock(&isp->loading); cpu_latency_qos_remove_request(&isp->pm_qos); atomisp_msi_irq_uninit(isp); pci_free_irq_vectors(pdev); From c10bcb13462e9cf43111d17f1e08b4bb4d4401b0 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Mon, 18 Oct 2021 01:23:34 +0900 Subject: [PATCH 028/397] media: atomisp: add NULL check for asd obtained from atomisp_video_pipe This is almost a BUG report with RFC patch that just avoids kernel oopses. Thus, prefixed with [BUG][RFC]. Here is the kernel log after running `v4l2-compliance -d /dev/video4` with this patch applied: kern :err : [25507.580392] atomisp-isp2 0000:00:03.0: can't change power state from D3cold to D0 (config space inaccessible) kern :warn : [25507.592343] isys dma store at addr(0xcd408) val(0) kern :err : [25507.592995] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.593685] atomisp-isp2 0000:00:03.0: atomisp_g_input(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.593719] atomisp-isp2 0000:00:03.0: atomisp_g_parm(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.593727] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC [omitting 42 same messages] kern :err : [25507.593976] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.594191] atomisp-isp2 0000:00:03.0: atomisp_g_input(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.594449] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC [omitting 43 same messages] kern :err : [25507.594756] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.594779] atomisp-isp2 0000:00:03.0: atomisp_g_ctrl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.594787] atomisp-isp2 0000:00:03.0: atomisp_s_ctrl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.594803] atomisp-isp2 0000:00:03.0: atomisp_camera_g_ext_ctrls(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.594880] atomisp-isp2 0000:00:03.0: atomisp_enum_fmt_cap(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.594915] atomisp-isp2 0000:00:03.0: atomisp_g_parm(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.595058] atomisp-isp2 0000:00:03.0: atomisp_try_fmt(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.595089] atomisp-isp2 0000:00:03.0: atomisp_set_fmt(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.595124] atomisp-isp2 0000:00:03.0: atomisp_set_fmt(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.595221] atomisp-isp2 0000:00:03.0: atomisp_set_fmt(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.595241] atomisp-isp2 0000:00:03.0: atomisp_set_fmt(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.601571] atomisp-isp2 0000:00:03.0: can't change power state from D3cold to D0 (config space inaccessible) kern :warn : [25507.607496] isys dma store at addr(0xcd408) val(0) kern :err : [25507.608604] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.611988] atomisp-isp2 0000:00:03.0: can't change power state from D3cold to D0 (config space inaccessible) kern :warn : [25507.617420] isys dma store at addr(0xcd408) val(0) kern :err : [25507.618429] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.618811] atomisp-isp2 0000:00:03.0: atomisp_g_parm(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.622193] atomisp-isp2 0000:00:03.0: can't change power state from D3cold to D0 (config space inaccessible) kern :warn : [25507.627355] isys dma store at addr(0xcd408) val(0) kern :err : [25507.628391] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.631143] atomisp-isp2 0000:00:03.0: can't change power state from D3cold to D0 (config space inaccessible) kern :warn : [25507.635813] isys dma store at addr(0xcd408) val(0) kern :err : [25507.636489] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.636504] atomisp-isp2 0000:00:03.0: atomisp_s_input(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.636516] atomisp-isp2 0000:00:03.0: atomisp_set_fmt(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.639111] atomisp-isp2 0000:00:03.0: can't change power state from D3cold to D0 (config space inaccessible) kern :warn : [25507.646152] isys dma store at addr(0xcd408) val(0) kern :err : [25507.646831] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.646847] atomisp-isp2 0000:00:03.0: atomisp_s_input(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.650079] atomisp-isp2 0000:00:03.0: can't change power state from D3cold to D0 (config space inaccessible) kern :warn : [25507.657476] isys dma store at addr(0xcd408) val(0) kern :err : [25507.658741] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.658759] atomisp-isp2 0000:00:03.0: atomisp_s_input(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.658771] atomisp-isp2 0000:00:03.0: atomisp_set_fmt(): asd is NULL, device is ATOMISP ISP ACC kern :err : [25507.660959] atomisp-isp2 0000:00:03.0: can't change power state from D3cold to D0 (config space inaccessible) kern :warn : [25507.666665] isys dma store at addr(0xcd408) val(0) kern :err : [25507.667397] atomisp-isp2 0000:00:03.0: atomisp_queryctl(): asd is NULL, device is ATOMISP ISP ACC [mchehab: fix coding style] Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 73 +++++++++++++++ .../staging/media/atomisp/pci/atomisp_fops.c | 6 ++ .../staging/media/atomisp/pci/atomisp_ioctl.c | 90 +++++++++++++++++++ 3 files changed, 169 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 366161cff560..75a531667d74 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -1715,6 +1715,12 @@ void atomisp_wdt_refresh_pipe(struct atomisp_video_pipe *pipe, { unsigned long next; + if (!pipe->asd) { + dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, pipe->vdev.name); + return; + } + if (delay != ATOMISP_WDT_KEEP_CURRENT_DELAY) pipe->wdt_duration = delay; @@ -1777,6 +1783,12 @@ void atomisp_wdt_refresh(struct atomisp_sub_device *asd, unsigned int delay) /* ISP2401 */ void atomisp_wdt_stop_pipe(struct atomisp_video_pipe *pipe, bool sync) { + if (!pipe->asd) { + dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, pipe->vdev.name); + return; + } + if (!atomisp_is_wdt_running(pipe)) return; @@ -4109,6 +4121,12 @@ void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe) unsigned long irqflags; bool need_to_enqueue_buffer = false; + if (!asd) { + dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, pipe->vdev.name); + return; + } + if (atomisp_is_vf_pipe(pipe)) return; @@ -4196,6 +4214,12 @@ int atomisp_set_parameters(struct video_device *vdev, struct atomisp_css_params *css_param = &asd->params.css_param; int ret; + if (!asd) { + dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { dev_err(asd->isp->dev, "%s: internal error!\n", __func__); return -EINVAL; @@ -4857,6 +4881,12 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, int source_pad = atomisp_subdev_source_pad(vdev); int ret; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (!isp->inputs[asd->input_curr].camera) return -EINVAL; @@ -5198,6 +5228,12 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, const struct atomisp_in_fmt_conv *fc; int ret, i; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + v4l2_fh_init(&fh.vfh, vdev); isp_sink_crop = atomisp_subdev_get_rect( @@ -5494,6 +5530,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, unsigned int dvs_env_w, unsigned int dvs_env_h) { struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); const struct atomisp_format_bridge *format; struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { @@ -5512,6 +5549,12 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, struct v4l2_subdev_fh fh; int ret; + if (!asd) { + dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + v4l2_fh_init(&fh.vfh, vdev); stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); @@ -5602,6 +5645,12 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) struct v4l2_subdev_fh fh; int ret; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (source_pad >= ATOMISP_SUBDEV_PADS_NUM) return -EINVAL; @@ -6034,6 +6083,12 @@ int atomisp_set_fmt_file(struct video_device *vdev, struct v4l2_format *f) struct v4l2_subdev_fh fh; int ret; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + v4l2_fh_init(&fh.vfh, vdev); dev_dbg(isp->dev, "setting fmt %ux%u 0x%x for file inject\n", @@ -6359,6 +6414,12 @@ bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe) { struct atomisp_sub_device *asd = pipe->asd; + if (!asd) { + dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, pipe->vdev.name); + return false; + } + if (pipe == &asd->video_out_vf) return true; @@ -6572,6 +6633,12 @@ static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe) { struct atomisp_sub_device *asd = pipe->asd; + if (!asd) { + dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, pipe->vdev.name); + return -EINVAL; + } + if (ATOMISP_USE_YUVPP(asd)) { return IA_CSS_PIPE_ID_YUVPP; } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { @@ -6609,6 +6676,12 @@ int atomisp_get_invalid_frame_num(struct video_device *vdev, struct ia_css_pipe_info p_info; int ret; + if (!asd) { + dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (asd->isp->inputs[asd->input_curr].camera_caps-> sensor[asd->sensor_curr].stream_num > 1) { /* External ISP */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 0732c9c0ed06..72cbdce2142a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -1187,6 +1187,12 @@ static int atomisp_mmap(struct file *file, struct vm_area_struct *vma) u32 origin_size, new_size; int ret; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (!(vma->vm_flags & (VM_WRITE | VM_READ))) return -EACCES; diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index c8a625667e81..a57e640fbf79 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -646,6 +646,12 @@ static int atomisp_g_input(struct file *file, void *fh, unsigned int *input) struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + rt_mutex_lock(&isp->mutex); *input = asd->input_curr; rt_mutex_unlock(&isp->mutex); @@ -665,6 +671,12 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input) struct v4l2_subdev *motor; int ret; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + rt_mutex_lock(&isp->mutex); if (input >= ATOM_ISP_MAX_INPUTS || input >= isp->input_cnt) { dev_dbg(isp->dev, "input_cnt: %d\n", isp->input_cnt); @@ -765,6 +777,12 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, unsigned int i, fi = 0; int rval; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + rt_mutex_lock(&isp->mutex); rval = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, enum_mbus_code, NULL, &code); @@ -1027,6 +1045,12 @@ int __atomisp_reqbufs(struct file *file, void *fh, u16 stream_id = atomisp_source_pad_to_stream_id(asd, source_pad); int ret = 0, i = 0; + if (!asd) { + dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (req->count == 0) { mutex_lock(&pipe->capq.vb_lock); if (!list_empty(&pipe->capq.stream)) @@ -1154,6 +1178,12 @@ static int atomisp_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) u32 pgnr; int ret = 0; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + rt_mutex_lock(&isp->mutex); if (isp->isp_fatal_error) { ret = -EIO; @@ -1389,6 +1419,12 @@ static int atomisp_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) struct atomisp_device *isp = video_get_drvdata(vdev); int ret = 0; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + rt_mutex_lock(&isp->mutex); if (isp->isp_fatal_error) { @@ -1640,6 +1676,12 @@ static int atomisp_streamon(struct file *file, void *fh, int ret = 0; unsigned long irqflags; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + dev_dbg(isp->dev, "Start stream on pad %d for asd%d\n", atomisp_subdev_source_pad(vdev), asd->index); @@ -1901,6 +1943,12 @@ int __atomisp_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) unsigned long flags; bool first_streamoff = false; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + dev_dbg(isp->dev, "Stop stream on pad %d for asd%d\n", atomisp_subdev_source_pad(vdev), asd->index); @@ -2150,6 +2198,12 @@ static int atomisp_g_ctrl(struct file *file, void *fh, struct atomisp_device *isp = video_get_drvdata(vdev); int i, ret = -EINVAL; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + for (i = 0; i < ctrls_num; i++) { if (ci_v4l2_controls[i].id == control->id) { ret = 0; @@ -2229,6 +2283,12 @@ static int atomisp_s_ctrl(struct file *file, void *fh, struct atomisp_device *isp = video_get_drvdata(vdev); int i, ret = -EINVAL; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + for (i = 0; i < ctrls_num; i++) { if (ci_v4l2_controls[i].id == control->id) { ret = 0; @@ -2310,6 +2370,12 @@ static int atomisp_queryctl(struct file *file, void *fh, struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; struct atomisp_device *isp = video_get_drvdata(vdev); + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + switch (qc->id) { case V4L2_CID_FOCUS_ABSOLUTE: case V4L2_CID_FOCUS_RELATIVE: @@ -2355,6 +2421,12 @@ static int atomisp_camera_g_ext_ctrls(struct file *file, void *fh, int i; int ret = 0; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (!IS_ISP2401) motor = isp->inputs[asd->input_curr].motor; else @@ -2466,6 +2538,12 @@ static int atomisp_camera_s_ext_ctrls(struct file *file, void *fh, int i; int ret = 0; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (!IS_ISP2401) motor = isp->inputs[asd->input_curr].motor; else @@ -2591,6 +2669,12 @@ static int atomisp_g_parm(struct file *file, void *fh, struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; struct atomisp_device *isp = video_get_drvdata(vdev); + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { dev_err(isp->dev, "unsupported v4l2 buf type\n"); return -EINVAL; @@ -2613,6 +2697,12 @@ static int atomisp_s_parm(struct file *file, void *fh, int rval; int fps; + if (!asd) { + dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { dev_err(isp->dev, "unsupported v4l2 buf type\n"); return -EINVAL; From fae46cb0531b45c789e39128f676f2bafa3a7b47 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Oct 2021 09:06:52 +0100 Subject: [PATCH 029/397] media: atomisp: fix enum formats logic Changeset 374d62e7aa50 ("media: v4l2-subdev: Verify v4l2_subdev_call() pad config argument") added an extra verification for a pads parameter for enum mbus format code. Such change broke atomisp, because now the V4L2 core refuses to enum MBUS formats if the state is empty. So, add .which field in order to select the active formats, in order to make it work again. While here, improve error messages. Fixes: 374d62e7aa50 ("media: v4l2-subdev: Verify v4l2_subdev_call() pad config argument") Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index a57e640fbf79..29826f8e4143 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -773,7 +773,10 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, struct video_device *vdev = video_devdata(file); struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; - struct v4l2_subdev_mbus_code_enum code = { 0 }; + struct v4l2_subdev_mbus_code_enum code = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + struct v4l2_subdev *camera; unsigned int i, fi = 0; int rval; @@ -783,14 +786,20 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, return -EINVAL; } + camera = isp->inputs[asd->input_curr].camera; + if(!camera) { + dev_err(isp->dev, "%s(): camera is NULL, device is %s\n", + __func__, vdev->name); + return -EINVAL; + } + rt_mutex_lock(&isp->mutex); - rval = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, - enum_mbus_code, NULL, &code); + + rval = v4l2_subdev_call(camera, pad, enum_mbus_code, NULL, &code); if (rval == -ENOIOCTLCMD) { dev_warn(isp->dev, - "enum_mbus_code pad op not supported. Please fix your sensor driver!\n"); - // rval = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - // video, enum_mbus_fmt, 0, &code.code); + "enum_mbus_code pad op not supported by %s. Please fix your sensor driver!\n", + camera->name); } rt_mutex_unlock(&isp->mutex); @@ -820,6 +829,8 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, f->pixelformat = format->pixelformat; return 0; } + dev_err(isp->dev, "%s(): format for code %x not found.\n", + __func__, code.code); return -EINVAL; } From 331adc2f4081886a6f12392dbcfb17e3512a7160 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Oct 2021 07:06:38 +0100 Subject: [PATCH 030/397] media: atomisp: better describe get_frame_info issues When atomisp is used by a normal client, it fails to get frame info. However, the information is confusing and misleading, as there are several wrappers for such function, and the error could be on different places. So, improve the error log in order to allow narrowing down where the error is actually occuring. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 6 +- .../media/atomisp/pci/atomisp_compat_css20.c | 73 ++++++++++--------- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 75a531667d74..70c8e86c3205 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -5453,9 +5453,9 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, else ret = get_frame_info(asd, output_info); if (ret) { - dev_err(isp->dev, "get_frame_info %ux%u (padded to %u)\n", - pix->width, pix->height, pix->bytesperline); - return -EINVAL; + dev_err(isp->dev, "__get_frame_info %ux%u (padded to %u) returned %d\n", + pix->width, pix->height, pix->bytesperline, ret); + return ret; } atomisp_update_grid_info(asd, pipe_id, source_pad); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 99a632f33d2d..1309855bb6c8 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -2657,42 +2657,49 @@ static int __get_frame_info(struct atomisp_sub_device *asd, if (__destroy_pipes(asd, true)) dev_warn(isp->dev, "destroy pipe failed.\n"); - if (__create_pipes(asd)) + if (__create_pipes(asd)) { + dev_err(isp->dev, "can't create pipes\n"); return -EINVAL; - - if (__create_streams(asd)) - goto stream_err; - - ret = ia_css_pipe_get_info( - asd->stream_env[stream_index] - .pipes[pipe_id], &p_info); - if (!ret) { - switch (type) { - case ATOMISP_CSS_VF_FRAME: - *info = p_info.vf_output_info[0]; - dev_dbg(isp->dev, "getting vf frame info.\n"); - break; - case ATOMISP_CSS_SECOND_VF_FRAME: - *info = p_info.vf_output_info[1]; - dev_dbg(isp->dev, "getting second vf frame info.\n"); - break; - case ATOMISP_CSS_OUTPUT_FRAME: - *info = p_info.output_info[0]; - dev_dbg(isp->dev, "getting main frame info.\n"); - break; - case ATOMISP_CSS_SECOND_OUTPUT_FRAME: - *info = p_info.output_info[1]; - dev_dbg(isp->dev, "getting second main frame info.\n"); - break; - case ATOMISP_CSS_RAW_FRAME: - *info = p_info.raw_output_info; - dev_dbg(isp->dev, "getting raw frame info.\n"); - } - dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n", - info->res.width, info->res.height, p_info.num_invalid_frames); - return 0; } + if (__create_streams(asd)) { + dev_err(isp->dev, "can't create streams\n"); + goto stream_err; + } + + ret = ia_css_pipe_get_info(asd->stream_env[stream_index].pipes[pipe_id], + &p_info); + if (ret) { + dev_err(isp->dev, "can't get info from pipe\n"); + goto stream_err; + } + + switch (type) { + case ATOMISP_CSS_VF_FRAME: + *info = p_info.vf_output_info[0]; + dev_dbg(isp->dev, "getting vf frame info.\n"); + break; + case ATOMISP_CSS_SECOND_VF_FRAME: + *info = p_info.vf_output_info[1]; + dev_dbg(isp->dev, "getting second vf frame info.\n"); + break; + case ATOMISP_CSS_OUTPUT_FRAME: + *info = p_info.output_info[0]; + dev_dbg(isp->dev, "getting main frame info.\n"); + break; + case ATOMISP_CSS_SECOND_OUTPUT_FRAME: + *info = p_info.output_info[1]; + dev_dbg(isp->dev, "getting second main frame info.\n"); + break; + case ATOMISP_CSS_RAW_FRAME: + *info = p_info.raw_output_info; + dev_dbg(isp->dev, "getting raw frame info.\n"); + } + dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n", + info->res.width, info->res.height, p_info.num_invalid_frames); + + return 0; + stream_err: __destroy_pipes(asd, true); return -EINVAL; From 6c84a35d781525696fcbeeed8c60d96a63811067 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Oct 2021 14:53:22 +0100 Subject: [PATCH 031/397] media: atomisp: properly implement g_fmt The current logic only initializes pipe->pix after setting up a pipeline - e. g. after start streaming. While it makes sense to get the format of the pipeline, when it is set, this breaks support for generic applications, as they rely on getting the current sensor format (which is usually the highest resolution format). So, implement a call to the sensor's get_fmt, when this is called before setting up a pipeline. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 13 +----- .../staging/media/atomisp/pci/atomisp_cmd.h | 4 +- .../staging/media/atomisp/pci/atomisp_ioctl.c | 44 +++++++++++++++++-- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 70c8e86c3205..6b308c81ef77 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -2034,7 +2034,7 @@ static int raw_output_format_match_input(u32 input, u32 output) return -EINVAL; } -static u32 get_pixel_depth(u32 pixelformat) +u32 atomisp_get_pixel_depth(u32 pixelformat) { switch (pixelformat) { case V4L2_PIX_FMT_YUV420: @@ -4816,15 +4816,6 @@ int atomisp_get_sensor_mode_data(struct atomisp_sub_device *asd, return 0; } -int atomisp_get_fmt(struct video_device *vdev, struct v4l2_format *f) -{ - struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); - - f->fmt.pix = pipe->pix; - - return 0; -} - static void __atomisp_update_stream_env(struct atomisp_sub_device *asd, u16 stream_index, struct atomisp_input_stream_info *stream_info) { @@ -4973,7 +4964,7 @@ atomisp_try_fmt_file(struct atomisp_device *isp, struct v4l2_format *f) return -EINVAL; } - depth = get_pixel_depth(pixelformat); + depth = atomisp_get_pixel_depth(pixelformat); if (field == V4L2_FIELD_ANY) { field = V4L2_FIELD_NONE; diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index e8bdd264d31b..fb848d716947 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -266,8 +266,6 @@ int atomisp_compare_grid(struct atomisp_sub_device *asd, int atomisp_get_sensor_mode_data(struct atomisp_sub_device *asd, struct atomisp_sensor_mode_data *config); -int atomisp_get_fmt(struct video_device *vdev, struct v4l2_format *f); - /* This function looks up the closest available resolution. */ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, bool *res_overflow); @@ -341,6 +339,8 @@ enum atomisp_metadata_type atomisp_get_metadata_type(struct atomisp_sub_device *asd, enum ia_css_pipe_id pipe_id); +u32 atomisp_get_pixel_depth(u32 pixelformat); + /* Function for HAL to inject a fake event to wake up poll thread */ int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event); diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 29826f8e4143..37542ea17a38 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -838,15 +838,53 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, static int atomisp_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE + }; struct video_device *vdev = video_devdata(file); struct atomisp_device *isp = video_get_drvdata(vdev); - + struct v4l2_fmtdesc fmtdesc = { 0 }; + struct atomisp_video_pipe *pipe; + struct atomisp_sub_device *asd; + struct v4l2_subdev *camera; + u32 depth; int ret; rt_mutex_lock(&isp->mutex); - ret = atomisp_get_fmt(vdev, f); + pipe = atomisp_to_video_pipe(vdev); rt_mutex_unlock(&isp->mutex); - return ret; + + f->fmt.pix = pipe->pix; + if (!f->fmt.pix.width) { + asd = atomisp_to_video_pipe(vdev)->asd; + if (!asd) + return -EINVAL; + + camera = isp->inputs[asd->input_curr].camera; + if(!camera) + return -EINVAL; + + ret = atomisp_enum_fmt_cap(file, fh, &fmtdesc); + if (ret) + return ret; + + rt_mutex_lock(&isp->mutex); + ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, + pad, get_fmt, NULL, &fmt); + rt_mutex_unlock(&isp->mutex); + if (ret) + return ret; + + v4l2_fill_pix_format(&f->fmt.pix, &fmt.format); + + f->fmt.pix.pixelformat = fmtdesc.pixelformat; + } + + depth = atomisp_get_pixel_depth(f->fmt.pix.pixelformat); + f->fmt.pix.bytesperline = (f->fmt.pix.width * depth) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; } static int atomisp_g_fmt_file(struct file *file, void *fh, From 2b806251a5b03ec3c95310253682be2351e6505b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 30 Oct 2021 12:01:30 +0100 Subject: [PATCH 032/397] media: atomisp: report colorspace information While different sensors could have different colorspaces, the colorspace V4L2 support didn't exist by the time atomisp driver was written. So, the sensors won't have any data about that. So, let's report what Asus T101HA uses (ov2680 sensor). It may require further changes, if other sensors used on this driver have different colorspaces. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 15 +++++++++++++++ drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 6b308c81ef77..ff8640314f65 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -4916,6 +4916,13 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, } f->pixelformat = fmt->pixelformat; + /* + * FIXME: do we need to setup this differently, depending on the + * sensor or the pipeline? + */ + f->colorspace = V4L2_COLORSPACE_REC709; + f->ycbcr_enc = V4L2_YCBCR_ENC_709; + f->xfer_func = V4L2_XFER_FUNC_709; /* * If the format is jpeg or custom RAW, then the width and height will @@ -6027,6 +6034,14 @@ done: pipe->pix.width = f->fmt.pix.width; pipe->pix.height = f->fmt.pix.height; pipe->pix.pixelformat = f->fmt.pix.pixelformat; + /* + * FIXME: do we need to setup this differently, depending on the + * sensor or the pipeline? + */ + pipe->pix.colorspace = V4L2_COLORSPACE_REC709; + pipe->pix.ycbcr_enc = V4L2_YCBCR_ENC_709; + pipe->pix.xfer_func = V4L2_XFER_FUNC_709; + if (format_bridge->planar) { pipe->pix.bytesperline = output_info.padded_width; pipe->pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 37542ea17a38..f082d7a67875 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -884,6 +884,14 @@ static int atomisp_g_fmt_cap(struct file *file, void *fh, f->fmt.pix.bytesperline = (f->fmt.pix.width * depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + /* + * FIXME: do we need to setup this differently, depending on the + * sensor or the pipeline? + */ + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709; + f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709; + return 0; } From 5380c4cfeb8e069b0ec1e2aae73c65229d76d18e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 30 Oct 2021 13:08:05 +0100 Subject: [PATCH 033/397] media: atomisp: don't print errors for ignored MBUS formats The bayer formats aren't currently available for userspace to select: those are marked as IA_CSS_FRAME_FORMAT_RAW and trying to get them result on binary firmware load errors: [74625.258097] atomisp-isp2 0000:00:03.0: Using binary isp_preview_var_isp2 (id 22), type 0, mode 1, continuous true [74625.258146] atomisp-isp2 0000:00:03.0: Seeking for binary failed at: [74625.258161] CPU: 3 PID: 2792 Comm: v4l2grab Tainted: G C 5.15.0-rc4+ #77 [74625.258190] Hardware name: ASUSTeK COMPUTER INC. T101HA/T101HA, BIOS T101HA.306 04/23/2019 [74625.258208] Call Trace: [74625.258231] dump_stack_lvl+0x46/0x5a [74625.258272] ia_css_binary_find+0xa7d/0xcf0 [atomisp] [74625.258570] load_preview_binaries+0x323/0x3c0 [atomisp] ... [74625.265892] atomisp-isp2 0000:00:03.0: can't create streams [74625.265937] atomisp-isp2 0000:00:03.0: __get_frame_info 1604x1200 (padded to 0) returned -22 [74625.265962] atomisp-isp2 0000:00:03.0: Can't set format on ISP. Error -22 As those formats are ignored by purpose, it doesn't make any sense to print a message like: atomisp_enum_fmt_cap(): format for code 3007 not found. for those. Yet, some day it would be interesting to also report the bayer formats, letting userspace to decode them on a different way. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index f082d7a67875..8f0a9a69f075 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -829,8 +829,6 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, f->pixelformat = format->pixelformat; return 0; } - dev_err(isp->dev, "%s(): format for code %x not found.\n", - __func__, code.code); return -EINVAL; } From 03723b924867718ca7f357668c414e2a218c18d4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 31 Oct 2021 09:38:51 +0000 Subject: [PATCH 034/397] media: atomisp: report the visible resolution The atomisp sensors and logic adds an extra pad lines/columns, called "dvs envelope". It also uses an extra 12 lines/columns at the sensor for BYT. As those are not visible to userspace, the V4L2 API should decrement such values when reporting the current resolution. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 8f0a9a69f075..d92d41dd0ade 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -876,6 +876,20 @@ static int atomisp_g_fmt_cap(struct file *file, void *fh, v4l2_fill_pix_format(&f->fmt.pix, &fmt.format); f->fmt.pix.pixelformat = fmtdesc.pixelformat; + + /* + * HACK: The atomisp does something different here, as it + * seems to set the sensor to a slightly higher resolution than + * the visible ones. That seems to be needed by atomisp's ISP + * in order to properly handle the frames. So, s_fmt adds 16 + * extra columns/lines. See atomisp_subdev_set_selection(). + * + * Yet, the V4L2 userspace API doesn't expect those, so it + * needs to be decremented when reporting the visible + * resolution to userspace. + */ + f->fmt.pix.width -= pad_w; + f->fmt.pix.height -= pad_h; } depth = atomisp_get_pixel_depth(f->fmt.pix.pixelformat); From 819d679b58bc4f3171b838c7914d55aff65a9f0d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 31 Oct 2021 10:56:10 +0000 Subject: [PATCH 035/397] media: atomisp: comment-out JPEG format This is already disabled on some parts of the code, and trying to use it with current firmware causes an error: [ 53.799946] atomisp-isp2 0000:00:03.0: can't create streams [ 53.799962] atomisp-isp2 0000:00:03.0: __get_frame_info 1600x900 (padded to 0) returned -22 So, completely disable reporting it. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 2 ++ drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index ff8640314f65..feb75491a273 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -1980,9 +1980,11 @@ v4l2_fmt_to_sh_fmt(u32 fmt) return IA_CSS_FRAME_FORMAT_RGBA888; case V4L2_PIX_FMT_RGB565: return IA_CSS_FRAME_FORMAT_RGB565; +#if 0 case V4L2_PIX_FMT_JPEG: case V4L2_PIX_FMT_CUSTOM_M10MO_RAW: return IA_CSS_FRAME_FORMAT_BINARY_8; +#endif case V4L2_PIX_FMT_SBGGR16: case V4L2_PIX_FMT_SBGGR10: case V4L2_PIX_FMT_SGBRG10: diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index d92d41dd0ade..936516daec7d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -492,23 +492,22 @@ const struct atomisp_format_bridge atomisp_output_fmts[] = { .mbus_code = MEDIA_BUS_FMT_BGR565_2X8_LE, .sh_fmt = IA_CSS_FRAME_FORMAT_RGB565, .description = "16 RGB 5-6-5" +#if 0 }, { .pixelformat = V4L2_PIX_FMT_JPEG, .depth = 8, .mbus_code = MEDIA_BUS_FMT_JPEG_1X8, .sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8, .description = "JPEG" - }, -#if 0 - { + }, { /* This is a custom format being used by M10MO to send the RAW data */ .pixelformat = V4L2_PIX_FMT_CUSTOM_M10MO_RAW, .depth = 8, .mbus_code = V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, .sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8, .description = "Custom RAW for M10MO" - }, #endif + }, }; const struct atomisp_format_bridge * From 5814f32fef137e34577c4f053272c53e7ca33cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sun, 12 Sep 2021 17:51:40 +0100 Subject: [PATCH 036/397] media: staging: max96712: Add basic support for MAX96712 GMSL2 deserializer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add basic support for Maxim MAX96712 quad GMSL2 deserializers. The driver is capable of powering on the device and configuring the MIPI CSI-2 bus in a DPHY 4-lane configuration as well as operating the internal VTG (Video Timing Generator) and VPG (Video Pattern Generator). Using these features the driver is able to act as a 1080p @ 30 fps V4L2 video source. Producing either a checkerboard or gradient pattern on the CSI-2 bus, selectable thru a V4L2 control. While the driver is useful as-is and have been used to prove the correct operation of the MAX96712 itself and "downstream" devices using the MAX96712 as a video source there are a lot of features missing. Most notably the ability to operate the GMSL bus. Signed-off-by: Niklas Söderlund Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 6 + drivers/staging/media/Kconfig | 2 + drivers/staging/media/Makefile | 1 + drivers/staging/media/max96712/Kconfig | 13 + drivers/staging/media/max96712/Makefile | 2 + drivers/staging/media/max96712/max96712.c | 440 ++++++++++++++++++++++ 6 files changed, 464 insertions(+) create mode 100644 drivers/staging/media/max96712/Kconfig create mode 100644 drivers/staging/media/max96712/Makefile create mode 100644 drivers/staging/media/max96712/max96712.c diff --git a/MAINTAINERS b/MAINTAINERS index 7a2345ce8521..bb60cfa5daf7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11523,6 +11523,12 @@ S: Maintained F: Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml F: drivers/media/i2c/max9286.c +MAX96712 QUAD GMSL2 DESERIALIZER DRIVER +M: Niklas Söderlund +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/staging/media/max96712/max96712.c + MAX9860 MONO AUDIO VOICE CODEC DRIVER M: Peter Rosin L: alsa-devel@alsa-project.org (moderated for non-subscribers) diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index e3aaae920847..b81cfa74edb7 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -26,6 +26,8 @@ source "drivers/staging/media/hantro/Kconfig" source "drivers/staging/media/imx/Kconfig" +source "drivers/staging/media/max96712/Kconfig" + source "drivers/staging/media/meson/vdec/Kconfig" source "drivers/staging/media/omap4iss/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 5b5afc5b03a0..7e2c86e3695d 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_INTEL_ATOMISP) += atomisp/ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/ +obj-$(CONFIG_VIDEO_MAX96712) += max96712/ obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/ diff --git a/drivers/staging/media/max96712/Kconfig b/drivers/staging/media/max96712/Kconfig new file mode 100644 index 000000000000..258d47644cbd --- /dev/null +++ b/drivers/staging/media/max96712/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +config VIDEO_MAX96712 + tristate "Maxim MAX96712 Quad GMSL2 Deserializer support" + depends on I2C + depends on OF_GPIO + select V4L2_FWNODE + select VIDEO_V4L2_SUBDEV_API + select MEDIA_CONTROLLER + help + This driver supports the Maxim MAX96712 Quad GMSL2 Deserializer. + + To compile this driver as a module, choose M here: the + module will be called max96712. diff --git a/drivers/staging/media/max96712/Makefile b/drivers/staging/media/max96712/Makefile new file mode 100644 index 000000000000..70c1974ce3f0 --- /dev/null +++ b/drivers/staging/media/max96712/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_VIDEO_MAX96712) += max96712.o diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c new file mode 100644 index 000000000000..847e2ffd4f53 --- /dev/null +++ b/drivers/staging/media/max96712/max96712.c @@ -0,0 +1,440 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Maxim MAX9286 Quad GMSL2 Deserializer Driver + * + * Copyright (C) 2021 Renesas Electronics Corporation + * Copyright (C) 2021 Niklas Söderlund + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MAX96712_ID 0x20 + +#define MAX96712_DPLL_FREQ 1000 + +enum max96712_pattern { + MAX96712_PATTERN_CHECKERBOARD = 0, + MAX96712_PATTERN_GRADIENT, +}; + +struct max96712_priv { + struct i2c_client *client; + struct regmap *regmap; + struct gpio_desc *gpiod_pwdn; + + struct v4l2_fwnode_bus_mipi_csi2 mipi; + + struct v4l2_subdev sd; + struct v4l2_ctrl_handler ctrl_handler; + struct media_pad pads[1]; + + enum max96712_pattern pattern; +}; + +static int max96712_read(struct max96712_priv *priv, int reg) +{ + int ret, val; + + ret = regmap_read(priv->regmap, reg, &val); + if (ret) { + dev_err(&priv->client->dev, "read 0x%04x failed\n", reg); + return ret; + } + + return val; +} + +static int max96712_write(struct max96712_priv *priv, unsigned int reg, u8 val) +{ + int ret; + + ret = regmap_write(priv->regmap, reg, val); + if (ret) + dev_err(&priv->client->dev, "write 0x%04x failed\n", reg); + + return ret; +} + +static int max96712_update_bits(struct max96712_priv *priv, unsigned int reg, + u8 mask, u8 val) +{ + int ret; + + ret = regmap_update_bits(priv->regmap, reg, mask, val); + if (ret) + dev_err(&priv->client->dev, "update 0x%04x failed\n", reg); + + return ret; +} + +static int max96712_write_bulk(struct max96712_priv *priv, unsigned int reg, + const void *val, size_t val_count) +{ + int ret; + + ret = regmap_bulk_write(priv->regmap, reg, val, val_count); + if (ret) + dev_err(&priv->client->dev, "bulk write 0x%04x failed\n", reg); + + return ret; +} + +static int max96712_write_bulk_value(struct max96712_priv *priv, + unsigned int reg, unsigned int val, + size_t val_count) +{ + unsigned int i; + u8 values[4]; + + for (i = 1; i <= val_count; i++) + values[i - 1] = (val >> ((val_count - i) * 8)) & 0xff; + + return max96712_write_bulk(priv, reg, &values, val_count); +} + +static void max96712_reset(struct max96712_priv *priv) +{ + max96712_update_bits(priv, 0x13, 0x40, 0x40); + msleep(20); +} + +static void max96712_mipi_enable(struct max96712_priv *priv, bool enable) +{ + if (enable) { + max96712_update_bits(priv, 0x40b, 0x02, 0x02); + max96712_update_bits(priv, 0x8a0, 0x80, 0x80); + } else { + max96712_update_bits(priv, 0x8a0, 0x80, 0x00); + max96712_update_bits(priv, 0x40b, 0x02, 0x00); + } +} + +static void max96712_mipi_configure(struct max96712_priv *priv) +{ + unsigned int i; + u8 phy5 = 0; + + max96712_mipi_enable(priv, false); + + /* Select 2x4 mode. */ + max96712_write(priv, 0x8a0, 0x04); + + /* Configure a 4-lane DPHY using PHY0 and PHY1. */ + /* TODO: Add support for 2-lane and 1-lane configurations. */ + /* TODO: Add support CPHY mode. */ + max96712_write(priv, 0x94a, 0xc0); + + /* Configure lane mapping for PHY0 and PHY1. */ + /* TODO: Add support for lane swapping. */ + max96712_write(priv, 0x8a3, 0xe4); + + /* Configure lane polarity for PHY0 and PHY1. */ + for (i = 0; i < priv->mipi.num_data_lanes + 1; i++) + if (priv->mipi.lane_polarities[i]) + phy5 |= BIT(i == 0 ? 5 : i < 3 ? i - 1 : i); + max96712_write(priv, 0x8a5, phy5); + + /* Set link frequency for PHY0 and PHY1. */ + max96712_update_bits(priv, 0x415, 0x3f, + ((MAX96712_DPLL_FREQ / 100) & 0x1f) | BIT(5)); + max96712_update_bits(priv, 0x418, 0x3f, + ((MAX96712_DPLL_FREQ / 100) & 0x1f) | BIT(5)); + + /* Enable PHY0 and PHY1 */ + max96712_update_bits(priv, 0x8a2, 0xf0, 0x30); +} + +static void max96712_pattern_enable(struct max96712_priv *priv, bool enable) +{ + const u32 h_active = 1920; + const u32 h_fp = 88; + const u32 h_sw = 44; + const u32 h_bp = 148; + const u32 h_tot = h_active + h_fp + h_sw + h_bp; + + const u32 v_active = 1080; + const u32 v_fp = 4; + const u32 v_sw = 5; + const u32 v_bp = 36; + const u32 v_tot = v_active + v_fp + v_sw + v_bp; + + if (!enable) { + max96712_write(priv, 0x1051, 0x00); + return; + } + + /* PCLK 75MHz. */ + max96712_write(priv, 0x0009, 0x01); + + /* Configure Video Timing Generator for 1920x1080 @ 30 fps. */ + max96712_write_bulk_value(priv, 0x1052, 0, 3); + max96712_write_bulk_value(priv, 0x1055, v_sw * h_tot, 3); + max96712_write_bulk_value(priv, 0x1058, + (v_active + v_fp + + v_bp) * h_tot, 3); + max96712_write_bulk_value(priv, 0x105b, 0, 3); + max96712_write_bulk_value(priv, 0x105e, h_sw, 2); + max96712_write_bulk_value(priv, 0x1060, h_active + h_fp + h_bp, 2); + max96712_write_bulk_value(priv, 0x1062, v_tot, 2); + max96712_write_bulk_value(priv, 0x1064, + h_tot * (v_sw + v_bp) + (h_sw + h_bp), 3); + max96712_write_bulk_value(priv, 0x1067, h_active, 2); + max96712_write_bulk_value(priv, 0x1069, h_fp + h_sw + h_bp, 2); + max96712_write_bulk_value(priv, 0x106b, v_active, 2); + + /* Generate VS, HS and DE in free-running mode. */ + max96712_write(priv, 0x1050, 0xfb); + + /* Configure Video Pattern Generator. */ + if (priv->pattern == MAX96712_PATTERN_CHECKERBOARD) { + /* Set checkerboard pattern size. */ + max96712_write(priv, 0x1074, 0x3c); + max96712_write(priv, 0x1075, 0x3c); + max96712_write(priv, 0x1076, 0x3c); + + /* Set checkerboard pattern colors. */ + max96712_write_bulk_value(priv, 0x106e, 0xfecc00, 3); + max96712_write_bulk_value(priv, 0x1071, 0x006aa7, 3); + + /* Generate checkerboard pattern. */ + max96712_write(priv, 0x1051, 0x10); + } else { + /* Set gradient increment. */ + max96712_write(priv, 0x106d, 0x10); + + /* Generate gradient pattern. */ + max96712_write(priv, 0x1051, 0x20); + } +} + +static int max96712_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct max96712_priv *priv = v4l2_get_subdevdata(sd); + + if (enable) { + max96712_pattern_enable(priv, true); + max96712_mipi_enable(priv, true); + } else { + max96712_mipi_enable(priv, false); + max96712_pattern_enable(priv, false); + } + + return 0; +} + +static const struct v4l2_subdev_video_ops max96712_video_ops = { + .s_stream = max96712_s_stream, +}; + +static int max96712_get_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *format) +{ + format->format.width = 1920; + format->format.height = 1080; + format->format.code = MEDIA_BUS_FMT_RGB888_1X24; + format->format.field = V4L2_FIELD_NONE; + + return 0; +} + +static const struct v4l2_subdev_pad_ops max96712_pad_ops = { + .get_fmt = max96712_get_pad_format, + .set_fmt = max96712_get_pad_format, +}; + +static struct v4l2_subdev_ops max96712_subdev_ops = { + .video = &max96712_video_ops, + .pad = &max96712_pad_ops, +}; + +static const char * const max96712_test_pattern[] = { + "Checkerboard", + "Gradient", +}; + +static int max96712_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct max96712_priv *priv = + container_of(ctrl->handler, struct max96712_priv, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_TEST_PATTERN: + priv->pattern = ctrl->val ? + MAX96712_PATTERN_GRADIENT : + MAX96712_PATTERN_CHECKERBOARD; + break; + } + return 0; +} + +static const struct v4l2_ctrl_ops max96712_ctrl_ops = { + .s_ctrl = max96712_s_ctrl, +}; + +static int max96712_v4l2_register(struct max96712_priv *priv) +{ + long pixel_rate; + int ret; + + v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96712_subdev_ops); + priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + + v4l2_ctrl_handler_init(&priv->ctrl_handler, 2); + + /* + * TODO: Once V4L2_CID_LINK_FREQ is changed from a menu control to an + * INT64 control it should be used here instead of V4L2_CID_PIXEL_RATE. + */ + pixel_rate = MAX96712_DPLL_FREQ / priv->mipi.num_data_lanes * 1000000; + v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE, + pixel_rate, pixel_rate, 1, pixel_rate); + + v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, &max96712_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(max96712_test_pattern) - 1, + 0, 0, max96712_test_pattern); + + priv->sd.ctrl_handler = &priv->ctrl_handler; + ret = priv->ctrl_handler.error; + if (ret) + goto error; + + priv->pads[0].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&priv->sd.entity, 1, priv->pads); + if (ret) + goto error; + + v4l2_set_subdevdata(&priv->sd, priv); + + ret = v4l2_async_register_subdev(&priv->sd); + if (ret < 0) { + dev_err(&priv->client->dev, "Unable to register subdevice\n"); + goto error; + } + + return 0; +error: + v4l2_ctrl_handler_free(&priv->ctrl_handler); + + return ret; +} + +static int max96712_parse_dt(struct max96712_priv *priv) +{ + struct fwnode_handle *ep; + struct v4l2_fwnode_endpoint v4l2_ep = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + int ret; + + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(&priv->client->dev), 4, + 0, 0); + if (!ep) { + dev_err(&priv->client->dev, "Not connected to subdevice\n"); + return -EINVAL; + } + + ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep); + fwnode_handle_put(ep); + if (ret) { + dev_err(&priv->client->dev, "Could not parse v4l2 endpoint\n"); + return -EINVAL; + } + + if (v4l2_ep.bus.mipi_csi2.num_data_lanes != 4) { + dev_err(&priv->client->dev, "Only 4 data lanes supported\n"); + return -EINVAL; + } + + priv->mipi = v4l2_ep.bus.mipi_csi2; + + return 0; +} + +static const struct regmap_config max96712_i2c_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = 0x1f00, +}; + +static int max96712_probe(struct i2c_client *client) +{ + struct max96712_priv *priv; + int ret; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->client = client; + i2c_set_clientdata(client, priv); + + priv->regmap = devm_regmap_init_i2c(client, &max96712_i2c_regmap); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable", + GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpiod_pwdn)) + return PTR_ERR(priv->gpiod_pwdn); + + gpiod_set_consumer_name(priv->gpiod_pwdn, "max96712-pwdn"); + gpiod_set_value_cansleep(priv->gpiod_pwdn, 1); + + if (priv->gpiod_pwdn) + usleep_range(4000, 5000); + + if (max96712_read(priv, 0x4a) != MAX96712_ID) + return -ENODEV; + + max96712_reset(priv); + + ret = max96712_parse_dt(priv); + if (ret) + return ret; + + max96712_mipi_configure(priv); + + return max96712_v4l2_register(priv); +} + +static int max96712_remove(struct i2c_client *client) +{ + struct max96712_priv *priv = i2c_get_clientdata(client); + + v4l2_async_unregister_subdev(&priv->sd); + + gpiod_set_value_cansleep(priv->gpiod_pwdn, 0); + + return 0; +} + +static const struct of_device_id max96712_of_table[] = { + { .compatible = "maxim,max96712" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, max96712_of_table); + +static struct i2c_driver max96712_i2c_driver = { + .driver = { + .name = "max96712", + .of_match_table = of_match_ptr(max96712_of_table), + }, + .probe_new = max96712_probe, + .remove = max96712_remove, +}; + +module_i2c_driver(max96712_i2c_driver); + +MODULE_DESCRIPTION("Maxim MAX96712 Quad GMSL2 Deserializer Driver"); +MODULE_AUTHOR("Niklas Söderlund "); +MODULE_LICENSE("GPL"); From b2598d9fa6e14a50b932201effe00299162bc06e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 2 Nov 2021 06:49:21 +0000 Subject: [PATCH 037/397] media: atomisp: add a default case at __get_frame_info() The switch() logic there misses a break and a default case. That makes it more prone to problems as the code change. Suggested-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_compat_css20.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 1309855bb6c8..a8972b231e06 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -2691,9 +2691,11 @@ static int __get_frame_info(struct atomisp_sub_device *asd, *info = p_info.output_info[1]; dev_dbg(isp->dev, "getting second main frame info.\n"); break; + default: case ATOMISP_CSS_RAW_FRAME: *info = p_info.raw_output_info; dev_dbg(isp->dev, "getting raw frame info.\n"); + break; } dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n", info->res.width, info->res.height, p_info.num_invalid_frames); From fcb10617f4654abdc7382abb8ee73bc7972fb268 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 1 Nov 2021 11:35:29 +0000 Subject: [PATCH 038/397] media: atomisp: TODO: make it updated to the current issues Now that this driver starting to show signals of real progress, let's update its TODO list. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/TODO | 191 +++++++++++++++++++---------- 1 file changed, 126 insertions(+), 65 deletions(-) diff --git a/drivers/staging/media/atomisp/TODO b/drivers/staging/media/atomisp/TODO index 2d1ef9eb262a..43b842043f29 100644 --- a/drivers/staging/media/atomisp/TODO +++ b/drivers/staging/media/atomisp/TODO @@ -1,92 +1,161 @@ +For both Cherrytrail (CHT) and Baytrail (BHT) the driver +requires the "candrpv_0415_20150521_0458" firmware version. +It should be noticed that the firmware file is different, +depending on the ISP model, so they're stored with different +names: + +- for BHT: /lib/firmware/shisp_2400b0_v21.bin + + Warning: The driver was not tested yet for BHT. + +- for CHT: /lib/firmware/shisp_2401a0_v21.bin + + https://github.com/intel-aero/meta-intel-aero-base/blob/master/recipes-kernel/linux/linux-yocto/shisp_2401a0_v21.bin + NOTE: ===== -While the driver probes the hardware and reports itself as a -V4L2 driver, there are still some issues preventing it to -stream (at least it doesn't with the standard V4L2 applications. -Didn't test yet with some custom-made app for this driver). -Solving the related bugs and issues preventing it to work is -needed (items 6 and 7 from the list below). +This driver currently doesn't work with most V4L2 applications, +as there are still some issues with regards to implementing +certain APIs at the standard way. + +Also, currently only USERPTR streaming mode is working. + +In order to test, it is needed to know what's the sensor's +resolution. This can be checked with: + +$ v4l2-ctl --get-fmt-video + Format Video Capture: + Width/Height : 1600/1200 + ... + +It is known to work with: + +- v4l2grab at contrib/test directory at https://git.linuxtv.org/v4l-utils.git/ + + The resolution should not be bigger than the max resolution + supported by the sensor, or it will fail. So, if the sensor + reports: + + The driver can be tested with: + + v4l2grab -f YUYV -x 1600 -y 1200 -d /dev/video2 -u + +- NVT at https://github.com/intel/nvt + + $ ./v4l2n -o testimage_@.raw \ + --device /dev/video2 \ + --input 0 \ + --exposure=30000,30000,30000,30000 \ + --parm type=1,capturemode=CI_MODE_PREVIEW \ + --fmt type=1,width=1600,height=1200,pixelformat=YUYV \ + --reqbufs count=2,memory=USERPTR \ + --parameters=wb_config.r=32768,wb_config.gr=21043,wb_config.gb=21043,wb_config.b=30863 \ + --capture=20 + + As the output is in raw format, images need to be converted with: + + $ for i in $(seq 0 19); do + name="testimage_$(printf "%03i" $i)" + ./raw2pnm -x$WIDTH -y$HEIGHT -f$FORMAT $name.raw $name.pnm + rm $name.raw + done TODO ==== -1. The atomisp doesn't rely at the usual i2c stuff to discover the - sensors. Instead, it calls a function from atomisp_gmin_platform.c. - There are some hacks added there for it to wait for sensors to be - probed (with a timeout of 2 seconds or so). - This should be converted to the usual way, using V4L2 async subdev - framework to wait for cameras to be probed; +1. Fix support for MMAP streaming mode. This is required for most + V4L2 applications; -2. Use ACPI _DSM table - DONE! +2. Implement and/or fix V4L2 ioctls in order to allow a normal app to + use it; -3. Switch the driver to use pm_runtime stuff. Right now, it probes the - existing PMIC code and sensors call it directly. +3. Ensure that the driver will pass v4l2-compliance tests; -4. There's a problem at the sensor drivers: when trying to set a video - format, the atomisp main driver calls the sensor drivers with the - sensor turned off. This causes them to fail. +4. Get manufacturer's authorization to redistribute the binaries for + the firmware files; - The only exception is the atomisp-ov2880, which has a hack inside it - to turn it on when VIDIOC_S_FMT is called. +5. remove VIDEO_ATOMISP_ISP2401, making the driver to auto-detect the + register address differences between ISP2400 and ISP2401; - The right fix seems to power on the sensor when a video device is - opened (or at the first VIDIOC_ ioctl - except for VIDIOC_QUERYCAP), - powering it down at close() syscall. +6. Cleanup the driver code, removing the abstraction layers inside it; - Such kind of control would need to be done inside the atomisp driver, - not at the sensors code. +7. The atomisp doesn't rely at the usual i2c stuff to discover the + sensors. Instead, it calls a function from atomisp_gmin_platform.c. + There are some hacks added there for it to wait for sensors to be + probed (with a timeout of 2 seconds or so). This should be converted + to the usual way, using V4L2 async subdev framework to wait for + cameras to be probed; -5. There are several issues related to memory management, causing - crashes. The atomisp splits the memory management on three separate - regions: +8. Switch to standard V4L2 sub-device API for sensor and lens. In + particular, the user space API needs to support V4L2 controls as + defined in the V4L2 spec and references to atomisp must be removed from + these drivers. + +9. Use LED flash API for flash LED drivers such as LM3554 (which already + has a LED class driver). + +10. Migrate the sensor drivers out of staging or re-using existing + drivers; + +11. Switch the driver to use pm_runtime stuff. Right now, it probes the + existing PMIC code and sensors call it directly. + +12. There's a problem on sensor drivers: when trying to set a video + format, the atomisp main driver calls the sensor drivers with the + sensor turned off. This causes them to fail. + + This was fixed at atomisp-ov2880, which has a hack inside it + to turn it on when VIDIOC_S_FMT is called, but this has to be + cheked on other drivers as well. + + The right fix seems to power on the sensor when a video device is + opened (or at the first VIDIOC_ ioctl - except for VIDIOC_QUERYCAP), + powering it down at close() syscall. + + Such kind of control would need to be done inside the atomisp driver, + not at the sensors code. + +13. There are several issues related to memory management, that can + cause crashes and/or memory leaks. The atomisp splits the memory + management on three separate regions: - dynamic pool; - reserved pool; - generic pool - The code implementing it is at: + The code implementing it is at: drivers/staging/media/atomisp/pci/hmm/ - It also has a separate code for managing DMA buffers at: + It also has a separate code for managing DMA buffers at: drivers/staging/media/atomisp/pci/mmu/ - The code there is really dirty, ugly and probably wrong. I fixed - one bug there already, but the best would be to just trash it and use - something else. Maybe the code from the newer intel driver could - serve as a model: + The code there is really dirty, ugly and probably wrong. I fixed + one bug there already, but the best would be to just trash it and use + something else. Maybe the code from the newer intel driver could + serve as a model: drivers/staging/media/ipu3/ipu3-mmu.c - But converting it to use something like that is painful and may - cause some breakages. + But converting it to use something like that is painful and may + cause some breakages. -6. There is some issues at the frame receive logic, causing the - DQBUF ioctls to fail. +14. The file structure needs to get tidied up to resemble a normal Linux + driver. -7. A single AtomISP driver needs to be implemented to support both - Baytrail (BYT) and Cherrytail (CHT) platforms at the same time. - The current driver is a mechanical and hand combined merge of the - two using several runtime macros, plus some ifdef ISP2401 to select the - CHT version. Yet, there are some ISP-specific headers that change the - driver's behavior during compile time. +15. Lots of the midlayer glue. Unused code and abstraction needs removing. -8. The file structure needs to get tidied up to resemble a normal Linux - driver. - -9. Lots of the midlayer glue. unused code and abstraction needs removing. - -10. The AtomISP driver includes some special IOCTLS (ATOMISP_IOC_XXXX_XXXX) +16. The AtomISP driver includes some special IOCTLS (ATOMISP_IOC_XXXX_XXXX) and controls that require some cleanup. Some of those code may have been removed during the cleanups. They could be needed in order to - properly support 3A algorithms + properly support 3A algorithms. Such IOCTL interface needs more documentation. The better would be to use something close to the interface used by the IPU3 IMGU driver. -11. The ISP code has some dependencies of the exact FW version. +17. The ISP code has some dependencies of the exact FW version. The version defined in pci/sh_css_firmware.c: BYT (isp2400): "irci_stable_candrpv_0415_20150521_0458" @@ -106,24 +175,16 @@ TODO there are any specific things that can be done to fold in support for multiple firmware versions. -12. Switch to standard V4L2 sub-device API for sensor and lens. In - particular, the user space API needs to support V4L2 controls as - defined in the V4L2 spec and references to atomisp must be removed from - these drivers. -13. Use LED flash API for flash LED drivers such as LM3554 (which already - has a LED class driver). +18. Switch from videobuf1 to videobuf2. Videobuf1 is being removed! -14. Switch from videobuf1 to videobuf2. Videobuf1 is being removed! - -15. Correct Coding Style. Please refrain sending coding style patches +19. Correct Coding Style. Please refrain sending coding style patches for this driver until the other work is done, as there will be a lot of code churn until this driver becomes functional again. -16. Fix private ioctls to not need a compat_ioctl handler for running - 32-bit tasks. The compat code has been removed because of bugs, - and should not be needed for modern drivers. Fixing this properly - unfortunately means an incompatible ABI change. +20. Remove the logic which sets up pipelines inside it, moving it to + libcamera and implement MC support. + Limitations =========== From 7474731541118aa32eaff38f4fb669f4a5208d22 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 2 Nov 2021 07:39:18 +0000 Subject: [PATCH 039/397] media: atomisp: align sizes returned by g_fmt Repeat the same round logic used inside s_fmt here, for the sake of sanity. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 936516daec7d..8df052f6190d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -892,8 +892,8 @@ static int atomisp_g_fmt_cap(struct file *file, void *fh, } depth = atomisp_get_pixel_depth(f->fmt.pix.pixelformat); - f->fmt.pix.bytesperline = (f->fmt.pix.width * depth) >> 3; - f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.bytesperline = DIV_ROUND_UP(f->fmt.pix.width * depth, 8); + f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline); /* * FIXME: do we need to setup this differently, depending on the From 9a542497cc887d2278689ee576c57c34072080f0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 11:20:37 +0000 Subject: [PATCH 040/397] media: atomisp: move a debug printf to a better place The sensor width/height report is alread being printed after its calculus. The only reason for an extra debug printk is when dis is used. So, change its message to reflect and move it to be inside the if checks. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index feb75491a273..76c9e89afb48 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -5583,6 +5583,10 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, pad, set_fmt, &pad_state, &vformat); if (ret) return ret; + + dev_dbg(isp->dev, "video dis: sensor width: %d, height: %d\n", + ffmt->width, ffmt->height); + if (ffmt->width < req_ffmt->width || ffmt->height < req_ffmt->height) { req_ffmt->height -= dvs_env_h; @@ -5593,8 +5597,6 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, asd->params.video_dis_en = false; } } - dev_dbg(isp->dev, "sensor width: %d, height: %d\n", - ffmt->width, ffmt->height); vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, set_fmt, NULL, &vformat); From f5f3cedf2b5a48af3092e7bc865ad65284503f5e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 11:23:14 +0000 Subject: [PATCH 041/397] media: atomisp: fix VIDIOC_S_FMT logic There are several issues on S_FMT implementation: - it doesn't properly handle pad_h/pad_w; - it reports a wrong visible size to userspace; - it allows setting the format to a raw mode, which currently causes the pipeline to break. Address such issues, for it to start working with generic apps. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 76c9e89afb48..851046ecbdbf 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -5635,13 +5635,17 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) const struct atomisp_format_bridge *format_bridge; const struct atomisp_format_bridge *snr_format_bridge; struct ia_css_frame_info output_info, raw_output_info; - struct v4l2_pix_format snr_fmt = f->fmt.pix; - struct v4l2_pix_format backup_fmt = snr_fmt, s_fmt; + struct v4l2_pix_format snr_fmt; + struct v4l2_pix_format backup_fmt, s_fmt; unsigned int dvs_env_w = 0, dvs_env_h = 0; unsigned int padding_w = pad_w, padding_h = pad_h; bool res_overflow = false, crop_needs_override = false; struct v4l2_mbus_framefmt *isp_sink_fmt; struct v4l2_mbus_framefmt isp_source_fmt = {0}; + struct v4l2_subdev_format vformat = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + struct v4l2_mbus_framefmt *ffmt = &vformat.format; struct v4l2_rect isp_sink_crop; u16 source_pad = atomisp_subdev_source_pad(vdev); struct v4l2_subdev_fh fh; @@ -5672,9 +5676,38 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) if (!format_bridge) return -EINVAL; + /* Currently, raw formats are broken!!! */ + + if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; + + format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); + if (!format_bridge) + return -EINVAL; + } pipe->sh_fmt = format_bridge->sh_fmt; pipe->pix.pixelformat = f->fmt.pix.pixelformat; + /* Ensure that the resolution is equal or below the maximum supported */ + + vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; + v4l2_fill_mbus_format(ffmt, &f->fmt.pix, format_bridge->mbus_code); + ffmt->height += padding_h; + ffmt->width += padding_w; + + ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, + set_fmt, NULL, &vformat); + if (ret) + return ret; + + f->fmt.pix.width = ffmt->width - padding_w; + f->fmt.pix.height = ffmt->height - padding_h; + + snr_fmt = f->fmt.pix; + backup_fmt = snr_fmt; + + /**********************************************************************/ + if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VF || (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)) { @@ -6080,6 +6113,15 @@ done: else isp->need_gfx_throttle = true; + /* Report the needed sizes */ + f->fmt.pix.sizeimage = pipe->pix.sizeimage; + f->fmt.pix.bytesperline = pipe->pix.bytesperline; + + dev_dbg(isp->dev, "%s: %dx%d, image size: %d, %d bytes per line\n", + __func__, + f->fmt.pix.width, f->fmt.pix.height, + f->fmt.pix.sizeimage, f->fmt.pix.bytesperline); + return 0; } From cc55907585f54bc748ebaf29a5427478de8304cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 11:27:55 +0000 Subject: [PATCH 042/397] media: atomisp: fix enum_fmt logic Currently, the enum lists the sensor's native format as a supported format. However, trying to setup a pipeline using it doesn't work. So, exclude such formats from the enum. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 8df052f6190d..30483a84ed80 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -775,6 +775,7 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, struct v4l2_subdev_mbus_code_enum code = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; + const struct atomisp_format_bridge *format; struct v4l2_subdev *camera; unsigned int i, fi = 0; int rval; @@ -806,15 +807,15 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, return rval; for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) { - const struct atomisp_format_bridge *format = - &atomisp_output_fmts[i]; + format = &atomisp_output_fmts[i]; /* * Is the atomisp-supported format is valid for the * sensor (configuration)? If not, skip it. + * + * FIXME: fix the pipeline to allow sensor format too. */ - if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW - && format->mbus_code != code.code) + if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) continue; /* Found a match. Now let's pick f->index'th one. */ From e0d42fc0ddbc4660afd6c725e1e75af3ce229f7d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 11:32:13 +0000 Subject: [PATCH 043/397] media: atomisp: move atomisp_g_fmt_cap() move atomisp_g_fmt_cap() for it to be after try_fmt, as we'll re-use try_fmt there. No functional changes. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 30483a84ed80..84ff97dabbed 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -833,6 +833,34 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, return -EINVAL; } +static int atomisp_g_fmt_file(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct video_device *vdev = video_devdata(file); + struct atomisp_device *isp = video_get_drvdata(vdev); + struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); + + rt_mutex_lock(&isp->mutex); + f->fmt.pix = pipe->pix; + rt_mutex_unlock(&isp->mutex); + + return 0; +} + +/* This function looks up the closest available resolution. */ +static int atomisp_try_fmt_cap(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct video_device *vdev = video_devdata(file); + struct atomisp_device *isp = video_get_drvdata(vdev); + int ret; + + rt_mutex_lock(&isp->mutex); + ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL); + rt_mutex_unlock(&isp->mutex); + return ret; +} + static int atomisp_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { @@ -907,34 +935,6 @@ static int atomisp_g_fmt_cap(struct file *file, void *fh, return 0; } -static int atomisp_g_fmt_file(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct video_device *vdev = video_devdata(file); - struct atomisp_device *isp = video_get_drvdata(vdev); - struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); - - rt_mutex_lock(&isp->mutex); - f->fmt.pix = pipe->pix; - rt_mutex_unlock(&isp->mutex); - - return 0; -} - -/* This function looks up the closest available resolution. */ -static int atomisp_try_fmt_cap(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct video_device *vdev = video_devdata(file); - struct atomisp_device *isp = video_get_drvdata(vdev); - int ret; - - rt_mutex_lock(&isp->mutex); - ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL); - rt_mutex_unlock(&isp->mutex); - return ret; -} - static int atomisp_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { From c9e9094c4e42124af909b2f5f6ded0498e0854ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 11:45:27 +0000 Subject: [PATCH 044/397] media: atomisp: fix try_fmt logic The internal try_fmt logic is not meant to provide everything that the V4L2 API should provide. Also, it doesn't decrement the pads that are used only internally by the driver, but aren't part of the device's output. Fix it. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 7 -- .../staging/media/atomisp/pci/atomisp_ioctl.c | 72 ++++++++++++++++++- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 851046ecbdbf..0ddee36cdcd7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -4918,13 +4918,6 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, } f->pixelformat = fmt->pixelformat; - /* - * FIXME: do we need to setup this differently, depending on the - * sensor or the pipeline? - */ - f->colorspace = V4L2_COLORSPACE_REC709; - f->ycbcr_enc = V4L2_YCBCR_ENC_709; - f->xfer_func = V4L2_XFER_FUNC_709; /* * If the format is jpeg or custom RAW, then the width and height will diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 84ff97dabbed..1e6da6116a06 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -847,6 +847,72 @@ static int atomisp_g_fmt_file(struct file *file, void *fh, return 0; } +static int atomisp_adjust_fmt(struct v4l2_format *f) +{ + const struct atomisp_format_bridge *format_bridge; + u32 padded_width; + + format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); + + padded_width = f->fmt.pix.width + pad_w; + + if (format_bridge->planar) { + f->fmt.pix.bytesperline = padded_width; + f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * + DIV_ROUND_UP(format_bridge->depth * + padded_width, 8)); + } else { + f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth * + padded_width, 8); + f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline); + } + + if (f->fmt.pix.field == V4L2_FIELD_ANY) + f->fmt.pix.field = V4L2_FIELD_NONE; + + format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); + if (!format_bridge) + return -EINVAL; + + /* Currently, raw formats are broken!!! */ + if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; + + format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); + if (!format_bridge) + return -EINVAL; + } + + padded_width = f->fmt.pix.width + pad_w; + + if (format_bridge->planar) { + f->fmt.pix.bytesperline = padded_width; + f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * + DIV_ROUND_UP(format_bridge->depth * + padded_width, 8)); + } else { + f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth * + padded_width, 8); + f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline); + } + + if (f->fmt.pix.field == V4L2_FIELD_ANY) + f->fmt.pix.field = V4L2_FIELD_NONE; + + /* + * FIXME: do we need to setup this differently, depending on the + * sensor or the pipeline? + */ + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709; + f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709; + + f->fmt.pix.width -= pad_w; + f->fmt.pix.height -= pad_h; + + return 0; +} + /* This function looks up the closest available resolution. */ static int atomisp_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) @@ -858,7 +924,11 @@ static int atomisp_try_fmt_cap(struct file *file, void *fh, rt_mutex_lock(&isp->mutex); ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL); rt_mutex_unlock(&isp->mutex); - return ret; + + if (ret) + return ret; + + return atomisp_adjust_fmt(f); } static int atomisp_g_fmt_cap(struct file *file, void *fh, From 0fbca1028567aa42133198e08d1a4421e133f1a5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 11:47:10 +0000 Subject: [PATCH 045/397] media: atomisp: fix g_fmt logic The g_fmt logic is currently broken, as it is not returning the same imagesize as previoulsy calculated by s_fmt. Fix it by just re-using whatever it was defined at s_fmt, if this was called before. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 64 ++----------------- 1 file changed, 7 insertions(+), 57 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 1e6da6116a06..2fb64d5cbead 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -934,75 +934,25 @@ static int atomisp_try_fmt_cap(struct file *file, void *fh, static int atomisp_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { - struct v4l2_subdev_format fmt = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE - }; struct video_device *vdev = video_devdata(file); struct atomisp_device *isp = video_get_drvdata(vdev); - struct v4l2_fmtdesc fmtdesc = { 0 }; struct atomisp_video_pipe *pipe; - struct atomisp_sub_device *asd; - struct v4l2_subdev *camera; - u32 depth; - int ret; rt_mutex_lock(&isp->mutex); pipe = atomisp_to_video_pipe(vdev); rt_mutex_unlock(&isp->mutex); f->fmt.pix = pipe->pix; - if (!f->fmt.pix.width) { - asd = atomisp_to_video_pipe(vdev)->asd; - if (!asd) - return -EINVAL; - camera = isp->inputs[asd->input_curr].camera; - if(!camera) - return -EINVAL; + /* If s_fmt was issued, just return whatever is was previouly set */ + if (f->fmt.pix.sizeimage) + return 0; - ret = atomisp_enum_fmt_cap(file, fh, &fmtdesc); - if (ret) - return ret; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + f->fmt.pix.width = 10000; + f->fmt.pix.height = 10000; - rt_mutex_lock(&isp->mutex); - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - pad, get_fmt, NULL, &fmt); - rt_mutex_unlock(&isp->mutex); - if (ret) - return ret; - - v4l2_fill_pix_format(&f->fmt.pix, &fmt.format); - - f->fmt.pix.pixelformat = fmtdesc.pixelformat; - - /* - * HACK: The atomisp does something different here, as it - * seems to set the sensor to a slightly higher resolution than - * the visible ones. That seems to be needed by atomisp's ISP - * in order to properly handle the frames. So, s_fmt adds 16 - * extra columns/lines. See atomisp_subdev_set_selection(). - * - * Yet, the V4L2 userspace API doesn't expect those, so it - * needs to be decremented when reporting the visible - * resolution to userspace. - */ - f->fmt.pix.width -= pad_w; - f->fmt.pix.height -= pad_h; - } - - depth = atomisp_get_pixel_depth(f->fmt.pix.pixelformat); - f->fmt.pix.bytesperline = DIV_ROUND_UP(f->fmt.pix.width * depth, 8); - f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline); - - /* - * FIXME: do we need to setup this differently, depending on the - * sensor or the pipeline? - */ - f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; - f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709; - f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709; - - return 0; + return atomisp_try_fmt_cap(file, fh, f); } static int atomisp_s_fmt_cap(struct file *file, void *fh, From b7573661282c92c8a186e7bf99a7cb3119daaf80 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Nov 2021 15:58:39 +0000 Subject: [PATCH 046/397] media: atomisp-ov2680: use v4l2_find_nearest_size() Instead of reinventing the wheel, use v4l2_find_nearest_size() in order to get the closest resolution. This should address a bug where the wrong resolution was selected. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 127 ++++-------------- drivers/staging/media/atomisp/i2c/ov2680.h | 3 +- 2 files changed, 25 insertions(+), 105 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 2111e4a478c1..ef439937717b 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -147,7 +147,7 @@ static int ov2680_g_bin_factor_x(struct v4l2_subdev *sd, s32 *val) struct i2c_client *client = v4l2_get_subdevdata(sd); dev_dbg(&client->dev, "++++ov2680_g_bin_factor_x\n"); - *val = ov2680_res[dev->fmt_idx].bin_factor_x; + *val = dev->res->bin_factor_x; return 0; } @@ -157,7 +157,7 @@ static int ov2680_g_bin_factor_y(struct v4l2_subdev *sd, s32 *val) struct ov2680_device *dev = to_ov2680_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - *val = ov2680_res[dev->fmt_idx].bin_factor_y; + *val = dev->res->bin_factor_y; dev_dbg(&client->dev, "++++ov2680_g_bin_factor_y\n"); return 0; } @@ -254,7 +254,7 @@ static long __ov2680_set_exposure(struct v4l2_subdev *sd, int coarse_itg, "+++++++__ov2680_set_exposure coarse_itg %d, gain %d, digitgain %d++\n", coarse_itg, gain, digitgain); - vts = ov2680_res[dev->fmt_idx].lines_per_frame; + vts = dev->res->lines_per_frame; /* group hold */ ret = ov2680_write_reg(client, 1, @@ -843,76 +843,6 @@ static int ov2680_s_power(struct v4l2_subdev *sd, int on) return ret; } -/* - * distance - calculate the distance - * @res: resolution - * @w: width - * @h: height - * - * Get the gap between resolution and w/h. - * res->width/height smaller than w/h wouldn't be considered. - * Returns the value of gap or -1 if fail. - */ -#define LARGEST_ALLOWED_RATIO_MISMATCH 600 -static int distance(struct ov2680_resolution *res, u32 w, u32 h) -{ - unsigned int w_ratio = (res->width << 13) / w; - unsigned int h_ratio; - int match; - - if (h == 0) - return -1; - h_ratio = (res->height << 13) / h; - if (h_ratio == 0) - return -1; - match = abs(((w_ratio << 13) / h_ratio) - 8192); - - if ((w_ratio < 8192) || (h_ratio < 8192) || - (match > LARGEST_ALLOWED_RATIO_MISMATCH)) - return -1; - - return w_ratio + h_ratio; -} - -/* Return the nearest higher resolution index */ -static int nearest_resolution_index(int w, int h) -{ - int i; - int idx = -1; - int dist; - int min_dist = INT_MAX; - struct ov2680_resolution *tmp_res = NULL; - - for (i = 0; i < N_RES; i++) { - tmp_res = &ov2680_res[i]; - dist = distance(tmp_res, w, h); - if (dist == -1) - continue; - if (dist < min_dist) { - min_dist = dist; - idx = i; - } - } - - return idx; -} - -static int get_resolution_index(int w, int h) -{ - int i; - - for (i = 0; i < N_RES; i++) { - if (w != ov2680_res[i].width) - continue; - if (h != ov2680_res[i].height) - continue; - - return i; - } - - return -1; -} - static int ov2680_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) @@ -921,8 +851,8 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, struct ov2680_device *dev = to_ov2680_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); struct camera_mipi_info *ov2680_info = NULL; + struct ov2680_resolution *res; int ret = 0; - int idx = 0; dev_dbg(&client->dev, "%s: %s: pad: %d, fmt: %p\n", __func__, @@ -940,41 +870,34 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, return -EINVAL; mutex_lock(&dev->input_lock); - idx = nearest_resolution_index(fmt->width, fmt->height); - if (idx == -1) { - /* return the largest resolution */ - fmt->width = ov2680_res[N_RES - 1].width; - fmt->height = ov2680_res[N_RES - 1].height; - } else { - fmt->width = ov2680_res[idx].width; - fmt->height = ov2680_res[idx].height; - } + + res = v4l2_find_nearest_size(ov2680_res_preview, + ARRAY_SIZE(ov2680_res_preview), width, + height, fmt->width, fmt->height); + if (!res) + res = &ov2680_res[N_RES - 1]; + + fmt->width = res->width; + fmt->height = res->height; + fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; if (format->which == V4L2_SUBDEV_FORMAT_TRY) { sd_state->pads->try_fmt = *fmt; mutex_unlock(&dev->input_lock); return 0; } - dev->fmt_idx = get_resolution_index(fmt->width, fmt->height); - dev_dbg(&client->dev, "%s: Resolution index: %d\n", - __func__, dev->fmt_idx); - if (dev->fmt_idx == -1) { - dev_err(&client->dev, "get resolution fail\n"); - mutex_unlock(&dev->input_lock); - return -EINVAL; - } - dev_dbg(&client->dev, "%s: i=%d, w=%d, h=%d\n", - __func__, dev->fmt_idx, fmt->width, fmt->height); + + dev_dbg(&client->dev, "%s: %dx%d\n", + __func__, fmt->width, fmt->height); // IS IT NEEDED? power_up(sd); - ret = ov2680_write_reg_array(client, ov2680_res[dev->fmt_idx].regs); + ret = ov2680_write_reg_array(client, dev->res->regs); if (ret) dev_err(&client->dev, "ov2680 write resolution register err: %d\n", ret); - ret = ov2680_get_intg_factor(client, ov2680_info, - &ov2680_res[dev->fmt_idx]); + ret = ov2680_get_intg_factor(client, ov2680_info, res); if (ret) { dev_err(&client->dev, "failed to get integration factor\n"); goto err; @@ -989,8 +912,6 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, if (v_flag) ov2680_v_flip(sd, v_flag); - v4l2_info(client, "\n%s idx %d\n", __func__, dev->fmt_idx); - /* * ret = startup(sd); * if (ret) @@ -1014,8 +935,8 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd, if (!fmt) return -EINVAL; - fmt->width = ov2680_res[dev->fmt_idx].width; - fmt->height = ov2680_res[dev->fmt_idx].height; + fmt->width = dev->res->width; + fmt->height = dev->res->height; fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; return 0; @@ -1155,7 +1076,7 @@ static int ov2680_g_frame_interval(struct v4l2_subdev *sd, struct ov2680_device *dev = to_ov2680_sensor(sd); interval->interval.numerator = 1; - interval->interval.denominator = ov2680_res[dev->fmt_idx].fps; + interval->interval.denominator = dev->res->fps; return 0; } @@ -1193,7 +1114,7 @@ static int ov2680_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) struct ov2680_device *dev = to_ov2680_sensor(sd); mutex_lock(&dev->input_lock); - *frames = ov2680_res[dev->fmt_idx].skip_frames; + *frames = dev->res->skip_frames; mutex_unlock(&dev->input_lock); return 0; @@ -1257,7 +1178,7 @@ static int ov2680_probe(struct i2c_client *client) mutex_init(&dev->input_lock); - dev->fmt_idx = 0; + dev->res = &ov2680_res_preview[0]; v4l2_i2c_subdev_init(&dev->sd, client, &ov2680_ops); pdata = gmin_camera_platform_data(&dev->sd, diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index 874115f35fca..535440ed14d7 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -172,11 +172,10 @@ struct ov2680_device { struct v4l2_mbus_framefmt format; struct mutex input_lock; struct v4l2_ctrl_handler ctrl_handler; + struct ov2680_resolution *res; struct camera_sensor_platform_data *platform_data; int vt_pix_clk_freq_mhz; - int fmt_idx; int run_mode; - u8 res; u8 type; }; From b4e281666cb2ea1134e0f20445d4a6acbc810e38 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 13:17:50 +0000 Subject: [PATCH 047/397] media: atomisp-ov2722: use v4l2_find_nearest_size() Instead of reinventing the wheel, use v4l2_find_nearest_size() in order to get the closest resolution. This should address a bug where the wrong resolution was selected. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2722.c | 118 ++++-------------- drivers/staging/media/atomisp/i2c/ov2722.h | 3 +- 2 files changed, 22 insertions(+), 99 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c index 90d0871a78a3..da98094d7094 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c @@ -557,7 +557,7 @@ static int ov2722_g_volatile_ctrl(struct v4l2_ctrl *ctrl) ret = ov2722_g_fnumber_range(&dev->sd, &ctrl->val); break; case V4L2_CID_LINK_FREQ: - val = ov2722_res[dev->fmt_idx].mipi_freq; + val = dev->res->mipi_freq; if (val == 0) return -EINVAL; @@ -782,76 +782,6 @@ static int ov2722_s_power(struct v4l2_subdev *sd, int on) return ret; } -/* - * distance - calculate the distance - * @res: resolution - * @w: width - * @h: height - * - * Get the gap between resolution and w/h. - * res->width/height smaller than w/h wouldn't be considered. - * Returns the value of gap or -1 if fail. - */ -#define LARGEST_ALLOWED_RATIO_MISMATCH 800 -static int distance(struct ov2722_resolution *res, u32 w, u32 h) -{ - unsigned int w_ratio = (res->width << 13) / w; - unsigned int h_ratio; - int match; - - if (h == 0) - return -1; - h_ratio = (res->height << 13) / h; - if (h_ratio == 0) - return -1; - match = abs(((w_ratio << 13) / h_ratio) - 8192); - - if ((w_ratio < 8192) || (h_ratio < 8192) || - (match > LARGEST_ALLOWED_RATIO_MISMATCH)) - return -1; - - return w_ratio + h_ratio; -} - -/* Return the nearest higher resolution index */ -static int nearest_resolution_index(int w, int h) -{ - int i; - int idx = -1; - int dist; - int min_dist = INT_MAX; - struct ov2722_resolution *tmp_res = NULL; - - for (i = 0; i < N_RES; i++) { - tmp_res = &ov2722_res[i]; - dist = distance(tmp_res, w, h); - if (dist == -1) - continue; - if (dist < min_dist) { - min_dist = dist; - idx = i; - } - } - - return idx; -} - -static int get_resolution_index(int w, int h) -{ - int i; - - for (i = 0; i < N_RES; i++) { - if (w != ov2722_res[i].width) - continue; - if (h != ov2722_res[i].height) - continue; - - return i; - } - - return -1; -} - /* TODO: remove it. */ static int startup(struct v4l2_subdev *sd) { @@ -866,7 +796,7 @@ static int startup(struct v4l2_subdev *sd) return ret; } - ret = ov2722_write_reg_array(client, ov2722_res[dev->fmt_idx].regs); + ret = ov2722_write_reg_array(client, dev->res->regs); if (ret) { dev_err(&client->dev, "ov2722 write register err.\n"); return ret; @@ -882,9 +812,9 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt = &format->format; struct ov2722_device *dev = to_ov2722_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2722_resolution *res; struct camera_mipi_info *ov2722_info = NULL; int ret = 0; - int idx; if (format->pad) return -EINVAL; @@ -895,15 +825,16 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, return -EINVAL; mutex_lock(&dev->input_lock); - idx = nearest_resolution_index(fmt->width, fmt->height); - if (idx == -1) { - /* return the largest resolution */ - fmt->width = ov2722_res[N_RES - 1].width; - fmt->height = ov2722_res[N_RES - 1].height; - } else { - fmt->width = ov2722_res[idx].width; - fmt->height = ov2722_res[idx].height; - } + res = v4l2_find_nearest_size(ov2722_res_preview, + ARRAY_SIZE(ov2722_res_preview), width, + height, fmt->width, fmt->height); + if (!res) + res = &ov2722_res_preview[N_RES - 1]; + + fmt->width = res->width; + fmt->height = res->height; + dev->res = res; + fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; if (format->which == V4L2_SUBDEV_FORMAT_TRY) { sd_state->pads->try_fmt = *fmt; @@ -911,15 +842,9 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, return 0; } - dev->fmt_idx = get_resolution_index(fmt->width, fmt->height); - if (dev->fmt_idx == -1) { - dev_err(&client->dev, "get resolution fail\n"); - mutex_unlock(&dev->input_lock); - return -EINVAL; - } - dev->pixels_per_line = ov2722_res[dev->fmt_idx].pixels_per_line; - dev->lines_per_frame = ov2722_res[dev->fmt_idx].lines_per_frame; + dev->pixels_per_line = dev->res->pixels_per_line; + dev->lines_per_frame = dev->res->lines_per_frame; ret = startup(sd); if (ret) { @@ -950,8 +875,7 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, } } - ret = ov2722_get_intg_factor(client, ov2722_info, - &ov2722_res[dev->fmt_idx]); + ret = ov2722_get_intg_factor(client, ov2722_info, dev->res); if (ret) dev_err(&client->dev, "failed to get integration_factor\n"); @@ -972,8 +896,8 @@ static int ov2722_get_fmt(struct v4l2_subdev *sd, if (!fmt) return -EINVAL; - fmt->width = ov2722_res[dev->fmt_idx].width; - fmt->height = ov2722_res[dev->fmt_idx].height; + fmt->width = dev->res->width; + fmt->height = dev->res->height; fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; return 0; @@ -1098,7 +1022,7 @@ static int ov2722_g_frame_interval(struct v4l2_subdev *sd, struct ov2722_device *dev = to_ov2722_sensor(sd); interval->interval.numerator = 1; - interval->interval.denominator = ov2722_res[dev->fmt_idx].fps; + interval->interval.denominator = dev->res->fps; return 0; } @@ -1136,7 +1060,7 @@ static int ov2722_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) struct ov2722_device *dev = to_ov2722_sensor(sd); mutex_lock(&dev->input_lock); - *frames = ov2722_res[dev->fmt_idx].skip_frames; + *frames = dev->res->skip_frames; mutex_unlock(&dev->input_lock); return 0; @@ -1220,7 +1144,7 @@ static int ov2722_probe(struct i2c_client *client) mutex_init(&dev->input_lock); - dev->fmt_idx = 0; + dev->res = &ov2722_res_preview[0]; v4l2_i2c_subdev_init(&dev->sd, client, &ov2722_ops); ovpdev = gmin_camera_platform_data(&dev->sd, diff --git a/drivers/staging/media/atomisp/i2c/ov2722.h b/drivers/staging/media/atomisp/i2c/ov2722.h index 7b0debb6c53d..d6e2510bc01c 100644 --- a/drivers/staging/media/atomisp/i2c/ov2722.h +++ b/drivers/staging/media/atomisp/i2c/ov2722.h @@ -201,14 +201,13 @@ struct ov2722_device { struct media_pad pad; struct v4l2_mbus_framefmt format; struct mutex input_lock; + struct ov2722_resolution *res; struct camera_sensor_platform_data *platform_data; int vt_pix_clk_freq_mhz; - int fmt_idx; int run_mode; u16 pixels_per_line; u16 lines_per_frame; - u8 res; u8 type; struct v4l2_ctrl_handler ctrl_handler; From e3b14bf8d660c28c8af37320830061ad1c6e9f08 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 13:47:34 +0000 Subject: [PATCH 048/397] media: atomisp-gc0310: use v4l2_find_nearest_size() Instead of reinventing the wheel, use v4l2_find_nearest_size() in order to get the closest resolution. This should address a bug where the wrong resolution was selected. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-gc0310.c | 119 ++++-------------- drivers/staging/media/atomisp/i2c/gc0310.h | 3 +- 2 files changed, 22 insertions(+), 100 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index 687888d643df..cbc8b1d91995 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -266,7 +266,7 @@ static int gc0310_g_bin_factor_x(struct v4l2_subdev *sd, s32 *val) { struct gc0310_device *dev = to_gc0310_sensor(sd); - *val = gc0310_res[dev->fmt_idx].bin_factor_x; + *val = dev->res->bin_factor_x; return 0; } @@ -275,7 +275,7 @@ static int gc0310_g_bin_factor_y(struct v4l2_subdev *sd, s32 *val) { struct gc0310_device *dev = to_gc0310_sensor(sd); - *val = gc0310_res[dev->fmt_idx].bin_factor_y; + *val = dev->res->bin_factor_y; return 0; } @@ -878,76 +878,6 @@ static int gc0310_s_power(struct v4l2_subdev *sd, int on) return gc0310_init(sd); } -/* - * distance - calculate the distance - * @res: resolution - * @w: width - * @h: height - * - * Get the gap between resolution and w/h. - * res->width/height smaller than w/h wouldn't be considered. - * Returns the value of gap or -1 if fail. - */ -#define LARGEST_ALLOWED_RATIO_MISMATCH 800 -static int distance(struct gc0310_resolution *res, u32 w, u32 h) -{ - unsigned int w_ratio = (res->width << 13) / w; - unsigned int h_ratio; - int match; - - if (h == 0) - return -1; - h_ratio = (res->height << 13) / h; - if (h_ratio == 0) - return -1; - match = abs(((w_ratio << 13) / h_ratio) - 8192); - - if ((w_ratio < 8192) || (h_ratio < 8192) || - (match > LARGEST_ALLOWED_RATIO_MISMATCH)) - return -1; - - return w_ratio + h_ratio; -} - -/* Return the nearest higher resolution index */ -static int nearest_resolution_index(int w, int h) -{ - int i; - int idx = -1; - int dist; - int min_dist = INT_MAX; - struct gc0310_resolution *tmp_res = NULL; - - for (i = 0; i < N_RES; i++) { - tmp_res = &gc0310_res[i]; - dist = distance(tmp_res, w, h); - if (dist == -1) - continue; - if (dist < min_dist) { - min_dist = dist; - idx = i; - } - } - - return idx; -} - -static int get_resolution_index(int w, int h) -{ - int i; - - for (i = 0; i < N_RES; i++) { - if (w != gc0310_res[i].width) - continue; - if (h != gc0310_res[i].height) - continue; - - return i; - } - - return -1; -} - /* TODO: remove it. */ static int startup(struct v4l2_subdev *sd) { @@ -955,7 +885,7 @@ static int startup(struct v4l2_subdev *sd) struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; - ret = gc0310_write_reg_array(client, gc0310_res[dev->fmt_idx].regs); + ret = gc0310_write_reg_array(client, dev->res->regs); if (ret) { dev_err(&client->dev, "gc0310 write register err.\n"); return ret; @@ -972,8 +902,8 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd, struct gc0310_device *dev = to_gc0310_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); struct camera_mipi_info *gc0310_info = NULL; + struct gc0310_resolution *res; int ret = 0; - int idx = 0; if (format->pad) return -EINVAL; @@ -987,15 +917,16 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd, mutex_lock(&dev->input_lock); - idx = nearest_resolution_index(fmt->width, fmt->height); - if (idx == -1) { - /* return the largest resolution */ - fmt->width = gc0310_res[N_RES - 1].width; - fmt->height = gc0310_res[N_RES - 1].height; - } else { - fmt->width = gc0310_res[idx].width; - fmt->height = gc0310_res[idx].height; - } + res = v4l2_find_nearest_size(gc0310_res_preview, + ARRAY_SIZE(gc0310_res_preview), width, + height, fmt->width, fmt->height); + if (!res) + res = &gc0310_res_preview[N_RES - 1]; + + fmt->width = res->width; + fmt->height = res->height; + dev->res = res; + fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8; if (format->which == V4L2_SUBDEV_FORMAT_TRY) { @@ -1004,23 +935,15 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd, return 0; } - dev->fmt_idx = get_resolution_index(fmt->width, fmt->height); - if (dev->fmt_idx == -1) { - dev_err(&client->dev, "get resolution fail\n"); - mutex_unlock(&dev->input_lock); - return -EINVAL; - } - dev_dbg(&client->dev, "%s: before gc0310_write_reg_array %s\n", - __func__, gc0310_res[dev->fmt_idx].desc); + __func__, dev->res->desc); ret = startup(sd); if (ret) { dev_err(&client->dev, "gc0310 startup err\n"); goto err; } - ret = gc0310_get_intg_factor(client, gc0310_info, - &gc0310_res[dev->fmt_idx]); + ret = gc0310_get_intg_factor(client, gc0310_info, dev->res); if (ret) { dev_err(&client->dev, "failed to get integration_factor\n"); goto err; @@ -1044,8 +967,8 @@ static int gc0310_get_fmt(struct v4l2_subdev *sd, if (!fmt) return -EINVAL; - fmt->width = gc0310_res[dev->fmt_idx].width; - fmt->height = gc0310_res[dev->fmt_idx].height; + fmt->width = dev->res->width; + fmt->height = dev->res->height; fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8; return 0; @@ -1199,7 +1122,7 @@ static int gc0310_g_frame_interval(struct v4l2_subdev *sd, struct gc0310_device *dev = to_gc0310_sensor(sd); interval->interval.numerator = 1; - interval->interval.denominator = gc0310_res[dev->fmt_idx].fps; + interval->interval.denominator = dev->res->fps; return 0; } @@ -1237,7 +1160,7 @@ static int gc0310_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) struct gc0310_device *dev = to_gc0310_sensor(sd); mutex_lock(&dev->input_lock); - *frames = gc0310_res[dev->fmt_idx].skip_frames; + *frames = dev->res->skip_frames; mutex_unlock(&dev->input_lock); return 0; @@ -1301,7 +1224,7 @@ static int gc0310_probe(struct i2c_client *client) mutex_init(&dev->input_lock); - dev->fmt_idx = 0; + dev->res = &gc0310_res_preview[0]; v4l2_i2c_subdev_init(&dev->sd, client, &gc0310_ops); pdata = gmin_camera_platform_data(&dev->sd, diff --git a/drivers/staging/media/atomisp/i2c/gc0310.h b/drivers/staging/media/atomisp/i2c/gc0310.h index 2fe3de115083..db643ebc3909 100644 --- a/drivers/staging/media/atomisp/i2c/gc0310.h +++ b/drivers/staging/media/atomisp/i2c/gc0310.h @@ -150,8 +150,7 @@ struct gc0310_device { struct camera_sensor_platform_data *platform_data; int vt_pix_clk_freq_mhz; - int fmt_idx; - u8 res; + struct gc0310_resolution *res; u8 type; }; From c286a3a0286bf70590720541b8408dbc3cd930a5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 13:57:35 +0000 Subject: [PATCH 049/397] media: atomisp-gc2235: use v4l2_find_nearest_size() Instead of reinventing the wheel, use v4l2_find_nearest_size() in order to get the closest resolution. This should address a bug where the wrong resolution was selected. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-gc2235.c | 113 +++--------------- drivers/staging/media/atomisp/i2c/gc2235.h | 3 +- 2 files changed, 20 insertions(+), 96 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c index 4d769590f2d3..5e7085264189 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c @@ -670,76 +670,6 @@ static int gc2235_s_power(struct v4l2_subdev *sd, int on) return ret; } -/* - * distance - calculate the distance - * @res: resolution - * @w: width - * @h: height - * - * Get the gap between resolution and w/h. - * res->width/height smaller than w/h wouldn't be considered. - * Returns the value of gap or -1 if fail. - */ -#define LARGEST_ALLOWED_RATIO_MISMATCH 800 -static int distance(struct gc2235_resolution *res, u32 w, u32 h) -{ - unsigned int w_ratio = (res->width << 13) / w; - unsigned int h_ratio; - int match; - - if (h == 0) - return -1; - h_ratio = (res->height << 13) / h; - if (h_ratio == 0) - return -1; - match = abs(((w_ratio << 13) / h_ratio) - 8192); - - if ((w_ratio < 8192) || (h_ratio < 8192) || - (match > LARGEST_ALLOWED_RATIO_MISMATCH)) - return -1; - - return w_ratio + h_ratio; -} - -/* Return the nearest higher resolution index */ -static int nearest_resolution_index(int w, int h) -{ - int i; - int idx = -1; - int dist; - int min_dist = INT_MAX; - struct gc2235_resolution *tmp_res = NULL; - - for (i = 0; i < N_RES; i++) { - tmp_res = &gc2235_res[i]; - dist = distance(tmp_res, w, h); - if (dist == -1) - continue; - if (dist < min_dist) { - min_dist = dist; - idx = i; - } - } - - return idx; -} - -static int get_resolution_index(int w, int h) -{ - int i; - - for (i = 0; i < N_RES; i++) { - if (w != gc2235_res[i].width) - continue; - if (h != gc2235_res[i].height) - continue; - - return i; - } - - return -1; -} - static int startup(struct v4l2_subdev *sd) { struct gc2235_device *dev = to_gc2235_sensor(sd); @@ -758,7 +688,7 @@ static int startup(struct v4l2_subdev *sd) gc2235_write_reg_array(client, gc2235_init_settings); } - ret = gc2235_write_reg_array(client, gc2235_res[dev->fmt_idx].regs); + ret = gc2235_write_reg_array(client, dev->res->regs); if (ret) { dev_err(&client->dev, "gc2235 write register err.\n"); return ret; @@ -776,8 +706,8 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd, struct gc2235_device *dev = to_gc2235_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); struct camera_mipi_info *gc2235_info = NULL; + struct gc2235_resolution *res; int ret = 0; - int idx; gc2235_info = v4l2_get_subdev_hostdata(sd); if (!gc2235_info) @@ -786,16 +716,18 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd, return -EINVAL; if (!fmt) return -EINVAL; + mutex_lock(&dev->input_lock); - idx = nearest_resolution_index(fmt->width, fmt->height); - if (idx == -1) { - /* return the largest resolution */ - fmt->width = gc2235_res[N_RES - 1].width; - fmt->height = gc2235_res[N_RES - 1].height; - } else { - fmt->width = gc2235_res[idx].width; - fmt->height = gc2235_res[idx].height; - } + res = v4l2_find_nearest_size(gc2235_res_preview, + ARRAY_SIZE(gc2235_res_preview), width, + height, fmt->width, fmt->height); + if (!res) + res = &gc2235_res_preview[N_RES - 1]; + + fmt->width = res->width; + fmt->height = res->height; + dev->res = res; + fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; if (format->which == V4L2_SUBDEV_FORMAT_TRY) { sd_state->pads->try_fmt = *fmt; @@ -803,13 +735,6 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd, return 0; } - dev->fmt_idx = get_resolution_index(fmt->width, fmt->height); - if (dev->fmt_idx == -1) { - dev_err(&client->dev, "get resolution fail\n"); - mutex_unlock(&dev->input_lock); - return -EINVAL; - } - ret = startup(sd); if (ret) { dev_err(&client->dev, "gc2235 startup err\n"); @@ -817,7 +742,7 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd, } ret = gc2235_get_intg_factor(client, gc2235_info, - &gc2235_res[dev->fmt_idx]); + dev->res); if (ret) dev_err(&client->dev, "failed to get integration_factor\n"); @@ -839,8 +764,8 @@ static int gc2235_get_fmt(struct v4l2_subdev *sd, if (!fmt) return -EINVAL; - fmt->width = gc2235_res[dev->fmt_idx].width; - fmt->height = gc2235_res[dev->fmt_idx].height; + fmt->width = dev->res->width; + fmt->height = dev->res->height; fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; return 0; @@ -953,7 +878,7 @@ static int gc2235_g_frame_interval(struct v4l2_subdev *sd, struct gc2235_device *dev = to_gc2235_sensor(sd); interval->interval.numerator = 1; - interval->interval.denominator = gc2235_res[dev->fmt_idx].fps; + interval->interval.denominator = dev->res->fps; return 0; } @@ -991,7 +916,7 @@ static int gc2235_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) struct gc2235_device *dev = to_gc2235_sensor(sd); mutex_lock(&dev->input_lock); - *frames = gc2235_res[dev->fmt_idx].skip_frames; + *frames = dev->res->skip_frames; mutex_unlock(&dev->input_lock); return 0; @@ -1055,7 +980,7 @@ static int gc2235_probe(struct i2c_client *client) mutex_init(&dev->input_lock); - dev->fmt_idx = 0; + dev->res = &gc2235_res_preview[0]; v4l2_i2c_subdev_init(&dev->sd, client, &gc2235_ops); gcpdev = gmin_camera_platform_data(&dev->sd, diff --git a/drivers/staging/media/atomisp/i2c/gc2235.h b/drivers/staging/media/atomisp/i2c/gc2235.h index ba5db1230033..806be5dff7a5 100644 --- a/drivers/staging/media/atomisp/i2c/gc2235.h +++ b/drivers/staging/media/atomisp/i2c/gc2235.h @@ -158,11 +158,10 @@ struct gc2235_device { struct v4l2_mbus_framefmt format; struct mutex input_lock; struct v4l2_ctrl_handler ctrl_handler; + struct gc2235_resolution *res; struct camera_sensor_platform_data *platform_data; int vt_pix_clk_freq_mhz; - int fmt_idx; - u8 res; u8 type; }; From 8cc0f5cfd543750b82895616f139d252021761fe Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Nov 2021 14:29:34 +0000 Subject: [PATCH 050/397] media: atomisp-mt9m114: use v4l2_find_nearest_size() Instead of reinventing the wheel, use v4l2_find_nearest_size() in order to get the closest resolution. This should address a bug where the wrong resolution was selected. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-mt9m114.c | 130 ++---------------- 1 file changed, 15 insertions(+), 115 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c index 49f4090856d3..00d6842c07d6 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c @@ -579,107 +579,6 @@ static int mt9m114_s_power(struct v4l2_subdev *sd, int power) return mt9m114_init_common(sd); } -/* - * distance - calculate the distance - * @res: resolution - * @w: width - * @h: height - * - * Get the gap between resolution and w/h. - * res->width/height smaller than w/h wouldn't be considered. - * Returns the value of gap or -1 if fail. - */ -#define LARGEST_ALLOWED_RATIO_MISMATCH 600 -static int distance(struct mt9m114_res_struct const *res, u32 w, u32 h) -{ - unsigned int w_ratio; - unsigned int h_ratio; - int match; - - if (w == 0) - return -1; - w_ratio = (res->width << 13) / w; - if (h == 0) - return -1; - h_ratio = (res->height << 13) / h; - if (h_ratio == 0) - return -1; - match = abs(((w_ratio << 13) / h_ratio) - 8192); - - if ((w_ratio < 8192) || (h_ratio < 8192) || - (match > LARGEST_ALLOWED_RATIO_MISMATCH)) - return -1; - - return w_ratio + h_ratio; -} - -/* Return the nearest higher resolution index */ -static int nearest_resolution_index(int w, int h) -{ - int i; - int idx = -1; - int dist; - int min_dist = INT_MAX; - const struct mt9m114_res_struct *tmp_res = NULL; - - for (i = 0; i < ARRAY_SIZE(mt9m114_res); i++) { - tmp_res = &mt9m114_res[i]; - dist = distance(tmp_res, w, h); - if (dist == -1) - continue; - if (dist < min_dist) { - min_dist = dist; - idx = i; - } - } - - return idx; -} - -static int mt9m114_try_res(u32 *w, u32 *h) -{ - int idx = 0; - - if ((*w > MT9M114_RES_960P_SIZE_H) - || (*h > MT9M114_RES_960P_SIZE_V)) { - *w = MT9M114_RES_960P_SIZE_H; - *h = MT9M114_RES_960P_SIZE_V; - } else { - idx = nearest_resolution_index(*w, *h); - - /* - * nearest_resolution_index() doesn't return smaller - * resolutions. If it fails, it means the requested - * resolution is higher than wecan support. Fallback - * to highest possible resolution in this case. - */ - if (idx == -1) - idx = ARRAY_SIZE(mt9m114_res) - 1; - - *w = mt9m114_res[idx].width; - *h = mt9m114_res[idx].height; - } - - return 0; -} - -static struct mt9m114_res_struct *mt9m114_to_res(u32 w, u32 h) -{ - int index; - - for (index = 0; index < N_RES; index++) { - if ((mt9m114_res[index].width == w) && - (mt9m114_res[index].height == h)) - break; - } - - /* No mode found */ - if (index >= N_RES) - return NULL; - - return &mt9m114_res[index]; -} - static int mt9m114_res2size(struct v4l2_subdev *sd, int *h_size, int *v_size) { struct mt9m114_device *dev = to_mt9m114_sensor(sd); @@ -829,7 +728,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt = &format->format; struct i2c_client *c = v4l2_get_subdevdata(sd); struct mt9m114_device *dev = to_mt9m114_sensor(sd); - struct mt9m114_res_struct *res_index; + struct mt9m114_res_struct *res; u32 width = fmt->width; u32 height = fmt->height; struct camera_mipi_info *mt9m114_info = NULL; @@ -845,20 +744,21 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, if (!mt9m114_info) return -EINVAL; - mt9m114_try_res(&width, &height); + res = v4l2_find_nearest_size(mt9m114_res, + ARRAY_SIZE(mt9m114_res), width, + height, fmt->width, fmt->height); + if (!res) + res = &mt9m114_res[N_RES - 1]; + + fmt->width = res->width; + fmt->height = res->height; + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { sd_state->pads->try_fmt = *fmt; return 0; } - res_index = mt9m114_to_res(width, height); - /* Sanity check */ - if (unlikely(!res_index)) { - WARN_ON(1); - return -EINVAL; - } - - switch (res_index->res) { + switch (res->res) { case MT9M114_RES_736P: ret = mt9m114_write_reg_array(c, mt9m114_736P_init, NO_POLLING); ret += misensor_rmw_reg(c, MISENSOR_16BIT, MISENSOR_READ_MODE, @@ -876,7 +776,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, MISENSOR_R_MODE_MASK, MISENSOR_NORMAL_SET); break; default: - v4l2_err(sd, "set resolution: %d failed!\n", res_index->res); + v4l2_err(sd, "set resolution: %d failed!\n", res->res); return -EINVAL; } @@ -890,7 +790,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, if (mt9m114_set_suspend(sd)) return -EINVAL; - if (dev->res != res_index->res) { + if (dev->res != res->res) { int index; /* Switch to different size */ @@ -922,7 +822,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, } } ret = mt9m114_get_intg_factor(c, mt9m114_info, - &mt9m114_res[res_index->res]); + &mt9m114_res[res->res]); if (ret) { dev_err(&c->dev, "failed to get integration_factor\n"); return -EINVAL; @@ -931,7 +831,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, * mt9m114 - we don't poll for context switch * because it does not happen with streaming disabled. */ - dev->res = res_index->res; + dev->res = res->res; fmt->width = width; fmt->height = height; From 821e6f16125a0e363d3ae7acebad78ee24badd9e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 07:50:15 +0000 Subject: [PATCH 051/397] media: atomisp: allocate a v4l2_fh at open time This avoids an OOPS when VIDIOC_*_PRIORITY calls are used. [ 90.820011] BUG: kernel NULL pointer dereference, address: 0000000000000020 [ 90.820021] #PF: supervisor read access in kernel mode [ 90.820026] #PF: error_code(0x0000) - not-present page [ 90.820030] PGD 1221bc067 P4D 1221bc067 PUD 1221bd067 PMD 0 [ 90.820042] Oops: 0000 [#1] SMP [ 90.820048] CPU: 0 PID: 2007 Comm: qv4l2 Tainted: G C 5.15.0-rc4+ #77 [ 90.820055] Hardware name: ASUSTeK COMPUTER INC. T101HA/T101HA, BIOS T101HA.306 04/23/2019 [ 90.820059] RIP: 0010:v4l2_prio_change+0xf/0x40 [videodev] [ 90.820096] Code: 48 8b 47 20 8b 40 44 25 ff ff 0f 00 48 8b 04 c5 20 58 44 c0 c3 66 0f 1f 44 00 00 0f 1f 44 00 00 8d 42 ff 83 f8 02 77 21 31 c0 <39> 16 74 20 8d 02 f0 ff 04 87 8b 06 89 c1 83 e9 01 83 f9 02 77 04 [ 90.820103] RSP: 0018:ffffb348c142fd70 EFLAGS: 00010246 [ 90.820109] RAX: 0000000000000000 RBX: ffff95575fbe2760 RCX: ffffb348c142fe48 [ 90.820114] RDX: 0000000000000002 RSI: 0000000000000020 RDI: ffff955740996088 [ 90.820118] RBP: 0000000040045644 R08: ffffffffc070da80 R09: 0000000000004000 [ 90.820122] R10: 0000000000000000 R11: 0000000000000000 R12: ffff955766725300 [ 90.820126] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000044 [ 90.820131] FS: 00007f848526b900(0000) GS:ffff9557bbe00000(0000) knlGS:0000000000000000 [ 90.820137] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 90.820141] CR2: 0000000000000020 CR3: 00000001221bf000 CR4: 00000000001006f0 [ 90.820146] Call Trace: [ 90.820155] __video_do_ioctl+0x37d/0x3b0 [videodev] [ 90.820189] video_usercopy+0x188/0x7a0 [videodev] [ 90.820218] ? v4l_print_control+0x20/0x20 [videodev] [ 90.820247] ? swake_up_one+0x39/0x70 [ 90.820258] ? rcu_core+0xff/0x2e0 [ 90.820267] ? sched_clock_cpu+0x9/0xa0 [ 90.820275] ? irqtime_account_irq+0x38/0xb0 [ 90.820282] v4l2_ioctl+0x46/0x50 [videodev] Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_fops.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 72cbdce2142a..4a7e5f2fe436 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -782,6 +782,14 @@ static int atomisp_open(struct file *file) * FIXME: revisit this with a better check once the code structure * is cleaned up a bit more */ + ret = v4l2_fh_open(file); + if (ret) { + dev_err(isp->dev, + "%s: v4l2_fh_open() returned error %d\n", + __func__, ret); + rt_mutex_unlock(&isp->loading); + return ret; + } if (!isp->ready) { rt_mutex_unlock(&isp->loading); return -ENXIO; @@ -1041,7 +1049,7 @@ done: rt_mutex_unlock(&isp->mutex); mutex_unlock(&isp->streamoff_mutex); - return 0; + return v4l2_fh_release(file); } /* From 9df9ee659cae6eb0451a022fa73223b529c24534 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 07:50:15 +0000 Subject: [PATCH 052/397] media: atomisp: drop duplicated ia_css_isp_configs.c Both 2400 and 2401 have this file, but they're identical. So, drop one of them. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/Makefile | 3 +- .../css_2401_system/hive/ia_css_isp_configs.c | 386 ------------------ .../hive => }/ia_css_isp_configs.c | 0 3 files changed, 1 insertion(+), 388 deletions(-) delete mode 100644 drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_configs.c rename drivers/staging/media/atomisp/pci/{css_2400_system/hive => }/ia_css_isp_configs.c (100%) diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile index 606b7754fdfd..320c14f4afa6 100644 --- a/drivers/staging/media/atomisp/Makefile +++ b/drivers/staging/media/atomisp/Makefile @@ -53,6 +53,7 @@ atomisp-objs += \ pci/hmm/hmm.o \ pci/hmm/hmm_reserved_pool.o \ pci/ia_css_device_access.o \ + pci/ia_css_isp_configs.o \ pci/isp/kernels/aa/aa_2/ia_css_aa2.host.o \ pci/isp/kernels/anr/anr_1.0/ia_css_anr.host.o \ pci/isp/kernels/anr/anr_2/ia_css_anr2.host.o \ @@ -157,7 +158,6 @@ atomisp-objs += \ pci/system_local.o \ obj-byt = \ - pci/css_2400_system/hive/ia_css_isp_configs.o \ pci/css_2400_system/hive/ia_css_isp_params.o \ pci/css_2400_system/hive/ia_css_isp_states.o \ @@ -166,7 +166,6 @@ obj-byt = \ # obj-cht = \ - pci/css_2401_system/hive/ia_css_isp_configs.o \ pci/css_2401_system/hive/ia_css_isp_params.o \ pci/css_2401_system/hive/ia_css_isp_states.o \ pci/css_2401_system/host/csi_rx.o \ diff --git a/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_configs.c b/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_configs.c deleted file mode 100644 index 1a021ae841fe..000000000000 --- a/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_configs.c +++ /dev/null @@ -1,386 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* Generated code: do not edit or commmit. */ - -#define IA_CSS_INCLUDE_CONFIGURATIONS -#include "ia_css_pipeline.h" -#include "ia_css_isp_configs.h" -#include "ia_css_debug.h" -#include "assert_support.h" - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_iterator( - const struct ia_css_binary *binary, - const struct ia_css_iterator_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_iterator() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.iterator.size; - offset = binary->info->mem_offsets.offsets.config->dmem.iterator.offset; - } - if (size) { - ia_css_iterator_config((struct sh_css_isp_iterator_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_iterator() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_copy_output( - const struct ia_css_binary *binary, - const struct ia_css_copy_output_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_copy_output() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.copy_output.size; - offset = binary->info->mem_offsets.offsets.config->dmem.copy_output.offset; - } - if (size) { - ia_css_copy_output_config((struct sh_css_isp_copy_output_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_copy_output() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_crop( - const struct ia_css_binary *binary, - const struct ia_css_crop_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_crop() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.crop.size; - offset = binary->info->mem_offsets.offsets.config->dmem.crop.offset; - } - if (size) { - ia_css_crop_config((struct sh_css_isp_crop_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_crop() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_fpn( - const struct ia_css_binary *binary, - const struct ia_css_fpn_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_fpn() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.fpn.size; - offset = binary->info->mem_offsets.offsets.config->dmem.fpn.offset; - } - if (size) { - ia_css_fpn_config((struct sh_css_isp_fpn_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_fpn() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_dvs( - const struct ia_css_binary *binary, - const struct ia_css_dvs_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_dvs() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.dvs.size; - offset = binary->info->mem_offsets.offsets.config->dmem.dvs.offset; - } - if (size) { - ia_css_dvs_config((struct sh_css_isp_dvs_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_dvs() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_qplane( - const struct ia_css_binary *binary, - const struct ia_css_qplane_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_qplane() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.qplane.size; - offset = binary->info->mem_offsets.offsets.config->dmem.qplane.offset; - } - if (size) { - ia_css_qplane_config((struct sh_css_isp_qplane_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_qplane() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_output0( - const struct ia_css_binary *binary, - const struct ia_css_output0_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output0() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.output0.size; - offset = binary->info->mem_offsets.offsets.config->dmem.output0.offset; - } - if (size) { - ia_css_output0_config((struct sh_css_isp_output_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output0() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_output1( - const struct ia_css_binary *binary, - const struct ia_css_output1_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output1() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.output1.size; - offset = binary->info->mem_offsets.offsets.config->dmem.output1.offset; - } - if (size) { - ia_css_output1_config((struct sh_css_isp_output_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output1() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_output( - const struct ia_css_binary *binary, - const struct ia_css_output_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.output.size; - offset = binary->info->mem_offsets.offsets.config->dmem.output.offset; - } - if (size) { - ia_css_output_config((struct sh_css_isp_output_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_raw( - const struct ia_css_binary *binary, - const struct ia_css_raw_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_raw() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.raw.size; - offset = binary->info->mem_offsets.offsets.config->dmem.raw.offset; - } - if (size) { - ia_css_raw_config((struct sh_css_isp_raw_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_raw() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_tnr( - const struct ia_css_binary *binary, - const struct ia_css_tnr_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_tnr() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.tnr.size; - offset = binary->info->mem_offsets.offsets.config->dmem.tnr.offset; - } - if (size) { - ia_css_tnr_config((struct sh_css_isp_tnr_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_tnr() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_ref( - const struct ia_css_binary *binary, - const struct ia_css_ref_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_ref() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.ref.size; - offset = binary->info->mem_offsets.offsets.config->dmem.ref.offset; - } - if (size) { - ia_css_ref_config((struct sh_css_isp_ref_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_ref() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_vf( - const struct ia_css_binary *binary, - const struct ia_css_vf_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_vf() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.vf.size; - offset = binary->info->mem_offsets.offsets.config->dmem.vf.offset; - } - if (size) { - ia_css_vf_config((struct sh_css_isp_vf_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_vf() leave:\n"); -} diff --git a/drivers/staging/media/atomisp/pci/css_2400_system/hive/ia_css_isp_configs.c b/drivers/staging/media/atomisp/pci/ia_css_isp_configs.c similarity index 100% rename from drivers/staging/media/atomisp/pci/css_2400_system/hive/ia_css_isp_configs.c rename to drivers/staging/media/atomisp/pci/ia_css_isp_configs.c From 3a9559d8f679c8c66f58a9138c4695f2420d891c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 11:09:02 +0000 Subject: [PATCH 053/397] media: atomisp: drop duplicated ia_css_isp_states.c Both 2400 and 2401 have this file, but they're identical. So, drop one of them. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/Makefile | 5 +- .../css_2401_system/hive/ia_css_isp_states.c | 224 ------------------ .../hive => }/ia_css_isp_states.c | 0 3 files changed, 2 insertions(+), 227 deletions(-) delete mode 100644 drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_states.c rename drivers/staging/media/atomisp/pci/{css_2400_system/hive => }/ia_css_isp_states.c (100%) diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile index 320c14f4afa6..f7f670a70d3f 100644 --- a/drivers/staging/media/atomisp/Makefile +++ b/drivers/staging/media/atomisp/Makefile @@ -54,6 +54,7 @@ atomisp-objs += \ pci/hmm/hmm_reserved_pool.o \ pci/ia_css_device_access.o \ pci/ia_css_isp_configs.o \ + pci/ia_css_isp_states.o \ pci/isp/kernels/aa/aa_2/ia_css_aa2.host.o \ pci/isp/kernels/anr/anr_1.0/ia_css_anr.host.o \ pci/isp/kernels/anr/anr_2/ia_css_anr2.host.o \ @@ -158,8 +159,7 @@ atomisp-objs += \ pci/system_local.o \ obj-byt = \ - pci/css_2400_system/hive/ia_css_isp_params.o \ - pci/css_2400_system/hive/ia_css_isp_states.o \ + pci/css_2400_system/hive/ia_css_isp_params.o # These will be needed when clean merge CHT support nicely into the driver # Keep them here handy for when we get to that point @@ -167,7 +167,6 @@ obj-byt = \ obj-cht = \ pci/css_2401_system/hive/ia_css_isp_params.o \ - pci/css_2401_system/hive/ia_css_isp_states.o \ pci/css_2401_system/host/csi_rx.o \ pci/css_2401_system/host/ibuf_ctrl.o \ pci/css_2401_system/host/isys_dma.o \ diff --git a/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_states.c b/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_states.c deleted file mode 100644 index 514ffe0303cb..000000000000 --- a/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_states.c +++ /dev/null @@ -1,224 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* Generated code: do not edit or commmit. */ - -#include "ia_css_pipeline.h" -#include "ia_css_isp_states.h" -#include "ia_css_debug.h" -#include "assert_support.h" - -/* Code generated by genparam/genstate.c:gen_init_function() */ - -static void -ia_css_initialize_aa_state( - const struct ia_css_binary *binary) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_aa_state() enter:\n"); - - { - unsigned int size = binary->info->mem_offsets.offsets.state->vmem.aa.size; - unsigned int offset = binary->info->mem_offsets.offsets.state->vmem.aa.offset; - - if (size) - memset(&binary->mem_params.params[IA_CSS_PARAM_CLASS_STATE][IA_CSS_ISP_VMEM].address[offset], - 0, size); - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_aa_state() leave:\n"); -} - -/* Code generated by genparam/genstate.c:gen_init_function() */ - -static void -ia_css_initialize_cnr_state( - const struct ia_css_binary *binary) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_cnr_state() enter:\n"); - - { - unsigned int size = binary->info->mem_offsets.offsets.state->vmem.cnr.size; - - unsigned int offset = binary->info->mem_offsets.offsets.state->vmem.cnr.offset; - - if (size) { - ia_css_init_cnr_state( - &binary->mem_params.params[IA_CSS_PARAM_CLASS_STATE][IA_CSS_ISP_VMEM].address[offset], - size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_cnr_state() leave:\n"); -} - -/* Code generated by genparam/genstate.c:gen_init_function() */ - -static void -ia_css_initialize_cnr2_state( - const struct ia_css_binary *binary) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_cnr2_state() enter:\n"); - - { - unsigned int size = binary->info->mem_offsets.offsets.state->vmem.cnr2.size; - - unsigned int offset = binary->info->mem_offsets.offsets.state->vmem.cnr2.offset; - - if (size) { - ia_css_init_cnr2_state( - &binary->mem_params.params[IA_CSS_PARAM_CLASS_STATE][IA_CSS_ISP_VMEM].address[offset], - size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_cnr2_state() leave:\n"); -} - -/* Code generated by genparam/genstate.c:gen_init_function() */ - -static void -ia_css_initialize_dp_state( - const struct ia_css_binary *binary) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_dp_state() enter:\n"); - - { - unsigned int size = binary->info->mem_offsets.offsets.state->vmem.dp.size; - - unsigned int offset = binary->info->mem_offsets.offsets.state->vmem.dp.offset; - - if (size) { - ia_css_init_dp_state( - &binary->mem_params.params[IA_CSS_PARAM_CLASS_STATE][IA_CSS_ISP_VMEM].address[offset], - size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_dp_state() leave:\n"); -} - -/* Code generated by genparam/genstate.c:gen_init_function() */ - -static void -ia_css_initialize_de_state( - const struct ia_css_binary *binary) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_de_state() enter:\n"); - - { - unsigned int size = binary->info->mem_offsets.offsets.state->vmem.de.size; - - unsigned int offset = binary->info->mem_offsets.offsets.state->vmem.de.offset; - - if (size) { - ia_css_init_de_state( - &binary->mem_params.params[IA_CSS_PARAM_CLASS_STATE][IA_CSS_ISP_VMEM].address[offset], - size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_de_state() leave:\n"); -} - -/* Code generated by genparam/genstate.c:gen_init_function() */ - -static void -ia_css_initialize_tnr_state( - const struct ia_css_binary *binary) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_tnr_state() enter:\n"); - - { - unsigned int size = binary->info->mem_offsets.offsets.state->dmem.tnr.size; - - unsigned int offset = binary->info->mem_offsets.offsets.state->dmem.tnr.offset; - - if (size) { - ia_css_init_tnr_state((struct sh_css_isp_tnr_dmem_state *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_STATE][IA_CSS_ISP_DMEM].address[offset], - size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_tnr_state() leave:\n"); -} - -/* Code generated by genparam/genstate.c:gen_init_function() */ - -static void -ia_css_initialize_ref_state( - const struct ia_css_binary *binary) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_ref_state() enter:\n"); - - { - unsigned int size = binary->info->mem_offsets.offsets.state->dmem.ref.size; - - unsigned int offset = binary->info->mem_offsets.offsets.state->dmem.ref.offset; - - if (size) { - ia_css_init_ref_state((struct sh_css_isp_ref_dmem_state *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_STATE][IA_CSS_ISP_DMEM].address[offset], - size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_ref_state() leave:\n"); -} - -/* Code generated by genparam/genstate.c:gen_init_function() */ - -static void -ia_css_initialize_ynr_state( - const struct ia_css_binary *binary) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_ynr_state() enter:\n"); - - { - unsigned int size = binary->info->mem_offsets.offsets.state->vmem.ynr.size; - - unsigned int offset = binary->info->mem_offsets.offsets.state->vmem.ynr.offset; - - if (size) { - ia_css_init_ynr_state( - &binary->mem_params.params[IA_CSS_PARAM_CLASS_STATE][IA_CSS_ISP_VMEM].address[offset], - size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_initialize_ynr_state() leave:\n"); -} - -/* Code generated by genparam/genstate.c:gen_state_init_table() */ - -void (*ia_css_kernel_init_state[IA_CSS_NUM_STATE_IDS])( - const struct ia_css_binary *binary) = { - ia_css_initialize_aa_state, - ia_css_initialize_cnr_state, - ia_css_initialize_cnr2_state, - ia_css_initialize_dp_state, - ia_css_initialize_de_state, - ia_css_initialize_tnr_state, - ia_css_initialize_ref_state, - ia_css_initialize_ynr_state, -}; diff --git a/drivers/staging/media/atomisp/pci/css_2400_system/hive/ia_css_isp_states.c b/drivers/staging/media/atomisp/pci/ia_css_isp_states.c similarity index 100% rename from drivers/staging/media/atomisp/pci/css_2400_system/hive/ia_css_isp_states.c rename to drivers/staging/media/atomisp/pci/ia_css_isp_states.c From 2aa384962a7f83924c5c049f89ab4eb4d22224d3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 11:17:05 +0000 Subject: [PATCH 054/397] media: atomisp: unify ia_css_isp_params.c The contents of ia_css_isp_params.c is almost identical for 2400 and 2401. The only difference is that, on 2400, there are some duplicated assignments. So, drop it, unifying this file. While here, simplify the Makefile's logic by dropping an unused define. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/Makefile | 12 +- .../css_2400_system/hive/ia_css_isp_params.c | 3420 ----------------- .../hive => }/ia_css_isp_params.c | 0 3 files changed, 3 insertions(+), 3429 deletions(-) delete mode 100644 drivers/staging/media/atomisp/pci/css_2400_system/hive/ia_css_isp_params.c rename drivers/staging/media/atomisp/pci/{css_2401_system/hive => }/ia_css_isp_params.c (100%) diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile index f7f670a70d3f..a23c04cf7f34 100644 --- a/drivers/staging/media/atomisp/Makefile +++ b/drivers/staging/media/atomisp/Makefile @@ -55,6 +55,7 @@ atomisp-objs += \ pci/ia_css_device_access.o \ pci/ia_css_isp_configs.o \ pci/ia_css_isp_states.o \ + pci/ia_css_isp_params.o \ pci/isp/kernels/aa/aa_2/ia_css_aa2.host.o \ pci/isp/kernels/anr/anr_1.0/ia_css_anr.host.o \ pci/isp/kernels/anr/anr_2/ia_css_anr2.host.o \ @@ -156,17 +157,13 @@ atomisp-objs += \ pci/hive_isp_css_common/host/timed_ctrl.o \ pci/hive_isp_css_common/host/vmem.o \ pci/hive_isp_css_shared/host/tag.o \ - pci/system_local.o \ - -obj-byt = \ - pci/css_2400_system/hive/ia_css_isp_params.o + pci/system_local.o # These will be needed when clean merge CHT support nicely into the driver # Keep them here handy for when we get to that point # obj-cht = \ - pci/css_2401_system/hive/ia_css_isp_params.o \ pci/css_2401_system/host/csi_rx.o \ pci/css_2401_system/host/ibuf_ctrl.o \ pci/css_2401_system/host/isys_dma.o \ @@ -322,10 +319,7 @@ ifeq ($(CONFIG_VIDEO_ATOMISP_ISP2401),y) atomisp-objs += \ $(obj-cht) \ pci/runtime/isys/src/ibuf_ctrl_rmgr.o -DEFINES += -DISP2401 -DISP2401_NEW_INPUT_SYSTEM -DSYSTEM_hive_isp_css_2401_system -else -atomisp-objs += $(obj-byt) -DEFINES += -DISP2400 -DSYSTEM_hive_isp_css_2400_system +DEFINES += -DISP2401 -DISP2401_NEW_INPUT_SYSTEM endif ccflags-y += $(INCLUDES) $(DEFINES) -fno-common diff --git a/drivers/staging/media/atomisp/pci/css_2400_system/hive/ia_css_isp_params.c b/drivers/staging/media/atomisp/pci/css_2400_system/hive/ia_css_isp_params.c deleted file mode 100644 index b786247b322b..000000000000 --- a/drivers/staging/media/atomisp/pci/css_2400_system/hive/ia_css_isp_params.c +++ /dev/null @@ -1,3420 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ -#define IA_CSS_INCLUDE_PARAMETERS -#include "sh_css_params.h" -#include "isp/kernels/aa/aa_2/ia_css_aa2.host.h" -#include "isp/kernels/anr/anr_1.0/ia_css_anr.host.h" -#include "isp/kernels/anr/anr_2/ia_css_anr2.host.h" -#include "isp/kernels/bh/bh_2/ia_css_bh.host.h" -#include "isp/kernels/bnr/bnr_1.0/ia_css_bnr.host.h" -#include "isp/kernels/bnr/bnr2_2/ia_css_bnr2_2.host.h" -#include "isp/kernels/cnr/cnr_2/ia_css_cnr2.host.h" -#include "isp/kernels/crop/crop_1.0/ia_css_crop.host.h" -#include "isp/kernels/csc/csc_1.0/ia_css_csc.host.h" -#include "isp/kernels/ctc/ctc_1.0/ia_css_ctc.host.h" -#include "isp/kernels/ctc/ctc1_5/ia_css_ctc1_5.host.h" -#include "isp/kernels/ctc/ctc2/ia_css_ctc2.host.h" -#include "isp/kernels/de/de_1.0/ia_css_de.host.h" -#include "isp/kernels/de/de_2/ia_css_de2.host.h" -#include "isp/kernels/dp/dp_1.0/ia_css_dp.host.h" -#include "isp/kernels/fixedbds/fixedbds_1.0/ia_css_fixedbds_param.h" -#include "isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h" -#include "isp/kernels/gc/gc_1.0/ia_css_gc.host.h" -#include "isp/kernels/gc/gc_2/ia_css_gc2.host.h" -#include "isp/kernels/macc/macc_1.0/ia_css_macc.host.h" -#include "isp/kernels/macc/macc1_5/ia_css_macc1_5.host.h" -#include "isp/kernels/ob/ob_1.0/ia_css_ob.host.h" -#include "isp/kernels/ob/ob2/ia_css_ob2.host.h" -#include "isp/kernels/output/output_1.0/ia_css_output.host.h" -#include "isp/kernels/raw_aa_binning/raw_aa_binning_1.0/ia_css_raa.host.h" -#include "isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.h" -#include "isp/kernels/sc/sc_1.0/ia_css_sc.host.h" -#include "isp/kernels/sdis/sdis_1.0/ia_css_sdis.host.h" -#include "isp/kernels/sdis/sdis_2/ia_css_sdis2.host.h" -#include "isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h" -#include "isp/kernels/uds/uds_1.0/ia_css_uds_param.h" -#include "isp/kernels/wb/wb_1.0/ia_css_wb.host.h" -#include "isp/kernels/xnr/xnr_1.0/ia_css_xnr.host.h" -#include "isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.h" -#include "isp/kernels/ynr/ynr_1.0/ia_css_ynr.host.h" -#include "isp/kernels/ynr/ynr_2/ia_css_ynr2.host.h" -#include "isp/kernels/fc/fc_1.0/ia_css_formats.host.h" -#include "isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.h" -#include "isp/kernels/dpc2/ia_css_dpc2.host.h" -#include "isp/kernels/eed1_8/ia_css_eed1_8.host.h" -#include "isp/kernels/bnlm/ia_css_bnlm.host.h" -#include "isp/kernels/conversion/conversion_1.0/ia_css_conversion.host.h" -/* Generated code: do not edit or commmit. */ - -#include "ia_css_pipeline.h" -#include "ia_css_isp_params.h" -#include "ia_css_debug.h" -#include "assert_support.h" - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_aa( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.aa.size; - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.aa.offset; - - if (size) { - struct sh_css_isp_aa_params *t = (struct sh_css_isp_aa_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset]; - t->strength = params->aa_config.strength; - } - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_anr( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.anr.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.anr.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_anr() enter:\n"); - - ia_css_anr_encode((struct sh_css_isp_anr_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->anr_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_anr() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_anr2( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vmem.anr2.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vmem.anr2.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_anr2() enter:\n"); - - ia_css_anr2_vmem_encode((struct ia_css_isp_anr2_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VMEM].address[offset], - ¶ms->anr_thres, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_anr2() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_bh( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.bh.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.bh.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_bh() enter:\n"); - - ia_css_bh_encode((struct sh_css_isp_bh_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->s3a_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_bh() leave:\n"); - } - } - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->hmem0.bh.size; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_bh() enter:\n"); - - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_HMEM0] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_bh() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_cnr( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.cnr.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.cnr.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_cnr() enter:\n"); - - ia_css_cnr_encode((struct sh_css_isp_cnr_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->cnr_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_cnr() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_crop( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.crop.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.crop.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_crop() enter:\n"); - - ia_css_crop_encode((struct sh_css_isp_crop_isp_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->crop_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_crop() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_csc( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.csc.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.csc.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_csc() enter:\n"); - - ia_css_csc_encode((struct sh_css_isp_csc_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->cc_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_csc() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_dp( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.dp.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.dp.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_dp() enter:\n"); - - ia_css_dp_encode((struct sh_css_isp_dp_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->dp_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_dp() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_bnr( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.bnr.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.bnr.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_bnr() enter:\n"); - - ia_css_bnr_encode((struct sh_css_isp_bnr_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->nr_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_bnr() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_de( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.de.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.de.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_de() enter:\n"); - - ia_css_de_encode((struct sh_css_isp_de_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->de_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_de() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_ecd( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.ecd.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.ecd.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_ecd() enter:\n"); - - ia_css_ecd_encode((struct sh_css_isp_ecd_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->ecd_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_ecd() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_formats( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.formats.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.formats.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_formats() enter:\n"); - - ia_css_formats_encode((struct sh_css_isp_formats_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->formats_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_formats() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_fpn( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.fpn.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.fpn.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_fpn() enter:\n"); - - ia_css_fpn_encode((struct sh_css_isp_fpn_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->fpn_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_fpn() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_gc( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.gc.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.gc.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_gc() enter:\n"); - - ia_css_gc_encode((struct sh_css_isp_gc_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->gc_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_gc() leave:\n"); - } - } - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vamem1.gc.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vamem1.gc.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_gc() enter:\n"); - - ia_css_gc_vamem_encode((struct sh_css_isp_gc_vamem_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VAMEM1].address[offset], - ¶ms->gc_table, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VAMEM1] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_gc() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_ce( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.ce.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.ce.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_ce() enter:\n"); - - ia_css_ce_encode((struct sh_css_isp_ce_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->ce_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_ce() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_yuv2rgb( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.yuv2rgb.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.yuv2rgb.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_yuv2rgb() enter:\n"); - - ia_css_yuv2rgb_encode((struct sh_css_isp_csc_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->yuv2rgb_cc_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_yuv2rgb() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_rgb2yuv( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.rgb2yuv.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.rgb2yuv.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_rgb2yuv() enter:\n"); - - ia_css_rgb2yuv_encode((struct sh_css_isp_csc_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->rgb2yuv_cc_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_rgb2yuv() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_r_gamma( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vamem0.r_gamma.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vamem0.r_gamma.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_r_gamma() enter:\n"); - - ia_css_r_gamma_vamem_encode((struct sh_css_isp_rgb_gamma_vamem_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VAMEM0].address[offset], - ¶ms->r_gamma_table, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VAMEM0] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_r_gamma() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_g_gamma( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vamem1.g_gamma.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vamem1.g_gamma.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_g_gamma() enter:\n"); - - ia_css_g_gamma_vamem_encode((struct sh_css_isp_rgb_gamma_vamem_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VAMEM1].address[offset], - ¶ms->g_gamma_table, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VAMEM1] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_g_gamma() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_b_gamma( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vamem2.b_gamma.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vamem2.b_gamma.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_b_gamma() enter:\n"); - - ia_css_b_gamma_vamem_encode((struct sh_css_isp_rgb_gamma_vamem_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VAMEM2].address[offset], - ¶ms->b_gamma_table, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VAMEM2] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_b_gamma() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_uds( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.uds.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.uds.offset; - - if (size) { - struct sh_css_sp_uds_params *p; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_uds() enter:\n"); - - p = (struct sh_css_sp_uds_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset]; - p->crop_pos = params->uds_config.crop_pos; - p->uds = params->uds_config.uds; - - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_uds() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_raa( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.raa.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.raa.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_raa() enter:\n"); - - ia_css_raa_encode((struct sh_css_isp_aa_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->raa_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_raa() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_s3a( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.s3a.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.s3a.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_s3a() enter:\n"); - - ia_css_s3a_encode((struct sh_css_isp_s3a_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->s3a_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_s3a() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_ob( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.ob.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.ob.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_ob() enter:\n"); - - ia_css_ob_encode((struct sh_css_isp_ob_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->ob_config, - ¶ms->stream_configs.ob, size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_ob() leave:\n"); - } - } - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vmem.ob.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vmem.ob.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_ob() enter:\n"); - - ia_css_ob_vmem_encode((struct sh_css_isp_ob_vmem_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VMEM].address[offset], - ¶ms->ob_config, - ¶ms->stream_configs.ob, size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_ob() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_output( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.output.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.output.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_output() enter:\n"); - - ia_css_output_encode((struct sh_css_isp_output_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->output_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_output() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_sc( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.sc.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.sc.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_sc() enter:\n"); - - ia_css_sc_encode((struct sh_css_isp_sc_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->sc_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_sc() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_bds( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.bds.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.bds.offset; - - if (size) { - struct sh_css_isp_bds_params *p; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_bds() enter:\n"); - - p = (struct sh_css_isp_bds_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset]; - p->baf_strength = params->bds_config.strength; - - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_bds() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_tnr( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.tnr.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.tnr.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_tnr() enter:\n"); - - ia_css_tnr_encode((struct sh_css_isp_tnr_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->tnr_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_tnr() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_macc( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.macc.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.macc.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_macc() enter:\n"); - - ia_css_macc_encode((struct sh_css_isp_macc_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->macc_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_macc() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_sdis_horicoef( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vmem.sdis_horicoef.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vmem.sdis_horicoef.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis_horicoef() enter:\n"); - - ia_css_sdis_horicoef_vmem_encode((struct sh_css_isp_sdis_hori_coef_tbl *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VMEM].address[offset], - ¶ms->dvs_coefs, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis_horicoef() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_sdis_vertcoef( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vmem.sdis_vertcoef.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vmem.sdis_vertcoef.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis_vertcoef() enter:\n"); - - ia_css_sdis_vertcoef_vmem_encode((struct sh_css_isp_sdis_vert_coef_tbl *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VMEM].address[offset], - ¶ms->dvs_coefs, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis_vertcoef() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_sdis_horiproj( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.sdis_horiproj.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.sdis_horiproj.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis_horiproj() enter:\n"); - - ia_css_sdis_horiproj_encode((struct sh_css_isp_sdis_hori_proj_tbl *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->dvs_coefs, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis_horiproj() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_sdis_vertproj( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.sdis_vertproj.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.sdis_vertproj.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis_vertproj() enter:\n"); - - ia_css_sdis_vertproj_encode((struct sh_css_isp_sdis_vert_proj_tbl *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->dvs_coefs, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis_vertproj() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_sdis2_horicoef( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vmem.sdis2_horicoef.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vmem.sdis2_horicoef.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis2_horicoef() enter:\n"); - - ia_css_sdis2_horicoef_vmem_encode((struct sh_css_isp_sdis_hori_coef_tbl *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VMEM].address[offset], - ¶ms->dvs2_coefs, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis2_horicoef() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_sdis2_vertcoef( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vmem.sdis2_vertcoef.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vmem.sdis2_vertcoef.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis2_vertcoef() enter:\n"); - - ia_css_sdis2_vertcoef_vmem_encode((struct sh_css_isp_sdis_vert_coef_tbl *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VMEM].address[offset], - ¶ms->dvs2_coefs, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis2_vertcoef() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_sdis2_horiproj( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.sdis2_horiproj.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.sdis2_horiproj.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis2_horiproj() enter:\n"); - - ia_css_sdis2_horiproj_encode((struct sh_css_isp_sdis_hori_proj_tbl *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->dvs2_coefs, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis2_horiproj() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_sdis2_vertproj( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.sdis2_vertproj.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.sdis2_vertproj.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis2_vertproj() enter:\n"); - - ia_css_sdis2_vertproj_encode((struct sh_css_isp_sdis_vert_proj_tbl *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->dvs2_coefs, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_sdis2_vertproj() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_wb( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.wb.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.wb.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_wb() enter:\n"); - - ia_css_wb_encode((struct sh_css_isp_wb_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->wb_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_wb() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_nr( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.nr.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.nr.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_nr() enter:\n"); - - ia_css_nr_encode((struct sh_css_isp_ynr_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->nr_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_nr() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_yee( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.yee.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.yee.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_yee() enter:\n"); - - ia_css_yee_encode((struct sh_css_isp_yee_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->yee_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_yee() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_ynr( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.ynr.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.ynr.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_ynr() enter:\n"); - - ia_css_ynr_encode((struct sh_css_isp_yee2_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->ynr_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_ynr() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_fc( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.fc.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.fc.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_fc() enter:\n"); - - ia_css_fc_encode((struct sh_css_isp_fc_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->fc_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_process_fc() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_ctc( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.ctc.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.ctc.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_ctc() enter:\n"); - - ia_css_ctc_encode((struct sh_css_isp_ctc_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->ctc_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_ctc() leave:\n"); - } - } - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vamem0.ctc.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vamem0.ctc.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_ctc() enter:\n"); - - ia_css_ctc_vamem_encode((struct sh_css_isp_ctc_vamem_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VAMEM0].address[offset], - ¶ms->ctc_table, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VAMEM0] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_ctc() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_xnr_table( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->vamem1.xnr_table.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->vamem1.xnr_table.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_xnr_table() enter:\n"); - - ia_css_xnr_table_vamem_encode((struct sh_css_isp_xnr_vamem_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_VAMEM1].address[offset], - ¶ms->xnr_table, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_VAMEM1] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_xnr_table() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_xnr( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.xnr.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.xnr.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_xnr() enter:\n"); - - ia_css_xnr_encode((struct sh_css_isp_xnr_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->xnr_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_xnr() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_process_function() */ - -static void -ia_css_process_xnr3( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) -{ - assert(params); - - { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.xnr3.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.xnr3.offset; - - if (size) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_xnr3() enter:\n"); - - ia_css_xnr3_encode((struct sh_css_isp_xnr3_params *) - &stage->binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->xnr3_config, - size); - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_process_xnr3() leave:\n"); - } - } -} - -/* Code generated by genparam/gencode.c:gen_param_process_table() */ - -void (*ia_css_kernel_process_param[IA_CSS_NUM_PARAMETER_IDS])( - unsigned int pipe_id, - const struct ia_css_pipeline_stage *stage, - struct ia_css_isp_parameters *params) = { - ia_css_process_aa, - ia_css_process_anr, - ia_css_process_anr2, - ia_css_process_bh, - ia_css_process_cnr, - ia_css_process_crop, - ia_css_process_csc, - ia_css_process_dp, - ia_css_process_bnr, - ia_css_process_de, - ia_css_process_ecd, - ia_css_process_formats, - ia_css_process_fpn, - ia_css_process_gc, - ia_css_process_ce, - ia_css_process_yuv2rgb, - ia_css_process_rgb2yuv, - ia_css_process_r_gamma, - ia_css_process_g_gamma, - ia_css_process_b_gamma, - ia_css_process_uds, - ia_css_process_raa, - ia_css_process_s3a, - ia_css_process_ob, - ia_css_process_output, - ia_css_process_sc, - ia_css_process_bds, - ia_css_process_tnr, - ia_css_process_macc, - ia_css_process_sdis_horicoef, - ia_css_process_sdis_vertcoef, - ia_css_process_sdis_horiproj, - ia_css_process_sdis_vertproj, - ia_css_process_sdis2_horicoef, - ia_css_process_sdis2_vertcoef, - ia_css_process_sdis2_horiproj, - ia_css_process_sdis2_vertproj, - ia_css_process_wb, - ia_css_process_nr, - ia_css_process_yee, - ia_css_process_ynr, - ia_css_process_fc, - ia_css_process_ctc, - ia_css_process_xnr_table, - ia_css_process_xnr, - ia_css_process_xnr3, -}; - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_dp_config(const struct ia_css_isp_parameters *params, - struct ia_css_dp_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_dp_config() enter: config=%p\n", - config); - - *config = params->dp_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_dp_config() leave\n"); - ia_css_dp_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_dp_config(struct ia_css_isp_parameters *params, - const struct ia_css_dp_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_dp_config() enter:\n"); - ia_css_dp_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->dp_config = *config; - params->config_changed[IA_CSS_DP_ID] = true; - params->config_changed[IA_CSS_DP_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_dp_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_wb_config(const struct ia_css_isp_parameters *params, - struct ia_css_wb_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_wb_config() enter: config=%p\n", - config); - - *config = params->wb_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_wb_config() leave\n"); - ia_css_wb_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_wb_config(struct ia_css_isp_parameters *params, - const struct ia_css_wb_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_wb_config() enter:\n"); - ia_css_wb_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->wb_config = *config; - params->config_changed[IA_CSS_WB_ID] = true; - params->config_changed[IA_CSS_WB_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_wb_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_tnr_config(const struct ia_css_isp_parameters *params, - struct ia_css_tnr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_tnr_config() enter: config=%p\n", - config); - - *config = params->tnr_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_tnr_config() leave\n"); - ia_css_tnr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_tnr_config(struct ia_css_isp_parameters *params, - const struct ia_css_tnr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_tnr_config() enter:\n"); - ia_css_tnr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->tnr_config = *config; - params->config_changed[IA_CSS_TNR_ID] = true; - params->config_changed[IA_CSS_TNR_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_tnr_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_ob_config(const struct ia_css_isp_parameters *params, - struct ia_css_ob_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ob_config() enter: config=%p\n", - config); - - *config = params->ob_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ob_config() leave\n"); - ia_css_ob_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_ob_config(struct ia_css_isp_parameters *params, - const struct ia_css_ob_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_ob_config() enter:\n"); - ia_css_ob_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->ob_config = *config; - params->config_changed[IA_CSS_OB_ID] = true; - params->config_changed[IA_CSS_OB_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_ob_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_de_config(const struct ia_css_isp_parameters *params, - struct ia_css_de_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_de_config() enter: config=%p\n", - config); - - *config = params->de_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_de_config() leave\n"); - ia_css_de_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_de_config(struct ia_css_isp_parameters *params, - const struct ia_css_de_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_de_config() enter:\n"); - ia_css_de_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->de_config = *config; - params->config_changed[IA_CSS_DE_ID] = true; - params->config_changed[IA_CSS_DE_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_de_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_anr_config(const struct ia_css_isp_parameters *params, - struct ia_css_anr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_anr_config() enter: config=%p\n", - config); - - *config = params->anr_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_anr_config() leave\n"); - ia_css_anr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_anr_config(struct ia_css_isp_parameters *params, - const struct ia_css_anr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_anr_config() enter:\n"); - ia_css_anr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->anr_config = *config; - params->config_changed[IA_CSS_ANR_ID] = true; - params->config_changed[IA_CSS_ANR_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_anr_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_anr2_config(const struct ia_css_isp_parameters *params, - struct ia_css_anr_thres *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_anr2_config() enter: config=%p\n", - config); - - *config = params->anr_thres; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_anr2_config() leave\n"); - ia_css_anr2_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_anr2_config(struct ia_css_isp_parameters *params, - const struct ia_css_anr_thres *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_anr2_config() enter:\n"); - ia_css_anr2_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->anr_thres = *config; - params->config_changed[IA_CSS_ANR2_ID] = true; - params->config_changed[IA_CSS_ANR2_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_anr2_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_ce_config(const struct ia_css_isp_parameters *params, - struct ia_css_ce_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ce_config() enter: config=%p\n", - config); - - *config = params->ce_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ce_config() leave\n"); - ia_css_ce_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_ce_config(struct ia_css_isp_parameters *params, - const struct ia_css_ce_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_ce_config() enter:\n"); - ia_css_ce_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->ce_config = *config; - params->config_changed[IA_CSS_CE_ID] = true; - params->config_changed[IA_CSS_CE_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_ce_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_ecd_config(const struct ia_css_isp_parameters *params, - struct ia_css_ecd_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ecd_config() enter: config=%p\n", - config); - - *config = params->ecd_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ecd_config() leave\n"); - ia_css_ecd_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_ecd_config(struct ia_css_isp_parameters *params, - const struct ia_css_ecd_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_ecd_config() enter:\n"); - ia_css_ecd_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->ecd_config = *config; - params->config_changed[IA_CSS_ECD_ID] = true; - params->config_changed[IA_CSS_ECD_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_ecd_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_ynr_config(const struct ia_css_isp_parameters *params, - struct ia_css_ynr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ynr_config() enter: config=%p\n", - config); - - *config = params->ynr_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ynr_config() leave\n"); - ia_css_ynr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_ynr_config(struct ia_css_isp_parameters *params, - const struct ia_css_ynr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_ynr_config() enter:\n"); - ia_css_ynr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->ynr_config = *config; - params->config_changed[IA_CSS_YNR_ID] = true; - params->config_changed[IA_CSS_YNR_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_ynr_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_fc_config(const struct ia_css_isp_parameters *params, - struct ia_css_fc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_fc_config() enter: config=%p\n", - config); - - *config = params->fc_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_fc_config() leave\n"); - ia_css_fc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_fc_config(struct ia_css_isp_parameters *params, - const struct ia_css_fc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_fc_config() enter:\n"); - ia_css_fc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->fc_config = *config; - params->config_changed[IA_CSS_FC_ID] = true; - params->config_changed[IA_CSS_FC_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_fc_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_cnr_config(const struct ia_css_isp_parameters *params, - struct ia_css_cnr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_cnr_config() enter: config=%p\n", - config); - - *config = params->cnr_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_cnr_config() leave\n"); - ia_css_cnr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_cnr_config(struct ia_css_isp_parameters *params, - const struct ia_css_cnr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_cnr_config() enter:\n"); - ia_css_cnr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->cnr_config = *config; - params->config_changed[IA_CSS_CNR_ID] = true; - params->config_changed[IA_CSS_CNR_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_cnr_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_macc_config(const struct ia_css_isp_parameters *params, - struct ia_css_macc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_macc_config() enter: config=%p\n", - config); - - *config = params->macc_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_macc_config() leave\n"); - ia_css_macc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_macc_config(struct ia_css_isp_parameters *params, - const struct ia_css_macc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_macc_config() enter:\n"); - ia_css_macc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->macc_config = *config; - params->config_changed[IA_CSS_MACC_ID] = true; - params->config_changed[IA_CSS_MACC_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_macc_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_ctc_config(const struct ia_css_isp_parameters *params, - struct ia_css_ctc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ctc_config() enter: config=%p\n", - config); - - *config = params->ctc_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_ctc_config() leave\n"); - ia_css_ctc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_ctc_config(struct ia_css_isp_parameters *params, - const struct ia_css_ctc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_ctc_config() enter:\n"); - ia_css_ctc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->ctc_config = *config; - params->config_changed[IA_CSS_CTC_ID] = true; - params->config_changed[IA_CSS_CTC_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_ctc_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_aa_config(const struct ia_css_isp_parameters *params, - struct ia_css_aa_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_aa_config() enter: config=%p\n", - config); - - *config = params->aa_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_aa_config() leave\n"); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_aa_config(struct ia_css_isp_parameters *params, - const struct ia_css_aa_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_aa_config() enter:\n"); - params->aa_config = *config; - params->config_changed[IA_CSS_AA_ID] = true; - params->config_changed[IA_CSS_AA_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_aa_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_yuv2rgb_config(const struct ia_css_isp_parameters *params, - struct ia_css_cc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_yuv2rgb_config() enter: config=%p\n", - config); - - *config = params->yuv2rgb_cc_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_yuv2rgb_config() leave\n"); - ia_css_yuv2rgb_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_yuv2rgb_config(struct ia_css_isp_parameters *params, - const struct ia_css_cc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_yuv2rgb_config() enter:\n"); - ia_css_yuv2rgb_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->yuv2rgb_cc_config = *config; - params->config_changed[IA_CSS_YUV2RGB_ID] = true; - params->config_changed[IA_CSS_YUV2RGB_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_yuv2rgb_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_rgb2yuv_config(const struct ia_css_isp_parameters *params, - struct ia_css_cc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_rgb2yuv_config() enter: config=%p\n", - config); - - *config = params->rgb2yuv_cc_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_rgb2yuv_config() leave\n"); - ia_css_rgb2yuv_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_rgb2yuv_config(struct ia_css_isp_parameters *params, - const struct ia_css_cc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_rgb2yuv_config() enter:\n"); - ia_css_rgb2yuv_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->rgb2yuv_cc_config = *config; - params->config_changed[IA_CSS_RGB2YUV_ID] = true; - params->config_changed[IA_CSS_RGB2YUV_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_rgb2yuv_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_csc_config(const struct ia_css_isp_parameters *params, - struct ia_css_cc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_csc_config() enter: config=%p\n", - config); - - *config = params->cc_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_csc_config() leave\n"); - ia_css_csc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_csc_config(struct ia_css_isp_parameters *params, - const struct ia_css_cc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_csc_config() enter:\n"); - ia_css_csc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->cc_config = *config; - params->config_changed[IA_CSS_CSC_ID] = true; - params->config_changed[IA_CSS_CSC_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_csc_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_nr_config(const struct ia_css_isp_parameters *params, - struct ia_css_nr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_nr_config() enter: config=%p\n", - config); - - *config = params->nr_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_nr_config() leave\n"); - ia_css_nr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_nr_config(struct ia_css_isp_parameters *params, - const struct ia_css_nr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_nr_config() enter:\n"); - ia_css_nr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->nr_config = *config; - params->config_changed[IA_CSS_BNR_ID] = true; - params->config_changed[IA_CSS_NR_ID] = true; - params->config_changed[IA_CSS_NR_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_nr_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_gc_config(const struct ia_css_isp_parameters *params, - struct ia_css_gc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_gc_config() enter: config=%p\n", - config); - - *config = params->gc_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_gc_config() leave\n"); - ia_css_gc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_gc_config(struct ia_css_isp_parameters *params, - const struct ia_css_gc_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_gc_config() enter:\n"); - ia_css_gc_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->gc_config = *config; - params->config_changed[IA_CSS_GC_ID] = true; - params->config_changed[IA_CSS_GC_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_gc_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_sdis_horicoef_config(const struct ia_css_isp_parameters *params, - struct ia_css_dvs_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis_horicoef_config() enter: config=%p\n", - config); - - *config = params->dvs_coefs; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis_horicoef_config() leave\n"); - ia_css_sdis_horicoef_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_sdis_horicoef_config(struct ia_css_isp_parameters *params, - const struct ia_css_dvs_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_set_sdis_horicoef_config() enter:\n"); - ia_css_sdis_horicoef_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->dvs_coefs = *config; - params->config_changed[IA_CSS_SDIS_HORICOEF_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTCOEF_ID] = true; - params->config_changed[IA_CSS_SDIS_HORIPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS_HORICOEF_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_sdis_horicoef_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_sdis_vertcoef_config(const struct ia_css_isp_parameters *params, - struct ia_css_dvs_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis_vertcoef_config() enter: config=%p\n", - config); - - *config = params->dvs_coefs; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis_vertcoef_config() leave\n"); - ia_css_sdis_vertcoef_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_sdis_vertcoef_config(struct ia_css_isp_parameters *params, - const struct ia_css_dvs_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_set_sdis_vertcoef_config() enter:\n"); - ia_css_sdis_vertcoef_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->dvs_coefs = *config; - params->config_changed[IA_CSS_SDIS_HORICOEF_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTCOEF_ID] = true; - params->config_changed[IA_CSS_SDIS_HORIPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTCOEF_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_sdis_vertcoef_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_sdis_horiproj_config(const struct ia_css_isp_parameters *params, - struct ia_css_dvs_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis_horiproj_config() enter: config=%p\n", - config); - - *config = params->dvs_coefs; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis_horiproj_config() leave\n"); - ia_css_sdis_horiproj_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_sdis_horiproj_config(struct ia_css_isp_parameters *params, - const struct ia_css_dvs_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_set_sdis_horiproj_config() enter:\n"); - ia_css_sdis_horiproj_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->dvs_coefs = *config; - params->config_changed[IA_CSS_SDIS_HORICOEF_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTCOEF_ID] = true; - params->config_changed[IA_CSS_SDIS_HORIPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS_HORIPROJ_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_sdis_horiproj_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_sdis_vertproj_config(const struct ia_css_isp_parameters *params, - struct ia_css_dvs_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis_vertproj_config() enter: config=%p\n", - config); - - *config = params->dvs_coefs; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis_vertproj_config() leave\n"); - ia_css_sdis_vertproj_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_sdis_vertproj_config(struct ia_css_isp_parameters *params, - const struct ia_css_dvs_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_set_sdis_vertproj_config() enter:\n"); - ia_css_sdis_vertproj_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->dvs_coefs = *config; - params->config_changed[IA_CSS_SDIS_HORICOEF_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTCOEF_ID] = true; - params->config_changed[IA_CSS_SDIS_HORIPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS_VERTPROJ_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_sdis_vertproj_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_sdis2_horicoef_config(const struct ia_css_isp_parameters *params, - struct ia_css_dvs2_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis2_horicoef_config() enter: config=%p\n", - config); - - *config = params->dvs2_coefs; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis2_horicoef_config() leave\n"); - ia_css_sdis2_horicoef_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_sdis2_horicoef_config(struct ia_css_isp_parameters *params, - const struct ia_css_dvs2_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_set_sdis2_horicoef_config() enter:\n"); - ia_css_sdis2_horicoef_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->dvs2_coefs = *config; - params->config_changed[IA_CSS_SDIS2_HORICOEF_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTCOEF_ID] = true; - params->config_changed[IA_CSS_SDIS2_HORIPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS2_HORICOEF_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_sdis2_horicoef_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_sdis2_vertcoef_config(const struct ia_css_isp_parameters *params, - struct ia_css_dvs2_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis2_vertcoef_config() enter: config=%p\n", - config); - - *config = params->dvs2_coefs; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis2_vertcoef_config() leave\n"); - ia_css_sdis2_vertcoef_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_sdis2_vertcoef_config(struct ia_css_isp_parameters *params, - const struct ia_css_dvs2_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_set_sdis2_vertcoef_config() enter:\n"); - ia_css_sdis2_vertcoef_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->dvs2_coefs = *config; - params->config_changed[IA_CSS_SDIS2_HORICOEF_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTCOEF_ID] = true; - params->config_changed[IA_CSS_SDIS2_HORIPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTCOEF_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_sdis2_vertcoef_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_sdis2_horiproj_config(const struct ia_css_isp_parameters *params, - struct ia_css_dvs2_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis2_horiproj_config() enter: config=%p\n", - config); - - *config = params->dvs2_coefs; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis2_horiproj_config() leave\n"); - ia_css_sdis2_horiproj_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_sdis2_horiproj_config(struct ia_css_isp_parameters *params, - const struct ia_css_dvs2_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_set_sdis2_horiproj_config() enter:\n"); - ia_css_sdis2_horiproj_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->dvs2_coefs = *config; - params->config_changed[IA_CSS_SDIS2_HORICOEF_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTCOEF_ID] = true; - params->config_changed[IA_CSS_SDIS2_HORIPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS2_HORIPROJ_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_sdis2_horiproj_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_sdis2_vertproj_config(const struct ia_css_isp_parameters *params, - struct ia_css_dvs2_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis2_vertproj_config() enter: config=%p\n", - config); - - *config = params->dvs2_coefs; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_sdis2_vertproj_config() leave\n"); - ia_css_sdis2_vertproj_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_sdis2_vertproj_config(struct ia_css_isp_parameters *params, - const struct ia_css_dvs2_coefficients *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_set_sdis2_vertproj_config() enter:\n"); - ia_css_sdis2_vertproj_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->dvs2_coefs = *config; - params->config_changed[IA_CSS_SDIS2_HORICOEF_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTCOEF_ID] = true; - params->config_changed[IA_CSS_SDIS2_HORIPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTPROJ_ID] = true; - params->config_changed[IA_CSS_SDIS2_VERTPROJ_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_sdis2_vertproj_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_r_gamma_config(const struct ia_css_isp_parameters *params, - struct ia_css_rgb_gamma_table *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_r_gamma_config() enter: config=%p\n", - config); - - *config = params->r_gamma_table; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_r_gamma_config() leave\n"); - ia_css_r_gamma_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_r_gamma_config(struct ia_css_isp_parameters *params, - const struct ia_css_rgb_gamma_table *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_r_gamma_config() enter:\n"); - ia_css_r_gamma_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->r_gamma_table = *config; - params->config_changed[IA_CSS_R_GAMMA_ID] = true; - params->config_changed[IA_CSS_R_GAMMA_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_r_gamma_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_g_gamma_config(const struct ia_css_isp_parameters *params, - struct ia_css_rgb_gamma_table *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_g_gamma_config() enter: config=%p\n", - config); - - *config = params->g_gamma_table; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_g_gamma_config() leave\n"); - ia_css_g_gamma_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_g_gamma_config(struct ia_css_isp_parameters *params, - const struct ia_css_rgb_gamma_table *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_g_gamma_config() enter:\n"); - ia_css_g_gamma_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->g_gamma_table = *config; - params->config_changed[IA_CSS_G_GAMMA_ID] = true; - params->config_changed[IA_CSS_G_GAMMA_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_g_gamma_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_b_gamma_config(const struct ia_css_isp_parameters *params, - struct ia_css_rgb_gamma_table *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_b_gamma_config() enter: config=%p\n", - config); - - *config = params->b_gamma_table; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_b_gamma_config() leave\n"); - ia_css_b_gamma_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_b_gamma_config(struct ia_css_isp_parameters *params, - const struct ia_css_rgb_gamma_table *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_b_gamma_config() enter:\n"); - ia_css_b_gamma_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->b_gamma_table = *config; - params->config_changed[IA_CSS_B_GAMMA_ID] = true; - params->config_changed[IA_CSS_B_GAMMA_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_b_gamma_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_xnr_table_config(const struct ia_css_isp_parameters *params, - struct ia_css_xnr_table *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_xnr_table_config() enter: config=%p\n", - config); - - *config = params->xnr_table; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_xnr_table_config() leave\n"); - ia_css_xnr_table_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_xnr_table_config(struct ia_css_isp_parameters *params, - const struct ia_css_xnr_table *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_set_xnr_table_config() enter:\n"); - ia_css_xnr_table_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->xnr_table = *config; - params->config_changed[IA_CSS_XNR_TABLE_ID] = true; - params->config_changed[IA_CSS_XNR_TABLE_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_xnr_table_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_formats_config(const struct ia_css_isp_parameters *params, - struct ia_css_formats_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_formats_config() enter: config=%p\n", - config); - - *config = params->formats_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_formats_config() leave\n"); - ia_css_formats_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_formats_config(struct ia_css_isp_parameters *params, - const struct ia_css_formats_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_formats_config() enter:\n"); - ia_css_formats_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->formats_config = *config; - params->config_changed[IA_CSS_FORMATS_ID] = true; - params->config_changed[IA_CSS_FORMATS_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_formats_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_xnr_config(const struct ia_css_isp_parameters *params, - struct ia_css_xnr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_xnr_config() enter: config=%p\n", - config); - - *config = params->xnr_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_xnr_config() leave\n"); - ia_css_xnr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_xnr_config(struct ia_css_isp_parameters *params, - const struct ia_css_xnr_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_xnr_config() enter:\n"); - ia_css_xnr_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->xnr_config = *config; - params->config_changed[IA_CSS_XNR_ID] = true; - params->config_changed[IA_CSS_XNR_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_xnr_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_xnr3_config(const struct ia_css_isp_parameters *params, - struct ia_css_xnr3_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_xnr3_config() enter: config=%p\n", - config); - - *config = params->xnr3_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_xnr3_config() leave\n"); - ia_css_xnr3_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_xnr3_config(struct ia_css_isp_parameters *params, - const struct ia_css_xnr3_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_xnr3_config() enter:\n"); - ia_css_xnr3_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->xnr3_config = *config; - params->config_changed[IA_CSS_XNR3_ID] = true; - params->config_changed[IA_CSS_XNR3_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_xnr3_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_s3a_config(const struct ia_css_isp_parameters *params, - struct ia_css_3a_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_s3a_config() enter: config=%p\n", - config); - - *config = params->s3a_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_s3a_config() leave\n"); - ia_css_s3a_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_s3a_config(struct ia_css_isp_parameters *params, - const struct ia_css_3a_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_s3a_config() enter:\n"); - ia_css_s3a_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->s3a_config = *config; - params->config_changed[IA_CSS_BH_ID] = true; - params->config_changed[IA_CSS_S3A_ID] = true; - params->config_changed[IA_CSS_S3A_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_s3a_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_get_function() */ - -static void -ia_css_get_output_config(const struct ia_css_isp_parameters *params, - struct ia_css_output_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_output_config() enter: config=%p\n", - config); - - *config = params->output_config; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_get_output_config() leave\n"); - ia_css_output_debug_dtrace(config, IA_CSS_DEBUG_TRACE); -} - -/* Code generated by genparam/gencode.c:gen_set_function() */ - -void -ia_css_set_output_config(struct ia_css_isp_parameters *params, - const struct ia_css_output_config *config) -{ - if (!config) - return; - - assert(params); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_set_output_config() enter:\n"); - ia_css_output_debug_dtrace(config, IA_CSS_DEBUG_TRACE); - params->output_config = *config; - params->config_changed[IA_CSS_OUTPUT_ID] = true; - params->config_changed[IA_CSS_OUTPUT_ID] = true; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_set_output_config() leave: return_void\n"); -} - -/* Code generated by genparam/gencode.c:gen_global_access_function() */ - -void -ia_css_get_configs(struct ia_css_isp_parameters *params, - const struct ia_css_isp_config *config) -{ - ia_css_get_dp_config(params, config->dp_config); - ia_css_get_wb_config(params, config->wb_config); - ia_css_get_tnr_config(params, config->tnr_config); - ia_css_get_ob_config(params, config->ob_config); - ia_css_get_de_config(params, config->de_config); - ia_css_get_anr_config(params, config->anr_config); - ia_css_get_anr2_config(params, config->anr_thres); - ia_css_get_ce_config(params, config->ce_config); - ia_css_get_ecd_config(params, config->ecd_config); - ia_css_get_ynr_config(params, config->ynr_config); - ia_css_get_fc_config(params, config->fc_config); - ia_css_get_cnr_config(params, config->cnr_config); - ia_css_get_macc_config(params, config->macc_config); - ia_css_get_ctc_config(params, config->ctc_config); - ia_css_get_aa_config(params, config->aa_config); - ia_css_get_yuv2rgb_config(params, config->yuv2rgb_cc_config); - ia_css_get_rgb2yuv_config(params, config->rgb2yuv_cc_config); - ia_css_get_csc_config(params, config->cc_config); - ia_css_get_nr_config(params, config->nr_config); - ia_css_get_gc_config(params, config->gc_config); - ia_css_get_sdis_horicoef_config(params, config->dvs_coefs); - ia_css_get_sdis_vertcoef_config(params, config->dvs_coefs); - ia_css_get_sdis_horiproj_config(params, config->dvs_coefs); - ia_css_get_sdis_vertproj_config(params, config->dvs_coefs); - ia_css_get_sdis2_horicoef_config(params, config->dvs2_coefs); - ia_css_get_sdis2_vertcoef_config(params, config->dvs2_coefs); - ia_css_get_sdis2_horiproj_config(params, config->dvs2_coefs); - ia_css_get_sdis2_vertproj_config(params, config->dvs2_coefs); - ia_css_get_r_gamma_config(params, config->r_gamma_table); - ia_css_get_g_gamma_config(params, config->g_gamma_table); - ia_css_get_b_gamma_config(params, config->b_gamma_table); - ia_css_get_xnr_table_config(params, config->xnr_table); - ia_css_get_formats_config(params, config->formats_config); - ia_css_get_xnr_config(params, config->xnr_config); - ia_css_get_xnr3_config(params, config->xnr3_config); - ia_css_get_s3a_config(params, config->s3a_config); - ia_css_get_output_config(params, config->output_config); -} - -/* Code generated by genparam/gencode.c:gen_global_access_function() */ - -void -ia_css_set_configs(struct ia_css_isp_parameters *params, - const struct ia_css_isp_config *config) -{ - ia_css_set_dp_config(params, config->dp_config); - ia_css_set_wb_config(params, config->wb_config); - ia_css_set_tnr_config(params, config->tnr_config); - ia_css_set_ob_config(params, config->ob_config); - ia_css_set_de_config(params, config->de_config); - ia_css_set_anr_config(params, config->anr_config); - ia_css_set_anr2_config(params, config->anr_thres); - ia_css_set_ce_config(params, config->ce_config); - ia_css_set_ecd_config(params, config->ecd_config); - ia_css_set_ynr_config(params, config->ynr_config); - ia_css_set_fc_config(params, config->fc_config); - ia_css_set_cnr_config(params, config->cnr_config); - ia_css_set_macc_config(params, config->macc_config); - ia_css_set_ctc_config(params, config->ctc_config); - ia_css_set_aa_config(params, config->aa_config); - ia_css_set_yuv2rgb_config(params, config->yuv2rgb_cc_config); - ia_css_set_rgb2yuv_config(params, config->rgb2yuv_cc_config); - ia_css_set_csc_config(params, config->cc_config); - ia_css_set_nr_config(params, config->nr_config); - ia_css_set_gc_config(params, config->gc_config); - ia_css_set_sdis_horicoef_config(params, config->dvs_coefs); - ia_css_set_sdis_vertcoef_config(params, config->dvs_coefs); - ia_css_set_sdis_horiproj_config(params, config->dvs_coefs); - ia_css_set_sdis_vertproj_config(params, config->dvs_coefs); - ia_css_set_sdis2_horicoef_config(params, config->dvs2_coefs); - ia_css_set_sdis2_vertcoef_config(params, config->dvs2_coefs); - ia_css_set_sdis2_horiproj_config(params, config->dvs2_coefs); - ia_css_set_sdis2_vertproj_config(params, config->dvs2_coefs); - ia_css_set_r_gamma_config(params, config->r_gamma_table); - ia_css_set_g_gamma_config(params, config->g_gamma_table); - ia_css_set_b_gamma_config(params, config->b_gamma_table); - ia_css_set_xnr_table_config(params, config->xnr_table); - ia_css_set_formats_config(params, config->formats_config); - ia_css_set_xnr_config(params, config->xnr_config); - ia_css_set_xnr3_config(params, config->xnr3_config); - ia_css_set_s3a_config(params, config->s3a_config); - ia_css_set_output_config(params, config->output_config); -} diff --git a/drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_params.c b/drivers/staging/media/atomisp/pci/ia_css_isp_params.c similarity index 100% rename from drivers/staging/media/atomisp/pci/css_2401_system/hive/ia_css_isp_params.c rename to drivers/staging/media/atomisp/pci/ia_css_isp_params.c From 08ae0ffdd6c4ff121d3f9f677ef61f58cf4a6313 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 12:08:37 +0000 Subject: [PATCH 055/397] media: atomisp: cleanup ia_css_isp_configs() code The auto-generated code inside ia_css_isp_configs() is more complex than it should be. Also, it doesn't return any errors. However, the functions called by it can mis-configure the pipelines, but, as there's no way to return errors, it internally calls the assert() macro. So, add a return parameter to each routine there, in order to prepare the code to be more robust. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/ia_css_isp_configs.c | 557 ++++++++---------- .../media/atomisp/pci/ia_css_isp_configs.h | 111 +--- 2 files changed, 273 insertions(+), 395 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/ia_css_isp_configs.c b/drivers/staging/media/atomisp/pci/ia_css_isp_configs.c index 1a021ae841fe..d28a76a68e43 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_isp_configs.c +++ b/drivers/staging/media/atomisp/pci/ia_css_isp_configs.c @@ -21,366 +21,301 @@ #include "ia_css_debug.h" #include "assert_support.h" -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_iterator( - const struct ia_css_binary *binary, - const struct ia_css_iterator_configuration *config_dmem) +int ia_css_configure_iterator(const struct ia_css_binary *binary, + const struct ia_css_iterator_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_iterator() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.iterator.size; - offset = binary->info->mem_offsets.offsets.config->dmem.iterator.offset; - } - if (size) { - ia_css_iterator_config((struct sh_css_isp_iterator_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_iterator() leave:\n"); + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.iterator.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.iterator.offset; + + ia_css_iterator_config((struct sh_css_isp_iterator_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; +} + +int ia_css_configure_copy_output(const struct ia_css_binary *binary, + const struct ia_css_copy_output_configuration *config_dmem) +{ + unsigned int offset = 0; + unsigned int size = 0; + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); + + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.copy_output.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.copy_output.offset; + + ia_css_copy_output_config((struct sh_css_isp_copy_output_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; } /* Code generated by genparam/genconfig.c:gen_configure_function() */ -void -ia_css_configure_copy_output( - const struct ia_css_binary *binary, - const struct ia_css_copy_output_configuration *config_dmem) +int ia_css_configure_crop(const struct ia_css_binary *binary, + const struct ia_css_crop_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_copy_output() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.copy_output.size; - offset = binary->info->mem_offsets.offsets.config->dmem.copy_output.offset; - } - if (size) { - ia_css_copy_output_config((struct sh_css_isp_copy_output_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_copy_output() leave:\n"); + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.crop.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.crop.offset; + + ia_css_crop_config((struct sh_css_isp_crop_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; } -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_crop( - const struct ia_css_binary *binary, - const struct ia_css_crop_configuration *config_dmem) +int ia_css_configure_fpn(const struct ia_css_binary *binary, + const struct ia_css_fpn_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_crop() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.crop.size; - offset = binary->info->mem_offsets.offsets.config->dmem.crop.offset; - } - if (size) { - ia_css_crop_config((struct sh_css_isp_crop_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_crop() leave:\n"); + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.fpn.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.fpn.offset; + ia_css_fpn_config((struct sh_css_isp_fpn_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; } -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_fpn( - const struct ia_css_binary *binary, - const struct ia_css_fpn_configuration *config_dmem) +int ia_css_configure_dvs(const struct ia_css_binary *binary, + const struct ia_css_dvs_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_fpn() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.fpn.size; - offset = binary->info->mem_offsets.offsets.config->dmem.fpn.offset; - } - if (size) { - ia_css_fpn_config((struct sh_css_isp_fpn_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_fpn() leave:\n"); + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.dvs.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.dvs.offset; + ia_css_dvs_config((struct sh_css_isp_dvs_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; } -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_dvs( - const struct ia_css_binary *binary, - const struct ia_css_dvs_configuration *config_dmem) +int ia_css_configure_qplane(const struct ia_css_binary *binary, + const struct ia_css_qplane_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_dvs() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.dvs.size; - offset = binary->info->mem_offsets.offsets.config->dmem.dvs.offset; - } - if (size) { - ia_css_dvs_config((struct sh_css_isp_dvs_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_dvs() leave:\n"); + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.qplane.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.qplane.offset; + ia_css_qplane_config((struct sh_css_isp_qplane_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + + return 0; } -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_qplane( - const struct ia_css_binary *binary, - const struct ia_css_qplane_configuration *config_dmem) +int ia_css_configure_output0(const struct ia_css_binary *binary, + const struct ia_css_output0_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_qplane() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.qplane.size; - offset = binary->info->mem_offsets.offsets.config->dmem.qplane.offset; - } - if (size) { - ia_css_qplane_config((struct sh_css_isp_qplane_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.output0.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.output0.offset; + + ia_css_output0_config((struct sh_css_isp_output_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; +} + +int ia_css_configure_output1(const struct ia_css_binary *binary, + const struct ia_css_output1_configuration *config_dmem) +{ + unsigned int offset = 0; + unsigned int size = 0; + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); + + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.output1.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.output1.offset; + + ia_css_output1_config((struct sh_css_isp_output_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; +} + +int ia_css_configure_output(const struct ia_css_binary *binary, + const struct ia_css_output_configuration *config_dmem) +{ + unsigned int offset = 0; + unsigned int size = 0; + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); + + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.output.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.output.offset; + + ia_css_output_config((struct sh_css_isp_output_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_qplane() leave:\n"); + return 0; } -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_output0( - const struct ia_css_binary *binary, - const struct ia_css_output0_configuration *config_dmem) +int ia_css_configure_raw(const struct ia_css_binary *binary, + const struct ia_css_raw_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output0() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.output0.size; - offset = binary->info->mem_offsets.offsets.config->dmem.output0.offset; - } - if (size) { - ia_css_output0_config((struct sh_css_isp_output_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output0() leave:\n"); + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.raw.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.raw.offset; + + ia_css_raw_config((struct sh_css_isp_raw_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; } -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_output1( - const struct ia_css_binary *binary, - const struct ia_css_output1_configuration *config_dmem) +int ia_css_configure_tnr(const struct ia_css_binary *binary, + const struct ia_css_tnr_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output1() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.output1.size; - offset = binary->info->mem_offsets.offsets.config->dmem.output1.offset; - } - if (size) { - ia_css_output1_config((struct sh_css_isp_output_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output1() leave:\n"); + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.tnr.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.tnr.offset; + + ia_css_tnr_config((struct sh_css_isp_tnr_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; } -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_output( - const struct ia_css_binary *binary, - const struct ia_css_output_configuration *config_dmem) +int ia_css_configure_ref(const struct ia_css_binary *binary, + const struct ia_css_ref_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.output.size; - offset = binary->info->mem_offsets.offsets.config->dmem.output.offset; - } - if (size) { - ia_css_output_config((struct sh_css_isp_output_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_output() leave:\n"); + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.ref.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.ref.offset; + + ia_css_ref_config((struct sh_css_isp_ref_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; } -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_raw( - const struct ia_css_binary *binary, - const struct ia_css_raw_configuration *config_dmem) +int ia_css_configure_vf(const struct ia_css_binary *binary, + const struct ia_css_vf_configuration *config_dmem) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_raw() enter:\n"); + unsigned int offset = 0; + unsigned int size = 0; - { - unsigned int offset = 0; - unsigned int size = 0; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s:\n", __func__); - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.raw.size; - offset = binary->info->mem_offsets.offsets.config->dmem.raw.offset; - } - if (size) { - ia_css_raw_config((struct sh_css_isp_raw_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_raw() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_tnr( - const struct ia_css_binary *binary, - const struct ia_css_tnr_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_tnr() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.tnr.size; - offset = binary->info->mem_offsets.offsets.config->dmem.tnr.offset; - } - if (size) { - ia_css_tnr_config((struct sh_css_isp_tnr_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_tnr() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_ref( - const struct ia_css_binary *binary, - const struct ia_css_ref_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_ref() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.ref.size; - offset = binary->info->mem_offsets.offsets.config->dmem.ref.offset; - } - if (size) { - ia_css_ref_config((struct sh_css_isp_ref_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_ref() leave:\n"); -} - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_vf( - const struct ia_css_binary *binary, - const struct ia_css_vf_configuration *config_dmem) -{ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_vf() enter:\n"); - - { - unsigned int offset = 0; - unsigned int size = 0; - - if (binary->info->mem_offsets.offsets.config) { - size = binary->info->mem_offsets.offsets.config->dmem.vf.size; - offset = binary->info->mem_offsets.offsets.config->dmem.vf.offset; - } - if (size) { - ia_css_vf_config((struct sh_css_isp_vf_isp_config *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], - config_dmem, size); - } - } - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "ia_css_configure_vf() leave:\n"); + if (!binary->info->mem_offsets.offsets.config) + return 0; + + size = binary->info->mem_offsets.offsets.config->dmem.vf.size; + if (!size) + return 0; + + offset = binary->info->mem_offsets.offsets.config->dmem.vf.offset; + + ia_css_vf_config((struct sh_css_isp_vf_isp_config *) + &binary->mem_params.params[IA_CSS_PARAM_CLASS_CONFIG][IA_CSS_ISP_DMEM].address[offset], + config_dmem, size); + return 0; } diff --git a/drivers/staging/media/atomisp/pci/ia_css_isp_configs.h b/drivers/staging/media/atomisp/pci/ia_css_isp_configs.h index 0364b932e79b..fffcfc871bd2 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_isp_configs.h +++ b/drivers/staging/media/atomisp/pci/ia_css_isp_configs.h @@ -27,14 +27,11 @@ #include "isp/kernels/vf/vf_1.0/ia_css_vf.host.h" #include "isp/kernels/iterator/iterator_1.0/ia_css_iterator.host.h" #include "isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.h" -#endif /* IA_CSS_INCLUDE_CONFIGURATIONS */ -/* Generated code: do not edit or commmit. */ +#endif #ifndef _IA_CSS_ISP_CONFIG_H #define _IA_CSS_ISP_CONFIG_H -/* Code generated by genparam/gencode.c:gen_param_enum() */ - enum ia_css_configuration_ids { IA_CSS_ITERATOR_CONFIG_ID, IA_CSS_COPY_OUTPUT_CONFIG_ID, @@ -56,8 +53,6 @@ enum ia_css_configuration_ids { IA_CSS_NUM_CONFIGURATION_IDS }; -/* Code generated by genparam/gencode.c:gen_param_offsets() */ - struct ia_css_config_memory_offsets { struct { struct ia_css_isp_parameter iterator; @@ -80,96 +75,44 @@ struct ia_css_config_memory_offsets { #include "ia_css_stream.h" /* struct ia_css_stream */ #include "ia_css_binary.h" /* struct ia_css_binary */ -/* Code generated by genparam/genconfig.c:gen_configure_function() */ -void -ia_css_configure_iterator( - const struct ia_css_binary *binary, - const struct ia_css_iterator_configuration *config_dmem); +int ia_css_configure_iterator(const struct ia_css_binary *binary, + const struct ia_css_iterator_configuration *config_dmem); -/* Code generated by genparam/genconfig.c:gen_configure_function() */ +int ia_css_configure_copy_output(const struct ia_css_binary *binary, + const struct ia_css_copy_output_configuration *config_dmem); -void -ia_css_configure_copy_output( - const struct ia_css_binary *binary, - const struct ia_css_copy_output_configuration *config_dmem); +int ia_css_configure_crop(const struct ia_css_binary *binary, + const struct ia_css_crop_configuration *config_dmem); -/* Code generated by genparam/genconfig.c:gen_configure_function() */ +int ia_css_configure_fpn(const struct ia_css_binary *binary, + const struct ia_css_fpn_configuration *config_dmem); -void -ia_css_configure_crop( - const struct ia_css_binary *binary, - const struct ia_css_crop_configuration *config_dmem); +int ia_css_configure_dvs(const struct ia_css_binary *binary, + const struct ia_css_dvs_configuration *config_dmem); -/* Code generated by genparam/genconfig.c:gen_configure_function() */ +int ia_css_configure_qplane(const struct ia_css_binary *binary, + const struct ia_css_qplane_configuration *config_dmem); +int ia_css_configure_output0(const struct ia_css_binary *binary, + const struct ia_css_output0_configuration *config_dmem); -void -ia_css_configure_fpn( - const struct ia_css_binary *binary, - const struct ia_css_fpn_configuration *config_dmem); +int ia_css_configure_output1(const struct ia_css_binary *binary, + const struct ia_css_output1_configuration *config_dmem); -/* Code generated by genparam/genconfig.c:gen_configure_function() */ +int ia_css_configure_output(const struct ia_css_binary *binary, + const struct ia_css_output_configuration *config_dmem); -void -ia_css_configure_dvs( - const struct ia_css_binary *binary, - const struct ia_css_dvs_configuration *config_dmem); +int ia_css_configure_raw(const struct ia_css_binary *binary, + const struct ia_css_raw_configuration *config_dmem); -/* Code generated by genparam/genconfig.c:gen_configure_function() */ +int ia_css_configure_tnr(const struct ia_css_binary *binary, + const struct ia_css_tnr_configuration *config_dmem); -void -ia_css_configure_qplane( - const struct ia_css_binary *binary, - const struct ia_css_qplane_configuration *config_dmem); +int ia_css_configure_ref(const struct ia_css_binary *binary, + const struct ia_css_ref_configuration *config_dmem); -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_output0( - const struct ia_css_binary *binary, - const struct ia_css_output0_configuration *config_dmem); - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_output1( - const struct ia_css_binary *binary, - const struct ia_css_output1_configuration *config_dmem); - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_output( - const struct ia_css_binary *binary, - const struct ia_css_output_configuration *config_dmem); - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_raw( - const struct ia_css_binary *binary, - const struct ia_css_raw_configuration *config_dmem); - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_tnr( - const struct ia_css_binary *binary, - const struct ia_css_tnr_configuration *config_dmem); - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_ref( - const struct ia_css_binary *binary, - const struct ia_css_ref_configuration *config_dmem); - -/* Code generated by genparam/genconfig.c:gen_configure_function() */ - -void -ia_css_configure_vf( - const struct ia_css_binary *binary, - const struct ia_css_vf_configuration *config_dmem); +int ia_css_configure_vf(const struct ia_css_binary *binary, + const struct ia_css_vf_configuration *config_dmem); #endif /* IA_CSS_INCLUDE_CONFIGURATION */ From f21e49be240ffc064a0ada822f3f1b316728eaa8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 12:18:02 +0000 Subject: [PATCH 056/397] media: atomisp: propagate errors at ia_css_*_configure() Propagate the lower lever ia_css config errors to the next level. Signed-off-by: Mauro Carvalho Chehab --- .../copy_output_1.0/ia_css_copy_output.host.c | 8 +++--- .../copy_output_1.0/ia_css_copy_output.host.h | 6 ++--- .../kernels/crop/crop_1.0/ia_css_crop.host.c | 8 +++--- .../kernels/crop/crop_1.0/ia_css_crop.host.h | 6 ++--- .../isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.c | 8 +++--- .../isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.h | 6 ++--- .../isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c | 8 +++--- .../isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h | 6 ++--- .../iterator_1.0/ia_css_iterator.host.c | 11 +++----- .../output/output_1.0/ia_css_output.host.c | 27 +++++++++---------- .../output/output_1.0/ia_css_output.host.h | 18 +++++-------- .../qplane/qplane_2/ia_css_qplane.host.c | 10 +++---- .../qplane/qplane_2/ia_css_qplane.host.h | 8 +++--- .../isp/kernels/raw/raw_1.0/ia_css_raw.host.c | 16 +++++------ .../isp/kernels/raw/raw_1.0/ia_css_raw.host.h | 14 +++++----- .../isp/kernels/ref/ref_1.0/ia_css_ref.host.c | 12 ++++----- .../isp/kernels/ref/ref_1.0/ia_css_ref.host.h | 8 +++--- .../isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c | 8 +++--- .../isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h | 6 ++--- .../isp/kernels/vf/vf_1.0/ia_css_vf.host.c | 14 +++++----- 20 files changed, 82 insertions(+), 126 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.c index 5d34f3256a43..cc415c72ad8f 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.c @@ -34,14 +34,12 @@ ia_css_copy_output_config( to->enable = from->enable; } -void -ia_css_copy_output_configure( - const struct ia_css_binary *binary, - bool enable) +int ia_css_copy_output_configure(const struct ia_css_binary *binary, + bool enable) { struct ia_css_copy_output_configuration config = default_config; config.enable = enable; - ia_css_configure_copy_output(binary, &config); + return ia_css_configure_copy_output(binary, &config); } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.h index 615cb6771884..44e3e45b0ec3 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/copy_output/copy_output_1.0/ia_css_copy_output.host.h @@ -27,9 +27,7 @@ ia_css_copy_output_config( const struct ia_css_copy_output_configuration *from, unsigned int size); -void -ia_css_copy_output_configure( - const struct ia_css_binary *binary, - bool enable); +int ia_css_copy_output_configure(const struct ia_css_binary *binary, + bool enable); #endif /* __IA_CSS_COPY_OUTPUT_HOST_H */ diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c index 38912062edd4..8ab0604b364a 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c @@ -52,14 +52,12 @@ ia_css_crop_config( assert(elems_a % to->port_b.elems == 0); } -void -ia_css_crop_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *info) +int ia_css_crop_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *info) { struct ia_css_crop_configuration config = default_config; config.info = info; - ia_css_configure_crop(binary, &config); + return ia_css_configure_crop(binary, &config); } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.h index 21a259d33256..877601bfa7c0 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.h @@ -34,9 +34,7 @@ ia_css_crop_config( const struct ia_css_crop_configuration *from, unsigned int size); -void -ia_css_crop_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *from); +int ia_css_crop_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *from); #endif /* __IA_CSS_CROP_HOST_H */ diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.c index 67f5540b48b5..07ce5b4f0816 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.c @@ -46,16 +46,14 @@ ia_css_dvs_config( DVS_NUM_BLOCKS_Y(from->info->res.height); } -void -ia_css_dvs_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *info) +int ia_css_dvs_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *info) { struct ia_css_dvs_configuration config = default_config; config.info = info; - ia_css_configure_dvs(binary, &config); + return ia_css_configure_dvs(binary, &config); } static void diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.h index f9bc17ee0f86..332aa5496c04 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.h @@ -35,10 +35,8 @@ ia_css_dvs_config( const struct ia_css_dvs_configuration *from, unsigned int size); -void -ia_css_dvs_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *from); +int ia_css_dvs_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *from); void convert_dvs_6axis_config( diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c index 47b5c7956fbd..9933113adf46 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c @@ -67,10 +67,8 @@ ia_css_fpn_config( assert(elems_a % to->port_b.elems == 0); } -void -ia_css_fpn_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *info) +int ia_css_fpn_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *info) { struct ia_css_frame_info my_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; const struct ia_css_fpn_configuration config = { @@ -85,5 +83,5 @@ ia_css_fpn_configure( my_info.raw_bayer_order = info->raw_bayer_order; my_info.crop_info = info->crop_info; - ia_css_configure_fpn(binary, &config); + return ia_css_configure_fpn(binary, &config); } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h index 12187d213d90..1c644c0decfe 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h @@ -37,9 +37,7 @@ ia_css_fpn_config( const struct ia_css_fpn_configuration *from, unsigned int size); -void -ia_css_fpn_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *from); +int ia_css_fpn_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *from); #endif /* __IA_CSS_FPN_HOST_H */ diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/iterator/iterator_1.0/ia_css_iterator.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/iterator/iterator_1.0/ia_css_iterator.host.c index 6d8a35a73750..5f186fb03642 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/iterator/iterator_1.0/ia_css_iterator.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/iterator/iterator_1.0/ia_css_iterator.host.c @@ -38,10 +38,9 @@ ia_css_iterator_config( ia_css_resolution_to_sp_resolution(&to->dvs_envelope, from->dvs_envelope); } -int -ia_css_iterator_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *in_info) { +int ia_css_iterator_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *in_info) +{ struct ia_css_frame_info my_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; struct ia_css_iterator_configuration config = default_config; @@ -75,7 +74,5 @@ ia_css_iterator_configure( my_info.res.height <<= binary->vf_downscale_log2; } - ia_css_configure_iterator(binary, &config); - - return 0; + return ia_css_configure_iterator(binary, &config); } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c index c8e074f42353..cf6311ebbeab 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c @@ -91,10 +91,8 @@ ia_css_output1_config( to, (const struct ia_css_output_configuration *)from, size); } -void -ia_css_output_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *info) +int ia_css_output_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *info) { if (info) { struct ia_css_output_configuration config = @@ -102,14 +100,13 @@ ia_css_output_configure( config.info = info; - ia_css_configure_output(binary, &config); + return ia_css_configure_output(binary, &config); } + return 0; } -void -ia_css_output0_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *info) +int ia_css_output0_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *info) { if (info) { struct ia_css_output0_configuration config = @@ -117,14 +114,13 @@ ia_css_output0_configure( config.info = info; - ia_css_configure_output0(binary, &config); + return ia_css_configure_output0(binary, &config); } + return 0; } -void -ia_css_output1_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *info) +int ia_css_output1_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *info) { if (info) { struct ia_css_output1_configuration config = @@ -132,8 +128,9 @@ ia_css_output1_configure( config.info = info; - ia_css_configure_output1(binary, &config); + return ia_css_configure_output1(binary, &config); } + return 0; } void diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.h index 1f5a2242640e..04c0023794cc 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.h @@ -48,20 +48,14 @@ ia_css_output1_config( const struct ia_css_output1_configuration *from, unsigned int size); -void -ia_css_output_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *from); +int ia_css_output_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *from); -void -ia_css_output0_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *from); +int ia_css_output0_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *from); -void -ia_css_output1_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *from); +int ia_css_output1_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *from); void ia_css_output_dump( diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c index 1603fd44ece3..7858dc573980 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c @@ -47,16 +47,14 @@ ia_css_qplane_config( to->format = from->info->format; } -void -ia_css_qplane_configure( - const struct sh_css_sp_pipeline *pipe, - const struct ia_css_binary *binary, - const struct ia_css_frame_info *info) +int ia_css_qplane_configure(const struct sh_css_sp_pipeline *pipe, + const struct ia_css_binary *binary, + const struct ia_css_frame_info *info) { struct ia_css_qplane_configuration config = default_config; config.pipe = pipe; config.info = info; - ia_css_configure_qplane(binary, &config); + return ia_css_configure_qplane(binary, &config); } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.h index 8d940959f40a..c4b863dc1498 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.h @@ -35,10 +35,8 @@ ia_css_qplane_config( const struct ia_css_qplane_configuration *from, unsigned int size); -void -ia_css_qplane_configure( - const struct sh_css_sp_pipeline *pipe, - const struct ia_css_binary *binary, - const struct ia_css_frame_info *from); +int ia_css_qplane_configure(const struct sh_css_sp_pipeline *pipe, + const struct ia_css_binary *binary, + const struct ia_css_frame_info *from); #endif /* __IA_CSS_QPLANE_HOST_H */ diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c index f741beb9ed8a..b35d81ad1a38 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c @@ -106,14 +106,12 @@ ia_css_raw_config( #endif } -void -ia_css_raw_configure( - const struct sh_css_sp_pipeline *pipe, - const struct ia_css_binary *binary, - const struct ia_css_frame_info *in_info, - const struct ia_css_frame_info *internal_info, - bool two_ppc, - bool deinterleaved) +int ia_css_raw_configure(const struct sh_css_sp_pipeline *pipe, + const struct ia_css_binary *binary, + const struct ia_css_frame_info *in_info, + const struct ia_css_frame_info *internal_info, + bool two_ppc, + bool deinterleaved) { u8 enable_left_padding = (uint8_t)((binary->left_padding) ? 1 : 0); struct ia_css_raw_configuration config = default_config; @@ -126,5 +124,5 @@ ia_css_raw_configure( config.deinterleaved = deinterleaved; config.enable_left_padding = enable_left_padding; - ia_css_configure_raw(binary, &config); + return ia_css_configure_raw(binary, &config); } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.h index 346928435a8b..33374ac9db99 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.h @@ -27,13 +27,11 @@ ia_css_raw_config( const struct ia_css_raw_configuration *from, unsigned int size); -void -ia_css_raw_configure( - const struct sh_css_sp_pipeline *pipe, - const struct ia_css_binary *binary, - const struct ia_css_frame_info *in_info, - const struct ia_css_frame_info *internal_info, - bool two_ppc, - bool deinterleaved); +int ia_css_raw_configure(const struct sh_css_sp_pipeline *pipe, + const struct ia_css_binary *binary, + const struct ia_css_frame_info *in_info, + const struct ia_css_frame_info *internal_info, + bool two_ppc, + bool deinterleaved); #endif /* __IA_CSS_RAW_HOST_H */ diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c index 061558fbe329..f5b0e333d554 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c @@ -55,19 +55,19 @@ ia_css_ref_config( assert(elems_a % to->port_b.elems == 0); } -void -ia_css_ref_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame * const *ref_frames, - const uint32_t dvs_frame_delay) +int ia_css_ref_configure(const struct ia_css_binary *binary, + const struct ia_css_frame * const *ref_frames, + const uint32_t dvs_frame_delay) { struct ia_css_ref_configuration config; unsigned int i; for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++) config.ref_frames[i] = ref_frames[i]; + config.dvs_frame_delay = dvs_frame_delay; - ia_css_configure_ref(binary, &config); + + return ia_css_configure_ref(binary, &config); } void diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.h index 3ce590b436a1..c407d471c7a0 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.h @@ -29,11 +29,9 @@ ia_css_ref_config( const struct ia_css_ref_configuration *from, unsigned int size); -void -ia_css_ref_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame * const *ref_frames, - const uint32_t dvs_frame_delay); +int ia_css_ref_configure(const struct ia_css_binary *binary, + const struct ia_css_frame * const *ref_frames, + const uint32_t dvs_frame_delay); void ia_css_init_ref_state( diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c index ac80e6c6e67e..170bd70b6e24 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c @@ -93,10 +93,8 @@ ia_css_tnr_config( assert(elems_a % to->port_b.elems == 0); } -void -ia_css_tnr_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame * const *frames) +int ia_css_tnr_configure(const struct ia_css_binary *binary, + const struct ia_css_frame * const *frames) { struct ia_css_tnr_configuration config; unsigned int i; @@ -104,7 +102,7 @@ ia_css_tnr_configure( for (i = 0; i < NUM_TNR_FRAMES; i++) config.tnr_frames[i] = frames[i]; - ia_css_configure_tnr(binary, &config); + return ia_css_configure_tnr(binary, &config); } void diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h index 90d6e6b44a8d..1c421c6a8512 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h @@ -45,10 +45,8 @@ ia_css_tnr_config( const struct ia_css_tnr_configuration *from, unsigned int size); -void -ia_css_tnr_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame * const *frames); +int ia_css_tnr_configure(const struct ia_css_binary *binary, + const struct ia_css_frame * const *frames); void ia_css_init_tnr_state( diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c index dd3670972936..a0926d05f1e1 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c @@ -120,12 +120,11 @@ configure_dma( config->info = vf_info; } -int -ia_css_vf_configure( - const struct ia_css_binary *binary, - const struct ia_css_frame_info *out_info, - struct ia_css_frame_info *vf_info, - unsigned int *downscale_log2) { +int ia_css_vf_configure(const struct ia_css_binary *binary, + const struct ia_css_frame_info *out_info, + struct ia_css_frame_info *vf_info, + unsigned int *downscale_log2) +{ int err; struct ia_css_vf_configuration config; const struct ia_css_binary_info *info = &binary->info->sp; @@ -138,7 +137,6 @@ ia_css_vf_configure( if (vf_info) vf_info->raw_bit_depth = info->dma.vfdec_bits_per_pixel; - ia_css_configure_vf(binary, &config); - return 0; + return ia_css_configure_vf(binary, &config); } From f88520495b85ac0a0edb3410d5edb337e1699046 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 13:44:34 +0000 Subject: [PATCH 057/397] media: atomisp: sh_css_sp: better handle pipeline config errors If something gets wrong while setup a pipeline, return an error code. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css_sp.c | 66 +++++++++++++------ 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index fa74ac172f94..f36f44b5e5b2 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -812,25 +812,47 @@ is_sp_stage(struct ia_css_pipeline_stage *stage) return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC; } -static int -configure_isp_from_args( - const struct sh_css_sp_pipeline *pipeline, - const struct ia_css_binary *binary, - const struct sh_css_binary_args *args, - bool two_ppc, - bool deinterleaved) +static int configure_isp_from_args(const struct sh_css_sp_pipeline *pipeline, + const struct ia_css_binary *binary, + const struct sh_css_binary_args *args, + bool two_ppc, + bool deinterleaved) { - ia_css_fpn_configure(binary, &binary->in_frame_info); - ia_css_crop_configure(binary, &args->delay_frames[0]->info); - ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info); - ia_css_output0_configure(binary, &args->out_frame[0]->info); - ia_css_output1_configure(binary, &args->out_vf_frame->info); - ia_css_copy_output_configure(binary, args->copy_output); - ia_css_output0_configure(binary, &args->out_frame[0]->info); - ia_css_iterator_configure(binary, &args->in_frame->info); - ia_css_dvs_configure(binary, &args->out_frame[0]->info); - ia_css_output_configure(binary, &args->out_frame[0]->info); - ia_css_raw_configure(pipeline, binary, &args->in_frame->info, &binary->in_frame_info, two_ppc, deinterleaved); + int ret; + + ret = ia_css_fpn_configure(binary, &binary->in_frame_info); + if (ret) + return ret; + ret = ia_css_crop_configure(binary, &args->delay_frames[0]->info); + if (ret) + return ret; + ret = ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info); + if (ret) + return ret; + ret = ia_css_output0_configure(binary, &args->out_frame[0]->info); + if (ret) + return ret; + ret = ia_css_output1_configure(binary, &args->out_vf_frame->info); + if (ret) + return ret; + ret = ia_css_copy_output_configure(binary, args->copy_output); + if (ret) + return ret; + ret = ia_css_output0_configure(binary, &args->out_frame[0]->info); + if (ret) + return ret; + ret = ia_css_iterator_configure(binary, &args->in_frame->info); + if (ret) + return ret; + ret = ia_css_dvs_configure(binary, &args->out_frame[0]->info); + if (ret) + return ret; + ret = ia_css_output_configure(binary, &args->out_frame[0]->info); + if (ret) + return ret; + ret = ia_css_raw_configure(pipeline, binary, &args->in_frame->info, &binary->in_frame_info, two_ppc, deinterleaved); + if (ret) + return ret; /* * FIXME: args->delay_frames can be NULL here @@ -842,8 +864,12 @@ configure_isp_from_args( * without crashing, but the pipeline should likely be built without * adding it at the first place (or there are a hidden bug somewhere) */ - ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay); - ia_css_tnr_configure(binary, args->tnr_frames); + ret = ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay); + if (ret) + return ret; + ret = ia_css_tnr_configure(binary, args->tnr_frames); + if (ret) + return ret; ia_css_bayer_io_config(binary, args); return 0; } From 874da1fd1df2428154f160a1b99cdbf2cab32058 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 16:29:14 +0000 Subject: [PATCH 058/397] media: atomisp: add return codes for pipeline config functions Those functions can internally break, but, as they don't return errors, internally there are some assert() calls, which is bad, as it hangs the driver. So, add return codes there, in preparation for removing such assert() calls. Signed-off-by: Mauro Carvalho Chehab --- .../kernels/crop/crop_1.0/ia_css_crop.host.c | 9 +++--- .../kernels/crop/crop_1.0/ia_css_crop.host.h | 8 ++--- .../isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c | 9 +++--- .../isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h | 8 ++--- .../bayer_io_ls/ia_css_bayer_io.host.c | 7 ++--- .../bayer_io_ls/ia_css_bayer_io.host.h | 6 ++-- .../yuv444_io_ls/ia_css_yuv444_io.host.c | 7 ++--- .../yuv444_io_ls/ia_css_yuv444_io.host.h | 6 ++-- .../output/output_1.0/ia_css_output.host.c | 31 +++++++------------ .../output/output_1.0/ia_css_output.host.h | 24 ++++++-------- .../qplane/qplane_2/ia_css_qplane.host.c | 9 +++--- .../qplane/qplane_2/ia_css_qplane.host.h | 8 ++--- .../isp/kernels/raw/raw_1.0/ia_css_raw.host.c | 10 +++--- .../isp/kernels/raw/raw_1.0/ia_css_raw.host.h | 8 ++--- .../isp/kernels/ref/ref_1.0/ia_css_ref.host.c | 9 +++--- .../isp/kernels/ref/ref_1.0/ia_css_ref.host.h | 8 ++--- .../isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c | 9 +++--- .../isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h | 8 ++--- .../isp/kernels/vf/vf_1.0/ia_css_vf.host.c | 9 +++--- .../isp/kernels/vf/vf_1.0/ia_css_vf.host.h | 8 ++--- .../runtime/frame/interface/ia_css_frame.h | 5 ++- .../atomisp/pci/runtime/frame/src/frame.c | 7 ++--- drivers/staging/media/atomisp/pci/sh_css_sp.c | 3 +- 23 files changed, 87 insertions(+), 129 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c index 8ab0604b364a..69b1c493e020 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c @@ -36,11 +36,9 @@ ia_css_crop_encode( to->crop_pos = from->crop_pos; } -void -ia_css_crop_config( - struct sh_css_isp_crop_isp_config *to, - const struct ia_css_crop_configuration *from, - unsigned int size) +int ia_css_crop_config(struct sh_css_isp_crop_isp_config *to, + const struct ia_css_crop_configuration *from, + unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; @@ -50,6 +48,7 @@ ia_css_crop_config( /* Assume divisiblity here, may need to generalize to fixed point. */ assert(elems_a % to->port_b.elems == 0); + return 0; } int ia_css_crop_configure(const struct ia_css_binary *binary, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.h index 877601bfa7c0..e700149c1e95 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.h @@ -28,11 +28,9 @@ ia_css_crop_encode( const struct ia_css_crop_config *from, unsigned int size); -void -ia_css_crop_config( - struct sh_css_isp_crop_isp_config *to, - const struct ia_css_crop_configuration *from, - unsigned int size); +int ia_css_crop_config(struct sh_css_isp_crop_isp_config *to, + const struct ia_css_crop_configuration *from, + unsigned int size); int ia_css_crop_configure(const struct ia_css_binary *binary, const struct ia_css_frame_info *from); diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c index 9933113adf46..be68192c2437 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c @@ -51,11 +51,9 @@ ia_css_fpn_dump( "fpn_enabled", fpn->enabled); } -void -ia_css_fpn_config( - struct sh_css_isp_fpn_isp_config *to, - const struct ia_css_fpn_configuration *from, - unsigned int size) +int ia_css_fpn_config(struct sh_css_isp_fpn_isp_config *to, + const struct ia_css_fpn_configuration *from, + unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; @@ -65,6 +63,7 @@ ia_css_fpn_config( /* Assume divisiblity here, may need to generalize to fixed point. */ assert(elems_a % to->port_b.elems == 0); + return 0; } int ia_css_fpn_configure(const struct ia_css_binary *binary, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h index 1c644c0decfe..bd341fa287fe 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.h @@ -31,11 +31,9 @@ ia_css_fpn_dump( const struct sh_css_isp_fpn_params *fpn, unsigned int level); -void -ia_css_fpn_config( - struct sh_css_isp_fpn_isp_config *to, - const struct ia_css_fpn_configuration *from, - unsigned int size); +int ia_css_fpn_config(struct sh_css_isp_fpn_isp_config *to, + const struct ia_css_fpn_configuration *from, + unsigned int size); int ia_css_fpn_configure(const struct ia_css_binary *binary, const struct ia_css_frame_info *from); diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c index ea8055148fb3..5e2755b45586 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c @@ -22,10 +22,8 @@ #include "ia_css_isp_params.h" #include "ia_css_frame.h" -void -ia_css_bayer_io_config( - const struct ia_css_binary *binary, - const struct sh_css_binary_args *args) +int ia_css_bayer_io_config(const struct ia_css_binary *binary, + const struct sh_css_binary_args *args) { const struct ia_css_frame *in_frame = args->in_frame; const struct ia_css_frame **out_frames = (const struct ia_css_frame **) @@ -91,4 +89,5 @@ ia_css_bayer_io_config( "ia_css_bayer_io_config() put part leave:\n"); #endif } + return 0; } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h index 635ccb1b27d0..9c7e5a1ad57b 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h @@ -21,9 +21,7 @@ #include "ia_css_binary.h" #include "sh_css_internal.h" -void -ia_css_bayer_io_config( - const struct ia_css_binary *binary, - const struct sh_css_binary_args *args); +int ia_css_bayer_io_config(const struct ia_css_binary *binary, + const struct sh_css_binary_args *args); #endif /*__BAYER_IO_HOST_H */ diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c index f8bd207b28e1..46fa1f708571 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c @@ -22,10 +22,8 @@ more details. #include "ia_css_isp_params.h" #include "ia_css_frame.h" -void -ia_css_yuv444_io_config( - const struct ia_css_binary *binary, - const struct sh_css_binary_args *args) +int ia_css_yuv444_io_config(const struct ia_css_binary *binary, + const struct sh_css_binary_args *args) { const struct ia_css_frame *in_frame = args->in_frame; const struct ia_css_frame **out_frames = (const struct ia_css_frame **) @@ -91,4 +89,5 @@ ia_css_yuv444_io_config( "ia_css_yuv444_io_config() put part leave:\n"); #endif } + return 0; } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.h index e7cfd380e108..13e50590f91e 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.h @@ -21,9 +21,7 @@ more details. #include "ia_css_binary.h" #include "sh_css_internal.h" -void -ia_css_yuv444_io_config( - const struct ia_css_binary *binary, - const struct sh_css_binary_args *args); +int ia_css_yuv444_io_config(const struct ia_css_binary *binary, + const struct sh_css_binary_args *args); #endif /*__YUV44_IO_HOST_H */ diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c index cf6311ebbeab..137e5b286ecf 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c @@ -52,11 +52,9 @@ ia_css_output_encode( to->enable_vflip = from->enable_vflip; } -void -ia_css_output_config( - struct sh_css_isp_output_isp_config *to, - const struct ia_css_output_configuration *from, - unsigned int size) +int ia_css_output_config(struct sh_css_isp_output_isp_config *to, + const struct ia_css_output_configuration *from, + unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; @@ -69,26 +67,21 @@ ia_css_output_config( /* Assume divisiblity here, may need to generalize to fixed point. */ assert(elems_a % to->port_b.elems == 0); + return 0; } -void -ia_css_output0_config( - struct sh_css_isp_output_isp_config *to, - const struct ia_css_output0_configuration *from, - unsigned int size) +int ia_css_output0_config(struct sh_css_isp_output_isp_config *to, + const struct ia_css_output0_configuration *from, + unsigned int size) { - ia_css_output_config( - to, (const struct ia_css_output_configuration *)from, size); + return ia_css_output_config(to, (const struct ia_css_output_configuration *)from, size); } -void -ia_css_output1_config( - struct sh_css_isp_output_isp_config *to, - const struct ia_css_output1_configuration *from, - unsigned int size) +int ia_css_output1_config(struct sh_css_isp_output_isp_config *to, + const struct ia_css_output1_configuration *from, + unsigned int size) { - ia_css_output_config( - to, (const struct ia_css_output_configuration *)from, size); + return ia_css_output_config(to, (const struct ia_css_output_configuration *)from, size); } int ia_css_output_configure(const struct ia_css_binary *binary, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.h index 04c0023794cc..c8523e95a394 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.h @@ -30,23 +30,17 @@ ia_css_output_encode( const struct ia_css_output_config *from, unsigned int size); -void -ia_css_output_config( - struct sh_css_isp_output_isp_config *to, - const struct ia_css_output_configuration *from, - unsigned int size); +int ia_css_output_config(struct sh_css_isp_output_isp_config *to, + const struct ia_css_output_configuration *from, + unsigned int size); -void -ia_css_output0_config( - struct sh_css_isp_output_isp_config *to, - const struct ia_css_output0_configuration *from, - unsigned int size); +int ia_css_output0_config(struct sh_css_isp_output_isp_config *to, + const struct ia_css_output0_configuration *from, + unsigned int size); -void -ia_css_output1_config( - struct sh_css_isp_output_isp_config *to, - const struct ia_css_output1_configuration *from, - unsigned int size); +int ia_css_output1_config(struct sh_css_isp_output_isp_config *to, + const struct ia_css_output1_configuration *from, + unsigned int size); int ia_css_output_configure(const struct ia_css_binary *binary, const struct ia_css_frame_info *from); diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c index 7858dc573980..38ad6e52a848 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c @@ -28,11 +28,9 @@ static const struct ia_css_qplane_configuration default_config = { .pipe = (struct sh_css_sp_pipeline *)NULL, }; -void -ia_css_qplane_config( - struct sh_css_isp_qplane_isp_config *to, - const struct ia_css_qplane_configuration *from, - unsigned int size) +int ia_css_qplane_config(struct sh_css_isp_qplane_isp_config *to, + const struct ia_css_qplane_configuration *from, + unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; @@ -45,6 +43,7 @@ ia_css_qplane_config( to->inout_port_config = from->pipe->inout_port_config; to->format = from->info->format; + return 0; } int ia_css_qplane_configure(const struct sh_css_sp_pipeline *pipe, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.h index c4b863dc1498..b3f8fa30c8ce 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.h @@ -29,11 +29,9 @@ #include "ia_css_qplane_types.h" #include "ia_css_qplane_param.h" -void -ia_css_qplane_config( - struct sh_css_isp_qplane_isp_config *to, - const struct ia_css_qplane_configuration *from, - unsigned int size); +int ia_css_qplane_config(struct sh_css_isp_qplane_isp_config *to, + const struct ia_css_qplane_configuration *from, + unsigned int size); int ia_css_qplane_configure(const struct sh_css_sp_pipeline *pipe, const struct ia_css_binary *binary, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c index b35d81ad1a38..aba0409a4a0d 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c @@ -64,11 +64,9 @@ css2isp_stream_format(enum atomisp_input_format from) { } } -void -ia_css_raw_config( - struct sh_css_isp_raw_isp_config *to, - const struct ia_css_raw_configuration *from, - unsigned int size) +int ia_css_raw_config(struct sh_css_isp_raw_isp_config *to, + const struct ia_css_raw_configuration *from, + unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; const struct ia_css_frame_info *in_info = from->in_info; @@ -104,6 +102,8 @@ ia_css_raw_config( to->start_line = in_info->crop_info.start_line; to->enable_left_padding = from->enable_left_padding; #endif + + return 0; } int ia_css_raw_configure(const struct sh_css_sp_pipeline *pipe, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.h index 33374ac9db99..23da51aabc8d 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.h @@ -21,11 +21,9 @@ #include "ia_css_raw_types.h" #include "ia_css_raw_param.h" -void -ia_css_raw_config( - struct sh_css_isp_raw_isp_config *to, - const struct ia_css_raw_configuration *from, - unsigned int size); +int ia_css_raw_config(struct sh_css_isp_raw_isp_config *to, + const struct ia_css_raw_configuration *from, + unsigned int size); int ia_css_raw_configure(const struct sh_css_sp_pipeline *pipe, const struct ia_css_binary *binary, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c index f5b0e333d554..663dbb7c39eb 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c @@ -22,11 +22,9 @@ #include "isp.h" #include "ia_css_ref.host.h" -void -ia_css_ref_config( - struct sh_css_isp_ref_isp_config *to, - const struct ia_css_ref_configuration *from, - unsigned int size) +int ia_css_ref_config(struct sh_css_isp_ref_isp_config *to, + const struct ia_css_ref_configuration *from, + unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS, i; @@ -53,6 +51,7 @@ ia_css_ref_config( /* Assume divisiblity here, may need to generalize to fixed point. */ assert(elems_a % to->port_b.elems == 0); + return 0; } int ia_css_ref_configure(const struct ia_css_binary *binary, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.h index c407d471c7a0..388cd4c367ba 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.h @@ -23,11 +23,9 @@ #include "ia_css_ref_param.h" #include "ia_css_ref_state.h" -void -ia_css_ref_config( - struct sh_css_isp_ref_isp_config *to, - const struct ia_css_ref_configuration *from, - unsigned int size); +int ia_css_ref_config(struct sh_css_isp_ref_isp_config *to, + const struct ia_css_ref_configuration *from, + unsigned int size); int ia_css_ref_configure(const struct ia_css_binary *binary, const struct ia_css_frame * const *ref_frames, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c index 170bd70b6e24..3a5bea219c48 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c @@ -71,11 +71,9 @@ ia_css_tnr_debug_dtrace( config->threshold_y, config->threshold_uv); } -void -ia_css_tnr_config( - struct sh_css_isp_tnr_isp_config *to, - const struct ia_css_tnr_configuration *from, - unsigned int size) +int ia_css_tnr_config(struct sh_css_isp_tnr_isp_config *to, + const struct ia_css_tnr_configuration *from, + unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; unsigned int i; @@ -91,6 +89,7 @@ ia_css_tnr_config( /* Assume divisiblity here, may need to generalize to fixed point. */ assert(elems_a % to->port_b.elems == 0); + return 0; } int ia_css_tnr_configure(const struct ia_css_binary *binary, diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h index 1c421c6a8512..acf92052b442 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.h @@ -39,11 +39,9 @@ ia_css_tnr_debug_dtrace( const struct ia_css_tnr_config *config, unsigned int level); -void -ia_css_tnr_config( - struct sh_css_isp_tnr_isp_config *to, - const struct ia_css_tnr_configuration *from, - unsigned int size); +int ia_css_tnr_config(struct sh_css_isp_tnr_isp_config *to, + const struct ia_css_tnr_configuration *from, + unsigned int size); int ia_css_tnr_configure(const struct ia_css_binary *binary, const struct ia_css_frame * const *frames); diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c index a0926d05f1e1..1ace34f59f8d 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c @@ -26,11 +26,9 @@ #include "isp.h" -void -ia_css_vf_config( - struct sh_css_isp_vf_isp_config *to, - const struct ia_css_vf_configuration *from, - unsigned int size) +int ia_css_vf_config(struct sh_css_isp_vf_isp_config *to, + const struct ia_css_vf_configuration *from, + unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; @@ -46,6 +44,7 @@ ia_css_vf_config( /* Assume divisiblity here, may need to generalize to fixed point. */ assert(elems_a % to->dma.port_b.elems == 0); } + return 0; } /* compute the log2 of the downscale factor needed to get closest diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.h index 0e8de034a00e..d6b45d3754b0 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.h @@ -32,11 +32,9 @@ sh_css_vf_downscale_log2( const struct ia_css_frame_info *vf_info, unsigned int *downscale_log2); -void -ia_css_vf_config( - struct sh_css_isp_vf_isp_config *to, - const struct ia_css_vf_configuration *from, - unsigned int size); +int ia_css_vf_config(struct sh_css_isp_vf_isp_config *to, + const struct ia_css_vf_configuration *from, + unsigned int size); int ia_css_vf_configure( diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h index 31f01e0f58aa..51ec7073d860 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h +++ b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h @@ -138,9 +138,8 @@ bool ia_css_frame_is_same_type( * @param[in] info The frame info * @return */ -void ia_css_dma_configure_from_info( - struct dma_port_config *config, - const struct ia_css_frame_info *info); +int ia_css_dma_configure_from_info(struct dma_port_config *config, + const struct ia_css_frame_info *info); /* ISP2401 */ /* @brief Finds the cropping resolution diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c index 10c4907187d9..647383e10f5e 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c +++ b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c @@ -594,10 +594,8 @@ bool ia_css_frame_is_same_type(const struct ia_css_frame *frame_a, return is_equal; } -void -ia_css_dma_configure_from_info( - struct dma_port_config *config, - const struct ia_css_frame_info *info) +int ia_css_dma_configure_from_info(struct dma_port_config *config, + const struct ia_css_frame_info *info) { unsigned int is_raw_packed = info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED; unsigned int bits_per_pixel = is_raw_packed ? info->raw_bit_depth : @@ -611,6 +609,7 @@ ia_css_dma_configure_from_info( config->width = (uint16_t)info->res.width; config->crop = 0; assert(config->width <= info->padded_width); + return 0; } /************************************************************************** diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index f36f44b5e5b2..77ac720017a2 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -870,8 +870,7 @@ static int configure_isp_from_args(const struct sh_css_sp_pipeline *pipeline, ret = ia_css_tnr_configure(binary, args->tnr_frames); if (ret) return ret; - ia_css_bayer_io_config(binary, args); - return 0; + return ia_css_bayer_io_config(binary, args); } static void From 62596705730e62671c61b93c42c3bb64375d941a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 16:30:48 +0000 Subject: [PATCH 059/397] media: atomisp: return errors from ia_css_dma_configure_from_info() Now that the pipeline config functions can return errors, change ia_css_dma_configure_from_info() and callers in order for them to return errors at pipelines instead of using assert(). Signed-off-by: Mauro Carvalho Chehab --- .../pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c | 11 ++++++++--- .../pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c | 11 ++++++++--- .../ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c | 9 +++++++-- .../ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c | 11 +++++++++-- .../kernels/output/output_1.0/ia_css_output.host.c | 11 ++++++++--- .../isp/kernels/qplane/qplane_2/ia_css_qplane.host.c | 11 ++++++++--- .../pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c | 6 ++++-- .../pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c | 9 +++++++-- .../pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c | 10 +++++++--- .../pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c | 9 ++++++--- .../media/atomisp/pci/runtime/frame/src/frame.c | 7 ++++++- 11 files changed, 78 insertions(+), 27 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c index 69b1c493e020..8c1d50f7aae4 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/crop/crop_1.0/ia_css_crop.host.c @@ -41,13 +41,18 @@ int ia_css_crop_config(struct sh_css_isp_crop_isp_config *to, unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; + int ret; + + ret = ia_css_dma_configure_from_info(&to->port_b, from->info); + if (ret) + return ret; - (void)size; - ia_css_dma_configure_from_info(&to->port_b, from->info); to->width_a_over_b = elems_a / to->port_b.elems; /* Assume divisiblity here, may need to generalize to fixed point. */ - assert(elems_a % to->port_b.elems == 0); + if (elems_a % to->port_b.elems != 0) + return -EINVAL; + return 0; } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c index be68192c2437..57b5e11e1cfe 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/fpn/fpn_1.0/ia_css_fpn.host.c @@ -56,13 +56,18 @@ int ia_css_fpn_config(struct sh_css_isp_fpn_isp_config *to, unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; + int ret; + + ret = ia_css_dma_configure_from_info(&to->port_b, from->info); + if (ret) + return ret; - (void)size; - ia_css_dma_configure_from_info(&to->port_b, from->info); to->width_a_over_b = elems_a / to->port_b.elems; /* Assume divisiblity here, may need to generalize to fixed point. */ - assert(elems_a % to->port_b.elems == 0); + if (elems_a % to->port_b.elems != 0) + return -EINVAL; + return 0; } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c index 5e2755b45586..c7d88552dfde 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c @@ -36,6 +36,7 @@ int ia_css_bayer_io_config(const struct ia_css_binary *binary, ddr_bits_per_element); unsigned int size_get = 0, size_put = 0; unsigned int offset = 0; + int ret; if (binary->info->mem_offsets.offsets.param) { size_get = binary->info->mem_offsets.offsets.param->dmem.get.size; @@ -51,7 +52,9 @@ int ia_css_bayer_io_config(const struct ia_css_binary *binary, "ia_css_bayer_io_config() get part enter:\n"); #endif - ia_css_dma_configure_from_info(&config, in_frame_info); + ret = ia_css_dma_configure_from_info(&config, in_frame_info); + if (ret) + return ret; // The base_address of the input frame will be set in the ISP to->width = in_frame_info->res.width; to->height = in_frame_info->res.height; @@ -77,7 +80,9 @@ int ia_css_bayer_io_config(const struct ia_css_binary *binary, "ia_css_bayer_io_config() put part enter:\n"); #endif - ia_css_dma_configure_from_info(&config, &out_frames[0]->info); + ret = ia_css_dma_configure_from_info(&config, &out_frames[0]->info); + if (ret) + return ret; to->base_address = out_frames[0]->data; to->width = out_frames[0]->info.res.width; to->height = out_frames[0]->info.res.height; diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c index 46fa1f708571..7d2ef6e26ee6 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c @@ -36,6 +36,7 @@ int ia_css_yuv444_io_config(const struct ia_css_binary *binary, ddr_bits_per_element); unsigned int size_get = 0, size_put = 0; unsigned int offset = 0; + int ret; if (binary->info->mem_offsets.offsets.param) { size_get = binary->info->mem_offsets.offsets.param->dmem.get.size; @@ -51,7 +52,10 @@ int ia_css_yuv444_io_config(const struct ia_css_binary *binary, "ia_css_yuv444_io_config() get part enter:\n"); #endif - ia_css_dma_configure_from_info(&config, in_frame_info); + ret = ia_css_dma_configure_from_info(&config, in_frame_info); + if (ret) + return ret; + // The base_address of the input frame will be set in the ISP to->width = in_frame_info->res.width; to->height = in_frame_info->res.height; @@ -77,7 +81,10 @@ int ia_css_yuv444_io_config(const struct ia_css_binary *binary, "ia_css_yuv444_io_config() put part enter:\n"); #endif - ia_css_dma_configure_from_info(&config, &out_frames[0]->info); + ret = ia_css_dma_configure_from_info(&config, &out_frames[0]->info); + if (ret) + return ret; + to->base_address = out_frames[0]->data; to->width = out_frames[0]->info.res.width; to->height = out_frames[0]->info.res.height; diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c index 137e5b286ecf..be9e4ef29fce 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/output/output_1.0/ia_css_output.host.c @@ -57,16 +57,21 @@ int ia_css_output_config(struct sh_css_isp_output_isp_config *to, unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; + int ret; + + ret = ia_css_dma_configure_from_info(&to->port_b, from->info); + if (ret) + return ret; - (void)size; - ia_css_dma_configure_from_info(&to->port_b, from->info); to->width_a_over_b = elems_a / to->port_b.elems; to->height = from->info ? from->info->res.height : 0; to->enable = from->info != NULL; ia_css_frame_info_to_frame_sp_info(&to->info, from->info); /* Assume divisiblity here, may need to generalize to fixed point. */ - assert(elems_a % to->port_b.elems == 0); + if (elems_a % to->port_b.elems != 0) + return -EINVAL; + return 0; } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c index 38ad6e52a848..9fd4435e96b0 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/qplane/qplane_2/ia_css_qplane.host.c @@ -33,16 +33,21 @@ int ia_css_qplane_config(struct sh_css_isp_qplane_isp_config *to, unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; + int ret; + + ret = ia_css_dma_configure_from_info(&to->port_b, from->info); + if (ret) + return ret; - (void)size; - ia_css_dma_configure_from_info(&to->port_b, from->info); to->width_a_over_b = elems_a / to->port_b.elems; /* Assume divisiblity here, may need to generalize to fixed point. */ - assert(elems_a % to->port_b.elems == 0); + if (elems_a % to->port_b.elems != 0) + return -EINVAL; to->inout_port_config = from->pipe->inout_port_config; to->format = from->info->format; + return 0; } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c index aba0409a4a0d..646d6e39c1e5 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/raw/raw_1.0/ia_css_raw.host.c @@ -71,8 +71,8 @@ int ia_css_raw_config(struct sh_css_isp_raw_isp_config *to, unsigned int elems_a = ISP_VEC_NELEMS; const struct ia_css_frame_info *in_info = from->in_info; const struct ia_css_frame_info *internal_info = from->internal_info; + int ret; - (void)size; #if !defined(ISP2401) /* 2401 input system uses input width width */ in_info = internal_info; @@ -84,7 +84,9 @@ int ia_css_raw_config(struct sh_css_isp_raw_isp_config *to, in_info = internal_info; #endif - ia_css_dma_configure_from_info(&to->port_b, in_info); + ret = ia_css_dma_configure_from_info(&to->port_b, in_info); + if (ret) + return ret; /* Assume divisiblity here, may need to generalize to fixed point. */ assert((in_info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) || diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c index 663dbb7c39eb..08ed916a7eb8 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c @@ -27,9 +27,12 @@ int ia_css_ref_config(struct sh_css_isp_ref_isp_config *to, unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS, i; + int ret; if (from->ref_frames[0]) { - ia_css_dma_configure_from_info(&to->port_b, &from->ref_frames[0]->info); + ret = ia_css_dma_configure_from_info(&to->port_b, &from->ref_frames[0]->info); + if (ret) + return ret; to->width_a_over_b = elems_a / to->port_b.elems; to->dvs_frame_delay = from->dvs_frame_delay; } else { @@ -50,7 +53,9 @@ int ia_css_ref_config(struct sh_css_isp_ref_isp_config *to, } /* Assume divisiblity here, may need to generalize to fixed point. */ - assert(elems_a % to->port_b.elems == 0); + if (elems_a % to->port_b.elems != 0) + return -EINVAL; + return 0; } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c index 3a5bea219c48..7177cf292fb0 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c @@ -77,9 +77,11 @@ int ia_css_tnr_config(struct sh_css_isp_tnr_isp_config *to, { unsigned int elems_a = ISP_VEC_NELEMS; unsigned int i; + int ret; - (void)size; - ia_css_dma_configure_from_info(&to->port_b, &from->tnr_frames[0]->info); + ret = ia_css_dma_configure_from_info(&to->port_b, &from->tnr_frames[0]->info); + if (ret) + return ret; to->width_a_over_b = elems_a / to->port_b.elems; to->frame_height = from->tnr_frames[0]->info.res.height; for (i = 0; i < NUM_TNR_FRAMES; i++) { @@ -88,7 +90,9 @@ int ia_css_tnr_config(struct sh_css_isp_tnr_isp_config *to, } /* Assume divisiblity here, may need to generalize to fixed point. */ - assert(elems_a % to->port_b.elems == 0); + if (elems_a % to->port_b.elems != 0) + return -EINVAL; + return 0; } diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c index 1ace34f59f8d..aecdcbe04ce1 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c @@ -31,18 +31,21 @@ int ia_css_vf_config(struct sh_css_isp_vf_isp_config *to, unsigned int size) { unsigned int elems_a = ISP_VEC_NELEMS; + int ret; - (void)size; to->vf_downscale_bits = from->vf_downscale_bits; to->enable = from->info != NULL; if (from->info) { ia_css_frame_info_to_frame_sp_info(&to->info, from->info); - ia_css_dma_configure_from_info(&to->dma.port_b, from->info); + ret = ia_css_dma_configure_from_info(&to->dma.port_b, from->info); + if (ret) + return ret; to->dma.width_a_over_b = elems_a / to->dma.port_b.elems; /* Assume divisiblity here, may need to generalize to fixed point. */ - assert(elems_a % to->dma.port_b.elems == 0); + if (elems_a % to->dma.port_b.elems != 0) + return -EINVAL; } return 0; } diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c index 647383e10f5e..3c9dd5c03850 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c +++ b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c @@ -608,7 +608,12 @@ int ia_css_dma_configure_from_info(struct dma_port_config *config, config->elems = (uint8_t)elems_b; config->width = (uint16_t)info->res.width; config->crop = 0; - assert(config->width <= info->padded_width); + + if (config->width > info->padded_width) { + dev_err(atomisp_dev, "internal error: padded_width is too small!\n"); + return -EINVAL; + } + return 0; } From 4a62b5cca5f04838854992eea720744928bec0f3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Nov 2021 18:09:13 +0000 Subject: [PATCH 060/397] media: atomisp: get rid of ISP2401_NEW_INPUT_SYSTEM All ISP2401 devices use the new input system. So, get rid of the remaining definitions, replacing them by runtime checks for BYT/CHT when applicable. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/Makefile | 4 +--- .../staging/media/atomisp/pci/atomisp_cmd.c | 19 +++++++++++-------- .../media/atomisp/pci/atomisp_compat_css20.c | 4 ++-- .../staging/media/atomisp/pci/atomisp_fops.c | 4 +--- .../staging/media/atomisp/pci/atomisp_v4l2.c | 14 ++------------ 5 files changed, 17 insertions(+), 28 deletions(-) diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile index a23c04cf7f34..a7ad8cfab602 100644 --- a/drivers/staging/media/atomisp/Makefile +++ b/drivers/staging/media/atomisp/Makefile @@ -301,10 +301,8 @@ INCLUDES += \ -I$(atomisp)/pci/runtime/rmgr/interface/ \ -I$(atomisp)/pci/runtime/spctrl/interface/ \ -I$(atomisp)/pci/runtime/tagger/interface/ \ - -I$(atomisp)/pci/css_2400_system/hive/ \ -I$(atomisp)/pci/css_2401_system/ \ -I$(atomisp)/pci/css_2401_system/host/ \ - -I$(atomisp)/pci/css_2401_system/hive/ \ -I$(atomisp)/pci/css_2401_system/hrt/ DEFINES := -DHRT_HW -DHRT_ISP_CSS_CUSTOM_HOST -DHRT_USE_VIR_ADDRS -D__HOST__ @@ -319,7 +317,7 @@ ifeq ($(CONFIG_VIDEO_ATOMISP_ISP2401),y) atomisp-objs += \ $(obj-cht) \ pci/runtime/isys/src/ibuf_ctrl_rmgr.o -DEFINES += -DISP2401 -DISP2401_NEW_INPUT_SYSTEM +DEFINES += -DISP2401 endif ccflags-y += $(INCLUDES) $(DEFINES) -fno-common diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 0ddee36cdcd7..4ef5d728cd2f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -5156,11 +5156,11 @@ static int css_input_resolution_changed(struct atomisp_sub_device *asd, dev_dbg(asd->isp->dev, "css_input_resolution_changed to %ux%u\n", ffmt->width, ffmt->height); -#if defined(ISP2401_NEW_INPUT_SYSTEM) - atomisp_css_input_set_two_pixels_per_clock(asd, false); -#else - atomisp_css_input_set_two_pixels_per_clock(asd, true); -#endif + if (IS_ISP2401) + atomisp_css_input_set_two_pixels_per_clock(asd, false); + else + atomisp_css_input_set_two_pixels_per_clock(asd, true); + if (asd->continuous_mode->val) { /* Note for all checks: ffmt includes pad_w+pad_h */ if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || @@ -5494,9 +5494,14 @@ static void atomisp_get_dis_envelop(struct atomisp_sub_device *asd, static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, int source_pad, struct v4l2_pix_format *f) { -#if defined(ISP2401_NEW_INPUT_SYSTEM) struct v4l2_mbus_framefmt *sink, *src; + if (!IS_ISP2401) { + /* Only used for the new input system */ + asd->copy_mode = false; + return; + } + sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK); src = atomisp_subdev_get_ffmt(&asd->subdev, NULL, @@ -5510,8 +5515,6 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, sensor[asd->sensor_curr].stream_num > 1))) asd->copy_mode = true; else -#endif - /* Only used for the new input system */ asd->copy_mode = false; dev_dbg(asd->isp->dev, "copy_mode: %d\n", asd->copy_mode); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index a8972b231e06..da177a8e78e3 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -972,7 +972,7 @@ int atomisp_css_irq_translate(struct atomisp_device *isp, void atomisp_css_rx_get_irq_info(enum mipi_port_id port, unsigned int *infos) { -#ifndef ISP2401_NEW_INPUT_SYSTEM +#ifndef IS_ISP2401 ia_css_isys_rx_get_irq_info(port, infos); #else *infos = 0; @@ -982,7 +982,7 @@ void atomisp_css_rx_get_irq_info(enum mipi_port_id port, void atomisp_css_rx_clear_irq_info(enum mipi_port_id port, unsigned int infos) { -#ifndef ISP2401_NEW_INPUT_SYSTEM +#ifndef IS_ISP2401 ia_css_isys_rx_clear_irq_info(port, infos); #endif } diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 4a7e5f2fe436..036a265502fe 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -464,13 +464,11 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE; } -#ifdef ISP2401_NEW_INPUT_SYSTEM - if (asd->copy_mode) { + if (IS_ISP2401 && asd->copy_mode) { css_capture_pipe_id = IA_CSS_PIPE_ID_COPY; css_preview_pipe_id = IA_CSS_PIPE_ID_COPY; css_video_pipe_id = IA_CSS_PIPE_ID_COPY; } -#endif if (asd->yuvpp_mode) { capture_pipe = &asd->video_out_capture; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index bbef485ee15c..0223e3dd95a6 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -1635,12 +1635,7 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i pdev->d3cold_delay = 0; break; case ATOMISP_PCI_DEVICE_SOC_ANN: - isp->media_dev.hw_revision = ( -#ifdef ISP2401_NEW_INPUT_SYSTEM - ATOMISP_HW_REVISION_ISP2401 -#else - ATOMISP_HW_REVISION_ISP2401_LEGACY -#endif + isp->media_dev.hw_revision = ( ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT); isp->media_dev.hw_revision |= pdev->revision < 2 ? ATOMISP_HW_STEPPING_A0 : ATOMISP_HW_STEPPING_B0; @@ -1648,12 +1643,7 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i isp->hpll_freq = HPLL_FREQ_1600MHZ; break; case ATOMISP_PCI_DEVICE_SOC_CHT: - isp->media_dev.hw_revision = ( -#ifdef ISP2401_NEW_INPUT_SYSTEM - ATOMISP_HW_REVISION_ISP2401 -#else - ATOMISP_HW_REVISION_ISP2401_LEGACY -#endif + isp->media_dev.hw_revision = ( ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT); isp->media_dev.hw_revision |= pdev->revision < 2 ? ATOMISP_HW_STEPPING_A0 : ATOMISP_HW_STEPPING_B0; From 2c45e343c581091835c9047ed5298518aa133163 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Oct 2021 08:09:39 +0100 Subject: [PATCH 061/397] media: atomisp: set per-device's default mode The atomisp driver originally used the s_parm command to initialize the run_mode type to the driver. So, before start setting up the streaming, s_parm should be called. So, even having 5 "normal" video devices, one meant to be used for each type, the run_mode was actually selected when s_parm is called. Without setting the run mode, applications that don't call VIDIOC_SET_PARM with a custom atomisp parameters won't work, as the pipeline won't be set: atomisp-isp2 0000:00:03.0: can't create streams atomisp-isp2 0000:00:03.0: __get_frame_info 1600x1200 (padded to 0) returned -22 However, commit 8a7c5594c020 ("media: v4l2-ioctl: clear fields in s_parm") broke support for it, with a good reason, as drivers shoudn't be extending the API for their own purposes. So, as an step to allow generic apps to use this driver, put the device's run_mode in preview after open. After this patch, using v4l2grab starts to work on preview mode (/dev/video2): $ v4l2grab -f YUYV -x 1600 -y 1200 -d /dev/video2 -n 1 -u $ feh out000.pnm So, let's just setup the default run_mode that each video devnode should assume, setting it at open() time. Reported-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_fops.c | 5 +++++ .../staging/media/atomisp/pci/atomisp_subdev.c | 15 ++++++++++----- .../staging/media/atomisp/pci/atomisp_subdev.h | 3 +++ drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 4 +++- drivers/staging/media/atomisp/pci/atomisp_v4l2.h | 3 ++- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 036a265502fe..a57d480820bd 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -899,6 +899,11 @@ done: else pipe->users++; rt_mutex_unlock(&isp->mutex); + + /* Ensure that a mode is set */ + if (asd) + v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode); + return 0; css_error: diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index 12f22ad007c7..ffaf11e0b0ad 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -1164,23 +1164,28 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) atomisp_init_acc_pipe(asd, &asd->video_acc); - ret = atomisp_video_init(&asd->video_in, "MEMORY"); + ret = atomisp_video_init(&asd->video_in, "MEMORY", + ATOMISP_RUN_MODE_SDV); if (ret < 0) return ret; - ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE"); + ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE", + ATOMISP_RUN_MODE_STILL_CAPTURE); if (ret < 0) return ret; - ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER"); + ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER", + ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE); if (ret < 0) return ret; - ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW"); + ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW", + ATOMISP_RUN_MODE_PREVIEW); if (ret < 0) return ret; - ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO"); + ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO", + ATOMISP_RUN_MODE_VIDEO); if (ret < 0) return ret; diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index d6fcfab6352d..a8d210ea5f8b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -81,6 +81,9 @@ struct atomisp_video_pipe { /* the link list to store per_frame parameters */ struct list_head per_frame_params; + /* Store here the initial run mode */ + unsigned int default_run_mode; + unsigned int buffers_in_css; /* irq_lock is used to protect video buffer state change operations and diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 0223e3dd95a6..1b240891a6e2 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -447,7 +447,8 @@ const struct atomisp_dfs_config dfs_config_cht_soc = { .dfs_table_size = ARRAY_SIZE(dfs_rules_cht_soc), }; -int atomisp_video_init(struct atomisp_video_pipe *video, const char *name) +int atomisp_video_init(struct atomisp_video_pipe *video, const char *name, + unsigned int run_mode) { int ret; const char *direction; @@ -478,6 +479,7 @@ int atomisp_video_init(struct atomisp_video_pipe *video, const char *name) "ATOMISP ISP %s %s", name, direction); video->vdev.release = video_device_release_empty; video_set_drvdata(&video->vdev, video->isp); + video->default_run_mode = run_mode; return 0; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h index 81bb356b8172..72611b8286a4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h @@ -27,7 +27,8 @@ struct v4l2_device; struct atomisp_device; struct firmware; -int atomisp_video_init(struct atomisp_video_pipe *video, const char *name); +int atomisp_video_init(struct atomisp_video_pipe *video, const char *name, + unsigned int run_mode); void atomisp_acc_init(struct atomisp_acc_pipe *video, const char *name); void atomisp_video_unregister(struct atomisp_video_pipe *video); void atomisp_acc_unregister(struct atomisp_acc_pipe *video); From 88f4f81e8c8e3e5c637602fe02ee9a102b67b7b0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 6 Nov 2021 11:26:20 +0000 Subject: [PATCH 062/397] media: atomisp: register first the preview devnode The atomisp currenyl registers 5 pairs of devices each one for one different run_mode, plus one for "ACC". The only one that behaves like a normal V4L2 device is the preview one. The others are doing weird things, and perhaps are using some proprietary extensions to the API. Change the device order to start with the preview one, e. g: /dev/video0: ATOMISP ISP PREVIEW output /dev/video1: ATOMISP ISP CAPTURE output /dev/video2: ATOMISP ISP VIEWFINDER output /dev/video3: ATOMISP ISP VIDEO output /dev/video4: ATOMISP ACC This way, a normal V4L2 application will get the right device, as the first one will be the one they should use. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_subdev.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index ffaf11e0b0ad..a3f3c42f9db7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -1356,6 +1356,14 @@ int atomisp_subdev_register_entities(struct atomisp_sub_device *asd, if (ret < 0) goto error; + asd->video_out_preview.vdev.v4l2_dev = vdev; + asd->video_out_preview.vdev.device_caps = device_caps | + V4L2_CAP_VIDEO_OUTPUT; + ret = video_register_device(&asd->video_out_preview.vdev, + VFL_TYPE_VIDEO, -1); + if (ret < 0) + goto error; + asd->video_out_capture.vdev.v4l2_dev = vdev; asd->video_out_capture.vdev.device_caps = device_caps | V4L2_CAP_VIDEO_OUTPUT; @@ -1371,13 +1379,7 @@ int atomisp_subdev_register_entities(struct atomisp_sub_device *asd, VFL_TYPE_VIDEO, -1); if (ret < 0) goto error; - asd->video_out_preview.vdev.v4l2_dev = vdev; - asd->video_out_preview.vdev.device_caps = device_caps | - V4L2_CAP_VIDEO_OUTPUT; - ret = video_register_device(&asd->video_out_preview.vdev, - VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto error; + asd->video_out_video_capture.vdev.v4l2_dev = vdev; asd->video_out_video_capture.vdev.device_caps = device_caps | V4L2_CAP_VIDEO_OUTPUT; From 83b1e1efe5ed113df37d0841683aafd69a19988b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:39 +0000 Subject: [PATCH 063/397] media: atomisp-ov2680: Remove a bunch of unused vars from ov2680_device Remove a couple of variables which where either completely unused, or only ever got a value assigned to them but were never read. Link: https://lore.kernel.org/linux-media/20211107171549.267583-2-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 25 ------------------- drivers/staging/media/atomisp/i2c/ov2680.h | 4 --- 2 files changed, 29 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index ef439937717b..56f95e44316d 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -166,8 +166,6 @@ static int ov2680_get_intg_factor(struct i2c_client *client, struct camera_mipi_info *info, const struct ov2680_resolution *res) { - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct ov2680_device *dev = to_ov2680_sensor(sd); struct atomisp_sensor_mode_data *buf = &info->data; unsigned int pix_clk_freq_hz; u16 reg_val; @@ -180,7 +178,6 @@ static int ov2680_get_intg_factor(struct i2c_client *client, /* pixel clock */ pix_clk_freq_hz = res->pix_clk_freq * 1000000; - dev->vt_pix_clk_freq_mhz = pix_clk_freq_hz; buf->vt_pix_clk_freq_mhz = pix_clk_freq_hz; /* get integration time */ @@ -434,24 +431,8 @@ err: return ret; } -static u32 ov2680_translate_bayer_order(enum atomisp_bayer_order code) -{ - switch (code) { - case atomisp_bayer_order_rggb: - return MEDIA_BUS_FMT_SRGGB10_1X10; - case atomisp_bayer_order_grbg: - return MEDIA_BUS_FMT_SGRBG10_1X10; - case atomisp_bayer_order_bggr: - return MEDIA_BUS_FMT_SBGGR10_1X10; - case atomisp_bayer_order_gbrg: - return MEDIA_BUS_FMT_SGBRG10_1X10; - } - return 0; -} - static int ov2680_v_flip(struct v4l2_subdev *sd, s32 value) { - struct ov2680_device *dev = to_ov2680_sensor(sd); struct camera_mipi_info *ov2680_info = NULL; struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; @@ -476,15 +457,12 @@ static int ov2680_v_flip(struct v4l2_subdev *sd, s32 value) ov2680_info = v4l2_get_subdev_hostdata(sd); if (ov2680_info) { ov2680_info->raw_bayer_order = ov2680_bayer_order_mapping[index]; - dev->format.code = ov2680_translate_bayer_order( - ov2680_info->raw_bayer_order); } return ret; } static int ov2680_h_flip(struct v4l2_subdev *sd, s32 value) { - struct ov2680_device *dev = to_ov2680_sensor(sd); struct camera_mipi_info *ov2680_info = NULL; struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; @@ -510,8 +488,6 @@ static int ov2680_h_flip(struct v4l2_subdev *sd, s32 value) ov2680_info = v4l2_get_subdev_hostdata(sd); if (ov2680_info) { ov2680_info->raw_bayer_order = ov2680_bayer_order_mapping[index]; - dev->format.code = ov2680_translate_bayer_order( - ov2680_info->raw_bayer_order); } return ret; } @@ -1199,7 +1175,6 @@ static int ov2680_probe(struct i2c_client *client) dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; dev->pad.flags = MEDIA_PAD_FL_SOURCE; - dev->format.code = MEDIA_BUS_FMT_SBGGR10_1X10; dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ret = v4l2_ctrl_handler_init(&dev->ctrl_handler, diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index 535440ed14d7..9f9f6695eed9 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -169,14 +169,10 @@ struct ov2680_format { struct ov2680_device { struct v4l2_subdev sd; struct media_pad pad; - struct v4l2_mbus_framefmt format; struct mutex input_lock; struct v4l2_ctrl_handler ctrl_handler; struct ov2680_resolution *res; struct camera_sensor_platform_data *platform_data; - int vt_pix_clk_freq_mhz; - int run_mode; - u8 type; }; /** From 12350633a8dbdcf7d8e0b1f726a4b58aa21e25db Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:40 +0000 Subject: [PATCH 064/397] media: atomisp-ov2680: Turn on power only once Add a power_on bool to track if the power is on, and make power_up() a no-op if the power is already on. This also removes a power_down() call from ov2680_s_config() since that is a no-op now, this is ok because s_config() is only called once on probe and the sensor is off at boot. Besides avoiding to the work in power_up() multiple times this patch is also a preparation for switching to the clk and regulator frameworks which keep an enable count, so there we must call enable() and disable() only once per power-cycle. Link: https://lore.kernel.org/linux-media/20211107171549.267583-3-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 27 +++++++++---------- drivers/staging/media/atomisp/i2c/ov2680.h | 1 + 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 56f95e44316d..7b7cf7a68823 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -736,6 +736,9 @@ static int power_up(struct v4l2_subdev *sd) return -ENODEV; } + if (dev->power_on) + return 0; /* Already on */ + /* power control */ ret = power_ctrl(sd, 1); if (ret) @@ -760,6 +763,7 @@ static int power_up(struct v4l2_subdev *sd) /* according to DS, 20ms is needed between PWDN and i2c access */ msleep(20); + dev->power_on = true; return 0; fail_clk: @@ -785,6 +789,9 @@ static int power_down(struct v4l2_subdev *sd) return -ENODEV; } + if (!dev->power_on) + return 0; /* Already off */ + ret = dev->platform_data->flisclk_ctrl(sd, 0); if (ret) dev_err(&client->dev, "flisclk failed\n"); @@ -799,10 +806,13 @@ static int power_down(struct v4l2_subdev *sd) /* power control */ ret = power_ctrl(sd, 0); - if (ret) + if (ret) { dev_err(&client->dev, "vprog failed.\n"); + return ret; + } - return ret; + dev->power_on = false; + return 0; } static int ov2680_s_power(struct v4l2_subdev *sd, int on) @@ -866,7 +876,7 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, dev_dbg(&client->dev, "%s: %dx%d\n", __func__, fmt->width, fmt->height); - // IS IT NEEDED? + /* s_power has not been called yet for std v4l2 clients (camorama) */ power_up(sd); ret = ov2680_write_reg_array(client, dev->res->regs); if (ret) @@ -998,16 +1008,6 @@ static int ov2680_s_config(struct v4l2_subdev *sd, (struct camera_sensor_platform_data *)platform_data; mutex_lock(&dev->input_lock); - /* - * power off the module, then power on it in future - * as first power on by board may not fulfill the - * power on sequqence needed by the module - */ - ret = power_down(sd); - if (ret) { - dev_err(&client->dev, "ov2680 power-off err.\n"); - goto fail_power_off; - } ret = power_up(sd); if (ret) { @@ -1041,7 +1041,6 @@ fail_csi_cfg: fail_power_on: power_down(sd); dev_err(&client->dev, "sensor power-gating failed\n"); -fail_power_off: mutex_unlock(&dev->input_lock); return ret; } diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index 9f9f6695eed9..edd87bb8563f 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -173,6 +173,7 @@ struct ov2680_device { struct v4l2_ctrl_handler ctrl_handler; struct ov2680_resolution *res; struct camera_sensor_platform_data *platform_data; + bool power_on; }; /** From e9174a6438adada772abdb16901280289aa4c3b2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:41 +0000 Subject: [PATCH 065/397] media: atomisp-ov2680: Push the input_lock taking up into ov2680_s_power() ov2680_s_power() is the only caller of ov2680_init(), push the input_lock taking from ov2680_init() up into ov2680_s_power(), this way the new power_on bool is also protected by it. Link: https://lore.kernel.org/linux-media/20211107171549.267583-4-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 7b7cf7a68823..2721223ebcde 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -655,21 +655,11 @@ static int ov2680_init_registers(struct v4l2_subdev *sd) static int ov2680_init(struct v4l2_subdev *sd) { - struct ov2680_device *dev = to_ov2680_sensor(sd); - - int ret; - - mutex_lock(&dev->input_lock); - /* restore settings */ ov2680_res = ov2680_res_preview; N_RES = N_RES_PREVIEW; - ret = ov2680_init_registers(sd); - - mutex_unlock(&dev->input_lock); - - return ret; + return ov2680_init_registers(sd); } static int power_ctrl(struct v4l2_subdev *sd, bool flag) @@ -817,15 +807,21 @@ static int power_down(struct v4l2_subdev *sd) static int ov2680_s_power(struct v4l2_subdev *sd, int on) { + struct ov2680_device *dev = to_ov2680_sensor(sd); int ret; + mutex_lock(&dev->input_lock); + if (on == 0) { ret = power_down(sd); } else { ret = power_up(sd); if (!ret) - return ov2680_init(sd); + ret = ov2680_init(sd); } + + mutex_unlock(&dev->input_lock); + return ret; } From b821cea597f84e37dc6d2df720a3dccb4eedf8b6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:42 +0000 Subject: [PATCH 066/397] media: atomisp-ov2680: Remove the ov2680_res and N_RES global variables The ov2680_res and N_RES global variables are just hardcoded as aliases for ov2680_res_preview and N_RES_PREVIEW, remove them. Link: https://lore.kernel.org/linux-media/20211107171549.267583-5-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 28 +++++-------------- drivers/staging/media/atomisp/i2c/ov2680.h | 3 -- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 2721223ebcde..b6927f9be022 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -653,15 +653,6 @@ static int ov2680_init_registers(struct v4l2_subdev *sd) return ret; } -static int ov2680_init(struct v4l2_subdev *sd) -{ - /* restore settings */ - ov2680_res = ov2680_res_preview; - N_RES = N_RES_PREVIEW; - - return ov2680_init_registers(sd); -} - static int power_ctrl(struct v4l2_subdev *sd, bool flag) { int ret = 0; @@ -817,7 +808,7 @@ static int ov2680_s_power(struct v4l2_subdev *sd, int on) } else { ret = power_up(sd); if (!ret) - ret = ov2680_init(sd); + ret = ov2680_init_registers(sd); } mutex_unlock(&dev->input_lock); @@ -857,7 +848,7 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, ARRAY_SIZE(ov2680_res_preview), width, height, fmt->width, fmt->height); if (!res) - res = &ov2680_res[N_RES - 1]; + res = &ov2680_res_preview[N_RES_PREVIEW - 1]; fmt->width = res->width; fmt->height = res->height; @@ -975,11 +966,6 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) ret = ov2680_write_reg(client, 1, OV2680_SW_STREAM, enable ? OV2680_START_STREAMING : OV2680_STOP_STREAMING); -#if 0 - /* restore settings */ - ov2680_res = ov2680_res_preview; - N_RES = N_RES_PREVIEW; -#endif //otp valid at stream on state //if(!dev->otp_data) @@ -1069,13 +1055,13 @@ static int ov2680_enum_frame_size(struct v4l2_subdev *sd, { int index = fse->index; - if (index >= N_RES) + if (index >= N_RES_PREVIEW) return -EINVAL; - fse->min_width = ov2680_res[index].width; - fse->min_height = ov2680_res[index].height; - fse->max_width = ov2680_res[index].width; - fse->max_height = ov2680_res[index].height; + fse->min_width = ov2680_res_preview[index].width; + fse->min_height = ov2680_res_preview[index].height; + fse->max_width = ov2680_res_preview[index].width; + fse->max_height = ov2680_res_preview[index].height; return 0; } diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index edd87bb8563f..c1998c9132a2 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -838,7 +838,4 @@ static struct ov2680_resolution ov2680_res_preview[] = { #define N_RES_PREVIEW (ARRAY_SIZE(ov2680_res_preview)) -static struct ov2680_resolution *ov2680_res = ov2680_res_preview; -static unsigned long N_RES = N_RES_PREVIEW; - #endif From 8eed52e182eeade19329a849c60a8150a101ac1e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:43 +0000 Subject: [PATCH 067/397] media: atomisp-ov2680: Move ov2680_init_registers() call to power_up() Move ov2680_init_registers() call to power_up(), so that we also init the registers on code-paths which do not call ov2680_s_power() like running camorama. Link: https://lore.kernel.org/linux-media/20211107171549.267583-6-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index b6927f9be022..83608ba4e70a 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -744,9 +744,15 @@ static int power_up(struct v4l2_subdev *sd) /* according to DS, 20ms is needed between PWDN and i2c access */ msleep(20); + ret = ov2680_init_registers(sd); + if (ret) + goto fail_init_registers; + dev->power_on = true; return 0; +fail_init_registers: + dev->platform_data->flisclk_ctrl(sd, 0); fail_clk: gpio_ctrl(sd, 0); fail_power: @@ -807,8 +813,6 @@ static int ov2680_s_power(struct v4l2_subdev *sd, int on) ret = power_down(sd); } else { ret = power_up(sd); - if (!ret) - ret = ov2680_init_registers(sd); } mutex_unlock(&dev->input_lock); From 4ed2caf8533753547364d22246a9c5c7d1e5943e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:44 +0000 Subject: [PATCH 068/397] media: atomisp-ov2680: Save/restore exposure and gain over sensor power-down Save/restore exposure and gain over sensor power-down and don't write them to the sensor when ov2680_set_exposure() is called while the sensor is off. Link: https://lore.kernel.org/linux-media/20211107171549.267583-7-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/i2c/atomisp-ov2680.c | 15 ++++++++++++++- drivers/staging/media/atomisp/i2c/ov2680.h | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 83608ba4e70a..5b192218ba91 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -359,7 +359,14 @@ static int ov2680_set_exposure(struct v4l2_subdev *sd, int exposure, int ret; mutex_lock(&dev->input_lock); - ret = __ov2680_set_exposure(sd, exposure, gain, digitgain); + + dev->exposure = exposure; + dev->gain = gain; + dev->digitgain = digitgain; + + if (dev->power_on) + ret = __ov2680_set_exposure(sd, exposure, gain, digitgain); + mutex_unlock(&dev->input_lock); return ret; @@ -748,6 +755,10 @@ static int power_up(struct v4l2_subdev *sd) if (ret) goto fail_init_registers; + ret = __ov2680_set_exposure(sd, dev->exposure, dev->gain, dev->digitgain); + if (ret) + goto fail_init_registers; + dev->power_on = true; return 0; @@ -1140,6 +1151,8 @@ static int ov2680_probe(struct i2c_client *client) mutex_init(&dev->input_lock); dev->res = &ov2680_res_preview[0]; + dev->exposure = dev->res->lines_per_frame - OV2680_INTEGRATION_TIME_MARGIN; + dev->gain = 250; /* 0-2047 */ v4l2_i2c_subdev_init(&dev->sd, client, &ov2680_ops); pdata = gmin_camera_platform_data(&dev->sd, diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index c1998c9132a2..ca20ce5aa285 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -174,6 +174,9 @@ struct ov2680_device { struct ov2680_resolution *res; struct camera_sensor_platform_data *platform_data; bool power_on; + u16 exposure; + u16 gain; + u16 digitgain; }; /** From 3aa39a49359c7049db8189cbec1aa1668f5a4583 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:45 +0000 Subject: [PATCH 069/397] media: atomisp-ov2680: Make ov2680_read_reg() support 24 bit registers Some ov2680 registers like exposure are 24 bit, ov2680_read_reg() already mostly supports this, we just need to change the return type from u16 to u32. Link: https://lore.kernel.org/linux-media/20211107171549.267583-8-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 5b192218ba91..7e49f4eb0410 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -48,7 +48,7 @@ static enum atomisp_bayer_order ov2680_bayer_order_mapping[] = { /* i2c read/write stuff */ static int ov2680_read_reg(struct i2c_client *client, - int len, u16 reg, u16 *val) + int len, u16 reg, u32 *val) { struct i2c_msg msgs[2]; u8 addr_buf[2] = { reg >> 8, reg & 0xff }; @@ -168,7 +168,7 @@ static int ov2680_get_intg_factor(struct i2c_client *client, { struct atomisp_sensor_mode_data *buf = &info->data; unsigned int pix_clk_freq_hz; - u16 reg_val; + u32 reg_val; int ret; dev_dbg(&client->dev, "++++ov2680_get_intg_factor\n"); @@ -410,7 +410,7 @@ static long ov2680_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) static int ov2680_q_exposure(struct v4l2_subdev *sd, s32 *value) { struct i2c_client *client = v4l2_get_subdevdata(sd); - u16 reg_v, reg_v2; + u32 reg_v, reg_v2; int ret; /* get exposure */ @@ -433,7 +433,7 @@ static int ov2680_q_exposure(struct v4l2_subdev *sd, s32 *value) if (ret) goto err; - *value = reg_v + (((u32)reg_v2 << 16)); + *value = reg_v + (reg_v2 << 16); err: return ret; } @@ -443,7 +443,7 @@ static int ov2680_v_flip(struct v4l2_subdev *sd, s32 value) struct camera_mipi_info *ov2680_info = NULL; struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; - u16 val; + u32 val; u8 index; dev_dbg(&client->dev, "@%s: value:%d\n", __func__, value); @@ -473,7 +473,7 @@ static int ov2680_h_flip(struct v4l2_subdev *sd, s32 value) struct camera_mipi_info *ov2680_info = NULL; struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; - u16 val; + u32 val; u8 index; dev_dbg(&client->dev, "@%s: value:%d\n", __func__, value); @@ -933,7 +933,7 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd, static int ov2680_detect(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - u16 high, low; + u32 high, low; int ret; u16 id; u8 revision; From bc53e5bdbc7b5044079506990b76b39511ee1582 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:46 +0000 Subject: [PATCH 070/397] media: atomisp-ov2680: Fix and simplify ov2680_q_exposure() Switch to ov2680_read_reg() to read all 24 bits in one go; and the exposure value sits in bits 4-19 of the 24 bit exposure register, so we need to shift the read value by 4 to report the correct value. Link: https://lore.kernel.org/linux-media/20211107171549.267583-9-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 7e49f4eb0410..d6a5f75fdd66 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -410,32 +410,17 @@ static long ov2680_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) static int ov2680_q_exposure(struct v4l2_subdev *sd, s32 *value) { struct i2c_client *client = v4l2_get_subdevdata(sd); - u32 reg_v, reg_v2; + u32 reg_val; int ret; /* get exposure */ - ret = ov2680_read_reg(client, 1, - OV2680_EXPOSURE_L, - ®_v); + ret = ov2680_read_reg(client, 3, OV2680_EXPOSURE_H, ®_val); if (ret) - goto err; + return ret; - ret = ov2680_read_reg(client, 1, - OV2680_EXPOSURE_M, - ®_v2); - if (ret) - goto err; - - reg_v += reg_v2 << 8; - ret = ov2680_read_reg(client, 1, - OV2680_EXPOSURE_H, - ®_v2); - if (ret) - goto err; - - *value = reg_v + (reg_v2 << 16); -err: - return ret; + /* Lower four bits are not part of the exposure val (always 0) */ + *value = reg_val >> 4; + return 0; } static int ov2680_v_flip(struct v4l2_subdev *sd, s32 value) From 9f7b638637da7b1785659fd963d79dbca5caaa69 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:47 +0000 Subject: [PATCH 071/397] media: atomisp-ov2680: Fix ov2680_write_reg() always writing 0 to 16 bit registers The shift << 16 of the value in the code path for 16 bit values is bogus, put_unaligned_be16() takes the lower 16 bits which will not always be 0. This was causing __ov2680_set_exposure() to always set the OV2680_AGC and OV2680_TIMING_VTS registers to 0. Link: https://lore.kernel.org/linux-media/20211107171549.267583-10-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index d6a5f75fdd66..1092d1c2993f 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -86,7 +86,7 @@ static int ov2680_write_reg(struct i2c_client *client, unsigned int len, int ret; if (len == 2) - put_unaligned_be16(val << (8 * (4 - len)), buf + 2); + put_unaligned_be16(val, buf + 2); else if (len == 1) buf[2] = val; else From 4492289c31364d28c2680b43b18883385a5d216c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:48 +0000 Subject: [PATCH 072/397] media: atomisp-ov2680: Fix ov2680_set_fmt() clobbering the exposure Now that we restore the default or last user set exposure setting on power_up() there is no need for the registers written by ov2680_set_fmt() to write to the exposure register. Not doing so fixes the exposure always being reset to the value from the res->regs array after a set_fmt(). Link: https://lore.kernel.org/linux-media/20211107171549.267583-11-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/ov2680.h | 24 ---------------------- 1 file changed, 24 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index ca20ce5aa285..d52b7fbe3c06 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -288,8 +288,6 @@ static struct ov2680_reg const ov2680_global_setting[] = { */ static struct ov2680_reg const ov2680_QCIF_30fps[] = { {0x3086, 0x01}, - {0x3501, 0x24}, - {0x3502, 0x40}, {0x370a, 0x23}, {0x3801, 0xa0}, {0x3802, 0x00}, @@ -333,8 +331,6 @@ static struct ov2680_reg const ov2680_QCIF_30fps[] = { */ static struct ov2680_reg const ov2680_CIF_30fps[] = { {0x3086, 0x01}, - {0x3501, 0x24}, - {0x3502, 0x40}, {0x370a, 0x23}, {0x3801, 0xa0}, {0x3802, 0x00}, @@ -376,8 +372,6 @@ static struct ov2680_reg const ov2680_CIF_30fps[] = { */ static struct ov2680_reg const ov2680_QVGA_30fps[] = { {0x3086, 0x01}, - {0x3501, 0x24}, - {0x3502, 0x40}, {0x370a, 0x23}, {0x3801, 0xa0}, {0x3802, 0x00}, @@ -419,8 +413,6 @@ static struct ov2680_reg const ov2680_QVGA_30fps[] = { */ static struct ov2680_reg const ov2680_656x496_30fps[] = { {0x3086, 0x01}, - {0x3501, 0x24}, - {0x3502, 0x40}, {0x370a, 0x23}, {0x3801, 0xa0}, {0x3802, 0x00}, @@ -462,8 +454,6 @@ static struct ov2680_reg const ov2680_656x496_30fps[] = { */ static struct ov2680_reg const ov2680_720x592_30fps[] = { {0x3086, 0x01}, - {0x3501, 0x26}, - {0x3502, 0x40}, {0x370a, 0x23}, {0x3801, 0x00}, // X_ADDR_START; {0x3802, 0x00}, @@ -507,8 +497,6 @@ static struct ov2680_reg const ov2680_720x592_30fps[] = { */ static struct ov2680_reg const ov2680_800x600_30fps[] = { {0x3086, 0x01}, - {0x3501, 0x26}, - {0x3502, 0x40}, {0x370a, 0x23}, {0x3801, 0x00}, {0x3802, 0x00}, @@ -550,8 +538,6 @@ static struct ov2680_reg const ov2680_800x600_30fps[] = { */ static struct ov2680_reg const ov2680_720p_30fps[] = { {0x3086, 0x00}, - {0x3501, 0x48}, - {0x3502, 0xe0}, {0x370a, 0x21}, {0x3801, 0xa0}, {0x3802, 0x00}, @@ -593,8 +579,6 @@ static struct ov2680_reg const ov2680_720p_30fps[] = { */ static struct ov2680_reg const ov2680_1296x976_30fps[] = { {0x3086, 0x00}, - {0x3501, 0x48}, - {0x3502, 0xe0}, {0x370a, 0x21}, {0x3801, 0xa0}, {0x3802, 0x00}, @@ -636,8 +620,6 @@ static struct ov2680_reg const ov2680_1296x976_30fps[] = { */ static struct ov2680_reg const ov2680_1456x1096_30fps[] = { {0x3086, 0x00}, - {0x3501, 0x48}, - {0x3502, 0xe0}, {0x370a, 0x21}, {0x3801, 0x90}, {0x3802, 0x00}, @@ -681,8 +663,6 @@ static struct ov2680_reg const ov2680_1456x1096_30fps[] = { static struct ov2680_reg const ov2680_1616x916_30fps[] = { {0x3086, 0x00}, - {0x3501, 0x48}, - {0x3502, 0xe0}, {0x370a, 0x21}, {0x3801, 0x00}, {0x3802, 0x00}, @@ -725,8 +705,6 @@ static struct ov2680_reg const ov2680_1616x916_30fps[] = { #if 0 static struct ov2680_reg const ov2680_1616x1082_30fps[] = { {0x3086, 0x00}, - {0x3501, 0x48}, - {0x3502, 0xe0}, {0x370a, 0x21}, {0x3801, 0x00}, {0x3802, 0x00}, @@ -768,8 +746,6 @@ static struct ov2680_reg const ov2680_1616x1082_30fps[] = { */ static struct ov2680_reg const ov2680_1616x1216_30fps[] = { {0x3086, 0x00}, - {0x3501, 0x48}, - {0x3502, 0xe0}, {0x370a, 0x21}, {0x3801, 0x00}, {0x3802, 0x00}, From 29400b5063db69fbed9ff483a44d635b15d847cc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Nov 2021 17:15:49 +0000 Subject: [PATCH 073/397] media: atomisp-ov2680: Fix ov2680_set_fmt() messing up high exposure settings For exposure settings > (lines_per_frame - vts_margin) the VTS register needs to be programmed to (exposure + vts_margin) rather then being set to lines_per_frame. The res->regs register array was clobbering this higher setting causing high exposure settings to not work. Fix this by letting ov2680_set_fmt() calculate the vts value, instead of hardcoding it. This is the last in a series of fixes which fixes exposure and gain settings not working, with this everything works, so drop the comment that it does not work. Link: https://lore.kernel.org/linux-media/20211107171549.267583-12-hdegoede@redhat.com Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 13 ++++++++-- drivers/staging/media/atomisp/i2c/ov2680.h | 24 ------------------- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 1092d1c2993f..34d008236bd9 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -387,7 +387,6 @@ static long ov2680_s_exposure(struct v4l2_subdev *sd, return -EINVAL; } - // EXPOSURE CONTROL DISABLED FOR INITIAL CHECKIN, TUNING DOESN'T WORK return ov2680_set_exposure(sd, coarse_itg, analog_gain, digital_gain); } @@ -825,7 +824,7 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, struct i2c_client *client = v4l2_get_subdevdata(sd); struct camera_mipi_info *ov2680_info = NULL; struct ov2680_resolution *res; - int ret = 0; + int vts, ret = 0; dev_dbg(&client->dev, "%s: %s: pad: %d, fmt: %p\n", __func__, @@ -870,6 +869,16 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, dev_err(&client->dev, "ov2680 write resolution register err: %d\n", ret); + /* If necessary increase the VTS to match exposure + MARGIN */ + if (dev->exposure > vts - OV2680_INTEGRATION_TIME_MARGIN) + vts = dev->exposure + OV2680_INTEGRATION_TIME_MARGIN; + else + vts = dev->res->lines_per_frame; + + ret = ov2680_write_reg(client, 2, OV2680_TIMING_VTS_H, vts); + if (ret) + dev_err(&client->dev, "ov2680 write vts err: %d\n", ret); + ret = ov2680_get_intg_factor(client, ov2680_info, res); if (ret) { dev_err(&client->dev, "failed to get integration factor\n"); diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index d52b7fbe3c06..e53be612a1e4 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -302,8 +302,6 @@ static struct ov2680_reg const ov2680_QCIF_30fps[] = { {0x380b, 0xa0}, {0x380c, 0x06}, {0x380d, 0xb0}, - {0x380e, 0x02}, - {0x380f, 0x84}, {0x3810, 0x00}, {0x3811, 0x04}, {0x3812, 0x00}, @@ -345,8 +343,6 @@ static struct ov2680_reg const ov2680_CIF_30fps[] = { {0x380b, 0x30}, {0x380c, 0x06}, {0x380d, 0xb0}, - {0x380e, 0x02}, - {0x380f, 0x84}, {0x3810, 0x00}, {0x3811, 0x04}, {0x3812, 0x00}, @@ -386,8 +382,6 @@ static struct ov2680_reg const ov2680_QVGA_30fps[] = { {0x380b, 0x00}, {0x380c, 0x06}, {0x380d, 0xb0}, - {0x380e, 0x02}, - {0x380f, 0x84}, {0x3810, 0x00}, {0x3811, 0x04}, {0x3812, 0x00}, @@ -427,8 +421,6 @@ static struct ov2680_reg const ov2680_656x496_30fps[] = { {0x380b, 0xf0}, {0x380c, 0x06}, {0x380d, 0xb0}, - {0x380e, 0x02}, - {0x380f, 0x84}, {0x3810, 0x00}, {0x3811, 0x04}, {0x3812, 0x00}, @@ -468,8 +460,6 @@ static struct ov2680_reg const ov2680_720x592_30fps[] = { {0x380b, 0x50}, // Y_OUTPUT_SIZE; {0x380c, 0x06}, {0x380d, 0xac}, // HTS; - {0x380e, 0x02}, - {0x380f, 0x84}, // VTS; {0x3810, 0x00}, {0x3811, 0x00}, {0x3812, 0x00}, @@ -511,8 +501,6 @@ static struct ov2680_reg const ov2680_800x600_30fps[] = { {0x380b, 0x58}, {0x380c, 0x06}, {0x380d, 0xac}, - {0x380e, 0x02}, - {0x380f, 0x84}, {0x3810, 0x00}, {0x3811, 0x00}, {0x3812, 0x00}, @@ -552,8 +540,6 @@ static struct ov2680_reg const ov2680_720p_30fps[] = { {0x380b, 0xe0}, {0x380c, 0x06}, {0x380d, 0xa8}, - {0x380e, 0x05}, - {0x380f, 0x0e}, {0x3810, 0x00}, {0x3811, 0x08}, {0x3812, 0x00}, @@ -593,8 +579,6 @@ static struct ov2680_reg const ov2680_1296x976_30fps[] = { {0x380b, 0xd0}, {0x380c, 0x06}, {0x380d, 0xa8}, - {0x380e, 0x05}, - {0x380f, 0x0e}, {0x3810, 0x00}, {0x3811, 0x08}, {0x3812, 0x00}, @@ -634,8 +618,6 @@ static struct ov2680_reg const ov2680_1456x1096_30fps[] = { {0x380b, 0x48}, {0x380c, 0x06}, {0x380d, 0xa8}, - {0x380e, 0x05}, - {0x380f, 0x0e}, {0x3810, 0x00}, {0x3811, 0x08}, {0x3812, 0x00}, @@ -677,8 +659,6 @@ static struct ov2680_reg const ov2680_1616x916_30fps[] = { {0x380b, 0x94}, {0x380c, 0x06}, {0x380d, 0xa8}, - {0x380e, 0x05}, - {0x380f, 0x0e}, {0x3810, 0x00}, {0x3811, 0x00}, {0x3812, 0x00}, @@ -719,8 +699,6 @@ static struct ov2680_reg const ov2680_1616x1082_30fps[] = { {0x380b, 0x3a}, {0x380c, 0x06}, {0x380d, 0xa8}, - {0x380e, 0x05}, - {0x380f, 0x0e}, {0x3810, 0x00}, {0x3811, 0x00}, {0x3812, 0x00}, @@ -760,8 +738,6 @@ static struct ov2680_reg const ov2680_1616x1216_30fps[] = { {0x380b, 0xc0},//c0}, {0x380c, 0x06}, {0x380d, 0xa8}, - {0x380e, 0x05}, - {0x380f, 0x0e}, {0x3810, 0x00}, {0x3811, 0x00}, {0x3812, 0x00}, From d9916e7c87c97781579c3d3d47e52c564e321c21 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 10 Nov 2021 10:54:41 +0000 Subject: [PATCH 074/397] media: atomisp-ov2680: initialize return var As the settings are only applied when the device is powered on, it should return 0 when the device is not powered. Not doing that causes a warning: drivers/staging/media/atomisp/i2c/atomisp-ov2680.c: In function 'ov2680_ioctl': drivers/staging/media/atomisp/i2c/atomisp-ov2680.c:390:16: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized] 390 | return ov2680_set_exposure(sd, coarse_itg, analog_gain, digital_gain); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/staging/media/atomisp/i2c/atomisp-ov2680.c:359:13: note: 'ret' was declared here 359 | int ret; | ^~~ Reported-by: Hans Verkuil Reviewed-by: Hans de Goede Fixes: 6b5b60687ada ("media: atomisp-ov2680: Save/restore exposure and gain over sensor power-down") Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 34d008236bd9..497884d332e1 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -356,7 +356,7 @@ static int ov2680_set_exposure(struct v4l2_subdev *sd, int exposure, int gain, int digitgain) { struct ov2680_device *dev = to_ov2680_sensor(sd); - int ret; + int ret = 0; mutex_lock(&dev->input_lock); From 22f2cac62dea739d395007b3ce68def36adafd6c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 10 Nov 2021 10:55:39 +0000 Subject: [PATCH 075/397] media: atomisp-ov2680: properly set the vts value The vts value should be set before being checked, as otherwise a warning will arise: drivers/staging/media/atomisp/i2c/atomisp-ov2680.c: In function 'ov2680_set_fmt': drivers/staging/media/atomisp/i2c/atomisp-ov2680.c:873:33: warning: 'vts' may be used uninitialized [-Wmaybe-uninitialized] 873 | if (dev->exposure > vts - OV2680_INTEGRATION_TIME_MARGIN) Reported-by: Hans Verkuil Reviewed-by: Hans de Goede Fixes: 62b984359b6f ("media: atomisp-ov2680: Fix ov2680_set_fmt() messing up high exposure settings") Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 497884d332e1..d24f8830fd94 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -869,11 +869,11 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, dev_err(&client->dev, "ov2680 write resolution register err: %d\n", ret); + vts = dev->res->lines_per_frame; + /* If necessary increase the VTS to match exposure + MARGIN */ if (dev->exposure > vts - OV2680_INTEGRATION_TIME_MARGIN) vts = dev->exposure + OV2680_INTEGRATION_TIME_MARGIN; - else - vts = dev->res->lines_per_frame; ret = ov2680_write_reg(client, 2, OV2680_TIMING_VTS_H, vts); if (ret) From cb4d67a998e97365afdf34965b069601da1dae60 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 12 Oct 2021 09:21:50 +0100 Subject: [PATCH 076/397] media: atomisp: fix uninitialized bug in gmin_get_pmic_id_and_addr() The "power" pointer is not initialized on the else path and that would lead to an Oops. Link: https://lore.kernel.org/linux-media/20211012082150.GA31086@kili Fixes: c30f4cb2d4c7 ("media: atomisp: Refactor PMIC detection to a separate function") Signed-off-by: Dan Carpenter Reviewed-by: Kieran Bingham Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index 948eb6f809f5..1cc581074ba7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -500,7 +500,7 @@ fail: static u8 gmin_get_pmic_id_and_addr(struct device *dev) { - struct i2c_client *power; + struct i2c_client *power = NULL; static u8 pmic_i2c_addr; if (pmic_id) From e5e59f81840be21c6c996c783effb8744958414e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 8 Nov 2021 09:40:25 +0000 Subject: [PATCH 077/397] media: atomisp: only initialize mode if pipe is not null During atomisp register, udev tries to open all devices. For some, pipe is NULL, at least during register time, causing the driver to try to access a NULL pointer. So, add an extra check to avoid such condition. Link: https://lore.kernel.org/linux-media/6406265f2d5f3791d5c7cbd1364186217f19524c.1636364423.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_fops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index a57d480820bd..c7ac313a2edf 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -901,7 +901,7 @@ done: rt_mutex_unlock(&isp->mutex); /* Ensure that a mode is set */ - if (asd) + if (asd && pipe) v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode); return 0; From 71665d816214124d6bc4eb80314ac8f84ecacd78 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 10 Nov 2021 12:59:11 +0000 Subject: [PATCH 078/397] media: atomisp: check before deference asd variable The asd->isp was referenced before checking if asd is not NULL. This fixes this warning: ../drivers/staging/media/atomisp/pci/atomisp_cmd.c:5548 atomisp_set_fmt_to_snr() warn: variable dereferenced before check 'asd' (see line 5540) While here, avoid getting the pipe pointer twice. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 4ef5d728cd2f..43e266f26504 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -5525,8 +5525,8 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, unsigned int padding_w, unsigned int padding_h, unsigned int dvs_env_w, unsigned int dvs_env_h) { - struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); + struct atomisp_sub_device *asd = pipe->asd; const struct atomisp_format_bridge *format; struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { @@ -5537,7 +5537,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, }; struct v4l2_mbus_framefmt *ffmt = &vformat.format; struct v4l2_mbus_framefmt *req_ffmt; - struct atomisp_device *isp = asd->isp; + struct atomisp_device *isp; struct atomisp_input_stream_info *stream_info = (struct atomisp_input_stream_info *)ffmt->reserved; u16 stream_index = ATOMISP_INPUT_STREAM_GENERAL; @@ -5551,6 +5551,8 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, return -EINVAL; } + isp = asd->isp; + v4l2_fh_init(&fh.vfh, vdev); stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); From 245f6f4a32fe7f60260f8ffdf4d5173bf3bebbca Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 10 Nov 2021 13:08:28 +0000 Subject: [PATCH 079/397] media: atomisp: simplify asd check on open() fops The open() fops support two types of devices: "acc" and normal ones. the acc works on a different way, using a different pipe struct. Not sure yet if it would make sense to setup a run_mode there. Also, As default_run_mode exists only on normal modes, we can simplify the logic to check if the device is in normal mode. That solves this warning: ../drivers/staging/media/atomisp/pci/atomisp_fops.c:904 atomisp_open() warn: variable dereferenced before check 'asd' (see line 807) Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_fops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index c7ac313a2edf..94ba8acf0e58 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -901,7 +901,7 @@ done: rt_mutex_unlock(&isp->mutex); /* Ensure that a mode is set */ - if (asd && pipe) + if (!acc_node) v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode); return 0; From b467d97ff37c456297c828c4e433c74b65488af1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 10 Nov 2021 11:43:46 +0000 Subject: [PATCH 080/397] media: atomisp: get rid of atomisp_get_frame_pgnr() abstraction Simplify the code by getting rid of this function, as it ends being just a single line of code. Link: https://lore.kernel.org/linux-media/80ea920d14379124ba92aab2e6a6d12a92d79b2b.1636544620.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 16 ---------------- drivers/staging/media/atomisp/pci/atomisp_cmd.h | 2 -- drivers/staging/media/atomisp/pci/atomisp_fops.c | 2 +- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 43e266f26504..72c61c732d53 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -1931,22 +1931,6 @@ out: return IRQ_HANDLED; } -/* - * utils for buffer allocation/free - */ - -int atomisp_get_frame_pgnr(struct atomisp_device *isp, - const struct ia_css_frame *frame, u32 *p_pgnr) -{ - if (!frame) { - dev_err(isp->dev, "%s: NULL frame pointer ERROR.\n", __func__); - return -EINVAL; - } - - *p_pgnr = DIV_ROUND_UP(frame->data_bytes, PAGE_SIZE); - return 0; -} - /* * Get internal fmt according to V4L2 fmt */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index fb848d716947..ebc729468f87 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -74,8 +74,6 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr); const struct atomisp_format_bridge *get_atomisp_format_bridge_from_mbus( u32 mbus_code); bool atomisp_is_mbuscode_raw(uint32_t code); -int atomisp_get_frame_pgnr(struct atomisp_device *isp, - const struct ia_css_frame *frame, u32 *p_pgnr); void atomisp_delayed_init_work(struct work_struct *work); /* Get internal fmt according to V4L2 fmt */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 94ba8acf0e58..be6a74d5ac19 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -1094,7 +1094,7 @@ static int frame_mmap(struct atomisp_device *isp, host_virt = vma->vm_start; isp_virt = frame->data; - atomisp_get_frame_pgnr(isp, frame, &pgnr); + pgnr = DIV_ROUND_UP(frame->data_bytes, PAGE_SIZE); if (do_isp_mm_remap(isp, vma, isp_virt, host_virt, pgnr)) return -EAGAIN; From 352ff3f3d449554f5259f75d77f65e638ea9d4a1 Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Wed, 10 Nov 2021 09:49:10 +0000 Subject: [PATCH 081/397] media: atomisp: Remove unneeded null check In ia_css_frame_map, the check of 'err' is unneeded to be done twice. Link: https://lore.kernel.org/linux-media/20211110094910.67951-1-vulab@iscas.ac.cn Signed-off-by: Xu Wang Signed-off-by: Mauro Carvalho Chehab --- .../atomisp/pci/runtime/frame/src/frame.c | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c index 3c9dd5c03850..e3242652f296 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c +++ b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c @@ -168,26 +168,24 @@ int ia_css_frame_map(struct ia_css_frame **frame, if (err) return err; - if (!err) { - if (pgnr < ((PAGE_ALIGN(me->data_bytes)) >> PAGE_SHIFT)) { - dev_err(atomisp_dev, - "user space memory size is less than the expected size..\n"); - err = -ENOMEM; - goto error; - } else if (pgnr > ((PAGE_ALIGN(me->data_bytes)) >> PAGE_SHIFT)) { - dev_err(atomisp_dev, - "user space memory size is large than the expected size..\n"); - err = -ENOMEM; - goto error; - } - - me->data = hmm_alloc(me->data_bytes, HMM_BO_USER, 0, data, - attribute & ATOMISP_MAP_FLAG_CACHED); - - if (me->data == mmgr_NULL) - err = -EINVAL; + if (pgnr < ((PAGE_ALIGN(me->data_bytes)) >> PAGE_SHIFT)) { + dev_err(atomisp_dev, + "user space memory size is less than the expected size..\n"); + err = -ENOMEM; + goto error; + } else if (pgnr > ((PAGE_ALIGN(me->data_bytes)) >> PAGE_SHIFT)) { + dev_err(atomisp_dev, + "user space memory size is large than the expected size..\n"); + err = -ENOMEM; + goto error; } + me->data = hmm_alloc(me->data_bytes, HMM_BO_USER, 0, data, + attribute & ATOMISP_MAP_FLAG_CACHED); + + if (me->data == mmgr_NULL) + err = -EINVAL; + error: if (err) { kvfree(me); From 62cea52ad4bead0ae4be2cfe1142eb0aae0e9fbd Mon Sep 17 00:00:00 2001 From: Jammy Huang Date: Wed, 3 Nov 2021 08:23:54 +0000 Subject: [PATCH 082/397] media: aspeed: fix mode-detect always time out at 2nd run aspeed_video_get_resolution() will try to do res-detect again if the timing got in last try is invalid. But it will always time out because VE_SEQ_CTRL_TRIG_MODE_DET is only cleared after 1st mode-detect. To fix the problem, just clear VE_SEQ_CTRL_TRIG_MODE_DET before setting it in aspeed_video_enable_mode_detect(). Fixes: d2b4387f3bdf ("media: platform: Add Aspeed Video Engine driver") Signed-off-by: Jammy Huang Acked-by: Paul Menzel Reviewed-by: Joel Stanley Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/aspeed-video.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c index cad3f97515ae..136383ad0e97 100644 --- a/drivers/media/platform/aspeed-video.c +++ b/drivers/media/platform/aspeed-video.c @@ -539,6 +539,10 @@ static void aspeed_video_enable_mode_detect(struct aspeed_video *video) aspeed_video_update(video, VE_INTERRUPT_CTRL, 0, VE_INTERRUPT_MODE_DETECT); + /* Disable mode detect in order to re-trigger */ + aspeed_video_update(video, VE_SEQ_CTRL, + VE_SEQ_CTRL_TRIG_MODE_DET, 0); + /* Trigger mode detect */ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_TRIG_MODE_DET); } @@ -824,10 +828,6 @@ static void aspeed_video_get_resolution(struct aspeed_video *video) return; } - /* Disable mode detect in order to re-trigger */ - aspeed_video_update(video, VE_SEQ_CTRL, - VE_SEQ_CTRL_TRIG_MODE_DET, 0); - aspeed_video_check_and_set_polarity(video); aspeed_video_enable_mode_detect(video); From 20c82fffd6d2bcc35ae63bad81df150b20301ec7 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Thu, 21 Oct 2021 09:41:42 +0100 Subject: [PATCH 083/397] media: gspca: Make use of the helper macro kthread_run() Repalce kthread_create/wake_up_process() with kthread_run() to simplify the code. Signed-off-by: Cai Huoqing Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/m5602/m5602_s5k83a.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c index bc4008d5d116..4504d615b1e4 100644 --- a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c +++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c @@ -339,14 +339,13 @@ int s5k83a_start(struct sd *sd) /* Create another thread, polling the GPIO ports of the camera to check if it got rotated. This is how the windows driver does it so we have to assume that there is no better way of accomplishing this */ - sd->rotation_thread = kthread_create(rotation_thread_function, - sd, "rotation thread"); + sd->rotation_thread = kthread_run(rotation_thread_function, + sd, "rotation thread"); if (IS_ERR(sd->rotation_thread)) { err = PTR_ERR(sd->rotation_thread); sd->rotation_thread = NULL; return err; } - wake_up_process(sd->rotation_thread); /* Preinit the sensor */ for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) { From 901181b7ff1659893f8714a7752465a9b719f19f Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 16 Oct 2021 09:40:29 +0100 Subject: [PATCH 084/397] media: tw5864: Simplify 'tw5864_finidev()' Some resources are allocated with 'pci_request_regions()', so use 'pci_release_regions()' to free them, instead of a verbose 'release_mem_region()'. There is no point in calling 'devm_kfree()'. The corresponding resource is managed, so it will be fried automatically. Signed-off-by: Christophe JAILLET Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw5864/tw5864-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/pci/tw5864/tw5864-core.c b/drivers/media/pci/tw5864/tw5864-core.c index 23d3cae54a5d..fee3b7711901 100644 --- a/drivers/media/pci/tw5864/tw5864-core.c +++ b/drivers/media/pci/tw5864/tw5864-core.c @@ -333,11 +333,9 @@ static void tw5864_finidev(struct pci_dev *pci_dev) /* release resources */ iounmap(dev->mmio); - release_mem_region(pci_resource_start(pci_dev, 0), - pci_resource_len(pci_dev, 0)); + pci_release_regions(pci_dev); v4l2_device_unregister(&dev->v4l2_dev); - devm_kfree(&pci_dev->dev, dev); } static struct pci_driver tw5864_pci_driver = { From 4406c813050727fce157e416851ddee389d0b135 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Fri, 22 Oct 2021 11:06:44 +0100 Subject: [PATCH 085/397] media: tw5864: Disable PCI device when finished The cleanup in tw5864_finidev() neglected to disable the PCI device after enabling it in tw5864_initdev(). Call pci_disable_device() after releasing the associated resources. Signed-off-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw5864/tw5864-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/pci/tw5864/tw5864-core.c b/drivers/media/pci/tw5864/tw5864-core.c index fee3b7711901..5cae73e6fb9c 100644 --- a/drivers/media/pci/tw5864/tw5864-core.c +++ b/drivers/media/pci/tw5864/tw5864-core.c @@ -334,6 +334,7 @@ static void tw5864_finidev(struct pci_dev *pci_dev) /* release resources */ iounmap(dev->mmio); pci_release_regions(pci_dev); + pci_disable_device(pci_dev); v4l2_device_unregister(&dev->v4l2_dev); } From 019b48989f2223320a7ffc4f6631d8b9354051fb Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 23 Oct 2021 11:10:48 +0100 Subject: [PATCH 086/397] media: s5p-mfc: Use 'bitmap_zalloc()' when applicable 'mfc_dev->mem_bitmap' is a bitmap. So use 'bitmap_zalloc()' to simplify code and improve the semantic. Also change the corresponding 'kfree()' into 'bitmap_free()' to keep consistency. Signed-off-by: Christophe JAILLET Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index fc85e4e2d020..f6732f031e96 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1185,7 +1185,6 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; unsigned long mem_size = SZ_4M; - unsigned int bitmap_size; if (IS_ENABLED(CONFIG_DMA_CMA) || exynos_is_iommu_available(dev)) mem_size = SZ_8M; @@ -1193,16 +1192,14 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) if (mfc_mem_size) mem_size = memparse(mfc_mem_size, NULL); - bitmap_size = BITS_TO_LONGS(mem_size >> PAGE_SHIFT) * sizeof(long); - - mfc_dev->mem_bitmap = kzalloc(bitmap_size, GFP_KERNEL); + mfc_dev->mem_bitmap = bitmap_zalloc(mem_size >> PAGE_SHIFT, GFP_KERNEL); if (!mfc_dev->mem_bitmap) return -ENOMEM; mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size, &mfc_dev->mem_base, GFP_KERNEL); if (!mfc_dev->mem_virt) { - kfree(mfc_dev->mem_bitmap); + bitmap_free(mfc_dev->mem_bitmap); dev_err(dev, "failed to preallocate %ld MiB for the firmware and context buffers\n", (mem_size / SZ_1M)); return -ENOMEM; @@ -1241,7 +1238,7 @@ static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev) dma_free_coherent(dev, mfc_dev->mem_size, mfc_dev->mem_virt, mfc_dev->mem_base); - kfree(mfc_dev->mem_bitmap); + bitmap_free(mfc_dev->mem_bitmap); vb2_dma_contig_clear_max_seg_size(dev); } From 91bd11a4a56895a9bf03c0be4ff15bd7caaaee0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 28 Oct 2021 10:37:49 +0100 Subject: [PATCH 087/397] media: dt-bindings: adv748x: Convert bindings to json-schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert ADV748X analog video decoder documentation to json-schema. While converting the bindings extend it to enforce that all port@n nodes shall be encapsulated inside a ports node. This change does not have an effect on drivers parsing the ports@n nodes. Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Reviewed-by: Kieran Bingham Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/adv748x.txt | 116 ---------- .../bindings/media/i2c/adv748x.yaml | 212 ++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 213 insertions(+), 116 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/i2c/adv748x.txt create mode 100644 Documentation/devicetree/bindings/media/i2c/adv748x.yaml diff --git a/Documentation/devicetree/bindings/media/i2c/adv748x.txt b/Documentation/devicetree/bindings/media/i2c/adv748x.txt deleted file mode 100644 index 4f91686e54a6..000000000000 --- a/Documentation/devicetree/bindings/media/i2c/adv748x.txt +++ /dev/null @@ -1,116 +0,0 @@ -* Analog Devices ADV748X video decoder with HDMI receiver - -The ADV7481 and ADV7482 are multi format video decoders with an integrated -HDMI receiver. They can output CSI-2 on two independent outputs TXA and TXB -from three input sources HDMI, analog and TTL. - -Required Properties: - - - compatible: Must contain one of the following - - "adi,adv7481" for the ADV7481 - - "adi,adv7482" for the ADV7482 - - - reg: I2C slave addresses - The ADV748x has up to twelve 256-byte maps that can be accessed via the - main I2C ports. Each map has it own I2C address and acts as a standard - slave device on the I2C bus. The main address is mandatory, others are - optional and remain at default values if not specified. - -Optional Properties: - - - interrupt-names: Should specify the interrupts as "intrq1", "intrq2" and/or - "intrq3". All interrupts are optional. The "intrq3" interrupt - is only available on the adv7481 - - interrupts: Specify the interrupt lines for the ADV748x - - reg-names : Names of maps with programmable addresses. - It shall contain all maps needing a non-default address. - Possible map names are: - "main", "dpll", "cp", "hdmi", "edid", "repeater", - "infoframe", "cbus", "cec", "sdp", "txa", "txb" - -The device node must contain one 'port' child node per device input and output -port, in accordance with the video interface bindings defined in -Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes -are numbered as follows. - - Name Type Port - --------------------------------------- - AIN0 sink 0 - AIN1 sink 1 - AIN2 sink 2 - AIN3 sink 3 - AIN4 sink 4 - AIN5 sink 5 - AIN6 sink 6 - AIN7 sink 7 - HDMI sink 8 - TTL sink 9 - TXA source 10 - TXB source 11 - -The digital output port nodes, when present, shall contain at least one -endpoint. Each of those endpoints shall contain the data-lanes property as -described in video-interfaces.txt. - -Required source endpoint properties: - - data-lanes: an array of physical data lane indexes - The accepted value(s) for this property depends on which of the two - sources are described. For TXA 1, 2 or 4 data lanes can be described - while for TXB only 1 data lane is valid. See video-interfaces.txt - for detailed description. - -Ports are optional if they are not connected to anything at the hardware level. - -Example: - - video-receiver@70 { - compatible = "adi,adv7482"; - reg = <0x70 0x71 0x72 0x73 0x74 0x75 - 0x60 0x61 0x62 0x63 0x64 0x65>; - reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater", - "infoframe", "cbus", "cec", "sdp", "txa", "txb"; - - #address-cells = <1>; - #size-cells = <0>; - - interrupt-parent = <&gpio6>; - interrupt-names = "intrq1", "intrq2"; - interrupts = <30 IRQ_TYPE_LEVEL_LOW>, - <31 IRQ_TYPE_LEVEL_LOW>; - - port@7 { - reg = <7>; - - adv7482_ain7: endpoint { - remote-endpoint = <&cvbs_in>; - }; - }; - - port@8 { - reg = <8>; - - adv7482_hdmi: endpoint { - remote-endpoint = <&hdmi_in>; - }; - }; - - port@a { - reg = <10>; - - adv7482_txa: endpoint { - clock-lanes = <0>; - data-lanes = <1 2 3 4>; - remote-endpoint = <&csi40_in>; - }; - }; - - port@b { - reg = <11>; - - adv7482_txb: endpoint { - clock-lanes = <0>; - data-lanes = <1>; - remote-endpoint = <&csi20_in>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/media/i2c/adv748x.yaml b/Documentation/devicetree/bindings/media/i2c/adv748x.yaml new file mode 100644 index 000000000000..d6353081402b --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/adv748x.yaml @@ -0,0 +1,212 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/adv748x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices ADV748X video decoder with HDMI receiver + +maintainers: + - Kieran Bingham + - Niklas Söderlund + +description: + The ADV7481 and ADV7482 are multi format video decoders with an integrated + HDMI receiver. They can output CSI-2 on two independent outputs TXA and TXB + from three input sources HDMI, analog and TTL. + +properties: + compatible: + items: + - enum: + - adi,adv7481 + - adi,adv7482 + + reg: + minItems: 1 + maxItems: 12 + description: + The ADV748x has up to twelve 256-byte maps that can be accessed via the + main I2C ports. Each map has it own I2C address and acts as a standard + slave device on the I2C bus. The main address is mandatory, others are + optional and remain at default values if not specified. + + reg-names: + minItems: 1 + items: + - const: main + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + - enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ] + + interrupts: true + + interrupt-names: true + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + patternProperties: + "^port@[0-7]$": + $ref: /schemas/graph.yaml#/properties/port + description: Input port nodes for analog inputs AIN[0-7]. + + properties: + port@8: + $ref: /schemas/graph.yaml#/properties/port + description: Input port node for HDMI. + + port@9: + $ref: /schemas/graph.yaml#/properties/port + description: Input port node for TTL. + + port@a: + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Output port node, single endpoint describing the CSI-2 transmitter TXA. + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + clock-lanes: + maxItems: 1 + + data-lanes: + minItems: 1 + maxItems: 4 + + required: + - clock-lanes + - data-lanes + + port@b: + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Output port node, single endpoint describing the CSI-2 transmitter TXB. + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + clock-lanes: + maxItems: 1 + + data-lanes: + maxItems: 1 + + required: + - clock-lanes + - data-lanes + +allOf: + - if: + properties: + compatible: + contains: + const: adi,adv7481 + then: + properties: + interrupts: + minItems: 1 + maxItems: 3 + + interrupt-names: + minItems: 1 + maxItems: 3 + items: + enum: [ intrq1, intrq2, intrq3 ] + else: + properties: + interrupts: + minItems: 1 + maxItems: 2 + + interrupt-names: + minItems: 1 + maxItems: 2 + items: + enum: [ intrq1, intrq2 ] + +additionalProperties: false + +required: + - compatible + - reg + - ports + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + video-receiver@70 { + compatible = "adi,adv7482"; + reg = <0x70 0x71 0x72 0x73 0x74 0x75 + 0x60 0x61 0x62 0x63 0x64 0x65>; + reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater", + "infoframe", "cbus", "cec", "sdp", "txa", "txb"; + + interrupt-parent = <&gpio6>; + interrupts = <30 IRQ_TYPE_LEVEL_LOW>, <31 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "intrq1", "intrq2"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@7 { + reg = <7>; + + adv7482_ain7: endpoint { + remote-endpoint = <&cvbs_in>; + }; + }; + + port@8 { + reg = <8>; + + adv7482_hdmi: endpoint { + remote-endpoint = <&hdmi_in>; + }; + }; + + port@a { + reg = <10>; + + adv7482_txa: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&csi40_in>; + }; + }; + + port@b { + reg = <11>; + + adv7482_txb: endpoint { + clock-lanes = <0>; + data-lanes = <1>; + remote-endpoint = <&csi20_in>; + }; + }; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index bb60cfa5daf7..8eea24d54624 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1139,6 +1139,7 @@ ANALOG DEVICES INC ADV748X DRIVER M: Kieran Bingham L: linux-media@vger.kernel.org S: Maintained +F: Documentation/devicetree/bindings/media/i2c/adv748x.yaml F: drivers/media/i2c/adv748x/* ANALOG DEVICES INC ADV7511 DRIVER From 22be5a10d0b24eec9e45decd15d7e6112b25f080 Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Mon, 1 Nov 2021 09:55:39 +0000 Subject: [PATCH 088/397] media: em28xx: fix memory leak in em28xx_init_dev In the em28xx_init_rev, if em28xx_audio_setup fails, this function fails to deallocate the media_dev allocated in the em28xx_media_device_init. Fix this by adding em28xx_unregister_media_device to free media_dev. BTW, this patch is tested in my local syzkaller instance, and it can prevent the memory leak from occurring again. CC: Pavel Skripkin Fixes: 37ecc7b1278f ("[media] em28xx: add media controller support") Signed-off-by: Dongliang Mu Reported-by: syzkaller Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index b207f34af5c6..b451ce3cb169 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3630,8 +3630,10 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, if (dev->is_audio_only) { retval = em28xx_audio_setup(dev); - if (retval) - return -ENODEV; + if (retval) { + retval = -ENODEV; + goto err_deinit_media; + } em28xx_init_extension(dev); return 0; @@ -3650,7 +3652,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, dev_err(&dev->intf->dev, "%s: em28xx_i2c_register bus 0 - error [%d]!\n", __func__, retval); - return retval; + goto err_deinit_media; } /* register i2c bus 1 */ @@ -3666,9 +3668,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, "%s: em28xx_i2c_register bus 1 - error [%d]!\n", __func__, retval); - em28xx_i2c_unregister(dev, 0); - - return retval; + goto err_unreg_i2c; } } @@ -3676,6 +3676,12 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, em28xx_card_setup(dev); return 0; + +err_unreg_i2c: + em28xx_i2c_unregister(dev, 0); +err_deinit_media: + em28xx_unregister_media_device(dev); + return retval; } static int em28xx_duplicate_dev(struct em28xx *dev) From d7894721f73bf5f135233625985a17043fa836a2 Mon Sep 17 00:00:00 2001 From: Kwang Son Date: Tue, 2 Nov 2021 11:17:47 +0000 Subject: [PATCH 089/397] media: docs: Fix newline typo Fix example code which has missing or double backslash typo. Signed-off-by: Kwang Son Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../userspace-api/media/v4l/capture.c.rst | 52 +++++++++---------- .../userspace-api/media/v4l/v4l2grab.c.rst | 8 +-- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Documentation/userspace-api/media/v4l/capture.c.rst b/Documentation/userspace-api/media/v4l/capture.c.rst index ccbd52c3897f..eef6772967a1 100644 --- a/Documentation/userspace-api/media/v4l/capture.c.rst +++ b/Documentation/userspace-api/media/v4l/capture.c.rst @@ -56,7 +56,7 @@ file: media/v4l/capture.c static void errno_exit(const char *s) { - fprintf(stderr, "%s error %d, %s\\n", s, errno, strerror(errno)); + fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno)); exit(EXIT_FAILURE); } @@ -201,7 +201,7 @@ file: media/v4l/capture.c } if (0 == r) { - fprintf(stderr, "select timeout\\n"); + fprintf(stderr, "select timeout\n"); exit(EXIT_FAILURE); } @@ -307,7 +307,7 @@ file: media/v4l/capture.c buffers = calloc(1, sizeof(*buffers)); if (!buffers) { - fprintf(stderr, "Out of memory\\n"); + fprintf(stderr, "Out of memory\n"); exit(EXIT_FAILURE); } @@ -315,7 +315,7 @@ file: media/v4l/capture.c buffers[0].start = malloc(buffer_size); if (!buffers[0].start) { - fprintf(stderr, "Out of memory\\n"); + fprintf(stderr, "Out of memory\n"); exit(EXIT_FAILURE); } } @@ -341,7 +341,7 @@ file: media/v4l/capture.c } if (req.count < 2) { - fprintf(stderr, "Insufficient buffer memory on %s\\n", + fprintf(stderr, "Insufficient buffer memory on %s\n", dev_name); exit(EXIT_FAILURE); } @@ -349,7 +349,7 @@ file: media/v4l/capture.c buffers = calloc(req.count, sizeof(*buffers)); if (!buffers) { - fprintf(stderr, "Out of memory\\n"); + fprintf(stderr, "Out of memory\n"); exit(EXIT_FAILURE); } @@ -401,7 +401,7 @@ file: media/v4l/capture.c buffers = calloc(4, sizeof(*buffers)); if (!buffers) { - fprintf(stderr, "Out of memory\\n"); + fprintf(stderr, "Out of memory\n"); exit(EXIT_FAILURE); } @@ -410,7 +410,7 @@ file: media/v4l/capture.c buffers[n_buffers].start = malloc(buffer_size); if (!buffers[n_buffers].start) { - fprintf(stderr, "Out of memory\\n"); + fprintf(stderr, "Out of memory\n"); exit(EXIT_FAILURE); } } @@ -426,7 +426,7 @@ file: media/v4l/capture.c if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) { if (EINVAL == errno) { - fprintf(stderr, "%s is no V4L2 device\\n", + fprintf(stderr, "%s is no V4L2 device\n", dev_name); exit(EXIT_FAILURE); } else { @@ -435,7 +435,7 @@ file: media/v4l/capture.c } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { - fprintf(stderr, "%s is no video capture device\\n", + fprintf(stderr, "%s is no video capture device\n", dev_name); exit(EXIT_FAILURE); } @@ -443,7 +443,7 @@ file: media/v4l/capture.c switch (io) { case IO_METHOD_READ: if (!(cap.capabilities & V4L2_CAP_READWRITE)) { - fprintf(stderr, "%s does not support read i/o\\n", + fprintf(stderr, "%s does not support read i/o\n", dev_name); exit(EXIT_FAILURE); } @@ -452,7 +452,7 @@ file: media/v4l/capture.c case IO_METHOD_MMAP: case IO_METHOD_USERPTR: if (!(cap.capabilities & V4L2_CAP_STREAMING)) { - fprintf(stderr, "%s does not support streaming i/o\\n", + fprintf(stderr, "%s does not support streaming i/o\n", dev_name); exit(EXIT_FAILURE); } @@ -541,7 +541,7 @@ file: media/v4l/capture.c struct stat st; if (-1 == stat(dev_name, &st)) { - fprintf(stderr, "Cannot identify '%s': %d, %s\\n", + fprintf(stderr, "Cannot identify '%s': %d, %s\n", dev_name, errno, strerror(errno)); exit(EXIT_FAILURE); } @@ -554,7 +554,7 @@ file: media/v4l/capture.c fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0); if (-1 == fd) { - fprintf(stderr, "Cannot open '%s': %d, %s\\n", + fprintf(stderr, "Cannot open '%s': %d, %s\n", dev_name, errno, strerror(errno)); exit(EXIT_FAILURE); } @@ -563,17 +563,17 @@ file: media/v4l/capture.c static void usage(FILE *fp, int argc, char **argv) { fprintf(fp, - "Usage: %s [options]\\n\\n" - "Version 1.3\\n" - "Options:\\n" - "-d | --device name Video device name [%s]n" - "-h | --help Print this messagen" - "-m | --mmap Use memory mapped buffers [default]n" - "-r | --read Use read() callsn" - "-u | --userp Use application allocated buffersn" - "-o | --output Outputs stream to stdoutn" - "-f | --format Force format to 640x480 YUYVn" - "-c | --count Number of frames to grab [%i]n" + "Usage: %s [options]\n\n" + "Version 1.3\n" + "Options:\n" + "-d | --device name Video device name [%s]\n" + "-h | --help Print this message\n" + "-m | --mmap Use memory mapped buffers [default]\n" + "-r | --read Use read() calls\n" + "-u | --userp Use application allocated buffers\n" + "-o | --output Outputs stream to stdout\n" + "-f | --format Force format to 640x480 YUYV\n" + "-c | --count Number of frames to grab [%i]\n" "", argv[0], dev_name, frame_count); } @@ -659,6 +659,6 @@ file: media/v4l/capture.c stop_capturing(); uninit_device(); close_device(); - fprintf(stderr, "\\n"); + fprintf(stderr, "\n"); return 0; } diff --git a/Documentation/userspace-api/media/v4l/v4l2grab.c.rst b/Documentation/userspace-api/media/v4l/v4l2grab.c.rst index eaa0f95048e7..b38f661da733 100644 --- a/Documentation/userspace-api/media/v4l/v4l2grab.c.rst +++ b/Documentation/userspace-api/media/v4l/v4l2grab.c.rst @@ -46,7 +46,7 @@ file: media/v4l/v4l2grab.c } while (r == -1 && ((errno == EINTR) || (errno == EAGAIN))); if (r == -1) { - fprintf(stderr, "error %d, %s\\n", errno, strerror(errno)); + fprintf(stderr, "error %d, %s\n", errno, strerror(errno)); exit(EXIT_FAILURE); } } @@ -80,11 +80,11 @@ file: media/v4l/v4l2grab.c fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; xioctl(fd, VIDIOC_S_FMT, &fmt); if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) { - printf("Libv4l didn't accept RGB24 format. Can't proceed.\\n"); + printf("Libv4l didn't accept RGB24 format. Can't proceed.\n"); exit(EXIT_FAILURE); } if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480)) - printf("Warning: driver is sending image at %dx%d\\n", + printf("Warning: driver is sending image at %dx%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height); CLEAR(req); @@ -151,7 +151,7 @@ file: media/v4l/v4l2grab.c perror("Cannot open image"); exit(EXIT_FAILURE); } - fprintf(fout, "P6\\n%d %d 255\\n", + fprintf(fout, "P6\n%d %d 255\n", fmt.fmt.pix.width, fmt.fmt.pix.height); fwrite(buffers[buf.index].start, buf.bytesused, 1, fout); fclose(fout); From 0a1c80c6570005ddc516cf649e0ced76c3d680e5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 2 Nov 2021 12:24:27 +0000 Subject: [PATCH 090/397] media: cec-ioc-receive.rst: clarify sequence and status fields Improve the documentation for CEC_RECEIVE/TRANSMIT w.r.t. the sequence and tx/rx_status fields. Also remove a duplicate tx_status description. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/cec/cec-ioc-receive.rst | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/Documentation/userspace-api/media/cec/cec-ioc-receive.rst b/Documentation/userspace-api/media/cec/cec-ioc-receive.rst index bd7f7e7235cb..364938ad34df 100644 --- a/Documentation/userspace-api/media/cec/cec-ioc-receive.rst +++ b/Documentation/userspace-api/media/cec/cec-ioc-receive.rst @@ -48,9 +48,12 @@ it will return -1 and set errno to the ``ETIMEDOUT`` error code. A received message can be: 1. a message received from another CEC device (the ``sequence`` field will - be 0). -2. the result of an earlier non-blocking transmit (the ``sequence`` field will - be non-zero). + be 0, ``tx_status`` will be 0 and ``rx_status`` will be non-zero). +2. the transmit result of an earlier non-blocking transmit (the ``sequence`` + field will be non-zero, ``tx_status`` will be non-zero and ``rx_status`` + will be 0). +3. the reply to an earlier non-blocking transmit (the ``sequence`` field will + be non-zero, ``tx_status`` will be 0 and ``rx_status`` will be non-zero). To send a CEC message the application has to fill in the struct :c:type:`cec_msg` and pass it to :ref:`ioctl CEC_TRANSMIT `. @@ -64,12 +67,11 @@ idea to fully fill up the transmit queue. If the file descriptor is in non-blocking mode then the transmit will return 0 and the result of the transmit will be available via -:ref:`ioctl CEC_RECEIVE ` once the transmit has finished -(including waiting for a reply, if requested). - -The ``sequence`` field is filled in for every transmit and this can be -checked against the received messages to find the corresponding transmit -result. +:ref:`ioctl CEC_RECEIVE ` once the transmit has finished. +If a non-blocking transmit also specified waiting for a reply, then +the reply will arrive in a later message. The ``sequence`` field can +be used to associate both transmit results and replies with the original +transmit. Normally calling :ref:`ioctl CEC_TRANSMIT ` when the physical address is invalid (due to e.g. a disconnect) will return ``ENONET``. @@ -123,17 +125,16 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV'). - ``sequence`` - A non-zero sequence number is automatically assigned by the CEC framework for all transmitted messages. It is used by the CEC framework when it queues - the transmit result (when transmit was called in non-blocking mode). This - allows the application to associate the received message with the original - transmit. + the transmit result for a non-blocking transmit. This allows the application + to associate the received message with the original transmit. + + In addition, if a non-blocking transmit will wait for a reply (ii.e. ``timeout`` + was not 0), then the ``sequence`` field of the reply will be set to the sequence + value of the original transmit. This allows the application to associate the + received message with the original transmit. * - __u32 - ``flags`` - Flags. See :ref:`cec-msg-flags` for a list of available flags. - * - __u8 - - ``tx_status`` - - The status bits of the transmitted message. See - :ref:`cec-tx-status` for the possible status values. It is 0 if - this message was received, not transmitted. * - __u8 - ``msg[16]`` - The message payload. For :ref:`ioctl CEC_TRANSMIT ` this is filled in by the @@ -162,15 +163,17 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV'). * - __u8 - ``rx_status`` - The status bits of the received message. See - :ref:`cec-rx-status` for the possible status values. It is 0 if - this message was transmitted, not received, unless this is the - reply to a transmitted message. In that case both ``rx_status`` - and ``tx_status`` are set. + :ref:`cec-rx-status` for the possible status values. * - __u8 - ``tx_status`` - The status bits of the transmitted message. See - :ref:`cec-tx-status` for the possible status values. It is 0 if - this message was received, not transmitted. + :ref:`cec-tx-status` for the possible status values. + When calling :ref:`ioctl CEC_TRANSMIT ` in non-blocking mode, + this field will be 0 if the transmit started, or non-0 if the transmit + result is known immediately. The latter would be the case when attempting + to transmit a Poll message to yourself. That results in a + :ref:`CEC_TX_STATUS_NACK ` without ever actually + transmitting the Poll message. * - __u8 - ``tx_arb_lost_cnt`` - A counter of the number of transmit attempts that resulted in the From cd9d9377ed235b294a492a094e1666178a5e78fd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 3 Nov 2021 12:28:31 +0000 Subject: [PATCH 091/397] media: v4l2-ioctl.c: readbuffers depends on V4L2_CAP_READWRITE If V4L2_CAP_READWRITE is not set, then readbuffers must be set to 0, otherwise v4l2-compliance will complain. A note on the Fixes tag below: this patch does not really fix that commit, but it can be applied from that commit onwards. For older code there is no guarantee that device_caps is set, so even though this patch would apply, it will not work reliably. Signed-off-by: Hans Verkuil Fixes: 049e684f2de9 (media: v4l2-dev: fix WARN_ON(!vdev->device_caps)) Cc: Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 31d0109ce5a8..69b74d0e8a90 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2090,6 +2090,7 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { + struct video_device *vfd = video_devdata(file); struct v4l2_streamparm *p = arg; v4l2_std_id std; int ret = check_fmt(file, p->type); @@ -2101,7 +2102,8 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; - p->parm.capture.readbuffers = 2; + if (vfd->device_caps & V4L2_CAP_READWRITE) + p->parm.capture.readbuffers = 2; ret = ops->vidioc_g_std(file, fh, &std); if (ret == 0) v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe); From b5150b6ec1cf45c2f499b501b6622a562437ee37 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Thu, 4 Nov 2021 12:24:26 +0000 Subject: [PATCH 092/397] media: mtk-vcodec: Align width and height to 64 bytes Width and height need to 64 bytes aligned when setting the format. Need to make sure all is 64 bytes align when use width and height to calculate buffer size. Signed-off-by: Yunfei Dong Acked-by: Nicolas Dufresne Tested-by: Steve Cho Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h | 1 + drivers/media/platform/mtk-vcodec/vdec/vdec_h264_req_if.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h index 46783516b84a..e08886a600a3 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h @@ -11,6 +11,7 @@ #include #include +#define VCODEC_DEC_ALIGNED_64 64 #define VCODEC_CAPABILITY_4K_DISABLED 0x10 #define VCODEC_DEC_4K_CODED_WIDTH 4096U #define VCODEC_DEC_4K_CODED_HEIGHT 2304U diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_req_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_req_if.c index 946c23088308..5a7eefe639a8 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_req_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_req_if.c @@ -562,8 +562,8 @@ static void get_pic_info(struct vdec_h264_slice_inst *inst, { struct mtk_vcodec_ctx *ctx = inst->ctx; - ctx->picinfo.buf_w = (ctx->picinfo.pic_w + 15) & 0xFFFFFFF0; - ctx->picinfo.buf_h = (ctx->picinfo.pic_h + 31) & 0xFFFFFFE0; + ctx->picinfo.buf_w = ALIGN(ctx->picinfo.pic_w, VCODEC_DEC_ALIGNED_64); + ctx->picinfo.buf_h = ALIGN(ctx->picinfo.pic_h, VCODEC_DEC_ALIGNED_64); ctx->picinfo.fb_sz[0] = ctx->picinfo.buf_w * ctx->picinfo.buf_h; ctx->picinfo.fb_sz[1] = ctx->picinfo.fb_sz[0] >> 1; inst->vsi_ctx.dec.cap_num_planes = From 29ba42670900ed57e6bf79d57d5dd31abc85bc48 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 8 Nov 2021 12:06:52 +0000 Subject: [PATCH 093/397] media: drivers/index.rst: add missing rkisp1 entry The Documentation/driver-api/media/drivers/rkisp1.rst file wasn't referenced in the index.rst file, so it was never included. Add it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/driver-api/media/drivers/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/driver-api/media/drivers/index.rst b/Documentation/driver-api/media/drivers/index.rst index 426cda633bf0..32406490557c 100644 --- a/Documentation/driver-api/media/drivers/index.rst +++ b/Documentation/driver-api/media/drivers/index.rst @@ -21,6 +21,7 @@ Video4Linux (V4L) drivers pvrusb2 pxa_camera radiotrack + rkisp1 saa7134-devel sh_mobile_ceu_camera tuners From af6d1bde395cac174ee71adcd3fa43f6435c7206 Mon Sep 17 00:00:00 2001 From: Jammy Huang Date: Tue, 9 Nov 2021 03:12:27 +0000 Subject: [PATCH 094/397] media: aspeed: Update signal status immediately to ensure sane hw state If res-chg, VE_INTERRUPT_MODE_DETECT_WD irq will be raised. But v4l2_input_status won't be updated to no-signal immediately until aspeed_video_get_resolution() in aspeed_video_resolution_work(). During the period of time, aspeed_video_start_frame() could be called because it doesn't know signal becomes unstable now. If it goes with aspeed_video_init_regs() of aspeed_video_irq_res_change() simultaneously, it will mess up hw state. To fix this problem, v4l2_input_status is updated to no-signal immediately for VE_INTERRUPT_MODE_DETECT_WD irq. Fixes: d2b4387f3bdf ("media: platform: Add Aspeed Video Engine driver") Signed-off-by: Jammy Huang Acked-by: Paul Menzel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/aspeed-video.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c index 136383ad0e97..7a24daf7165a 100644 --- a/drivers/media/platform/aspeed-video.c +++ b/drivers/media/platform/aspeed-video.c @@ -595,6 +595,8 @@ static void aspeed_video_irq_res_change(struct aspeed_video *video, ulong delay) set_bit(VIDEO_RES_CHANGE, &video->flags); clear_bit(VIDEO_FRAME_INPRG, &video->flags); + video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL; + aspeed_video_off(video); aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR); @@ -1375,7 +1377,6 @@ static void aspeed_video_resolution_work(struct work_struct *work) struct delayed_work *dwork = to_delayed_work(work); struct aspeed_video *video = container_of(dwork, struct aspeed_video, res_work); - u32 input_status = video->v4l2_input_status; aspeed_video_on(video); @@ -1388,8 +1389,7 @@ static void aspeed_video_resolution_work(struct work_struct *work) aspeed_video_get_resolution(video); if (video->detected_timings.width != video->active_timings.width || - video->detected_timings.height != video->active_timings.height || - input_status != video->v4l2_input_status) { + video->detected_timings.height != video->active_timings.height) { static const struct v4l2_event ev = { .type = V4L2_EVENT_SOURCE_CHANGE, .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, From 147907e9322406beb5d0da7fd9ff4e789fc38b9f Mon Sep 17 00:00:00 2001 From: Dillon Min Date: Sun, 7 Nov 2021 14:41:44 +0000 Subject: [PATCH 095/397] media: stm32-dma2d: fix compile errors when W=1 remove unused functions to avoid compile errors when W=1. >> drivers/media/platform/stm32/dma2d/dma2d-hw.c:29:20: error: unused function 'reg_set' [-Werror,-Wunused-function] static inline void reg_set(void __iomem *base, u32 reg, u32 mask) >> drivers/media/platform/stm32/dma2d/dma2d-hw.c:34:20: error: unused function 'reg_clear' [-Werror,-Wunused-function] static inline void reg_clear(void __iomem *base, u32 reg, u32 mask) Fixes: bff6e3e2f4c9 ("media: stm32-dma2d: STM32 DMA2D driver") Reported-by: kernel test robot Signed-off-by: Dillon Min Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/stm32/dma2d/dma2d-hw.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/media/platform/stm32/dma2d/dma2d-hw.c b/drivers/media/platform/stm32/dma2d/dma2d-hw.c index 8c1c664ab13b..ea4cc84d8a39 100644 --- a/drivers/media/platform/stm32/dma2d/dma2d-hw.c +++ b/drivers/media/platform/stm32/dma2d/dma2d-hw.c @@ -26,16 +26,6 @@ static inline void reg_write(void __iomem *base, u32 reg, u32 val) writel_relaxed(val, base + reg); } -static inline void reg_set(void __iomem *base, u32 reg, u32 mask) -{ - reg_write(base, reg, reg_read(base, reg) | mask); -} - -static inline void reg_clear(void __iomem *base, u32 reg, u32 mask) -{ - reg_write(base, reg, reg_read(base, reg) & ~mask); -} - static inline void reg_update_bits(void __iomem *base, u32 reg, u32 mask, u32 val) { From d9fbdedc56eabb9c5d49b37d8b1f8189fa48a4c8 Mon Sep 17 00:00:00 2001 From: Dillon Min Date: Thu, 28 Oct 2021 07:40:20 +0100 Subject: [PATCH 096/397] media: stm32-dma2d: fix compile-testing failed get compile-test failed report from lkp@intel.com after the driver submitted. "ld.lld: error: undefined symbol: v4l2_fh_init" so, make CONFIG_STM32_DMA2D depends on CONFIG_VIDEO_DEV and CONFIG_VIDEO_V4L2 to fix this compile error. Fixes: bff6e3e2f4c9 ("media: stm32-dma2d: STM32 DMA2D driver") Reported-by: kernel test robot Signed-off-by: Dillon Min Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 68f16aef8754..9fbdba0fd1e7 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -494,7 +494,8 @@ endif # VIDEO_STI_DELTA config VIDEO_STM32_DMA2D tristate "STM32 Chrom-Art Accelerator (DMA2D)" - depends on (VIDEO_DEV && VIDEO_V4L2 && ARCH_STM32) || COMPILE_TEST + depends on VIDEO_DEV && VIDEO_V4L2 + depends on ARCH_STM32 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV help From 4eb684bd22a2b43f17dd8c9fcbd60ab612512297 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 10 Nov 2021 07:56:11 +0000 Subject: [PATCH 097/397] media: mtk-vcodec: vdec: remove redundant 'pfb' assignment A clang-analyzer warning was reported. >> drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c:133:18: warning: Value stored to 'pfb' during its initialization is never read [clang-analyzer-deadcode.DeadStores] struct vdec_fb *pfb = &framebuf->frame_buffer; ^~~ ~~~~~~~~~~~~~~~~~~~~~~~ Removes the redundant 'pfb' assignment to fix. Reported-by: kernel test robot Signed-off-by: Tzung-Bi Shih Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c index 8f4a1f0a0769..3d9f47555884 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_stateless.c @@ -133,7 +133,6 @@ static struct vdec_fb *vdec_get_cap_buffer(struct mtk_vcodec_ctx *ctx, struct vdec_fb *pfb = &framebuf->frame_buffer; struct vb2_buffer *dst_buf = &vb2_v4l2->vb2_buf; - pfb = &framebuf->frame_buffer; pfb->base_y.va = NULL; pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); pfb->base_y.size = ctx->q_data[MTK_Q_DATA_DST].sizeimage[0]; From 09f4d1513267d0ab712f5d29e7bd136535748709 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 7 Nov 2021 18:19:23 +0000 Subject: [PATCH 098/397] media: correct MEDIA_TEST_SUPPORT help text Fix grammar/wording in the help text for MEDIA_TEST_SUPPORT. Fixes: 4b32216adb01 ("media: split test drivers from platform directory") Signed-off-by: Randy Dunlap Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index b07812657cee..f3f24c63536b 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -141,10 +141,10 @@ config MEDIA_TEST_SUPPORT prompt "Test drivers" if MEDIA_SUPPORT_FILTER default y if !MEDIA_SUPPORT_FILTER help - Those drivers should not be used on production Kernels, but - can be useful on debug ones. It enables several dummy drivers - that simulate a real hardware. Very useful to test userspace - applications and to validate if the subsystem core is doesn't + These drivers should not be used on production kernels, but + can be useful on debug ones. This option enables several dummy drivers + that simulate real hardware. Very useful to test userspace + applications and to validate if the subsystem core doesn't have regressions. Say Y if you want to use some virtual test driver. From 360c887a39cb56e75be4f558b16f1b6409ecb93f Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 14 Oct 2021 19:21:43 +0100 Subject: [PATCH 099/397] media: mtk-vpu: Remove redundant 'flush_workqueue()' calls 'destroy_workqueue()' already drains the queue before destroying it, so there is no need to flush it explicitly. Remove the redundant 'flush_workqueue()' calls. This was generated with coccinelle: @@ expression E; @@ - flush_workqueue(E); destroy_workqueue(E); Signed-off-by: Christophe JAILLET Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vpu/mtk_vpu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c index 7f1647da0ade..7bd715fc844d 100644 --- a/drivers/media/platform/mtk-vpu/mtk_vpu.c +++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c @@ -964,10 +964,8 @@ static int mtk_vpu_remove(struct platform_device *pdev) #ifdef CONFIG_DEBUG_FS debugfs_remove(vpu_debugfs); #endif - if (vpu->wdt.wq) { - flush_workqueue(vpu->wdt.wq); + if (vpu->wdt.wq) destroy_workqueue(vpu->wdt.wq); - } vpu_free_ext_mem(vpu, P_FW); vpu_free_ext_mem(vpu, D_FW); mutex_destroy(&vpu->vpu_mutex); From f1af0c562f74b67d8752005a1d92ff3b855fa99a Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 14 Oct 2021 19:12:35 +0100 Subject: [PATCH 100/397] media: mtk-vcodec: Remove redundant 'flush_workqueue()' calls 'destroy_workqueue()' already drains the queue before destroying it, so there is no need to flush it explicitly. Remove the redundant 'flush_workqueue()' calls. This was generated with coccinelle: @@ expression E; @@ - flush_workqueue(E); destroy_workqueue(E); Signed-off-by: Christophe JAILLET Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 1 - drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c index e6e6a8203eeb..68abb1422c40 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c @@ -390,7 +390,6 @@ static int mtk_vcodec_dec_remove(struct platform_device *pdev) { struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev); - flush_workqueue(dev->decode_workqueue); destroy_workqueue(dev->decode_workqueue); if (media_devnode_is_registered(dev->mdev_dec.devnode)) { diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index eed67394cf46..b576f44ce505 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -461,7 +461,6 @@ static int mtk_vcodec_enc_remove(struct platform_device *pdev) struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev); mtk_v4l2_debug_enter(); - flush_workqueue(dev->encode_workqueue); destroy_workqueue(dev->encode_workqueue); if (dev->m2m_dev_enc) v4l2_m2m_release(dev->m2m_dev_enc); From 220546727ab5acd61d6f307cf4d11998c873db4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 20 Oct 2021 13:59:32 +0100 Subject: [PATCH 101/397] media: rc: ir-spi: Drop empty spi_driver remove callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A driver with a remove callback that just returns 0 behaves identically to a driver with no remove callback at all. So simplify accordingly. Signed-off-by: Uwe Kleine-König Reviewed-by: Kieran Bingham Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-spi.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/rc/ir-spi.c b/drivers/media/rc/ir-spi.c index c58f2d38a458..51aa55a84bb5 100644 --- a/drivers/media/rc/ir-spi.c +++ b/drivers/media/rc/ir-spi.c @@ -152,11 +152,6 @@ static int ir_spi_probe(struct spi_device *spi) return devm_rc_register_device(&spi->dev, idata->rc); } -static int ir_spi_remove(struct spi_device *spi) -{ - return 0; -} - static const struct of_device_id ir_spi_of_match[] = { { .compatible = "ir-spi-led" }, {}, @@ -165,7 +160,6 @@ MODULE_DEVICE_TABLE(of, ir_spi_of_match); static struct spi_driver ir_spi_driver = { .probe = ir_spi_probe, - .remove = ir_spi_remove, .driver = { .name = IR_SPI_DRIVER_NAME, .of_match_table = ir_spi_of_match, From 8985696ad985f5311975d177f83e95127f0523c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Wed, 27 Oct 2021 16:34:30 +0100 Subject: [PATCH 102/397] media: rc: pwm-ir-tx: Switch to atomic PWM API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove legacy PWM interface (pwm_config, pwm_enable, pwm_disable) and replace it for the atomic PWM API. Signed-off-by: Maíra Canal Acked-by: Uwe Kleine-König Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/pwm-ir-tx.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/rc/pwm-ir-tx.c b/drivers/media/rc/pwm-ir-tx.c index 4bc28d2c9cc9..105a9c24f1e3 100644 --- a/drivers/media/rc/pwm-ir-tx.c +++ b/drivers/media/rc/pwm-ir-tx.c @@ -53,22 +53,21 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf, { struct pwm_ir *pwm_ir = dev->priv; struct pwm_device *pwm = pwm_ir->pwm; - int i, duty, period; + struct pwm_state state; + int i; ktime_t edge; long delta; - period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, pwm_ir->carrier); - duty = DIV_ROUND_CLOSEST(pwm_ir->duty_cycle * period, 100); + pwm_init_state(pwm, &state); - pwm_config(pwm, duty, period); + state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, pwm_ir->carrier); + pwm_set_relative_duty_cycle(&state, pwm_ir->duty_cycle, 100); edge = ktime_get(); for (i = 0; i < count; i++) { - if (i % 2) // space - pwm_disable(pwm); - else - pwm_enable(pwm); + state.enabled = !(i % 2); + pwm_apply_state(pwm, &state); edge = ktime_add_us(edge, txbuf[i]); delta = ktime_us_delta(edge, ktime_get()); @@ -76,7 +75,8 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf, usleep_range(delta, delta + 10); } - pwm_disable(pwm); + state.enabled = false; + pwm_apply_state(pwm, &state); return count; } From 99076cd117c4cb51c684c066fb6bb85e23cb0624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Thu, 4 Nov 2021 18:50:18 +0000 Subject: [PATCH 103/397] media: ir-rx51: Switch to atomic PWM API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove legacy PWM interface (pwm_config, pwm_enable, pwm_disable) and replace it for the atomic PWM API. Signed-off-by: Maíra Canal Reviewed-by: Uwe Kleine-König Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-rx51.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c index a0d9c02a7588..a3b145183260 100644 --- a/drivers/media/rc/ir-rx51.c +++ b/drivers/media/rc/ir-rx51.c @@ -19,6 +19,7 @@ struct ir_rx51 { struct rc_dev *rcdev; struct pwm_device *pwm; + struct pwm_state state; struct hrtimer timer; struct device *dev; wait_queue_head_t wqueue; @@ -32,22 +33,20 @@ struct ir_rx51 { static inline void ir_rx51_on(struct ir_rx51 *ir_rx51) { - pwm_enable(ir_rx51->pwm); + ir_rx51->state.enabled = true; + pwm_apply_state(ir_rx51->pwm, &ir_rx51->state); } static inline void ir_rx51_off(struct ir_rx51 *ir_rx51) { - pwm_disable(ir_rx51->pwm); + ir_rx51->state.enabled = false; + pwm_apply_state(ir_rx51->pwm, &ir_rx51->state); } static int init_timing_params(struct ir_rx51 *ir_rx51) { - struct pwm_device *pwm = ir_rx51->pwm; - int duty, period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, ir_rx51->freq); - - duty = DIV_ROUND_CLOSEST(ir_rx51->duty_cycle * period, 100); - - pwm_config(pwm, duty, period); + ir_rx51->state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, ir_rx51->freq); + pwm_set_relative_duty_cycle(&ir_rx51->state, ir_rx51->duty_cycle, 100); return 0; } @@ -242,6 +241,7 @@ static int ir_rx51_probe(struct platform_device *dev) /* Use default, in case userspace does not set the carrier */ ir_rx51.freq = DIV_ROUND_CLOSEST_ULL(pwm_get_period(pwm), NSEC_PER_SEC); + pwm_init_state(pwm, &ir_rx51.state); pwm_put(pwm); hrtimer_init(&ir_rx51.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); From 5efe5721c18c326036ca71bec4fb56472e1f9350 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Tue, 9 Nov 2021 12:55:20 +0000 Subject: [PATCH 104/397] media: rc: ir-hix5hd2: Add the dependency on HAS_IOMEM The helper function devm_platform_ioremap_resource() needs HAS_IOMEM enabled, so add the dependency on HAS_IOMEM. Signed-off-by: Cai Huoqing Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 9506baf3c4c1..c111af820ae4 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -175,7 +175,7 @@ config IR_ENE config IR_HIX5HD2 tristate "Hisilicon hix5hd2 IR remote control" - depends on OF || COMPILE_TEST + depends on (OF && HAS_IOMEM) || COMPILE_TEST help Say Y here if you want to use hisilicon hix5hd2 remote control. To compile this driver as a module, choose M here: the module will be From 652af08aad4223742b43addbc6193428489b8586 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Nov 2021 22:57:05 +0000 Subject: [PATCH 105/397] media: ipu3: drop an unused variable Fix this clang Werror with W=1: drivers/staging/media/ipu3/ipu3-css-params.c:774:8: error: variable 'pin_scale' set but not used [-Werror,-Wunused-but-set-variable] int pin_scale = 0; ^ Reviewed-by: Nathan Chancellor Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/ipu3/ipu3-css-params.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/media/ipu3/ipu3-css-params.c b/drivers/staging/media/ipu3/ipu3-css-params.c index e9d6bd9e9332..d9e3c3785075 100644 --- a/drivers/staging/media/ipu3/ipu3-css-params.c +++ b/drivers/staging/media/ipu3/ipu3-css-params.c @@ -771,7 +771,6 @@ static int imgu_css_osys_calc_frame_and_stripe_params( */ { unsigned int i; - int pin_scale = 0; /*Input resolution */ stripe_params[s].input_width = stripe_input_width_y; @@ -791,8 +790,6 @@ static int imgu_css_osys_calc_frame_and_stripe_params( reso.pin_height[i]; stripe_params[s].output_offset[i] = stripe_offset_out_y; - - pin_scale += frame_params[i].scaled; } else { /* Unscaled pin */ stripe_params[s].output_width[i] = From ea3e24ca30123b6060d6d52a5c74206f0e07e62b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Nov 2021 22:58:38 +0000 Subject: [PATCH 106/397] media: atomisp-gc2235: drop an unused var Fix this clang Werror with W=1: drivers/staging/media/atomisp/i2c/atomisp-gc2235.c:573:6: error: variable 'ret' set but not used [-Werror,-Wunused-but-set-variable] int ret = -1; ^ Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-gc2235.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c index 5e7085264189..0e6b2e6100d1 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c @@ -570,14 +570,16 @@ static int power_ctrl(struct v4l2_subdev *sd, bool flag) static int gpio_ctrl(struct v4l2_subdev *sd, bool flag) { struct gc2235_device *dev = to_gc2235_sensor(sd); - int ret = -1; + int ret; if (!dev || !dev->platform_data) return -ENODEV; - ret |= dev->platform_data->gpio1_ctrl(sd, !flag); + ret = dev->platform_data->gpio1_ctrl(sd, !flag); usleep_range(60, 90); - return dev->platform_data->gpio0_ctrl(sd, flag); + ret |= dev->platform_data->gpio0_ctrl(sd, flag); + + return ret; } static int power_up(struct v4l2_subdev *sd) From 8734c1d948f4ea7025c4ebce7f5c332ee1692697 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Nov 2021 08:46:37 +0000 Subject: [PATCH 107/397] media: atomisp-ov2680: uncomment other resolutions There are several resolutions defined for this sensor, but just two are currently uncommented. Change the driver to allow other resolutions to also be used. Reviewed-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/ov2680.h | 159 ++++++++++++++++++++- 1 file changed, 153 insertions(+), 6 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index e53be612a1e4..ed68510bb0b9 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -282,7 +282,6 @@ static struct ov2680_reg const ov2680_global_setting[] = { {} }; -#if 0 /* None of the definitions below are used currently */ /* * 176x144 30fps VBlanking 1lane 10Bit (binning) */ @@ -442,7 +441,7 @@ static struct ov2680_reg const ov2680_656x496_30fps[] = { }; /* - * 800x600 30fps VBlanking 1lane 10Bit (binning) + * 720x592 30fps VBlanking 1lane 10Bit (binning) */ static struct ov2680_reg const ov2680_720x592_30fps[] = { {0x3086, 0x01}, @@ -637,7 +636,6 @@ static struct ov2680_reg const ov2680_1456x1096_30fps[] = { // {0x5090, 0x0c}, {} }; -#endif /* *1616x916 30fps VBlanking 1lane 10bit @@ -680,9 +678,8 @@ static struct ov2680_reg const ov2680_1616x916_30fps[] = { }; /* - * 1612x1212 30fps VBlanking 1lane 10Bit + * 1616x1082 30fps VBlanking 1lane 10Bit */ -#if 0 static struct ov2680_reg const ov2680_1616x1082_30fps[] = { {0x3086, 0x00}, {0x370a, 0x21}, @@ -718,7 +715,7 @@ static struct ov2680_reg const ov2680_1616x1082_30fps[] = { {0x5081, 0x41}, {} }; -#endif + /* * 1616x1216 30fps VBlanking 1lane 10Bit */ @@ -774,6 +771,21 @@ static struct ov2680_resolution ov2680_res_preview[] = { .skip_frames = 3, .regs = ov2680_1616x1216_30fps, }, + { + .desc = "ov2680_1616x1082_30fps", + .width = 1616, + .height = 1082, + .pix_clk_freq = 66, + .fps = 30, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_1616x1082_30fps, + }, { .desc = "ov2680_1616x916_30fps", .width = 1616, @@ -789,6 +801,141 @@ static struct ov2680_resolution ov2680_res_preview[] = { .skip_frames = 3, .regs = ov2680_1616x916_30fps, }, + { + .desc = "ov2680_1456x1096_30fps", + .width = 1456, + .height = 1096, + .fps = 30, + .pix_clk_freq = 66, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_1456x1096_30fps, + }, + { + .desc = "ov2680_1296x976_30fps", + .width = 1296, + .height = 976, + .fps = 30, + .pix_clk_freq = 66, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_1296x976_30fps, + }, + { + .desc = "ov2680_720p_30fps", + .width = 1280, + .height = 720, + .fps = 30, + .pix_clk_freq = 66, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_720p_30fps, + }, + { + .desc = "ov2680_800x600_30fps", + .width = 800, + .height = 600, + .fps = 30, + .pix_clk_freq = 66, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_800x600_30fps, + }, + { + .desc = "ov2680_720x592_30fps", + .width = 720, + .height = 592, + .fps = 30, + .pix_clk_freq = 66, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_720x592_30fps, + }, + { + .desc = "ov2680_656x496_30fps", + .width = 656, + .height = 496, + .fps = 30, + .pix_clk_freq = 66, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_656x496_30fps, + }, + { + .desc = "ov2680_QVGA_30fps", + .width = 336, + .height = 256, + .fps = 30, + .pix_clk_freq = 66, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_QVGA_30fps, + }, + { + .desc = "ov2680_CIF_30fps", + .width = 352, + .height = 288, + .fps = 30, + .pix_clk_freq = 66, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_CIF_30fps, + }, + { + .desc = "ov2680_QCIF_30fps", + .width = 176, + .height = 144, + .fps = 30, + .pix_clk_freq = 66, + .used = 0, + .pixels_per_line = 1698,//1704, + .lines_per_frame = 1294, + .bin_factor_x = 0, + .bin_factor_y = 0, + .bin_mode = 0, + .skip_frames = 3, + .regs = ov2680_QCIF_30fps, + }, }; #define N_RES_PREVIEW (ARRAY_SIZE(ov2680_res_preview)) From 04da0010c097ae01187a530f8717890ac6b6a41f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Nov 2021 08:50:53 +0000 Subject: [PATCH 108/397] media: atomisp-ov2680: remove some unused fields The sensor resolution arrays have two unused fields. Drop them. Reviewed-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/ov2680.h | 26 ---------------------- 1 file changed, 26 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index ed68510bb0b9..cb3c37d1c38e 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -141,7 +141,6 @@ struct regval_list { }; struct ov2680_resolution { - u8 *desc; const struct ov2680_reg *regs; int res; int width; @@ -154,7 +153,6 @@ struct ov2680_resolution { u8 bin_factor_x; u8 bin_factor_y; u8 bin_mode; - bool used; }; struct ov2680_format { @@ -757,12 +755,10 @@ static struct ov2680_reg const ov2680_1616x1216_30fps[] = { static struct ov2680_resolution ov2680_res_preview[] = { { - .desc = "ov2680_1616x1216_30fps", .width = 1616, .height = 1216, .pix_clk_freq = 66, .fps = 30, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -772,12 +768,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_1616x1216_30fps, }, { - .desc = "ov2680_1616x1082_30fps", .width = 1616, .height = 1082, .pix_clk_freq = 66, .fps = 30, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -787,12 +781,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_1616x1082_30fps, }, { - .desc = "ov2680_1616x916_30fps", .width = 1616, .height = 916, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -802,12 +794,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_1616x916_30fps, }, { - .desc = "ov2680_1456x1096_30fps", .width = 1456, .height = 1096, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -817,12 +807,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_1456x1096_30fps, }, { - .desc = "ov2680_1296x976_30fps", .width = 1296, .height = 976, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -832,12 +820,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_1296x976_30fps, }, { - .desc = "ov2680_720p_30fps", .width = 1280, .height = 720, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -847,12 +833,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_720p_30fps, }, { - .desc = "ov2680_800x600_30fps", .width = 800, .height = 600, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -862,12 +846,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_800x600_30fps, }, { - .desc = "ov2680_720x592_30fps", .width = 720, .height = 592, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -877,12 +859,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_720x592_30fps, }, { - .desc = "ov2680_656x496_30fps", .width = 656, .height = 496, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -892,12 +872,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_656x496_30fps, }, { - .desc = "ov2680_QVGA_30fps", .width = 336, .height = 256, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -907,12 +885,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_QVGA_30fps, }, { - .desc = "ov2680_CIF_30fps", .width = 352, .height = 288, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, @@ -922,12 +898,10 @@ static struct ov2680_resolution ov2680_res_preview[] = { .regs = ov2680_CIF_30fps, }, { - .desc = "ov2680_QCIF_30fps", .width = 176, .height = 144, .fps = 30, .pix_clk_freq = 66, - .used = 0, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, .bin_factor_x = 0, From dd8e6adb9b5dff3b01813dbc1216e438ed1414cf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Nov 2021 10:21:22 +0000 Subject: [PATCH 109/397] media: atomisp-ov2680: adjust the maximum frame rate The ov2680 supports a maximum bandwidth of 660Mbps and allows up to 60fps when the resolution is below 720p. Adjust the sensor's table to reflect that. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/ov2680.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index cb3c37d1c38e..4e351196fe34 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -822,7 +822,7 @@ static struct ov2680_resolution ov2680_res_preview[] = { { .width = 1280, .height = 720, - .fps = 30, + .fps = 60, .pix_clk_freq = 66, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, @@ -835,7 +835,7 @@ static struct ov2680_resolution ov2680_res_preview[] = { { .width = 800, .height = 600, - .fps = 30, + .fps = 60, .pix_clk_freq = 66, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, @@ -848,7 +848,7 @@ static struct ov2680_resolution ov2680_res_preview[] = { { .width = 720, .height = 592, - .fps = 30, + .fps = 60, .pix_clk_freq = 66, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, @@ -861,7 +861,7 @@ static struct ov2680_resolution ov2680_res_preview[] = { { .width = 656, .height = 496, - .fps = 30, + .fps = 60, .pix_clk_freq = 66, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, @@ -874,7 +874,7 @@ static struct ov2680_resolution ov2680_res_preview[] = { { .width = 336, .height = 256, - .fps = 30, + .fps = 60, .pix_clk_freq = 66, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, @@ -887,7 +887,7 @@ static struct ov2680_resolution ov2680_res_preview[] = { { .width = 352, .height = 288, - .fps = 30, + .fps = 60, .pix_clk_freq = 66, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, @@ -900,7 +900,7 @@ static struct ov2680_resolution ov2680_res_preview[] = { { .width = 176, .height = 144, - .fps = 30, + .fps = 60, .pix_clk_freq = 66, .pixels_per_line = 1698,//1704, .lines_per_frame = 1294, From d45d97873b8e4a005701bdbc3d916f368f95bc60 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Nov 2021 10:15:44 +0000 Subject: [PATCH 110/397] media: atomisp-ov2680: implement enum frame intervals Allow the sensor to report the per-resolution frame interval. It should be noticed that, despite the ov2680 datasheet says that, for resolutions <= 1280x720, the sensor supports 60fps, the data at ov2680.h tells otherwise, limiting it to 30fps. Not sure yet if this is a limitation of atomisp or if it is just because the tables are incorrect. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index d24f8830fd94..4ba99c660681 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -1075,6 +1075,26 @@ static int ov2680_enum_frame_size(struct v4l2_subdev *sd, return 0; } +static int ov2680_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct v4l2_fract fract; + + if (fie->index >= N_RES_PREVIEW || + fie->width > ov2680_res_preview[0].width || + fie->height > ov2680_res_preview[0].height || + fie->which > V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + fract.denominator = ov2680_res_preview[fie->index].fps; + fract.numerator = 1; + + fie->interval = fract; + + return 0; +} + static int ov2680_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) { struct ov2680_device *dev = to_ov2680_sensor(sd); @@ -1103,6 +1123,7 @@ static const struct v4l2_subdev_core_ops ov2680_core_ops = { static const struct v4l2_subdev_pad_ops ov2680_pad_ops = { .enum_mbus_code = ov2680_enum_mbus_code, .enum_frame_size = ov2680_enum_frame_size, + .enum_frame_interval = ov2680_enum_frame_interval, .get_fmt = ov2680_get_fmt, .set_fmt = ov2680_set_fmt, }; From 363d50b73dd8189615994877953f02adbe6fcf02 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Nov 2021 11:04:31 +0000 Subject: [PATCH 111/397] media: atomisp: implement enum framesize/frameinterval Add logic to enumerate sensor's frame size and interval. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 2fb64d5cbead..b2d3b8349234 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -766,6 +766,57 @@ error: return ret; } +static int atomisp_enum_framesizes(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + struct video_device *vdev = video_devdata(file); + struct atomisp_device *isp = video_get_drvdata(vdev); + struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct v4l2_subdev_frame_size_enum fse = { + .index = fsize->index, + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + int ret; + + ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, + pad, enum_frame_size, NULL, &fse); + if (ret) + return ret; + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fse.max_width - pad_w; + fsize->discrete.height = fse.max_height - pad_h; + + return 0; +} + +static int atomisp_enum_frameintervals(struct file *file, void *priv, + struct v4l2_frmivalenum *fival) +{ + struct video_device *vdev = video_devdata(file); + struct atomisp_device *isp = video_get_drvdata(vdev); + struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct v4l2_subdev_frame_interval_enum fie = { + .code = atomisp_in_fmt_conv[0].code, + .index = fival->index, + .width = fival->width, + .height = fival->height, + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + int ret; + + ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, + pad, enum_frame_interval, NULL, + &fie); + if (ret) + return ret; + + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; + fival->discrete = fie.interval; + + return ret; +} + static int atomisp_enum_fmt_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) { @@ -3214,6 +3265,8 @@ const struct v4l2_ioctl_ops atomisp_ioctl_ops = { .vidioc_g_ctrl = atomisp_g_ctrl, .vidioc_s_ext_ctrls = atomisp_s_ext_ctrls, .vidioc_g_ext_ctrls = atomisp_g_ext_ctrls, + .vidioc_enum_framesizes = atomisp_enum_framesizes, + .vidioc_enum_frameintervals = atomisp_enum_frameintervals, .vidioc_enum_fmt_vid_cap = atomisp_enum_fmt_cap, .vidioc_try_fmt_vid_cap = atomisp_try_fmt_cap, .vidioc_g_fmt_vid_cap = atomisp_g_fmt_cap, From 58043dbf6d1ae9deab4f5aa1e039c70112017682 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Nov 2021 23:04:09 +0000 Subject: [PATCH 112/397] media: atomisp: handle errors at sh_css_create_isp_params() The succ var tracks memory allocation erros on this function. Fix it, in order to stop this W=1 Werror in clang: drivers/staging/media/atomisp/pci/sh_css_params.c:2430:7: error: variable 'succ' set but not used [-Werror,-Wunused-but-set-variable] bool succ = true; ^ Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css_params.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c index dbd3bfe3d343..ccc007879564 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/sh_css_params.c @@ -2431,7 +2431,7 @@ sh_css_create_isp_params(struct ia_css_stream *stream, unsigned int i; struct sh_css_ddr_address_map *ddr_ptrs; struct sh_css_ddr_address_map_size *ddr_ptrs_size; - int err = 0; + int err; size_t params_size; struct ia_css_isp_parameters *params = kvmalloc(sizeof(struct ia_css_isp_parameters), GFP_KERNEL); @@ -2473,7 +2473,11 @@ sh_css_create_isp_params(struct ia_css_stream *stream, succ &= (ddr_ptrs->macc_tbl != mmgr_NULL); *isp_params_out = params; - return err; + + if (!succ) + return -ENOMEM; + + return 0; } static bool From bcc3ba664931f1213bfc96f3fe7cfbfc20d49d49 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Nov 2021 11:43:17 +0000 Subject: [PATCH 113/397] media: atomisp: get rid of phys event abstractions ia_css_dequeue_event() is just an alias to ia_css_dequeue_psys_event(), and atomisp_css_dequeue_event() do nothing but calling the event dequeue logic. Get rid of both abstractions, calling the function directly. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 2 +- .../staging/media/atomisp/pci/atomisp_compat.h | 2 -- .../media/atomisp/pci/atomisp_compat_css20.c | 10 +--------- .../media/atomisp/pci/ia_css_event_public.h | 17 +---------------- drivers/staging/media/atomisp/pci/sh_css.c | 6 ------ 5 files changed, 3 insertions(+), 34 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 72c61c732d53..4783590969b6 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -1881,7 +1881,7 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr) /* * The standard CSS2.0 API tells the following calling sequence of * dequeue ready buffers: - * while (ia_css_dequeue_event(...)) { + * while (ia_css_dequeue_psys_event(...)) { * switch (event.type) { * ... * ia_css_pipe_dequeue_buffer() diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h index c16eaf3d126f..64c1bf0943e6 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h @@ -133,8 +133,6 @@ void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd, struct atomisp_css_buffer *isp_css_buffer, struct ia_css_isp_dvs_statistics_map *dvs_map); -int atomisp_css_dequeue_event(struct atomisp_css_event *current_event); - void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd, struct atomisp_css_event *current_event); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index da177a8e78e3..7edee293b132 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -1633,14 +1633,6 @@ void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd, } } -int atomisp_css_dequeue_event(struct atomisp_css_event *current_event) -{ - if (ia_css_dequeue_event(¤t_event->event)) - return -EINVAL; - - return 0; -} - void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd, struct atomisp_css_event *current_event) { @@ -4120,7 +4112,7 @@ int atomisp_css_isr_thread(struct atomisp_device *isp, bool reset_wdt_timer[MAX_STREAM_NUM] = {false}; int i; - while (!atomisp_css_dequeue_event(¤t_event)) { + while (!ia_css_dequeue_psys_event(¤t_event.event)) { if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_ASSERT) { /* diff --git a/drivers/staging/media/atomisp/pci/ia_css_event_public.h b/drivers/staging/media/atomisp/pci/ia_css_event_public.h index 08ea801dd5ac..76219d741d2e 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_event_public.h +++ b/drivers/staging/media/atomisp/pci/ia_css_event_public.h @@ -157,21 +157,6 @@ struct ia_css_event { int ia_css_dequeue_psys_event(struct ia_css_event *event); -/* @brief Dequeue an event from the CSS system. - * - * @param[out] event Pointer to the event struct which will be filled by - * this function if an event is available. - * @return -ENODATA if no events are - * available or - * 0 otherwise. - * - * deprecated{Use ia_css_dequeue_psys_event instead}. - * Unless the isys event queue is explicitly enabled, this function will - * dequeue both isys (EOF) and psys events (all others). - */ -int -ia_css_dequeue_event(struct ia_css_event *event); - /* @brief Dequeue an ISYS event from the CSS system. * * @param[out] event Pointer to the event struct which will be filled by @@ -182,7 +167,7 @@ ia_css_dequeue_event(struct ia_css_event *event); * * This function dequeues an event from the ISYS event queue. The queue is * between host and the CSS system. - * Unlike the ia_css_dequeue_event() function, this function can be called + * Unlike the ia_css_dequeue_psys_event() function, this function can be called * directly from an interrupt service routine (ISR) and it is safe to call * this function in parallel with other CSS API functions (but only one * call to this function should be in flight at any point in time). diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 79003077f390..c714c15c49d2 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -4423,12 +4423,6 @@ static enum ia_css_event_type convert_event_sp_to_host_domain[] = { 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */ }; -int -ia_css_dequeue_event(struct ia_css_event *event) -{ - return ia_css_dequeue_psys_event(event); -} - int ia_css_dequeue_psys_event(struct ia_css_event *event) { From 77db47351071a1e1b53b17510480ae2eefb4f074 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 14 Nov 2021 09:23:21 +0000 Subject: [PATCH 114/397] media: atomisp: get rid of if CONFIG_ON_FRAME_ENQUEUE This is not used with supported firmwares, so get rid of such code. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 38 ------------------- .../media/atomisp/pci/sh_css_internal.h | 12 ------ 2 files changed, 50 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index c714c15c49d2..bd3f96bd7d6d 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -384,10 +384,6 @@ ia_css_get_acc_configs( struct ia_css_pipe *pipe, struct ia_css_isp_config *config); -#if CONFIG_ON_FRAME_ENQUEUE() -static int set_config_on_frame_enqueue(struct ia_css_frame_info - *info, struct frame_data_wrapper *frame); -#endif #ifdef ISP2401 static unsigned int get_crop_lines_for_bayer_order(const struct @@ -4071,15 +4067,6 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n", buf_type, buffer->data.frame->data); -#if CONFIG_ON_FRAME_ENQUEUE() - return_err = set_config_on_frame_enqueue( - &buffer->data.frame->info, - &ddr_buffer.payload.frame); - if (return_err) { - IA_CSS_LEAVE_ERR(return_err); - return return_err; - } -#endif } /* start of test for using rmgr for acq/rel memory */ @@ -10311,31 +10298,6 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) IA_CSS_LEAVE(""); } -#if CONFIG_ON_FRAME_ENQUEUE() -static int set_config_on_frame_enqueue(struct ia_css_frame_info - *info, struct frame_data_wrapper *frame) -{ - frame->config_on_frame_enqueue.padded_width = 0; - - /* currently we support configuration on frame enqueue only on YUV formats */ - /* on other formats the padded_width is zeroed for no configuration override */ - switch (info->format) { - case IA_CSS_FRAME_FORMAT_YUV420: - case IA_CSS_FRAME_FORMAT_NV12: - if (info->padded_width > info->res.width) - frame->config_on_frame_enqueue.padded_width = info->padded_width; - else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) - return -EINVAL; - - /* nothing to do if width == padded width or padded width is zeroed (the same) */ - break; - default: - break; - } - - return 0; -} -#endif int ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) diff --git a/drivers/staging/media/atomisp/pci/sh_css_internal.h b/drivers/staging/media/atomisp/pci/sh_css_internal.h index 92fb7e67610c..f26df3f44a7a 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_internal.h +++ b/drivers/staging/media/atomisp/pci/sh_css_internal.h @@ -687,8 +687,6 @@ struct sh_css_sp_output { unsigned int sw_interrupt_value[SH_CSS_NUM_SDW_IRQS]; }; -#define CONFIG_ON_FRAME_ENQUEUE() 0 - /** * @brief Data structure for the circular buffer. * The circular buffer is empty if "start == end". The @@ -726,9 +724,6 @@ struct sh_css_hmm_buffer { u32 exp_id; u32 isp_parameters_id; /** Unique ID to track which config was actually applied to a particular frame */ -#if CONFIG_ON_FRAME_ENQUEUE() - struct sh_css_config_on_frame_enqueue config_on_frame_enqueue; -#endif } frame; ia_css_ptr ddr_ptrs; } payload; @@ -744,16 +739,9 @@ struct sh_css_hmm_buffer { clock_value_t isys_eof_clock_tick; }; -#if CONFIG_ON_FRAME_ENQUEUE() -#define SIZE_OF_FRAME_STRUCT \ - (SIZE_OF_HRT_VADDRESS + \ - (3 * sizeof(uint32_t)) + \ - sizeof(uint32_t)) -#else #define SIZE_OF_FRAME_STRUCT \ (SIZE_OF_HRT_VADDRESS + \ (3 * sizeof(uint32_t))) -#endif #define SIZE_OF_PAYLOAD_UNION \ (MAX(MAX(MAX(MAX( \ From 4005ecee616a51cb0305d8e3664af45376e7cf65 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 14 Nov 2021 11:06:24 +0000 Subject: [PATCH 115/397] media: atomisp: shift some structs from input_system_local There are several stucts under ISP2400 that could be moved to the global file without causing any build issues. Move those to the common header, in order to reduce the number of things that are #ifdef dependent. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/input_system_local.h | 134 ++++++++++++++++++ .../atomisp/pci/isp2400_input_system_local.h | 126 ---------------- .../atomisp/pci/isp2401_input_system_local.h | 26 ---- 3 files changed, 134 insertions(+), 152 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/input_system_local.h b/drivers/staging/media/atomisp/pci/input_system_local.h index b33aa2838290..357987d629cd 100644 --- a/drivers/staging/media/atomisp/pci/input_system_local.h +++ b/drivers/staging/media/atomisp/pci/input_system_local.h @@ -4,6 +4,140 @@ * (c) 2020 Mauro Carvalho Chehab */ +#include "type_support.h" +#include "input_system_global.h" + +typedef enum { + INPUT_SYSTEM_PORT_A = 0, + INPUT_SYSTEM_PORT_B, + INPUT_SYSTEM_PORT_C, + N_INPUT_SYSTEM_PORTS +} input_system_csi_port_t; + +typedef struct ctrl_unit_cfg_s ctrl_unit_cfg_t; +typedef struct input_system_network_cfg_s input_system_network_cfg_t; +typedef struct target_cfg2400_s target_cfg2400_t; +typedef struct channel_cfg_s channel_cfg_t; +typedef struct backend_channel_cfg_s backend_channel_cfg_t; +typedef struct input_system_cfg2400_s input_system_cfg2400_t; +typedef struct mipi_port_state_s mipi_port_state_t; +typedef struct rx_channel_state_s rx_channel_state_t; +typedef struct input_switch_cfg_channel_s input_switch_cfg_channel_t; +typedef struct input_switch_cfg_s input_switch_cfg_t; + +struct ctrl_unit_cfg_s { + isp2400_ib_buffer_t buffer_mipi[N_CAPTURE_UNIT_ID]; + isp2400_ib_buffer_t buffer_acquire[N_ACQUISITION_UNIT_ID]; +}; + +struct input_system_network_cfg_s { + input_system_connection_t multicast_cfg[N_CAPTURE_UNIT_ID]; + input_system_multiplex_t mux_cfg; + ctrl_unit_cfg_t ctrl_unit_cfg[N_CTRL_UNIT_ID]; +}; + +typedef struct { +// TBD. + u32 dummy_parameter; +} target_isp_cfg_t; + +typedef struct { +// TBD. + u32 dummy_parameter; +} target_sp_cfg_t; + +typedef struct { +// TBD. + u32 dummy_parameter; +} target_strm2mem_cfg_t; + +struct input_switch_cfg_channel_s { + u32 hsync_data_reg[2]; + u32 vsync_data_reg; +}; + +struct backend_channel_cfg_s { + u32 fmt_control_word_1; // Format config. + u32 fmt_control_word_2; + u32 no_side_band; +}; + +typedef union { + csi_cfg_t csi_cfg; + tpg_cfg_t tpg_cfg; + prbs_cfg_t prbs_cfg; + gpfifo_cfg_t gpfifo_cfg; +} source_cfg_t; + +struct input_switch_cfg_s { + u32 hsync_data_reg[N_RX_CHANNEL_ID * 2]; + u32 vsync_data_reg; +}; + +/* + * In 2300 ports can be configured independently and stream + * formats need to be specified. In 2400, there are only 8 + * supported configurations but the HW is fused to support + * only a single one. + * + * In 2300 the compressed format types are programmed by the + * user. In 2400 all stream formats are encoded on the stream. + * + * Use the enum to check validity of a user configuration + */ +typedef enum { + MONO_4L_1L_0L = 0, + MONO_3L_1L_0L, + MONO_2L_1L_0L, + MONO_1L_1L_0L, + STEREO_2L_1L_2L, + STEREO_3L_1L_1L, + STEREO_2L_1L_1L, + STEREO_1L_1L_1L, + N_RX_MODE +} rx_mode_t; + +#define UNCOMPRESSED_BITS_PER_PIXEL_10 10 +#define UNCOMPRESSED_BITS_PER_PIXEL_12 12 +#define COMPRESSED_BITS_PER_PIXEL_6 6 +#define COMPRESSED_BITS_PER_PIXEL_7 7 +#define COMPRESSED_BITS_PER_PIXEL_8 8 +enum mipi_compressor { + MIPI_COMPRESSOR_NONE = 0, + MIPI_COMPRESSOR_10_6_10, + MIPI_COMPRESSOR_10_7_10, + MIPI_COMPRESSOR_10_8_10, + MIPI_COMPRESSOR_12_6_12, + MIPI_COMPRESSOR_12_7_12, + MIPI_COMPRESSOR_12_8_12, + N_MIPI_COMPRESSOR_METHODS +}; + +typedef enum mipi_compressor mipi_compressor_t; + +typedef enum { + MIPI_PREDICTOR_NONE = 0, + MIPI_PREDICTOR_TYPE1, + MIPI_PREDICTOR_TYPE2, + N_MIPI_PREDICTOR_TYPES +} mipi_predictor_t; + +typedef struct rx_cfg_s rx_cfg_t; + +/* + * Applied per port + */ +struct rx_cfg_s { + rx_mode_t mode; /* The HW config */ + enum mipi_port_id port; /* The port ID to apply the control on */ + unsigned int timeout; + unsigned int initcount; + unsigned int synccount; + unsigned int rxcount; + mipi_predictor_t comp; /* Just for backward compatibility */ + bool is_two_ppc; +}; + #ifdef ISP2401 # include "isp2401_input_system_local.h" #else diff --git a/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h b/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h index 2614b89b8e34..6880c9b6aa65 100644 --- a/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h +++ b/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h @@ -16,10 +16,6 @@ #ifndef __INPUT_SYSTEM_LOCAL_H_INCLUDED__ #define __INPUT_SYSTEM_LOCAL_H_INCLUDED__ -#include - -#include "input_system_global.h" - #include "input_system_defs.h" /* HIVE_ISYS_GPREG_MULTICAST_A_IDX,... */ /* @@ -33,54 +29,7 @@ #include "isp_acquisition_defs.h" #include "input_system_ctrl_defs.h" -typedef enum { - INPUT_SYSTEM_PORT_A = 0, - INPUT_SYSTEM_PORT_B, - INPUT_SYSTEM_PORT_C, - N_INPUT_SYSTEM_PORTS -} input_system_csi_port_t; - -typedef struct ctrl_unit_cfg_s ctrl_unit_cfg_t; -typedef struct input_system_network_cfg_s input_system_network_cfg_t; -typedef struct target_cfg2400_s target_cfg2400_t; -typedef struct channel_cfg_s channel_cfg_t; -typedef struct backend_channel_cfg_s backend_channel_cfg_t; typedef struct input_system_cfg2400_s input_system_cfg2400_t; -typedef struct mipi_port_state_s mipi_port_state_t; -typedef struct rx_channel_state_s rx_channel_state_t; -typedef struct input_switch_cfg_channel_s input_switch_cfg_channel_t; -typedef struct input_switch_cfg_s input_switch_cfg_t; - -struct ctrl_unit_cfg_s { - isp2400_ib_buffer_t buffer_mipi[N_CAPTURE_UNIT_ID]; - isp2400_ib_buffer_t buffer_acquire[N_ACQUISITION_UNIT_ID]; -}; - -struct input_system_network_cfg_s { - input_system_connection_t multicast_cfg[N_CAPTURE_UNIT_ID]; - input_system_multiplex_t mux_cfg; - ctrl_unit_cfg_t ctrl_unit_cfg[N_CTRL_UNIT_ID]; -}; - -typedef struct { -// TBD. - u32 dummy_parameter; -} target_isp_cfg_t; - -typedef struct { -// TBD. - u32 dummy_parameter; -} target_sp_cfg_t; - -typedef struct { -// TBD. - u32 dummy_parameter; -} target_strm2mem_cfg_t; - -struct input_switch_cfg_channel_s { - u32 hsync_data_reg[2]; - u32 vsync_data_reg; -}; struct target_cfg2400_s { input_switch_cfg_channel_t input_switch_channel_cfg; @@ -89,24 +38,6 @@ struct target_cfg2400_s { target_strm2mem_cfg_t target_strm2mem_cfg; }; -struct backend_channel_cfg_s { - u32 fmt_control_word_1; // Format config. - u32 fmt_control_word_2; - u32 no_side_band; -}; - -typedef union { - csi_cfg_t csi_cfg; - tpg_cfg_t tpg_cfg; - prbs_cfg_t prbs_cfg; - gpfifo_cfg_t gpfifo_cfg; -} source_cfg_t; - -struct input_switch_cfg_s { - u32 hsync_data_reg[N_RX_CHANNEL_ID * 2]; - u32 vsync_data_reg; -}; - // Configuration of a channel. struct channel_cfg_s { u32 ch_id; @@ -238,47 +169,6 @@ typedef struct capture_unit_state_s capture_unit_state_t; typedef struct acquisition_unit_state_s acquisition_unit_state_t; typedef struct ctrl_unit_state_s ctrl_unit_state_t; -/* - * In 2300 ports can be configured independently and stream - * formats need to be specified. In 2400, there are only 8 - * supported configurations but the HW is fused to support - * only a single one. - * - * In 2300 the compressed format types are programmed by the - * user. In 2400 all stream formats are encoded on the stream. - * - * Use the enum to check validity of a user configuration - */ -typedef enum { - MONO_4L_1L_0L = 0, - MONO_3L_1L_0L, - MONO_2L_1L_0L, - MONO_1L_1L_0L, - STEREO_2L_1L_2L, - STEREO_3L_1L_1L, - STEREO_2L_1L_1L, - STEREO_1L_1L_1L, - N_RX_MODE -} rx_mode_t; - -typedef enum { - MIPI_PREDICTOR_NONE = 0, - MIPI_PREDICTOR_TYPE1, - MIPI_PREDICTOR_TYPE2, - N_MIPI_PREDICTOR_TYPES -} mipi_predictor_t; - -typedef enum { - MIPI_COMPRESSOR_NONE = 0, - MIPI_COMPRESSOR_10_6_10, - MIPI_COMPRESSOR_10_7_10, - MIPI_COMPRESSOR_10_8_10, - MIPI_COMPRESSOR_12_6_12, - MIPI_COMPRESSOR_12_7_12, - MIPI_COMPRESSOR_12_8_12, - N_MIPI_COMPRESSOR_METHODS -} mipi_compressor_t; - typedef enum { MIPI_FORMAT_RGB888 = 0, MIPI_FORMAT_RGB555, @@ -339,22 +229,6 @@ typedef enum { RX_IRQ_INFO_ERR_LINE_SYNC = 1UL << _HRT_CSS_RECEIVER_IRQ_ERR_LINE_SYNC_BIT, } rx_irq_info_t; -typedef struct rx_cfg_s rx_cfg_t; - -/* - * Applied per port - */ -struct rx_cfg_s { - rx_mode_t mode; /* The HW config */ - enum mipi_port_id port; /* The port ID to apply the control on */ - unsigned int timeout; - unsigned int initcount; - unsigned int synccount; - unsigned int rxcount; - mipi_predictor_t comp; /* Just for backward compatibility */ - bool is_two_ppc; -}; - /* NOTE: The base has already an offset of 0x0100 */ static const hrt_address __maybe_unused MIPI_PORT_OFFSET[N_MIPI_PORT_ID] = { 0x00000000UL, diff --git a/drivers/staging/media/atomisp/pci/isp2401_input_system_local.h b/drivers/staging/media/atomisp/pci/isp2401_input_system_local.h index 24026090cd35..74bfa10e670e 100644 --- a/drivers/staging/media/atomisp/pci/isp2401_input_system_local.h +++ b/drivers/staging/media/atomisp/pci/isp2401_input_system_local.h @@ -16,9 +16,6 @@ #ifndef __INPUT_SYSTEM_LOCAL_H_INCLUDED__ #define __INPUT_SYSTEM_LOCAL_H_INCLUDED__ -#include "type_support.h" -#include "input_system_global.h" - #include "csi_rx.h" #include "pixelgen.h" #include "isys_stream2mmio.h" @@ -69,29 +66,6 @@ typedef enum { /* The number of stores for compressed format types */ #define N_MIPI_COMPRESSOR_CONTEXT (N_RX_CHANNEL_ID * N_MIPI_FORMAT_CUSTOM) -#define UNCOMPRESSED_BITS_PER_PIXEL_10 10 -#define UNCOMPRESSED_BITS_PER_PIXEL_12 12 -#define COMPRESSED_BITS_PER_PIXEL_6 6 -#define COMPRESSED_BITS_PER_PIXEL_7 7 -#define COMPRESSED_BITS_PER_PIXEL_8 8 -enum mipi_compressor { - MIPI_COMPRESSOR_NONE = 0, - MIPI_COMPRESSOR_10_6_10, - MIPI_COMPRESSOR_10_7_10, - MIPI_COMPRESSOR_10_8_10, - MIPI_COMPRESSOR_12_6_12, - MIPI_COMPRESSOR_12_7_12, - MIPI_COMPRESSOR_12_8_12, - N_MIPI_COMPRESSOR_METHODS -}; - -typedef enum { - MIPI_PREDICTOR_NONE = 0, - MIPI_PREDICTOR_TYPE1, - MIPI_PREDICTOR_TYPE2, - N_MIPI_PREDICTOR_TYPES -} mipi_predictor_t; - typedef struct input_system_state_s input_system_state_t; struct input_system_state_s { ibuf_ctrl_state_t ibuf_ctrl_state[N_IBUF_CTRL_ID]; From 55e14acd99fd1ae3f624cdf75ec6ffe163007c81 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 14 Nov 2021 11:44:37 +0000 Subject: [PATCH 116/397] media: atomisp: ia_css_stream.h: remove ifdefs from the header Now that the input system always declare rx_cfg_t, we can remove the ifdef ISP2401 from this header. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/ia_css_stream.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/ia_css_stream.h b/drivers/staging/media/atomisp/pci/ia_css_stream.h index 70b0378748f1..cf847586dc61 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_stream.h +++ b/drivers/staging/media/atomisp/pci/ia_css_stream.h @@ -18,9 +18,7 @@ #include #include -#if !defined(ISP2401) #include -#endif #include "ia_css_types.h" #include "ia_css_stream_public.h" @@ -30,9 +28,7 @@ struct ia_css_stream { struct ia_css_stream_config config; struct ia_css_stream_info info; -#if !defined(ISP2401) rx_cfg_t csi_rx_config; -#endif bool reconfigure_css_rx; struct ia_css_pipe *last_pipe; int num_pipes; From 0badc300c03aeff5c038eb852122f6e95df64821 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 12:05:25 +0000 Subject: [PATCH 117/397] media: atomisp: fix comments coding style at sh_css.c Use the coding style for the comments at this file. While here, drop a do-nothing if logic. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 881 ++++++++++++--------- 1 file changed, 521 insertions(+), 360 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index bd3f96bd7d6d..5ee777909cce 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -62,9 +62,9 @@ #include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */ #include "gdc_device.h" /* HRT_GDC_N */ #include "dma.h" /* dma_set_max_burst_size() */ -#include "irq.h" /* virq */ -#include "sp.h" /* cnd_sp_irq_enable() */ -#include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */ +#include "irq.h" /* virq */ +#include "sp.h" /* cnd_sp_irq_enable() */ +#include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */ #include "gp_device.h" /* gp_device_reg_store() */ #define __INLINE_GPIO__ #include "gpio.h" @@ -97,8 +97,9 @@ static int thread_alive; /* Size of Refcount List */ #define REFCOUNT_SIZE 1000 -/* for JPEG, we don't know the length of the image upfront, - * but since we support sensor upto 16MP, we take this as +/* + * for JPEG, we don't know the length of the image upfront, + * but since we support sensor up to 16MP, we take this as * upper limit. */ #define JPEG_BYTES (16 * 1024 * 1024) @@ -110,9 +111,10 @@ struct sh_css my_css; int __printf(1, 0) (*sh_css_printf)(const char *fmt, va_list args) = NULL; -/* modes of work: stream_create and stream_destroy will update the save/restore data - only when in working mode, not suspend/resume -*/ +/* + * modes of work: stream_create and stream_destroy will update the save/restore + * data only when in working mode, not suspend/resume + */ enum ia_sh_css_modes { sh_css_mode_none = 0, sh_css_mode_working, @@ -120,40 +122,55 @@ enum ia_sh_css_modes { sh_css_mode_resume }; -/* a stream seed, to save and restore the stream data. - the stream seed contains all the data required to "grow" the seed again after it was closed. +/** + * struct sh_css_stream_seed - a stream seed, to save and restore the + * stream data. + * + * @orig_stream: pointer to restore the original handle + * @stream: handle, used as ID too. + * @stream_config: stream config struct + * @num_pipes: number of pipes + * @pipes: pipe handles + * @orig_pipes: pointer to restore original handle + * @pipe_config: pipe config structs + * + * the stream seed contains all the data required to "grow" the seed again + * after it was closed. */ struct sh_css_stream_seed { - struct ia_css_stream - **orig_stream; /* pointer to restore the original handle */ - struct ia_css_stream *stream; /* handle, used as ID too.*/ - struct ia_css_stream_config stream_config; /* stream config struct */ + struct ia_css_stream **orig_stream; + struct ia_css_stream *stream; + struct ia_css_stream_config stream_config; int num_pipes; - struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM]; /* pipe handles */ - struct ia_css_pipe - **orig_pipes[IA_CSS_PIPE_ID_NUM]; /* pointer to restore original handle */ - struct ia_css_pipe_config - pipe_config[IA_CSS_PIPE_ID_NUM]; /* pipe config structs */ + struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM]; + struct ia_css_pipe **orig_pipes[IA_CSS_PIPE_ID_NUM]; + struct ia_css_pipe_config pipe_config[IA_CSS_PIPE_ID_NUM]; }; #define MAX_ACTIVE_STREAMS 5 -/* A global struct for save/restore to hold all the data that should sustain power-down: - MMU base, IRQ type, env for routines, binary loaded FW and the stream seeds. -*/ +/* + * A global struct for save/restore to hold all the data that should + * sustain power-down: MMU base, IRQ type, env for routines, binary loaded FW + * and the stream seeds. + */ struct sh_css_save { enum ia_sh_css_modes mode; - u32 mmu_base; /* the last mmu_base */ + u32 mmu_base; /* the last mmu_base */ enum ia_css_irq_type irq_type; struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS]; - struct ia_css_fw *loaded_fw; /* fw struct previously loaded */ - struct ia_css_env driver_env; /* driver-supplied env copy */ + struct ia_css_fw *loaded_fw; /* fw struct previously loaded */ + struct ia_css_env driver_env; /* driver-supplied env copy */ }; static bool my_css_save_initialized; /* if my_css_save was initialized */ static struct sh_css_save my_css_save; -/* pqiao NOTICE: this is for css internal buffer recycling when stopping pipeline, - this array is temporary and will be replaced by resource manager*/ +/* + * pqiao NOTICE: this is for css internal buffer recycling when stopping + * pipeline, + * this array is temporary and will be replaced by resource manager + */ + /* Taking the biggest Size for number of Elements */ #define MAX_HMM_BUFFER_NUM \ (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2)) @@ -443,9 +460,10 @@ static enum ia_css_frame_format yuv422_copy_formats[] = { IA_CSS_FRAME_FORMAT_YUYV }; -/* Verify whether the selected output format is can be produced +/* + * Verify whether the selected output format is can be produced * by the copy binary given the stream format. - * */ + */ static int verify_copy_out_frame_format(struct ia_css_pipe *pipe) { @@ -682,13 +700,13 @@ static unsigned int csi2_protocol_calculate_max_subpixels_per_line( /* * The frame format layout is shown below. * - * Line 0: Pixel Pixel ... Pixel - * Line 1: Pixel Pixel ... Pixel - * Line 2: Pixel Pixel ... Pixel - * Line 3: Pixel Pixel ... Pixel + * Line 0: Pixel ... Pixel + * Line 1: Pixel ... Pixel + * Line 2: Pixel ... Pixel + * Line 3: Pixel ... Pixel * ... - * Line (n-2): Pixel Pixel ... Pixel - * Line (n-1): Pixel Pixel ... Pixel + * Line (n-2): Pixel ... Pixel + * Line (n-1): Pixel ... Pixel * * In this frame format, the even-line is * as wide as the odd-line. @@ -899,8 +917,10 @@ static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr( isys_stream_descr->metadata.lines_per_frame = stream_cfg->metadata_config.resolution.height; #ifdef ISP2401 - /* For new input system, number of str2mmio requests must be even. - * So we round up number of metadata lines to be even. */ + /* + * For new input system, number of str2mmio requests must be even. + * So we round up number of metadata lines to be even. + */ if (isys_stream_descr->metadata.lines_per_frame > 0) isys_stream_descr->metadata.lines_per_frame += (isys_stream_descr->metadata.lines_per_frame & 1); @@ -1067,7 +1087,8 @@ sh_css_config_input_network(struct ia_css_stream *stream) binary = pipe->pipeline.stages->binary; if (binary) { - /* this was being done in ifmtr in 2400. + /* + * this was being done in ifmtr in 2400. * online and cont bypass the init_in_frameinfo_memory_defaults * so need to do it here */ @@ -1546,17 +1567,18 @@ ia_css_reset_defaults(struct sh_css *css) /* Reset everything to zero */ memset(&default_css, 0, sizeof(default_css)); - /* Initialize the non zero values*/ + /* Initialize the non zero values */ default_css.check_system_idle = true; default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES; - /* All should be 0: but memset does it already. + /* + * All should be 0: but memset does it already. * default_css.num_mipi_frames[N_CSI_PORTS] = 0; */ default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE; - /*Set the defaults to the output */ + /* Set the defaults to the output */ *css = default_css; } @@ -1619,6 +1641,7 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, * the SIZE_OF_XXX macro of the corresponding struct. If they are not * equal, functionality will break. */ + /* Check struct sh_css_ddr_address_map */ COMPILATION_ERROR_IF(sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT); /* Check struct host_sp_queues */ @@ -1688,8 +1711,11 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, mipi_init(); #ifndef ISP2401 - /* In case this has been programmed already, update internal - data structure ... DEPRECATED */ + /* + * In case this has been programmed already, update internal + * data structure ... + * DEPRECATED + */ my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID); #endif @@ -1752,12 +1778,13 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, IA_CSS_LEAVE_ERR(-EBUSY); return -EBUSY; } - /* can be called here, queuing works, but: - - when sp is started later, it will wipe queued items - so for now we leave it for later and make sure - updates are not called to frequently. - sh_css_init_buffer_queues(); - */ + /* + * can be called here, queuing works, but: + * - when sp is started later, it will wipe queued items + * so for now we leave it for later and make sure + * updates are not called to frequently. + * sh_css_init_buffer_queues(); + */ #if defined(ISP2401) gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1); @@ -1798,10 +1825,12 @@ sh_css_flush(struct ia_css_acc_fw *fw) my_css.flush(fw); } -/* Mapping sp threads. Currently, this is done when a stream is created and +/* + * Mapping sp threads. Currently, this is done when a stream is created and * pipelines are ready to be converted to sp pipelines. Be careful if you are * doing it from stream_create since we could run out of sp threads due to - * allocation on inactive pipelines. */ + * allocation on inactive pipelines. + */ static int map_sp_threads(struct ia_css_stream *stream, bool map) { @@ -1865,8 +1894,10 @@ map_sp_threads(struct ia_css_stream *stream, bool map) return err; } -/* creates a host pipeline skeleton for all pipes in a stream. Called during - * stream_create. */ +/* + * creates a host pipeline skeleton for all pipes in a stream. Called during + * stream_create. + */ static int create_host_pipeline_structure(struct ia_css_stream *stream) { @@ -1965,8 +1996,10 @@ create_host_pipeline_structure(struct ia_css_stream *stream) return err; } -/* creates a host pipeline for all pipes in a stream. Called during - * stream_start. */ +/* + * creates a host pipeline for all pipes in a stream. Called during + * stream_start. + */ static int create_host_pipeline(struct ia_css_stream *stream) { @@ -1986,15 +2019,25 @@ create_host_pipeline(struct ia_css_stream *stream) main_pipe = stream->last_pipe; pipe_id = main_pipe->mode; - /* No continuous frame allocation for capture pipe. It uses the - * "main" pipe's frames. */ + /* + * No continuous frame allocation for capture pipe. It uses the + * "main" pipe's frames. + */ if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) || (pipe_id == IA_CSS_PIPE_ID_VIDEO)) { - /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY: - * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory - * based input frames) there is no continuous mode and thus no need for allocated continuous frames - * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this - * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added. + /* + * About + * pipe_id == IA_CSS_PIPE_ID_PREVIEW && + * stream->config.mode != IA_CSS_INPUT_MODE_MEMORY: + * + * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is + * too strong. E.g. in SkyCam (with memory based input frames) + * there is no continuous mode and thus no need for allocated + * continuous frames. + * This is not only for SkyCam but for all preview cases that + * use DDR based input frames. For this reason the + * stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed + * added. */ if (stream->config.continuous || (pipe_id == IA_CSS_PIPE_ID_PREVIEW && @@ -2204,7 +2247,7 @@ pipe_generate_pipe_num(const struct ia_css_pipe *pipe, /* Assign a new pipe_num .... search for empty place */ for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { if (!my_css.all_pipes[i]) { - /*position is reserved */ + /* position is reserved */ my_css.all_pipes[i] = (struct ia_css_pipe *)pipe; pipe_num = i; break; @@ -2321,8 +2364,10 @@ ia_css_pipe_destroy(struct ia_css_pipe *pipe) switch (pipe->config.mode) { case IA_CSS_PIPE_MODE_PREVIEW: - /* need to take into account that this function is also called - on the internal copy pipe */ + /* + * need to take into account that this function is also called + * on the internal copy pipe + */ if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) { ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES, pipe->continuous_frames); @@ -2454,8 +2499,10 @@ int ia_css_irq_translate( switch (irq) { case virq_sp: - /* When SP goes to idle, info is available in the - * event queue. */ + /* + * When SP goes to idle, info is available in the + * event queue. + */ infos |= IA_CSS_IRQ_INFO_EVENTS_READY; break; case virq_isp: @@ -2563,8 +2610,10 @@ sh_css_get_sw_interrupt_value(unsigned int irq) return irq_value; } -/* configure and load the copy binary, the next binary is used to - determine whether the copy binary needs to do left padding. */ +/* + * configure and load the copy binary, the next binary is used to + * determine whether the copy binary needs to do left padding. + */ static int load_copy_binary( struct ia_css_pipe *pipe, struct ia_css_binary *copy_binary, @@ -2761,7 +2810,8 @@ load_preview_binaries(struct ia_css_pipe *pipe) if (err) return err; - /* Note: the current selection of vf_pp binary and + /* + * Note: the current selection of vf_pp binary and * parameterization of the preview binary contains a few pieces * of hardcoded knowledge. This needs to be cleaned up such that * the binary selection becomes more generic. @@ -2774,7 +2824,7 @@ load_preview_binaries(struct ia_css_pipe *pipe) * The decision if the vf_pp binary is needed for YUV downscaling is * made after the preview binary selection, since some preview binaries * can perform the requested YUV downscaling. - * */ + */ need_vf_pp = pipe->config.enable_dz; need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE && !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 || @@ -2786,11 +2836,12 @@ load_preview_binaries(struct ia_css_pipe *pipe) prev_vf_info = pipe->vf_yuv_ds_input_info; else prev_vf_info = *pipe_out_info; - /* If vf_pp is needed, then preview must output yuv_line. + /* + * If vf_pp is needed, then preview must output yuv_line. * The exception is when vf_pp is manually disabled, that is only * used in combination with a pipeline extension that requires * yuv_line as input. - * */ + */ if (need_vf_pp) ia_css_frame_info_set_format(&prev_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE); @@ -2823,7 +2874,8 @@ load_preview_binaries(struct ia_css_pipe *pipe) need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width; need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height; - /* When vf_pp is needed, then the output format of the selected + /* + * When vf_pp is needed, then the output format of the selected * preview binary must be yuv_line. If this is not the case, * then the preview binary selection is done again. */ @@ -2867,12 +2919,14 @@ load_preview_binaries(struct ia_css_pipe *pipe) } #ifdef ISP2401 - /* When the input system is 2401, only the Direct Sensor Mode + /* + * When the input system is 2401, only the Direct Sensor Mode * Offline Preview uses the ISP copy binary. */ need_isp_copy_binary = !online && sensor; #else - /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY: + /* + * About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY: * This is typical the case with SkyCam (which has no input system) but it also applies to all cases * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical * copies sensor data to DDR) does not have much use. @@ -3226,8 +3280,10 @@ get_crop_columns_for_bayer_order(const struct ia_css_stream_config *config) return 0; } -/* This function is to get the sum of all extra pixels in addition to the effective - * input, it includes dvs envelop and filter run-in */ +/* + * This function is to get the sum of all extra pixels in addition to the effective + * input, it includes dvs envelop and filter run-in + */ static void get_pipe_extra_pixel(struct ia_css_pipe *pipe, unsigned int *extra_row, unsigned int *extra_column) { @@ -3236,7 +3292,8 @@ static void get_pipe_extra_pixel(struct ia_css_pipe *pipe, unsigned int i; struct ia_css_resolution dvs_env = pipe->config.dvs_envelope; - /* The dvs envelope info may not be correctly sent down via pipe config + /* + * The dvs envelope info may not be correctly sent down via pipe config * The check is made and the correct value is populated in the binary info * Use this value when computing crop, else excess lines may get trimmed */ @@ -3330,7 +3387,8 @@ ia_css_get_crop_offsets( * 2. Require the special support for the online use cases. */ - /* ISP expects GRBG bayer order, we skip one line and/or one row + /* + * ISP expects GRBG bayer order, we skip one line and/or one row * to correct in case the input bayer order is different. */ column += get_crop_columns_for_bayer_order(&pipe->stream->config); @@ -3448,7 +3506,8 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe) me->dvs_frame_delay = pipe->dvs_frame_delay; #ifdef ISP2401 - /* When the input system is 2401, always enable 'in_frameinfo_memory' + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' * except for the following: online or continuous */ need_in_frameinfo_memory = !(pipe->stream->config.online || @@ -3504,7 +3563,8 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe) in_frame = me->stages->args.out_frame[0]; } else if (pipe->stream->config.continuous) { #ifdef ISP2401 - /* When continuous is enabled, configure in_frame with the + /* + * When continuous is enabled, configure in_frame with the * last pipe, which is the copy pipe. */ in_frame = pipe->stream->last_pipe->continuous_frames[0]; @@ -3516,8 +3576,10 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe) ia_css_pipe_util_set_output_frames(out_frames, 0, need_yuv_pp ? NULL : out_frame); - /* when the video binary supports a second output pin, - it can directly produce the vf_frame. */ + /* + * when the video binary supports a second output pin, + * it can directly produce the vf_frame. + */ if (need_vf_pp) { ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary, out_frames, in_frame, NULL); @@ -3689,7 +3751,8 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) ia_css_pipeline_clean(me); #ifdef ISP2401 - /* When the input system is 2401, always enable 'in_frameinfo_memory' + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' * except for the following: * - Direct Sensor Mode Online Preview * - Buffered Sensor Mode Online Preview @@ -3738,7 +3801,8 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) in_frame = me->stages->args.out_frame[0]; } else if (pipe->stream->config.continuous) { #ifdef ISP2401 - /* When continuous is enabled, configure in_frame with the + /* + * When continuous is enabled, configure in_frame with the * last pipe, which is the copy pipe. */ if (continuous || !online) @@ -3877,8 +3941,10 @@ preview_start(struct ia_css_pipe *pipe) coord, params); - /* make the preview pipe start with mem mode input, copy handles - the actual mode */ + /* + * make the preview pipe start with mem mode input, copy handles + * the actual mode + */ preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY; } @@ -4096,8 +4162,10 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, } for (stage = pipeline->stages; stage; stage = stage->next) { - /* The SP will read the params - after it got empty 3a and dis */ + /* + * The SP will read the params after it got + * empty 3a and dis + */ if (STATS_ENABLED(stage)) { /* there is a stage that needs it */ return_err = ia_css_bufq_enqueue_buffer(thread_id, @@ -4163,7 +4231,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, /* * TODO: Free up the hmm memory space. - */ + */ int ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, struct ia_css_buffer *buffer) @@ -4230,7 +4298,8 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, hmm_buffer_record = sh_css_hmm_buffer_record_validate( ddr_buffer_addr, buf_type); if (hmm_buffer_record) { - /* valid hmm_buffer_record found. Save the kernel_ptr + /* + * valid hmm_buffer_record found. Save the kernel_ptr * for validation after performing hmm_load. The * vbuf handle and buffer_record can be released. */ @@ -4248,7 +4317,8 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, &ddr_buffer, sizeof(struct sh_css_hmm_buffer)); - /* if the kernel_ptr is 0 or an invalid, return an error. + /* + * if the kernel_ptr is 0 or an invalid, return an error. * do not access the buffer via the kernal_ptr. */ if ((ddr_buffer.kernel_ptr == 0) || @@ -4262,8 +4332,11 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, } if (ddr_buffer.kernel_ptr != 0) { - /* buffer->exp_id : all instances to be removed later once the driver change - * is completed. See patch #5758 for reference */ + /* + * buffer->exp_id : all instances to be removed later + * once the driver change is completed. See patch #5758 + * for reference + */ buffer->exp_id = 0; buffer->driver_cookie = ddr_buffer.cookie_ptr; buffer->timing_data = ddr_buffer.timing_data; @@ -4279,8 +4352,10 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: if (pipe && pipe->stop_requested) { #if !defined(ISP2401) - /* free mipi frames only for old input system - * for 2401 it is done in ia_css_stream_destroy call + /* + * free mipi frames only for old input + * system for 2401 it is done in + * ia_css_stream_destroy call */ return_err = free_mipi_frames(pipe); if (return_err) { @@ -4391,22 +4466,22 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c) */ static enum ia_css_event_type convert_event_sp_to_host_domain[] = { - IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /** Output frame ready. */ - IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /** Second output frame ready. */ - IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /** Viewfinder Output frame ready. */ - IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /** Second viewfinder Output frame ready. */ - IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /** Indication that 3A statistics are available. */ - IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /** Indication that DIS statistics are available. */ - IA_CSS_EVENT_TYPE_PIPELINE_DONE, /** Pipeline Done event, sent after last pipeline stage. */ - IA_CSS_EVENT_TYPE_FRAME_TAGGED, /** Frame tagged. */ - IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /** Input frame ready. */ - IA_CSS_EVENT_TYPE_METADATA_DONE, /** Metadata ready. */ - IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /** Indication that LACE statistics are available. */ - IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /** Extension stage executed. */ - IA_CSS_EVENT_TYPE_TIMER, /** Timing measurement data. */ - IA_CSS_EVENT_TYPE_PORT_EOF, /** End Of Frame event, sent when in buffered sensor mode. */ - IA_CSS_EVENT_TYPE_FW_WARNING, /** Performance warning encountered by FW */ - IA_CSS_EVENT_TYPE_FW_ASSERT, /** Assertion hit by FW */ + IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /* Output frame ready. */ + IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /* Second output frame ready. */ + IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /* Viewfinder Output frame ready. */ + IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /* Second viewfinder Output frame ready. */ + IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /* Indication that 3A statistics are available. */ + IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /* Indication that DIS statistics are available. */ + IA_CSS_EVENT_TYPE_PIPELINE_DONE, /* Pipeline Done event, sent after last pipeline stage. */ + IA_CSS_EVENT_TYPE_FRAME_TAGGED, /* Frame tagged. */ + IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /* Input frame ready. */ + IA_CSS_EVENT_TYPE_METADATA_DONE, /* Metadata ready. */ + IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /* Indication that LACE statistics are available. */ + IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /* Extension stage executed. */ + IA_CSS_EVENT_TYPE_TIMER, /* Timing measurement data. */ + IA_CSS_EVENT_TYPE_PORT_EOF, /* End Of Frame event, sent when in buffered sensor mode. */ + IA_CSS_EVENT_TYPE_FW_WARNING, /* Performance warning encountered by FW */ + IA_CSS_EVENT_TYPE_FW_ASSERT, /* Assertion hit by FW */ 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */ }; @@ -4417,13 +4492,15 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) u8 payload[4] = {0, 0, 0, 0}; int ret_err; - /*TODO: + /* + * TODO: * a) use generic decoding function , same as the one used by sp. * b) group decode and dequeue into eventQueue module * * We skip the IA_CSS_ENTER logging call * to avoid flooding the logs when the host application - * uses polling. */ + * uses polling. + */ if (!event) return -EINVAL; @@ -4442,9 +4519,11 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) ia_css_bufq_enqueue_psys_event( IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0); - /* Events are decoded into 4 bytes of payload, the first byte + /* + * Events are decoded into 4 bytes of payload, the first byte * contains the sp event type. This is converted to a host enum. - * TODO: can this enum conversion be eliminated */ + * TODO: can this enum conversion be eliminated + */ event->type = convert_event_sp_to_host_domain[payload[0]]; /* Some sane default values since not all events use all fields. */ event->pipe = NULL; @@ -4457,7 +4536,10 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) event->timer_subcode = 0; if (event->type == IA_CSS_EVENT_TYPE_TIMER) { - /* timer event ??? get the 2nd event and decode the data into the event struct */ + /* + * timer event ??? get the 2nd event and decode the data + * into the event struct + */ u32 tmp_data; /* 1st event: LSB 16-bit timer data and code */ event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8)); @@ -4466,8 +4548,10 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) ret_err = ia_css_bufq_dequeue_psys_event(payload); if (ret_err) { /* no 2nd event ??? an error */ - /* Putting IA_CSS_ERROR is resulting in failures in - * Merrifield smoke testing */ + /* + * Putting IA_CSS_ERROR is resulting in failures in + * Merrifield smoke testing + */ IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n"); return ret_err; } @@ -4481,11 +4565,15 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) event->timer_data |= (tmp_data << 16); event->timer_subcode = payload[2]; } else { - /* It's a non timer event. So clear first half of the timer event data. - * If the second part of the TIMER event is not received, we discard - * the first half of the timer data and process the non timer event without - * affecting the flow. So the non timer event falls through - * the code. */ + /* + * It's a non timer event. So clear first half of the + * timer event data. + * If the second part of the TIMER event is not + * received, we discard the first half of the timer + * data and process the non timer event without + * affecting the flow. So the non timer event falls + * through the code. + */ event->timer_data = 0; event->timer_code = 0; event->timer_subcode = 0; @@ -4506,9 +4594,11 @@ ia_css_dequeue_psys_event(struct ia_css_event *event) event->fw_assert_line_no = (payload[2] << 8) + payload[3]; /* payload[2] is line_no>>8, payload[3] is line_no&0xff */ } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) { - /* pipe related events. + /* + * pipe related events. * payload[1] contains the pipe_num, - * payload[2] contains the pipe_id. These are different. */ + * payload[2] contains the pipe_id. These are different. + */ event->pipe = find_pipe_by_num(payload[1]); pipe_id = (enum ia_css_pipe_id)payload[2]; /* Check to see if pipe still exists */ @@ -4560,9 +4650,11 @@ ia_css_dequeue_isys_event(struct ia_css_event *event) u8 payload[4] = {0, 0, 0, 0}; int err = 0; - /* We skip the IA_CSS_ENTER logging call + /* + * We skip the IA_CSS_ENTER logging call * to avoid flooding the logs when the host application - * uses polling. */ + * uses polling. + */ if (!event) return -EINVAL; @@ -4686,7 +4778,8 @@ sh_css_pipe_start(struct ia_css_stream *stream) return err; } - /* Force ISP parameter calculation after a mode change + /* + * Force ISP parameter calculation after a mode change * Acceleration API examples pass NULL for stream but they * don't use ISP parameters anyway. So this should be okay. * The SP binary (jpeg) copy does not use any parameters. @@ -5103,11 +5196,13 @@ sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe, (const struct ia_css_stream_config *)&pipe->stream->config, shading_info, pipe_config); - /* Other function calls can be added here when other shading correction types will be added - * in the future. + /* + * Other function calls can be added here when other shading + * correction types will be added in the future. */ } else { - /* When the pipe does not have a binary which has the shading + /* + * When the pipe does not have a binary which has the shading * correction, this function does not need to fill the shading * information. It is not a error case, and then * this function should return 0. @@ -5220,7 +5315,8 @@ static int load_video_binaries(struct ia_css_pipe *pipe) IA_CSS_ENTER_PRIVATE(""); assert(pipe); assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO); - /* we only test the video_binary because offline video doesn't need a + /* + * we only test the video_binary because offline video doesn't need a * vf_pp binary and online does not (always use) the copy_binary. * All are always reset at the same time anyway. */ @@ -5333,7 +5429,8 @@ static int load_video_binaries(struct ia_css_pipe *pipe) if (err) return err; - /* In the case where video_vf_info is not NULL, this allows + /* + * In the case where video_vf_info is not NULL, this allows * us to find a potential video library with desired vf format. * If success, no vf_pp binary is needed. * If failed, we will look up video binary with YUV_LINE vf format @@ -5348,17 +5445,23 @@ static int load_video_binaries(struct ia_css_pipe *pipe) else return err; } else if (video_vf_info) { - /* The first video binary lookup is successful, but we may - * still need vf_pp binary based on additiona check */ + /* + * The first video binary lookup is successful, but we + * may still need vf_pp binary based on additional check + */ num_output_pins = mycs->video_binary.info->num_output_pins; vf_ds_log2 = mycs->video_binary.vf_downscale_log2; - /* If the binary has dual output pins, we need vf_pp if the resolution - * is different. */ + /* + * If the binary has dual output pins, we need vf_pp + * if the resolution is different. + */ need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output); - /* If the binary has single output pin, we need vf_pp if additional - * scaling is needed for vf */ + /* + * If the binary has single output pin, we need vf_pp + * if additional scaling is needed for vf + */ need_vf_pp |= ((num_output_pins == 1) && ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) || (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height))); @@ -5388,19 +5491,25 @@ static int load_video_binaries(struct ia_css_pipe *pipe) } } - /* If a video binary does not use a ref_frame, we set the frame delay - * to 0. This is the case for the 1-stage low-power video binary. */ + /* + * If a video binary does not use a ref_frame, we set the frame delay + * to 0. This is the case for the 1-stage low-power video binary. + */ if (!mycs->video_binary.info->sp.enable.ref_frame) pipe->dvs_frame_delay = 0; - /* The delay latency determines the number of invalid frames after - * a stream is started. */ + /* + * The delay latency determines the number of invalid frames after + * a stream is started. + */ pipe->num_invalid_frames = pipe->dvs_frame_delay; pipe->info.num_invalid_frames = pipe->num_invalid_frames; - /* Viewfinder frames also decrement num_invalid_frames. If the pipe + /* + * Viewfinder frames also decrement num_invalid_frames. If the pipe * outputs a viewfinder output, then we need double the number of - * invalid frames */ + * invalid frames + */ if (video_vf_info) pipe->num_invalid_frames *= 2; @@ -5412,7 +5521,8 @@ static int load_video_binaries(struct ia_css_pipe *pipe) #if !defined(ISP2401) /* Copy */ if (!online && !continuous) { - /* TODO: what exactly needs doing, prepend the copy binary to + /* + * TODO: what exactly needs doing, prepend the copy binary to * video base this only on !online? */ err = load_copy_binary(pipe, @@ -5435,8 +5545,11 @@ static int load_video_binaries(struct ia_css_pipe *pipe) &mycs->video_binary.vf_frame_info, pipe_vf_out_info); } else { - /* output from main binary is not yuv line. currently this is - * possible only when bci is enabled on vfpp output */ + /* + * output from main binary is not yuv line. currently + * this is possible only when bci is enabled on vfpp + * output + */ assert(pipe->config.enable_vfpp_bci); ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr, &mycs->video_binary.vf_frame_info, @@ -5598,8 +5711,10 @@ static int video_start(struct ia_css_pipe *pipe) coord, params); - /* make the video pipe start with mem mode input, copy handles - the actual mode */ + /* + * make the video pipe start with mem mode input, copy handles + * the actual mode + */ video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY; } @@ -5857,9 +5972,11 @@ static int load_primary_binaries( } need_pp = need_capture_pp(pipe); - /* we use the vf output info to get the primary/capture_pp binary - configured for vf_veceven. It will select the closest downscaling - factor. */ + /* + * we use the vf output info to get the primary/capture_pp binary + * configured for vf_veceven. It will select the closest downscaling + * factor. + */ vf_info = *pipe_vf_out_info; /* @@ -5871,13 +5988,15 @@ static int load_primary_binaries( * required. This should not be considered as a clean solution. * Proper investigation should be done to come up with the clean * solution. - * */ + */ ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE); - /* TODO: All this yuv_scaler and capturepp calculation logic + /* + * TODO: All this yuv_scaler and capturepp calculation logic * can be shared later. Capture_pp is also a yuv_scale binary * with extra XNR funcionality. Therefore, it can be made as the - * first step of the cascade. */ + * first step of the cascade. + */ capt_pp_out_info = pipe->out_yuv_ds_input_info; capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420; capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP; @@ -6023,15 +6142,15 @@ static int load_primary_binaries( vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info; /* - * WARNING: The #if def flag has been added below as a - * temporary solution to solve the problem of enabling the - * view finder in a single binary in a capture flow. The - * vf-pp stage has been removed for Skycam in the solution - * provided. The vf-pp stage should be re-introduced when - * required. Thisshould not be considered as a clean solution. - * Proper * investigation should be done to come up with the clean - * solution. - * */ + * WARNING: The #if def flag has been added below as a + * temporary solution to solve the problem of enabling the + * view finder in a single binary in a capture flow. The + * vf-pp stage has been removed for Skycam in the solution + * provided. The vf-pp stage should be re-introduced when + * required. Thisshould not be considered as a clean solution. + * Proper * investigation should be done to come up with the clean + * solution. + */ if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { struct ia_css_binary_descr vf_pp_descr; @@ -6049,9 +6168,10 @@ static int load_primary_binaries( return err; #ifdef ISP2401 - /* When the input system is 2401, only the Direct Sensor Mode - * Offline Capture uses the ISP copy binary. - */ + /* + * When the input system is 2401, only the Direct Sensor Mode + * Offline Capture uses the ISP copy binary. + */ need_isp_copy_binary = !online && sensor; #else need_isp_copy_binary = !online && !continuous && !memory; @@ -6105,17 +6225,19 @@ allocate_delay_frames(struct ia_css_pipe *pipe) struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video; ref_info = mycs_video->video_binary.internal_frame_info; - /*The ref frame expects - * 1. Y plane - * 2. UV plane with line interleaving, like below - * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) - * - * This format is not YUV420(which has Y, U and V planes). - * Its closer to NV12, except that the UV plane has UV - * interleaving, like UVUVUVUVUVUVUVUVU... - * - * TODO: make this ref_frame format as a separate frame format - */ + + /* + * The ref frame expects + * 1. Y plane + * 2. UV plane with line interleaving, like below + * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) + * + * This format is not YUV420(which has Y, U and V planes). + * Its closer to NV12, except that the UV plane has UV + * interleaving, like UVUVUVUVUVUVUVUVU... + * + * TODO: make this ref_frame format as a separate frame format + */ ref_info.format = IA_CSS_FRAME_FORMAT_NV12; delay_frames = mycs_video->delay_frames; } @@ -6124,17 +6246,19 @@ allocate_delay_frames(struct ia_css_pipe *pipe) struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview; ref_info = mycs_preview->preview_binary.internal_frame_info; - /*The ref frame expects - * 1. Y plane - * 2. UV plane with line interleaving, like below - * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) - * - * This format is not YUV420(which has Y, U and V planes). - * Its closer to NV12, except that the UV plane has UV - * interleaving, like UVUVUVUVUVUVUVUVU... - * - * TODO: make this ref_frame format as a separate frame format - */ + + /* + * The ref frame expects + * 1. Y plane + * 2. UV plane with line interleaving, like below + * UUUUUU(width/2 times) VVVVVVVV..(width/2 times) + * + * This format is not YUV420(which has Y, U and V planes). + * Its closer to NV12, except that the UV plane has UV + * interleaving, like UVUVUVUVUVUVUVUVU... + * + * TODO: make this ref_frame format as a separate frame format + */ ref_info.format = IA_CSS_FRAME_FORMAT_NV12; delay_frames = mycs_preview->delay_frames; } @@ -6591,9 +6715,11 @@ need_yuv_scaler_stage(const struct ia_css_pipe *pipe) return false; } -/* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */ -/* which has some hard-coded knowledge which prevents reuse of the function. */ -/* Later, merge this with ia_css_pipe_create_cas_scaler_desc */ +/* + * TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc + * which has some hard-coded knowledge which prevents reuse of the function. + * Later, merge this with ia_css_pipe_create_cas_scaler_desc + */ static int ia_css_pipe_create_cas_scaler_desc_single_output( struct ia_css_frame_info *cas_scaler_in_info, struct ia_css_frame_info *cas_scaler_out_info, @@ -6990,22 +7116,22 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) #if defined(ISP2401) /* - * NOTES - * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when - * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"? - * - * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_ - * binary". However, the "yuv_scale_binary" does NOT support the input-frame - * format as "IA_CSS_STREAM _FORMAT_YUV422_8". - * - * Hence, the "isp_copy_binary" is required to be present in front of the "yuv - * _scale_binary". It would translate the input-frame to the frame formats that - * are supported by the "yuv_scale_binary". - * - * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_ - * pp_defs.h" for the list of input-frame formats that are supported by the - * "yuv_scale_binary". - */ + * NOTES + * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when + * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"? + * + * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_ + * binary". However, the "yuv_scale_binary" does NOT support the input-frame + * format as "IA_CSS_STREAM _FORMAT_YUV422_8". + * + * Hence, the "isp_copy_binary" is required to be present in front of the "yuv + * _scale_binary". It would translate the input-frame to the frame formats that + * are supported by the "yuv_scale_binary". + * + * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_ + * pp_defs.h" for the list of input-frame formats that are supported by the + * "yuv_scale_binary". + */ need_isp_copy_binary = (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8); #else /* !ISP2401 */ @@ -7021,23 +7147,23 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) goto ERR; /* - * NOTES - * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified? - * - * In some use cases, the first stage in the "yuvpp" pipe is the - * "isp_copy_binary". The "isp_copy_binary" is designed to process - * the input from either the system DDR or from the IPU internal VMEM. - * So it provides the flag "online" to specify where its input is from, - * i.e.: - * - * (1) "online <= true", the input is from the IPU internal VMEM. - * (2) "online <= false", the input is from the system DDR. - * - * In other use cases, the first stage in the "yuvpp" pipe is the - * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the - * input ONLY from the system DDR. So it does not provide the flag "online" - * to specify where its input is from. - */ + * NOTES + * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified? + * + * In some use cases, the first stage in the "yuvpp" pipe is the + * "isp_copy_binary". The "isp_copy_binary" is designed to process + * the input from either the system DDR or from the IPU internal VMEM. + * So it provides the flag "online" to specify where its input is from, + * i.e.: + * + * (1) "online <= true", the input is from the IPU internal VMEM. + * (2) "online <= false", the input is from the system DDR. + * + * In other use cases, the first stage in the "yuvpp" pipe is the + * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the + * input ONLY from the system DDR. So it does not provide the flag "online" + * to specify where its input is from. + */ pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; } @@ -7230,8 +7356,11 @@ sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) } if (err) { if (sh_css_pipe_unload_binaries(pipe)) { - /* currently css does not support multiple error returns in a single function, - * using -EINVAL in this case */ + /* + * currently css does not support multiple error + * returns in a single function, using -EINVAL in + * this case + */ err = -EINVAL; } } @@ -7282,12 +7411,13 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) num_output_stage = pipe->pipe_settings.yuvpp.num_output; #ifdef ISP2401 - /* When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Continuous Capture - * - Buffered Sensor Mode Continuous Capture - */ + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: + * - Direct Sensor Mode Online Capture + * - Direct Sensor Mode Continuous Capture + * - Buffered Sensor Mode Continuous Capture + */ sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; online = pipe->stream->config.online; @@ -7298,19 +7428,23 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) /* Construct in_frame info (only in case we have dynamic input */ need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; #endif - /* the input frame can come from: - * a) memory: connect yuvscaler to me->in_frame - * b) sensor, via copy binary: connect yuvscaler to copy binary later on */ + /* + * the input frame can come from: + * + * a) memory: connect yuvscaler to me->in_frame + * b) sensor, via copy binary: connect yuvscaler to copy binary later + * on + */ if (need_in_frameinfo_memory) { /* TODO: improve for different input formats. */ /* - * "pipe->stream->config.input_config.format" represents the sensor output - * frame format, e.g. YUV422 8-bit. - * - * "in_frame_format" represents the imaging pipe's input frame format, e.g. - * Bayer-Quad RAW. - */ + * "pipe->stream->config.input_config.format" represents the sensor output + * frame format, e.g. YUV422 8-bit. + * + * "in_frame_format" represents the imaging pipe's input frame format, e.g. + * Bayer-Quad RAW. + */ int in_frame_format; if (pipe->stream->config.input_config.format == @@ -7319,22 +7453,22 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) } else if (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8) { /* - * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8", - * the "isp_copy_var" binary is selected as the first stage in the yuvpp - * pipe. - * - * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from - * the frame buffer (at DDR) to the frame-line buffer (at VMEM). - * - * By now, the "isp_copy_var" binary does NOT provide a separated - * frame-line buffer to store the YUV422-8 pixels. Instead, it stores - * the YUV422-8 pixels in the frame-line buffer which is designed to - * store the Bayer-Quad RAW pixels. - * - * To direct the "isp_copy_var" binary reading from the RAW frame-line - * buffer, its input frame format must be specified as "IA_CSS_FRAME_ - * FORMAT_RAW". - */ + * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8", + * the "isp_copy_var" binary is selected as the first stage in the yuvpp + * pipe. + * + * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from + * the frame buffer (at DDR) to the frame-line buffer (at VMEM). + * + * By now, the "isp_copy_var" binary does NOT provide a separated + * frame-line buffer to store the YUV422-8 pixels. Instead, it stores + * the YUV422-8 pixels in the frame-line buffer which is designed to + * store the Bayer-Quad RAW pixels. + * + * To direct the "isp_copy_var" binary reading from the RAW frame-line + * buffer, its input frame format must be specified as "IA_CSS_FRAME_ + * FORMAT_RAW". + */ in_frame_format = IA_CSS_FRAME_FORMAT_RAW; } else { in_frame_format = IA_CSS_FRAME_FORMAT_NV12; @@ -7633,13 +7767,14 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) ia_css_pipe_util_create_output_frames(out_frames); #ifdef ISP2401 - /* When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Continuous Capture - * - Buffered Sensor Mode Continuous Capture - */ + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: + * - Direct Sensor Mode Online Capture + * - Direct Sensor Mode Online Capture + * - Direct Sensor Mode Continuous Capture + * - Buffered Sensor Mode Continuous Capture + */ sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); online = pipe->stream->config.online; @@ -7772,15 +7907,15 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) local_out_frame = NULL; ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame); /* - * WARNING: The #if def flag has been added below as a - * temporary solution to solve the problem of enabling the - * view finder in a single binary in a capture flow. The - * vf-pp stage has been removed from Skycam in the solution - * provided. The vf-pp stage should be re-introduced when - * required. This * should not be considered as a clean solution. - * Proper investigation should be done to come up with the clean - * solution. - * */ + * WARNING: The #if def flag has been added below as a + * temporary solution to solve the problem of enabling the + * view finder in a single binary in a capture flow. The + * vf-pp stage has been removed from Skycam in the solution + * provided. The vf-pp stage should be re-introduced when + * required. This * should not be considered as a clean solution. + * Proper investigation should be done to come up with the clean + * solution. + */ ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i], out_frames, @@ -7794,8 +7929,7 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) return err; } } - /* If we use copy iso primary, - the input must be yuv iso raw */ + /* If we use copy iso primary, the input must be yuv iso raw */ current_stage->args.copy_vf = primary_binary[0]->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY; @@ -7920,14 +8054,14 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) } /* - * WARNING: The #if def flag has been added below as a - * temporary solution to solve the problem of enabling the - * view finder in a single binary in a capture flow. The vf-pp - * stage has been removed from Skycam in the solution provided. - * The vf-pp stage should be re-introduced when required. This - * should not be considered as a clean solution. Proper - * investigation should be done to come up with the clean solution. - * */ + * WARNING: The #if def flag has been added below as a + * temporary solution to solve the problem of enabling the + * view finder in a single binary in a capture flow. The vf-pp + * stage has been removed from Skycam in the solution provided. + * The vf-pp stage should be re-introduced when required. This + * should not be considered as a clean solution. Proper + * investigation should be done to come up with the clean solution. + */ if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame) { @@ -8021,10 +8155,10 @@ static int capture_start(struct ia_css_pipe *pipe) #if !defined(ISP2401) /* - * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured, - * which is currently done in start_binary(); but COPY pipe contains no binary, - * and does not call start_binary(); so we need to configure the rx here. - */ + * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured, + * which is currently done in start_binary(); but COPY pipe contains no binary, + * and does not call start_binary(); so we need to configure the rx here. + */ if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY && pipe->stream->reconfigure_css_rx) { ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, @@ -8140,7 +8274,8 @@ append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) while (*l) l = &(*l)->next; *l = firmware; - /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */ + /* when multiple acc extensions are loaded, 'next' can be not NULL */ + /*firmware->next = NULL;*/ IA_CSS_LEAVE_PRIVATE(""); } @@ -8326,9 +8461,9 @@ sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline, } /* - * @brief Tag a specific frame in continuous capture. - * Refer to "sh_css_internal.h" for details. - */ + * @brief Tag a specific frame in continuous capture. + * Refer to "sh_css_internal.h" for details. + */ int ia_css_stream_capture_frame(struct ia_css_stream *stream, unsigned int exp_id) { @@ -8355,10 +8490,12 @@ int ia_css_stream_capture_frame(struct ia_css_stream *stream, sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr); /* Encode the tag descriptor into a 32-bit value */ encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr); - /* Enqueue the encoded tag to the host2sp queue. - * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 - * on both host and the SP side. - * It is mainly because it is enough to have only one tag_cmd queue */ + /* + * Enqueue the encoded tag to the host2sp queue. + * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 + * on both host and the SP side. + * It is mainly because it is enough to have only one tag_cmd queue + */ err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr); IA_CSS_LEAVE_ERR(err); @@ -8366,9 +8503,9 @@ int ia_css_stream_capture_frame(struct ia_css_stream *stream, } /* - * @brief Configure the continuous capture. - * Refer to "sh_css_internal.h" for details. - */ + * @brief Configure the continuous capture. + * Refer to "sh_css_internal.h" for details. + */ int ia_css_stream_capture(struct ia_css_stream *stream, int num_captures, unsigned int skip, int offset) { @@ -8404,10 +8541,12 @@ int ia_css_stream_capture(struct ia_css_stream *stream, int num_captures, return -EBUSY; } - /* Enqueue the encoded tag to the host2sp queue. - * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 - * on both host and the SP side. - * It is mainly because it is enough to have only one tag_cmd queue */ + /* + * Enqueue the encoded tag to the host2sp queue. + * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0 + * on both host and the SP side. + * It is mainly because it is enough to have only one tag_cmd queue + */ return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, @@ -8552,9 +8691,11 @@ void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config) stream_config->online = true; stream_config->left_padding = -1; stream_config->pixels_per_clock = 1; - /* temporary default value for backwards compatibility. - * This field used to be hardcoded within CSS but this has now - * been moved to the stream_config struct. */ + /* + * temporary default value for backwards compatibility. + * This field used to be hardcoded within CSS but this has now + * been moved to the stream_config struct. + */ stream_config->source.port.rxcount = 0x04040404; } @@ -8568,7 +8709,7 @@ ia_css_acc_pipe_create(struct ia_css_pipe *pipe) return -EINVAL; } - /* There is not meaning for num_execs = 0 semantically. Run atleast once. */ + /* There is not meaning for num_execs = 0 semantically. Run at least once. */ if (pipe->config.acc_num_execs == 0) pipe->config.acc_num_execs = 1; @@ -8639,9 +8780,11 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config, ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config); if (config->mode == IA_CSS_PIPE_MODE_ACC) { - /* Temporary hack to migrate acceleration to CSS 2.0. - * In the future the code for all pipe types should be - * unified. */ + /* + * Temporary hack to migrate acceleration to CSS 2.0. + * In the future the code for all pipe types should be + * unified. + */ *pipe = internal_pipe; if (!internal_pipe->config.acc_extension && internal_pipe->config.num_acc_stages == @@ -8653,21 +8796,23 @@ ia_css_pipe_create_extra(const struct ia_css_pipe_config *config, return ia_css_acc_pipe_create(internal_pipe); } - /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */ + /* + * Use config value when dvs_frame_delay setting equal to 2, + * otherwise always 1 by default + */ if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2) internal_pipe->dvs_frame_delay = 2; else internal_pipe->dvs_frame_delay = 1; - /* we still keep enable_raw_binning for backward compatibility, for any new - fractional bayer downscaling, we should use bayer_ds_out_res. if both are - specified, bayer_ds_out_res will take precedence.if none is specified, we - set bayer_ds_out_res equal to IF output resolution(IF may do cropping on - sensor output) or use default decimation factor 1. */ - if (internal_pipe->extra_config.enable_raw_binning && - internal_pipe->config.bayer_ds_out_res.width) { - /* fill some code here, if no code is needed, please remove it during integration */ - } + /* + * we still keep enable_raw_binning for backward compatibility, + * for any new fractional bayer downscaling, we should use + * bayer_ds_out_res. if both are specified, bayer_ds_out_res will + * take precedence.if none is specified, we set bayer_ds_out_res + * equal to IF output resolution(IF may do cropping on sensor output) + * or use default decimation factor 1. + */ /* YUV downscaling */ if ((internal_pipe->config.vf_pp_in_res.width || @@ -8871,8 +9016,10 @@ ia_css_stream_configure_rx(struct ia_css_stream *stream) if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE) stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE; else - /* not implemented yet, requires extension of the rx_cfg_t - * struct */ + /* + * not implemented yet, requires extension of the rx_cfg_t + * struct + */ return -EINVAL; stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2); @@ -8959,8 +9106,10 @@ metadata_info_init(const struct ia_css_metadata_config *mdc, return -EINVAL; md->resolution = mdc->resolution; - /* We round up the stride to a multiple of the width - * of the port going to DDR, this is a HW requirements (DMA). */ + /* + * We round up the stride to a multiple of the width + * of the port going to DDR, this is a HW requirements (DMA). + */ md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES); md->size = mdc->resolution.height * md->stride; return 0; @@ -9523,10 +9672,13 @@ ia_css_stream_destroy(struct ia_css_stream *stream) if (free_mpi) { for (i = 0; i < stream->num_pipes; i++) { struct ia_css_pipe *entry = stream->pipes[i]; - /* free any mipi frames that are remaining: - * some test stream create-destroy cycles do not generate output frames - * and the mipi buffer is not freed in the deque function - */ + /* + * free any mipi frames that are remaining: + * some test stream create-destroy cycles do + * not generate output frames + * and the mipi buffer is not freed in the + * deque function + */ if (entry) free_mipi_frames(entry); } @@ -9605,11 +9757,11 @@ ia_css_stream_get_info(const struct ia_css_stream *stream, } /* - * Rebuild a stream, including allocating structs, setting configuration and - * building the required pipes. - * The data is taken from the css_save struct updated upon stream creation. - * The stream handle is used to identify the correct entry in the css_save struct - */ + * Rebuild a stream, including allocating structs, setting configuration and + * building the required pipes. + * The data is taken from the css_save struct updated upon stream creation. + * The stream handle is used to identify the correct entry in the css_save struct + */ int ia_css_stream_load(struct ia_css_stream *stream) { @@ -9737,8 +9889,10 @@ ia_css_stream_stop(struct ia_css_stream *stream) if (err) return err; - /* Ideally, unmapping should happen after pipeline_stop, but current - * semantics do not allow that. */ + /* + * Ideally, unmapping should happen after pipeline_stop, but current + * semantics do not allow that. + */ /* err = map_sp_threads(stream, false); */ return err; @@ -9761,9 +9915,9 @@ ia_css_stream_has_stopped(struct ia_css_stream *stream) /* ISP2400 */ /* - * Destroy the stream and all the pipes related to it. - * The stream handle is used to identify the correct entry in the css_save struct - */ + * Destroy the stream and all the pipes related to it. + * The stream handle is used to identify the correct entry in the css_save struct + */ int ia_css_stream_unload(struct ia_css_stream *stream) { @@ -10026,11 +10180,12 @@ ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) { assert(pipe); - /* KW was not sure this function was not returning a value - that was out of range; so added an assert, and, for the - case when asserts are not enabled, clip to the largest - value; pipe_num is unsigned so the value cannot be too small - */ + /* + * KW was not sure this function was not returning a value + * that was out of range; so added an assert, and, for the + * case when asserts are not enabled, clip to the largest + * value; pipe_num is unsigned so the value cannot be too small + */ assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX); if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX) @@ -10085,10 +10240,10 @@ ia_css_start_sp(void) } /* - * Time to wait SP for termincate. Only condition when this can happen - * is a fatal hw failure, but we must be able to detect this and emit - * a proper error trace. - */ + * Time to wait SP for termincate. Only condition when this can happen + * is a fatal hw failure, but we must be able to detect this and emit + * a proper error trace. + */ #define SP_SHUTDOWN_TIMEOUT_US 200000 int @@ -10306,8 +10461,10 @@ ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) IA_CSS_ENTER(""); - /* Only continuous streams have a tagger to which we can send the - * unlock message. */ + /* + * Only continuous streams have a tagger to which we can send the + * unlock message. + */ if (!stream || !stream->config.continuous) { IA_CSS_ERROR("invalid stream pointer"); return -EINVAL; @@ -10319,8 +10476,10 @@ ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) return -EINVAL; } - /* Send the event. Since we verified that the exp_id is valid, - * we can safely assign it to an 8-bit argument here. */ + /* + * Send the event. Since we verified that the exp_id is valid, + * we can safely assign it to an 8-bit argument here. + */ ret = ia_css_bufq_enqueue_psys_event( IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0); @@ -10328,9 +10487,10 @@ ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) return ret; } -/* @brief Set the state (Enable or Disable) of the Extension stage in the - * given pipe. - */ +/* + * @brief Set the state (Enable or Disable) of the Extension stage in the + * given pipe. + */ int ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool enable) @@ -10374,9 +10534,10 @@ ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, return err; } -/* @brief Get the state (Enable or Disable) of the Extension stage in the - * given pipe. - */ +/* + * @brief Get the state (Enable or Disable) of the Extension stage in the + * given pipe. + */ int ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool *enable) From c35abde30ac69383328c21d368dbff8811ff8d89 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 12:18:52 +0000 Subject: [PATCH 118/397] media: atomisp: Avoid some {} just to define new vars There are a couple of places where {} are used just to define a new var. Just move the var to the top of the function and get rid of that ugly blocks. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 51 +++++++++------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 5ee777909cce..ac3519d08971 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -3884,6 +3884,7 @@ preview_start(struct ia_css_pipe *pipe) enum ia_css_input_mode preview_pipe_input_mode; const struct ia_css_coordinate *coord = NULL; const struct ia_css_isp_parameters *params = NULL; + unsigned int thread_id; IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) { @@ -3907,17 +3908,13 @@ preview_start(struct ia_css_pipe *pipe) } send_raw_frames(pipe); - { - unsigned int thread_id; + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); + copy_ovrd = 1 << thread_id; - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - copy_ovrd = 1 << thread_id; - - if (pipe->stream->cont_capt) { - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), - &thread_id); - copy_ovrd |= 1 << thread_id; - } + if (pipe->stream->cont_capt) { + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), + &thread_id); + copy_ovrd |= 1 << thread_id; } if (IS_ISP2401) { @@ -5653,9 +5650,9 @@ static int video_start(struct ia_css_pipe *pipe) struct ia_css_pipe *copy_pipe, *capture_pipe; enum sh_css_pipe_config_override copy_ovrd; enum ia_css_input_mode video_pipe_input_mode; - const struct ia_css_coordinate *coord = NULL; const struct ia_css_isp_parameters *params = NULL; + unsigned int thread_id; IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { @@ -5677,17 +5674,14 @@ static int video_start(struct ia_css_pipe *pipe) return err; send_raw_frames(pipe); - { - unsigned int thread_id; - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - copy_ovrd = 1 << thread_id; + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); + copy_ovrd = 1 << thread_id; - if (pipe->stream->cont_capt) { - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), - &thread_id); - copy_ovrd |= 1 << thread_id; - } + if (pipe->stream->cont_capt) { + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), + &thread_id); + copy_ovrd |= 1 << thread_id; } if (IS_ISP2401) { @@ -7254,6 +7248,7 @@ static int yuvpp_start(struct ia_css_pipe *pipe) int err = 0; enum sh_css_pipe_config_override copy_ovrd; enum ia_css_input_mode yuvpp_pipe_input_mode; + unsigned int thread_id; IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { @@ -7273,12 +7268,8 @@ static int yuvpp_start(struct ia_css_pipe *pipe) return err; } - { - unsigned int thread_id; - - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - copy_ovrd = 1 << thread_id; - } + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); + copy_ovrd = 1 << thread_id; start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode); @@ -8105,6 +8096,7 @@ create_host_capture_pipeline(struct ia_css_pipe *pipe) static int capture_start(struct ia_css_pipe *pipe) { struct ia_css_pipeline *me; + unsigned int thread_id; int err = 0; enum sh_css_pipe_config_override copy_ovrd; @@ -8145,12 +8137,9 @@ static int capture_start(struct ia_css_pipe *pipe) #endif - { - unsigned int thread_id; + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); + copy_ovrd = 1 << thread_id; - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - copy_ovrd = 1 << thread_id; - } start_pipe(pipe, copy_ovrd, pipe->stream->config.mode); #if !defined(ISP2401) From 47f6b6d498ec12e669c283799e7f7f5ca89cda0a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 15:53:12 +0000 Subject: [PATCH 119/397] media: atomisp: drop two vars that are currently ignored Those two vars are meaningful only with some ISP2401 firmwares. The one we chose to support doesn't use, so simply drop the extra code. Signed-off-by: Mauro Carvalho Chehab --- .../pci/runtime/pipeline/src/pipeline.c | 3 +- drivers/staging/media/atomisp/pci/sh_css.c | 49 +++---------------- drivers/staging/media/atomisp/pci/sh_css_sp.c | 7 +-- drivers/staging/media/atomisp/pci/sh_css_sp.h | 7 +-- 4 files changed, 10 insertions(+), 56 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/runtime/pipeline/src/pipeline.c b/drivers/staging/media/atomisp/pci/runtime/pipeline/src/pipeline.c index d03957d1ecf4..dfc50247ea8e 100644 --- a/drivers/staging/media/atomisp/pci/runtime/pipeline/src/pipeline.c +++ b/drivers/staging/media/atomisp/pci/runtime/pipeline/src/pipeline.c @@ -140,8 +140,7 @@ void ia_css_pipeline_start(enum ia_css_pipe_id pipe_id, false, false, false, true, SH_CSS_BDS_FACTOR_1_00, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD, IA_CSS_INPUT_MODE_MEMORY, NULL, NULL, - (enum mipi_port_id)0, - NULL, NULL); + (enum mipi_port_id)0); ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); if (!sh_css_sp_is_running()) { diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index ac3519d08971..3aa4f8bc39c4 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -1426,20 +1426,11 @@ static void start_pipe( enum sh_css_pipe_config_override copy_ovrd, enum ia_css_input_mode input_mode) { - const struct ia_css_coordinate *coord = NULL; - const struct ia_css_isp_parameters *params = NULL; - - IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d", me, copy_ovrd, input_mode); assert(me); /* all callers are in this file and call with non null argument */ - if (IS_ISP2401) { - coord = &me->config.internal_frame_origin_bqs_on_sctbl; - params = me->stream->isp_params_configs; - } - sh_css_sp_init_pipeline(&me->pipeline, me->mode, (uint8_t)ia_css_pipe_get_pipe_num(me), @@ -1454,9 +1445,7 @@ static void start_pipe( &me->stream->info.metadata_info , (input_mode == IA_CSS_INPUT_MODE_MEMORY) ? (enum mipi_port_id)0 : - me->stream->config.source.port.port, - coord, - params); + me->stream->config.source.port.port); if (me->config.mode != IA_CSS_PIPE_MODE_COPY) { struct ia_css_pipeline_stage *stage; @@ -3882,8 +3871,6 @@ preview_start(struct ia_css_pipe *pipe) struct ia_css_pipe *acc_pipe; enum sh_css_pipe_config_override copy_ovrd; enum ia_css_input_mode preview_pipe_input_mode; - const struct ia_css_coordinate *coord = NULL; - const struct ia_css_isp_parameters *params = NULL; unsigned int thread_id; IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); @@ -3913,15 +3900,10 @@ preview_start(struct ia_css_pipe *pipe) if (pipe->stream->cont_capt) { ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), - &thread_id); + &thread_id); copy_ovrd |= 1 << thread_id; } - if (IS_ISP2401) { - coord = &pipe->config.internal_frame_origin_bqs_on_sctbl; - params = pipe->stream->isp_params_configs; - } - /* Construct and load the copy pipe */ if (pipe->stream->config.continuous) { sh_css_sp_init_pipeline(©_pipe->pipeline, @@ -3934,9 +3916,7 @@ preview_start(struct ia_css_pipe *pipe) pipe->stream->config.mode, &pipe->stream->config.metadata_config, &pipe->stream->info.metadata_info, - pipe->stream->config.source.port.port, - coord, - params); + pipe->stream->config.source.port.port); /* * make the preview pipe start with mem mode input, copy handles @@ -3959,9 +3939,7 @@ preview_start(struct ia_css_pipe *pipe) IA_CSS_INPUT_MODE_MEMORY, &pipe->stream->config.metadata_config, &pipe->stream->info.metadata_info, - (enum mipi_port_id)0, - coord, - params); + (enum mipi_port_id)0); } if (acc_pipe) { @@ -3977,9 +3955,7 @@ preview_start(struct ia_css_pipe *pipe) IA_CSS_INPUT_MODE_MEMORY, NULL, NULL, - (enum mipi_port_id)0, - coord, - params); + (enum mipi_port_id)0); } start_pipe(pipe, copy_ovrd, preview_pipe_input_mode); @@ -5650,8 +5626,6 @@ static int video_start(struct ia_css_pipe *pipe) struct ia_css_pipe *copy_pipe, *capture_pipe; enum sh_css_pipe_config_override copy_ovrd; enum ia_css_input_mode video_pipe_input_mode; - const struct ia_css_coordinate *coord = NULL; - const struct ia_css_isp_parameters *params = NULL; unsigned int thread_id; IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); @@ -5684,11 +5658,6 @@ static int video_start(struct ia_css_pipe *pipe) copy_ovrd |= 1 << thread_id; } - if (IS_ISP2401) { - coord = &pipe->config.internal_frame_origin_bqs_on_sctbl; - params = pipe->stream->isp_params_configs; - } - /* Construct and load the copy pipe */ if (pipe->stream->config.continuous) { sh_css_sp_init_pipeline(©_pipe->pipeline, @@ -5701,9 +5670,7 @@ static int video_start(struct ia_css_pipe *pipe) pipe->stream->config.mode, &pipe->stream->config.metadata_config, &pipe->stream->info.metadata_info, - pipe->stream->config.source.port.port, - coord, - params); + pipe->stream->config.source.port.port); /* * make the video pipe start with mem mode input, copy handles @@ -5726,9 +5693,7 @@ static int video_start(struct ia_css_pipe *pipe) IA_CSS_INPUT_MODE_MEMORY, &pipe->stream->config.metadata_config, &pipe->stream->info.metadata_info, - (enum mipi_port_id)0, - coord, - params); + (enum mipi_port_id)0); } start_pipe(pipe, copy_ovrd, video_pipe_input_mode); diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index 77ac720017a2..ff7c2c5fd94d 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -1217,12 +1217,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, enum ia_css_input_mode input_mode, const struct ia_css_metadata_config *md_config, const struct ia_css_metadata_info *md_info, - const enum mipi_port_id port_id, - const struct ia_css_coordinate - *internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame - positioned on shading table at shading correction in ISP. */ - const struct ia_css_isp_parameters *params - ) + const enum mipi_port_id port_id) { /* Get first stage */ struct ia_css_pipeline_stage *stage = NULL; diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.h b/drivers/staging/media/atomisp/pci/sh_css_sp.h index 832eed711525..f69a79b0b0da 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.h +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.h @@ -66,12 +66,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, enum ia_css_input_mode input_mode, const struct ia_css_metadata_config *md_config, const struct ia_css_metadata_info *md_info, - const enum mipi_port_id port_id, - const struct ia_css_coordinate - *internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame - positioned on shading table at shading correction in ISP. */ - const struct ia_css_isp_parameters *params - ); + const enum mipi_port_id port_id); void sh_css_sp_uninit_pipeline(unsigned int pipe_num); From 7bedd01849d64e2b9c4b873342b5a3d0e45812eb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 16:05:51 +0000 Subject: [PATCH 120/397] media: atomisp: drop an useless #ifdef ISP2401 The Yocto Aero driver for ISP2401 sets my_css_save.loaded_fw. As we're using the same firmware, remove the ifdef there. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 3aa4f8bc39c4..51dbd4e495d0 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -1742,9 +1742,8 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, return err; } fw_explicitly_loaded = false; -#ifndef ISP2401 + my_css_save.loaded_fw = (struct ia_css_fw *)fw; -#endif } if (!sh_css_setup_spctrl_config(&sh_css_sp_fw, SP_PROG_NAME, &spctrl_cfg)) return -EINVAL; From 29a3764a76ede92fc7dda648f4e2ae1a32597671 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 18:12:56 +0000 Subject: [PATCH 121/397] media: atomisp: remove #ifdef HAS_OUTPUT_SYSTEM None of the firmwares we use has support for it. So, drop the unused code. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 2 -- drivers/staging/media/atomisp/pci/sh_css_params.c | 3 --- 2 files changed, 5 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 51dbd4e495d0..3a347b72e4bd 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -5507,7 +5507,6 @@ static int load_video_binaries(struct ia_css_pipe *pipe) (void)continuous; #endif -#if !defined(HAS_OUTPUT_SYSTEM) if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) { struct ia_css_binary_descr vf_pp_descr; @@ -5533,7 +5532,6 @@ static int load_video_binaries(struct ia_css_pipe *pipe) if (err) return err; } -#endif err = allocate_delay_frames(pipe); diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c index ccc007879564..b3ef6b4c3225 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/sh_css_params.c @@ -96,9 +96,6 @@ #include "xnr/xnr_3.0/ia_css_xnr3.host.h" -#if defined(HAS_OUTPUT_SYSTEM) -#include -#endif #include "sh_css_frac.h" #include "ia_css_bufq.h" From 16d0c92ef8a5e30cce5954c2a4c4f9aa179dbb0d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 12:13:13 +0000 Subject: [PATCH 122/397] media: atomisp: drop #ifdef SH_CSS_ENABLE_PER_FRAME_PARAMS This is enabled for the firmware we're using. So, just drop the if's. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 4 ---- .../staging/media/atomisp/pci/sh_css_internal.h | 2 -- .../staging/media/atomisp/pci/sh_css_params.c | 17 ----------------- drivers/staging/media/atomisp/pci/sh_css_sp.c | 2 -- .../staging/media/atomisp/pci/system_global.h | 3 --- 5 files changed, 28 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 3a347b72e4bd..6d3c4a0558e1 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -4154,14 +4154,12 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, return_err = ia_css_bufq_enqueue_buffer(thread_id, queue_id, (uint32_t)h_vbuf->vptr); -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) if (!return_err && buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d", ddr_buffer.payload.frame.frame_data, queue_id, thread_id); } -#endif } if (!return_err) { @@ -4364,12 +4362,10 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, sh_css_sp_get_binary_copy_size(); #endif } -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d", frame->data, frame->isp_config_id, thread_id); } -#endif ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n", diff --git a/drivers/staging/media/atomisp/pci/sh_css_internal.h b/drivers/staging/media/atomisp/pci/sh_css_internal.h index f26df3f44a7a..87ac3ea15dfc 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_internal.h +++ b/drivers/staging/media/atomisp/pci/sh_css_internal.h @@ -536,9 +536,7 @@ struct sh_css_sp_pipeline { ia_css_ptr cont_buf; /* Address of continuous buffer */ } metadata; #endif -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) u32 output_frame_queue_id; -#endif union { struct { u32 bytes_available; diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c index b3ef6b4c3225..448b07162382 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/sh_css_params.c @@ -731,13 +731,11 @@ sh_css_set_global_isp_config_on_pipe( const struct ia_css_isp_config *config, struct ia_css_pipe *pipe); -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) static int sh_css_set_per_frame_isp_config_on_pipe( struct ia_css_stream *stream, const struct ia_css_isp_config *config, struct ia_css_pipe *pipe); -#endif static int sh_css_update_uds_and_crop_info_based_on_zoom_region( @@ -1905,11 +1903,9 @@ ia_css_stream_set_isp_config_on_pipe( IA_CSS_ENTER("stream=%p, config=%p, pipe=%p", stream, config, pipe); -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) if (config->output_frame) err = sh_css_set_per_frame_isp_config_on_pipe(stream, config, pipe); else -#endif err = sh_css_set_global_isp_config_on_pipe(stream->pipes[0], config, pipe); IA_CSS_LEAVE_ERR(err); @@ -1930,11 +1926,9 @@ ia_css_pipe_set_isp_config(struct ia_css_pipe *pipe, ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "config=%p\n", config); -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) if (config->output_frame) err = sh_css_set_per_frame_isp_config_on_pipe(pipe->stream, config, pipe); else -#endif err = sh_css_set_global_isp_config_on_pipe(pipe, config, pipe_in); IA_CSS_LEAVE_ERR(err); return err; @@ -1969,7 +1963,6 @@ sh_css_set_global_isp_config_on_pipe( return err; } -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) static int sh_css_set_per_frame_isp_config_on_pipe( struct ia_css_stream *stream, @@ -2039,7 +2032,6 @@ exit: IA_CSS_LEAVE_ERR_PRIVATE(err); return err; } -#endif static int sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe, @@ -3253,15 +3245,10 @@ sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe, isp_pipe_version = ia_css_pipe_get_isp_pipe_version(pipe); ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) ia_css_query_internal_queue_id(params->output_frame ? IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET : IA_CSS_BUFFER_TYPE_PARAMETER_SET, thread_id, &queue_id); -#else - ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_PARAMETER_SET, thread_id, - &queue_id); -#endif if (!sh_css_sp_is_running()) { /* SP is not running. The queues are not valid */ err = -EBUSY; @@ -3357,12 +3344,10 @@ sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe, err = ia_css_bufq_enqueue_buffer(thread_id, queue_id, (uint32_t)cpy); if (err) { free_ia_css_isp_parameter_set_info(cpy); -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) IA_CSS_LOG("pfp: FAILED to add config id %d for OF %d to q %d on thread %d", isp_params_info.isp_parameters_id, isp_params_info.output_frame_ptr, queue_id, thread_id); -#endif break; } else { /* TMP: check discrepancy between nr of enqueued @@ -3384,12 +3369,10 @@ sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe, (uint8_t)thread_id, (uint8_t)queue_id, 0); -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) IA_CSS_LOG("pfp: added config id %d for OF %d to q %d on thread %d", isp_params_info.isp_parameters_id, isp_params_info.output_frame_ptr, queue_id, thread_id); -#endif } /* clean-up old copy */ ia_css_dequeue_param_buffers(/*pipe_num*/); diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index ff7c2c5fd94d..4a0206f564c9 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -1319,14 +1319,12 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, (void)md_info; #endif -#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID; if (pipe_id != IA_CSS_PIPE_ID_COPY) { ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, (enum sh_css_queue_id *)( &sh_css_sp_group.pipe[thread_id].output_frame_queue_id)); } -#endif IA_CSS_LOG("pipe_id %d port_config %08x", pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config); diff --git a/drivers/staging/media/atomisp/pci/system_global.h b/drivers/staging/media/atomisp/pci/system_global.h index 9b22b8c168be..060b924023ec 100644 --- a/drivers/staging/media/atomisp/pci/system_global.h +++ b/drivers/staging/media/atomisp/pci/system_global.h @@ -25,9 +25,6 @@ * N.B. the 3 input formatters are of 2 different classess */ -/* per-frame parameter handling support */ -#define SH_CSS_ENABLE_PER_FRAME_PARAMS - #define DMA_DDR_TO_VAMEM_WORKAROUND #define DMA_DDR_TO_HMEM_WORKAROUND From 52481d4d319c0179dfdf7c0ccd1b25ee435e303c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 15:46:36 +0000 Subject: [PATCH 123/397] media: atomisp: drop #ifdef WITH_PC_MONITORING This is not needed for the driver to work. So, just drop it. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 118 --------------------- 1 file changed, 118 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 6d3c4a0558e1..c3f08c69f36d 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -74,15 +74,6 @@ #define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0 -#if WITH_PC_MONITORING -#define MULTIPLE_SAMPLES 1 -#define NOF_SAMPLES 60 -#include "linux/kthread.h" -#include "linux/sched.h" -#include "linux/delay.h" -#include "sh_css_metrics.h" -static int thread_alive; -#endif /* WITH_PC_MONITORING */ #include "ia_css_spctrl.h" #include "ia_css_version_data.h" @@ -1261,89 +1252,6 @@ static inline int stream_unregister_with_csi_rx( } #endif -#if WITH_PC_MONITORING -static struct task_struct *my_kthread; /* Handle for the monitoring thread */ -static int sh_binary_running; /* Enable sampling in the thread */ - -static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist) -{ - unsigned int i; - unsigned int cnt_run = 0; - unsigned int cnt_stall = 0; - - if (!hist) - return; - - sh_css_print("%s histogram length = %d\n", core_name, hist->length); - sh_css_print("%s PC\turn\tstall\n", core_name); - - for (i = 0; i < hist->length; i++) { - if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i])) - continue; - sh_css_print("%s %d\t%d\t%d\n", - core_name, i, hist->run[i], hist->stall[i]); - cnt_run += hist->run[i]; - cnt_stall += hist->stall[i]; - } - - sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, hist->length = %d\n", - core_name, cnt_run, cnt_stall, hist->length); -} - -static void print_pc_histogram(void) -{ - struct ia_css_binary_metrics *metrics; - - for (metrics = sh_css_metrics.binary_metrics; - metrics; - metrics = metrics->next) { - if (metrics->mode == IA_CSS_BINARY_MODE_PREVIEW || - metrics->mode == IA_CSS_BINARY_MODE_VF_PP) { - sh_css_print("pc_histogram for binary %d is SKIPPED\n", - metrics->id); - continue; - } - - sh_css_print(" pc_histogram for binary %d\n", metrics->id); - print_pc_histo(" ISP", &metrics->isp_histogram); - print_pc_histo(" SP", &metrics->sp_histogram); - sh_css_print("print_pc_histogram() done for binary->id = %d, done.\n", - metrics->id); - } - - sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n"); -} - -static int pc_monitoring(void *data) -{ - int i = 0; - - (void)data; - while (true) { - if (sh_binary_running) { - sh_css_metrics_sample_pcs(); -#if MULTIPLE_SAMPLES - for (i = 0; i < NOF_SAMPLES; i++) - sh_css_metrics_sample_pcs(); -#endif - } - usleep_range(10, 50); - } - return 0; -} - -static void spying_thread_create(void) -{ - my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor"); - sh_css_metrics_enable_pc_histogram(1); -} - -static void input_frame_info(struct ia_css_frame_info frame_info) -{ - sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, frame->info.res.height = %d, format = %d\n", - frame_info.res.width, frame_info.res.height, frame_info.format); -} -#endif /* WITH_PC_MONITORING */ static void start_binary(struct ia_css_pipe *pipe, @@ -1355,15 +1263,6 @@ start_binary(struct ia_css_pipe *pipe, if (binary) sh_css_metrics_start_binary(&binary->metrics); -#if WITH_PC_MONITORING - sh_css_print("PC_MONITORING: %s() -- binary id = %d , enable_dvs_envelope = %d\n", - __func__, binary->info->sp.id, - binary->info->sp.enable.dvs_envelope); - input_frame_info(binary->in_frame_info); - - if (binary && binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_VIDEO) - sh_binary_running = true; -#endif #if !defined(ISP2401) if (pipe->stream->reconfigure_css_rx) { @@ -1754,14 +1653,6 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, return err; } -#if WITH_PC_MONITORING - if (!thread_alive) { - thread_alive++; - sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n", - __func__); - spying_thread_create(); - } -#endif if (!sh_css_hrt_system_is_idle()) { IA_CSS_LEAVE_ERR(-EBUSY); return -EBUSY; @@ -2427,10 +2318,6 @@ void ia_css_uninit(void) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n"); -#if WITH_PC_MONITORING - sh_css_print("PC_MONITORING: %s() -- started\n", __func__); - print_pc_histogram(); -#endif sh_css_params_free_default_gdc_lut(); @@ -2479,11 +2366,6 @@ int ia_css_irq_translate( if (status == hrt_isp_css_irq_status_error) return -EINVAL; -#if WITH_PC_MONITORING - sh_css_print("PC_MONITORING: %s() irq = %d, sh_binary_running set to 0\n", - __func__, irq); - sh_binary_running = 0; -#endif switch (irq) { case virq_sp: From 9e22032e9c9e801514daf0fdaba2ad587dc88497 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 22:19:50 +0000 Subject: [PATCH 124/397] media: atomisp: remove #ifdef SH_CSS_ENABLE_METADATA The chosen firmware has it enabled, so, drop this symbol. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 12 ------------ drivers/staging/media/atomisp/pci/sh_css_internal.h | 12 +----------- drivers/staging/media/atomisp/pci/sh_css_sp.c | 13 ------------- 3 files changed, 1 insertion(+), 36 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index c3f08c69f36d..1f0b941de71f 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -10195,9 +10195,7 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif if (pipe->pipe_settings.preview.preview_binary.info && pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a) ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); @@ -10210,9 +10208,7 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) { for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) { if (pipe->pipe_settings.capture.primary_binary[i].info && @@ -10237,9 +10233,7 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif if (pipe->pipe_settings.video.video_binary.info && pipe->pipe_settings.video.video_binary.info->sp.enable.s3a) ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map); @@ -10252,18 +10246,14 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); if (!pipe->stream->config.continuous) ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); -#if defined SH_CSS_ENABLE_METADATA ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) { if (need_input_queue) ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) { unsigned int idx; @@ -10275,9 +10265,7 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) if (need_input_queue) ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map); ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map); -#if defined SH_CSS_ENABLE_METADATA ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map); -#endif } IA_CSS_LEAVE(""); } diff --git a/drivers/staging/media/atomisp/pci/sh_css_internal.h b/drivers/staging/media/atomisp/pci/sh_css_internal.h index 87ac3ea15dfc..735540eceb37 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_internal.h +++ b/drivers/staging/media/atomisp/pci/sh_css_internal.h @@ -86,12 +86,6 @@ #define SH_CSS_MAX_IF_CONFIGS 3 /* Must match with IA_CSS_NR_OF_CONFIGS (not defined yet).*/ #define SH_CSS_IF_CONFIG_NOT_NEEDED 0xFF -#define SH_CSS_ENABLE_METADATA - -#if defined(SH_CSS_ENABLE_METADATA) && !defined(ISP2401) -#define SH_CSS_ENABLE_METADATA_THREAD -#endif - /* * SH_CSS_MAX_SP_THREADS: * sp threads visible to host with connected communication queues @@ -101,7 +95,7 @@ * these threads can't be used as image pipe */ -#if defined(SH_CSS_ENABLE_METADATA_THREAD) +#if !defined(ISP2401) #define SH_CSS_SP_INTERNAL_METADATA_THREAD 1 #else #define SH_CSS_SP_INTERNAL_METADATA_THREAD 0 @@ -526,7 +520,6 @@ struct sh_css_sp_pipeline { this struct; needs cleanup */ s32 num_execs; /* number of times to run if this is an acceleration pipe. */ -#if defined(SH_CSS_ENABLE_METADATA) struct { u32 format; /* Metadata format in hrt format */ u32 width; /* Width of a line */ @@ -535,7 +528,6 @@ struct sh_css_sp_pipeline { u32 size; /* Total size (in bytes) */ ia_css_ptr cont_buf; /* Address of continuous buffer */ } metadata; -#endif u32 output_frame_queue_id; union { struct { @@ -570,9 +562,7 @@ struct ia_css_frames_sp { struct ia_css_frame_sp_info internal_frame_info; struct ia_css_buffer_sp s3a_buf; struct ia_css_buffer_sp dvs_buf; -#if defined SH_CSS_ENABLE_METADATA struct ia_css_buffer_sp metadata_buf; -#endif }; /* Information for a single pipeline stage for an ISP */ diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index 4a0206f564c9..778639f391cb 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -330,9 +330,7 @@ sh_css_sp_start_isys_copy(struct ia_css_frame *out_frame, unsigned int thread_id; u8 stage_num = 0; struct sh_css_sp_pipeline *pipe; -#if defined SH_CSS_ENABLE_METADATA enum sh_css_queue_id queue_id; -#endif assert(out_frame); @@ -372,7 +370,6 @@ sh_css_sp_start_isys_copy(struct ia_css_frame *out_frame, set_output_frame_buffer(out_frame, 0); -#if defined SH_CSS_ENABLE_METADATA if (pipe->metadata.height > 0) { ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id); @@ -380,7 +377,6 @@ sh_css_sp_start_isys_copy(struct ia_css_frame *out_frame, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA); } -#endif ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame); } @@ -904,9 +900,7 @@ initialize_stage_frames(struct ia_css_frames_sp *frames) initialize_frame_buffer_attribute(&frames->out_vf.buf_attr); initialize_frame_buffer_attribute(&frames->s3a_buf); initialize_frame_buffer_attribute(&frames->dvs_buf); -#if defined SH_CSS_ENABLE_METADATA initialize_frame_buffer_attribute(&frames->metadata_buf); -#endif } static int @@ -1032,10 +1026,8 @@ sh_css_sp_init_stage(struct ia_css_binary *binary, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_DIS_STATISTICS); } -#if defined SH_CSS_ENABLE_METADATA ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id); sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA); -#endif if (err) return err; @@ -1304,7 +1296,6 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, } sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe); -#if defined(SH_CSS_ENABLE_METADATA) if (md_info && md_info->size > 0) { sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width; sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height; @@ -1314,10 +1305,6 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, md_config->data_type, MIPI_PREDICTOR_NONE, &sh_css_sp_group.pipe[thread_id].metadata.format); } -#else - (void)md_config; - (void)md_info; -#endif sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID; if (pipe_id != IA_CSS_PIPE_ID_COPY) { From 2a01213bfa104ab90d861d86fcee5dea1a865592 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 23:33:01 +0000 Subject: [PATCH 125/397] media: atomisp: solve #ifdef HAS_NO_PACKED_RAW_PIXELS This was never defined, so remove the #ifdefs, keeping the code. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c | 2 -- drivers/staging/media/atomisp/pci/sh_css.c | 2 -- drivers/staging/media/atomisp/pci/sh_css_mipi.c | 4 ---- 3 files changed, 8 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c b/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c index 3e3e5a4f8117..d09cc486e33e 100644 --- a/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c +++ b/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c @@ -571,11 +571,9 @@ void ia_css_pipe_get_primary_binarydesc( in_info->res = pipe->config.input_effective_res; in_info->padded_width = in_info->res.width; -#if !defined(HAS_NO_PACKED_RAW_PIXELS) if (pipe->stream->config.pack_raw_pixels) in_info->format = IA_CSS_FRAME_FORMAT_RAW_PACKED; else -#endif in_info->format = IA_CSS_FRAME_FORMAT_RAW; in_info->raw_bit_depth = ia_css_pipe_util_pipe_input_format_bpp(pipe); diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 1f0b941de71f..d1074c3d56c6 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -2570,13 +2570,11 @@ alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time) ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS); #endif -#if !defined(HAS_NO_PACKED_RAW_PIXELS) if (pipe->stream->config.pack_raw_pixels) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n"); ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED; } else -#endif { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n"); diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index de56a1da754d..87f1df575d9f 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -133,15 +133,11 @@ ia_css_mipi_frame_calculate_size(const unsigned int width, break; case ATOMISP_INPUT_FORMAT_YUV420_10: /* odd 4p, 5B, 40bits, even 4p, 10B, 80bits */ case ATOMISP_INPUT_FORMAT_RAW_10: /* 4p, 5B, 40bits */ -#if !defined(HAS_NO_PACKED_RAW_PIXELS) /* The changes will be reverted as soon as RAW * Buffers are deployed by the 2401 Input System * in the non-continuous use scenario. */ bits_per_pixel = 10; -#else - bits_per_pixel = 16; -#endif break; case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: /* 2p, 3B, 24bits */ case ATOMISP_INPUT_FORMAT_RAW_12: /* 2p, 3B, 24bits */ From 0a9e6351ea709249e7bd1796ffe832ebb81befde Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 18:48:50 +0000 Subject: [PATCH 126/397] media: atomisp: drop crop code at stream create function The firmware chosen for ISP2401 doesn't support it. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 164 --------------------- 1 file changed, 164 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index d1074c3d56c6..6f1dca0788b4 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -400,17 +400,7 @@ static unsigned int get_crop_columns_for_bayer_order(const struct ia_css_stream_config *config); static void get_pipe_extra_pixel(struct ia_css_pipe *pipe, unsigned int *extra_row, unsigned int *extra_column); -static int -aspect_ratio_crop_init(struct ia_css_stream *curr_stream, - struct ia_css_pipe *pipes[], - bool *do_crop_status); -static bool -aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe); - -static int -aspect_ratio_crop(struct ia_css_pipe *curr_pipe, - struct ia_css_resolution *effective_res); #endif static void @@ -8999,9 +8989,6 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, int err = -EINVAL; struct ia_css_metadata_info md_info; struct ia_css_resolution effective_res; -#ifdef ISP2401 - bool aspect_ratio_crop_enabled = false; -#endif IA_CSS_ENTER("num_pipes=%d", num_pipes); ia_css_debug_dump_stream_config(stream_config, num_pipes); @@ -9178,14 +9165,6 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, IA_CSS_LOG("mode sensor/default"); } -#ifdef ISP2401 - err = aspect_ratio_crop_init(curr_stream, pipes, - &aspect_ratio_crop_enabled); - if (err) { - IA_CSS_LEAVE_ERR(err); - goto ERR; - } -#endif for (i = 0; i < num_pipes; i++) { struct ia_css_resolution effective_res; @@ -9198,22 +9177,6 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, if (effective_res.height == 0 || effective_res.width == 0) { effective_res = curr_pipe->stream->config.input_config.effective_res; -#if defined(ISP2401) - /* The aspect ratio cropping is currently only - * supported on the new input system. */ - if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) { - struct ia_css_resolution crop_res; - - err = aspect_ratio_crop(curr_pipe, &crop_res); - if (!err) { - effective_res = crop_res; - } else { - /* in case of error fallback to default - * effective resolution from driver. */ - IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err); - } - } -#endif curr_pipe->config.input_effective_res = effective_res; } IA_CSS_LOG("effective_res=%dx%d", @@ -10470,133 +10433,6 @@ ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, return err; } -#ifdef ISP2401 -static int -aspect_ratio_crop_init(struct ia_css_stream *curr_stream, - struct ia_css_pipe *pipes[], - bool *do_crop_status) -{ - int err = 0; - int i; - struct ia_css_pipe *curr_pipe; - u32 pipe_mask = 0; - - if ((!curr_stream) || - (curr_stream->num_pipes == 0) || - (!pipes) || - (!do_crop_status)) { - err = -EINVAL; - IA_CSS_LEAVE_ERR(err); - return err; - } - - for (i = 0; i < curr_stream->num_pipes; i++) { - curr_pipe = pipes[i]; - pipe_mask |= (1 << curr_pipe->config.mode); - } - - *do_crop_status = - (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) || - (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) && - (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) && - curr_stream->config.continuous); - return 0; -} - -static bool -aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) -{ - bool status = false; - - if ((curr_pipe) && enabled) { - if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) || - (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) || - (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE)) - status = true; - } - - return status; -} - -static int -aspect_ratio_crop(struct ia_css_pipe *curr_pipe, - struct ia_css_resolution *effective_res) -{ - int err = 0; - struct ia_css_resolution crop_res; - struct ia_css_resolution *in_res = NULL; - struct ia_css_resolution *out_res = NULL; - bool use_bds_output_info = false; - bool use_vf_pp_in_res = false; - bool use_capt_pp_in_res = false; - - if ((!curr_pipe) || - (!effective_res)) { - err = -EINVAL; - IA_CSS_LEAVE_ERR(err); - return err; - } - - if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) && - (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) && - (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) { - err = -EINVAL; - IA_CSS_LEAVE_ERR(err); - return err; - } - - use_bds_output_info = - ((curr_pipe->bds_output_info.res.width != 0) && - (curr_pipe->bds_output_info.res.height != 0)); - - use_vf_pp_in_res = - ((curr_pipe->config.vf_pp_in_res.width != 0) && - (curr_pipe->config.vf_pp_in_res.height != 0)); - - use_capt_pp_in_res = - ((curr_pipe->config.capt_pp_in_res.width != 0) && - (curr_pipe->config.capt_pp_in_res.height != 0)); - - in_res = &curr_pipe->stream->config.input_config.effective_res; - out_res = &curr_pipe->output_info[0].res; - - switch (curr_pipe->config.mode) { - case IA_CSS_PIPE_MODE_PREVIEW: - if (use_bds_output_info) - out_res = &curr_pipe->bds_output_info.res; - else if (use_vf_pp_in_res) - out_res = &curr_pipe->config.vf_pp_in_res; - break; - case IA_CSS_PIPE_MODE_VIDEO: - if (use_bds_output_info) - out_res = &curr_pipe->bds_output_info.res; - break; - case IA_CSS_PIPE_MODE_CAPTURE: - if (use_capt_pp_in_res) - out_res = &curr_pipe->config.capt_pp_in_res; - break; - case IA_CSS_PIPE_MODE_ACC: - case IA_CSS_PIPE_MODE_COPY: - case IA_CSS_PIPE_MODE_YUVPP: - default: - IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n", - curr_pipe->config.mode); - assert(0); - break; - } - - err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res); - if (!err) - *effective_res = crop_res; - else - /* in case of error fallback to default - * effective resolution from driver. */ - IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err); - - return err; -} -#endif - static void sh_css_hmm_buffer_record_init(void) { From 802dfce3b96e538a101fd1ba413ea1db11ba1df0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 19:35:02 +0000 Subject: [PATCH 127/397] media: atomisp: get rid of ia_css_stream_load() This function is marked as obsolete and nobody calls it. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/ia_css_stream_public.h | 9 ---- drivers/staging/media/atomisp/pci/sh_css.c | 52 ------------------- 2 files changed, 61 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/ia_css_stream_public.h b/drivers/staging/media/atomisp/pci/ia_css_stream_public.h index 83846e417ae5..649f22b03de8 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_stream_public.h +++ b/drivers/staging/media/atomisp/pci/ia_css_stream_public.h @@ -202,15 +202,6 @@ int ia_css_stream_get_info(const struct ia_css_stream *stream, struct ia_css_stream_info *stream_info); -/* @brief load (rebuild) a stream that was unloaded. - * @param[in] stream The stream - * @return 0 or the error code - * - * Rebuild a stream, including allocating structs, setting configuration and - * building the required pipes. - */ -int -ia_css_stream_load(struct ia_css_stream *stream); /* @brief Starts the stream. * @param[in] stream The stream. diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 6f1dca0788b4..c73ef67959c9 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -9546,58 +9546,6 @@ ia_css_stream_get_info(const struct ia_css_stream *stream, return 0; } -/* - * Rebuild a stream, including allocating structs, setting configuration and - * building the required pipes. - * The data is taken from the css_save struct updated upon stream creation. - * The stream handle is used to identify the correct entry in the css_save struct - */ -int -ia_css_stream_load(struct ia_css_stream *stream) -{ - int i, j, err; - - if (IS_ISP2401) { - /* TODO remove function - DEPRECATED */ - (void)stream; - return -ENOTSUPP; - } - - assert(stream); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n"); - for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { - if (my_css_save.stream_seeds[i].stream != stream) - continue; - - for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) { - int k; - - err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j], - &my_css_save.stream_seeds[i].pipes[j]); - if (!err) - continue; - - for (k = 0; k < j; k++) - ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]); - return err; - } - err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config, - my_css_save.stream_seeds[i].num_pipes, - my_css_save.stream_seeds[i].pipes, - &my_css_save.stream_seeds[i].stream); - if (!err) - break; - - ia_css_stream_destroy(stream); - for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) - ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]); - return err; - } - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit,\n"); - return 0; -} - int ia_css_stream_start(struct ia_css_stream *stream) { From 6a28541ff52f30bded470fdf68b8d196ea17403d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 19:40:26 +0000 Subject: [PATCH 128/397] media: atomisp: unify ia_css_stream stop logic There are two versions of those functions. It turns that the choosen firmware use the old version. So, drop the unused ones and ensure that all devices will use the right functions. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 214 +-------------------- 1 file changed, 2 insertions(+), 212 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index c73ef67959c9..adec184c8536 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -189,27 +189,6 @@ allocate_delay_frames(struct ia_css_pipe *pipe); static int sh_css_pipe_start(struct ia_css_stream *stream); -/* ISP 2401 */ -/* - * @brief Stop all "ia_css_pipe" instances in the target - * "ia_css_stream" instance. - * - * @param[in] stream Point to the target "ia_css_stream" instance. - * - * @return - * - 0, if the "stop" requests have been successfully sent out. - * - CSS error code, otherwise. - * - * - * NOTE - * This API sends the "stop" requests to the "ia_css_pipe" - * instances in the same "ia_css_stream" instance. It will - * return without waiting for all "ia_css_pipe" instatnces - * being stopped. - */ -static int -sh_css_pipes_stop(struct ia_css_stream *stream); - /* * @brief Check if all "ia_css_pipe" instances in the target * "ia_css_stream" instance have stopped. @@ -221,9 +200,6 @@ sh_css_pipes_stop(struct ia_css_stream *stream); * instance have ben stopped. * - false, otherwise. */ -/* ISP 2401 */ -static bool -sh_css_pipes_have_stopped(struct ia_css_stream *stream); /* ISP 2401 */ static int @@ -4786,185 +4762,6 @@ ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, return 0; } -/* - * @brief Stop all "ia_css_pipe" instances in the target - * "ia_css_stream" instance. - * - * Refer to "Local prototypes" for more info. - */ -/* ISP2401 */ -static int -sh_css_pipes_stop(struct ia_css_stream *stream) -{ - int err = 0; - struct ia_css_pipe *main_pipe; - enum ia_css_pipe_id main_pipe_id; - int i; - - if (!stream) { - IA_CSS_LOG("stream does NOT exist!"); - err = -EINVAL; - goto ERR; - } - - main_pipe = stream->last_pipe; - if (!main_pipe) { - IA_CSS_LOG("main_pipe does NOT exist!"); - err = -EINVAL; - goto ERR; - } - - main_pipe_id = main_pipe->mode; - IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id); - - /* - * Stop all "ia_css_pipe" instances in this target - * "ia_css_stream" instance. - */ - for (i = 0; i < stream->num_pipes; i++) { - /* send the "stop" request to the "ia_css_pipe" instance */ - IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", - stream->pipes[i]->pipeline.pipe_id); - err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline); - - /* - * Exit this loop if "ia_css_pipeline_request_stop()" - * returns the error code. - * - * The error code would be generated in the following - * two cases: - * (1) The Scalar Processor has already been stopped. - * (2) The "Host->SP" event queue is full. - * - * As the convention of using CSS API 2.0/2.1, such CSS - * error code would be propogated from the CSS-internal - * API returned value to the CSS API returned value. Then - * the CSS driver should capture these error code and - * handle it in the driver exception handling mechanism. - */ - if (err) - goto ERR; - } - - /* - * In the CSS firmware use scenario "Continuous Preview" - * as well as "Continuous Video", the "ia_css_pipe" instance - * "Copy Pipe" is activated. This "Copy Pipe" is private to - * the CSS firmware so that it is not listed in the target - * "ia_css_stream" instance. - * - * We need to stop this "Copy Pipe", as well. - */ - if (main_pipe->stream->config.continuous) { - struct ia_css_pipe *copy_pipe = NULL; - - /* get the reference to "Copy Pipe" */ - if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW) - copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; - else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO) - copy_pipe = main_pipe->pipe_settings.video.copy_pipe; - - /* return the error code if "Copy Pipe" does NOT exist */ - if (!copy_pipe) { - IA_CSS_LOG("Copy Pipe does NOT exist!"); - err = -EINVAL; - goto ERR; - } - - /* send the "stop" request to "Copy Pipe" */ - IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", - copy_pipe->pipeline.pipe_id); - err = ia_css_pipeline_request_stop(©_pipe->pipeline); - } - -ERR: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - -/* - * @brief Check if all "ia_css_pipe" instances in the target - * "ia_css_stream" instance have stopped. - * - * Refer to "Local prototypes" for more info. - */ -/* ISP2401 */ -static bool -sh_css_pipes_have_stopped(struct ia_css_stream *stream) -{ - bool rval = true; - - struct ia_css_pipe *main_pipe; - enum ia_css_pipe_id main_pipe_id; - - int i; - - if (!stream) { - IA_CSS_LOG("stream does NOT exist!"); - rval = false; - goto RET; - } - - main_pipe = stream->last_pipe; - - if (!main_pipe) { - IA_CSS_LOG("main_pipe does NOT exist!"); - rval = false; - goto RET; - } - - main_pipe_id = main_pipe->mode; - IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id); - - /* - * Check if every "ia_css_pipe" instance in this target - * "ia_css_stream" instance has stopped. - */ - for (i = 0; i < stream->num_pipes; i++) { - rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline); - IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d", - stream->pipes[i]->pipeline.pipe_id, - rval); - } - - /* - * In the CSS firmware use scenario "Continuous Preview" - * as well as "Continuous Video", the "ia_css_pipe" instance - * "Copy Pipe" is activated. This "Copy Pipe" is private to - * the CSS firmware so that it is not listed in the target - * "ia_css_stream" instance. - * - * We need to check if this "Copy Pipe" has stopped, as well. - */ - if (main_pipe->stream->config.continuous) { - struct ia_css_pipe *copy_pipe = NULL; - - /* get the reference to "Copy Pipe" */ - if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW) - copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; - else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO) - copy_pipe = main_pipe->pipe_settings.video.copy_pipe; - - /* return if "Copy Pipe" does NOT exist */ - if (!copy_pipe) { - IA_CSS_LOG("Copy Pipe does NOT exist!"); - - rval = false; - goto RET; - } - - /* check if "Copy Pipe" has stopped or not */ - rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline); - IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d", - copy_pipe->pipeline.pipe_id, - rval); - } - -RET: - IA_CSS_LEAVE_PRIVATE("rval=%d", rval); - return rval; -} - #if !defined(ISP2401) unsigned int sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx) @@ -9619,11 +9416,7 @@ ia_css_stream_stop(struct ia_css_stream *stream) } #endif - if (!IS_ISP2401) - err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline); - else - err = sh_css_pipes_stop(stream); - + err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline); if (err) return err; @@ -9643,10 +9436,7 @@ ia_css_stream_has_stopped(struct ia_css_stream *stream) assert(stream); - if (!IS_ISP2401) - stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline); - else - stopped = sh_css_pipes_have_stopped(stream); + stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline); return stopped; } From 1de7694155a7615b17b14af79ce9bd4abfba7f15 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 22:34:08 +0000 Subject: [PATCH 129/397] media: atomisp: drop ia_css_pipe_update_qos_ext_mapped_arg This function is not used. Drop it. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/ia_css_pipe_public.h | 23 ------ drivers/staging/media/atomisp/pci/sh_css.c | 82 ------------------- 2 files changed, 105 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h b/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h index 45e8fe36cb74..7352cbf779fb 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h +++ b/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h @@ -479,29 +479,6 @@ ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, u32 fw_handle, bool *enable); -/* ISP2401 */ -/* @brief Update mapped CSS and ISP arguments for QoS pipe during SP runtime. - * @param[in] pipe Pipe handle. - * @param[in] fw_handle Extension firmware Handle (ia_css_fw_info.handle). - * @param[in] css_seg Parameter memory descriptors for CSS segments. - * @param[in] isp_seg Parameter memory descriptors for ISP segments. - * - * @return - * 0 : Success - * -EINVAL : Invalid Parameters - * -EBUSY : Inactive QOS Pipe - * (No active stream with this pipe) - * - * \deprecated{This interface is used to temporarily support a late-developed, - * specific use-case on a specific IPU2 platform. It will not be supported or - * maintained on IPU3 or further.} - */ -int -ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, - u32 fw_handle, - struct ia_css_isp_param_css_segments *css_seg, - struct ia_css_isp_param_isp_segments *isp_seg); - /* @brief Get selected configuration settings * @param[in] pipe The pipe. * @param[out] config Configuration settings. diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index adec184c8536..766d92a4c2eb 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -10089,88 +10089,6 @@ ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, return err; } -/* ISP2401 */ -int -ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, - u32 fw_handle, - struct ia_css_isp_param_css_segments *css_seg, - struct ia_css_isp_param_isp_segments *isp_seg) -{ - unsigned int HIVE_ADDR_sp_group; - static struct sh_css_sp_group sp_group; - static struct sh_css_sp_stage sp_stage; - static struct sh_css_isp_stage isp_stage; - const struct ia_css_fw_info *fw; - unsigned int thread_id; - struct ia_css_pipeline_stage *stage; - int err = 0; - int stage_num = 0; - enum ia_css_isp_memories mem; - bool enabled; - - IA_CSS_ENTER(""); - - fw = &sh_css_sp_fw; - - /* Parameter Check */ - if (!pipe || !pipe->stream) { - IA_CSS_ERROR("Invalid Pipe."); - err = -EINVAL; - } else if (!(pipe->config.acc_extension)) { - IA_CSS_ERROR("Invalid Pipe (No Extension Firmware)."); - err = -EINVAL; - } else if (!sh_css_sp_is_running()) { - IA_CSS_ERROR("Leaving: queue unavailable."); - err = -EBUSY; - } else { - /* Query the thread_id and stage_num corresponding to the Extension firmware */ - ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); - err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); - if (!err) { - /* Get the Extension State */ - enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id], - stage->stage_num)) ? true : false; - /* Update mapped arg only when extension stage is not enabled */ - if (enabled) { - IA_CSS_ERROR("Leaving: cannot update when stage is enabled."); - err = -EBUSY; - } else { - stage_num = stage->stage_num; - - HIVE_ADDR_sp_group = fw->info.sp.group; - sp_dmem_load(SP0_ID, - (unsigned int)sp_address_of(sp_group), - &sp_group, - sizeof(struct sh_css_sp_group)); - hmm_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num], - &sp_stage, sizeof(struct sh_css_sp_stage)); - - hmm_load(sp_stage.isp_stage_addr, - &isp_stage, sizeof(struct sh_css_isp_stage)); - - for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) { - isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address = - css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address; - isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size = - css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size; - isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address - = - isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address; - isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size - = - isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size; - } - - hmm_store(sp_stage.isp_stage_addr, - &isp_stage, - sizeof(struct sh_css_isp_stage)); - } - } - } - IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle); - return err; -} - static void sh_css_hmm_buffer_record_init(void) { From e05b3bbbf12f2a1352b375ea6d16dae92f70bb7c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Nov 2021 09:13:38 +0000 Subject: [PATCH 130/397] media: atomisp: drop a dead code There's a commented dead code related to some future thing to be implemented. As this won't happen, as it would require a newer firmware, just drop the code. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 31 ---------------------- 1 file changed, 31 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 766d92a4c2eb..5d022bb373a6 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -3833,38 +3833,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, } buf_type = buffer->type; - /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME - is removed */ -#if 0 - if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { - bool found_pipe = false; - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) && - (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) { - buf_type += i; - found_pipe = true; - break; - } - } - if (!found_pipe) - return -EINVAL; - } - if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) { - bool found_pipe = false; - - for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { - if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) && - (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) { - buf_type += i; - found_pipe = true; - break; - } - } - if (!found_pipe) - return -EINVAL; - } -#endif pipe_id = pipe->mode; IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type); From 37746513f6821e32c0c2dbac50985802ed556c32 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 18:43:22 +0000 Subject: [PATCH 131/397] media: atomisp: get rid of some weird warn-suppress logic There are some dead code meant to suppress "C_RUN" warnings. Drop it from sh_css.c, as it doesn't make much sense. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 5d022bb373a6..6970cf8a5dfe 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -8198,15 +8198,6 @@ sh_css_init_host_sp_control_vars(void) #endif HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com; - (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */ - - (void)HIVE_ADDR_sp_sleep_mode; - (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb; -#ifndef ISP2401 - (void)HIVE_ADDR_sp_stop_copy_preview; -#endif - (void)HIVE_ADDR_host_sp_com; - sp_dmem_store_uint32(SP0_ID, (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started), (uint32_t)(0)); From dc41f7df78af19ba56c689c6deb7efe5aa7e22b6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 18:54:50 +0000 Subject: [PATCH 132/397] media: atomisp: drop check_pipe_resolutions() logic Such function doesn't exist on Intel Aero driver. As we're using its firmware, it may mean that this is not compatible with the current file. So, drop it. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 56 ---------------------- 1 file changed, 56 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 6970cf8a5dfe..12dfecbb6145 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -208,8 +208,6 @@ ia_css_pipe_check_format(struct ia_css_pipe *pipe, /* ISP 2401 */ static int -check_pipe_resolutions(const struct ia_css_pipe *pipe); - static int ia_css_pipe_load_extension(struct ia_css_pipe *pipe, struct ia_css_fw_info *firmware); @@ -8689,49 +8687,6 @@ metadata_info_init(const struct ia_css_metadata_config *mdc, return 0; } -/* ISP2401 */ -static int check_pipe_resolutions(const struct ia_css_pipe *pipe) -{ - int err = 0; - - IA_CSS_ENTER_PRIVATE(""); - - if (!pipe || !pipe->stream) { - IA_CSS_ERROR("null arguments"); - err = -EINVAL; - goto EXIT; - } - - if (ia_css_util_check_res(pipe->config.input_effective_res.width, - pipe->config.input_effective_res.height) != 0) { - IA_CSS_ERROR("effective resolution not supported"); - err = -EINVAL; - goto EXIT; - } - if (!ia_css_util_resolution_is_zero( - pipe->stream->config.input_config.input_res)) { - if (!ia_css_util_res_leq(pipe->config.input_effective_res, - pipe->stream->config.input_config.input_res)) { - IA_CSS_ERROR("effective resolution is larger than input resolution"); - err = -EINVAL; - goto EXIT; - } - } - if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) { - IA_CSS_ERROR("output resolution must be even"); - err = -EINVAL; - goto EXIT; - } - if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) { - IA_CSS_ERROR("VF resolution must be even"); - err = -EINVAL; - goto EXIT; - } -EXIT: - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - int ia_css_stream_create(const struct ia_css_stream_config *stream_config, int num_pipes, @@ -8941,17 +8896,6 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, effective_res.height); } - if (IS_ISP2401) { - for (i = 0; i < num_pipes; i++) { - if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC && - pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) { - err = check_pipe_resolutions(pipes[i]); - if (err) - goto ERR; - } - } - } - err = ia_css_stream_isp_parameters_init(curr_stream); if (err) goto ERR; From ec1804dadf362882f526b2f7e18893d8eb2bd1dd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Nov 2021 09:13:32 +0000 Subject: [PATCH 133/397] media: atomisp: warn if mipi de-allocation failed There's a note at the uninit function that warns about issues with mipi frames de-allocation. print a warning if the problem ever happens. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 6 +++++- drivers/staging/media/atomisp/pci/sh_css_mipi.c | 11 +++++++++++ drivers/staging/media/atomisp/pci/sh_css_mipi.h | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 12dfecbb6145..8bcf610ccae3 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -20,6 +20,8 @@ #include "hmm.h" +#include "atomisp_internal.h" + #include "ia_css.h" #include "sh_css_hrt.h" /* only for file 2 MIPI */ #include "ia_css_buffer.h" @@ -2286,7 +2288,9 @@ ia_css_uninit(void) sh_css_params_free_default_gdc_lut(); /* TODO: JB: implement decent check and handling of freeing mipi frames */ - //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed + if (!mipi_is_free()) + dev_warn(atomisp_dev, "mipi frames are not freed.\n"); + /* cleanup generic data */ sh_css_params_uninit(); ia_css_refcount_uninit(); diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index 87f1df575d9f..cfaa4719177c 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -261,6 +261,17 @@ mipi_init(void) ref_count_mipi_allocation[i] = 0; } +bool mipi_is_free(void) +{ + unsigned int i; + + for (i = 0; i < N_CSI_PORTS; i++) + if (ref_count_mipi_allocation[i]) + return false; + + return true; +} + int calculate_mipi_buff_size( struct ia_css_stream_config *stream_cfg, diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.h b/drivers/staging/media/atomisp/pci/sh_css_mipi.h index 52f08a103883..dffec2205620 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.h +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.h @@ -23,6 +23,8 @@ void mipi_init(void); +bool mipi_is_free(void); + int allocate_mipi_frames(struct ia_css_pipe *pipe, struct ia_css_stream_info *info); From 912680064f94e37cf4a5c26e699d1da0e555e1f0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Nov 2021 17:32:45 +0000 Subject: [PATCH 134/397] media: atomisp: make sh_css similar to Intel Aero driver As we're using the firmware from Intel Aero, ensure that the logic inside sh_css as similar as possible to such driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 150 +++------------------ 1 file changed, 19 insertions(+), 131 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 8bcf610ccae3..e5e22f966286 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -210,7 +210,6 @@ ia_css_pipe_check_format(struct ia_css_pipe *pipe, /* ISP 2401 */ static int -static int ia_css_pipe_load_extension(struct ia_css_pipe *pipe, struct ia_css_fw_info *firmware); @@ -1023,17 +1022,6 @@ sh_css_config_input_network(struct ia_css_stream *stream) pipe = stream->last_pipe->pipe_settings.video.copy_pipe; } else { pipe = stream->last_pipe; - if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { - /* - * We need to poll the ISYS HW in capture_indication itself - * for "non-continuous" capture usecase for getting accurate - * isys frame capture timestamps. - * This is because the capturepipe propcessing takes longer - * to execute than the input system frame capture. - * 2401 specific - */ - early_polling = true; - } } if (!pipe) @@ -2695,17 +2683,6 @@ load_preview_binaries(struct ia_css_pipe *pipe) if (err) return err; - if (IS_ISP2401) { - /* The delay latency determines the number of invalid frames after - * a stream is started. */ - pipe->num_invalid_frames = pipe->dvs_frame_delay; - pipe->info.num_invalid_frames = pipe->num_invalid_frames; - - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n", - pipe->num_invalid_frames, pipe->dvs_frame_delay); - } - /* The vf_pp binary is needed when (further) YUV downscaling is required */ need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width; need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height; @@ -4847,6 +4824,8 @@ sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe, ia_css_binary_dvs_stat_grid_info(binary, info, pipe); } else { memset(&info->dvs_grid, 0, sizeof(info->dvs_grid)); + memset(&info->dvs_grid.dvs_stat_grid_info, 0, + sizeof(info->dvs_grid.dvs_stat_grid_info)); } if (binary) { @@ -5173,35 +5152,10 @@ static int load_video_binaries(struct ia_css_pipe *pipe) return err; if (mycs->video_binary.info->sp.enable.block_output) { - unsigned int tnr_width; - unsigned int tnr_height; - tnr_info = mycs->video_binary.out_frame_info[0]; - if (IS_ISP2401) { - /* Select resolution for TNR. If - * output_system_in_resolution(GDC_out_resolution) is - * being used, then select that as it will also be in resolution for - * TNR. At present, it only make sense for Skycam */ - if (pipe->config.output_system_in_res.width && - pipe->config.output_system_in_res.height) { - tnr_width = pipe->config.output_system_in_res.width; - tnr_height = pipe->config.output_system_in_res.height; - } else { - tnr_width = tnr_info.res.width; - tnr_height = tnr_info.res.height; - } - - /* Make tnr reference buffers output block width(in pix) align */ - tnr_info.res.width = CEIL_MUL(tnr_width, - (mycs->video_binary.info->sp.block.block_width * ISP_NWAY)); - tnr_info.padded_width = tnr_info.res.width; - } else { - tnr_height = tnr_info.res.height; - } - /* Make tnr reference buffers output block height align */ - tnr_info.res.height = CEIL_MUL(tnr_height, + tnr_info.res.height = CEIL_MUL(tnr_info.res.height, mycs->video_binary.info->sp.block.output_block_height); } else { tnr_info = mycs->video_binary.internal_frame_info; @@ -5434,12 +5388,6 @@ static bool need_capture_pp( assert(pipe); assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE); - if (IS_ISP2401) { - /* ldc and capture_pp are not supported in the same pipeline */ - if (need_capt_ldc(pipe)) - return false; - } - /* determine whether we need to use the capture_pp binary. * This is needed for: * 1. XNR or @@ -5648,33 +5596,13 @@ static int load_primary_binaries( /* TODO Do we disable ldc for skycam */ need_ldc = need_capt_ldc(pipe); - if (IS_ISP2401 && need_ldc) { - /* ldc and capt_pp are not supported in the same pipeline */ - struct ia_css_binary_descr capt_ldc_descr; - - ia_css_pipe_get_ldc_binarydesc(pipe, - &capt_ldc_descr, &prim_out_info, - &capt_pp_out_info); - - err = ia_css_binary_find(&capt_ldc_descr, - &mycs->capture_ldc_binary); - if (err) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - need_pp = false; - need_ldc = false; - } /* we build up the pipeline starting at the end */ /* Capture post-processing */ if (need_pp) { struct ia_css_binary_descr capture_pp_descr; - if (!IS_ISP2401) - capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info; - else - capt_pp_in_info = &prim_out_info; + capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info; ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr, @@ -7575,7 +7503,6 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) } } -#ifndef ISP2401 if (need_pp && current_stage) { struct ia_css_frame *local_in_frame = NULL; @@ -7595,20 +7522,6 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) } err = add_capture_pp_stage(pipe, me, local_in_frame, need_yuv_pp ? NULL : out_frame, -#else - /* ldc and capture_pp not supported in same pipeline */ - if (need_ldc && current_stage) { - in_frame = current_stage->args.out_frame[0]; - ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); - ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, - out_frames, in_frame, NULL); - err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, - NULL); - } else if (need_pp && current_stage) { - in_frame = current_stage->args.out_frame[0]; - err = add_capture_pp_stage(pipe, me, in_frame, - need_yuv_pp ? NULL : out_frame, -#endif capture_pp_binary, ¤t_stage); if (err) { @@ -7722,7 +7635,7 @@ static int capture_start(struct ia_css_pipe *pipe) IA_CSS_LEAVE_ERR_PRIVATE(err); return err; } -#elif defined(ISP2401) +#else if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) { err = send_mipi_frames(pipe); if (err) { @@ -7730,7 +7643,6 @@ static int capture_start(struct ia_css_pipe *pipe) return err; } } - #endif ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); @@ -8176,9 +8088,7 @@ sh_css_init_host_sp_control_vars(void) unsigned int HIVE_ADDR_host_sp_queues_initialized; unsigned int HIVE_ADDR_sp_sleep_mode; unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb; -#ifndef ISP2401 unsigned int HIVE_ADDR_sp_stop_copy_preview; -#endif unsigned int HIVE_ADDR_host_sp_com; unsigned int o = offsetof(struct host_sp_communication, host2sp_command) / sizeof(int); @@ -8195,9 +8105,7 @@ sh_css_init_host_sp_control_vars(void) fw->info.sp.host_sp_queues_initialized; HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode; HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb; -#ifndef ISP2401 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview; -#endif HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com; sp_dmem_store_uint32(SP0_ID, @@ -8213,11 +8121,9 @@ sh_css_init_host_sp_control_vars(void) sp_dmem_store_uint32(SP0_ID, (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb), (uint32_t)(false)); -#ifndef ISP2401 sp_dmem_store_uint32(SP0_ID, (unsigned int)sp_address_of(sp_stop_copy_preview), my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0)); -#endif store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready); for (i = 0; i < N_CSI_PORTS; i++) { @@ -8937,9 +8843,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, if (num_pipes >= 2) { curr_stream->cont_capt = true; curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder; - - if (!IS_ISP2401) - curr_stream->stop_copy_preview = my_css.stop_copy_preview; + curr_stream->stop_copy_preview = my_css.stop_copy_preview; } /* Create copy pipe here, since it may not be exposed to the driver */ @@ -8997,16 +8901,15 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, /* set current stream */ curr_pipe->stream = curr_stream; - if (!IS_ISP2401) { - /* take over effective info */ + /* take over effective info */ + + effective_res = curr_pipe->config.input_effective_res; + err = ia_css_util_check_res( + effective_res.width, + effective_res.height); + if (err) + goto ERR; - effective_res = curr_pipe->config.input_effective_res; - err = ia_css_util_check_res( - effective_res.width, - effective_res.height); - if (err) - goto ERR; - } /* sensor binning per pipe */ if (sensor_binning_changed) sh_css_pipe_free_shading_table(curr_pipe); @@ -9031,9 +8934,6 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, goto ERR; } - if (IS_ISP2401) - pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res; - if (!spcopyonly) { if (!IS_ISP2401) err = sh_css_pipe_get_shading_info(curr_pipe, @@ -9133,8 +9033,6 @@ ia_css_stream_destroy(struct ia_css_stream *stream) if ((stream->last_pipe) && ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) { #if defined(ISP2401) - bool free_mpi; - for (i = 0; i < stream->num_pipes; i++) { struct ia_css_pipe *entry = stream->pipes[i]; unsigned int sp_thread_id; @@ -9158,13 +9056,7 @@ ia_css_stream_destroy(struct ia_css_stream *stream) } } } - free_mpi = stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; - if (IS_ISP2401) { - free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_TPG; - free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_PRBS; - } - - if (free_mpi) { + if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { for (i = 0; i < stream->num_pipes; i++) { struct ia_css_pipe *entry = stream->pipes[i]; /* @@ -9699,14 +9591,10 @@ ia_css_stop_sp(void) } /* For now, stop whole SP */ - if (!IS_ISP2401) { - sh_css_write_host2sp_command(host2sp_cmd_terminate); - } else { - if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) { - IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); - ia_css_debug_dump_sp_sw_debug_info(); - ia_css_debug_dump_debug_info(NULL); - } + if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) { + IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); + ia_css_debug_dump_sp_sw_debug_info(); + ia_css_debug_dump_debug_info(NULL); } sh_css_sp_set_sp_running(false); From 5b49e068beada2b5d9707acb2307f62fc5d7b197 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Nov 2021 11:16:54 +0000 Subject: [PATCH 135/397] media: atomisp: get rid of #ifdef ISP_VEC_NELEMS This is defined as 64 for the devices/firmware that were chosen. So, evaluate the macros accordingly. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/isp/modes/interface/isp_const.h | 10 ---------- drivers/staging/media/atomisp/pci/sh_css_defs.h | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/isp/modes/interface/isp_const.h b/drivers/staging/media/atomisp/pci/isp/modes/interface/isp_const.h index 11e439d838ae..e5c595e5020b 100644 --- a/drivers/staging/media/atomisp/pci/isp/modes/interface/isp_const.h +++ b/drivers/staging/media/atomisp/pci/isp/modes/interface/isp_const.h @@ -36,17 +36,7 @@ more details. #define BITS8_ELEMENTS_PER_XMEM_ADDR CEIL_DIV(XMEM_WIDTH_BITS, 8) #define BITS16_ELEMENTS_PER_XMEM_ADDR CEIL_DIV(XMEM_WIDTH_BITS, 16) -#if ISP_VEC_NELEMS == 64 #define ISP_NWAY_LOG2 6 -#elif ISP_VEC_NELEMS == 32 -#define ISP_NWAY_LOG2 5 -#elif ISP_VEC_NELEMS == 16 -#define ISP_NWAY_LOG2 4 -#elif ISP_VEC_NELEMS == 8 -#define ISP_NWAY_LOG2 3 -#else -#error "isp_const.h ISP_VEC_NELEMS must be one of {8, 16, 32, 64}" -#endif /* ***************************** * ISP input/output buffer sizes diff --git a/drivers/staging/media/atomisp/pci/sh_css_defs.h b/drivers/staging/media/atomisp/pci/sh_css_defs.h index 30a84a587b2a..239230ae4b4b 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_defs.h +++ b/drivers/staging/media/atomisp/pci/sh_css_defs.h @@ -117,13 +117,8 @@ RGB[0,8191],coef[-8192,8191] -> RGB[0,8191] #define SH_CSS_NUM_INPUT_BUF_LINES 4 /* Left cropping only applicable for sufficiently large nway */ -#if ISP_VEC_NELEMS == 16 -#define SH_CSS_MAX_LEFT_CROPPING 0 -#define SH_CSS_MAX_TOP_CROPPING 0 -#else #define SH_CSS_MAX_LEFT_CROPPING 12 #define SH_CSS_MAX_TOP_CROPPING 12 -#endif #define SH_CSS_SP_MAX_WIDTH 1280 @@ -137,13 +132,8 @@ RGB[0,8191],coef[-8192,8191] -> RGB[0,8191] #define SH_CSS_MIN_DVS_ENVELOPE 12U /* The FPGA system (vec_nelems == 16) only supports upto 5MP */ -#if ISP_VEC_NELEMS == 16 -#define SH_CSS_MAX_SENSOR_WIDTH 2560 -#define SH_CSS_MAX_SENSOR_HEIGHT 1920 -#else #define SH_CSS_MAX_SENSOR_WIDTH 4608 #define SH_CSS_MAX_SENSOR_HEIGHT 3450 -#endif /* Limited to reduce vmem pressure */ #if ISP_VMEM_DEPTH >= 3072 From da8fdf490b954f04af6c254f51c29e4e305fc1b9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Nov 2021 13:29:44 +0000 Subject: [PATCH 136/397] media: atomisp: drop empty files There's nothing inside such files. Just drop them. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/Makefile | 4 ---- .../staging/media/atomisp/pci/sh_css_metadata.c | 17 ----------------- .../staging/media/atomisp/pci/sh_css_morph.c | 17 ----------------- .../staging/media/atomisp/pci/sh_css_shading.c | 17 ----------------- .../staging/media/atomisp/pci/sh_css_stream.c | 17 ----------------- 5 files changed, 72 deletions(-) delete mode 100644 drivers/staging/media/atomisp/pci/sh_css_metadata.c delete mode 100644 drivers/staging/media/atomisp/pci/sh_css_morph.c delete mode 100644 drivers/staging/media/atomisp/pci/sh_css_shading.c delete mode 100644 drivers/staging/media/atomisp/pci/sh_css_stream.c diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile index a7ad8cfab602..2485d7b3fee2 100644 --- a/drivers/staging/media/atomisp/Makefile +++ b/drivers/staging/media/atomisp/Makefile @@ -27,20 +27,16 @@ atomisp-objs += \ pci/sh_css_firmware.o \ pci/sh_css_host_data.o \ pci/sh_css_hrt.o \ - pci/sh_css_metadata.o \ pci/sh_css_metrics.o \ pci/sh_css_mipi.o \ pci/sh_css_mmu.o \ - pci/sh_css_morph.o \ pci/sh_css.o \ pci/sh_css_param_dvs.o \ pci/sh_css_param_shading.o \ pci/sh_css_params.o \ pci/sh_css_properties.o \ - pci/sh_css_shading.o \ pci/sh_css_sp.o \ pci/sh_css_stream_format.o \ - pci/sh_css_stream.o \ pci/sh_css_version.o \ pci/base/circbuf/src/circbuf.o \ pci/base/refcount/src/refcount.o \ diff --git a/drivers/staging/media/atomisp/pci/sh_css_metadata.c b/drivers/staging/media/atomisp/pci/sh_css_metadata.c deleted file mode 100644 index 04a4b7da85e2..000000000000 --- a/drivers/staging/media/atomisp/pci/sh_css_metadata.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* This file will contain the code to implement the functions declared in ia_css_metadata.h - and associated helper functions */ diff --git a/drivers/staging/media/atomisp/pci/sh_css_morph.c b/drivers/staging/media/atomisp/pci/sh_css_morph.c deleted file mode 100644 index edd1da941ccb..000000000000 --- a/drivers/staging/media/atomisp/pci/sh_css_morph.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* This file will contain the code to implement the functions declared in ia_css_morph.h - and associated helper functions */ diff --git a/drivers/staging/media/atomisp/pci/sh_css_shading.c b/drivers/staging/media/atomisp/pci/sh_css_shading.c deleted file mode 100644 index 462caf9cb571..000000000000 --- a/drivers/staging/media/atomisp/pci/sh_css_shading.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* This file will contain the code to implement the functions declared in ia_css_shading.h - and associated helper functions */ diff --git a/drivers/staging/media/atomisp/pci/sh_css_stream.c b/drivers/staging/media/atomisp/pci/sh_css_stream.c deleted file mode 100644 index a768ce90f51c..000000000000 --- a/drivers/staging/media/atomisp/pci/sh_css_stream.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* This file will contain the code to implement the functions declared in ia_css_stream.h - and associated helper functions */ From 839467839ca0a664da0d1e16d402b61c7cea1bbc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Nov 2021 12:39:37 +0000 Subject: [PATCH 137/397] media: atomisp: simplify sh_css_defs.h There are several unused macros. Simplify the logic there, making it closer to the Intel Aero driver and the corresponding firmware, as this is what we have widely available for this device. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 28 +++-------- .../staging/media/atomisp/pci/ia_css_pipe.h | 4 +- .../isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c | 6 +-- .../kernels/tnr/tnr_1.0/ia_css_tnr_param.h | 4 +- .../pci/isp/modes/interface/isp_const.h | 4 +- .../atomisp/pci/runtime/binary/src/binary.c | 8 ++-- .../pci/runtime/debug/src/ia_css_debug.c | 2 +- drivers/staging/media/atomisp/pci/sh_css.c | 10 ++-- .../staging/media/atomisp/pci/sh_css_defs.h | 48 ++++--------------- .../media/atomisp/pci/sh_css_internal.h | 2 +- 10 files changed, 36 insertions(+), 80 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 4783590969b6..7181b901cde4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3617,18 +3617,10 @@ int atomisp_cp_lsc_table(struct atomisp_sub_device *asd, } /* Shading table size per color */ - if (!IS_ISP2401) { - if (st->width > ISP2400_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || - st->height > ISP2400_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) { - dev_err(asd->isp->dev, "shading table w/h validate failed!"); - return -EINVAL; - } - } else { - if (st->width > ISP2401_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || - st->height > ISP2401_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) { - dev_err(asd->isp->dev, "shading table w/h validate failed!"); - return -EINVAL; - } + if (st->width > SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || + st->height > SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) { + dev_err(asd->isp->dev, "shading table w/h validate failed!"); + return -EINVAL; } shading_table = atomisp_css_shading_table_alloc(st->width, st->height); @@ -6181,15 +6173,9 @@ int atomisp_set_shading_table(struct atomisp_sub_device *asd, } /* Shading table size per color */ - if (!IS_ISP2401) { - if (user_shading_table->width > ISP2400_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || - user_shading_table->height > ISP2400_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) - return -EINVAL; - } else { - if (user_shading_table->width > ISP2401_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || - user_shading_table->height > ISP2401_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) - return -EINVAL; - } + if (user_shading_table->width > SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || + user_shading_table->height > SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) + return -EINVAL; shading_table = atomisp_css_shading_table_alloc( user_shading_table->width, user_shading_table->height); diff --git a/drivers/staging/media/atomisp/pci/ia_css_pipe.h b/drivers/staging/media/atomisp/pci/ia_css_pipe.h index bb0abf9bffb1..fb58535bff40 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_pipe.h +++ b/drivers/staging/media/atomisp/pci/ia_css_pipe.h @@ -33,7 +33,7 @@ struct ia_css_preview_settings { /* 2401 only for these two - do we in fact use them for anything real */ struct ia_css_frame *delay_frames[MAX_NUM_VIDEO_DELAY_FRAMES]; - struct ia_css_frame *tnr_frames[NUM_TNR_FRAMES]; + struct ia_css_frame *tnr_frames[NUM_VIDEO_TNR_FRAMES]; struct ia_css_pipe *copy_pipe; struct ia_css_pipe *capture_pipe; @@ -81,7 +81,7 @@ struct ia_css_video_settings { struct ia_css_binary vf_pp_binary; struct ia_css_binary *yuv_scaler_binary; struct ia_css_frame *delay_frames[MAX_NUM_VIDEO_DELAY_FRAMES]; - struct ia_css_frame *tnr_frames[NUM_TNR_FRAMES]; + struct ia_css_frame *tnr_frames[NUM_VIDEO_TNR_FRAMES]; struct ia_css_frame *vf_pp_in_frame; struct ia_css_pipe *copy_pipe; struct ia_css_pipe *capture_pipe; diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c index 7177cf292fb0..53050c0c49fc 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c @@ -84,7 +84,7 @@ int ia_css_tnr_config(struct sh_css_isp_tnr_isp_config *to, return ret; to->width_a_over_b = elems_a / to->port_b.elems; to->frame_height = from->tnr_frames[0]->info.res.height; - for (i = 0; i < NUM_TNR_FRAMES; i++) { + for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) { to->tnr_frame_addr[i] = from->tnr_frames[i]->data + from->tnr_frames[i]->planes.yuyv.offset; } @@ -102,7 +102,7 @@ int ia_css_tnr_configure(const struct ia_css_binary *binary, struct ia_css_tnr_configuration config; unsigned int i; - for (i = 0; i < NUM_TNR_FRAMES; i++) + for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) config.tnr_frames[i] = frames[i]; return ia_css_configure_tnr(binary, &config); @@ -115,7 +115,7 @@ ia_css_init_tnr_state( { (void)size; - assert(NUM_TNR_FRAMES >= 2); + assert(NUM_VIDEO_TNR_FRAMES >= 2); assert(sizeof(*state) == size); state->tnr_in_buf_idx = 0; state->tnr_out_buf_idx = 1; diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr_param.h b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr_param.h index 60a2542cf685..551dd5cfa9f1 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr_param.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr_param.h @@ -28,14 +28,14 @@ struct sh_css_isp_tnr_params { }; struct ia_css_tnr_configuration { - const struct ia_css_frame *tnr_frames[NUM_TNR_FRAMES]; + const struct ia_css_frame *tnr_frames[NUM_VIDEO_TNR_FRAMES]; }; struct sh_css_isp_tnr_isp_config { u32 width_a_over_b; u32 frame_height; struct dma_port_config port_b; - ia_css_ptr tnr_frame_addr[NUM_TNR_FRAMES]; + ia_css_ptr tnr_frame_addr[NUM_VIDEO_TNR_FRAMES]; }; #endif /* __IA_CSS_TNR_PARAM_H */ diff --git a/drivers/staging/media/atomisp/pci/isp/modes/interface/isp_const.h b/drivers/staging/media/atomisp/pci/isp/modes/interface/isp_const.h index e5c595e5020b..bfe4f5976771 100644 --- a/drivers/staging/media/atomisp/pci/isp/modes/interface/isp_const.h +++ b/drivers/staging/media/atomisp/pci/isp/modes/interface/isp_const.h @@ -154,9 +154,9 @@ more details. /* [isp vmem] table size[vectors] per line per color (GR,R,B,GB), multiples of NWAY */ #define ISP2400_SCTBL_VECTORS_PER_LINE_PER_COLOR \ - CEIL_DIV(ISP2400_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR, ISP_VEC_NELEMS) + CEIL_DIV(SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR, ISP_VEC_NELEMS) #define ISP2401_SCTBL_VECTORS_PER_LINE_PER_COLOR \ - CEIL_DIV(ISP2401_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR, ISP_VEC_NELEMS) + CEIL_DIV(SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR, ISP_VEC_NELEMS) /* [isp vmem] table size[vectors] per line for 4colors (GR,R,B,GB), multiples of NWAY */ #define SCTBL_VECTORS_PER_LINE \ diff --git a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c index 8c0e02e4e1af..851e1d34a521 100644 --- a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c +++ b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c @@ -1336,12 +1336,12 @@ ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo, if (info->enable.sc) { if (!IS_ISP2401) { - binary->sctbl_width_per_color = _ISP2400_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci); - binary->sctbl_aligned_width_per_color = ISP2400_SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR; - binary->sctbl_height = _ISP2400_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci); + binary->sctbl_width_per_color = _ISP_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci); + binary->sctbl_aligned_width_per_color = SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR; + binary->sctbl_height = _ISP_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci); } else { binary->sctbl_width_per_color = _ISP2401_SCTBL_WIDTH_PER_COLOR(isp_internal_width, s3a_log_deci); - binary->sctbl_aligned_width_per_color = ISP2401_SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR; + binary->sctbl_aligned_width_per_color = SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR; binary->sctbl_height = _ISP2401_SCTBL_HEIGHT(isp_internal_height, s3a_log_deci); binary->sctbl_legacy_width_per_color = _ISP_SCTBL_LEGACY_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci); binary->sctbl_legacy_height = _ISP_SCTBL_LEGACY_HEIGHT(sc_3a_dis_height, s3a_log_deci); diff --git a/drivers/staging/media/atomisp/pci/runtime/debug/src/ia_css_debug.c b/drivers/staging/media/atomisp/pci/runtime/debug/src/ia_css_debug.c index 05ce0f73f5ae..f46238725eea 100644 --- a/drivers/staging/media/atomisp/pci/runtime/debug/src/ia_css_debug.c +++ b/drivers/staging/media/atomisp/pci/runtime/debug/src/ia_css_debug.c @@ -2821,7 +2821,7 @@ ia_css_debug_pipe_graph_dump_stage( "in", true); } - for (i = 0; i < NUM_TNR_FRAMES; i++) { + for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) { if (stage->args.tnr_frames[i]) { ia_css_debug_pipe_graph_dump_frame( stage->args.tnr_frames[i], id, diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index e5e22f966286..acaa4c8b1884 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -1261,7 +1261,7 @@ void sh_css_binary_args_reset(struct sh_css_binary_args *args) { unsigned int i; - for (i = 0; i < NUM_TNR_FRAMES; i++) + for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) args->tnr_frames[i] = NULL; for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++) args->delay_frames[i] = NULL; @@ -2228,10 +2228,10 @@ ia_css_pipe_destroy(struct ia_css_pipe *pipe) } } #ifndef ISP2401 - ia_css_frame_free_multiple(NUM_TNR_FRAMES, + ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames); #else - ia_css_frame_free_multiple(NUM_TNR_FRAMES, + ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames); #endif ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, @@ -3424,7 +3424,7 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe) if (video_stage) { int frm; - for (frm = 0; frm < NUM_TNR_FRAMES; frm++) { + for (frm = 0; frm < NUM_VIDEO_TNR_FRAMES; frm++) { video_stage->args.tnr_frames[frm] = pipe->pipe_settings.video.tnr_frames[frm]; } @@ -5163,7 +5163,7 @@ static int load_video_binaries(struct ia_css_pipe *pipe) tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE; tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH; - for (i = 0; i < NUM_TNR_FRAMES; i++) { + for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) { if (mycs->tnr_frames[i]) { ia_css_frame_free(mycs->tnr_frames[i]); mycs->tnr_frames[i] = NULL; diff --git a/drivers/staging/media/atomisp/pci/sh_css_defs.h b/drivers/staging/media/atomisp/pci/sh_css_defs.h index 239230ae4b4b..7eb10b226f0a 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_defs.h +++ b/drivers/staging/media/atomisp/pci/sh_css_defs.h @@ -168,50 +168,20 @@ RGB[0,8191],coef[-8192,8191] -> RGB[0,8191] #define SH_CSS_MORPH_TABLE_ELEMS_PER_DDR_WORD \ (HIVE_ISP_DDR_WORD_BYTES / SH_CSS_MORPH_TABLE_ELEM_BYTES) -#define ISP2400_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR (SH_CSS_MAX_BQ_GRID_WIDTH + 1) -#define ISP2400_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR (SH_CSS_MAX_BQ_GRID_HEIGHT + 1) +#define SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR (SH_CSS_MAX_BQ_GRID_WIDTH + 1) +#define SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR (SH_CSS_MAX_BQ_GRID_HEIGHT + 1) -#define ISP2400_SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR \ - CEIL_MUL(ISP2400_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR, ISP_VEC_NELEMS) - -/* TODO: I will move macros of "*_SCTBL_*" to SC kernel. - "+ 2" should be "+ SH_CSS_SCTBL_CENTERING_MARGIN + SH_CSS_SCTBL_LAST_GRID_COUNT". (michie, Sep/23/2014) */ -#define ISP2401_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR (SH_CSS_MAX_BQ_GRID_WIDTH + 2) -#define ISP2401_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR (SH_CSS_MAX_BQ_GRID_HEIGHT + 2) - -#define ISP2401_SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR \ - CEIL_MUL(ISP2400_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR, ISP_VEC_NELEMS) +#define SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR \ + CEIL_MUL(SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR, ISP_VEC_NELEMS) /* Each line of this table is aligned to the maximum line width. */ #define SH_CSS_MAX_S3ATBL_WIDTH SH_CSS_MAX_BQ_GRID_WIDTH /* Video mode specific DVS define */ /* The video binary supports a delay of 1 or 2 frames */ -#define VIDEO_FRAME_DELAY 2 +#define MAX_DVS_FRAME_DELAY 2 /* +1 because DVS reads the previous and writes the current frame concurrently */ -#define MAX_NUM_VIDEO_DELAY_FRAMES (VIDEO_FRAME_DELAY + 1) - -/* Preview mode specific DVS define. */ -/* In preview we only need GDC functionality (and not the DVS functionality) */ -/* The minimum number of DVS frames you need is 2, one were GDC reads from and another where GDC writes into */ -#define NUM_PREVIEW_DVS_FRAMES (2) - -/* TNR is no longer exclusive to video, SkyCam preview has TNR too (same kernel as video). - * All uses the generic define NUM_TNR_FRAMES. The define NUM_VIDEO_TNR_FRAMES has been deprecated. - * - * Notes - * 1) The value depends on the used TNR kernel and is not something that depends on the mode - * and it is not something you just could choice. - * 2) For the luma only pipeline a version that supports two different sets of TNR reference frames - * is being used. - *. - */ -#define NUM_VALID_TNR_REF_FRAMES (1) /* At least one valid TNR reference frame is required */ -#define NUM_TNR_FRAMES_PER_REF_BUF_SET (2) -/* In luma-only mode alternate illuminated frames are supported, that requires two double buffers */ -#define NUM_TNR_REF_BUF_SETS (1) - -#define NUM_TNR_FRAMES (NUM_TNR_FRAMES_PER_REF_BUF_SET * NUM_TNR_REF_BUF_SETS) +#define MAX_NUM_VIDEO_DELAY_FRAMES (MAX_DVS_FRAME_DELAY + 1) #define NUM_VIDEO_TNR_FRAMES 2 @@ -240,11 +210,11 @@ RGB[0,8191],coef[-8192,8191] -> RGB[0,8191] CEIL_MUL(_ISP_MORPH_TABLE_WIDTH(width), \ SH_CSS_MORPH_TABLE_ELEMS_PER_DDR_WORD) -#define _ISP2400_SCTBL_WIDTH_PER_COLOR(input_width, deci_factor_log2) \ +#define _ISP_SCTBL_WIDTH_PER_COLOR(input_width, deci_factor_log2) \ (ISP_BQ_GRID_WIDTH(input_width, deci_factor_log2) + 1) -#define _ISP2400_SCTBL_HEIGHT(input_height, deci_factor_log2) \ +#define _ISP_SCTBL_HEIGHT(input_height, deci_factor_log2) \ (ISP_BQ_GRID_HEIGHT(input_height, deci_factor_log2) + 1) -#define _ISP2400_SCTBL_ALIGNED_WIDTH_PER_COLOR(input_width, deci_factor_log2) \ +#define _ISP_SCTBL_ALIGNED_WIDTH_PER_COLOR(input_width, deci_factor_log2) \ CEIL_MUL(_ISP_SCTBL_WIDTH_PER_COLOR(input_width, deci_factor_log2), \ ISP_VEC_NELEMS) diff --git a/drivers/staging/media/atomisp/pci/sh_css_internal.h b/drivers/staging/media/atomisp/pci/sh_css_internal.h index 735540eceb37..435b3cedd1c3 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_internal.h +++ b/drivers/staging/media/atomisp/pci/sh_css_internal.h @@ -270,7 +270,7 @@ struct sh_css_binary_args { struct ia_css_frame *in_frame; /* input frame */ const struct ia_css_frame *delay_frames[MAX_NUM_VIDEO_DELAY_FRAMES]; /* reference input frame */ - const struct ia_css_frame *tnr_frames[NUM_TNR_FRAMES]; /* tnr frames */ + const struct ia_css_frame *tnr_frames[NUM_VIDEO_TNR_FRAMES]; /* tnr frames */ struct ia_css_frame *out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; /* output frame */ struct ia_css_frame *out_vf_frame; /* viewfinder output frame */ From ef3f3627ff1b2cdb0960a95b8a93299cd36fd86c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Nov 2021 13:31:59 +0000 Subject: [PATCH 138/397] media: atomisp: sh_css_metrics: drop some unused code There are two #ifdefs there which aren't defined anywhere. So, just drop the dead code. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/sh_css_metrics.c | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_metrics.c b/drivers/staging/media/atomisp/pci/sh_css_metrics.c index 9744bbebe1bc..8ded6cdd1575 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_metrics.c +++ b/drivers/staging/media/atomisp/pci/sh_css_metrics.c @@ -123,40 +123,15 @@ sh_css_metrics_sample_pcs(void) unsigned int pc; unsigned int msink; -#if SUSPEND - unsigned int sc = 0; - unsigned int stopped_sc = 0; - unsigned int resume_sc = 0; -#endif -#if MULTIPLE_PCS - int i; - unsigned int pc_tab[NOF_PCS]; - - for (i = 0; i < NOF_PCS; i++) - pc_tab[i] = 0; -#endif if (!pc_histogram_enabled) return; if (isp_histogram) { -#if SUSPEND - /* STOP the ISP */ - isp_ctrl_store(ISP0_ID, ISP_SC_REG, STOP_MASK); -#endif msink = isp_ctrl_load(ISP0_ID, ISP_CTRL_SINK_REG); -#if MULTIPLE_PCS - for (i = 0; i < NOF_PCS; i++) - pc_tab[i] = isp_ctrl_load(ISP0_ID, ISP_PC_REG); -#else pc = isp_ctrl_load(ISP0_ID, ISP_PC_REG); -#endif -#if SUSPEND - /* RESUME the ISP */ - isp_ctrl_store(ISP0_ID, ISP_SC_REG, RESUME_MASK); -#endif isp_histogram->msink[pc] &= msink; stall = (msink != 0x7FF); From b541d4c9923154be7ae0518d01ce994acbef3f9b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Nov 2021 14:45:55 +0000 Subject: [PATCH 139/397] media: atomisp: sh_css_mipi: cleanup the code With the ISP2401 firmware we're using, the code differences are not that much from ISP2400. Cleanup the code in order to make it closer to Intel Aero driver. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/sh_css_mipi.c | 159 +++++------------- .../staging/media/atomisp/pci/sh_css_mipi.h | 15 -- 2 files changed, 38 insertions(+), 136 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index cfaa4719177c..0acf75497ae7 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -33,47 +33,6 @@ static u32 ref_count_mipi_allocation[N_CSI_PORTS]; /* Initialized in mipi_init */ -/* - * Check if a source port or TPG/PRBS ID is valid - */ -static bool ia_css_mipi_is_source_port_valid(struct ia_css_pipe *pipe, - unsigned int *pport) -{ - bool ret = true; - unsigned int port = 0; - unsigned int max_ports = 0; - - switch (pipe->stream->config.mode) { - case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: - port = (unsigned int)pipe->stream->config.source.port.port; - max_ports = N_CSI_PORTS; - break; - case IA_CSS_INPUT_MODE_TPG: - port = (unsigned int)pipe->stream->config.source.tpg.id; - max_ports = N_CSS_TPG_IDS; - break; - case IA_CSS_INPUT_MODE_PRBS: - port = (unsigned int)pipe->stream->config.source.prbs.id; - max_ports = N_CSS_PRBS_IDS; - break; - default: - assert(false); - ret = false; - break; - } - - if (ret) { - assert(port < max_ports); - - if (port >= max_ports) - ret = false; - } - - *pport = port; - - return ret; -} - /* Assumptions: * - A line is multiple of 4 bytes = 1 word. * - Each frame has SOF and EOF (each 1 word). @@ -227,6 +186,10 @@ ia_css_mipi_frame_calculate_size(const unsigned int width, return err; } +/* + * Check if a source port or TPG/PRBS ID is valid + */ + #if !defined(ISP2401) int ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port, @@ -272,16 +235,20 @@ bool mipi_is_free(void) return true; } -int -calculate_mipi_buff_size( - struct ia_css_stream_config *stream_cfg, - unsigned int *size_mem_words) +#if defined(ISP2401) +/* + * @brief Calculate the required MIPI buffer sizes. + * Based on the stream configuration, calculate the + * required MIPI buffer sizes (in DDR words). + * + * @param[in] stream_cfg Point to the target stream configuration + * @param[out] size_mem_words MIPI buffer size in DDR words. + * + * @return + */ +static int calculate_mipi_buff_size(struct ia_css_stream_config *stream_cfg, + unsigned int *size_mem_words) { -#if !defined(ISP2401) - int err = -EINVAL; - (void)stream_cfg; - (void)size_mem_words; -#else unsigned int width; unsigned int height; enum atomisp_input_format format; @@ -373,26 +340,9 @@ calculate_mipi_buff_size( *size_mem_words = mem_words_per_buff; IA_CSS_LEAVE_ERR(err); -#endif return err; } - -static bool buffers_needed(struct ia_css_pipe *pipe) -{ - if (!IS_ISP2401) { - if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) - return true; - else - return false; - } - - if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR || - pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG || - pipe->stream->config.mode == IA_CSS_INPUT_MODE_PRBS) - return true; - - return false; -} +#endif int allocate_mipi_frames(struct ia_css_pipe *pipe, @@ -422,45 +372,25 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, } #endif - - if (!buffers_needed(pipe)) { + if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: no buffers needed for pipe mode.\n", pipe); return 0; /* AM TODO: Check */ } - if (!IS_ISP2401) { - port = (unsigned int)pipe->stream->config.source.port.port; - } else { - /* Returns true if port is valid. So, invert it */ - err = !ia_css_mipi_is_source_port_valid(pipe, &port); - } - - assert(port < N_CSI_PORTS); - - if ((!IS_ISP2401 && port >= N_CSI_PORTS) || - (IS_ISP2401 && err)) { + port = (unsigned int)pipe->stream->config.source.port.port; + if (port >= N_CSI_PORTS) { IA_CSS_ERROR("allocate_mipi_frames(%p) exit: port is not correct (port=%d).", pipe, port); return -EINVAL; } #ifdef ISP2401 - err = calculate_mipi_buff_size( - &pipe->stream->config, - &my_css.mipi_frame_size[port]); -#endif - -#if !defined(ISP2401) - if (ref_count_mipi_allocation[port] != 0) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n", - pipe, port); - return 0; - } -#else - /* 2401 system allows multiple streams to use same physical port. This is not + err = calculate_mipi_buff_size(&pipe->stream->config, + &my_css.mipi_frame_size[port]); + /* + * 2401 system allows multiple streams to use same physical port. This is not * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution. * TODO AM: Once that is changed (removed) this code should be removed as well. * In that case only 2400 related code should remain. @@ -472,6 +402,13 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, pipe, port); return 0; } +#else + if (ref_count_mipi_allocation[port] != 0) { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n", + pipe, port); + return 0; + } #endif ref_count_mipi_allocation[port]++; @@ -552,23 +489,15 @@ free_mipi_frames(struct ia_css_pipe *pipe) return -EINVAL; } - if (!buffers_needed(pipe)) { + if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { IA_CSS_ERROR("free_mipi_frames(%p) exit: wrong mode.", pipe); return err; } - if (!IS_ISP2401) { - port = (unsigned int)pipe->stream->config.source.port.port; - } else { - /* Returns true if port is valid. So, invert it */ - err = !ia_css_mipi_is_source_port_valid(pipe, &port); - } + port = (unsigned int)pipe->stream->config.source.port.port; - assert(port < N_CSI_PORTS); - - if ((!IS_ISP2401 && port >= N_CSI_PORTS) || - (IS_ISP2401 && err)) { + if (port >= N_CSI_PORTS) { IA_CSS_ERROR("free_mipi_frames(%p, %d) exit: pipe port is not correct.", pipe, port); return err; @@ -647,11 +576,7 @@ send_mipi_frames(struct ia_css_pipe *pipe) { int err = -EINVAL; unsigned int i; -#ifndef ISP2401 unsigned int port; -#else - unsigned int port = 0; -#endif IA_CSS_ENTER_PRIVATE("pipe=%p", pipe); @@ -664,23 +589,15 @@ send_mipi_frames(struct ia_css_pipe *pipe) /* multi stream video needs mipi buffers */ /* nothing to be done in other cases. */ - if (!buffers_needed(pipe)) { + if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { IA_CSS_LOG("nothing to be done for this mode"); return 0; /* TODO: AM: maybe this should be returning an error. */ } - if (!IS_ISP2401) { - port = (unsigned int)pipe->stream->config.source.port.port; - } else { - /* Returns true if port is valid. So, invert it */ - err = !ia_css_mipi_is_source_port_valid(pipe, &port); - } + port = (unsigned int)pipe->stream->config.source.port.port; - assert(port < N_CSI_PORTS); - - if ((!IS_ISP2401 && port >= N_CSI_PORTS) || - (IS_ISP2401 && err)) { + if (port >= N_CSI_PORTS) { IA_CSS_ERROR("send_mipi_frames(%p) exit: invalid port specified (port=%d).", pipe, port); return err; diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.h b/drivers/staging/media/atomisp/pci/sh_css_mipi.h index dffec2205620..e6c86d0ac483 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.h +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.h @@ -34,19 +34,4 @@ free_mipi_frames(struct ia_css_pipe *pipe); int send_mipi_frames(struct ia_css_pipe *pipe); -/** - * @brief Calculate the required MIPI buffer sizes. - * Based on the stream configuration, calculate the - * required MIPI buffer sizes (in DDR words). - * - * @param[in] stream_cfg Point to the target stream configuration - * @param[out] size_mem_words MIPI buffer size in DDR words. - * - * @return - */ -int -calculate_mipi_buff_size( - struct ia_css_stream_config *stream_cfg, - unsigned int *size_mem_words); - #endif /* __SH_CSS_MIPI_H */ From 037de9f2b2c1a1c250f166134b9aec47c1298f83 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 06:40:52 +0000 Subject: [PATCH 140/397] media: atomisp: sh_css_params: remove tests for ISP2401 Those tests are related to the input system, which is the same for the chosen firmware, so both ISP2400 and ISP2401 will be identical with that regards. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/sh_css_params.c | 117 ++---------------- 1 file changed, 8 insertions(+), 109 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c index 448b07162382..68d8f54473ea 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/sh_css_params.c @@ -104,15 +104,10 @@ (sizeof(char) * (binary)->in_frame_info.res.height * \ (binary)->in_frame_info.padded_width) -#define ISP2400_SCTBL_BYTES(binary) \ +#define SCTBL_BYTES(binary) \ (sizeof(unsigned short) * (binary)->sctbl_height * \ (binary)->sctbl_aligned_width_per_color * IA_CSS_SC_NUM_COLORS) -#define ISP2401_SCTBL_BYTES(binary) \ - (sizeof(unsigned short) * max((binary)->sctbl_height, (binary)->sctbl_legacy_height) * \ - /* height should be the larger height between new api and legacy api */ \ - (binary)->sctbl_aligned_width_per_color * IA_CSS_SC_NUM_COLORS) - #define MORPH_PLANE_BYTES(binary) \ (SH_CSS_MORPH_TABLE_ELEM_BYTES * (binary)->morph_tbl_aligned_width * \ (binary)->morph_tbl_height) @@ -1611,18 +1606,6 @@ ia_css_set_param_exceptions(const struct ia_css_pipe *pipe, params->dp_config.r = params->wb_config.r; params->dp_config.b = params->wb_config.b; params->dp_config.gb = params->wb_config.gb; - - if (IS_ISP2401) { - assert(pipe); - assert(pipe->mode < IA_CSS_PIPE_ID_NUM); - - if (pipe->mode < IA_CSS_PIPE_ID_NUM) { - params->pipe_dp_config[pipe->mode].gr = params->wb_config.gr; - params->pipe_dp_config[pipe->mode].r = params->wb_config.r; - params->pipe_dp_config[pipe->mode].b = params->wb_config.b; - params->pipe_dp_config[pipe->mode].gb = params->wb_config.gb; - } - } } /* ISP2401 */ @@ -2072,16 +2055,6 @@ sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe, params->output_frame = config->output_frame; params->isp_parameters_id = config->isp_config_id; - /* Currently we do not offer CSS interface to set different - * configurations for DPC, i.e. depending on DPC being enabled - * before (NORM+OBC) or after. The folllowing code to set the - * DPC configuration should be updated when this interface is made - * available */ - if (IS_ISP2401) { - sh_css_set_dp_config(pipe, params, config->dp_config); - ia_css_set_param_exceptions(pipe, params); - } - if (0 == sh_css_select_dp_10bpp_config(pipe, &is_dp_10bpp)) { /* return an error when both DPC and BDS is enabled by the @@ -2096,8 +2069,7 @@ sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe, goto exit; } - if (!IS_ISP2401) - ia_css_set_param_exceptions(pipe, params); + ia_css_set_param_exceptions(pipe, params); exit: IA_CSS_LEAVE_ERR_PRIVATE(err); @@ -2514,29 +2486,7 @@ sh_css_init_isp_params_from_global(struct ia_css_stream *stream, ia_css_set_ob_config(params, &default_ob_config); ia_css_set_dp_config(params, &default_dp_config); - if (!IS_ISP2401) { - ia_css_set_param_exceptions(pipe_in, params); - } else { - for (i = 0; i < stream->num_pipes; i++) { - if (sh_css_select_dp_10bpp_config(stream->pipes[i], - &is_dp_10bpp) == 0) { - /* set the return value as false if both DPC and - * BDS is enabled by the user. But we do not return - * the value immediately to enable internal firmware - * feature testing. */ - if (is_dp_10bpp) { - sh_css_set_dp_config(stream->pipes[i], params, &default_dp_10bpp_config); - } else { - sh_css_set_dp_config(stream->pipes[i], params, &default_dp_config); - } - } else { - retval = false; - goto exit; - } - - ia_css_set_param_exceptions(stream->pipes[i], params); - } - } + ia_css_set_param_exceptions(pipe_in, params); ia_css_set_de_config(params, &default_de_config); ia_css_set_gc_config(params, &default_gc_config); @@ -2641,20 +2591,9 @@ sh_css_init_isp_params_from_global(struct ia_css_stream *stream, retval = false; goto exit; } - if (IS_ISP2401) { - if (stream->pipes[i]->mode < IA_CSS_PIPE_ID_NUM) { - sh_css_set_dp_config(stream->pipes[i], params, - &stream_params->pipe_dp_config[stream->pipes[i]->mode]); - ia_css_set_param_exceptions(stream->pipes[i], params); - } else { - retval = false; - goto exit; - } - } } - if (!IS_ISP2401) - ia_css_set_param_exceptions(pipe_in, params); + ia_css_set_param_exceptions(pipe_in, params); params->fpn_config.data = stream_params->fpn_config.data; params->config_changed[IA_CSS_FPN_ID] = @@ -2806,10 +2745,7 @@ int ia_css_pipe_set_bci_scaler_lut(struct ia_css_pipe *pipe, pipe->scaler_pp_lut = mmgr_NULL; if (!stream_started) { - if (!IS_ISP2401) - pipe->scaler_pp_lut = hmm_alloc(sizeof(zoom_table), HMM_BO_PRIVATE, 0, NULL, 0); - else - pipe->scaler_pp_lut = sh_css_params_alloc_gdc_lut(); + pipe->scaler_pp_lut = hmm_alloc(sizeof(zoom_table), HMM_BO_PRIVATE, 0, NULL, 0); if (pipe->scaler_pp_lut == mmgr_NULL) { ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, @@ -2851,10 +2787,7 @@ int sh_css_params_map_and_store_default_gdc_lut(void) host_lut_store((void *)zoom_table); - if (!IS_ISP2401) - default_gdc_lut = hmm_alloc(sizeof(zoom_table), HMM_BO_PRIVATE, 0, NULL, 0); - else - default_gdc_lut = sh_css_params_alloc_gdc_lut(); + default_gdc_lut = hmm_alloc(sizeof(zoom_table), HMM_BO_PRIVATE, 0, NULL, 0); if (default_gdc_lut == mmgr_NULL) return -ENOMEM; @@ -3450,18 +3383,12 @@ sh_css_params_write_to_ddr_internal( if (binary->info->sp.enable.sc) { u32 enable_conv; - size_t bytes; - - if (!IS_ISP2401) - bytes = ISP2400_SCTBL_BYTES(binary); - else - bytes = ISP2401_SCTBL_BYTES(binary); enable_conv = params->shading_settings.enable_shading_table_conversion; buff_realloced = reallocate_buffer(&ddr_map->sc_tbl, &ddr_map_size->sc_tbl, - bytes, + SCTBL_BYTES(binary), params->sc_table_changed, &err); if (err) { @@ -3546,28 +3473,6 @@ sh_css_params_write_to_ddr_internal( } } - /* DPC configuration is made pipe specific to allow flexibility in positioning of the - * DPC kernel. The code below sets the pipe specific configuration to - * individual binaries. */ - if (IS_ISP2401 && - params->pipe_dpc_config_changed[pipe_id] && binary->info->sp.enable.dpc) { - unsigned int size = - stage->binary->info->mem_offsets.offsets.param->dmem.dp.size; - - unsigned int offset = - stage->binary->info->mem_offsets.offsets.param->dmem.dp.offset; - - if (size) { - ia_css_dp_encode((struct sh_css_isp_dp_params *) - &binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset], - ¶ms->pipe_dp_config[pipe_id], size); - - params->isp_params_changed = true; - params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM] = - true; - } - } - if (params->config_changed[IA_CSS_MACC_ID] && binary->info->sp.enable.macc) { unsigned int i, j, idx; unsigned int idx_map[] = { @@ -3649,13 +3554,7 @@ sh_css_params_write_to_ddr_internal( if (!params->pipe_dvs_6axis_config[pipe_id]) { struct ia_css_resolution dvs_offset = {0}; - if (!IS_ISP2401) { - dvs_offset.width = (PIX_SHIFT_FILTER_RUN_IN_X + binary->dvs_envelope.width) / 2; - } else { - if (binary->dvs_envelope.width || binary->dvs_envelope.height) { - dvs_offset.width = (PIX_SHIFT_FILTER_RUN_IN_X + binary->dvs_envelope.width) / 2; - } - } + dvs_offset.width = (PIX_SHIFT_FILTER_RUN_IN_X + binary->dvs_envelope.width) / 2; dvs_offset.height = (PIX_SHIFT_FILTER_RUN_IN_Y + binary->dvs_envelope.height) / 2; params->pipe_dvs_6axis_config[pipe_id] = From 35009261b9e9d02190afad4c8485cf6d2a8b80aa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 06:44:29 +0000 Subject: [PATCH 141/397] media: atomisp: sh_css_params: cleanup the code Now that the tests for the new ISP2401 input system were dropped, simplify the code, making it closer to the Intel Aero device driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 6 +- .../staging/media/atomisp/pci/sh_css_params.c | 92 +++---------------- .../staging/media/atomisp/pci/sh_css_params.h | 8 -- 3 files changed, 15 insertions(+), 91 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index acaa4c8b1884..1d605e533e29 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -2250,8 +2250,10 @@ ia_css_pipe_destroy(struct ia_css_pipe *pipe) break; } - sh_css_params_free_gdc_lut(pipe->scaler_pp_lut); - pipe->scaler_pp_lut = mmgr_NULL; + if (pipe->scaler_pp_lut != mmgr_NULL) { + hmm_free(pipe->scaler_pp_lut); + pipe->scaler_pp_lut = mmgr_NULL; + } my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL; sh_css_pipe_free_shading_table(pipe); diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c index 68d8f54473ea..f3f8d99c84a4 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/sh_css_params.c @@ -1020,16 +1020,6 @@ sh_css_params_set_binning_factor(struct ia_css_stream *stream, return params->sc_table_changed; } -static void -sh_css_update_shading_table_status(struct ia_css_pipe *pipe, - struct ia_css_isp_parameters *params) -{ - if (params && pipe && (pipe->pipe_num != params->sc_table_last_pipe_num)) { - params->sc_table_dirty = true; - params->sc_table_last_pipe_num = pipe->pipe_num; - } -} - static void sh_css_set_shading_table(struct ia_css_stream *stream, struct ia_css_isp_parameters *params, @@ -1043,10 +1033,9 @@ sh_css_set_shading_table(struct ia_css_stream *stream, if (!table->enable) table = NULL; - if ((table != params->sc_table) || params->sc_table_dirty) { + if (table != params->sc_table) { params->sc_table = table; params->sc_table_changed = true; - params->sc_table_dirty = false; /* Not very clean, this goes to sh_css.c to invalidate the * shading table for all pipes. Should replaced by a loop * and a pipe-specific call. @@ -1608,45 +1597,6 @@ ia_css_set_param_exceptions(const struct ia_css_pipe *pipe, params->dp_config.gb = params->wb_config.gb; } -/* ISP2401 */ -static void -sh_css_set_dp_config(const struct ia_css_pipe *pipe, - struct ia_css_isp_parameters *params, - const struct ia_css_dp_config *config) -{ - if (!config) - return; - - assert(params); - assert(pipe); - assert(pipe->mode < IA_CSS_PIPE_ID_NUM); - - IA_CSS_ENTER_PRIVATE("config=%p", config); - ia_css_dp_debug_dtrace(config, IA_CSS_DEBUG_TRACE_PRIVATE); - if (pipe->mode < IA_CSS_PIPE_ID_NUM) { - params->pipe_dp_config[pipe->mode] = *config; - params->pipe_dpc_config_changed[pipe->mode] = true; - } - IA_CSS_LEAVE_PRIVATE("void"); -} - -static void -sh_css_get_dp_config(const struct ia_css_pipe *pipe, - const struct ia_css_isp_parameters *params, - struct ia_css_dp_config *config) -{ - if (!config) - return; - - assert(params); - assert(pipe); - IA_CSS_ENTER_PRIVATE("config=%p", config); - - *config = params->pipe_dp_config[pipe->mode]; - - IA_CSS_LEAVE_PRIVATE("void"); -} - static void sh_css_set_nr_config(struct ia_css_isp_parameters *params, const struct ia_css_nr_config *config) @@ -1718,9 +1668,7 @@ sh_css_set_pipe_dvs_6axis_config(const struct ia_css_pipe *pipe, copy_dvs_6axis_table(params->pipe_dvs_6axis_config[pipe->mode], dvs_config); -#if !defined(HAS_NO_DVS_6AXIS_CONFIG_UPDATE) params->pipe_dvs_6axis_config_changed[pipe->mode] = true; -#endif IA_CSS_LEAVE_PRIVATE("void"); } @@ -2039,7 +1987,6 @@ sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe, sh_css_set_pipe_dvs_6axis_config(pipe, params, config->dvs_6axis_config); sh_css_set_dz_config(params, config->dz_config); sh_css_set_motion_vector(params, config->motion_vector); - sh_css_update_shading_table_status(pipe_in, params); sh_css_set_shading_table(pipe->stream, params, config->shading_table); sh_css_set_morph_table(params, config->morph_table); sh_css_set_macc_table(params, config->macc_table); @@ -2104,7 +2051,6 @@ ia_css_pipe_get_isp_config(struct ia_css_pipe *pipe, sh_css_get_ee_config(params, config->ee_config); sh_css_get_baa_config(params, config->baa_config); sh_css_get_pipe_dvs_6axis_config(pipe, params, config->dvs_6axis_config); - sh_css_get_dp_config(pipe, params, config->dp_config); sh_css_get_macc_table(params, config->macc_table); sh_css_get_gamma_table(params, config->gamma_table); sh_css_get_ctc_table(params, config->ctc_table); @@ -2523,8 +2469,6 @@ sh_css_init_isp_params_from_global(struct ia_css_stream *stream, params->sc_table = NULL; params->sc_table_changed = true; - params->sc_table_dirty = false; - params->sc_table_last_pipe_num = 0; ia_css_sdis2_clear_coefficients(¶ms->dvs2_coefs); params->dvs2_coef_table_changed = true; @@ -2582,11 +2526,8 @@ sh_css_init_isp_params_from_global(struct ia_css_stream *stream, * BDS is enabled by the user. But we do not return * the value immediately to enable internal firmware * feature testing. */ - - if (is_dp_10bpp) { - retval = false; - /* FIXME: should it ignore this error? */ - } + retval = !is_dp_10bpp; + /* FIXME: should it ignore this error? */ } else { retval = false; goto exit; @@ -2604,13 +2545,10 @@ sh_css_init_isp_params_from_global(struct ia_css_stream *stream, sh_css_set_morph_table(params, stream_params->morph_table); if (stream_params->sc_table) { - sh_css_update_shading_table_status(pipe_in, params); sh_css_set_shading_table(stream, params, stream_params->sc_table); } else { params->sc_table = NULL; params->sc_table_changed = true; - params->sc_table_dirty = false; - params->sc_table_last_pipe_num = 0; } /* Only IA_CSS_PIPE_ID_VIDEO & IA_CSS_PIPE_ID_CAPTURE will support dvs_6axis_config*/ @@ -2703,18 +2641,6 @@ static void host_lut_store(const void *lut) gdc_lut_store((gdc_ID_t)i, (const int (*)[HRT_GDC_N]) lut); } -/* Note that allocation is in ipu address space. */ -inline ia_css_ptr sh_css_params_alloc_gdc_lut(void) -{ - return hmm_alloc(sizeof(zoom_table), HMM_BO_PRIVATE, 0, NULL, 0); -} - -inline void sh_css_params_free_gdc_lut(ia_css_ptr addr) -{ - if (addr != mmgr_NULL) - hmm_free(addr); -} - int ia_css_pipe_set_bci_scaler_lut(struct ia_css_pipe *pipe, const void *lut) { @@ -2741,8 +2667,10 @@ int ia_css_pipe_set_bci_scaler_lut(struct ia_css_pipe *pipe, } /* Free any existing tables. */ - sh_css_params_free_gdc_lut(pipe->scaler_pp_lut); - pipe->scaler_pp_lut = mmgr_NULL; + if (pipe->scaler_pp_lut != mmgr_NULL) { + hmm_free(pipe->scaler_pp_lut); + pipe->scaler_pp_lut = mmgr_NULL; + } if (!stream_started) { pipe->scaler_pp_lut = hmm_alloc(sizeof(zoom_table), HMM_BO_PRIVATE, 0, NULL, 0); @@ -2805,8 +2733,10 @@ void sh_css_params_free_default_gdc_lut(void) { IA_CSS_ENTER_PRIVATE("void"); - sh_css_params_free_gdc_lut(default_gdc_lut); - default_gdc_lut = mmgr_NULL; + if (default_gdc_lut != mmgr_NULL) { + hmm_free(default_gdc_lut); + default_gdc_lut = mmgr_NULL; + } IA_CSS_LEAVE_PRIVATE("void"); } diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.h b/drivers/staging/media/atomisp/pci/sh_css_params.h index 62a7b6ada237..bbca19d0e8fc 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.h +++ b/drivers/staging/media/atomisp/pci/sh_css_params.h @@ -121,8 +121,6 @@ struct ia_css_isp_parameters { bool dvs2_coef_table_changed; bool morph_table_changed; bool sc_table_changed; - bool sc_table_dirty; - unsigned int sc_table_last_pipe_num; bool anr_thres_changed; /* ---- deprecated: replaced with pipe_dvs_6axis_config_changed ---- */ bool dvs_6axis_config_changed; @@ -168,12 +166,6 @@ ia_css_params_alloc_convert_sctbl( struct ia_css_isp_config * sh_css_pipe_isp_config_get(struct ia_css_pipe *pipe); -/* ipu address allocation/free for gdc lut */ -ia_css_ptr -sh_css_params_alloc_gdc_lut(void); -void -sh_css_params_free_gdc_lut(ia_css_ptr addr); - int sh_css_params_map_and_store_default_gdc_lut(void); From 63705da3dfc8922a2dbfc3c805a5faadb4416954 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 07:19:06 +0000 Subject: [PATCH 142/397] media: atomisp: remove #ifdef HAS_NO_HMEM This is not defined anywhere, so, solve the ifdefs, getting rid of them. Signed-off-by: Mauro Carvalho Chehab --- .../atomisp/pci/isp/kernels/bh/bh_2/ia_css_bh.host.c | 2 -- .../raw_aa_binning_1.0/ia_css_raa.host.c | 2 -- .../pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.c | 5 ----- .../media/atomisp/pci/runtime/binary/src/binary.c | 4 ---- drivers/staging/media/atomisp/pci/sh_css_params.c | 10 ---------- 5 files changed, 23 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/bh/bh_2/ia_css_bh.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/bh/bh_2/ia_css_bh.host.c index 82aa69b74677..2091f001502d 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/bh/bh_2/ia_css_bh.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/bh/bh_2/ia_css_bh.host.c @@ -13,7 +13,6 @@ * more details. */ -#if !defined(HAS_NO_HMEM) #include "ia_css_types.h" #include "sh_css_internal.h" @@ -63,4 +62,3 @@ ia_css_bh_encode( uDIGIT_FITTING(from->ae_y_coef_b, 16, SH_CSS_AE_YCOEF_SHIFT); } -#endif diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/raw_aa_binning/raw_aa_binning_1.0/ia_css_raa.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/raw_aa_binning/raw_aa_binning_1.0/ia_css_raa.host.c index 29c707ecf9f3..9b756daddee0 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/raw_aa_binning/raw_aa_binning_1.0/ia_css_raa.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/raw_aa_binning/raw_aa_binning_1.0/ia_css_raa.host.c @@ -13,7 +13,6 @@ * more details. */ -#if !defined(HAS_NO_HMEM) #include "ia_css_types.h" #include "sh_css_internal.h" @@ -32,4 +31,3 @@ ia_css_raa_encode( (void)from; } -#endif diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.c index ba52c80df4a5..bd7b89d9475b 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.c +++ b/drivers/staging/media/atomisp/pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.c @@ -227,10 +227,6 @@ ia_css_s3a_hmem_decode( struct ia_css_3a_statistics *host_stats, const struct ia_css_bh_table *hmem_buf) { -#if defined(HAS_NO_HMEM) - (void)host_stats; - (void)hmem_buf; -#else struct ia_css_3a_rgby_output *out_ptr; int i; @@ -291,7 +287,6 @@ ia_css_s3a_hmem_decode( out_ptr[0].g -= diff; out_ptr[0].b -= diff; out_ptr[0].y -= diff; -#endif } void diff --git a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c index 851e1d34a521..bbb93cb8c070 100644 --- a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c +++ b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c @@ -805,11 +805,7 @@ ia_css_binary_3a_grid_info(const struct ia_css_binary *binary, s3a_info->deci_factor_log2 = binary->deci_factor_log2; s3a_info->elem_bit_depth = SH_CSS_BAYER_BITS; s3a_info->use_dmem = binary->info->sp.s3a.s3atbl_use_dmem; -#if defined(HAS_NO_HMEM) - s3a_info->has_histogram = 1; -#else s3a_info->has_histogram = 0; -#endif IA_CSS_LEAVE_ERR_PRIVATE(err); return err; } diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c index f3f8d99c84a4..41ed8e4600ff 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/sh_css_params.c @@ -16,12 +16,10 @@ #include "gdc_device.h" /* gdc_lut_store(), ... */ #include "isp.h" /* ISP_VEC_ELEMBITS */ #include "vamem.h" -#if !defined(HAS_NO_HMEM) #ifndef __INLINE_HMEM__ #define __INLINE_HMEM__ #endif #include "hmem.h" -#endif /* !defined(HAS_NO_HMEM) */ #define IA_CSS_INCLUDE_PARAMETERS #define IA_CSS_INCLUDE_ACC_PARAMETERS @@ -1489,10 +1487,8 @@ ia_css_translate_3a_statistics( ia_css_s3a_vmem_decode(host_stats, isp_stats->vmem_stats_hi, isp_stats->vmem_stats_lo); } -#if !defined(HAS_NO_HMEM) IA_CSS_LOG("3A: HMEM"); ia_css_s3a_hmem_decode(host_stats, isp_stats->hmem_stats); -#endif IA_CSS_LEAVE("void"); } @@ -2157,9 +2153,7 @@ ia_css_isp_3a_statistics_allocate(const struct ia_css_3a_grid_info *grid) me->vmem_size = ISP_S3ATBL_HI_LO_STRIDE_BYTES * grid->aligned_height; } -#if !defined(HAS_NO_HMEM) me->hmem_size = sizeof_hmem(HMEM0_ID); -#endif /* All subsections need to be aligned to the system bus width */ me->dmem_size = CEIL_MUL(me->dmem_size, HIVE_ISP_DDR_WORD_BYTES); @@ -4148,12 +4142,8 @@ ia_css_3a_statistics_allocate(const struct ia_css_3a_grid_info *grid) me->data = kvmalloc(grid_size * sizeof(*me->data), GFP_KERNEL); if (!me->data) goto err; -#if !defined(HAS_NO_HMEM) /* No weighted histogram, no structure, treat the histogram data as a byte dump in a byte array */ me->rgby_data = kvmalloc(sizeof_hmem(HMEM0_ID), GFP_KERNEL); -#else - me->rgby_data = NULL; -#endif IA_CSS_LEAVE("return=%p", me); return me; From d7ab37bcddc7d7e13681dbb9841b455b0c0bdfe4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 07:24:40 +0000 Subject: [PATCH 143/397] media: atomisp: get rid of USE_WINDOWS_BINNING_FACTOR tests This is meant to select a platform-dependent factor between Linux and Windows. It makes no sense to keep it on Kernel. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/ia_css_stream_public.h | 10 ++++------ .../media/atomisp/pci/sh_css_param_shading.c | 16 ---------------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/ia_css_stream_public.h b/drivers/staging/media/atomisp/pci/ia_css_stream_public.h index 649f22b03de8..47846ece8d64 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_stream_public.h +++ b/drivers/staging/media/atomisp/pci/ia_css_stream_public.h @@ -102,12 +102,10 @@ struct ia_css_stream_config { isys_config[IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH]; struct ia_css_stream_input_config input_config; - /* Currently, Android and Windows platforms interpret the binning_factor parameter - * differently. In Android, the binning factor is expressed in the form - * 2^N * 2^N, whereas in Windows platform, the binning factor is N*N - * To use the Windows method of specification, the caller has to define - * macro USE_WINDOWS_BINNING_FACTOR. This is for backward compatibility only - * and will be deprecated. In the future,all platforms will use the N*N method + /* + * Currently, Linux and Windows platforms interpret the binning_factor + * parameter differently. In Linux, the binning factor is expressed + * in the form 2^N * 2^N */ /* ISP2401 */ unsigned int sensor_binning_factor; /** Binning factor used by sensor diff --git a/drivers/staging/media/atomisp/pci/sh_css_param_shading.c b/drivers/staging/media/atomisp/pci/sh_css_param_shading.c index 69cc4e423d8b..dc433fd96d55 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_param_shading.c +++ b/drivers/staging/media/atomisp/pci/sh_css_param_shading.c @@ -271,15 +271,6 @@ prepare_shading_table(const struct ia_css_shading_table *in_table, bds_denominator - binary->info->sp.pipeline.top_cropping; -#if !defined(USE_WINDOWS_BINNING_FACTOR) - /* @deprecated{This part of the code will be replaced by the code - * in the #else section below to make the calculation same across - * all platforms. - * Android and Windows platforms interpret the binning_factor parameter - * differently. In Android, the binning factor is expressed in the form - * 2^N * 2^N, whereas in Windows platform, the binning factor is N*N} - */ - /* We take into account the binning done by the sensor. We do this by cropping the non-binned part of the shading table and then increasing the size of a grid cell with this same binning factor. */ @@ -291,13 +282,6 @@ prepare_shading_table(const struct ia_css_shading_table *in_table, left_padding <<= sensor_binning; right_padding <<= sensor_binning; top_padding <<= sensor_binning; -#else - input_width *= sensor_binning; - input_height *= sensor_binning; - left_padding *= sensor_binning; - right_padding *= sensor_binning; - top_padding *= sensor_binning; -#endif /*USE_WINDOWS_BINNING_FACTOR*/ /* during simulation, the used resolution can exceed the sensor resolution, so we clip it. */ From c0a7df148e9d641c622c5ef807da449c99b7fabf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 08:02:39 +0000 Subject: [PATCH 144/397] media: atomisp: get rid of #ifdef HAS_BL This does nothing but declare extern to a non-existing var. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css_firmware.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.h b/drivers/staging/media/atomisp/pci/sh_css_firmware.h index 66cd38f08f71..a73ce703adfb 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_firmware.h +++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.h @@ -29,9 +29,6 @@ struct sh_css_fw_bi_file_h { }; extern struct ia_css_fw_info sh_css_sp_fw; -#if defined(HAS_BL) -extern struct ia_css_fw_info sh_css_bl_fw; -#endif /* HAS_BL */ extern struct ia_css_blob_descr *sh_css_blob_info; extern unsigned int sh_css_num_binaries; From 50f1d9343b915a7c3480c0aff9f6a01aea034987 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 08:28:51 +0000 Subject: [PATCH 145/397] media: atomisp: get rid of sctbl_legacy_* Those seem to be used only on certain ISP2401 firmwares that aren't supported by the driver. So, get rid of them. Signed-off-by: Mauro Carvalho Chehab --- .../atomisp/pci/runtime/binary/interface/ia_css_binary.h | 2 -- .../staging/media/atomisp/pci/runtime/binary/src/binary.c | 6 ------ drivers/staging/media/atomisp/pci/sh_css_param_shading.c | 8 ++++---- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h b/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h index 6f110d241836..9935ac860bc2 100644 --- a/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h +++ b/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h @@ -130,8 +130,6 @@ struct ia_css_binary { int sctbl_width_per_color; int sctbl_aligned_width_per_color; int sctbl_height; - int sctbl_legacy_width_per_color; - int sctbl_legacy_height; struct ia_css_sdis_info dis; struct ia_css_resolution dvs_envelope; bool online; diff --git a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c index bbb93cb8c070..9af23fdb127b 100644 --- a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c +++ b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c @@ -1339,18 +1339,12 @@ ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo, binary->sctbl_width_per_color = _ISP2401_SCTBL_WIDTH_PER_COLOR(isp_internal_width, s3a_log_deci); binary->sctbl_aligned_width_per_color = SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR; binary->sctbl_height = _ISP2401_SCTBL_HEIGHT(isp_internal_height, s3a_log_deci); - binary->sctbl_legacy_width_per_color = _ISP_SCTBL_LEGACY_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci); - binary->sctbl_legacy_height = _ISP_SCTBL_LEGACY_HEIGHT(sc_3a_dis_height, s3a_log_deci); } } else { binary->sctbl_width_per_color = 0; binary->sctbl_aligned_width_per_color = 0; binary->sctbl_height = 0; - if (IS_ISP2401) { - binary->sctbl_legacy_width_per_color = 0; - binary->sctbl_legacy_height = 0; - } } ia_css_sdis_init_info(&binary->dis, sc_3a_dis_width, diff --git a/drivers/staging/media/atomisp/pci/sh_css_param_shading.c b/drivers/staging/media/atomisp/pci/sh_css_param_shading.c index dc433fd96d55..0abd5bf36b7f 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_param_shading.c +++ b/drivers/staging/media/atomisp/pci/sh_css_param_shading.c @@ -242,8 +242,8 @@ prepare_shading_table(const struct ia_css_shading_table *in_table, if (!in_table) { sh_css_params_shading_id_table_generate(target_table, - binary->sctbl_legacy_width_per_color, - binary->sctbl_legacy_height); + binary->sctbl_width_per_color, + binary->sctbl_height); return; } @@ -290,8 +290,8 @@ prepare_shading_table(const struct ia_css_shading_table *in_table, /* This prepare_shading_table() function is called only in legacy API (not in new API). Then, the legacy shading table width and height should be used. */ - table_width = binary->sctbl_legacy_width_per_color; - table_height = binary->sctbl_legacy_height; + table_width = binary->sctbl_width_per_color; + table_height = binary->sctbl_height; result = ia_css_shading_table_alloc(table_width, table_height); if (!result) { From 3b941c5a19680ea9d42527152b56685acd681b09 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 08:38:30 +0000 Subject: [PATCH 146/397] media: atomisp: sh_css_param_shading: fix comments coding style The comments are not following Kernel coding style. Also, there are two missing comments that are found at the Intel Aero device driver code. Add them. No functional changes. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/sh_css_param_shading.c | 58 ++++++++++++------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_param_shading.c b/drivers/staging/media/atomisp/pci/sh_css_param_shading.c index 0abd5bf36b7f..41a4c9162319 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_param_shading.c +++ b/drivers/staging/media/atomisp/pci/sh_css_param_shading.c @@ -118,8 +118,10 @@ crop_and_interpolate(unsigned int cropped_width, int ty, src_y0, src_y1; unsigned int sy0, sy1, dy0, dy1, divy; - /* calculate target point and make sure it falls within - the table */ + /* + * calculate target point and make sure it falls within + * the table + */ ty = out_start_row + i * out_cell_size; /* calculate closest source points in shading table and @@ -166,19 +168,24 @@ crop_and_interpolate(unsigned int cropped_width, src_x1 = clamp(src_x1, 0, (int)table_width - 1); tx = min(clamp(tx, 0, (int)sensor_width - 1), (int)table_cell_w); - /* calculate closest source points for distance - computation */ + /* + * calculate closest source points for distance + * computation + */ sx0 = min(src_x0 * in_cell_size, sensor_width - 1); sx1 = min(src_x1 * in_cell_size, sensor_width - 1); - /* calculate distances between source and target - pixels */ + /* + * calculate distances between source and target + * pixels + */ dx0 = tx - sx0; dx1 = sx1 - tx; divx = sx1 - sx0; /* if we're at the edge, we just use the closest - point still in the grid. We make up for the divider - in this case by setting the distance to - out_cell_size, since it's actually 0. */ + * point still in the grid. We make up for the divider + * in this case by setting the distance to + * out_cell_size, since it's actually 0. + */ if (divx == 0) { dx0 = 1; divx = 1; @@ -271,20 +278,26 @@ prepare_shading_table(const struct ia_css_shading_table *in_table, bds_denominator - binary->info->sp.pipeline.top_cropping; - /* We take into account the binning done by the sensor. We do this - by cropping the non-binned part of the shading table and then - increasing the size of a grid cell with this same binning factor. */ + /* + * We take into account the binning done by the sensor. We do this + * by cropping the non-binned part of the shading table and then + * increasing the size of a grid cell with this same binning factor. + */ input_width <<= sensor_binning; input_height <<= sensor_binning; - /* We also scale the padding by the same binning factor. This will - make it much easier later on to calculate the padding of the - shading table. */ + /* + * We also scale the padding by the same binning factor. This will + * make it much easier later on to calculate the padding of the + * shading table. + */ left_padding <<= sensor_binning; right_padding <<= sensor_binning; top_padding <<= sensor_binning; - /* during simulation, the used resolution can exceed the sensor - resolution, so we clip it. */ + /* + * during simulation, the used resolution can exceed the sensor + * resolution, so we clip it. + */ input_width = min(input_width, in_table->sensor_width); input_height = min(input_height, in_table->sensor_height); @@ -302,8 +315,10 @@ prepare_shading_table(const struct ia_css_shading_table *in_table, result->sensor_height = in_table->sensor_height; result->fraction_bits = in_table->fraction_bits; - /* now we crop the original shading table and then interpolate to the - requested resolution and decimation factor. */ + /* + * now we crop the original shading table and then interpolate to the + * requested resolution and decimation factor. + */ for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) { crop_and_interpolate(input_width, input_height, left_padding, right_padding, top_padding, @@ -360,9 +375,10 @@ ia_css_shading_table_free(struct ia_css_shading_table *table) if (!table) return; - /* We only output logging when the table is not NULL, otherwise + /* + * We only output logging when the table is not NULL, otherwise * logs will give the impression that a table was freed. - * */ + */ IA_CSS_ENTER(""); for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) { From 072927d1cebf47eb3020c26d2d2db3f51936c928 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 09:12:50 +0000 Subject: [PATCH 147/397] media: atomisp: sh_css_sp: better support the current firmware As we're using Intel Aero firmware, make the code closer to the driver for such device. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css_sp.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index 778639f391cb..615500a7d3c4 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -1032,16 +1032,14 @@ sh_css_sp_init_stage(struct ia_css_binary *binary, return err; #ifdef ISP2401 - if (stage == 0) { - pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num); - if (!pipe) - return -EINVAL; + pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num); + if (!pipe) + return -EINVAL; - if (args->in_frame) - ia_css_get_crop_offsets(pipe, &args->in_frame->info); - else - ia_css_get_crop_offsets(pipe, &binary->in_frame_info); - } + if (args->in_frame) + ia_css_get_crop_offsets(pipe, &args->in_frame->info); + else + ia_css_get_crop_offsets(pipe, &binary->in_frame_info); #else (void)pipe; /*avoid build warning*/ #endif From 13d72e694271dcc67029dc5bb7709053b813fe2d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 14:13:11 +0000 Subject: [PATCH 148/397] media: atomisp: atomisp_cmd: make it more compatible with firmware Change some recovery logic at the driver, in order to make it more compatible with ISP2401 Intel Aero firmware. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 7181b901cde4..86dad9fe61bf 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -1046,13 +1046,8 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error, asd->pending_capture_request--; - if (IS_ISP2401) - asd->re_trigger_capture = false; - dev_dbg(isp->dev, "Trigger capture again for new buffer. err=%d\n", err); - } else if (IS_ISP2401) { - asd->re_trigger_capture = true; } break; case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: @@ -1474,7 +1469,7 @@ void atomisp_wdt_work(struct work_struct *work) wdt_work); int i; unsigned int pipe_wdt_cnt[MAX_STREAM_NUM][4] = { {0} }; - bool css_recover = false; + bool css_recover = true; rt_mutex_lock(&isp->mutex); if (!atomisp_streaming_count(isp)) { @@ -1487,12 +1482,7 @@ void atomisp_wdt_work(struct work_struct *work) dev_err(isp->dev, "timeout %d of %d\n", atomic_read(&isp->wdt_count) + 1, ATOMISP_ISP_MAX_TIMEOUT_COUNT); - - if (atomic_inc_return(&isp->wdt_count) < ATOMISP_ISP_MAX_TIMEOUT_COUNT) - css_recover = true; } else { - css_recover = true; - for (i = 0; i < isp->num_of_streams; i++) { struct atomisp_sub_device *asd = &isp->asd[i]; @@ -6003,7 +5993,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) * which appears to be related by a hardware * performance limitation. It's unclear why this * particular code triggers the issue. */ - if (!IS_ISP2401 || crop_needs_override) { + if (crop_needs_override) { if (isp_sink_crop.width * main_compose.height > isp_sink_crop.height * main_compose.width) { sink_crop.height = isp_sink_crop.height; From 3f323bb4cfdf53ab6e23e6be7979066826cab7a9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 17:15:09 +0000 Subject: [PATCH 149/397] media: atomisp: get rid of set pipe version custom ctrl It doesn't make sense to have a control for that. Besides that, the Intel Aero implementation doesn't have, which means that even the custom control is not used in practice, at least outside Android. So, get rid of it. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_compat_css20.c | 9 -------- .../media/atomisp/pci/atomisp_subdev.c | 23 ------------------- .../media/atomisp/pci/atomisp_subdev.h | 1 - 3 files changed, 33 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 7edee293b132..1173be0e72b0 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -611,15 +611,6 @@ static void __apply_additional_pipe_config( if (stream_env->pipe_configs[pipe_id]. default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW) stream_env->pipe_configs[pipe_id].enable_dz = false; - - if (IS_ISP2401) { - /* the isp default to use ISP2.2 and the camera hal will - * control whether use isp2.7 */ - if (asd->select_isp_version->val == ATOMISP_CSS_ISP_PIPE_VERSION_2_7) - stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_7; - else - stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_2; - } break; case IA_CSS_PIPE_ID_VIDEO: /* enable reduced pipe to have binary diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index a3f3c42f9db7..1807cfa786a7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -1058,24 +1058,6 @@ static const struct v4l2_ctrl_config ctrl_depth_mode = { .def = 0, }; -/* - * Control for selectting ISP version - * - * When enabled, that means ISP version will be used ISP2.7. when disable, the - * isp will default to use ISP2.2. - * Note: Make sure set this configuration before creating stream. - */ -static const struct v4l2_ctrl_config ctrl_select_isp_version = { - .ops = &ctrl_ops, - .id = V4L2_CID_ATOMISP_SELECT_ISP_VERSION, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Select Isp version", - .min = 0, - .max = 1, - .step = 1, - .def = 0, -}; - static void atomisp_init_subdev_pipe(struct atomisp_sub_device *asd, struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type) { @@ -1223,11 +1205,6 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) v4l2_ctrl_new_custom(&asd->ctrl_handler, &ctrl_disable_dz, NULL); - if (IS_ISP2401) { - asd->select_isp_version = v4l2_ctrl_new_custom(&asd->ctrl_handler, - &ctrl_select_isp_version, - NULL); - } /* Make controls visible on subdev as well. */ asd->subdev.ctrl_handler = &asd->ctrl_handler; diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index a8d210ea5f8b..7d731f1fee72 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -319,7 +319,6 @@ struct atomisp_sub_device { /* ISP2401 */ struct v4l2_ctrl *ion_dev_fd; - struct v4l2_ctrl *select_isp_version; struct v4l2_ctrl *disable_dz; From 4f948a3283809317389d54077cbc2b08bac536f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 17:44:26 +0000 Subject: [PATCH 150/397] media: atomisp: simplify binary.c Signed-off-by: Mauro Carvalho Chehab --- .../atomisp/pci/runtime/binary/src/binary.c | 413 +----------------- 1 file changed, 10 insertions(+), 403 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c index 9af23fdb127b..5e435bec942b 100644 --- a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c +++ b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c @@ -261,227 +261,12 @@ ia_css_binary_compute_shading_table_bayer_origin( return err; } -/* ISP2401: Get the requirements for the shading correction. */ -static int -sh_css_binary_get_sc_requirements(const struct ia_css_binary *binary, /* [in] */ - unsigned int required_bds_factor, /* [in] */ - const struct ia_css_stream_config *stream_config, /* [in] */ - struct sh_css_binary_sc_requirements *scr) /* [out] */ -{ - int err; - - /* Numerator and denominator of the fixed bayer downscaling factor. (numerator >= denominator) */ - unsigned int bds_num, bds_den; - - /* Horizontal/Vertical ratio of bayer scaling between input area and output area. */ - unsigned int bs_hor_ratio_in, bs_hor_ratio_out, bs_ver_ratio_in, bs_ver_ratio_out; - - /* Left padding set by InputFormatter. */ - unsigned int left_padding_bqs; - - /* Flags corresponding to NEED_BDS_FACTOR_2_00/NEED_BDS_FACTOR_1_50/NEED_BDS_FACTOR_1_25 macros - * defined in isp kernels. */ - unsigned int need_bds_factor_2_00, need_bds_factor_1_50, need_bds_factor_1_25; - - /* Left padding adjusted inside the isp kernels. */ - unsigned int left_padding_adjusted_bqs; - - /* Top padding padded inside the isp kernel for bayer downscaling binaries. */ - unsigned int top_padding_bqs; - - /* Bayer downscaling factor 1.0 by fixed-point. */ - int bds_frac_acc = FRAC_ACC; /* FRAC_ACC is defined in ia_css_fixedbds_param.h. */ - - /* Right/Down shift amount caused by filters applied BEFORE shading corrertion. */ - unsigned int right_shift_bqs_before_bs; /* right shift before bayer scaling */ - unsigned int right_shift_bqs_after_bs; /* right shift after bayer scaling */ - unsigned int down_shift_bqs_before_bs; /* down shift before bayer scaling */ - unsigned int down_shift_bqs_after_bs; /* down shift after bayer scaling */ - - /* Origin of the real sensor data area on the internal frame at shading correction. */ - unsigned int sensor_data_origin_x_bqs_on_internal; - unsigned int sensor_data_origin_y_bqs_on_internal; - - unsigned int bs_frac = bds_frac_acc; /* scaling factor 1.0 in fixed point */ - unsigned int bs_out, bs_in; /* scaling ratio in fixed point */ - - IA_CSS_ENTER_PRIVATE("binary=%p, required_bds_factor=%d, stream_config=%p", - binary, required_bds_factor, stream_config); - - /* Get the numerator and denominator of the required bayer downscaling factor. */ - err = sh_css_bds_factor_get_numerator_denominator(required_bds_factor, - &bds_num, &bds_den); - if (err) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - IA_CSS_LOG("bds_num=%d, bds_den=%d", bds_num, bds_den); - - /* Set the horizontal/vertical ratio of bayer scaling between input area and output area. */ - bs_hor_ratio_in = bds_num; - bs_hor_ratio_out = bds_den; - bs_ver_ratio_in = bds_num; - bs_ver_ratio_out = bds_den; - - /* Set the left padding set by InputFormatter. (ia_css_ifmtr_configure() in ifmtr.c) */ - if (stream_config->left_padding == -1) - left_padding_bqs = _ISP_BQS(binary->left_padding); - else - left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS - _ISP_BQS(stream_config->left_padding)); - - IA_CSS_LOG("stream.left_padding=%d, binary.left_padding=%d, left_padding_bqs=%d", - stream_config->left_padding, binary->left_padding, - left_padding_bqs); - - /* Set the left padding adjusted inside the isp kernels. - * When the bds_factor isn't 1.00, the left padding size is adjusted inside the isp, - * before bayer downscaling. (scaled_hor_plane_index(), raw_compute_hphase() in raw.isp.c) - */ - need_bds_factor_2_00 = ((binary->info->sp.bds.supported_bds_factors & - (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_00) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_00) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_8_00))) != 0); - - need_bds_factor_1_50 = ((binary->info->sp.bds.supported_bds_factors & - (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_1_50) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_25) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00))) != 0); - - need_bds_factor_1_25 = ((binary->info->sp.bds.supported_bds_factors & - (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_1_25) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) | - PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00))) != 0); - - if (binary->info->sp.pipeline.left_cropping > 0 && - (need_bds_factor_2_00 || need_bds_factor_1_50 || need_bds_factor_1_25)) { - /* - * downscale 2.0 -> first_vec_adjusted_bqs = 128 - * downscale 1.5 -> first_vec_adjusted_bqs = 96 - * downscale 1.25 -> first_vec_adjusted_bqs = 80 - */ - unsigned int first_vec_adjusted_bqs = ISP_VEC_NELEMS * bs_hor_ratio_in / bs_hor_ratio_out; - left_padding_adjusted_bqs = first_vec_adjusted_bqs - - _ISP_BQS(binary->info->sp.pipeline.left_cropping); - } else { - left_padding_adjusted_bqs = left_padding_bqs; - } - - IA_CSS_LOG("supported_bds_factors=%d, need_bds_factor:2_00=%d, 1_50=%d, 1_25=%d", - binary->info->sp.bds.supported_bds_factors, - need_bds_factor_2_00, need_bds_factor_1_50, - need_bds_factor_1_25); - IA_CSS_LOG("left_cropping=%d, left_padding_adjusted_bqs=%d", - binary->info->sp.pipeline.left_cropping, - left_padding_adjusted_bqs); - - /* Set the top padding padded inside the isp kernel for bayer downscaling binaries. - * When the bds_factor isn't 1.00, the top padding is padded inside the isp - * before bayer downscaling, because the top cropping size (input margin) is not enough. - * (calculate_input_line(), raw_compute_vphase(), dma_read_raw() in raw.isp.c) - * NOTE: In dma_read_raw(), the factor passed to raw_compute_vphase() is got by get_bds_factor_for_dma_read(). - * This factor is BDS_FPVAL_100/BDS_FPVAL_125/BDS_FPVAL_150/BDS_FPVAL_200. - */ - top_padding_bqs = 0; - if (binary->info->sp.pipeline.top_cropping > 0 && - (required_bds_factor == SH_CSS_BDS_FACTOR_1_25 || - required_bds_factor == SH_CSS_BDS_FACTOR_1_50 || - required_bds_factor == SH_CSS_BDS_FACTOR_2_00)) { - /* Calculation from calculate_input_line() and raw_compute_vphase() in raw.isp.c. */ - int top_cropping_bqs = _ISP_BQS(binary->info->sp.pipeline.top_cropping); - /* top cropping (in bqs) */ - int factor = bds_num * bds_frac_acc / - bds_den; /* downscaling factor by fixed-point */ - int top_padding_bqsxfrac_acc = (top_cropping_bqs * factor - top_cropping_bqs * - bds_frac_acc) - + (2 * bds_frac_acc - factor); /* top padding by fixed-point (in bqs) */ - - top_padding_bqs = (unsigned int)((top_padding_bqsxfrac_acc + bds_frac_acc / 2 - - 1) / bds_frac_acc); - } - - IA_CSS_LOG("top_cropping=%d, top_padding_bqs=%d", - binary->info->sp.pipeline.top_cropping, top_padding_bqs); - - /* Set the right/down shift amount caused by filters applied BEFORE bayer scaling, - * which scaling is applied BEFORE shading corrertion. - * - * When the bds_factor isn't 1.00, 3x3 anti-alias filter is applied to each color plane(Gr/R/B/Gb) - * before bayer downscaling. - * This filter shifts each color plane (Gr/R/B/Gb) to right/down directions by 1 pixel. - */ - right_shift_bqs_before_bs = 0; - down_shift_bqs_before_bs = 0; - - if (need_bds_factor_2_00 || need_bds_factor_1_50 || need_bds_factor_1_25) { - right_shift_bqs_before_bs = 1; - down_shift_bqs_before_bs = 1; - } - - IA_CSS_LOG("right_shift_bqs_before_bs=%d, down_shift_bqs_before_bs=%d", - right_shift_bqs_before_bs, down_shift_bqs_before_bs); - - /* Set the right/down shift amount caused by filters applied AFTER bayer scaling, - * which scaling is applied BEFORE shading corrertion. - * - * When DPC&BNR is processed between bayer scaling and shading correction, - * DPC&BNR moves each color plane (Gr/R/B/Gb) to right/down directions by 1 pixel. - */ - right_shift_bqs_after_bs = 0; - down_shift_bqs_after_bs = 0; - - /* if DPC&BNR is enabled in the binary */ - if (binary->info->mem_offsets.offsets.param->dmem.dp.size != 0) { - right_shift_bqs_after_bs = 1; - down_shift_bqs_after_bs = 1; - } - - IA_CSS_LOG("right_shift_bqs_after_bs=%d, down_shift_bqs_after_bs=%d", - right_shift_bqs_after_bs, down_shift_bqs_after_bs); - - bs_out = bs_hor_ratio_out * bs_frac; - bs_in = bs_hor_ratio_in * bs_frac; - sensor_data_origin_x_bqs_on_internal = - ((left_padding_adjusted_bqs + right_shift_bqs_before_bs) * bs_out + bs_in / 2) / bs_in - + right_shift_bqs_after_bs; /* "+ bs_in/2": rounding */ - - bs_out = bs_ver_ratio_out * bs_frac; - bs_in = bs_ver_ratio_in * bs_frac; - sensor_data_origin_y_bqs_on_internal = - ((top_padding_bqs + down_shift_bqs_before_bs) * bs_out + bs_in / 2) / bs_in - + down_shift_bqs_after_bs; /* "+ bs_in/2": rounding */ - - scr->bayer_scale_hor_ratio_in = (uint32_t)bs_hor_ratio_in; - scr->bayer_scale_hor_ratio_out = (uint32_t)bs_hor_ratio_out; - scr->bayer_scale_ver_ratio_in = (uint32_t)bs_ver_ratio_in; - scr->bayer_scale_ver_ratio_out = (uint32_t)bs_ver_ratio_out; - scr->sensor_data_origin_x_bqs_on_internal = (uint32_t)sensor_data_origin_x_bqs_on_internal; - scr->sensor_data_origin_y_bqs_on_internal = (uint32_t)sensor_data_origin_y_bqs_on_internal; - - IA_CSS_LOG("sc_requirements: %d, %d, %d, %d, %d, %d", - scr->bayer_scale_hor_ratio_in, - scr->bayer_scale_hor_ratio_out, - scr->bayer_scale_ver_ratio_in, scr->bayer_scale_ver_ratio_out, - scr->sensor_data_origin_x_bqs_on_internal, - scr->sensor_data_origin_y_bqs_on_internal); - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - /* Get the shading information of Shading Correction Type 1. */ static int -isp2400_binary_get_shading_info_type_1(const struct ia_css_binary *binary, /* [in] */ - unsigned int required_bds_factor, /* [in] */ - const struct ia_css_stream_config *stream_config, /* [in] */ - struct ia_css_shading_info *info) /* [out] */ +binary_get_shading_info_type_1(const struct ia_css_binary *binary, /* [in] */ + unsigned int required_bds_factor, /* [in] */ + const struct ia_css_stream_config *stream_config, /* [in] */ + struct ia_css_shading_info *info) /* [out] */ { int err; struct sh_css_shading_table_bayer_origin_compute_results res; @@ -522,173 +307,6 @@ isp2400_binary_get_shading_info_type_1(const struct ia_css_binary *binary, /* [i return err; } -/* Get the shading information of Shading Correction Type 1. */ -static int -isp2401_binary_get_shading_info_type_1(const struct ia_css_binary *binary, /* [in] */ - unsigned int required_bds_factor, /* [in] */ - const struct ia_css_stream_config *stream_config, /* [in] */ - struct ia_css_shading_info *shading_info, /* [out] */ - struct ia_css_pipe_config *pipe_config) /* [out] */ -{ - int err; - struct sh_css_binary_sc_requirements scr; - - u32 in_width_bqs, in_height_bqs, internal_width_bqs, internal_height_bqs; - u32 num_hor_grids, num_ver_grids, bqs_per_grid_cell, tbl_width_bqs, tbl_height_bqs; - u32 sensor_org_x_bqs_on_internal, sensor_org_y_bqs_on_internal, sensor_width_bqs, sensor_height_bqs; - u32 sensor_center_x_bqs_on_internal, sensor_center_y_bqs_on_internal; - u32 left, right, upper, lower; - u32 adjust_left, adjust_right, adjust_upper, adjust_lower, adjust_width_bqs, adjust_height_bqs; - u32 internal_org_x_bqs_on_tbl, internal_org_y_bqs_on_tbl; - u32 sensor_org_x_bqs_on_tbl, sensor_org_y_bqs_on_tbl; - - assert(binary); - assert(stream_config); - assert(shading_info); - assert(pipe_config); - - IA_CSS_ENTER_PRIVATE("binary=%p, required_bds_factor=%d, stream_config=%p", - binary, required_bds_factor, stream_config); - - /* Initialize by default values. */ - *shading_info = DEFAULT_SHADING_INFO_TYPE_1; - - err = sh_css_binary_get_sc_requirements(binary, required_bds_factor, stream_config, &scr); - if (err) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - IA_CSS_LOG("binary: id=%d, sctbl=%dx%d, deci=%d", - binary->info->sp.id, binary->sctbl_width_per_color, binary->sctbl_height, binary->deci_factor_log2); - IA_CSS_LOG("binary: in=%dx%d, in_padded_w=%d, int=%dx%d, int_padded_w=%d, out=%dx%d, out_padded_w=%d", - binary->in_frame_info.res.width, binary->in_frame_info.res.height, binary->in_frame_info.padded_width, - binary->internal_frame_info.res.width, binary->internal_frame_info.res.height, - binary->internal_frame_info.padded_width, - binary->out_frame_info[0].res.width, binary->out_frame_info[0].res.height, - binary->out_frame_info[0].padded_width); - - /* Set the input size from sensor, which includes left/top crop size. */ - in_width_bqs = _ISP_BQS(binary->in_frame_info.res.width); - in_height_bqs = _ISP_BQS(binary->in_frame_info.res.height); - - /* - * Frame size internally used in ISP, including sensor data and padding. - * This is the frame size, to which the shading correction is applied. - */ - internal_width_bqs = _ISP_BQS(binary->internal_frame_info.res.width); - internal_height_bqs = _ISP_BQS(binary->internal_frame_info.res.height); - - /* Shading table. */ - num_hor_grids = binary->sctbl_width_per_color; - num_ver_grids = binary->sctbl_height; - bqs_per_grid_cell = (1 << binary->deci_factor_log2); - tbl_width_bqs = (num_hor_grids - 1) * bqs_per_grid_cell; - tbl_height_bqs = (num_ver_grids - 1) * bqs_per_grid_cell; - - IA_CSS_LOG("tbl_width_bqs=%d, tbl_height_bqs=%d", tbl_width_bqs, tbl_height_bqs); - - /* - * Real sensor data area on the internal frame at shading correction. - * Filters and scaling are applied to the internal frame before - * shading correction, depending on the binary. - */ - sensor_org_x_bqs_on_internal = scr.sensor_data_origin_x_bqs_on_internal; - sensor_org_y_bqs_on_internal = scr.sensor_data_origin_y_bqs_on_internal; - { - unsigned int bs_frac = 8; /* scaling factor 1.0 in fixed point (8 == FRAC_ACC macro in ISP) */ - unsigned int bs_out, bs_in; /* scaling ratio in fixed point */ - - bs_out = scr.bayer_scale_hor_ratio_out * bs_frac; - bs_in = scr.bayer_scale_hor_ratio_in * bs_frac; - sensor_width_bqs = (in_width_bqs * bs_out + bs_in / 2) / bs_in; /* "+ bs_in/2": rounding */ - - bs_out = scr.bayer_scale_ver_ratio_out * bs_frac; - bs_in = scr.bayer_scale_ver_ratio_in * bs_frac; - sensor_height_bqs = (in_height_bqs * bs_out + bs_in / 2) / bs_in; /* "+ bs_in/2": rounding */ - } - - /* Center of the sensor data on the internal frame at shading correction. */ - sensor_center_x_bqs_on_internal = sensor_org_x_bqs_on_internal + sensor_width_bqs / 2; - sensor_center_y_bqs_on_internal = sensor_org_y_bqs_on_internal + sensor_height_bqs / 2; - - /* Size of left/right/upper/lower sides of the sensor center on the internal frame. */ - left = sensor_center_x_bqs_on_internal; - right = internal_width_bqs - sensor_center_x_bqs_on_internal; - upper = sensor_center_y_bqs_on_internal; - lower = internal_height_bqs - sensor_center_y_bqs_on_internal; - - /* Align the size of left/right/upper/lower sides to a multiple of the grid cell size. */ - adjust_left = CEIL_MUL(left, bqs_per_grid_cell); - adjust_right = CEIL_MUL(right, bqs_per_grid_cell); - adjust_upper = CEIL_MUL(upper, bqs_per_grid_cell); - adjust_lower = CEIL_MUL(lower, bqs_per_grid_cell); - - /* Shading table should cover the adjusted frame size. */ - adjust_width_bqs = adjust_left + adjust_right; - adjust_height_bqs = adjust_upper + adjust_lower; - - IA_CSS_LOG("adjust_width_bqs=%d, adjust_height_bqs=%d", adjust_width_bqs, adjust_height_bqs); - - if (adjust_width_bqs > tbl_width_bqs || adjust_height_bqs > tbl_height_bqs) { - IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); - return -EINVAL; - } - - /* Origin of the internal frame on the shading table. */ - internal_org_x_bqs_on_tbl = adjust_left - left; - internal_org_y_bqs_on_tbl = adjust_upper - upper; - - /* Origin of the real sensor data area on the shading table. */ - sensor_org_x_bqs_on_tbl = internal_org_x_bqs_on_tbl + sensor_org_x_bqs_on_internal; - sensor_org_y_bqs_on_tbl = internal_org_y_bqs_on_tbl + sensor_org_y_bqs_on_internal; - - /* The shading information necessary as API is stored in the shading_info. */ - shading_info->info.type_1.num_hor_grids = num_hor_grids; - shading_info->info.type_1.num_ver_grids = num_ver_grids; - shading_info->info.type_1.bqs_per_grid_cell = bqs_per_grid_cell; - - shading_info->info.type_1.bayer_scale_hor_ratio_in = scr.bayer_scale_hor_ratio_in; - shading_info->info.type_1.bayer_scale_hor_ratio_out = scr.bayer_scale_hor_ratio_out; - shading_info->info.type_1.bayer_scale_ver_ratio_in = scr.bayer_scale_ver_ratio_in; - shading_info->info.type_1.bayer_scale_ver_ratio_out = scr.bayer_scale_ver_ratio_out; - - shading_info->info.type_1.isp_input_sensor_data_res_bqs.width = in_width_bqs; - shading_info->info.type_1.isp_input_sensor_data_res_bqs.height = in_height_bqs; - - shading_info->info.type_1.sensor_data_res_bqs.width = sensor_width_bqs; - shading_info->info.type_1.sensor_data_res_bqs.height = sensor_height_bqs; - - shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.x = (int32_t)sensor_org_x_bqs_on_tbl; - shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.y = (int32_t)sensor_org_y_bqs_on_tbl; - - /* The shading information related to ISP (but, not necessary as API) is stored in the pipe_config. */ - pipe_config->internal_frame_origin_bqs_on_sctbl.x = (int32_t)internal_org_x_bqs_on_tbl; - pipe_config->internal_frame_origin_bqs_on_sctbl.y = (int32_t)internal_org_y_bqs_on_tbl; - - IA_CSS_LOG("shading_info: grids=%dx%d, cell=%d, scale=%d,%d,%d,%d, input=%dx%d, data=%dx%d, origin=(%d,%d)", - shading_info->info.type_1.num_hor_grids, - shading_info->info.type_1.num_ver_grids, - shading_info->info.type_1.bqs_per_grid_cell, - shading_info->info.type_1.bayer_scale_hor_ratio_in, - shading_info->info.type_1.bayer_scale_hor_ratio_out, - shading_info->info.type_1.bayer_scale_ver_ratio_in, - shading_info->info.type_1.bayer_scale_ver_ratio_out, - shading_info->info.type_1.isp_input_sensor_data_res_bqs.width, - shading_info->info.type_1.isp_input_sensor_data_res_bqs.height, - shading_info->info.type_1.sensor_data_res_bqs.width, - shading_info->info.type_1.sensor_data_res_bqs.height, - shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.x, - shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.y); - - IA_CSS_LOG("pipe_config: origin=(%d,%d)", - pipe_config->internal_frame_origin_bqs_on_sctbl.x, - pipe_config->internal_frame_origin_bqs_on_sctbl.y); - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; -} - int ia_css_binary_get_shading_info(const struct ia_css_binary *binary, /* [in] */ @@ -706,24 +324,13 @@ ia_css_binary_get_shading_info(const struct ia_css_binary *binary, /* [in] */ IA_CSS_ENTER_PRIVATE("binary=%p, type=%d, required_bds_factor=%d, stream_config=%p", binary, type, required_bds_factor, stream_config); - if (type != IA_CSS_SHADING_CORRECTION_TYPE_1) { - err = -ENOTSUPP; - - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } - - if (!IS_ISP2401) - err = isp2400_binary_get_shading_info_type_1(binary, - required_bds_factor, - stream_config, - shading_info); + if (type == IA_CSS_SHADING_CORRECTION_TYPE_1) + err = binary_get_shading_info_type_1(binary, + required_bds_factor, + stream_config, + shading_info); else - err = isp2401_binary_get_shading_info_type_1(binary, - required_bds_factor, - stream_config, - shading_info, - pipe_config); + err = -ENOTSUPP; IA_CSS_LEAVE_ERR_PRIVATE(err); return err; From 5c5a95385ad644b7d698718c2d8eae1f9fe9b678 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 18:32:09 +0000 Subject: [PATCH 151/397] media: atomisp: binary.c: drop logic incompatible with firmware As we're using this firmware for ISP2401: https://github.com/intel-aero/meta-intel-aero-base/blob/master/recipes-kernel/linux/linux-yocto/shisp_2401a0_v21.bin It makes no sense to try to select a non-existing binary inside the firmware. So, revert it to reflect the Intel Aero device driver. Signed-off-by: Mauro Carvalho Chehab --- .../atomisp/pci/runtime/binary/src/binary.c | 76 +++---------------- 1 file changed, 9 insertions(+), 67 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c index 5e435bec942b..406ed5fb4c6a 100644 --- a/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c +++ b/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c @@ -108,7 +108,6 @@ ia_css_binary_internal_res(const struct ia_css_frame_info *in_info, binary_dvs_env.height); } -/* ISP2400 */ /* Computation results of the origin coordinate of bayer on the shading table. */ struct sh_css_shading_table_bayer_origin_compute_results { u32 bayer_scale_hor_ratio_in; /* Horizontal ratio (in) of bayer scaling. */ @@ -119,23 +118,7 @@ struct sh_css_shading_table_bayer_origin_compute_results { u32 sc_bayer_origin_y_bqs_on_shading_table; /* Y coordinate (in bqs) of bayer origin on shading table. */ }; -/* ISP2401 */ -/* Requirements for the shading correction. */ -struct sh_css_binary_sc_requirements { - /* Bayer scaling factor, for the scaling which is applied before shading correction. */ - u32 bayer_scale_hor_ratio_in; /* Horizontal ratio (in) of scaling applied BEFORE shading correction. */ - u32 bayer_scale_hor_ratio_out; /* Horizontal ratio (out) of scaling applied BEFORE shading correction. */ - u32 bayer_scale_ver_ratio_in; /* Vertical ratio (in) of scaling applied BEFORE shading correction. */ - u32 bayer_scale_ver_ratio_out; /* Vertical ratio (out) of scaling applied BEFORE shading correction. */ - - /* ISP internal frame is composed of the real sensor data and the padding data. */ - u32 sensor_data_origin_x_bqs_on_internal; /* X origin (in bqs) of sensor data on internal frame - at shading correction. */ - u32 sensor_data_origin_y_bqs_on_internal; /* Y origin (in bqs) of sensor data on internal frame - at shading correction. */ -}; - -/* ISP2400: Get the requirements for the shading correction. */ +/* Get the requirements for the shading correction. */ static int ia_css_binary_compute_shading_table_bayer_origin( const struct ia_css_binary *binary, /* [in] */ @@ -568,15 +551,9 @@ binary_grid_deci_factor_log2(int width, int height) /* 3A/Shading decimation factor spcification (at August 2008) * ------------------------------------------------------------------ * [Image Width (BQ)] [Decimation Factor (BQ)] [Resulting grid cells] - #ifndef ISP2401 * 1280 ?c 32 40 ?c * 640 ?c 1279 16 40 ?c 80 * ?c 639 8 ?c 80 - #else - * from 1280 32 from 40 - * from 640 to 1279 16 from 40 to 80 - * to 639 8 to 80 - #endif * ------------------------------------------------------------------ */ /* Maximum and minimum decimation factor by the specification */ @@ -938,15 +915,9 @@ ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo, if (info->enable.sc) { - if (!IS_ISP2401) { - binary->sctbl_width_per_color = _ISP_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci); - binary->sctbl_aligned_width_per_color = SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR; - binary->sctbl_height = _ISP_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci); - } else { - binary->sctbl_width_per_color = _ISP2401_SCTBL_WIDTH_PER_COLOR(isp_internal_width, s3a_log_deci); - binary->sctbl_aligned_width_per_color = SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR; - binary->sctbl_height = _ISP2401_SCTBL_HEIGHT(isp_internal_height, s3a_log_deci); - } + binary->sctbl_width_per_color = _ISP_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci); + binary->sctbl_aligned_width_per_color = SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR; + binary->sctbl_height = _ISP_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci); } else { binary->sctbl_width_per_color = 0; @@ -980,11 +951,7 @@ static int __ia_css_binary_find(struct ia_css_binary_descr *descr, *req_vf_info; struct ia_css_binary_xinfo *xcandidate; -#ifndef ISP2401 bool need_ds, need_dz, need_dvs, need_xnr, need_dpc; -#else - bool need_ds, need_dz, need_dvs, need_xnr, need_dpc, need_tnr; -#endif bool striped; bool enable_yuv_ds; bool enable_high_speed; @@ -1012,33 +979,21 @@ static int __ia_css_binary_find(struct ia_css_binary_descr *descr, stream_format = descr->stream_format; req_in_info = descr->in_info; req_bds_out_info = descr->bds_out_info; - for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) - { + for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { req_out_info[i] = descr->out_info[i]; if (req_out_info[i] && (req_out_info[i]->res.width != 0)) req_bin_out_info = req_out_info[i]; } if (!req_bin_out_info) return -EINVAL; -#ifndef ISP2401 req_vf_info = descr->vf_info; -#else - - if ((descr->vf_info) && (descr->vf_info->res.width == 0)) - /* width==0 means that there is no vf pin (e.g. in SkyCam preview case) */ - req_vf_info = NULL; - else - req_vf_info = descr->vf_info; -#endif need_xnr = descr->enable_xnr; need_ds = descr->enable_fractional_ds; need_dz = false; need_dvs = false; need_dpc = descr->enable_dpc; -#ifdef ISP2401 - need_tnr = descr->enable_tnr; -#endif + enable_yuv_ds = descr->enable_yuv_ds; enable_high_speed = descr->enable_high_speed; enable_dvs_6axis = descr->enable_dvs_6axis; @@ -1053,8 +1008,7 @@ static int __ia_css_binary_find(struct ia_css_binary_descr *descr, internal_res.width = 0; internal_res.height = 0; - if (mode == IA_CSS_BINARY_MODE_VIDEO) - { + if (mode == IA_CSS_BINARY_MODE_VIDEO) { dvs_env = descr->dvs_env; need_dz = descr->enable_dz; /* Video is the only mode that has a nodz variant. */ @@ -1063,8 +1017,7 @@ static int __ia_css_binary_find(struct ia_css_binary_descr *descr, /* print a map of the binary file */ ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "BINARY INFO:\n"); - for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++) - { + for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++) { xcandidate = binary_infos[i]; if (xcandidate) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%d:\n", i); @@ -1079,8 +1032,7 @@ static int __ia_css_binary_find(struct ia_css_binary_descr *descr, /* printf("sh_css_binary_find: pipe version %d\n", isp_pipe_version); */ for (xcandidate = binary_infos[mode]; xcandidate; - xcandidate = xcandidate->next) - { + xcandidate = xcandidate->next) { struct ia_css_binary_info *candidate = &xcandidate->sp; /* printf("sh_css_binary_find: evaluating candidate: * %d\n",candidate->id); */ @@ -1338,16 +1290,6 @@ static int __ia_css_binary_find(struct ia_css_binary_descr *descr, continue; } -#ifdef ISP2401 - if (!candidate->enable.tnr && need_tnr) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_binary_find() [%d] continue: !%d && %d\n", - __LINE__, candidate->enable.tnr, - descr->enable_tnr); - continue; - } - -#endif /* reconfigure any variable properties of the binary */ err = ia_css_binary_fill_info(xcandidate, online, two_ppc, stream_format, req_in_info, From c37ed67335518948ec21c4bce811f6aa847301b0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 18:58:25 +0000 Subject: [PATCH 152/397] media: atomisp: pipe_binarydesc: drop logic incompatible with firmware As we're using this firmware for ISP2401: https://github.com/intel-aero/meta-intel-aero-base/blob/master/recipes-kernel/linux/linux-yocto/shisp_2401a0_v21.bin Revert some changes that are not compatible with it, making the code close to the Intel Aero one. Signed-off-by: Mauro Carvalho Chehab --- .../pci/camera/pipe/src/pipe_binarydesc.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c b/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c index d09cc486e33e..7dd0e4a53c8b 100644 --- a/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c +++ b/drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c @@ -601,16 +601,9 @@ void ia_css_pipe_get_primary_binarydesc( * since it has better performance. */ if (pipe_version == IA_CSS_PIPE_VERSION_2_6_1) prim_descr->striped = false; - else if (!IS_ISP2401) { + else prim_descr->striped = prim_descr->continuous && (!pipe->stream->stop_copy_preview || !pipe->stream->disable_cont_vf); - } else { - prim_descr->striped = prim_descr->continuous && !pipe->stream->disable_cont_vf; - - if ((pipe->config.default_capture_config.enable_xnr != 0) && - (pipe->extra_config.enable_dvs_6axis == true)) - prim_descr->enable_xnr = true; - } } IA_CSS_LEAVE_PRIVATE(""); } @@ -842,14 +835,7 @@ void ia_css_pipe_get_ldc_binarydesc( assert(out_info); IA_CSS_ENTER_PRIVATE(""); - if (!IS_ISP2401) { - *in_info = *out_info; - } else { - if (pipe->out_yuv_ds_input_info.res.width) - *in_info = pipe->out_yuv_ds_input_info; - else - *in_info = *out_info; - } + *in_info = *out_info; in_info->format = IA_CSS_FRAME_FORMAT_YUV420; in_info->raw_bit_depth = 0; From 72fb16a130aca80ff3b7cc520078785a23651f26 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 18:41:06 +0000 Subject: [PATCH 153/397] media: atomisp: frame.c: drop a now-unused function ia_css_frame_find_crop_resolution() is not used anymore. So, remove it. Signed-off-by: Mauro Carvalho Chehab --- .../runtime/frame/interface/ia_css_frame.h | 19 ----- .../atomisp/pci/runtime/frame/src/frame.c | 70 ------------------- 2 files changed, 89 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h index 51ec7073d860..c756a134efc3 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h +++ b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h @@ -141,23 +141,4 @@ bool ia_css_frame_is_same_type( int ia_css_dma_configure_from_info(struct dma_port_config *config, const struct ia_css_frame_info *info); -/* ISP2401 */ -/* @brief Finds the cropping resolution - * This function finds the maximum cropping resolution in an input image keeping - * the aspect ratio for the given output resolution.Calculates the coordinates - * for cropping from the center and returns the starting pixel location of the - * region in the input image. Also returns the dimension of the cropping - * resolution. - * - * @param - * @param[in] in_res Resolution of input image - * @param[in] out_res Resolution of output image - * @param[out] crop_res Crop resolution of input image - * @return Returns 0 or -EINVAL on error - */ -int -ia_css_frame_find_crop_resolution(const struct ia_css_resolution *in_res, - const struct ia_css_resolution *out_res, - struct ia_css_resolution *crop_res); - #endif /* __IA_CSS_FRAME_H__ */ diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c index e3242652f296..a3aae638b0bf 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c +++ b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c @@ -933,73 +933,3 @@ void ia_css_resolution_to_sp_resolution( to->width = (uint16_t)from->width; to->height = (uint16_t)from->height; } - -/* ISP2401 */ -int -ia_css_frame_find_crop_resolution(const struct ia_css_resolution *in_res, - const struct ia_css_resolution *out_res, - struct ia_css_resolution *crop_res) { - u32 wd_even_ceil, ht_even_ceil; - u32 in_ratio, out_ratio; - - if ((!in_res) || (!out_res) || (!crop_res)) - return -EINVAL; - - IA_CSS_ENTER_PRIVATE("in(%ux%u) -> out(%ux%u)", in_res->width, - in_res->height, out_res->width, out_res->height); - - if ((in_res->width == 0) - || (in_res->height == 0) - || (out_res->width == 0) - || (out_res->height == 0)) - return -EINVAL; - - if ((out_res->width > in_res->width) || - (out_res->height > in_res->height)) - return -EINVAL; - - /* If aspect ratio (width/height) of out_res is higher than the aspect - * ratio of the in_res, then we crop vertically, otherwise we crop - * horizontally. - */ - in_ratio = in_res->width * out_res->height; - out_ratio = out_res->width * in_res->height; - - if (in_ratio == out_ratio) - { - crop_res->width = in_res->width; - crop_res->height = in_res->height; - } else if (out_ratio > in_ratio) - { - crop_res->width = in_res->width; - crop_res->height = ROUND_DIV(out_res->height * crop_res->width, - out_res->width); - } else - { - crop_res->height = in_res->height; - crop_res->width = ROUND_DIV(out_res->width * crop_res->height, - out_res->height); - } - - /* Round new (cropped) width and height to an even number. - * binarydesc_calculate_bds_factor is such that we should consider as - * much of the input as possible. This is different only when we end up - * with an odd number in the last step. So, we take the next even number - * if it falls within the input, otherwise take the previous even no. - */ - wd_even_ceil = EVEN_CEIL(crop_res->width); - ht_even_ceil = EVEN_CEIL(crop_res->height); - if ((wd_even_ceil > in_res->width) || (ht_even_ceil > in_res->height)) - { - crop_res->width = EVEN_FLOOR(crop_res->width); - crop_res->height = EVEN_FLOOR(crop_res->height); - } else - { - crop_res->width = wd_even_ceil; - crop_res->height = ht_even_ceil; - } - - IA_CSS_LEAVE_PRIVATE("in(%ux%u) -> out(%ux%u)", crop_res->width, - crop_res->height, out_res->width, out_res->height); - return 0; -} From 3c82bf0295252f6dd9af864770b1cbc583dde14c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 14:55:04 +0000 Subject: [PATCH 154/397] media: atomisp: add YUVPP at __atomisp_get_pipe() logic Aligns it which the Intel Aero firmware. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 86dad9fe61bf..5a90cc31cd1a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -857,7 +857,8 @@ static struct atomisp_video_pipe *__atomisp_get_pipe( } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { /* For online video or SDV video pipe. */ if (css_pipe_id == IA_CSS_PIPE_ID_VIDEO || - css_pipe_id == IA_CSS_PIPE_ID_COPY) { + css_pipe_id == IA_CSS_PIPE_ID_COPY || + css_pipe_id == IA_CSS_PIPE_ID_YUVPP) { if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) return &asd->video_out_video_capture; return &asd->video_out_preview; @@ -865,7 +866,8 @@ static struct atomisp_video_pipe *__atomisp_get_pipe( } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { /* For online preview or ZSL preview pipe. */ if (css_pipe_id == IA_CSS_PIPE_ID_PREVIEW || - css_pipe_id == IA_CSS_PIPE_ID_COPY) + css_pipe_id == IA_CSS_PIPE_ID_COPY || + css_pipe_id == IA_CSS_PIPE_ID_YUVPP) return &asd->video_out_preview; } /* For capture pipe. */ From 999ed03518cb01aa9ef55c025db79567eec6268c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2021 17:44:26 +0000 Subject: [PATCH 155/397] media: atomisp: cleanup qbuf logic The logic there is meant to be used by newer firmwares. clean it up, in order to make compatible with the chosen firmware version. Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index b2d3b8349234..562789c75299 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1457,25 +1457,8 @@ done: pipe->capq.streaming && !asd->enable_raw_buffer_lock->val && asd->params.offline_parm.num_captures == 1) { - if (!IS_ISP2401) { asd->pending_capture_request++; dev_dbg(isp->dev, "Add one pending capture request.\n"); - } else { - if (asd->re_trigger_capture) { - ret = atomisp_css_offline_capture_configure(asd, - asd->params.offline_parm.num_captures, - asd->params.offline_parm.skip_frames, - asd->params.offline_parm.offset); - asd->re_trigger_capture = false; - dev_dbg(isp->dev, "%s Trigger capture again ret=%d\n", - __func__, ret); - - } else { - asd->pending_capture_request++; - asd->re_trigger_capture = false; - dev_dbg(isp->dev, "Add one pending capture request.\n"); - } - } } rt_mutex_unlock(&isp->mutex); @@ -1868,8 +1851,6 @@ static int atomisp_streamon(struct file *file, void *fh, /* Reset pending capture request count. */ asd->pending_capture_request = 0; - if (IS_ISP2401) - asd->re_trigger_capture = false; if ((atomisp_subdev_streaming_count(asd) > sensor_start_stream) && (!isp->inputs[asd->input_curr].camera_caps->multi_stream_ctrl)) { From 37365b050d63b11727ffa43c58845cf71dcd698f Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Fri, 22 Oct 2021 16:04:08 +0100 Subject: [PATCH 156/397] media: mtk-vcodec: enc: add vp8 profile ctrl In order for the encoder to work with gstreamer it needs to have the V4L2_CID_MPEG_VIDEO_VP8_PROFILE ctrl. This patch adds that ctrl with only profile 0 supported. Signed-off-by: Dafna Hirschfeld Acked-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index 7457451ebff0..7232dc053c64 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -104,6 +104,13 @@ static int vidioc_venc_s_ctrl(struct v4l2_ctrl *ctrl) p->gop_size = ctrl->val; ctx->param_change |= MTK_ENCODE_PARAM_GOP_SIZE; break; + case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: + /* + * FIXME - what vp8 profiles are actually supported? + * The ctrl is added (with only profile 0 supported) for now. + */ + mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_VP8_PROFILE val = %d", ctrl->val); + break; case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME"); p->force_intra = 1; @@ -1395,6 +1402,9 @@ int mtk_vcodec_enc_ctrls_setup(struct mtk_vcodec_ctx *ctx) v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL, h264_max_level, 0, V4L2_MPEG_VIDEO_H264_LEVEL_4_0); + v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_MPEG_VIDEO_VP8_PROFILE, + V4L2_MPEG_VIDEO_VP8_PROFILE_0, 0, V4L2_MPEG_VIDEO_VP8_PROFILE_0); + if (handler->error) { mtk_v4l2_err("Init control handler fail %d", From 10d0f56800b31320d06ada90e64d374862544841 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Fri, 22 Oct 2021 16:04:10 +0100 Subject: [PATCH 157/397] media: mtk-vcodec: remove unused func parameter The prarameter bs_size to function vpu_enc_encode is not used. Remove it. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c | 9 +++------ drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c | 3 +-- drivers/media/platform/mtk-vcodec/venc_vpu_if.c | 1 - drivers/media/platform/mtk-vcodec/venc_vpu_if.h | 1 - 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c index b6a4f2074fa5..bf03888a824f 100644 --- a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c +++ b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c @@ -367,8 +367,7 @@ static int h264_encode_sps(struct venc_h264_inst *inst, mtk_vcodec_debug_enter(inst); - ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS, NULL, - bs_buf, bs_size, NULL); + ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS, NULL, bs_buf, NULL); if (ret) return ret; @@ -394,8 +393,7 @@ static int h264_encode_pps(struct venc_h264_inst *inst, mtk_vcodec_debug_enter(inst); - ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS, NULL, - bs_buf, bs_size, NULL); + ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS, NULL, bs_buf, NULL); if (ret) return ret; @@ -451,8 +449,7 @@ static int h264_encode_frame(struct venc_h264_inst *inst, mtk_vcodec_debug(inst, "frm_count = %d,skip_frm_count =%d,frm_type=%d.\n", frame_info.frm_count, frame_info.skip_frm_count, frame_info.frm_type); - ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf, - bs_buf, bs_size, &frame_info); + ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf, bs_buf, &frame_info); if (ret) return ret; diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c index 8267a9c4fd25..6b66957d5192 100644 --- a/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c +++ b/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c @@ -302,8 +302,7 @@ static int vp8_enc_encode_frame(struct venc_vp8_inst *inst, mtk_vcodec_debug(inst, "->frm_cnt=%d", inst->frm_cnt); - ret = vpu_enc_encode(&inst->vpu_inst, 0, frm_buf, bs_buf, bs_size, - NULL); + ret = vpu_enc_encode(&inst->vpu_inst, 0, frm_buf, bs_buf, NULL); if (ret) return ret; diff --git a/drivers/media/platform/mtk-vcodec/venc_vpu_if.c b/drivers/media/platform/mtk-vcodec/venc_vpu_if.c index be6d8790a41e..e7899d8a3e4e 100644 --- a/drivers/media/platform/mtk-vcodec/venc_vpu_if.c +++ b/drivers/media/platform/mtk-vcodec/venc_vpu_if.c @@ -225,7 +225,6 @@ int vpu_enc_set_param(struct venc_vpu_inst *vpu, int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode, struct venc_frm_buf *frm_buf, struct mtk_vcodec_mem *bs_buf, - unsigned int *bs_size, struct venc_frame_info *frame_info) { const bool is_ext = MTK_ENC_CTX_IS_EXT(vpu->ctx); diff --git a/drivers/media/platform/mtk-vcodec/venc_vpu_if.h b/drivers/media/platform/mtk-vcodec/venc_vpu_if.h index f9be9cab7ff7..f83bc1b3f2bf 100644 --- a/drivers/media/platform/mtk-vcodec/venc_vpu_if.h +++ b/drivers/media/platform/mtk-vcodec/venc_vpu_if.h @@ -45,7 +45,6 @@ int vpu_enc_set_param(struct venc_vpu_inst *vpu, int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode, struct venc_frm_buf *frm_buf, struct mtk_vcodec_mem *bs_buf, - unsigned int *bs_size, struct venc_frame_info *frame_info); int vpu_enc_deinit(struct venc_vpu_inst *vpu); From 16394e998cbb050730536bdf7e89f5a70efbd974 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 25 Oct 2021 13:16:34 +0100 Subject: [PATCH 158/397] media: mceusb: fix control-message timeouts USB control-message timeouts are specified in milliseconds and should specifically not vary with CONFIG_HZ. Fixes: 66e89522aff7 ("V4L/DVB: IR: add mceusb IR receiver driver") Cc: stable@vger.kernel.org # 2.6.36 Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/mceusb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index d09bee82c04c..2dc810f5a73f 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -1430,7 +1430,7 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) */ ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, - data, USB_CTRL_MSG_SZ, HZ * 3); + data, USB_CTRL_MSG_SZ, 3000); dev_dbg(dev, "set address - ret = %d", ret); dev_dbg(dev, "set address - data[0] = %d, data[1] = %d", data[0], data[1]); @@ -1438,20 +1438,20 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) /* set feature: bit rate 38400 bps */ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, - 0xc04e, 0x0000, NULL, 0, HZ * 3); + 0xc04e, 0x0000, NULL, 0, 3000); dev_dbg(dev, "set feature - ret = %d", ret); /* bRequest 4: set char length to 8 bits */ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 4, USB_TYPE_VENDOR, - 0x0808, 0x0000, NULL, 0, HZ * 3); + 0x0808, 0x0000, NULL, 0, 3000); dev_dbg(dev, "set char length - retB = %d", ret); /* bRequest 2: set handshaking to use DTR/DSR */ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 2, USB_TYPE_VENDOR, - 0x0000, 0x0100, NULL, 0, HZ * 3); + 0x0000, 0x0100, NULL, 0, 3000); dev_dbg(dev, "set handshake - retC = %d", ret); /* device resume */ From 2adc965c8bfa224e11ecccf9c92fd458c4236428 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 25 Oct 2021 13:16:35 +0100 Subject: [PATCH 159/397] media: redrat3: fix control-message timeouts USB control-message timeouts are specified in milliseconds and should specifically not vary with CONFIG_HZ. Fixes: 2154be651b90 ("[media] redrat3: new rc-core IR transceiver device driver") Cc: stable@vger.kernel.org # 3.0 Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/redrat3.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index ac85464864b9..cb22316b3f00 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -404,7 +404,7 @@ static int redrat3_send_cmd(int cmd, struct redrat3_dev *rr3) udev = rr3->udev; res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), cmd, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x0000, 0x0000, data, sizeof(u8), HZ * 10); + 0x0000, 0x0000, data, sizeof(u8), 10000); if (res < 0) { dev_err(rr3->dev, "%s: Error sending rr3 cmd res %d, data %d", @@ -480,7 +480,7 @@ static u32 redrat3_get_timeout(struct redrat3_dev *rr3) pipe = usb_rcvctrlpipe(rr3->udev, 0); ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5); + RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, 5000); if (ret != len) dev_warn(rr3->dev, "Failed to read timeout from hardware\n"); else { @@ -510,7 +510,7 @@ static int redrat3_set_timeout(struct rc_dev *rc_dev, unsigned int timeoutus) ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), RR3_SET_IR_PARAM, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, RR3_IR_IO_SIG_TIMEOUT, 0, timeout, sizeof(*timeout), - HZ * 25); + 25000); dev_dbg(dev, "set ir parm timeout %d ret 0x%02x\n", be32_to_cpu(*timeout), ret); @@ -542,32 +542,32 @@ static void redrat3_reset(struct redrat3_dev *rr3) *val = 0x01; rc = usb_control_msg(udev, rxpipe, RR3_RESET, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - RR3_CPUCS_REG_ADDR, 0, val, len, HZ * 25); + RR3_CPUCS_REG_ADDR, 0, val, len, 25000); dev_dbg(dev, "reset returned 0x%02x\n", rc); *val = length_fuzz; rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - RR3_IR_IO_LENGTH_FUZZ, 0, val, len, HZ * 25); + RR3_IR_IO_LENGTH_FUZZ, 0, val, len, 25000); dev_dbg(dev, "set ir parm len fuzz %d rc 0x%02x\n", *val, rc); *val = (65536 - (minimum_pause * 2000)) / 256; rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - RR3_IR_IO_MIN_PAUSE, 0, val, len, HZ * 25); + RR3_IR_IO_MIN_PAUSE, 0, val, len, 25000); dev_dbg(dev, "set ir parm min pause %d rc 0x%02x\n", *val, rc); *val = periods_measure_carrier; rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - RR3_IR_IO_PERIODS_MF, 0, val, len, HZ * 25); + RR3_IR_IO_PERIODS_MF, 0, val, len, 25000); dev_dbg(dev, "set ir parm periods measure carrier %d rc 0x%02x", *val, rc); *val = RR3_DRIVER_MAXLENS; rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - RR3_IR_IO_MAX_LENGTHS, 0, val, len, HZ * 25); + RR3_IR_IO_MAX_LENGTHS, 0, val, len, 25000); dev_dbg(dev, "set ir parm max lens %d rc 0x%02x\n", *val, rc); kfree(val); @@ -585,7 +585,7 @@ static void redrat3_get_firmware_rev(struct redrat3_dev *rr3) rc = usb_control_msg(rr3->udev, usb_rcvctrlpipe(rr3->udev, 0), RR3_FW_VERSION, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0, 0, buffer, RR3_FW_VERSION_LEN, HZ * 5); + 0, 0, buffer, RR3_FW_VERSION_LEN, 5000); if (rc >= 0) dev_info(rr3->dev, "Firmware rev: %s", buffer); @@ -825,14 +825,14 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress); ret = usb_bulk_msg(rr3->udev, pipe, irdata, - sendbuf_len, &ret_len, 10 * HZ); + sendbuf_len, &ret_len, 10000); dev_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, ret); /* now tell the hardware to transmit what we sent it */ pipe = usb_rcvctrlpipe(rr3->udev, 0); ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0, 0, irdata, 2, HZ * 10); + 0, 0, irdata, 2, 10000); if (ret < 0) dev_err(dev, "Error: control msg send failed, rc %d\n", ret); From cd1798a387825cc4a51282f5a611ad05bb1ad75f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 25 Oct 2021 13:16:36 +0100 Subject: [PATCH 160/397] media: flexcop-usb: fix control-message timeouts USB control-message timeouts are specified in milliseconds and should specifically not vary with CONFIG_HZ. Note that the driver was multiplying some of the timeout values with HZ twice resulting in 3000-second timeouts with HZ=1000. Also note that two of the timeout defines are currently unused. Fixes: 2154be651b90 ("[media] redrat3: new rc-core IR transceiver device driver") Cc: stable@vger.kernel.org # 3.0 Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/b2c2/flexcop-usb.c | 10 +++++----- drivers/media/usb/b2c2/flexcop-usb.h | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index 5d38171b7638..bfeb92d93de3 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -87,7 +87,7 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, 0, fc_usb->data, sizeof(u32), - B2C2_WAIT_FOR_OPERATION_RDW * HZ); + B2C2_WAIT_FOR_OPERATION_RDW); if (ret != sizeof(u32)) { err("error while %s dword from %d (%d).", read ? "reading" : @@ -155,7 +155,7 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, wIndex, fc_usb->data, buflen, - nWaitTime * HZ); + nWaitTime); if (ret != buflen) ret = -EIO; @@ -248,13 +248,13 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, /* DKT 020208 - add this to support special case of DiSEqC */ case USB_FUNC_I2C_CHECKWRITE: pipe = B2C2_USB_CTRL_PIPE_OUT; - nWaitTime = 2; + nWaitTime = 2000; request_type |= USB_DIR_OUT; break; case USB_FUNC_I2C_READ: case USB_FUNC_I2C_REPEATREAD: pipe = B2C2_USB_CTRL_PIPE_IN; - nWaitTime = 2; + nWaitTime = 2000; request_type |= USB_DIR_IN; break; default: @@ -281,7 +281,7 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, wIndex, fc_usb->data, buflen, - nWaitTime * HZ); + nWaitTime); if (ret != buflen) ret = -EIO; diff --git a/drivers/media/usb/b2c2/flexcop-usb.h b/drivers/media/usb/b2c2/flexcop-usb.h index 2f230bf72252..c7cca1a5ee59 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.h +++ b/drivers/media/usb/b2c2/flexcop-usb.h @@ -91,13 +91,13 @@ typedef enum { UTILITY_SRAM_TESTVERIFY = 0x16, } flexcop_usb_utility_function_t; -#define B2C2_WAIT_FOR_OPERATION_RW (1*HZ) -#define B2C2_WAIT_FOR_OPERATION_RDW (3*HZ) -#define B2C2_WAIT_FOR_OPERATION_WDW (1*HZ) +#define B2C2_WAIT_FOR_OPERATION_RW 1000 +#define B2C2_WAIT_FOR_OPERATION_RDW 3000 +#define B2C2_WAIT_FOR_OPERATION_WDW 1000 -#define B2C2_WAIT_FOR_OPERATION_V8READ (3*HZ) -#define B2C2_WAIT_FOR_OPERATION_V8WRITE (3*HZ) -#define B2C2_WAIT_FOR_OPERATION_V8FLASH (3*HZ) +#define B2C2_WAIT_FOR_OPERATION_V8READ 3000 +#define B2C2_WAIT_FOR_OPERATION_V8WRITE 3000 +#define B2C2_WAIT_FOR_OPERATION_V8FLASH 3000 typedef enum { V8_MEMORY_PAGE_DVB_CI = 0x20, From 10729be03327f53258cb196362015ad5c6eabe02 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 25 Oct 2021 13:16:37 +0100 Subject: [PATCH 161/397] media: cpia2: fix control-message timeouts USB control-message timeouts are specified in milliseconds and should specifically not vary with CONFIG_HZ. Fixes: ab33d5071de7 ("V4L/DVB (3376): Add cpia2 camera support") Cc: stable@vger.kernel.org # 2.6.17 Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cpia2/cpia2_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c index 76aac06f9fb8..cba03b286473 100644 --- a/drivers/media/usb/cpia2/cpia2_usb.c +++ b/drivers/media/usb/cpia2/cpia2_usb.c @@ -550,7 +550,7 @@ static int write_packet(struct usb_device *udev, 0, /* index */ buf, /* buffer */ size, - HZ); + 1000); kfree(buf); return ret; @@ -582,7 +582,7 @@ static int read_packet(struct usb_device *udev, 0, /* index */ buf, /* buffer */ size, - HZ); + 1000); if (ret >= 0) memcpy(registers, buf, size); From d9b7e8df3aa9b8c10708aab60e72e79ac08237e4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 25 Oct 2021 13:16:38 +0100 Subject: [PATCH 162/397] media: em28xx: fix control-message timeouts USB control-message timeouts are specified in milliseconds and should specifically not vary with CONFIG_HZ. Fixes: a6c2ba283565 ("[PATCH] v4l: 716: support for em28xx board family") Cc: stable@vger.kernel.org # 2.6.16 Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index acc0bf7dbe2b..c837cc528a33 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -89,7 +89,7 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, mutex_lock(&dev->ctrl_urb_lock); ret = usb_control_msg(udev, pipe, req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, dev->urb_buf, len, HZ); + 0x0000, reg, dev->urb_buf, len, 1000); if (ret < 0) { em28xx_regdbg("(pipe 0x%08x): IN: %02x %02x %02x %02x %02x %02x %02x %02x failed with error %i\n", pipe, @@ -158,7 +158,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, memcpy(dev->urb_buf, buf, len); ret = usb_control_msg(udev, pipe, req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, dev->urb_buf, len, HZ); + 0x0000, reg, dev->urb_buf, len, 1000); mutex_unlock(&dev->ctrl_urb_lock); if (ret < 0) { From b82bf9b9dc305d7d3d93eab106d70dbf2171b43e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 25 Oct 2021 13:16:39 +0100 Subject: [PATCH 163/397] media: pvrusb2: fix control-message timeouts USB control-message timeouts are specified in milliseconds and should specifically not vary with CONFIG_HZ. Fixes: d855497edbfb ("V4L/DVB (4228a): pvrusb2 to kernel 2.6.18") Cc: stable@vger.kernel.org # 2.6.18 Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index d38dee1792e4..3915d551d59e 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -1467,7 +1467,7 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) for (address = 0; address < fwsize; address += 0x800) { memcpy(fw_ptr, fw_entry->data + address, 0x800); ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address, - 0, fw_ptr, 0x800, HZ); + 0, fw_ptr, 0x800, 1000); } trace_firmware("Upload done, releasing device's CPU"); @@ -1605,7 +1605,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]); ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt, - &actual_length, HZ); + &actual_length, 1000); ret |= (actual_length != bcnt); if (ret) break; fw_done += bcnt; @@ -3438,7 +3438,7 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, 0xa0,0xc0, address,0, hdw->fw_buffer+address, - 0x800,HZ); + 0x800,1000); if (ret < 0) break; } @@ -3977,7 +3977,7 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val) /* Write the CPUCS register on the 8051. The lsb of the register is the reset bit; a 1 asserts reset while a 0 clears it. */ pipe = usb_sndctrlpipe(hdw->usb_dev, 0); - ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ); + ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,1000); if (ret < 0) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "cpureset_assert(%d) error=%d",val,ret); From f71d272ad4e354097020a4e6b1dc6e4b59feb50f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 25 Oct 2021 13:16:40 +0100 Subject: [PATCH 164/397] media: s2255: fix control-message timeouts USB control-message timeouts are specified in milliseconds and should specifically not vary with CONFIG_HZ. Use the common control-message timeout define for the five-second timeouts. Fixes: 38f993ad8b1f ("V4L/DVB (8125): This driver adds support for the Sensoray 2255 devices.") Cc: stable@vger.kernel.org # 2.6.27 Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/s2255/s2255drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index 3b0e4ed75d99..acf18e2251a5 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -1882,7 +1882,7 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, Value, Index, buf, - TransferBufferLength, HZ * 5); + TransferBufferLength, USB_CTRL_SET_TIMEOUT); if (r >= 0) memcpy(TransferBuffer, buf, TransferBufferLength); @@ -1891,7 +1891,7 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request, r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE, Value, Index, buf, - TransferBufferLength, HZ * 5); + TransferBufferLength, USB_CTRL_SET_TIMEOUT); } kfree(buf); return r; From 6aa6e70cdb5b863a57bad61310bf89b6617a5d2d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 25 Oct 2021 13:16:41 +0100 Subject: [PATCH 165/397] media: stk1160: fix control-message timeouts USB control-message timeouts are specified in milliseconds and should specifically not vary with CONFIG_HZ. Fixes: 9cb2173e6ea8 ("[media] media: Add stk1160 new driver (easycap replacement)") Cc: stable@vger.kernel.org # 3.7 Signed-off-by: Johan Hovold Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/stk1160/stk1160-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c index b4f8bc5db138..4e1698f78818 100644 --- a/drivers/media/usb/stk1160/stk1160-core.c +++ b/drivers/media/usb/stk1160/stk1160-core.c @@ -65,7 +65,7 @@ int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value) return -ENOMEM; ret = usb_control_msg(dev->udev, pipe, 0x00, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x00, reg, buf, sizeof(u8), HZ); + 0x00, reg, buf, sizeof(u8), 1000); if (ret < 0) { stk1160_err("read failed on reg 0x%x (%d)\n", reg, ret); @@ -85,7 +85,7 @@ int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value) ret = usb_control_msg(dev->udev, pipe, 0x01, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, reg, NULL, 0, HZ); + value, reg, NULL, 0, 1000); if (ret < 0) { stk1160_err("write failed on reg 0x%x (%d)\n", reg, ret); From 0bbaec386cc1f410f4deb8e0ec310096ec1fdef1 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Thu, 4 Nov 2021 11:41:53 +0000 Subject: [PATCH 166/397] media: imx: Remove unused functions Neither imx_media_mbus_fmt_to_ipu_image nor imx_media_ipu_image_to_mbus_fmt were used anywhere. Signed-off-by: Dorota Czaplejewicz Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-utils.c | 42 --------------------- drivers/staging/media/imx/imx-media.h | 4 -- 2 files changed, 46 deletions(-) diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 6f90acf9c725..94bc866ca28c 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -569,48 +569,6 @@ int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix, } EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_pix_fmt); -int imx_media_mbus_fmt_to_ipu_image(struct ipu_image *image, - const struct v4l2_mbus_framefmt *mbus) -{ - int ret; - - memset(image, 0, sizeof(*image)); - - ret = imx_media_mbus_fmt_to_pix_fmt(&image->pix, mbus, NULL); - if (ret) - return ret; - - image->rect.width = mbus->width; - image->rect.height = mbus->height; - - return 0; -} -EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_ipu_image); - -int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus, - const struct ipu_image *image) -{ - const struct imx_media_pixfmt *fmt; - - fmt = imx_media_find_pixel_format(image->pix.pixelformat, - PIXFMT_SEL_ANY); - if (!fmt || !fmt->codes || !fmt->codes[0]) - return -EINVAL; - - memset(mbus, 0, sizeof(*mbus)); - mbus->width = image->pix.width; - mbus->height = image->pix.height; - mbus->code = fmt->codes[0]; - mbus->field = image->pix.field; - mbus->colorspace = image->pix.colorspace; - mbus->xfer_func = image->pix.xfer_func; - mbus->ycbcr_enc = image->pix.ycbcr_enc; - mbus->quantization = image->pix.quantization; - - return 0; -} -EXPORT_SYMBOL_GPL(imx_media_ipu_image_to_mbus_fmt); - void imx_media_free_dma_buf(struct device *dev, struct imx_media_dma_buf *buf) { diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index 6740e7917458..f263fc3adbb9 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -199,10 +199,6 @@ void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt, int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix, const struct v4l2_mbus_framefmt *mbus, const struct imx_media_pixfmt *cc); -int imx_media_mbus_fmt_to_ipu_image(struct ipu_image *image, - const struct v4l2_mbus_framefmt *mbus); -int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus, - const struct ipu_image *image); void imx_media_grp_id_to_sd_name(char *sd_name, int sz, u32 grp_id, int ipu_id); struct v4l2_subdev * From dca7cc1cbd998f6765ba331c89eec5ed205b48d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Mon, 8 Nov 2021 16:02:17 +0000 Subject: [PATCH 167/397] media: rcar-vin: Free buffers with error if hardware stop fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver already has logic to detect if it fails to stop properly and report this error to the user. The driver however did not report the unused buffers or buffers given to the hardware (if any) with an error, the buffers where instead returned to user-space in the active state. Build on the existing detection of the error condition and correctly return the buffers with an error if it triggers. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-dma.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 25ead9333d00..79bb9081853f 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -1371,6 +1371,16 @@ void rvin_stop_streaming(struct rvin_dev *vin) spin_unlock_irqrestore(&vin->qlock, flags); + /* If something went wrong, free buffers with an error. */ + if (!buffersFreed) { + return_unused_buffers(vin, VB2_BUF_STATE_ERROR); + for (i = 0; i < HW_BUFFER_NUM; i++) { + if (vin->buf_hw[i].buffer) + vb2_buffer_done(&vin->buf_hw[i].buffer->vb2_buf, + VB2_BUF_STATE_ERROR); + } + } + rvin_set_stream(vin, 0); /* disable interrupts */ From ea8587d9de22aa08e1449779c59687407f7de21e Mon Sep 17 00:00:00 2001 From: Martin Weber Date: Tue, 9 Nov 2021 11:43:09 +0000 Subject: [PATCH 168/397] media: coda: V4L2_PIX_FMT_GREY for coda960 JPEG Encoder support greyscale pix fmt input for coda9_jpeg_encoder. The hardware supports it, so allow V4L2 Mem2Mem JPEG Encoder use it as well. Tested on an i.MX6QP. [hverkuil: updated the Subject line as suggested by Philipp] Signed-off-by: Martin Weber Reviewed-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 0e312b0842d7..3cfd4368e9a9 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -43,7 +43,7 @@ #define CODA_NAME "coda" #define CODADX6_MAX_INSTANCES 4 -#define CODA_MAX_FORMATS 4 +#define CODA_MAX_FORMATS 5 #define CODA_ISRAM_SIZE (2048 * 2) @@ -247,6 +247,7 @@ static const struct coda_video_device coda9_jpeg_encoder = { V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_YVU420, V4L2_PIX_FMT_YUV422P, + V4L2_PIX_FMT_GREY, }, .dst_formats = { V4L2_PIX_FMT_JPEG, @@ -626,6 +627,11 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height * 2; break; + case V4L2_PIX_FMT_GREY: + /* keep 16 pixel alignment of 8-bit pixel data */ + f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; + break; case V4L2_PIX_FMT_JPEG: case V4L2_PIX_FMT_H264: case V4L2_PIX_FMT_MPEG4: From ab599eb11882f834951c436cc080c3455ba32b9b Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Fri, 15 Oct 2021 16:57:41 +0800 Subject: [PATCH 169/397] media: dmxdev: fix UAF when dvb_register_device() fails I got a use-after-free report: dvbdev: dvb_register_device: failed to create device dvb1.dvr0 (-12) ... ================================================================== BUG: KASAN: use-after-free in dvb_dmxdev_release+0xce/0x2f0 ... Call Trace: dump_stack_lvl+0x6c/0x8b print_address_description.constprop.0+0x48/0x70 kasan_report.cold+0x82/0xdb __asan_load4+0x6b/0x90 dvb_dmxdev_release+0xce/0x2f0 ... Allocated by task 7666: kasan_save_stack+0x23/0x50 __kasan_kmalloc+0x83/0xa0 kmem_cache_alloc_trace+0x22e/0x470 dvb_register_device+0x12f/0x980 dvb_dmxdev_init+0x1f3/0x230 ... Freed by task 7666: kasan_save_stack+0x23/0x50 kasan_set_track+0x20/0x30 kasan_set_free_info+0x24/0x40 __kasan_slab_free+0xf2/0x130 kfree+0xd1/0x5c0 dvb_register_device.cold+0x1ac/0x1fa dvb_dmxdev_init+0x1f3/0x230 ... When dvb_register_device() in dvb_dmxdev_init() fails, dvb_dmxdev_init() does not return a failure, and the memory pointed to by dvbdev or dvr_dvbdev is invalid at this point. If they are used subsequently, it will result in UFA or null-ptr-deref. If dvb_register_device() in dvb_dmxdev_init() fails, fix the bug by making dvb_dmxdev_init() return an error as well. Link: https://lore.kernel.org/linux-media/20211015085741.1203283-1-wanghai38@huawei.com Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Hulk Robot Signed-off-by: Wang Hai Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dmxdev.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 5d5a48475a54..01f288fa37e0 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -1413,7 +1413,7 @@ static const struct dvb_device dvbdev_dvr = { }; int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) { - int i; + int i, ret; if (dmxdev->demux->open(dmxdev->demux) < 0) return -EUSERS; @@ -1432,14 +1432,26 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) DMXDEV_STATE_FREE); } - dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, + ret = dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, DVB_DEVICE_DEMUX, dmxdev->filternum); - dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, + if (ret < 0) + goto err_register_dvbdev; + + ret = dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dmxdev, DVB_DEVICE_DVR, dmxdev->filternum); + if (ret < 0) + goto err_register_dvr_dvbdev; dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); return 0; + +err_register_dvr_dvbdev: + dvb_unregister_device(dmxdev->dvbdev); +err_register_dvbdev: + vfree(dmxdev->filter); + dmxdev->filter = NULL; + return ret; } EXPORT_SYMBOL(dvb_dmxdev_init); From 8d395ce6f04b4af8d2b7397e0fa2f849bd22c231 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Thu, 16 Sep 2021 03:00:18 +0100 Subject: [PATCH 170/397] media: dvb-core: Convert to SPDX identifier use SPDX-License-Identifier instead of a verbose license text and remove verbose license text. Link: https://lore.kernel.org/linux-media/20210916020018.8550-1-caihuoqing@baidu.com Signed-off-by: Cai Huoqing Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dmxdev.c | 12 +----------- drivers/media/dvb-core/dvb_demux.c | 12 +----------- drivers/media/dvb-core/dvb_vb2.c | 4 ---- drivers/media/dvb-core/dvbdev.c | 12 +----------- 4 files changed, 3 insertions(+), 37 deletions(-) diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 01f288fa37e0..f6ee678107d3 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -1,19 +1,9 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * dmxdev.c - DVB demultiplexer device * * Copyright (C) 2000 Ralph Metzler & Marcus Metzler * for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #define pr_fmt(fmt) "dmxdev: " fmt diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c index 5fde1d38b3e3..83cc32ad7e12 100644 --- a/drivers/media/dvb-core/dvb_demux.c +++ b/drivers/media/dvb-core/dvb_demux.c @@ -1,20 +1,10 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * dvb_demux.c - DVB kernel demux API * * Copyright (C) 2000-2001 Ralph Metzler * & Marcus Metzler * for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #define pr_fmt(fmt) "dvb_demux: " fmt diff --git a/drivers/media/dvb-core/dvb_vb2.c b/drivers/media/dvb-core/dvb_vb2.c index 959d110407a4..a1bd6d9c9223 100644 --- a/drivers/media/dvb-core/dvb_vb2.c +++ b/drivers/media/dvb-core/dvb_vb2.c @@ -5,10 +5,6 @@ * Copyright (C) 2015 Samsung Electronics * * Author: jh1009.sung@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. */ #include diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 795d9bfaba5c..675d877a67b2 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -1,20 +1,10 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * dvbdev.c * * Copyright (C) 2000 Ralph Metzler * & Marcus Metzler * for convergence integrated media GmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #define pr_fmt(fmt) "dvbdev: " fmt From b13203032e679674c7c518f52a7ec0801ca3a829 Mon Sep 17 00:00:00 2001 From: Zheyu Ma Date: Tue, 11 May 2021 10:00:03 +0100 Subject: [PATCH 171/397] media: b2c2: Add missing check in flexcop_pci_isr: A out-of-bounds bug can be triggered by an interrupt, the reason for this bug is the lack of checking of register values. In flexcop_pci_isr, the driver reads value from a register and uses it as a dma address. Finally, this address will be passed to the count parameter of find_next_packet. If this value is larger than the size of dma, the index of buffer will be out-of-bounds. Fix this by adding a check after reading the value of the register. The following KASAN report reveals it: BUG: KASAN: slab-out-of-bounds in find_next_packet drivers/media/dvb-core/dvb_demux.c:528 [inline] BUG: KASAN: slab-out-of-bounds in _dvb_dmx_swfilter drivers/media/dvb-core/dvb_demux.c:572 [inline] BUG: KASAN: slab-out-of-bounds in dvb_dmx_swfilter+0x3fa/0x420 drivers/media/dvb-core/dvb_demux.c:603 Read of size 1 at addr ffff8880608c00a0 by task swapper/2/0 CPU: 2 PID: 0 Comm: swapper/2 Not tainted 4.19.177-gdba4159c14ef #25 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xec/0x156 lib/dump_stack.c:118 print_address_description+0x78/0x290 mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report+0x25b/0x380 mm/kasan/report.c:412 __asan_report_load1_noabort+0x19/0x20 mm/kasan/report.c:430 find_next_packet drivers/media/dvb-core/dvb_demux.c:528 [inline] _dvb_dmx_swfilter drivers/media/dvb-core/dvb_demux.c:572 [inline] dvb_dmx_swfilter+0x3fa/0x420 drivers/media/dvb-core/dvb_demux.c:603 flexcop_pass_dmx_data+0x2e/0x40 drivers/media/common/b2c2/flexcop.c:167 flexcop_pci_isr+0x3d1/0x5d0 drivers/media/pci/b2c2/flexcop-pci.c:212 __handle_irq_event_percpu+0xfb/0x770 kernel/irq/handle.c:149 handle_irq_event_percpu+0x79/0x150 kernel/irq/handle.c:189 handle_irq_event+0xac/0x140 kernel/irq/handle.c:206 handle_fasteoi_irq+0x232/0x5c0 kernel/irq/chip.c:725 generic_handle_irq_desc include/linux/irqdesc.h:155 [inline] handle_irq+0x230/0x3a0 arch/x86/kernel/irq_64.c:87 do_IRQ+0xa7/0x1e0 arch/x86/kernel/irq.c:247 common_interrupt+0xf/0xf arch/x86/entry/entry_64.S:670 RIP: 0010:native_safe_halt+0x28/0x30 arch/x86/include/asm/irqflags.h:61 Code: 00 00 55 be 04 00 00 00 48 c7 c7 00 62 2f 8c 48 89 e5 e8 fb 31 e8 f8 8b 05 75 4f 8e 03 85 c0 7e 07 0f 00 2d 8a 61 66 00 fb f4 <5d> c3 90 90 90 90 90 90 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 RSP: 0018:ffff88806b71fcc8 EFLAGS: 00000246 ORIG_RAX: ffffffffffffffde RAX: 0000000000000000 RBX: ffffffff8bde44c8 RCX: ffffffff88a11285 RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffffffff8c2f6200 RBP: ffff88806b71fcc8 R08: fffffbfff185ec40 R09: fffffbfff185ec40 R10: 0000000000000001 R11: fffffbfff185ec40 R12: 0000000000000002 R13: ffffffff8be9d6e0 R14: 0000000000000000 R15: 0000000000000000 arch_safe_halt arch/x86/include/asm/paravirt.h:94 [inline] default_idle+0x6f/0x360 arch/x86/kernel/process.c:557 arch_cpu_idle+0xf/0x20 arch/x86/kernel/process.c:548 default_idle_call+0x3b/0x60 kernel/sched/idle.c:93 cpuidle_idle_call kernel/sched/idle.c:153 [inline] do_idle+0x2ab/0x3c0 kernel/sched/idle.c:263 cpu_startup_entry+0xcb/0xe0 kernel/sched/idle.c:369 start_secondary+0x3b8/0x4e0 arch/x86/kernel/smpboot.c:271 secondary_startup_64+0xa4/0xb0 arch/x86/kernel/head_64.S:243 Allocated by task 1: save_stack+0x43/0xd0 mm/kasan/kasan.c:448 set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:553 kasan_slab_alloc+0x11/0x20 mm/kasan/kasan.c:490 slab_post_alloc_hook mm/slab.h:445 [inline] slab_alloc_node mm/slub.c:2741 [inline] slab_alloc mm/slub.c:2749 [inline] kmem_cache_alloc+0xeb/0x280 mm/slub.c:2754 kmem_cache_zalloc include/linux/slab.h:699 [inline] __kernfs_new_node+0xe2/0x6f0 fs/kernfs/dir.c:633 kernfs_new_node+0x9a/0x120 fs/kernfs/dir.c:693 __kernfs_create_file+0x5f/0x340 fs/kernfs/file.c:992 sysfs_add_file_mode_ns+0x22a/0x4e0 fs/sysfs/file.c:306 create_files fs/sysfs/group.c:63 [inline] internal_create_group+0x34e/0xc30 fs/sysfs/group.c:147 sysfs_create_group fs/sysfs/group.c:173 [inline] sysfs_create_groups+0x9c/0x140 fs/sysfs/group.c:200 driver_add_groups+0x3e/0x50 drivers/base/driver.c:129 bus_add_driver+0x3a5/0x790 drivers/base/bus.c:684 driver_register+0x1cd/0x410 drivers/base/driver.c:170 __pci_register_driver+0x197/0x200 drivers/pci/pci-driver.c:1411 cx88_audio_pci_driver_init+0x23/0x25 drivers/media/pci/cx88/cx88-alsa.c: 1017 do_one_initcall+0xe0/0x610 init/main.c:884 do_initcall_level init/main.c:952 [inline] do_initcalls init/main.c:960 [inline] do_basic_setup init/main.c:978 [inline] kernel_init_freeable+0x4d0/0x592 init/main.c:1145 kernel_init+0x18/0x190 init/main.c:1062 ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:415 Freed by task 0: (stack is not available) The buggy address belongs to the object at ffff8880608c0000 which belongs to the cache kernfs_node_cache of size 160 The buggy address is located 0 bytes to the right of 160-byte region [ffff8880608c0000, ffff8880608c00a0) The buggy address belongs to the page: page:ffffea0001823000 count:1 mapcount:0 mapping:ffff88806bed1e00 index:0x0 compound_mapcount: 0 flags: 0x100000000008100(slab|head) raw: 0100000000008100 dead000000000100 dead000000000200 ffff88806bed1e00 raw: 0000000000000000 0000000000240024 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8880608bff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff8880608c0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >ffff8880608c0080: 00 00 00 00 fc fc fc fc fc fc fc fc 00 00 00 00 ^ ffff8880608c0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff8880608c0180: fc fc fc fc fc fc fc fc 00 00 00 00 00 00 00 00 ================================================================== Link: https://lore.kernel.org/linux-media/1620723603-30912-1-git-send-email-zheyuma97@gmail.com Reported-by: Zheyu Ma Signed-off-by: Zheyu Ma Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/b2c2/flexcop-pci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/pci/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c index 6a4c7cb0ad0f..486c8ec0fa60 100644 --- a/drivers/media/pci/b2c2/flexcop-pci.c +++ b/drivers/media/pci/b2c2/flexcop-pci.c @@ -185,6 +185,8 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id) dma_addr_t cur_addr = fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; + if (cur_pos > fc_pci->dma[0].size * 2) + goto error; deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ", jiffies_to_usecs(jiffies - fc_pci->last_irq), @@ -225,6 +227,7 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id) ret = IRQ_NONE; } +error: spin_unlock_irqrestore(&fc_pci->irq_lock, flags); return ret; } From 98a1ca29768aca6e06e93f2bc4439f01ba439ac4 Mon Sep 17 00:00:00 2001 From: Lukas Middendorf Date: Sun, 18 Apr 2021 01:12:03 +0100 Subject: [PATCH 172/397] media: media dvb_frontend: add suspend and resume callbacks to dvb_frontend_ops While dvb_tuner_ops already has dedicated suspend and resume callbacks, dvb_frontend_ops currently does not have them. Add those callbacks and use them for suspend and resume. If they are not set, the old behavior of calling sleep or init is used. This allows dvb_frontend drivers to handle resume differently from init, and suspend differently from sleep. No change is required for drivers not needing this functionality. Link: https://lore.kernel.org/linux-media/20210418001204.7453-2-kernel@tuxforce.de Cc: Lukas Middendorf , Antti Palosaari , Mauro Carvalho Chehab , Luis Chamberlain Signed-off-by: Lukas Middendorf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 8 ++++++-- include/media/dvb_frontend.h | 13 +++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 258637d762d6..8fc59f3cfb6c 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -2935,7 +2935,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe) else if (fe->ops.tuner_ops.sleep) ret = fe->ops.tuner_ops.sleep(fe); - if (fe->ops.sleep) + if (fe->ops.suspend) + ret = fe->ops.suspend(fe); + else if (fe->ops.sleep) ret = fe->ops.sleep(fe); return ret; @@ -2951,7 +2953,9 @@ int dvb_frontend_resume(struct dvb_frontend *fe) fe->id); fe->exit = DVB_FE_DEVICE_RESUME; - if (fe->ops.init) + if (fe->ops.resume) + ret = fe->ops.resume(fe); + else if (fe->ops.init) ret = fe->ops.init(fe); if (fe->ops.tuner_ops.resume) diff --git a/include/media/dvb_frontend.h b/include/media/dvb_frontend.h index 0d76fa4551b3..e7c44870f20d 100644 --- a/include/media/dvb_frontend.h +++ b/include/media/dvb_frontend.h @@ -364,6 +364,10 @@ struct dvb_frontend_internal_info { * allocated by the driver. * @init: callback function used to initialize the tuner device. * @sleep: callback function used to put the tuner to sleep. + * @suspend: callback function used to inform that the Kernel will + * suspend. + * @resume: callback function used to inform that the Kernel is + * resuming from suspend. * @write: callback function used by some demod legacy drivers to * allow other drivers to write data into their registers. * Should not be used on new drivers. @@ -443,6 +447,8 @@ struct dvb_frontend_ops { int (*init)(struct dvb_frontend* fe); int (*sleep)(struct dvb_frontend* fe); + int (*suspend)(struct dvb_frontend *fe); + int (*resume)(struct dvb_frontend *fe); int (*write)(struct dvb_frontend* fe, const u8 buf[], int len); @@ -755,7 +761,8 @@ void dvb_frontend_detach(struct dvb_frontend *fe); * &dvb_frontend_ops.tuner_ops.suspend\(\) is available, it calls it. Otherwise, * it will call &dvb_frontend_ops.tuner_ops.sleep\(\), if available. * - * It will also call &dvb_frontend_ops.sleep\(\) to put the demod to suspend. + * It will also call &dvb_frontend_ops.suspend\(\) to put the demod to suspend, + * if available. Otherwise it will call &dvb_frontend_ops.sleep\(\). * * The drivers should also call dvb_frontend_suspend\(\) as part of their * handler for the &device_driver.suspend\(\). @@ -769,7 +776,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe); * * This function resumes the usual operation of the tuner after resume. * - * In order to resume the frontend, it calls the demod &dvb_frontend_ops.init\(\). + * In order to resume the frontend, it calls the demod + * &dvb_frontend_ops.resume\(\) if available. Otherwise it calls demod + * &dvb_frontend_ops.init\(\). * * If &dvb_frontend_ops.tuner_ops.resume\(\) is available, It, it calls it. * Otherwise,t will call &dvb_frontend_ops.tuner_ops.init\(\), if available. From e59a9e50ec8c421818c10df6e619cec9cc9ed4e8 Mon Sep 17 00:00:00 2001 From: zhaoxiao Date: Wed, 17 Nov 2021 03:06:56 +0000 Subject: [PATCH 173/397] media: dib9000: Use min() instead of doing it manually Fix following coccicheck warning: drivers/media/dvb-frontends/dib9000.c:261:10-11: WARNING opportunity for min() drivers/media/dvb-frontends/dib9000.c:345:10-11: WARNING opportunity for min() Link: https://lore.kernel.org/linux-media/20211117030656.14984-1-zhaoxiao@uniontech.com Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, zhaoxiao Signed-off-by: zhaoxiao Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/dib9000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 04d92d614279..914ca820c174 100644 --- a/drivers/media/dvb-frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c @@ -258,7 +258,7 @@ static int dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 *b, u32 state->i2c_write_buffer[0] |= (1 << 4); do { - l = len < chunk_size ? len : chunk_size; + l = min(len, chunk_size); state->msg[1].len = l; state->msg[1].buf = b; ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0; @@ -342,7 +342,7 @@ static int dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * state->i2c_write_buffer[0] |= (1 << 4); do { - l = len < chunk_size ? len : chunk_size; + l = min(len, chunk_size); state->msg[0].len = l + 2; memcpy(&state->i2c_write_buffer[2], buf, l); From 32f4797d03b581aec1e20347e95bd36d6c2fd6cd Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 14 Oct 2021 16:32:53 +0100 Subject: [PATCH 174/397] media: dvb-frontends/stv0367: remove redundant variable ADCClk_Hz GIT_AUTHOR_NAME=Colin King GIT_AUTHOR_EMAIL=colin.king@canonical.com Variable ADCClk_Hz is being initialised with a variable that is never read and then re-assigned immediately afterwards. Clean up the code by removing it and just returning the return value from the call to stv0367cab_get_mclk Addresses-Coverity: ("Unused value") Link: https://lore.kernel.org/linux-media/20211014153253.63527-1-colin.king@canonical.com Cc: kernel-janitors@vger.kernel.org, linux-kernel@vger.kernel.org Signed-off-by: Colin Ian King Reviewed-by: Kieran Bingham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stv0367.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c index 6c2b05fae1c5..95e376f23506 100644 --- a/drivers/media/dvb-frontends/stv0367.c +++ b/drivers/media/dvb-frontends/stv0367.c @@ -1797,11 +1797,7 @@ static u32 stv0367cab_get_mclk(struct dvb_frontend *fe, u32 ExtClk_Hz) static u32 stv0367cab_get_adc_freq(struct dvb_frontend *fe, u32 ExtClk_Hz) { - u32 ADCClk_Hz = ExtClk_Hz; - - ADCClk_Hz = stv0367cab_get_mclk(fe, ExtClk_Hz); - - return ADCClk_Hz; + return stv0367cab_get_mclk(fe, ExtClk_Hz); } static enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state, From 40f45ab7a7edc76244cc67c3ae26df2e666088e2 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 14 Oct 2021 16:12:35 +0100 Subject: [PATCH 175/397] media: drivers: cx24113: remove redundant variable r Variable r is being assigned values but its value was never used, being overriden on its first usage. So, drop the initialization. Addresses-Coverity: ("Unused value") Link: https://lore.kernel.org/linux-media/20211014151235.62671-1-colin.king@canonical.com Cc: kernel-janitors@vger.kernel.org, linux-kernel@vger.kernel.org Signed-off-by: Colin Ian King Reviewed-by: Kieran Bingham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/cx24113.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/cx24113.c b/drivers/media/dvb-frontends/cx24113.c index 60a9f70275f7..dd55d314bf9a 100644 --- a/drivers/media/dvb-frontends/cx24113.c +++ b/drivers/media/dvb-frontends/cx24113.c @@ -378,7 +378,7 @@ static void cx24113_set_nfr(struct cx24113_state *state, u16 n, s32 f, u8 r) static int cx24113_set_frequency(struct cx24113_state *state, u32 frequency) { - u8 r = 1; /* or 2 */ + u8 r; u16 n = 6; s32 f = 0; From 4160420012b9b0a594793b6d644016ae4b8c9409 Mon Sep 17 00:00:00 2001 From: Scott K Logan Date: Sun, 3 Oct 2021 01:18:30 +0100 Subject: [PATCH 176/397] media: s5h1411.c: Fix a typo in the VSB SNR table This looks like a typo. By manipulating the antenna on a device while monitoring the reported SNR, I was able to see the unexpected jump. After applying this patch, the spike was no longer present. Link: https://lore.kernel.org/linux-media/20211003001805.735092-1-logans@cottsay.net Signed-off-by: Scott K Logan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/s5h1411.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c index c1334d7eb442..2563a72e98b7 100644 --- a/drivers/media/dvb-frontends/s5h1411.c +++ b/drivers/media/dvb-frontends/s5h1411.c @@ -150,7 +150,7 @@ static struct vsb_snr_tab { { 0x35b, 235, }, { 0x353, 230, }, { 0x349, 225, }, - { 0x340, 320, }, + { 0x340, 220, }, { 0x337, 215, }, { 0x327, 210, }, { 0x31b, 205, }, From f7b77ebe6d2f49c7747b2d619586d1aa33f9ea91 Mon Sep 17 00:00:00 2001 From: Michael Kuron Date: Sun, 26 Sep 2021 21:51:26 +0100 Subject: [PATCH 177/397] media: dib0700: fix undefined behavior in tuner shutdown This fixes a problem where closing the tuner would leave it in a state where it would not tune to any channel when reopened. This problem was discovered as part of https://github.com/hselasky/webcamd/issues/16. Since adap->id is 0 or 1, this bit-shift overflows, which is undefined behavior. The driver still worked in practice as the overflow would in most environments result in 0, which rendered the line a no-op. When running the driver as part of webcamd however, the overflow could lead to 0xff due to optimizations by the compiler, which would, in the end, improperly shut down the tuner. The bug is a regression introduced in the commit referenced below. The present patch causes identical behavior to before that commit for adap->id equal to 0 or 1. The driver does not contain support for dib0700 devices with more adapters, assuming such even exist. Tests have been performed with the Xbox One Digital TV Tuner on amd64. Not all dib0700 devices are expected to be affected by the regression; this code path is only taken by those with incorrect endpoint numbers. Link: https://lore.kernel.org/linux-media/1d2fc36d94ced6f67c7cc21dcc469d5e5bdd8201.1632689033.git.mchehab+huawei@kernel.org Cc: stable@vger.kernel.org Fixes: 7757ddda6f4f ("[media] DiB0700: add function to change I2C-speed") Signed-off-by: Michael Kuron Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dib0700_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 70219b3e8566..7ea8f68b0f45 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -618,8 +618,6 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint); if (onoff) st->channel_state |= 1 << (adap->id); - else - st->channel_state |= 1 << ~(adap->id); } else { if (onoff) st->channel_state |= 1 << (adap->fe_adap[0].stream.props.endpoint-2); From e08d8f0fadad540ecd134724a7d6b519823e4637 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 26 Sep 2021 21:51:27 +0100 Subject: [PATCH 178/397] media: dib0700: cleanup start/stop streaming logic Having two different paths to start/stop streaming, depending weather the USB endpoints are 0x82/0x83 or not makes it more prune to errors. Unify the logic. Link: https://lore.kernel.org/linux-media/065a6fff925a42153671fa5202c81882ca12c59c.1632689033.git.mchehab+huawei@kernel.org Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mauro Carvalho Chehab , Mauro Carvalho Chehab , Michael Kuron , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, pb@linuxtv.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dib0700_core.c | 26 +++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 7ea8f68b0f45..d7c5836b9271 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -583,7 +583,7 @@ out: int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct dib0700_state *st = adap->dev->priv; - int ret; + int ret, adapt_nr; if ((onoff != 0) && (st->fw_version >= 0x10201)) { /* for firmware later than 1.20.1, @@ -610,24 +610,26 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) st->buf[3] = 0x00; - deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); - st->channel_state &= ~0x3; + if ((adap->fe_adap[0].stream.props.endpoint != 2) - && (adap->fe_adap[0].stream.props.endpoint != 3)) { - deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint); - if (onoff) - st->channel_state |= 1 << (adap->id); + && (adap->fe_adap[0].stream.props.endpoint != 3)) { + deb_info("the endpoint number (%i) is not correct, use the adapter id instead\n", + adap->fe_adap[0].stream.props.endpoint); + adapt_nr = adap->id; } else { - if (onoff) - st->channel_state |= 1 << (adap->fe_adap[0].stream.props.endpoint-2); - else - st->channel_state |= 1 << (3-adap->fe_adap[0].stream.props.endpoint); + adapt_nr = adap->fe_adap[0].stream.props.endpoint - 2; } + if (onoff) + st->channel_state |= 1 << adapt_nr; + else + st->channel_state |= 1 << (1 - adapt_nr); + st->buf[2] |= st->channel_state; - deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); + deb_info("adapter %d, streaming %s: %*ph\n", + adapt_nr, onoff ? "ON" : "OFF", 3, st->buf); ret = dib0700_ctrl_wr(adap->dev, st->buf, 4); mutex_unlock(&adap->dev->usb_mutex); From c50fdd1546ea1f3e085a955ab553008e8eb4d6a3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 26 Sep 2021 21:51:28 +0100 Subject: [PATCH 179/397] media: dib0700: Only touch one bit when start/stop an adapter Only touch the right bit to enable/disable an adapter channel, without touching the other adapter's one. Tested on Nova-TD. Link: https://lore.kernel.org/linux-media/4214942f248baddec9cfd2b4b2424993ac356a51.1632689033.git.mchehab+huawei@kernel.org Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mauro Carvalho Chehab , Mauro Carvalho Chehab , Michael Kuron , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, pb@linuxtv.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dib0700_core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index d7c5836b9271..1caabb51ea47 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -610,8 +610,6 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) st->buf[3] = 0x00; - st->channel_state &= ~0x3; - if ((adap->fe_adap[0].stream.props.endpoint != 2) && (adap->fe_adap[0].stream.props.endpoint != 3)) { deb_info("the endpoint number (%i) is not correct, use the adapter id instead\n", @@ -624,7 +622,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) if (onoff) st->channel_state |= 1 << adapt_nr; else - st->channel_state |= 1 << (1 - adapt_nr); + st->channel_state &= ~(1 << adapt_nr); st->buf[2] |= st->channel_state; From 40ae6eff068e32d727ad518a02574598c458a0c7 Mon Sep 17 00:00:00 2001 From: Lukas Middendorf Date: Sun, 18 Apr 2021 17:15:44 +0100 Subject: [PATCH 180/397] media: si2168: drop support for old firmware file name for si2168 B40 The si2168 B40 firmware file name has been changed in or before 2014. During initialization, the new file name is preferred, but the old file name is used as a fallback when request_firmware with the new file name fails. Once reading the old file name has been attempted, only this name will be used on further firmware loading attempts. During resume, firmware reading with the new file name can (and likely will) fail even when it actually exists. So this permanent switch to the fallback firmware name happens even when not desired. Any system using a recent kernel version can be expected to have the firmware under the new name. The major distributions are either using the dvb firmware collection from LibreELEC, which has the new firmware file name, or do not package the firmware file but have documentation pointing towards a manual installation of the firmware file under the new name. If the firmware is available under the old name, it is severely outdated. If the switch to the old file name is performed, further firmware loading will either permanently fail (if it is not available) or an outdated firmware version will be used. Drop support for the fallback firmware file name and fail directly if the firmware is not available under its current name. On following attempts, the firmware read will then be retried with the correct current name instead of the old name. As reasoned above, there should be no negative effects of this change, while simplifying code (the B40 variant will be handled identical compared to the other variants of the si2168) and at the same time fixing possible problems if firmware loading fails on resume. Link: https://lore.kernel.org/linux-media/20210418161544.58858-1-kernel@tuxforce.de Signed-off-by: Lukas Middendorf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 21 ++++----------------- drivers/media/dvb-frontends/si2168_priv.h | 1 - 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 14b93a7d3358..7fae5b1b8adf 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -448,23 +448,10 @@ static int si2168_init(struct dvb_frontend *fe) /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, dev->firmware_name, &client->dev); if (ret) { - /* fallback mechanism to handle old name for Si2168 B40 fw */ - if (dev->chip_id == SI2168_CHIP_ID_B40) { - dev->firmware_name = SI2168_B40_FIRMWARE_FALLBACK; - ret = request_firmware(&fw, dev->firmware_name, - &client->dev); - } - - if (ret == 0) { - dev_notice(&client->dev, - "please install firmware file '%s'\n", - SI2168_B40_FIRMWARE); - } else { - dev_err(&client->dev, - "firmware file '%s' not found\n", - dev->firmware_name); - goto err_release_firmware; - } + dev_err(&client->dev, + "firmware file '%s' not found\n", + dev->firmware_name); + goto err_release_firmware; } dev_info(&client->dev, "downloading firmware from file '%s'\n", diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h index 18bea5222082..4f4d122e3963 100644 --- a/drivers/media/dvb-frontends/si2168_priv.h +++ b/drivers/media/dvb-frontends/si2168_priv.h @@ -18,7 +18,6 @@ #define SI2168_A30_FIRMWARE "dvb-demod-si2168-a30-01.fw" #define SI2168_B40_FIRMWARE "dvb-demod-si2168-b40-01.fw" #define SI2168_D60_FIRMWARE "dvb-demod-si2168-d60-01.fw" -#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw" /* state struct */ struct si2168_dev { From 51c2664ab051908dfb467b922e017a792c489cec Mon Sep 17 00:00:00 2001 From: Lukas Middendorf Date: Sun, 18 Apr 2021 01:12:04 +0100 Subject: [PATCH 181/397] media: media si2168: fully initialize si2168 on resume only when necessary At connection time (or boot) in si2168_probe(), the firmware is not loaded to the device and the device is not fully activated. It is not useful or sensible to do this full initialization on resume in case it has not been previously initialized and is expected to be in this initialized state. Calling si2168_init() and therefore reading the firmware file for the first time during resume leads to problems and should be avoided. It is however safe to read the firmware file once it has already been read outside of a suspend/resume situation. Add a staus flag 'initialized' to store whether si2168_init() has successfully been called. If initialization fails (e.g. due to missing firmware file), the flag is not set. Register a separate si2168_resume callback which only calls si2168_init() once the 'initialized' flag has been set and it is safe to load the firmware at resume. The first call to si2168_init() will now always happen when the device is actually used for the first time and never during resume. This avoids the unsafe firmware file reading and should also speed up resume by skipping unnecessary device initialization. Link: https://lore.kernel.org/linux-media/20210418001204.7453-3-kernel@tuxforce.de [mchehab: fix several Coding Style issues] Cc: Antti Palosaari Signed-off-by: Lukas Middendorf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 22 ++++++++++++++++++++++ drivers/media/dvb-frontends/si2168_priv.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 7fae5b1b8adf..8a3c41a80c03 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -514,6 +514,7 @@ static int si2168_init(struct dvb_frontend *fe) goto err; dev->warm = true; + dev->initialized = true; warm: /* Init stats here to indicate which stats are supported */ c->cnr.len = 1; @@ -535,6 +536,26 @@ err: return ret; } +static int si2168_resume(struct dvb_frontend *fe) +{ + struct i2c_client *client = fe->demodulator_priv; + struct si2168_dev *dev = i2c_get_clientdata(client); + + /* + * check whether si2168_init() has been called successfully + * outside of a resume cycle. Only call it (and load firmware) + * in this case. si2168_init() is only called during resume + * once the device has actually been used. Otherwise, leave the + * device untouched. + */ + if (dev->initialized) { + dev_dbg(&client->dev, "previsously initialized, call si2168_init()\n"); + return si2168_init(fe); + } + dev_dbg(&client->dev, "not initialized yet, skipping init on resume\n"); + return 0; +} + static int si2168_sleep(struct dvb_frontend *fe) { struct i2c_client *client = fe->demodulator_priv; @@ -644,6 +665,7 @@ static const struct dvb_frontend_ops si2168_ops = { .init = si2168_init, .sleep = si2168_sleep, + .resume = si2168_resume, .set_frontend = si2168_set_frontend, diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h index 4f4d122e3963..3a8976229a4a 100644 --- a/drivers/media/dvb-frontends/si2168_priv.h +++ b/drivers/media/dvb-frontends/si2168_priv.h @@ -36,6 +36,7 @@ struct si2168_dev { u8 ts_mode; unsigned int active:1; unsigned int warm:1; + unsigned int initialized:1; unsigned int ts_clock_inv:1; unsigned int ts_clock_gapped:1; unsigned int spectral_inversion:1; From e594cda5f8c8e34ac6444166418690c65bbda47f Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Sat, 17 Apr 2021 00:53:36 +0100 Subject: [PATCH 182/397] media: sp887x: drop unneeded assignment The pointer 'mem' was initialized to 'fw->data' but immediately after that it was assigned 'fw->data + 10'. Lets remove the extra assignement and initialize the pointer to the address its going to use. Link: https://lore.kernel.org/linux-media/20210416235336.1552102-1-sudipm.mukherjee@gmail.com Cc: Sudip Mukherjee Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/sp887x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/dvb-frontends/sp887x.c b/drivers/media/dvb-frontends/sp887x.c index c89a91a3daf4..146e7f2dd3c5 100644 --- a/drivers/media/dvb-frontends/sp887x.c +++ b/drivers/media/dvb-frontends/sp887x.c @@ -140,7 +140,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware u8 buf [BLOCKSIZE + 2]; int i; int fw_size = fw->size; - const unsigned char *mem = fw->data; + const unsigned char *mem = fw->data + 10; dprintk("%s\n", __func__); @@ -148,8 +148,6 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware if (fw_size < FW_SIZE + 10) return -ENODEV; - mem = fw->data + 10; - /* soft reset */ sp887x_writereg(state, 0xf1a, 0x000); From 9393761aec4c56b7f2f19d21f806d316731401c1 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 16 Nov 2021 14:38:31 +0000 Subject: [PATCH 183/397] media: hantro: postproc: Fix motion vector space size When the post-processor hardware block is enabled, the driver allocates an internal queue of buffers for the decoder enginer, and uses the vb2 queue for the post-processor engine. For instance, on a G1 core, the decoder engine produces NV12 buffers and the post-processor engine can produce YUY2 buffers. The decoder engine expects motion vectors to be appended to the NV12 buffers, but this is only required for CODECs that need motion vectors, such as H.264. Fix the post-processor logic accordingly. Signed-off-by: Ezequiel Garcia Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_postproc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c index ed8916c950a4..07842152003f 100644 --- a/drivers/staging/media/hantro/hantro_postproc.c +++ b/drivers/staging/media/hantro/hantro_postproc.c @@ -132,9 +132,10 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) unsigned int num_buffers = cap_queue->num_buffers; unsigned int i, buf_size; - buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage + - hantro_h264_mv_size(ctx->dst_fmt.width, - ctx->dst_fmt.height); + buf_size = ctx->dst_fmt.plane_fmt[0].sizeimage; + if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_H264_SLICE) + buf_size += hantro_h264_mv_size(ctx->dst_fmt.width, + ctx->dst_fmt.height); for (i = 0; i < num_buffers; ++i) { struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; From 04dad52ee341c738adfd929d5f2b906001a2aeda Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 16 Nov 2021 14:38:32 +0000 Subject: [PATCH 184/397] media: hantro: postproc: Introduce struct hantro_postproc_ops Turns out the post-processor block on the G2 core is substantially different from the one on the G1 core. Introduce hantro_postproc_ops with .enable and .disable methods, which will allow to support the G2 post-processor cleanly. Signed-off-by: Ezequiel Garcia Signed-off-by: Andrzej Pietrasiewicz Reviewed-by: Benjamin Gaignard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro.h | 5 +-- drivers/staging/media/hantro/hantro_hw.h | 13 ++++++- .../staging/media/hantro/hantro_postproc.c | 35 +++++++++++++------ drivers/staging/media/hantro/imx8m_vpu_hw.c | 2 +- .../staging/media/hantro/rockchip_vpu_hw.c | 6 ++-- .../staging/media/hantro/sama5d4_vdec_hw.c | 2 +- 6 files changed, 45 insertions(+), 18 deletions(-) diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index c2e2dca38628..c2e01959dc00 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -28,6 +28,7 @@ struct hantro_ctx; struct hantro_codec_ops; +struct hantro_postproc_ops; #define HANTRO_JPEG_ENCODER BIT(0) #define HANTRO_ENCODERS 0x0000ffff @@ -59,6 +60,7 @@ struct hantro_irq { * @num_dec_fmts: Number of decoder formats. * @postproc_fmts: Post-processor formats. * @num_postproc_fmts: Number of post-processor formats. + * @postproc_ops: Post-processor ops. * @codec: Supported codecs * @codec_ops: Codec ops. * @init: Initialize hardware, optional. @@ -69,7 +71,6 @@ struct hantro_irq { * @num_clocks: number of clocks in the array * @reg_names: array of register range names * @num_regs: number of register range names in the array - * @postproc_regs: &struct hantro_postproc_regs pointer */ struct hantro_variant { unsigned int enc_offset; @@ -80,6 +81,7 @@ struct hantro_variant { unsigned int num_dec_fmts; const struct hantro_fmt *postproc_fmts; unsigned int num_postproc_fmts; + const struct hantro_postproc_ops *postproc_ops; unsigned int codec; const struct hantro_codec_ops *codec_ops; int (*init)(struct hantro_dev *vpu); @@ -90,7 +92,6 @@ struct hantro_variant { int num_clocks; const char * const *reg_names; int num_regs; - const struct hantro_postproc_regs *postproc_regs; }; /** diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 267a6d33a47b..2f85430682d8 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -174,6 +174,17 @@ struct hantro_postproc_ctx { struct hantro_aux_buf dec_q[VB2_MAX_FRAME]; }; +/** + * struct hantro_postproc_ops - post-processor operations + * + * @enable: Enable the post-processor block. Optional. + * @disable: Disable the post-processor block. Optional. + */ +struct hantro_postproc_ops { + void (*enable)(struct hantro_ctx *ctx); + void (*disable)(struct hantro_ctx *ctx); +}; + /** * struct hantro_codec_ops - codec mode specific operations * @@ -221,7 +232,7 @@ extern const struct hantro_variant rk3328_vpu_variant; extern const struct hantro_variant rk3399_vpu_variant; extern const struct hantro_variant sama5d4_vdec_variant; -extern const struct hantro_postproc_regs hantro_g1_postproc_regs; +extern const struct hantro_postproc_ops hantro_g1_postproc_ops; extern const u32 hantro_vp8_dec_mc_filter[8][6]; diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c index 07842152003f..882fb8bc5ddd 100644 --- a/drivers/staging/media/hantro/hantro_postproc.c +++ b/drivers/staging/media/hantro/hantro_postproc.c @@ -15,14 +15,14 @@ #define HANTRO_PP_REG_WRITE(vpu, reg_name, val) \ { \ hantro_reg_write(vpu, \ - &(vpu)->variant->postproc_regs->reg_name, \ + &hantro_g1_postproc_regs.reg_name, \ val); \ } #define HANTRO_PP_REG_WRITE_S(vpu, reg_name, val) \ { \ hantro_reg_write_s(vpu, \ - &(vpu)->variant->postproc_regs->reg_name, \ + &hantro_g1_postproc_regs.reg_name, \ val); \ } @@ -64,16 +64,13 @@ bool hantro_needs_postproc(const struct hantro_ctx *ctx, return fmt->fourcc != V4L2_PIX_FMT_NV12; } -void hantro_postproc_enable(struct hantro_ctx *ctx) +static void hantro_postproc_g1_enable(struct hantro_ctx *ctx) { struct hantro_dev *vpu = ctx->dev; struct vb2_v4l2_buffer *dst_buf; u32 src_pp_fmt, dst_pp_fmt; dma_addr_t dst_dma; - if (!vpu->variant->postproc_regs) - return; - /* Turn on pipeline mode. Must be done first. */ HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x1); @@ -154,12 +151,30 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) return 0; } +static void hantro_postproc_g1_disable(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + + HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x0); +} + void hantro_postproc_disable(struct hantro_ctx *ctx) { struct hantro_dev *vpu = ctx->dev; - if (!vpu->variant->postproc_regs) - return; - - HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x0); + if (vpu->variant->postproc_ops && vpu->variant->postproc_ops->disable) + vpu->variant->postproc_ops->disable(ctx); } + +void hantro_postproc_enable(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + + if (vpu->variant->postproc_ops && vpu->variant->postproc_ops->enable) + vpu->variant->postproc_ops->enable(ctx); +} + +const struct hantro_postproc_ops hantro_g1_postproc_ops = { + .enable = hantro_postproc_g1_enable, + .disable = hantro_postproc_g1_disable, +}; diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c index ea919bfb9891..22fa7d2f3b64 100644 --- a/drivers/staging/media/hantro/imx8m_vpu_hw.c +++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c @@ -262,7 +262,7 @@ const struct hantro_variant imx8mq_vpu_variant = { .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts), .postproc_fmts = imx8m_vpu_postproc_fmts, .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts), - .postproc_regs = &hantro_g1_postproc_regs, + .postproc_ops = &hantro_g1_postproc_ops, .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | HANTRO_H264_DECODER, .codec_ops = imx8mq_vpu_codec_ops, diff --git a/drivers/staging/media/hantro/rockchip_vpu_hw.c b/drivers/staging/media/hantro/rockchip_vpu_hw.c index d4f52957cc53..6c1ad5534ce5 100644 --- a/drivers/staging/media/hantro/rockchip_vpu_hw.c +++ b/drivers/staging/media/hantro/rockchip_vpu_hw.c @@ -460,7 +460,7 @@ const struct hantro_variant rk3036_vpu_variant = { .num_dec_fmts = ARRAY_SIZE(rk3066_vpu_dec_fmts), .postproc_fmts = rockchip_vpu1_postproc_fmts, .num_postproc_fmts = ARRAY_SIZE(rockchip_vpu1_postproc_fmts), - .postproc_regs = &hantro_g1_postproc_regs, + .postproc_ops = &hantro_g1_postproc_ops, .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | HANTRO_H264_DECODER, .codec_ops = rk3036_vpu_codec_ops, @@ -485,7 +485,7 @@ const struct hantro_variant rk3066_vpu_variant = { .num_dec_fmts = ARRAY_SIZE(rk3066_vpu_dec_fmts), .postproc_fmts = rockchip_vpu1_postproc_fmts, .num_postproc_fmts = ARRAY_SIZE(rockchip_vpu1_postproc_fmts), - .postproc_regs = &hantro_g1_postproc_regs, + .postproc_ops = &hantro_g1_postproc_ops, .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | HANTRO_H264_DECODER, .codec_ops = rk3066_vpu_codec_ops, @@ -505,7 +505,7 @@ const struct hantro_variant rk3288_vpu_variant = { .num_dec_fmts = ARRAY_SIZE(rk3288_vpu_dec_fmts), .postproc_fmts = rockchip_vpu1_postproc_fmts, .num_postproc_fmts = ARRAY_SIZE(rockchip_vpu1_postproc_fmts), - .postproc_regs = &hantro_g1_postproc_regs, + .postproc_ops = &hantro_g1_postproc_ops, .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | HANTRO_H264_DECODER, .codec_ops = rk3288_vpu_codec_ops, diff --git a/drivers/staging/media/hantro/sama5d4_vdec_hw.c b/drivers/staging/media/hantro/sama5d4_vdec_hw.c index 9c3b8cd0b239..f3fecc7248c4 100644 --- a/drivers/staging/media/hantro/sama5d4_vdec_hw.c +++ b/drivers/staging/media/hantro/sama5d4_vdec_hw.c @@ -100,7 +100,7 @@ const struct hantro_variant sama5d4_vdec_variant = { .num_dec_fmts = ARRAY_SIZE(sama5d4_vdec_fmts), .postproc_fmts = sama5d4_vdec_postproc_fmts, .num_postproc_fmts = ARRAY_SIZE(sama5d4_vdec_postproc_fmts), - .postproc_regs = &hantro_g1_postproc_regs, + .postproc_ops = &hantro_g1_postproc_ops, .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | HANTRO_H264_DECODER, .codec_ops = sama5d4_vdec_codec_ops, From 53a3e71095c572333ceea30762565dbedec951ca Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 16 Nov 2021 14:38:33 +0000 Subject: [PATCH 185/397] media: hantro: Simplify postprocessor Add a 'postprocessed' boolean property to struct hantro_fmt to signal that a format is produced by the post-processor. This will allow to introduce the G2 post-processor in a simple way. Signed-off-by: Ezequiel Garcia Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro.h | 2 ++ drivers/staging/media/hantro/hantro_postproc.c | 8 +------- drivers/staging/media/hantro/imx8m_vpu_hw.c | 1 + drivers/staging/media/hantro/rockchip_vpu_hw.c | 1 + drivers/staging/media/hantro/sama5d4_vdec_hw.c | 1 + 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index c2e01959dc00..dd5e56765d4e 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -263,6 +263,7 @@ struct hantro_ctx { * @max_depth: Maximum depth, for bitstream formats * @enc_fmt: Format identifier for encoder registers. * @frmsize: Supported range of frame sizes (only for bitstream formats). + * @postprocessed: Indicates if this format needs the post-processor. */ struct hantro_fmt { char *name; @@ -272,6 +273,7 @@ struct hantro_fmt { int max_depth; enum hantro_enc_fmt enc_fmt; struct v4l2_frmsize_stepwise frmsize; + bool postprocessed; }; struct hantro_reg { diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c index 882fb8bc5ddd..4549aec08feb 100644 --- a/drivers/staging/media/hantro/hantro_postproc.c +++ b/drivers/staging/media/hantro/hantro_postproc.c @@ -53,15 +53,9 @@ const struct hantro_postproc_regs hantro_g1_postproc_regs = { bool hantro_needs_postproc(const struct hantro_ctx *ctx, const struct hantro_fmt *fmt) { - struct hantro_dev *vpu = ctx->dev; - if (ctx->is_encoder) return false; - - if (!vpu->variant->postproc_fmts) - return false; - - return fmt->fourcc != V4L2_PIX_FMT_NV12; + return fmt->postprocessed; } static void hantro_postproc_g1_enable(struct hantro_ctx *ctx) diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c index 22fa7d2f3b64..02e61438220a 100644 --- a/drivers/staging/media/hantro/imx8m_vpu_hw.c +++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c @@ -82,6 +82,7 @@ static const struct hantro_fmt imx8m_vpu_postproc_fmts[] = { { .fourcc = V4L2_PIX_FMT_YUYV, .codec_mode = HANTRO_MODE_NONE, + .postprocessed = true, }, }; diff --git a/drivers/staging/media/hantro/rockchip_vpu_hw.c b/drivers/staging/media/hantro/rockchip_vpu_hw.c index 6c1ad5534ce5..f372f767d4ff 100644 --- a/drivers/staging/media/hantro/rockchip_vpu_hw.c +++ b/drivers/staging/media/hantro/rockchip_vpu_hw.c @@ -62,6 +62,7 @@ static const struct hantro_fmt rockchip_vpu1_postproc_fmts[] = { { .fourcc = V4L2_PIX_FMT_YUYV, .codec_mode = HANTRO_MODE_NONE, + .postprocessed = true, }, }; diff --git a/drivers/staging/media/hantro/sama5d4_vdec_hw.c b/drivers/staging/media/hantro/sama5d4_vdec_hw.c index f3fecc7248c4..b2fc1c5613e1 100644 --- a/drivers/staging/media/hantro/sama5d4_vdec_hw.c +++ b/drivers/staging/media/hantro/sama5d4_vdec_hw.c @@ -15,6 +15,7 @@ static const struct hantro_fmt sama5d4_vdec_postproc_fmts[] = { { .fourcc = V4L2_PIX_FMT_YUYV, .codec_mode = HANTRO_MODE_NONE, + .postprocessed = true, }, }; From bb91e46eb017876689757cc208c047c518b4189b Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 16 Nov 2021 14:38:34 +0000 Subject: [PATCH 186/397] media: hantro: Add quirk for NV12/NV12_4L4 capture format The G2 core decoder engine produces NV12_4L4 format, which is a simple NV12 4x4 tiled format. The driver currently hides this format by always enabling the post-processor engine, and therefore offering NV12 directly. This is done without using the logic in hantro_postproc.c and therefore makes it difficult to add VP9 cleanly. Since fixing this is not easy, add a small quirk to force NV12 if HEVC was configured, but otherwise declare NV12_4L4 as the pixel format in imx8mq_vpu_g2_variant.dec_fmts. This will be used by the VP9 decoder which will be added soon. Signed-off-by: Ezequiel Garcia Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_v4l2.c | 14 ++++++++++++++ drivers/staging/media/hantro/imx8m_vpu_hw.c | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c index bcb0bdff4a9a..d1f060c55fed 100644 --- a/drivers/staging/media/hantro/hantro_v4l2.c +++ b/drivers/staging/media/hantro/hantro_v4l2.c @@ -150,6 +150,20 @@ static int vidioc_enum_fmt(struct file *file, void *priv, unsigned int num_fmts, i, j = 0; bool skip_mode_none; + /* + * The HEVC decoder on the G2 core needs a little quirk to offer NV12 + * only on the capture side. Once the post-processor logic is used, + * we will be able to expose NV12_4L4 and NV12 as the other cases, + * and therefore remove this quirk. + */ + if (capture && ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE) { + if (f->index == 0) { + f->pixelformat = V4L2_PIX_FMT_NV12; + return 0; + } + return -EINVAL; + } + /* * When dealing with an encoder: * - on the capture side we want to filter out all MODE_NONE formats. diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c index 02e61438220a..a40b161e5956 100644 --- a/drivers/staging/media/hantro/imx8m_vpu_hw.c +++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c @@ -134,7 +134,7 @@ static const struct hantro_fmt imx8m_vpu_dec_fmts[] = { static const struct hantro_fmt imx8m_vpu_g2_dec_fmts[] = { { - .fourcc = V4L2_PIX_FMT_NV12, + .fourcc = V4L2_PIX_FMT_NV12_4L4, .codec_mode = HANTRO_MODE_NONE, }, { From b88dbe38dca82425a273d126785866af39ba0770 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 16 Nov 2021 14:38:35 +0000 Subject: [PATCH 187/397] media: uapi: Add VP9 stateless decoder controls Add the VP9 stateless decoder controls plus the documentation that goes with it. Signed-off-by: Boris Brezillon Co-developed-by: Ezequiel Garcia Signed-off-by: Ezequiel Garcia Signed-off-by: Adrian Ratiu Signed-off-by: Andrzej Pietrasiewicz Co-developed-by: Daniel Almeida Signed-off-by: Daniel Almeida Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../userspace-api/media/v4l/biblio.rst | 10 + .../media/v4l/ext-ctrls-codec-stateless.rst | 573 ++++++++++++++++++ .../media/v4l/pixfmt-compressed.rst | 15 + .../media/v4l/vidioc-g-ext-ctrls.rst | 8 + .../media/v4l/vidioc-queryctrl.rst | 12 + .../media/videodev2.h.rst.exceptions | 2 + drivers/media/v4l2-core/v4l2-ctrls-core.c | 180 ++++++ drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 + drivers/media/v4l2-core/v4l2-ioctl.c | 1 + include/media/v4l2-ctrls.h | 4 + include/uapi/linux/v4l2-controls.h | 284 +++++++++ include/uapi/linux/videodev2.h | 6 + 12 files changed, 1103 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/biblio.rst b/Documentation/userspace-api/media/v4l/biblio.rst index 7b8e6738ff9e..9cd18c153d19 100644 --- a/Documentation/userspace-api/media/v4l/biblio.rst +++ b/Documentation/userspace-api/media/v4l/biblio.rst @@ -417,3 +417,13 @@ VP8 :title: RFC 6386: "VP8 Data Format and Decoding Guide" :author: J. Bankoski et al. + +.. _vp9: + +VP9 +=== + + +:title: VP9 Bitstream & Decoding Process Specification + +:author: Adrian Grange (Google), Peter de Rivaz (Argon Design), Jonathan Hunt (Argon Design) diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst index 72f5e85b4f34..cc080c4257d0 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst @@ -1458,3 +1458,576 @@ FWHT Flags .. raw:: latex \normalsize + +.. _v4l2-codec-stateless-vp9: + +``V4L2_CID_STATELESS_VP9_COMPRESSED_HDR (struct)`` + Stores VP9 probabilities updates as parsed from the current compressed frame + header. A value of zero in an array element means no update of the relevant + probability. Motion vector-related updates contain a new value or zero. All + other updates contain values translated with inv_map_table[] (see 6.3.5 in + :ref:`vp9`). + +.. c:type:: v4l2_ctrl_vp9_compressed_hdr + +.. tabularcolumns:: |p{1cm}|p{4.8cm}|p{11.4cm}| + +.. cssclass:: longtable + +.. flat-table:: struct v4l2_ctrl_vp9_compressed_hdr + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``tx_mode`` + - Specifies the TX mode. See :ref:`TX Mode ` for more details. + * - __u8 + - ``tx8[2][1]`` + - TX 8x8 probabilities delta. + * - __u8 + - ``tx16[2][2]`` + - TX 16x16 probabilities delta. + * - __u8 + - ``tx32[2][3]`` + - TX 32x32 probabilities delta. + * - __u8 + - ``coef[4][2][2][6][6][3]`` + - Coefficient probabilities delta. + * - __u8 + - ``skip[3]`` + - Skip probabilities delta. + * - __u8 + - ``inter_mode[7][3]`` + - Inter prediction mode probabilities delta. + * - __u8 + - ``interp_filter[4][2]`` + - Interpolation filter probabilities delta. + * - __u8 + - ``is_inter[4]`` + - Is inter-block probabilities delta. + * - __u8 + - ``comp_mode[5]`` + - Compound prediction mode probabilities delta. + * - __u8 + - ``single_ref[5][2]`` + - Single reference probabilities delta. + * - __u8 + - ``comp_ref[5]`` + - Compound reference probabilities delta. + * - __u8 + - ``y_mode[4][9]`` + - Y prediction mode probabilities delta. + * - __u8 + - ``uv_mode[10][9]`` + - UV prediction mode probabilities delta. + * - __u8 + - ``partition[16][3]`` + - Partition probabilities delta. + * - __u8 + - ``mv.joint[3]`` + - Motion vector joint probabilities delta. + * - __u8 + - ``mv.sign[2]`` + - Motion vector sign probabilities delta. + * - __u8 + - ``mv.classes[2][10]`` + - Motion vector class probabilities delta. + * - __u8 + - ``mv.class0_bit[2]`` + - Motion vector class0 bit probabilities delta. + * - __u8 + - ``mv.bits[2][10]`` + - Motion vector bits probabilities delta. + * - __u8 + - ``mv.class0_fr[2][2][3]`` + - Motion vector class0 fractional bit probabilities delta. + * - __u8 + - ``mv.fr[2][3]`` + - Motion vector fractional bit probabilities delta. + * - __u8 + - ``mv.class0_hp[2]`` + - Motion vector class0 high precision fractional bit probabilities delta. + * - __u8 + - ``mv.hp[2]`` + - Motion vector high precision fractional bit probabilities delta. + +.. _vp9_tx_mode: + +``TX Mode`` + +.. tabularcolumns:: |p{6.5cm}|p{0.5cm}|p{10.3cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP9_TX_MODE_ONLY_4X4`` + - 0 + - Transform size is 4x4. + * - ``V4L2_VP9_TX_MODE_ALLOW_8X8`` + - 1 + - Transform size can be up to 8x8. + * - ``V4L2_VP9_TX_MODE_ALLOW_16X16`` + - 2 + - Transform size can be up to 16x16. + * - ``V4L2_VP9_TX_MODE_ALLOW_32X32`` + - 3 + - transform size can be up to 32x32. + * - ``V4L2_VP9_TX_MODE_SELECT`` + - 4 + - Bitstream contains the transform size for each block. + +See section '7.3.1 Tx mode semantics' of the :ref:`vp9` specification for more details. + +``V4L2_CID_STATELESS_VP9_FRAME (struct)`` + Specifies the frame parameters for the associated VP9 frame decode request. + This includes the necessary parameters for configuring a stateless hardware + decoding pipeline for VP9. The bitstream parameters are defined according + to :ref:`vp9`. + +.. c:type:: v4l2_ctrl_vp9_frame + +.. raw:: latex + + \small + +.. tabularcolumns:: |p{4.7cm}|p{5.5cm}|p{7.1cm}| + +.. cssclass:: longtable + +.. flat-table:: struct v4l2_ctrl_vp9_frame + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - struct :c:type:`v4l2_vp9_loop_filter` + - ``lf`` + - Loop filter parameters. See struct :c:type:`v4l2_vp9_loop_filter` for more details. + * - struct :c:type:`v4l2_vp9_quantization` + - ``quant`` + - Quantization parameters. See :c:type:`v4l2_vp9_quantization` for more details. + * - struct :c:type:`v4l2_vp9_segmentation` + - ``seg`` + - Segmentation parameters. See :c:type:`v4l2_vp9_segmentation` for more details. + * - __u32 + - ``flags`` + - Combination of V4L2_VP9_FRAME_FLAG_* flags. See :ref:`Frame Flags`. + * - __u16 + - ``compressed_header_size`` + - Compressed header size in bytes. + * - __u16 + - ``uncompressed_header_size`` + - Uncompressed header size in bytes. + * - __u16 + - ``frame_width_minus_1`` + - Add 1 to get the frame width expressed in pixels. See section 7.2.3 in :ref:`vp9`. + * - __u16 + - ``frame_height_minus_1`` + - Add 1 to get the frame height expressed in pixels. See section 7.2.3 in :ref:`vp9`. + * - __u16 + - ``render_width_minus_1`` + - Add 1 to get the expected render width expressed in pixels. This is + not used during the decoding process but might be used by HW scalers to + prepare a frame that's ready for scanout. See section 7.2.4 in :ref:`vp9`. + * - __u16 + - render_height_minus_1 + - Add 1 to get the expected render height expressed in pixels. This is + not used during the decoding process but might be used by HW scalers to + prepare a frame that's ready for scanout. See section 7.2.4 in :ref:`vp9`. + * - __u64 + - ``last_frame_ts`` + - "last" reference buffer timestamp. + The timestamp refers to the ``timestamp`` field in + struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()` + function to convert the struct :c:type:`timeval` in struct + :c:type:`v4l2_buffer` to a __u64. + * - __u64 + - ``golden_frame_ts`` + - "golden" reference buffer timestamp. + The timestamp refers to the ``timestamp`` field in + struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()` + function to convert the struct :c:type:`timeval` in struct + :c:type:`v4l2_buffer` to a __u64. + * - __u64 + - ``alt_frame_ts`` + - "alt" reference buffer timestamp. + The timestamp refers to the ``timestamp`` field in + struct :c:type:`v4l2_buffer`. Use the :c:func:`v4l2_timeval_to_ns()` + function to convert the struct :c:type:`timeval` in struct + :c:type:`v4l2_buffer` to a __u64. + * - __u8 + - ``ref_frame_sign_bias`` + - a bitfield specifying whether the sign bias is set for a given + reference frame. See :ref:`Reference Frame Sign Bias` + for more details. + * - __u8 + - ``reset_frame_context`` + - specifies whether the frame context should be reset to default values. See + :ref:`Reset Frame Context` for more details. + * - __u8 + - ``frame_context_idx`` + - Frame context that should be used/updated. + * - __u8 + - ``profile`` + - VP9 profile. Can be 0, 1, 2 or 3. + * - __u8 + - ``bit_depth`` + - Component depth in bits. Can be 8, 10 or 12. Note that not all profiles + support 10 and/or 12 bits depths. + * - __u8 + - ``interpolation_filter`` + - Specifies the filter selection used for performing inter prediction. See + :ref:`Interpolation Filter` for more details. + * - __u8 + - ``tile_cols_log2`` + - Specifies the base 2 logarithm of the width of each tile (where the + width is measured in units of 8x8 blocks). Shall be less than or equal + to 6. + * - __u8 + - ``tile_rows_log2`` + - Specifies the base 2 logarithm of the height of each tile (where the + height is measured in units of 8x8 blocks). + * - __u8 + - ``reference_mode`` + - Specifies the type of inter prediction to be used. See + :ref:`Reference Mode` for more details. + * - __u8 + - ``reserved[7]`` + - Applications and drivers must set this to zero. + +.. raw:: latex + + \normalsize + +.. _vp9_frame_flags: + +``Frame Flags`` + +.. tabularcolumns:: |p{10.0cm}|p{1.2cm}|p{6.1cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP9_FRAME_FLAG_KEY_FRAME`` + - 0x001 + - The frame is a key frame. + * - ``V4L2_VP9_FRAME_FLAG_SHOW_FRAME`` + - 0x002 + - The frame should be displayed. + * - ``V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT`` + - 0x004 + - The decoding should be error resilient. + * - ``V4L2_VP9_FRAME_FLAG_INTRA_ONLY`` + - 0x008 + - The frame does not reference other frames. + * - ``V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV`` + - 0x010 + - The frame can use high precision motion vectors. + * - ``V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX`` + - 0x020 + - Frame context should be updated after decoding. + * - ``V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE`` + - 0x040 + - Parallel decoding is used. + * - ``V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING`` + - 0x080 + - Vertical subsampling is enabled. + * - ``V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING`` + - 0x100 + - Horizontal subsampling is enabled. + * - ``V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING`` + - 0x200 + - The full UV range is used. + +.. _vp9_ref_frame_sign_bias: + +``Reference Frame Sign Bias`` + +.. tabularcolumns:: |p{7.0cm}|p{1.2cm}|p{9.1cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP9_SIGN_BIAS_LAST`` + - 0x1 + - Sign bias is set for the last reference frame. + * - ``V4L2_VP9_SIGN_BIAS_GOLDEN`` + - 0x2 + - Sign bias is set for the golden reference frame. + * - ``V4L2_VP9_SIGN_BIAS_ALT`` + - 0x2 + - Sign bias is set for the alt reference frame. + +.. _vp9_reset_frame_context: + +``Reset Frame Context`` + +.. tabularcolumns:: |p{7.0cm}|p{1.2cm}|p{9.1cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP9_RESET_FRAME_CTX_NONE`` + - 0 + - Do not reset any frame context. + * - ``V4L2_VP9_RESET_FRAME_CTX_SPEC`` + - 1 + - Reset the frame context pointed to by + :c:type:`v4l2_ctrl_vp9_frame`.frame_context_idx. + * - ``V4L2_VP9_RESET_FRAME_CTX_ALL`` + - 2 + - Reset all frame contexts. + +See section '7.2 Uncompressed header semantics' of the :ref:`vp9` specification +for more details. + +.. _vp9_interpolation_filter: + +``Interpolation Filter`` + +.. tabularcolumns:: |p{9.0cm}|p{1.2cm}|p{7.1cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP9_INTERP_FILTER_EIGHTTAP`` + - 0 + - Eight tap filter. + * - ``V4L2_VP9_INTERP_FILTER_EIGHTTAP_SMOOTH`` + - 1 + - Eight tap smooth filter. + * - ``V4L2_VP9_INTERP_FILTER_EIGHTTAP_SHARP`` + - 2 + - Eeight tap sharp filter. + * - ``V4L2_VP9_INTERP_FILTER_BILINEAR`` + - 3 + - Bilinear filter. + * - ``V4L2_VP9_INTERP_FILTER_SWITCHABLE`` + - 4 + - Filter selection is signaled at the block level. + +See section '7.2.7 Interpolation filter semantics' of the :ref:`vp9` specification +for more details. + +.. _vp9_reference_mode: + +``Reference Mode`` + +.. tabularcolumns:: |p{9.6cm}|p{0.5cm}|p{7.2cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE`` + - 0 + - Indicates that all the inter blocks use only a single reference frame + to generate motion compensated prediction. + * - ``V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE`` + - 1 + - Requires all the inter blocks to use compound mode. Single reference + frame prediction is not allowed. + * - ``V4L2_VP9_REFERENCE_MODE_SELECT`` + - 2 + - Allows each individual inter block to select between single and + compound prediction modes. + +See section '7.3.6 Frame reference mode semantics' of the :ref:`vp9` specification for more details. + +.. c:type:: v4l2_vp9_segmentation + +Encodes the quantization parameters. See section '7.2.10 Segmentation +params syntax' of the :ref:`vp9` specification for more details. + +.. tabularcolumns:: |p{0.8cm}|p{5cm}|p{11.4cm}| + +.. cssclass:: longtable + +.. flat-table:: struct v4l2_vp9_segmentation + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``feature_data[8][4]`` + - Data attached to each feature. Data entry is only valid if the feature + is enabled. The array shall be indexed with segment number as the first dimension + (0..7) and one of V4L2_VP9_SEG_* as the second dimension. + See :ref:`Segment Feature IDs`. + * - __u8 + - ``feature_enabled[8]`` + - Bitmask defining which features are enabled in each segment. The value for each + segment is a combination of V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) values where id is + one of V4L2_VP9_SEG_*. See :ref:`Segment Feature IDs`. + * - __u8 + - ``tree_probs[7]`` + - Specifies the probability values to be used when decoding a Segment-ID. + See '5.15. Segmentation map' section of :ref:`vp9` for more details. + * - __u8 + - ``pred_probs[3]`` + - Specifies the probability values to be used when decoding a + Predicted-Segment-ID. See '6.4.14. Get segment id syntax' + section of :ref:`vp9` for more details. + * - __u8 + - ``flags`` + - Combination of V4L2_VP9_SEGMENTATION_FLAG_* flags. See + :ref:`Segmentation Flags`. + * - __u8 + - ``reserved[5]`` + - Applications and drivers must set this to zero. + +.. _vp9_segment_feature: + +``Segment feature IDs`` + +.. tabularcolumns:: |p{6.0cm}|p{1cm}|p{10.3cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP9_SEG_LVL_ALT_Q`` + - 0 + - Quantizer segment feature. + * - ``V4L2_VP9_SEG_LVL_ALT_L`` + - 1 + - Loop filter segment feature. + * - ``V4L2_VP9_SEG_LVL_REF_FRAME`` + - 2 + - Reference frame segment feature. + * - ``V4L2_VP9_SEG_LVL_SKIP`` + - 3 + - Skip segment feature. + * - ``V4L2_VP9_SEG_LVL_MAX`` + - 4 + - Number of segment features. + +.. _vp9_segmentation_flags: + +``Segmentation Flags`` + +.. tabularcolumns:: |p{10.6cm}|p{0.8cm}|p{5.9cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP9_SEGMENTATION_FLAG_ENABLED`` + - 0x01 + - Indicates that this frame makes use of the segmentation tool. + * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP`` + - 0x02 + - Indicates that the segmentation map should be updated during the + decoding of this frame. + * - ``V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE`` + - 0x04 + - Indicates that the updates to the segmentation map are coded + relative to the existing segmentation map. + * - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA`` + - 0x08 + - Indicates that new parameters are about to be specified for each + segment. + * - ``V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE`` + - 0x10 + - Indicates that the segmentation parameters represent the actual values + to be used. + +.. c:type:: v4l2_vp9_quantization + +Encodes the quantization parameters. See section '7.2.9 Quantization params +syntax' of the VP9 specification for more details. + +.. tabularcolumns:: |p{0.8cm}|p{4cm}|p{12.4cm}| + +.. cssclass:: longtable + +.. flat-table:: struct v4l2_vp9_quantization + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``base_q_idx`` + - Indicates the base frame qindex. + * - __s8 + - ``delta_q_y_dc`` + - Indicates the Y DC quantizer relative to base_q_idx. + * - __s8 + - ``delta_q_uv_dc`` + - Indicates the UV DC quantizer relative to base_q_idx. + * - __s8 + - ``delta_q_uv_ac`` + - Indicates the UV AC quantizer relative to base_q_idx. + * - __u8 + - ``reserved[4]`` + - Applications and drivers must set this to zero. + +.. c:type:: v4l2_vp9_loop_filter + +This structure contains all loop filter related parameters. See sections +'7.2.8 Loop filter semantics' of the :ref:`vp9` specification for more details. + +.. tabularcolumns:: |p{0.8cm}|p{4cm}|p{12.4cm}| + +.. cssclass:: longtable + +.. flat-table:: struct v4l2_vp9_loop_filter + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __s8 + - ``ref_deltas[4]`` + - Contains the adjustment needed for the filter level based on the chosen + reference frame. + * - __s8 + - ``mode_deltas[2]`` + - Contains the adjustment needed for the filter level based on the chosen + mode. + * - __u8 + - ``level`` + - Indicates the loop filter strength. + * - __u8 + - ``sharpness`` + - Indicates the sharpness level. + * - __u8 + - ``flags`` + - Combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags. + See :ref:`Loop Filter Flags `. + * - __u8 + - ``reserved[7]`` + - Applications and drivers must set this to zero. + + +.. _vp9_loop_filter_flags: + +``Loop Filter Flags`` + +.. tabularcolumns:: |p{9.6cm}|p{0.5cm}|p{7.2cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED`` + - 0x1 + - When set, the filter level depends on the mode and reference frame used + to predict a block. + * - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE`` + - 0x2 + - When set, the bitstream contains additional syntax elements that + specify which mode and reference frame deltas are to be updated. diff --git a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst index 0ede39907ee2..967fc803ef94 100644 --- a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst +++ b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst @@ -172,6 +172,21 @@ Compressed Formats - VP9 compressed video frame. The encoder generates one compressed frame per buffer, and the decoder requires one compressed frame per buffer. + * .. _V4L2-PIX-FMT-VP9-FRAME: + + - ``V4L2_PIX_FMT_VP9_FRAME`` + - 'VP9F' + - VP9 parsed frame, including the frame header, as extracted from the container. + This format is adapted for stateless video decoders that implement a + VP9 pipeline with the :ref:`stateless_decoder`. + Metadata associated with the frame to decode is required to be passed + through the ``V4L2_CID_STATELESS_VP9_FRAME`` and + the ``V4L2_CID_STATELESS_VP9_COMPRESSED_HDR`` controls. + See the :ref:`associated Codec Control IDs `. + Exactly one output and one capture buffer must be provided for use with + this pixel format. The output buffer must contain the appropriate number + of macroblocks to decode a full corresponding frame to the matching + capture buffer. * .. _V4L2-PIX-FMT-HEVC: - ``V4L2_PIX_FMT_HEVC`` diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst index fdde0ae6d521..29971a45a2d4 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst @@ -233,6 +233,14 @@ still cause this situation. - ``p_mpeg2_quantisation`` - A pointer to a struct :c:type:`v4l2_ctrl_mpeg2_quantisation`. Valid if this control is of type ``V4L2_CTRL_TYPE_MPEG2_QUANTISATION``. + * - struct :c:type:`v4l2_ctrl_vp9_compressed_hdr` * + - ``p_vp9_compressed_hdr_probs`` + - A pointer to a struct :c:type:`v4l2_ctrl_vp9_compressed_hdr`. Valid if this + control is of type ``V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR``. + * - struct :c:type:`v4l2_ctrl_vp9_frame` * + - ``p_vp9_frame`` + - A pointer to a struct :c:type:`v4l2_ctrl_vp9_frame`. Valid if this + control is of type ``V4L2_CTRL_TYPE_VP9_FRAME``. * - struct :c:type:`v4l2_ctrl_hdr10_cll_info` * - ``p_hdr10_cll`` - A pointer to a struct :c:type:`v4l2_ctrl_hdr10_cll_info`. Valid if this control is diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst index 2f491c17dd5d..88f630252d98 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -513,6 +513,18 @@ See also the examples in :ref:`control`. - n/a - A struct :c:type:`v4l2_ctrl_hevc_decode_params`, containing HEVC decoding parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_vp9_compressed_hdr`, containing VP9 + probabilities updates for stateless video decoders. + * - ``V4L2_CTRL_TYPE_VP9_FRAME`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_vp9_frame`, containing VP9 + frame decode parameters for stateless video decoders. .. raw:: latex diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions index eb0b1cd37abd..9cbb7a0c354a 100644 --- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions @@ -149,6 +149,8 @@ replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_AREA :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_FWHT_PARAMS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_VP8_FRAME :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_VP9_FRAME :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HDR10_CLL_INFO :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY :c:type:`v4l2_ctrl_type` diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 70adfc1b9c81..54abe5245dcc 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -283,6 +283,12 @@ static void std_log(const struct v4l2_ctrl *ctrl) case V4L2_CTRL_TYPE_MPEG2_PICTURE: pr_cont("MPEG2_PICTURE"); break; + case V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR: + pr_cont("VP9_COMPRESSED_HDR"); + break; + case V4L2_CTRL_TYPE_VP9_FRAME: + pr_cont("VP9_FRAME"); + break; default: pr_cont("unknown type %d", ctrl->type); break; @@ -317,6 +323,168 @@ static void std_log(const struct v4l2_ctrl *ctrl) #define zero_reserved(s) \ memset(&(s).reserved, 0, sizeof((s).reserved)) +static int +validate_vp9_lf_params(struct v4l2_vp9_loop_filter *lf) +{ + unsigned int i; + + if (lf->flags & ~(V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED | + V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE)) + return -EINVAL; + + /* That all values are in the accepted range. */ + if (lf->level > GENMASK(5, 0)) + return -EINVAL; + + if (lf->sharpness > GENMASK(2, 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) + if (lf->ref_deltas[i] < -63 || lf->ref_deltas[i] > 63) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) + if (lf->mode_deltas[i] < -63 || lf->mode_deltas[i] > 63) + return -EINVAL; + + zero_reserved(*lf); + return 0; +} + +static int +validate_vp9_quant_params(struct v4l2_vp9_quantization *quant) +{ + if (quant->delta_q_y_dc < -15 || quant->delta_q_y_dc > 15 || + quant->delta_q_uv_dc < -15 || quant->delta_q_uv_dc > 15 || + quant->delta_q_uv_ac < -15 || quant->delta_q_uv_ac > 15) + return -EINVAL; + + zero_reserved(*quant); + return 0; +} + +static int +validate_vp9_seg_params(struct v4l2_vp9_segmentation *seg) +{ + unsigned int i, j; + + if (seg->flags & ~(V4L2_VP9_SEGMENTATION_FLAG_ENABLED | + V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP | + V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE | + V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA | + V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(seg->feature_enabled); i++) { + if (seg->feature_enabled[i] & + ~V4L2_VP9_SEGMENT_FEATURE_ENABLED_MASK) + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(seg->feature_data); i++) { + const int range[] = { 255, 63, 3, 0 }; + + for (j = 0; j < ARRAY_SIZE(seg->feature_data[j]); j++) { + if (seg->feature_data[i][j] < -range[j] || + seg->feature_data[i][j] > range[j]) + return -EINVAL; + } + } + + zero_reserved(*seg); + return 0; +} + +static int +validate_vp9_compressed_hdr(struct v4l2_ctrl_vp9_compressed_hdr *hdr) +{ + if (hdr->tx_mode > V4L2_VP9_TX_MODE_SELECT) + return -EINVAL; + + return 0; +} + +static int +validate_vp9_frame(struct v4l2_ctrl_vp9_frame *frame) +{ + int ret; + + /* Make sure we're not passed invalid flags. */ + if (frame->flags & ~(V4L2_VP9_FRAME_FLAG_KEY_FRAME | + V4L2_VP9_FRAME_FLAG_SHOW_FRAME | + V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT | + V4L2_VP9_FRAME_FLAG_INTRA_ONLY | + V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV | + V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX | + V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE | + V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING | + V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING | + V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING)) + return -EINVAL; + + if (frame->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT && + frame->flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX) + return -EINVAL; + + if (frame->profile > V4L2_VP9_PROFILE_MAX) + return -EINVAL; + + if (frame->reset_frame_context > V4L2_VP9_RESET_FRAME_CTX_ALL) + return -EINVAL; + + if (frame->frame_context_idx >= V4L2_VP9_NUM_FRAME_CTX) + return -EINVAL; + + /* + * Profiles 0 and 1 only support 8-bit depth, profiles 2 and 3 only 10 + * and 12 bit depths. + */ + if ((frame->profile < 2 && frame->bit_depth != 8) || + (frame->profile >= 2 && + (frame->bit_depth != 10 && frame->bit_depth != 12))) + return -EINVAL; + + /* Profile 0 and 2 only accept YUV 4:2:0. */ + if ((frame->profile == 0 || frame->profile == 2) && + (!(frame->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) || + !(frame->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING))) + return -EINVAL; + + /* Profile 1 and 3 only accept YUV 4:2:2, 4:4:0 and 4:4:4. */ + if ((frame->profile == 1 || frame->profile == 3) && + ((frame->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) && + (frame->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING))) + return -EINVAL; + + if (frame->interpolation_filter > V4L2_VP9_INTERP_FILTER_SWITCHABLE) + return -EINVAL; + + /* + * According to the spec, tile_cols_log2 shall be less than or equal + * to 6. + */ + if (frame->tile_cols_log2 > 6) + return -EINVAL; + + if (frame->reference_mode > V4L2_VP9_REFERENCE_MODE_SELECT) + return -EINVAL; + + ret = validate_vp9_lf_params(&frame->lf); + if (ret) + return ret; + + ret = validate_vp9_quant_params(&frame->quant); + if (ret) + return ret; + + ret = validate_vp9_seg_params(&frame->seg); + if (ret) + return ret; + + zero_reserved(*frame); + return 0; +} + /* * Compound controls validation requires setting unused fields/flags to zero * in order to properly detect unchanged controls with std_equal's memcmp. @@ -690,6 +858,12 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: break; + case V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR: + return validate_vp9_compressed_hdr(p); + + case V4L2_CTRL_TYPE_VP9_FRAME: + return validate_vp9_frame(p); + case V4L2_CTRL_TYPE_AREA: area = p; if (!area->width || !area->height) @@ -1255,6 +1429,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, case V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY: elem_size = sizeof(struct v4l2_ctrl_hdr10_mastering_display); break; + case V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR: + elem_size = sizeof(struct v4l2_ctrl_vp9_compressed_hdr); + break; + case V4L2_CTRL_TYPE_VP9_FRAME: + elem_size = sizeof(struct v4l2_ctrl_vp9_frame); + break; case V4L2_CTRL_TYPE_AREA: elem_size = sizeof(struct v4l2_area); break; diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index 431f7ec17557..54ca4e6b820b 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -1178,6 +1178,8 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_STATELESS_MPEG2_SEQUENCE: return "MPEG-2 Sequence Header"; case V4L2_CID_STATELESS_MPEG2_PICTURE: return "MPEG-2 Picture Header"; case V4L2_CID_STATELESS_MPEG2_QUANTISATION: return "MPEG-2 Quantisation Matrices"; + case V4L2_CID_STATELESS_VP9_COMPRESSED_HDR: return "VP9 Probabilities Updates"; + case V4L2_CID_STATELESS_VP9_FRAME: return "VP9 Frame Decode Parameters"; /* Colorimetry controls */ /* Keep the order of the 'case's the same as in v4l2-controls.h! */ @@ -1506,6 +1508,12 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS: *type = V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS; break; + case V4L2_CID_STATELESS_VP9_COMPRESSED_HDR: + *type = V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR; + break; + case V4L2_CID_STATELESS_VP9_FRAME: + *type = V4L2_CTRL_TYPE_VP9_FRAME; + break; case V4L2_CID_UNIT_CELL_SIZE: *type = V4L2_CTRL_TYPE_AREA; *flags |= V4L2_CTRL_FLAG_READ_ONLY; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 69b74d0e8a90..9ac557b8e146 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1413,6 +1413,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_VP8: descr = "VP8"; break; case V4L2_PIX_FMT_VP8_FRAME: descr = "VP8 Frame"; break; case V4L2_PIX_FMT_VP9: descr = "VP9"; break; + case V4L2_PIX_FMT_VP9_FRAME: descr = "VP9 Frame"; break; case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ case V4L2_PIX_FMT_HEVC_SLICE: descr = "HEVC Parsed Slice Data"; break; case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 575b59fbac77..b3ce438f1329 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -50,6 +50,8 @@ struct video_device; * @p_h264_decode_params: Pointer to a struct v4l2_ctrl_h264_decode_params. * @p_h264_pred_weights: Pointer to a struct v4l2_ctrl_h264_pred_weights. * @p_vp8_frame: Pointer to a VP8 frame params structure. + * @p_vp9_compressed_hdr_probs: Pointer to a VP9 frame compressed header probs structure. + * @p_vp9_frame: Pointer to a VP9 frame params structure. * @p_hevc_sps: Pointer to an HEVC sequence parameter set structure. * @p_hevc_pps: Pointer to an HEVC picture parameter set structure. * @p_hevc_slice_params: Pointer to an HEVC slice parameters structure. @@ -80,6 +82,8 @@ union v4l2_ctrl_ptr { struct v4l2_ctrl_hevc_sps *p_hevc_sps; struct v4l2_ctrl_hevc_pps *p_hevc_pps; struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; + struct v4l2_ctrl_vp9_compressed_hdr *p_vp9_compressed_hdr_probs; + struct v4l2_ctrl_vp9_frame *p_vp9_frame; struct v4l2_ctrl_hdr10_cll_info *p_hdr10_cll; struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering; struct v4l2_area *p_area; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index c9eea93a43a9..c8e0f84d204d 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -2018,6 +2018,290 @@ struct v4l2_ctrl_hdr10_mastering_display { __u32 min_display_mastering_luminance; }; +/* Stateless VP9 controls */ + +#define V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED 0x1 +#define V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE 0x2 + +/** + * struct v4l2_vp9_loop_filter - VP9 loop filter parameters + * + * @ref_deltas: contains the adjustment needed for the filter level based on the + * chosen reference frame. If this syntax element is not present in the bitstream, + * users should pass its last value. + * @mode_deltas: contains the adjustment needed for the filter level based on the + * chosen mode. If this syntax element is not present in the bitstream, users should + * pass its last value. + * @level: indicates the loop filter strength. + * @sharpness: indicates the sharpness level. + * @flags: combination of V4L2_VP9_LOOP_FILTER_FLAG_{} flags. + * @reserved: padding field. Should be zeroed by applications. + * + * This structure contains all loop filter related parameters. See sections + * '7.2.8 Loop filter semantics' of the VP9 specification for more details. + */ +struct v4l2_vp9_loop_filter { + __s8 ref_deltas[4]; + __s8 mode_deltas[2]; + __u8 level; + __u8 sharpness; + __u8 flags; + __u8 reserved[7]; +}; + +/** + * struct v4l2_vp9_quantization - VP9 quantization parameters + * + * @base_q_idx: indicates the base frame qindex. + * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx. + * @delta_q_uv_dc: indicates the UV DC quantizer relative to base_q_idx. + * @delta_q_uv_ac: indicates the UV AC quantizer relative to base_q_idx. + * @reserved: padding field. Should be zeroed by applications. + * + * Encodes the quantization parameters. See section '7.2.9 Quantization params + * syntax' of the VP9 specification for more details. + */ +struct v4l2_vp9_quantization { + __u8 base_q_idx; + __s8 delta_q_y_dc; + __s8 delta_q_uv_dc; + __s8 delta_q_uv_ac; + __u8 reserved[4]; +}; + +#define V4L2_VP9_SEGMENTATION_FLAG_ENABLED 0x01 +#define V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP 0x02 +#define V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE 0x04 +#define V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA 0x08 +#define V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE 0x10 + +#define V4L2_VP9_SEG_LVL_ALT_Q 0 +#define V4L2_VP9_SEG_LVL_ALT_L 1 +#define V4L2_VP9_SEG_LVL_REF_FRAME 2 +#define V4L2_VP9_SEG_LVL_SKIP 3 +#define V4L2_VP9_SEG_LVL_MAX 4 + +#define V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) (1 << (id)) +#define V4L2_VP9_SEGMENT_FEATURE_ENABLED_MASK 0xf + +/** + * struct v4l2_vp9_segmentation - VP9 segmentation parameters + * + * @feature_data: data attached to each feature. Data entry is only valid if + * the feature is enabled. The array shall be indexed with segment number as + * the first dimension (0..7) and one of V4L2_VP9_SEG_{} as the second dimension. + * @feature_enabled: bitmask defining which features are enabled in each segment. + * The value for each segment is a combination of V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) + * values where id is one of V4L2_VP9_SEG_LVL_{}. + * @tree_probs: specifies the probability values to be used when decoding a + * Segment-ID. See '5.15. Segmentation map' section of the VP9 specification + * for more details. + * @pred_probs: specifies the probability values to be used when decoding a + * Predicted-Segment-ID. See '6.4.14. Get segment id syntax' section of :ref:`vp9` + * for more details. + * @flags: combination of V4L2_VP9_SEGMENTATION_FLAG_{} flags. + * @reserved: padding field. Should be zeroed by applications. + * + * Encodes the quantization parameters. See section '7.2.10 Segmentation params syntax' of + * the VP9 specification for more details. + */ +struct v4l2_vp9_segmentation { + __s16 feature_data[8][4]; + __u8 feature_enabled[8]; + __u8 tree_probs[7]; + __u8 pred_probs[3]; + __u8 flags; + __u8 reserved[5]; +}; + +#define V4L2_VP9_FRAME_FLAG_KEY_FRAME 0x001 +#define V4L2_VP9_FRAME_FLAG_SHOW_FRAME 0x002 +#define V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT 0x004 +#define V4L2_VP9_FRAME_FLAG_INTRA_ONLY 0x008 +#define V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV 0x010 +#define V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX 0x020 +#define V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE 0x040 +#define V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING 0x080 +#define V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING 0x100 +#define V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING 0x200 + +#define V4L2_VP9_SIGN_BIAS_LAST 0x1 +#define V4L2_VP9_SIGN_BIAS_GOLDEN 0x2 +#define V4L2_VP9_SIGN_BIAS_ALT 0x4 + +#define V4L2_VP9_RESET_FRAME_CTX_NONE 0 +#define V4L2_VP9_RESET_FRAME_CTX_SPEC 1 +#define V4L2_VP9_RESET_FRAME_CTX_ALL 2 + +#define V4L2_VP9_INTERP_FILTER_EIGHTTAP 0 +#define V4L2_VP9_INTERP_FILTER_EIGHTTAP_SMOOTH 1 +#define V4L2_VP9_INTERP_FILTER_EIGHTTAP_SHARP 2 +#define V4L2_VP9_INTERP_FILTER_BILINEAR 3 +#define V4L2_VP9_INTERP_FILTER_SWITCHABLE 4 + +#define V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE 0 +#define V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE 1 +#define V4L2_VP9_REFERENCE_MODE_SELECT 2 + +#define V4L2_VP9_PROFILE_MAX 3 + +#define V4L2_CID_STATELESS_VP9_FRAME (V4L2_CID_CODEC_STATELESS_BASE + 300) +/** + * struct v4l2_ctrl_vp9_frame - VP9 frame decoding control + * + * @lf: loop filter parameters. See &v4l2_vp9_loop_filter for more details. + * @quant: quantization parameters. See &v4l2_vp9_quantization for more details. + * @seg: segmentation parameters. See &v4l2_vp9_segmentation for more details. + * @flags: combination of V4L2_VP9_FRAME_FLAG_{} flags. + * @compressed_header_size: compressed header size in bytes. + * @uncompressed_header_size: uncompressed header size in bytes. + * @frame_width_minus_1: add 1 to it and you'll get the frame width expressed in pixels. + * @frame_height_minus_1: add 1 to it and you'll get the frame height expressed in pixels. + * @render_width_minus_1: add 1 to it and you'll get the expected render width expressed in + * pixels. This is not used during the decoding process but might be used by HW scalers + * to prepare a frame that's ready for scanout. + * @render_height_minus_1: add 1 to it and you'll get the expected render height expressed in + * pixels. This is not used during the decoding process but might be used by HW scalers + * to prepare a frame that's ready for scanout. + * @last_frame_ts: "last" reference buffer timestamp. + * The timestamp refers to the timestamp field in struct v4l2_buffer. + * Use v4l2_timeval_to_ns() to convert the struct timeval to a __u64. + * @golden_frame_ts: "golden" reference buffer timestamp. + * The timestamp refers to the timestamp field in struct v4l2_buffer. + * Use v4l2_timeval_to_ns() to convert the struct timeval to a __u64. + * @alt_frame_ts: "alt" reference buffer timestamp. + * The timestamp refers to the timestamp field in struct v4l2_buffer. + * Use v4l2_timeval_to_ns() to convert the struct timeval to a __u64. + * @ref_frame_sign_bias: a bitfield specifying whether the sign bias is set for a given + * reference frame. Either of V4L2_VP9_SIGN_BIAS_{}. + * @reset_frame_context: specifies whether the frame context should be reset to default values. + * Either of V4L2_VP9_RESET_FRAME_CTX_{}. + * @frame_context_idx: frame context that should be used/updated. + * @profile: VP9 profile. Can be 0, 1, 2 or 3. + * @bit_depth: bits per components. Can be 8, 10 or 12. Note that not all profiles support + * 10 and/or 12 bits depths. + * @interpolation_filter: specifies the filter selection used for performing inter prediction. + * Set to one of V4L2_VP9_INTERP_FILTER_{}. + * @tile_cols_log2: specifies the base 2 logarithm of the width of each tile (where the width + * is measured in units of 8x8 blocks). Shall be less than or equal to 6. + * @tile_rows_log2: specifies the base 2 logarithm of the height of each tile (where the height + * is measured in units of 8x8 blocks). + * @reference_mode: specifies the type of inter prediction to be used. + * Set to one of V4L2_VP9_REFERENCE_MODE_{}. + * @reserved: padding field. Should be zeroed by applications. + */ +struct v4l2_ctrl_vp9_frame { + struct v4l2_vp9_loop_filter lf; + struct v4l2_vp9_quantization quant; + struct v4l2_vp9_segmentation seg; + __u32 flags; + __u16 compressed_header_size; + __u16 uncompressed_header_size; + __u16 frame_width_minus_1; + __u16 frame_height_minus_1; + __u16 render_width_minus_1; + __u16 render_height_minus_1; + __u64 last_frame_ts; + __u64 golden_frame_ts; + __u64 alt_frame_ts; + __u8 ref_frame_sign_bias; + __u8 reset_frame_context; + __u8 frame_context_idx; + __u8 profile; + __u8 bit_depth; + __u8 interpolation_filter; + __u8 tile_cols_log2; + __u8 tile_rows_log2; + __u8 reference_mode; + __u8 reserved[7]; +}; + +#define V4L2_VP9_NUM_FRAME_CTX 4 + +/** + * struct v4l2_vp9_mv_probs - VP9 Motion vector probability updates + * @joint: motion vector joint probability updates. + * @sign: motion vector sign probability updates. + * @classes: motion vector class probability updates. + * @class0_bit: motion vector class0 bit probability updates. + * @bits: motion vector bits probability updates. + * @class0_fr: motion vector class0 fractional bit probability updates. + * @fr: motion vector fractional bit probability updates. + * @class0_hp: motion vector class0 high precision fractional bit probability updates. + * @hp: motion vector high precision fractional bit probability updates. + * + * This structure contains new values of motion vector probabilities. + * A value of zero in an array element means there is no update of the relevant probability. + * See `struct v4l2_vp9_prob_updates` for details. + */ +struct v4l2_vp9_mv_probs { + __u8 joint[3]; + __u8 sign[2]; + __u8 classes[2][10]; + __u8 class0_bit[2]; + __u8 bits[2][10]; + __u8 class0_fr[2][2][3]; + __u8 fr[2][3]; + __u8 class0_hp[2]; + __u8 hp[2]; +}; + +#define V4L2_CID_STATELESS_VP9_COMPRESSED_HDR (V4L2_CID_CODEC_STATELESS_BASE + 301) + +#define V4L2_VP9_TX_MODE_ONLY_4X4 0 +#define V4L2_VP9_TX_MODE_ALLOW_8X8 1 +#define V4L2_VP9_TX_MODE_ALLOW_16X16 2 +#define V4L2_VP9_TX_MODE_ALLOW_32X32 3 +#define V4L2_VP9_TX_MODE_SELECT 4 + +/** + * struct v4l2_ctrl_vp9_compressed_hdr - VP9 probability updates control + * @tx_mode: specifies the TX mode. Set to one of V4L2_VP9_TX_MODE_{}. + * @tx8: TX 8x8 probability updates. + * @tx16: TX 16x16 probability updates. + * @tx32: TX 32x32 probability updates. + * @coef: coefficient probability updates. + * @skip: skip probability updates. + * @inter_mode: inter mode probability updates. + * @interp_filter: interpolation filter probability updates. + * @is_inter: is inter-block probability updates. + * @comp_mode: compound prediction mode probability updates. + * @single_ref: single ref probability updates. + * @comp_ref: compound ref probability updates. + * @y_mode: Y prediction mode probability updates. + * @uv_mode: UV prediction mode probability updates. + * @partition: partition probability updates. + * @mv: motion vector probability updates. + * + * This structure holds the probabilities update as parsed in the compressed + * header (Spec 6.3). These values represent the value of probability update after + * being translated with inv_map_table[] (see 6.3.5). A value of zero in an array element + * means that there is no update of the relevant probability. + * + * This control is optional and needs to be used when dealing with the hardware which is + * not capable of parsing the compressed header itself. Only drivers which need it will + * implement it. + */ +struct v4l2_ctrl_vp9_compressed_hdr { + __u8 tx_mode; + __u8 tx8[2][1]; + __u8 tx16[2][2]; + __u8 tx32[2][3]; + __u8 coef[4][2][2][6][6][3]; + __u8 skip[3]; + __u8 inter_mode[7][3]; + __u8 interp_filter[4][2]; + __u8 is_inter[4]; + __u8 comp_mode[5]; + __u8 single_ref[5][2]; + __u8 comp_ref[5]; + __u8 y_mode[4][9]; + __u8 uv_mode[10][9]; + __u8 partition[16][3]; + + struct v4l2_vp9_mv_probs mv; +}; + /* MPEG-compression definitions kept for backwards compatibility */ #ifndef __KERNEL__ #define V4L2_CTRL_CLASS_MPEG V4L2_CTRL_CLASS_CODEC diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index f118fe7a9f58..df8b9c486ba1 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -703,6 +703,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* VP8 */ #define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F') /* VP8 parsed frame */ #define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0') /* VP9 */ +#define V4L2_PIX_FMT_VP9_FRAME v4l2_fourcc('V', 'P', '9', 'F') /* VP9 parsed frame */ #define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C') /* HEVC aka H.265 */ #define V4L2_PIX_FMT_FWHT v4l2_fourcc('F', 'W', 'H', 'T') /* Fast Walsh Hadamard Transform (vicodec) */ #define V4L2_PIX_FMT_FWHT_STATELESS v4l2_fourcc('S', 'F', 'W', 'H') /* Stateless FWHT (vicodec) */ @@ -1759,6 +1760,8 @@ struct v4l2_ext_control { struct v4l2_ctrl_mpeg2_sequence __user *p_mpeg2_sequence; struct v4l2_ctrl_mpeg2_picture __user *p_mpeg2_picture; struct v4l2_ctrl_mpeg2_quantisation __user *p_mpeg2_quantisation; + struct v4l2_ctrl_vp9_compressed_hdr __user *p_vp9_compressed_hdr_probs; + struct v4l2_ctrl_vp9_frame __user *p_vp9_frame; void __user *ptr; }; } __attribute__ ((packed)); @@ -1823,6 +1826,9 @@ enum v4l2_ctrl_type { V4L2_CTRL_TYPE_MPEG2_QUANTISATION = 0x0250, V4L2_CTRL_TYPE_MPEG2_SEQUENCE = 0x0251, V4L2_CTRL_TYPE_MPEG2_PICTURE = 0x0252, + + V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR = 0x0260, + V4L2_CTRL_TYPE_VP9_FRAME = 0x0261, }; /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ From 3e3b1fb0e5d95c0cd7278717185ca3fb00f5d771 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 16 Nov 2021 14:38:36 +0000 Subject: [PATCH 188/397] media: Add VP9 v4l2 library Provide code common to vp9 drivers in one central location. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Kconfig | 4 + drivers/media/v4l2-core/Makefile | 1 + drivers/media/v4l2-core/v4l2-vp9.c | 1850 ++++++++++++++++++++++++++++ include/media/v4l2-vp9.h | 233 ++++ 4 files changed, 2088 insertions(+) create mode 100644 drivers/media/v4l2-core/v4l2-vp9.c create mode 100644 include/media/v4l2-vp9.h diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index 02dc1787e953..6ee75c6c820e 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -52,6 +52,10 @@ config V4L2_JPEG_HELPER config V4L2_H264 tristate +# Used by drivers that need v4l2-vp9.ko +config V4L2_VP9 + tristate + # Used by drivers that need v4l2-mem2mem.ko config V4L2_MEM2MEM_DEV tristate diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 66a78c556c98..83fac5c746f5 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o obj-$(CONFIG_V4L2_H264) += v4l2-h264.o +obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o diff --git a/drivers/media/v4l2-core/v4l2-vp9.c b/drivers/media/v4l2-core/v4l2-vp9.c new file mode 100644 index 000000000000..859589f1fd35 --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-vp9.c @@ -0,0 +1,1850 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * V4L2 VP9 helpers. + * + * Copyright (C) 2021 Collabora, Ltd. + * + * Author: Andrzej Pietrasiewicz + */ + +#include + +#include + +const u8 v4l2_vp9_kf_y_mode_prob[10][10][9] = { + { + /* above = dc */ + { 137, 30, 42, 148, 151, 207, 70, 52, 91 }, /*left = dc */ + { 92, 45, 102, 136, 116, 180, 74, 90, 100 }, /*left = v */ + { 73, 32, 19, 187, 222, 215, 46, 34, 100 }, /*left = h */ + { 91, 30, 32, 116, 121, 186, 93, 86, 94 }, /*left = d45 */ + { 72, 35, 36, 149, 68, 206, 68, 63, 105 }, /*left = d135*/ + { 73, 31, 28, 138, 57, 124, 55, 122, 151 }, /*left = d117*/ + { 67, 23, 21, 140, 126, 197, 40, 37, 171 }, /*left = d153*/ + { 86, 27, 28, 128, 154, 212, 45, 43, 53 }, /*left = d207*/ + { 74, 32, 27, 107, 86, 160, 63, 134, 102 }, /*left = d63 */ + { 59, 67, 44, 140, 161, 202, 78, 67, 119 }, /*left = tm */ + }, { /* above = v */ + { 63, 36, 126, 146, 123, 158, 60, 90, 96 }, /*left = dc */ + { 43, 46, 168, 134, 107, 128, 69, 142, 92 }, /*left = v */ + { 44, 29, 68, 159, 201, 177, 50, 57, 77 }, /*left = h */ + { 58, 38, 76, 114, 97, 172, 78, 133, 92 }, /*left = d45 */ + { 46, 41, 76, 140, 63, 184, 69, 112, 57 }, /*left = d135*/ + { 38, 32, 85, 140, 46, 112, 54, 151, 133 }, /*left = d117*/ + { 39, 27, 61, 131, 110, 175, 44, 75, 136 }, /*left = d153*/ + { 52, 30, 74, 113, 130, 175, 51, 64, 58 }, /*left = d207*/ + { 47, 35, 80, 100, 74, 143, 64, 163, 74 }, /*left = d63 */ + { 36, 61, 116, 114, 128, 162, 80, 125, 82 }, /*left = tm */ + }, { /* above = h */ + { 82, 26, 26, 171, 208, 204, 44, 32, 105 }, /*left = dc */ + { 55, 44, 68, 166, 179, 192, 57, 57, 108 }, /*left = v */ + { 42, 26, 11, 199, 241, 228, 23, 15, 85 }, /*left = h */ + { 68, 42, 19, 131, 160, 199, 55, 52, 83 }, /*left = d45 */ + { 58, 50, 25, 139, 115, 232, 39, 52, 118 }, /*left = d135*/ + { 50, 35, 33, 153, 104, 162, 64, 59, 131 }, /*left = d117*/ + { 44, 24, 16, 150, 177, 202, 33, 19, 156 }, /*left = d153*/ + { 55, 27, 12, 153, 203, 218, 26, 27, 49 }, /*left = d207*/ + { 53, 49, 21, 110, 116, 168, 59, 80, 76 }, /*left = d63 */ + { 38, 72, 19, 168, 203, 212, 50, 50, 107 }, /*left = tm */ + }, { /* above = d45 */ + { 103, 26, 36, 129, 132, 201, 83, 80, 93 }, /*left = dc */ + { 59, 38, 83, 112, 103, 162, 98, 136, 90 }, /*left = v */ + { 62, 30, 23, 158, 200, 207, 59, 57, 50 }, /*left = h */ + { 67, 30, 29, 84, 86, 191, 102, 91, 59 }, /*left = d45 */ + { 60, 32, 33, 112, 71, 220, 64, 89, 104 }, /*left = d135*/ + { 53, 26, 34, 130, 56, 149, 84, 120, 103 }, /*left = d117*/ + { 53, 21, 23, 133, 109, 210, 56, 77, 172 }, /*left = d153*/ + { 77, 19, 29, 112, 142, 228, 55, 66, 36 }, /*left = d207*/ + { 61, 29, 29, 93, 97, 165, 83, 175, 162 }, /*left = d63 */ + { 47, 47, 43, 114, 137, 181, 100, 99, 95 }, /*left = tm */ + }, { /* above = d135 */ + { 69, 23, 29, 128, 83, 199, 46, 44, 101 }, /*left = dc */ + { 53, 40, 55, 139, 69, 183, 61, 80, 110 }, /*left = v */ + { 40, 29, 19, 161, 180, 207, 43, 24, 91 }, /*left = h */ + { 60, 34, 19, 105, 61, 198, 53, 64, 89 }, /*left = d45 */ + { 52, 31, 22, 158, 40, 209, 58, 62, 89 }, /*left = d135*/ + { 44, 31, 29, 147, 46, 158, 56, 102, 198 }, /*left = d117*/ + { 35, 19, 12, 135, 87, 209, 41, 45, 167 }, /*left = d153*/ + { 55, 25, 21, 118, 95, 215, 38, 39, 66 }, /*left = d207*/ + { 51, 38, 25, 113, 58, 164, 70, 93, 97 }, /*left = d63 */ + { 47, 54, 34, 146, 108, 203, 72, 103, 151 }, /*left = tm */ + }, { /* above = d117 */ + { 64, 19, 37, 156, 66, 138, 49, 95, 133 }, /*left = dc */ + { 46, 27, 80, 150, 55, 124, 55, 121, 135 }, /*left = v */ + { 36, 23, 27, 165, 149, 166, 54, 64, 118 }, /*left = h */ + { 53, 21, 36, 131, 63, 163, 60, 109, 81 }, /*left = d45 */ + { 40, 26, 35, 154, 40, 185, 51, 97, 123 }, /*left = d135*/ + { 35, 19, 34, 179, 19, 97, 48, 129, 124 }, /*left = d117*/ + { 36, 20, 26, 136, 62, 164, 33, 77, 154 }, /*left = d153*/ + { 45, 18, 32, 130, 90, 157, 40, 79, 91 }, /*left = d207*/ + { 45, 26, 28, 129, 45, 129, 49, 147, 123 }, /*left = d63 */ + { 38, 44, 51, 136, 74, 162, 57, 97, 121 }, /*left = tm */ + }, { /* above = d153 */ + { 75, 17, 22, 136, 138, 185, 32, 34, 166 }, /*left = dc */ + { 56, 39, 58, 133, 117, 173, 48, 53, 187 }, /*left = v */ + { 35, 21, 12, 161, 212, 207, 20, 23, 145 }, /*left = h */ + { 56, 29, 19, 117, 109, 181, 55, 68, 112 }, /*left = d45 */ + { 47, 29, 17, 153, 64, 220, 59, 51, 114 }, /*left = d135*/ + { 46, 16, 24, 136, 76, 147, 41, 64, 172 }, /*left = d117*/ + { 34, 17, 11, 108, 152, 187, 13, 15, 209 }, /*left = d153*/ + { 51, 24, 14, 115, 133, 209, 32, 26, 104 }, /*left = d207*/ + { 55, 30, 18, 122, 79, 179, 44, 88, 116 }, /*left = d63 */ + { 37, 49, 25, 129, 168, 164, 41, 54, 148 }, /*left = tm */ + }, { /* above = d207 */ + { 82, 22, 32, 127, 143, 213, 39, 41, 70 }, /*left = dc */ + { 62, 44, 61, 123, 105, 189, 48, 57, 64 }, /*left = v */ + { 47, 25, 17, 175, 222, 220, 24, 30, 86 }, /*left = h */ + { 68, 36, 17, 106, 102, 206, 59, 74, 74 }, /*left = d45 */ + { 57, 39, 23, 151, 68, 216, 55, 63, 58 }, /*left = d135*/ + { 49, 30, 35, 141, 70, 168, 82, 40, 115 }, /*left = d117*/ + { 51, 25, 15, 136, 129, 202, 38, 35, 139 }, /*left = d153*/ + { 68, 26, 16, 111, 141, 215, 29, 28, 28 }, /*left = d207*/ + { 59, 39, 19, 114, 75, 180, 77, 104, 42 }, /*left = d63 */ + { 40, 61, 26, 126, 152, 206, 61, 59, 93 }, /*left = tm */ + }, { /* above = d63 */ + { 78, 23, 39, 111, 117, 170, 74, 124, 94 }, /*left = dc */ + { 48, 34, 86, 101, 92, 146, 78, 179, 134 }, /*left = v */ + { 47, 22, 24, 138, 187, 178, 68, 69, 59 }, /*left = h */ + { 56, 25, 33, 105, 112, 187, 95, 177, 129 }, /*left = d45 */ + { 48, 31, 27, 114, 63, 183, 82, 116, 56 }, /*left = d135*/ + { 43, 28, 37, 121, 63, 123, 61, 192, 169 }, /*left = d117*/ + { 42, 17, 24, 109, 97, 177, 56, 76, 122 }, /*left = d153*/ + { 58, 18, 28, 105, 139, 182, 70, 92, 63 }, /*left = d207*/ + { 46, 23, 32, 74, 86, 150, 67, 183, 88 }, /*left = d63 */ + { 36, 38, 48, 92, 122, 165, 88, 137, 91 }, /*left = tm */ + }, { /* above = tm */ + { 65, 70, 60, 155, 159, 199, 61, 60, 81 }, /*left = dc */ + { 44, 78, 115, 132, 119, 173, 71, 112, 93 }, /*left = v */ + { 39, 38, 21, 184, 227, 206, 42, 32, 64 }, /*left = h */ + { 58, 47, 36, 124, 137, 193, 80, 82, 78 }, /*left = d45 */ + { 49, 50, 35, 144, 95, 205, 63, 78, 59 }, /*left = d135*/ + { 41, 53, 52, 148, 71, 142, 65, 128, 51 }, /*left = d117*/ + { 40, 36, 28, 143, 143, 202, 40, 55, 137 }, /*left = d153*/ + { 52, 34, 29, 129, 183, 227, 42, 35, 43 }, /*left = d207*/ + { 42, 44, 44, 104, 105, 164, 64, 130, 80 }, /*left = d63 */ + { 43, 81, 53, 140, 169, 204, 68, 84, 72 }, /*left = tm */ + } +}; +EXPORT_SYMBOL_GPL(v4l2_vp9_kf_y_mode_prob); + +const u8 v4l2_vp9_kf_partition_probs[16][3] = { + /* 8x8 -> 4x4 */ + { 158, 97, 94 }, /* a/l both not split */ + { 93, 24, 99 }, /* a split, l not split */ + { 85, 119, 44 }, /* l split, a not split */ + { 62, 59, 67 }, /* a/l both split */ + /* 16x16 -> 8x8 */ + { 149, 53, 53 }, /* a/l both not split */ + { 94, 20, 48 }, /* a split, l not split */ + { 83, 53, 24 }, /* l split, a not split */ + { 52, 18, 18 }, /* a/l both split */ + /* 32x32 -> 16x16 */ + { 150, 40, 39 }, /* a/l both not split */ + { 78, 12, 26 }, /* a split, l not split */ + { 67, 33, 11 }, /* l split, a not split */ + { 24, 7, 5 }, /* a/l both split */ + /* 64x64 -> 32x32 */ + { 174, 35, 49 }, /* a/l both not split */ + { 68, 11, 27 }, /* a split, l not split */ + { 57, 15, 9 }, /* l split, a not split */ + { 12, 3, 3 }, /* a/l both split */ +}; +EXPORT_SYMBOL_GPL(v4l2_vp9_kf_partition_probs); + +const u8 v4l2_vp9_kf_uv_mode_prob[10][9] = { + { 144, 11, 54, 157, 195, 130, 46, 58, 108 }, /* y = dc */ + { 118, 15, 123, 148, 131, 101, 44, 93, 131 }, /* y = v */ + { 113, 12, 23, 188, 226, 142, 26, 32, 125 }, /* y = h */ + { 120, 11, 50, 123, 163, 135, 64, 77, 103 }, /* y = d45 */ + { 113, 9, 36, 155, 111, 157, 32, 44, 161 }, /* y = d135 */ + { 116, 9, 55, 176, 76, 96, 37, 61, 149 }, /* y = d117 */ + { 115, 9, 28, 141, 161, 167, 21, 25, 193 }, /* y = d153 */ + { 120, 12, 32, 145, 195, 142, 32, 38, 86 }, /* y = d207 */ + { 116, 12, 64, 120, 140, 125, 49, 115, 121 }, /* y = d63 */ + { 102, 19, 66, 162, 182, 122, 35, 59, 128 } /* y = tm */ +}; +EXPORT_SYMBOL_GPL(v4l2_vp9_kf_uv_mode_prob); + +const struct v4l2_vp9_frame_context v4l2_vp9_default_probs = { + .tx8 = { + { 100 }, + { 66 }, + }, + .tx16 = { + { 20, 152 }, + { 15, 101 }, + }, + .tx32 = { + { 3, 136, 37 }, + { 5, 52, 13 }, + }, + .coef = { + { /* tx = 4x4 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 195, 29, 183 }, + { 84, 49, 136 }, + { 8, 42, 71 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 31, 107, 169 }, + { 35, 99, 159 }, + { 17, 82, 140 }, + { 8, 66, 114 }, + { 2, 44, 76 }, + { 1, 19, 32 }, + }, + { /* Coeff Band 2 */ + { 40, 132, 201 }, + { 29, 114, 187 }, + { 13, 91, 157 }, + { 7, 75, 127 }, + { 3, 58, 95 }, + { 1, 28, 47 }, + }, + { /* Coeff Band 3 */ + { 69, 142, 221 }, + { 42, 122, 201 }, + { 15, 91, 159 }, + { 6, 67, 121 }, + { 1, 42, 77 }, + { 1, 17, 31 }, + }, + { /* Coeff Band 4 */ + { 102, 148, 228 }, + { 67, 117, 204 }, + { 17, 82, 154 }, + { 6, 59, 114 }, + { 2, 39, 75 }, + { 1, 15, 29 }, + }, + { /* Coeff Band 5 */ + { 156, 57, 233 }, + { 119, 57, 212 }, + { 58, 48, 163 }, + { 29, 40, 124 }, + { 12, 30, 81 }, + { 3, 12, 31 } + }, + }, + { /* Inter */ + { /* Coeff Band 0 */ + { 191, 107, 226 }, + { 124, 117, 204 }, + { 25, 99, 155 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 29, 148, 210 }, + { 37, 126, 194 }, + { 8, 93, 157 }, + { 2, 68, 118 }, + { 1, 39, 69 }, + { 1, 17, 33 }, + }, + { /* Coeff Band 2 */ + { 41, 151, 213 }, + { 27, 123, 193 }, + { 3, 82, 144 }, + { 1, 58, 105 }, + { 1, 32, 60 }, + { 1, 13, 26 }, + }, + { /* Coeff Band 3 */ + { 59, 159, 220 }, + { 23, 126, 198 }, + { 4, 88, 151 }, + { 1, 66, 114 }, + { 1, 38, 71 }, + { 1, 18, 34 }, + }, + { /* Coeff Band 4 */ + { 114, 136, 232 }, + { 51, 114, 207 }, + { 11, 83, 155 }, + { 3, 56, 105 }, + { 1, 33, 65 }, + { 1, 17, 34 }, + }, + { /* Coeff Band 5 */ + { 149, 65, 234 }, + { 121, 57, 215 }, + { 61, 49, 166 }, + { 28, 36, 114 }, + { 12, 25, 76 }, + { 3, 16, 42 }, + }, + }, + }, + { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 214, 49, 220 }, + { 132, 63, 188 }, + { 42, 65, 137 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 85, 137, 221 }, + { 104, 131, 216 }, + { 49, 111, 192 }, + { 21, 87, 155 }, + { 2, 49, 87 }, + { 1, 16, 28 }, + }, + { /* Coeff Band 2 */ + { 89, 163, 230 }, + { 90, 137, 220 }, + { 29, 100, 183 }, + { 10, 70, 135 }, + { 2, 42, 81 }, + { 1, 17, 33 }, + }, + { /* Coeff Band 3 */ + { 108, 167, 237 }, + { 55, 133, 222 }, + { 15, 97, 179 }, + { 4, 72, 135 }, + { 1, 45, 85 }, + { 1, 19, 38 }, + }, + { /* Coeff Band 4 */ + { 124, 146, 240 }, + { 66, 124, 224 }, + { 17, 88, 175 }, + { 4, 58, 122 }, + { 1, 36, 75 }, + { 1, 18, 37 }, + }, + { /* Coeff Band 5 */ + { 141, 79, 241 }, + { 126, 70, 227 }, + { 66, 58, 182 }, + { 30, 44, 136 }, + { 12, 34, 96 }, + { 2, 20, 47 }, + }, + }, + { /* Inter */ + { /* Coeff Band 0 */ + { 229, 99, 249 }, + { 143, 111, 235 }, + { 46, 109, 192 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 82, 158, 236 }, + { 94, 146, 224 }, + { 25, 117, 191 }, + { 9, 87, 149 }, + { 3, 56, 99 }, + { 1, 33, 57 }, + }, + { /* Coeff Band 2 */ + { 83, 167, 237 }, + { 68, 145, 222 }, + { 10, 103, 177 }, + { 2, 72, 131 }, + { 1, 41, 79 }, + { 1, 20, 39 }, + }, + { /* Coeff Band 3 */ + { 99, 167, 239 }, + { 47, 141, 224 }, + { 10, 104, 178 }, + { 2, 73, 133 }, + { 1, 44, 85 }, + { 1, 22, 47 }, + }, + { /* Coeff Band 4 */ + { 127, 145, 243 }, + { 71, 129, 228 }, + { 17, 93, 177 }, + { 3, 61, 124 }, + { 1, 41, 84 }, + { 1, 21, 52 }, + }, + { /* Coeff Band 5 */ + { 157, 78, 244 }, + { 140, 72, 231 }, + { 69, 58, 184 }, + { 31, 44, 137 }, + { 14, 38, 105 }, + { 8, 23, 61 }, + }, + }, + }, + }, + { /* tx = 8x8 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 125, 34, 187 }, + { 52, 41, 133 }, + { 6, 31, 56 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 37, 109, 153 }, + { 51, 102, 147 }, + { 23, 87, 128 }, + { 8, 67, 101 }, + { 1, 41, 63 }, + { 1, 19, 29 }, + }, + { /* Coeff Band 2 */ + { 31, 154, 185 }, + { 17, 127, 175 }, + { 6, 96, 145 }, + { 2, 73, 114 }, + { 1, 51, 82 }, + { 1, 28, 45 }, + }, + { /* Coeff Band 3 */ + { 23, 163, 200 }, + { 10, 131, 185 }, + { 2, 93, 148 }, + { 1, 67, 111 }, + { 1, 41, 69 }, + { 1, 14, 24 }, + }, + { /* Coeff Band 4 */ + { 29, 176, 217 }, + { 12, 145, 201 }, + { 3, 101, 156 }, + { 1, 69, 111 }, + { 1, 39, 63 }, + { 1, 14, 23 }, + }, + { /* Coeff Band 5 */ + { 57, 192, 233 }, + { 25, 154, 215 }, + { 6, 109, 167 }, + { 3, 78, 118 }, + { 1, 48, 69 }, + { 1, 21, 29 }, + }, + }, + { /* Inter */ + { /* Coeff Band 0 */ + { 202, 105, 245 }, + { 108, 106, 216 }, + { 18, 90, 144 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 33, 172, 219 }, + { 64, 149, 206 }, + { 14, 117, 177 }, + { 5, 90, 141 }, + { 2, 61, 95 }, + { 1, 37, 57 }, + }, + { /* Coeff Band 2 */ + { 33, 179, 220 }, + { 11, 140, 198 }, + { 1, 89, 148 }, + { 1, 60, 104 }, + { 1, 33, 57 }, + { 1, 12, 21 }, + }, + { /* Coeff Band 3 */ + { 30, 181, 221 }, + { 8, 141, 198 }, + { 1, 87, 145 }, + { 1, 58, 100 }, + { 1, 31, 55 }, + { 1, 12, 20 }, + }, + { /* Coeff Band 4 */ + { 32, 186, 224 }, + { 7, 142, 198 }, + { 1, 86, 143 }, + { 1, 58, 100 }, + { 1, 31, 55 }, + { 1, 12, 22 }, + }, + { /* Coeff Band 5 */ + { 57, 192, 227 }, + { 20, 143, 204 }, + { 3, 96, 154 }, + { 1, 68, 112 }, + { 1, 42, 69 }, + { 1, 19, 32 }, + }, + }, + }, + { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 212, 35, 215 }, + { 113, 47, 169 }, + { 29, 48, 105 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 74, 129, 203 }, + { 106, 120, 203 }, + { 49, 107, 178 }, + { 19, 84, 144 }, + { 4, 50, 84 }, + { 1, 15, 25 }, + }, + { /* Coeff Band 2 */ + { 71, 172, 217 }, + { 44, 141, 209 }, + { 15, 102, 173 }, + { 6, 76, 133 }, + { 2, 51, 89 }, + { 1, 24, 42 }, + }, + { /* Coeff Band 3 */ + { 64, 185, 231 }, + { 31, 148, 216 }, + { 8, 103, 175 }, + { 3, 74, 131 }, + { 1, 46, 81 }, + { 1, 18, 30 }, + }, + { /* Coeff Band 4 */ + { 65, 196, 235 }, + { 25, 157, 221 }, + { 5, 105, 174 }, + { 1, 67, 120 }, + { 1, 38, 69 }, + { 1, 15, 30 }, + }, + { /* Coeff Band 5 */ + { 65, 204, 238 }, + { 30, 156, 224 }, + { 7, 107, 177 }, + { 2, 70, 124 }, + { 1, 42, 73 }, + { 1, 18, 34 }, + }, + }, + { /* Inter */ + { /* Coeff Band 0 */ + { 225, 86, 251 }, + { 144, 104, 235 }, + { 42, 99, 181 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 85, 175, 239 }, + { 112, 165, 229 }, + { 29, 136, 200 }, + { 12, 103, 162 }, + { 6, 77, 123 }, + { 2, 53, 84 }, + }, + { /* Coeff Band 2 */ + { 75, 183, 239 }, + { 30, 155, 221 }, + { 3, 106, 171 }, + { 1, 74, 128 }, + { 1, 44, 76 }, + { 1, 17, 28 }, + }, + { /* Coeff Band 3 */ + { 73, 185, 240 }, + { 27, 159, 222 }, + { 2, 107, 172 }, + { 1, 75, 127 }, + { 1, 42, 73 }, + { 1, 17, 29 }, + }, + { /* Coeff Band 4 */ + { 62, 190, 238 }, + { 21, 159, 222 }, + { 2, 107, 172 }, + { 1, 72, 122 }, + { 1, 40, 71 }, + { 1, 18, 32 }, + }, + { /* Coeff Band 5 */ + { 61, 199, 240 }, + { 27, 161, 226 }, + { 4, 113, 180 }, + { 1, 76, 129 }, + { 1, 46, 80 }, + { 1, 23, 41 }, + }, + }, + }, + }, + { /* tx = 16x16 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 7, 27, 153 }, + { 5, 30, 95 }, + { 1, 16, 30 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 50, 75, 127 }, + { 57, 75, 124 }, + { 27, 67, 108 }, + { 10, 54, 86 }, + { 1, 33, 52 }, + { 1, 12, 18 }, + }, + { /* Coeff Band 2 */ + { 43, 125, 151 }, + { 26, 108, 148 }, + { 7, 83, 122 }, + { 2, 59, 89 }, + { 1, 38, 60 }, + { 1, 17, 27 }, + }, + { /* Coeff Band 3 */ + { 23, 144, 163 }, + { 13, 112, 154 }, + { 2, 75, 117 }, + { 1, 50, 81 }, + { 1, 31, 51 }, + { 1, 14, 23 }, + }, + { /* Coeff Band 4 */ + { 18, 162, 185 }, + { 6, 123, 171 }, + { 1, 78, 125 }, + { 1, 51, 86 }, + { 1, 31, 54 }, + { 1, 14, 23 }, + }, + { /* Coeff Band 5 */ + { 15, 199, 227 }, + { 3, 150, 204 }, + { 1, 91, 146 }, + { 1, 55, 95 }, + { 1, 30, 53 }, + { 1, 11, 20 }, + } + }, + { /* Inter */ + { /* Coeff Band 0 */ + { 19, 55, 240 }, + { 19, 59, 196 }, + { 3, 52, 105 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 41, 166, 207 }, + { 104, 153, 199 }, + { 31, 123, 181 }, + { 14, 101, 152 }, + { 5, 72, 106 }, + { 1, 36, 52 }, + }, + { /* Coeff Band 2 */ + { 35, 176, 211 }, + { 12, 131, 190 }, + { 2, 88, 144 }, + { 1, 60, 101 }, + { 1, 36, 60 }, + { 1, 16, 28 }, + }, + { /* Coeff Band 3 */ + { 28, 183, 213 }, + { 8, 134, 191 }, + { 1, 86, 142 }, + { 1, 56, 96 }, + { 1, 30, 53 }, + { 1, 12, 20 }, + }, + { /* Coeff Band 4 */ + { 20, 190, 215 }, + { 4, 135, 192 }, + { 1, 84, 139 }, + { 1, 53, 91 }, + { 1, 28, 49 }, + { 1, 11, 20 }, + }, + { /* Coeff Band 5 */ + { 13, 196, 216 }, + { 2, 137, 192 }, + { 1, 86, 143 }, + { 1, 57, 99 }, + { 1, 32, 56 }, + { 1, 13, 24 }, + }, + }, + }, + { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 211, 29, 217 }, + { 96, 47, 156 }, + { 22, 43, 87 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 78, 120, 193 }, + { 111, 116, 186 }, + { 46, 102, 164 }, + { 15, 80, 128 }, + { 2, 49, 76 }, + { 1, 18, 28 }, + }, + { /* Coeff Band 2 */ + { 71, 161, 203 }, + { 42, 132, 192 }, + { 10, 98, 150 }, + { 3, 69, 109 }, + { 1, 44, 70 }, + { 1, 18, 29 }, + }, + { /* Coeff Band 3 */ + { 57, 186, 211 }, + { 30, 140, 196 }, + { 4, 93, 146 }, + { 1, 62, 102 }, + { 1, 38, 65 }, + { 1, 16, 27 }, + }, + { /* Coeff Band 4 */ + { 47, 199, 217 }, + { 14, 145, 196 }, + { 1, 88, 142 }, + { 1, 57, 98 }, + { 1, 36, 62 }, + { 1, 15, 26 }, + }, + { /* Coeff Band 5 */ + { 26, 219, 229 }, + { 5, 155, 207 }, + { 1, 94, 151 }, + { 1, 60, 104 }, + { 1, 36, 62 }, + { 1, 16, 28 }, + } + }, + { /* Inter */ + { /* Coeff Band 0 */ + { 233, 29, 248 }, + { 146, 47, 220 }, + { 43, 52, 140 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 100, 163, 232 }, + { 179, 161, 222 }, + { 63, 142, 204 }, + { 37, 113, 174 }, + { 26, 89, 137 }, + { 18, 68, 97 }, + }, + { /* Coeff Band 2 */ + { 85, 181, 230 }, + { 32, 146, 209 }, + { 7, 100, 164 }, + { 3, 71, 121 }, + { 1, 45, 77 }, + { 1, 18, 30 }, + }, + { /* Coeff Band 3 */ + { 65, 187, 230 }, + { 20, 148, 207 }, + { 2, 97, 159 }, + { 1, 68, 116 }, + { 1, 40, 70 }, + { 1, 14, 29 }, + }, + { /* Coeff Band 4 */ + { 40, 194, 227 }, + { 8, 147, 204 }, + { 1, 94, 155 }, + { 1, 65, 112 }, + { 1, 39, 66 }, + { 1, 14, 26 }, + }, + { /* Coeff Band 5 */ + { 16, 208, 228 }, + { 3, 151, 207 }, + { 1, 98, 160 }, + { 1, 67, 117 }, + { 1, 41, 74 }, + { 1, 17, 31 }, + }, + }, + }, + }, + { /* tx = 32x32 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 17, 38, 140 }, + { 7, 34, 80 }, + { 1, 17, 29 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 37, 75, 128 }, + { 41, 76, 128 }, + { 26, 66, 116 }, + { 12, 52, 94 }, + { 2, 32, 55 }, + { 1, 10, 16 }, + }, + { /* Coeff Band 2 */ + { 50, 127, 154 }, + { 37, 109, 152 }, + { 16, 82, 121 }, + { 5, 59, 85 }, + { 1, 35, 54 }, + { 1, 13, 20 }, + }, + { /* Coeff Band 3 */ + { 40, 142, 167 }, + { 17, 110, 157 }, + { 2, 71, 112 }, + { 1, 44, 72 }, + { 1, 27, 45 }, + { 1, 11, 17 }, + }, + { /* Coeff Band 4 */ + { 30, 175, 188 }, + { 9, 124, 169 }, + { 1, 74, 116 }, + { 1, 48, 78 }, + { 1, 30, 49 }, + { 1, 11, 18 }, + }, + { /* Coeff Band 5 */ + { 10, 222, 223 }, + { 2, 150, 194 }, + { 1, 83, 128 }, + { 1, 48, 79 }, + { 1, 27, 45 }, + { 1, 11, 17 }, + }, + }, + { /* Inter */ + { /* Coeff Band 0 */ + { 36, 41, 235 }, + { 29, 36, 193 }, + { 10, 27, 111 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 85, 165, 222 }, + { 177, 162, 215 }, + { 110, 135, 195 }, + { 57, 113, 168 }, + { 23, 83, 120 }, + { 10, 49, 61 }, + }, + { /* Coeff Band 2 */ + { 85, 190, 223 }, + { 36, 139, 200 }, + { 5, 90, 146 }, + { 1, 60, 103 }, + { 1, 38, 65 }, + { 1, 18, 30 }, + }, + { /* Coeff Band 3 */ + { 72, 202, 223 }, + { 23, 141, 199 }, + { 2, 86, 140 }, + { 1, 56, 97 }, + { 1, 36, 61 }, + { 1, 16, 27 }, + }, + { /* Coeff Band 4 */ + { 55, 218, 225 }, + { 13, 145, 200 }, + { 1, 86, 141 }, + { 1, 57, 99 }, + { 1, 35, 61 }, + { 1, 13, 22 }, + }, + { /* Coeff Band 5 */ + { 15, 235, 212 }, + { 1, 132, 184 }, + { 1, 84, 139 }, + { 1, 57, 97 }, + { 1, 34, 56 }, + { 1, 14, 23 }, + }, + }, + }, + { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 181, 21, 201 }, + { 61, 37, 123 }, + { 10, 38, 71 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 47, 106, 172 }, + { 95, 104, 173 }, + { 42, 93, 159 }, + { 18, 77, 131 }, + { 4, 50, 81 }, + { 1, 17, 23 }, + }, + { /* Coeff Band 2 */ + { 62, 147, 199 }, + { 44, 130, 189 }, + { 28, 102, 154 }, + { 18, 75, 115 }, + { 2, 44, 65 }, + { 1, 12, 19 }, + }, + { /* Coeff Band 3 */ + { 55, 153, 210 }, + { 24, 130, 194 }, + { 3, 93, 146 }, + { 1, 61, 97 }, + { 1, 31, 50 }, + { 1, 10, 16 }, + }, + { /* Coeff Band 4 */ + { 49, 186, 223 }, + { 17, 148, 204 }, + { 1, 96, 142 }, + { 1, 53, 83 }, + { 1, 26, 44 }, + { 1, 11, 17 }, + }, + { /* Coeff Band 5 */ + { 13, 217, 212 }, + { 2, 136, 180 }, + { 1, 78, 124 }, + { 1, 50, 83 }, + { 1, 29, 49 }, + { 1, 14, 23 }, + }, + }, + { /* Inter */ + { /* Coeff Band 0 */ + { 197, 13, 247 }, + { 82, 17, 222 }, + { 25, 17, 162 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { /* Coeff Band 1 */ + { 126, 186, 247 }, + { 234, 191, 243 }, + { 176, 177, 234 }, + { 104, 158, 220 }, + { 66, 128, 186 }, + { 55, 90, 137 }, + }, + { /* Coeff Band 2 */ + { 111, 197, 242 }, + { 46, 158, 219 }, + { 9, 104, 171 }, + { 2, 65, 125 }, + { 1, 44, 80 }, + { 1, 17, 91 }, + }, + { /* Coeff Band 3 */ + { 104, 208, 245 }, + { 39, 168, 224 }, + { 3, 109, 162 }, + { 1, 79, 124 }, + { 1, 50, 102 }, + { 1, 43, 102 }, + }, + { /* Coeff Band 4 */ + { 84, 220, 246 }, + { 31, 177, 231 }, + { 2, 115, 180 }, + { 1, 79, 134 }, + { 1, 55, 77 }, + { 1, 60, 79 }, + }, + { /* Coeff Band 5 */ + { 43, 243, 240 }, + { 8, 180, 217 }, + { 1, 115, 166 }, + { 1, 84, 121 }, + { 1, 51, 67 }, + { 1, 16, 6 }, + }, + }, + }, + }, + }, + + .skip = { 192, 128, 64 }, + .inter_mode = { + { 2, 173, 34 }, + { 7, 145, 85 }, + { 7, 166, 63 }, + { 7, 94, 66 }, + { 8, 64, 46 }, + { 17, 81, 31 }, + { 25, 29, 30 }, + }, + .interp_filter = { + { 235, 162 }, + { 36, 255 }, + { 34, 3 }, + { 149, 144 }, + }, + .is_inter = { 9, 102, 187, 225 }, + .comp_mode = { 239, 183, 119, 96, 41 }, + .single_ref = { + { 33, 16 }, + { 77, 74 }, + { 142, 142 }, + { 172, 170 }, + { 238, 247 }, + }, + .comp_ref = { 50, 126, 123, 221, 226 }, + .y_mode = { + { 65, 32, 18, 144, 162, 194, 41, 51, 98 }, + { 132, 68, 18, 165, 217, 196, 45, 40, 78 }, + { 173, 80, 19, 176, 240, 193, 64, 35, 46 }, + { 221, 135, 38, 194, 248, 121, 96, 85, 29 }, + }, + .uv_mode = { + { 120, 7, 76, 176, 208, 126, 28, 54, 103 } /* y = dc */, + { 48, 12, 154, 155, 139, 90, 34, 117, 119 } /* y = v */, + { 67, 6, 25, 204, 243, 158, 13, 21, 96 } /* y = h */, + { 97, 5, 44, 131, 176, 139, 48, 68, 97 } /* y = d45 */, + { 83, 5, 42, 156, 111, 152, 26, 49, 152 } /* y = d135 */, + { 80, 5, 58, 178, 74, 83, 33, 62, 145 } /* y = d117 */, + { 86, 5, 32, 154, 192, 168, 14, 22, 163 } /* y = d153 */, + { 85, 5, 32, 156, 216, 148, 19, 29, 73 } /* y = d207 */, + { 77, 7, 64, 116, 132, 122, 37, 126, 120 } /* y = d63 */, + { 101, 21, 107, 181, 192, 103, 19, 67, 125 } /* y = tm */ + }, + .partition = { + /* 8x8 -> 4x4 */ + { 199, 122, 141 } /* a/l both not split */, + { 147, 63, 159 } /* a split, l not split */, + { 148, 133, 118 } /* l split, a not split */, + { 121, 104, 114 } /* a/l both split */, + /* 16x16 -> 8x8 */ + { 174, 73, 87 } /* a/l both not split */, + { 92, 41, 83 } /* a split, l not split */, + { 82, 99, 50 } /* l split, a not split */, + { 53, 39, 39 } /* a/l both split */, + /* 32x32 -> 16x16 */ + { 177, 58, 59 } /* a/l both not split */, + { 68, 26, 63 } /* a split, l not split */, + { 52, 79, 25 } /* l split, a not split */, + { 17, 14, 12 } /* a/l both split */, + /* 64x64 -> 32x32 */ + { 222, 34, 30 } /* a/l both not split */, + { 72, 16, 44 } /* a split, l not split */, + { 58, 32, 12 } /* l split, a not split */, + { 10, 7, 6 } /* a/l both split */, + }, + + .mv = { + .joint = { 32, 64, 96 }, + .sign = { 128, 128 }, + .classes = { + { 224, 144, 192, 168, 192, 176, 192, 198, 198, 245 }, + { 216, 128, 176, 160, 176, 176, 192, 198, 198, 208 }, + }, + .class0_bit = { 216, 208 }, + .bits = { + { 136, 140, 148, 160, 176, 192, 224, 234, 234, 240}, + { 136, 140, 148, 160, 176, 192, 224, 234, 234, 240}, + }, + .class0_fr = { + { + { 128, 128, 64 }, + { 96, 112, 64 }, + }, + { + { 128, 128, 64 }, + { 96, 112, 64 }, + }, + }, + .fr = { + { 64, 96, 64 }, + { 64, 96, 64 }, + }, + .class0_hp = { 160, 160 }, + .hp = { 128, 128 }, + }, +}; +EXPORT_SYMBOL_GPL(v4l2_vp9_default_probs); + +static u32 fastdiv(u32 dividend, u16 divisor) +{ +#define DIV_INV(d) ((u32)(((1ULL << 32) + ((d) - 1)) / (d))) +#define DIVS_INV(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) \ + DIV_INV(d0), DIV_INV(d1), DIV_INV(d2), DIV_INV(d3), \ + DIV_INV(d4), DIV_INV(d5), DIV_INV(d6), DIV_INV(d7), \ + DIV_INV(d8), DIV_INV(d9) + + static const u32 inv[] = { + DIV_INV(2), DIV_INV(3), DIV_INV(4), DIV_INV(5), + DIV_INV(6), DIV_INV(7), DIV_INV(8), DIV_INV(9), + DIVS_INV(10, 11, 12, 13, 14, 15, 16, 17, 18, 19), + DIVS_INV(20, 21, 22, 23, 24, 25, 26, 27, 28, 29), + DIVS_INV(30, 31, 32, 33, 34, 35, 36, 37, 38, 39), + DIVS_INV(40, 41, 42, 43, 44, 45, 46, 47, 48, 49), + DIVS_INV(50, 51, 52, 53, 54, 55, 56, 57, 58, 59), + DIVS_INV(60, 61, 62, 63, 64, 65, 66, 67, 68, 69), + DIVS_INV(70, 71, 72, 73, 74, 75, 76, 77, 78, 79), + DIVS_INV(80, 81, 82, 83, 84, 85, 86, 87, 88, 89), + DIVS_INV(90, 91, 92, 93, 94, 95, 96, 97, 98, 99), + DIVS_INV(100, 101, 102, 103, 104, 105, 106, 107, 108, 109), + DIVS_INV(110, 111, 112, 113, 114, 115, 116, 117, 118, 119), + DIVS_INV(120, 121, 122, 123, 124, 125, 126, 127, 128, 129), + DIVS_INV(130, 131, 132, 133, 134, 135, 136, 137, 138, 139), + DIVS_INV(140, 141, 142, 143, 144, 145, 146, 147, 148, 149), + DIVS_INV(150, 151, 152, 153, 154, 155, 156, 157, 158, 159), + DIVS_INV(160, 161, 162, 163, 164, 165, 166, 167, 168, 169), + DIVS_INV(170, 171, 172, 173, 174, 175, 176, 177, 178, 179), + DIVS_INV(180, 181, 182, 183, 184, 185, 186, 187, 188, 189), + DIVS_INV(190, 191, 192, 193, 194, 195, 196, 197, 198, 199), + DIVS_INV(200, 201, 202, 203, 204, 205, 206, 207, 208, 209), + DIVS_INV(210, 211, 212, 213, 214, 215, 216, 217, 218, 219), + DIVS_INV(220, 221, 222, 223, 224, 225, 226, 227, 228, 229), + DIVS_INV(230, 231, 232, 233, 234, 235, 236, 237, 238, 239), + DIVS_INV(240, 241, 242, 243, 244, 245, 246, 247, 248, 249), + DIV_INV(250), DIV_INV(251), DIV_INV(252), DIV_INV(253), + DIV_INV(254), DIV_INV(255), DIV_INV(256), + }; + + if (divisor == 0) + return 0; + else if (divisor == 1) + return dividend; + + if (WARN_ON(divisor - 2 >= ARRAY_SIZE(inv))) + return dividend; + + return ((u64)dividend * inv[divisor - 2]) >> 32; +} + +/* 6.3.6 inv_recenter_nonneg(v, m) */ +static int inv_recenter_nonneg(int v, int m) +{ + if (v > 2 * m) + return v; + + if (v & 1) + return m - ((v + 1) >> 1); + + return m + (v >> 1); +} + +/* + * part of 6.3.5 inv_remap_prob(deltaProb, prob) + * delta = inv_map_table[deltaProb] done by userspace + */ +static int update_prob(int delta, int prob) +{ + if (!delta) + return prob; + + return prob <= 128 ? + 1 + inv_recenter_nonneg(delta, prob - 1) : + 255 - inv_recenter_nonneg(delta, 255 - prob); +} + +/* Counterpart to 6.3.2 tx_mode_probs() */ +static void update_tx_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(probs->tx8); i++) { + u8 *p8x8 = probs->tx8[i]; + u8 *p16x16 = probs->tx16[i]; + u8 *p32x32 = probs->tx32[i]; + const u8 *d8x8 = deltas->tx8[i]; + const u8 *d16x16 = deltas->tx16[i]; + const u8 *d32x32 = deltas->tx32[i]; + + p8x8[0] = update_prob(d8x8[0], p8x8[0]); + p16x16[0] = update_prob(d16x16[0], p16x16[0]); + p16x16[1] = update_prob(d16x16[1], p16x16[1]); + p32x32[0] = update_prob(d32x32[0], p32x32[0]); + p32x32[1] = update_prob(d32x32[1], p32x32[1]); + p32x32[2] = update_prob(d32x32[2], p32x32[2]); + } +} + +#define BAND_6(band) ((band) == 0 ? 3 : 6) + +static void update_coeff(const u8 deltas[6][6][3], u8 probs[6][6][3]) +{ + int l, m, n; + + for (l = 0; l < 6; l++) + for (m = 0; m < BAND_6(l); m++) { + u8 *p = probs[l][m]; + const u8 *d = deltas[l][m]; + + for (n = 0; n < 3; n++) + p[n] = update_prob(d[n], p[n]); + } +} + +/* Counterpart to 6.3.7 read_coef_probs() */ +static void update_coef_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + int i, j, k; + + for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { + for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) + for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); k++) + update_coeff(deltas->coef[i][j][k], probs->coef[i][j][k]); + + if (deltas->tx_mode == i) + break; + } +} + +/* Counterpart to 6.3.8 read_skip_prob() */ +static void update_skip_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(probs->skip); i++) + probs->skip[i] = update_prob(deltas->skip[i], probs->skip[i]); +} + +/* Counterpart to 6.3.9 read_inter_mode_probs() */ +static void update_inter_mode_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(probs->inter_mode); i++) { + u8 *p = probs->inter_mode[i]; + const u8 *d = deltas->inter_mode[i]; + + p[0] = update_prob(d[0], p[0]); + p[1] = update_prob(d[1], p[1]); + p[2] = update_prob(d[2], p[2]); + } +} + +/* Counterpart to 6.3.10 read_interp_filter_probs() */ +static void update_interp_filter_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(probs->interp_filter); i++) { + u8 *p = probs->interp_filter[i]; + const u8 *d = deltas->interp_filter[i]; + + p[0] = update_prob(d[0], p[0]); + p[1] = update_prob(d[1], p[1]); + } +} + +/* Counterpart to 6.3.11 read_is_inter_probs() */ +static void update_is_inter_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(probs->is_inter); i++) + probs->is_inter[i] = update_prob(deltas->is_inter[i], probs->is_inter[i]); +} + +/* 6.3.12 frame_reference_mode() done entirely in userspace */ + +/* Counterpart to 6.3.13 frame_reference_mode_probs() */ +static void +update_frame_reference_mode_probs(unsigned int reference_mode, + struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas) +{ + int i; + + if (reference_mode == V4L2_VP9_REFERENCE_MODE_SELECT) + for (i = 0; i < ARRAY_SIZE(probs->comp_mode); i++) + probs->comp_mode[i] = update_prob(deltas->comp_mode[i], + probs->comp_mode[i]); + + if (reference_mode != V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE) + for (i = 0; i < ARRAY_SIZE(probs->single_ref); i++) { + u8 *p = probs->single_ref[i]; + const u8 *d = deltas->single_ref[i]; + + p[0] = update_prob(d[0], p[0]); + p[1] = update_prob(d[1], p[1]); + } + + if (reference_mode != V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE) + for (i = 0; i < ARRAY_SIZE(probs->comp_ref); i++) + probs->comp_ref[i] = update_prob(deltas->comp_ref[i], probs->comp_ref[i]); +} + +/* Counterpart to 6.3.14 read_y_mode_probs() */ +static void update_y_mode_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(probs->y_mode); i++) + for (j = 0; j < ARRAY_SIZE(probs->y_mode[0]); ++j) + probs->y_mode[i][j] = + update_prob(deltas->y_mode[i][j], probs->y_mode[i][j]); +} + +/* Counterpart to 6.3.15 read_partition_probs() */ +static void update_partition_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas) +{ + int i, j; + + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) { + u8 *p = probs->partition[i * 4 + j]; + const u8 *d = deltas->partition[i * 4 + j]; + + p[0] = update_prob(d[0], p[0]); + p[1] = update_prob(d[1], p[1]); + p[2] = update_prob(d[2], p[2]); + } +} + +static inline int update_mv_prob(int delta, int prob) +{ + if (!delta) + return prob; + + return delta; +} + +/* Counterpart to 6.3.16 mv_probs() */ +static void update_mv_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + u8 *p = probs->mv.joint; + const u8 *d = deltas->mv.joint; + unsigned int i, j; + + p[0] = update_mv_prob(d[0], p[0]); + p[1] = update_mv_prob(d[1], p[1]); + p[2] = update_mv_prob(d[2], p[2]); + + for (i = 0; i < ARRAY_SIZE(probs->mv.sign); i++) { + p = probs->mv.sign; + d = deltas->mv.sign; + p[i] = update_mv_prob(d[i], p[i]); + + p = probs->mv.classes[i]; + d = deltas->mv.classes[i]; + for (j = 0; j < ARRAY_SIZE(probs->mv.classes[0]); j++) + p[j] = update_mv_prob(d[j], p[j]); + + p = probs->mv.class0_bit; + d = deltas->mv.class0_bit; + p[i] = update_mv_prob(d[i], p[i]); + + p = probs->mv.bits[i]; + d = deltas->mv.bits[i]; + for (j = 0; j < ARRAY_SIZE(probs->mv.bits[0]); j++) + p[j] = update_mv_prob(d[j], p[j]); + + for (j = 0; j < ARRAY_SIZE(probs->mv.class0_fr[0]); j++) { + p = probs->mv.class0_fr[i][j]; + d = deltas->mv.class0_fr[i][j]; + + p[0] = update_mv_prob(d[0], p[0]); + p[1] = update_mv_prob(d[1], p[1]); + p[2] = update_mv_prob(d[2], p[2]); + } + + p = probs->mv.fr[i]; + d = deltas->mv.fr[i]; + for (j = 0; j < ARRAY_SIZE(probs->mv.fr[i]); j++) + p[j] = update_mv_prob(d[j], p[j]); + + if (dec_params->flags & V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV) { + p = probs->mv.class0_hp; + d = deltas->mv.class0_hp; + p[i] = update_mv_prob(d[i], p[i]); + + p = probs->mv.hp; + d = deltas->mv.hp; + p[i] = update_mv_prob(d[i], p[i]); + } + } +} + +/* Counterpart to 6.3 compressed_header(), but parsing has been done in userspace. */ +void v4l2_vp9_fw_update_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + if (deltas->tx_mode == V4L2_VP9_TX_MODE_SELECT) + update_tx_probs(probs, deltas); + + update_coef_probs(probs, deltas, dec_params); + + update_skip_probs(probs, deltas); + + if (dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME || + dec_params->flags & V4L2_VP9_FRAME_FLAG_INTRA_ONLY) + return; + + update_inter_mode_probs(probs, deltas); + + if (dec_params->interpolation_filter == V4L2_VP9_INTERP_FILTER_SWITCHABLE) + update_interp_filter_probs(probs, deltas); + + update_is_inter_probs(probs, deltas); + + update_frame_reference_mode_probs(dec_params->reference_mode, probs, deltas); + + update_y_mode_probs(probs, deltas); + + update_partition_probs(probs, deltas); + + update_mv_probs(probs, deltas, dec_params); +} +EXPORT_SYMBOL_GPL(v4l2_vp9_fw_update_probs); + +u8 v4l2_vp9_reset_frame_ctx(const struct v4l2_ctrl_vp9_frame *dec_params, + struct v4l2_vp9_frame_context *frame_context) +{ + int i; + + u8 fctx_idx = dec_params->frame_context_idx; + + if (dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME || + dec_params->flags & V4L2_VP9_FRAME_FLAG_INTRA_ONLY || + dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) { + /* + * setup_past_independence() + * We do nothing here. Instead of storing default probs in some intermediate + * location and then copying from that location to appropriate contexts + * in save_probs() below, we skip that step and save default probs directly + * to appropriate contexts. + */ + if (dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME || + dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT || + dec_params->reset_frame_context == V4L2_VP9_RESET_FRAME_CTX_ALL) + for (i = 0; i < 4; ++i) + /* save_probs(i) */ + memcpy(&frame_context[i], &v4l2_vp9_default_probs, + sizeof(v4l2_vp9_default_probs)); + else if (dec_params->reset_frame_context == V4L2_VP9_RESET_FRAME_CTX_SPEC) + /* save_probs(fctx_idx) */ + memcpy(&frame_context[fctx_idx], &v4l2_vp9_default_probs, + sizeof(v4l2_vp9_default_probs)); + fctx_idx = 0; + } + + return fctx_idx; +} +EXPORT_SYMBOL_GPL(v4l2_vp9_reset_frame_ctx); + +/* 8.4.1 Merge prob process */ +static u8 merge_prob(u8 pre_prob, u32 ct0, u32 ct1, u16 count_sat, u32 max_update_factor) +{ + u32 den, prob, count, factor; + + den = ct0 + ct1; + if (!den) { + /* + * prob = 128, count = 0, update_factor = 0 + * Round2's argument: pre_prob * 256 + * (pre_prob * 256 + 128) >> 8 == pre_prob + */ + return pre_prob; + } + + prob = clamp(((ct0 << 8) + (den >> 1)) / den, (u32)1, (u32)255); + count = min_t(u32, den, count_sat); + factor = fastdiv(max_update_factor * count, count_sat); + + /* + * Round2(pre_prob * (256 - factor) + prob * factor, 8) + * Round2(pre_prob * 256 + (prob - pre_prob) * factor, 8) + * (pre_prob * 256 >> 8) + (((prob - pre_prob) * factor + 128) >> 8) + */ + return pre_prob + (((prob - pre_prob) * factor + 128) >> 8); +} + +static inline u8 noncoef_merge_prob(u8 pre_prob, u32 ct0, u32 ct1) +{ + return merge_prob(pre_prob, ct0, ct1, 20, 128); +} + +/* 8.4.2 Merge probs process */ +/* + * merge_probs() is a recursive function in the spec. We avoid recursion in the kernel. + * That said, the "tree" parameter of merge_probs() controls how deep the recursion goes. + * It turns out that in all cases the recursive calls boil down to a short-ish series + * of merge_prob() invocations (note no "s"). + * + * Variant A + * --------- + * merge_probs(small_token_tree, 2): + * merge_prob(p[1], c[0], c[1] + c[2]) + * merge_prob(p[2], c[1], c[2]) + * + * Variant B + * --------- + * merge_probs(binary_tree, 0) or + * merge_probs(tx_size_8_tree, 0): + * merge_prob(p[0], c[0], c[1]) + * + * Variant C + * --------- + * merge_probs(inter_mode_tree, 0): + * merge_prob(p[0], c[2], c[1] + c[0] + c[3]) + * merge_prob(p[1], c[0], c[1] + c[3]) + * merge_prob(p[2], c[1], c[3]) + * + * Variant D + * --------- + * merge_probs(intra_mode_tree, 0): + * merge_prob(p[0], c[0], c[1] + ... + c[9]) + * merge_prob(p[1], c[9], c[1] + ... + c[8]) + * merge_prob(p[2], c[1], c[2] + ... + c[8]) + * merge_prob(p[3], c[2] + c[4] + c[5], c[3] + c[8] + c[6] + c[7]) + * merge_prob(p[4], c[2], c[4] + c[5]) + * merge_prob(p[5], c[4], c[5]) + * merge_prob(p[6], c[3], c[8] + c[6] + c[7]) + * merge_prob(p[7], c[8], c[6] + c[7]) + * merge_prob(p[8], c[6], c[7]) + * + * Variant E + * --------- + * merge_probs(partition_tree, 0) or + * merge_probs(tx_size_32_tree, 0) or + * merge_probs(mv_joint_tree, 0) or + * merge_probs(mv_fr_tree, 0): + * merge_prob(p[0], c[0], c[1] + c[2] + c[3]) + * merge_prob(p[1], c[1], c[2] + c[3]) + * merge_prob(p[2], c[2], c[3]) + * + * Variant F + * --------- + * merge_probs(interp_filter_tree, 0) or + * merge_probs(tx_size_16_tree, 0): + * merge_prob(p[0], c[0], c[1] + c[2]) + * merge_prob(p[1], c[1], c[2]) + * + * Variant G + * --------- + * merge_probs(mv_class_tree, 0): + * merge_prob(p[0], c[0], c[1] + ... + c[10]) + * merge_prob(p[1], c[1], c[2] + ... + c[10]) + * merge_prob(p[2], c[2] + c[3], c[4] + ... + c[10]) + * merge_prob(p[3], c[2], c[3]) + * merge_prob(p[4], c[4] + c[5], c[6] + ... + c[10]) + * merge_prob(p[5], c[4], c[5]) + * merge_prob(p[6], c[6], c[7] + ... + c[10]) + * merge_prob(p[7], c[7] + c[8], c[9] + c[10]) + * merge_prob(p[8], c[7], c[8]) + * merge_prob(p[9], c[9], [10]) + */ + +static inline void merge_probs_variant_a(u8 *p, const u32 *c, u16 count_sat, u32 update_factor) +{ + p[1] = merge_prob(p[1], c[0], c[1] + c[2], count_sat, update_factor); + p[2] = merge_prob(p[2], c[1], c[2], count_sat, update_factor); +} + +static inline void merge_probs_variant_b(u8 *p, const u32 *c, u16 count_sat, u32 update_factor) +{ + p[0] = merge_prob(p[0], c[0], c[1], count_sat, update_factor); +} + +static inline void merge_probs_variant_c(u8 *p, const u32 *c) +{ + p[0] = noncoef_merge_prob(p[0], c[2], c[1] + c[0] + c[3]); + p[1] = noncoef_merge_prob(p[1], c[0], c[1] + c[3]); + p[2] = noncoef_merge_prob(p[2], c[1], c[3]); +} + +static void merge_probs_variant_d(u8 *p, const u32 *c) +{ + u32 sum = 0, s2; + + sum = c[1] + c[2] + c[3] + c[4] + c[5] + c[6] + c[7] + c[8] + c[9]; + + p[0] = noncoef_merge_prob(p[0], c[0], sum); + sum -= c[9]; + p[1] = noncoef_merge_prob(p[1], c[9], sum); + sum -= c[1]; + p[2] = noncoef_merge_prob(p[2], c[1], sum); + s2 = c[2] + c[4] + c[5]; + sum -= s2; + p[3] = noncoef_merge_prob(p[3], s2, sum); + s2 -= c[2]; + p[4] = noncoef_merge_prob(p[4], c[2], s2); + p[5] = noncoef_merge_prob(p[5], c[4], c[5]); + sum -= c[3]; + p[6] = noncoef_merge_prob(p[6], c[3], sum); + sum -= c[8]; + p[7] = noncoef_merge_prob(p[7], c[8], sum); + p[8] = noncoef_merge_prob(p[8], c[6], c[7]); +} + +static inline void merge_probs_variant_e(u8 *p, const u32 *c) +{ + p[0] = noncoef_merge_prob(p[0], c[0], c[1] + c[2] + c[3]); + p[1] = noncoef_merge_prob(p[1], c[1], c[2] + c[3]); + p[2] = noncoef_merge_prob(p[2], c[2], c[3]); +} + +static inline void merge_probs_variant_f(u8 *p, const u32 *c) +{ + p[0] = noncoef_merge_prob(p[0], c[0], c[1] + c[2]); + p[1] = noncoef_merge_prob(p[1], c[1], c[2]); +} + +static void merge_probs_variant_g(u8 *p, const u32 *c) +{ + u32 sum; + + sum = c[1] + c[2] + c[3] + c[4] + c[5] + c[6] + c[7] + c[8] + c[9] + c[10]; + p[0] = noncoef_merge_prob(p[0], c[0], sum); + sum -= c[1]; + p[1] = noncoef_merge_prob(p[1], c[1], sum); + sum -= c[2] + c[3]; + p[2] = noncoef_merge_prob(p[2], c[2] + c[3], sum); + p[3] = noncoef_merge_prob(p[3], c[2], c[3]); + sum -= c[4] + c[5]; + p[4] = noncoef_merge_prob(p[4], c[4] + c[5], sum); + p[5] = noncoef_merge_prob(p[5], c[4], c[5]); + sum -= c[6]; + p[6] = noncoef_merge_prob(p[6], c[6], sum); + p[7] = noncoef_merge_prob(p[7], c[7] + c[8], c[9] + c[10]); + p[8] = noncoef_merge_prob(p[8], c[7], c[8]); + p[9] = noncoef_merge_prob(p[9], c[9], c[10]); +} + +/* 8.4.3 Coefficient probability adaptation process */ +static inline void adapt_probs_variant_a_coef(u8 *p, const u32 *c, u32 update_factor) +{ + merge_probs_variant_a(p, c, 24, update_factor); +} + +static inline void adapt_probs_variant_b_coef(u8 *p, const u32 *c, u32 update_factor) +{ + merge_probs_variant_b(p, c, 24, update_factor); +} + +static void _adapt_coeff(unsigned int i, unsigned int j, unsigned int k, + struct v4l2_vp9_frame_context *probs, + const struct v4l2_vp9_frame_symbol_counts *counts, + u32 uf) +{ + s32 l, m; + + for (l = 0; l < ARRAY_SIZE(probs->coef[0][0][0]); l++) { + for (m = 0; m < BAND_6(l); m++) { + u8 *p = probs->coef[i][j][k][l][m]; + const u32 counts_more_coefs[2] = { + *counts->eob[i][j][k][l][m][1], + *counts->eob[i][j][k][l][m][0] - *counts->eob[i][j][k][l][m][1], + }; + + adapt_probs_variant_a_coef(p, *counts->coeff[i][j][k][l][m], uf); + adapt_probs_variant_b_coef(p, counts_more_coefs, uf); + } + } +} + +static void _adapt_coef_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_vp9_frame_symbol_counts *counts, + unsigned int uf) +{ + unsigned int i, j, k; + + for (i = 0; i < ARRAY_SIZE(probs->coef); i++) + for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) + for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); k++) + _adapt_coeff(i, j, k, probs, counts, uf); +} + +void v4l2_vp9_adapt_coef_probs(struct v4l2_vp9_frame_context *probs, + struct v4l2_vp9_frame_symbol_counts *counts, + bool use_128, + bool frame_is_intra) +{ + if (frame_is_intra) { + _adapt_coef_probs(probs, counts, 112); + } else { + if (use_128) + _adapt_coef_probs(probs, counts, 128); + else + _adapt_coef_probs(probs, counts, 112); + } +} +EXPORT_SYMBOL_GPL(v4l2_vp9_adapt_coef_probs); + +/* 8.4.4 Non coefficient probability adaptation process, adapt_probs() */ +static inline void adapt_probs_variant_b(u8 *p, const u32 *c) +{ + merge_probs_variant_b(p, c, 20, 128); +} + +static inline void adapt_probs_variant_c(u8 *p, const u32 *c) +{ + merge_probs_variant_c(p, c); +} + +static inline void adapt_probs_variant_d(u8 *p, const u32 *c) +{ + merge_probs_variant_d(p, c); +} + +static inline void adapt_probs_variant_e(u8 *p, const u32 *c) +{ + merge_probs_variant_e(p, c); +} + +static inline void adapt_probs_variant_f(u8 *p, const u32 *c) +{ + merge_probs_variant_f(p, c); +} + +static inline void adapt_probs_variant_g(u8 *p, const u32 *c) +{ + merge_probs_variant_g(p, c); +} + +/* 8.4.4 Non coefficient probability adaptation process, adapt_prob() */ +static inline u8 adapt_prob(u8 prob, const u32 counts[2]) +{ + return noncoef_merge_prob(prob, counts[0], counts[1]); +} + +/* 8.4.4 Non coefficient probability adaptation process */ +void v4l2_vp9_adapt_noncoef_probs(struct v4l2_vp9_frame_context *probs, + struct v4l2_vp9_frame_symbol_counts *counts, + u8 reference_mode, u8 interpolation_filter, u8 tx_mode, + u32 flags) +{ + unsigned int i, j; + + for (i = 0; i < ARRAY_SIZE(probs->is_inter); i++) + probs->is_inter[i] = adapt_prob(probs->is_inter[i], (*counts->intra_inter)[i]); + + for (i = 0; i < ARRAY_SIZE(probs->comp_mode); i++) + probs->comp_mode[i] = adapt_prob(probs->comp_mode[i], (*counts->comp)[i]); + + for (i = 0; i < ARRAY_SIZE(probs->comp_ref); i++) + probs->comp_ref[i] = adapt_prob(probs->comp_ref[i], (*counts->comp_ref)[i]); + + if (reference_mode != V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE) + for (i = 0; i < ARRAY_SIZE(probs->single_ref); i++) + for (j = 0; j < ARRAY_SIZE(probs->single_ref[0]); j++) + probs->single_ref[i][j] = adapt_prob(probs->single_ref[i][j], + (*counts->single_ref)[i][j]); + + for (i = 0; i < ARRAY_SIZE(probs->inter_mode); i++) + adapt_probs_variant_c(probs->inter_mode[i], (*counts->mv_mode)[i]); + + for (i = 0; i < ARRAY_SIZE(probs->y_mode); i++) + adapt_probs_variant_d(probs->y_mode[i], (*counts->y_mode)[i]); + + for (i = 0; i < ARRAY_SIZE(probs->uv_mode); i++) + adapt_probs_variant_d(probs->uv_mode[i], (*counts->uv_mode)[i]); + + for (i = 0; i < ARRAY_SIZE(probs->partition); i++) + adapt_probs_variant_e(probs->partition[i], (*counts->partition)[i]); + + for (i = 0; i < ARRAY_SIZE(probs->skip); i++) + probs->skip[i] = adapt_prob(probs->skip[i], (*counts->skip)[i]); + + if (interpolation_filter == V4L2_VP9_INTERP_FILTER_SWITCHABLE) + for (i = 0; i < ARRAY_SIZE(probs->interp_filter); i++) + adapt_probs_variant_f(probs->interp_filter[i], (*counts->filter)[i]); + + if (tx_mode == V4L2_VP9_TX_MODE_SELECT) + for (i = 0; i < ARRAY_SIZE(probs->tx8); i++) { + adapt_probs_variant_b(probs->tx8[i], (*counts->tx8p)[i]); + adapt_probs_variant_f(probs->tx16[i], (*counts->tx16p)[i]); + adapt_probs_variant_e(probs->tx32[i], (*counts->tx32p)[i]); + } + + adapt_probs_variant_e(probs->mv.joint, *counts->mv_joint); + + for (i = 0; i < ARRAY_SIZE(probs->mv.sign); i++) { + probs->mv.sign[i] = adapt_prob(probs->mv.sign[i], (*counts->sign)[i]); + + adapt_probs_variant_g(probs->mv.classes[i], (*counts->classes)[i]); + + probs->mv.class0_bit[i] = adapt_prob(probs->mv.class0_bit[i], (*counts->class0)[i]); + + for (j = 0; j < ARRAY_SIZE(probs->mv.bits[0]); j++) + probs->mv.bits[i][j] = adapt_prob(probs->mv.bits[i][j], + (*counts->bits)[i][j]); + + for (j = 0; j < ARRAY_SIZE(probs->mv.class0_fr[0]); j++) + adapt_probs_variant_e(probs->mv.class0_fr[i][j], + (*counts->class0_fp)[i][j]); + + adapt_probs_variant_e(probs->mv.fr[i], (*counts->fp)[i]); + + if (!(flags & V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV)) + continue; + + probs->mv.class0_hp[i] = adapt_prob(probs->mv.class0_hp[i], + (*counts->class0_hp)[i]); + + probs->mv.hp[i] = adapt_prob(probs->mv.hp[i], (*counts->hp)[i]); + } +} +EXPORT_SYMBOL_GPL(v4l2_vp9_adapt_noncoef_probs); + +bool +v4l2_vp9_seg_feat_enabled(const u8 *feature_enabled, + unsigned int feature, + unsigned int segid) +{ + u8 mask = V4L2_VP9_SEGMENT_FEATURE_ENABLED(feature); + + return !!(feature_enabled[segid] & mask); +} +EXPORT_SYMBOL_GPL(v4l2_vp9_seg_feat_enabled); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("V4L2 VP9 Helpers"); +MODULE_AUTHOR("Andrzej Pietrasiewicz "); diff --git a/include/media/v4l2-vp9.h b/include/media/v4l2-vp9.h new file mode 100644 index 000000000000..05478ad6d4ab --- /dev/null +++ b/include/media/v4l2-vp9.h @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Helper functions for vp9 codecs. + * + * Copyright (c) 2021 Collabora, Ltd. + * + * Author: Andrzej Pietrasiewicz + */ + +#ifndef _MEDIA_V4L2_VP9_H +#define _MEDIA_V4L2_VP9_H + +#include + +/** + * struct v4l2_vp9_frame_mv_context - motion vector-related probabilities + * + * @joint: motion vector joint probabilities. + * @sign: motion vector sign probabilities. + * @classes: motion vector class probabilities. + * @class0_bit: motion vector class0 bit probabilities. + * @bits: motion vector bits probabilities. + * @class0_fr: motion vector class0 fractional bit probabilities. + * @fr: motion vector fractional bit probabilities. + * @class0_hp: motion vector class0 high precision fractional bit probabilities. + * @hp: motion vector high precision fractional bit probabilities. + * + * A member of v4l2_vp9_frame_context. + */ +struct v4l2_vp9_frame_mv_context { + u8 joint[3]; + u8 sign[2]; + u8 classes[2][10]; + u8 class0_bit[2]; + u8 bits[2][10]; + u8 class0_fr[2][2][3]; + u8 fr[2][3]; + u8 class0_hp[2]; + u8 hp[2]; +}; + +/** + * struct v4l2_vp9_frame_context - frame probabilities, including motion-vector related + * + * @tx8: TX 8x8 probabilities. + * @tx16: TX 16x16 probabilities. + * @tx32: TX 32x32 probabilities. + * @coef: coefficient probabilities. + * @skip: skip probabilities. + * @inter_mode: inter mode probabilities. + * @interp_filter: interpolation filter probabilities. + * @is_inter: is inter-block probabilities. + * @comp_mode: compound prediction mode probabilities. + * @single_ref: single ref probabilities. + * @comp_ref: compound ref probabilities. + * @y_mode: Y prediction mode probabilities. + * @uv_mode: UV prediction mode probabilities. + * @partition: partition probabilities. + * @mv: motion vector probabilities. + * + * Drivers which need to keep track of frame context(s) can use this struct. + * The members correspond to probability tables, which are specified only implicitly in the + * vp9 spec. Section 10.5 "Default probability tables" contains all the types of involved + * tables, i.e. the actual tables are of the same kind, and when they are reset (which is + * mandated by the spec sometimes) they are overwritten with values from the default tables. + */ +struct v4l2_vp9_frame_context { + u8 tx8[2][1]; + u8 tx16[2][2]; + u8 tx32[2][3]; + u8 coef[4][2][2][6][6][3]; + u8 skip[3]; + u8 inter_mode[7][3]; + u8 interp_filter[4][2]; + u8 is_inter[4]; + u8 comp_mode[5]; + u8 single_ref[5][2]; + u8 comp_ref[5]; + u8 y_mode[4][9]; + u8 uv_mode[10][9]; + u8 partition[16][3]; + + struct v4l2_vp9_frame_mv_context mv; +}; + +/** + * struct v4l2_vp9_frame_symbol_counts - pointers to arrays of symbol counts + * + * @partition: partition counts. + * @skip: skip counts. + * @intra_inter: is inter-block counts. + * @tx32p: TX32 counts. + * @tx16p: TX16 counts. + * @tx8p: TX8 counts. + * @y_mode: Y prediction mode counts. + * @uv_mode: UV prediction mode counts. + * @comp: compound prediction mode counts. + * @comp_ref: compound ref counts. + * @single_ref: single ref counts. + * @mv_mode: inter mode counts. + * @filter: interpolation filter counts. + * @mv_joint: motion vector joint counts. + * @sign: motion vector sign counts. + * @classes: motion vector class counts. + * @class0: motion vector class0 bit counts. + * @bits: motion vector bits counts. + * @class0_fp: motion vector class0 fractional bit counts. + * @fp: motion vector fractional bit counts. + * @class0_hp: motion vector class0 high precision fractional bit counts. + * @hp: motion vector high precision fractional bit counts. + * @coeff: coefficient counts. + * @eob: eob counts + * + * The fields correspond to what is specified in section 8.3 "Clear counts process" of the spec. + * Different pieces of hardware can report the counts in different order, so we cannot rely on + * simply overlaying a struct on a relevant block of memory. Instead we provide pointers to + * arrays or array of pointers to arrays in case of coeff, or array of pointers for eob. + */ +struct v4l2_vp9_frame_symbol_counts { + u32 (*partition)[16][4]; + u32 (*skip)[3][2]; + u32 (*intra_inter)[4][2]; + u32 (*tx32p)[2][4]; + u32 (*tx16p)[2][4]; + u32 (*tx8p)[2][2]; + u32 (*y_mode)[4][10]; + u32 (*uv_mode)[10][10]; + u32 (*comp)[5][2]; + u32 (*comp_ref)[5][2]; + u32 (*single_ref)[5][2][2]; + u32 (*mv_mode)[7][4]; + u32 (*filter)[4][3]; + u32 (*mv_joint)[4]; + u32 (*sign)[2][2]; + u32 (*classes)[2][11]; + u32 (*class0)[2][2]; + u32 (*bits)[2][10][2]; + u32 (*class0_fp)[2][2][4]; + u32 (*fp)[2][4]; + u32 (*class0_hp)[2][2]; + u32 (*hp)[2][2]; + u32 (*coeff[4][2][2][6][6])[3]; + u32 *eob[4][2][2][6][6][2]; +}; + +extern const u8 v4l2_vp9_kf_y_mode_prob[10][10][9]; /* Section 10.4 of the spec */ +extern const u8 v4l2_vp9_kf_partition_probs[16][3]; /* Section 10.4 of the spec */ +extern const u8 v4l2_vp9_kf_uv_mode_prob[10][9]; /* Section 10.4 of the spec */ +extern const struct v4l2_vp9_frame_context v4l2_vp9_default_probs; /* Section 10.5 of the spec */ + +/** + * v4l2_vp9_fw_update_probs() - Perform forward update of vp9 probabilities + * + * @probs: current probabilities values + * @deltas: delta values from compressed header + * @dec_params: vp9 frame decoding parameters + * + * This function performs forward updates of probabilities for the vp9 boolean decoder. + * The frame header can contain a directive to update the probabilities (deltas), if so, then + * the deltas are provided in the header, too. The userspace parses those and passes the said + * deltas struct to the kernel. + */ +void v4l2_vp9_fw_update_probs(struct v4l2_vp9_frame_context *probs, + const struct v4l2_ctrl_vp9_compressed_hdr *deltas, + const struct v4l2_ctrl_vp9_frame *dec_params); + +/** + * v4l2_vp9_reset_frame_ctx() - Reset appropriate frame context + * + * @dec_params: vp9 frame decoding parameters + * @frame_context: array of the 4 frame contexts + * + * This function resets appropriate frame contexts, based on what's in dec_params. + * + * Returns the frame context index after the update, which might be reset to zero if + * mandated by the spec. + */ +u8 v4l2_vp9_reset_frame_ctx(const struct v4l2_ctrl_vp9_frame *dec_params, + struct v4l2_vp9_frame_context *frame_context); + +/** + * v4l2_vp9_adapt_coef_probs() - Perform backward update of vp9 coefficients probabilities + * + * @probs: current probabilities values + * @counts: values of symbol counts after the current frame has been decoded + * @use_128: flag to request that 128 is used as update factor if true, otherwise 112 is used + * @frame_is_intra: flag indicating that FrameIsIntra is true + * + * This function performs backward updates of coefficients probabilities for the vp9 boolean + * decoder. After a frame has been decoded the counts of how many times a given symbol has + * occurred are known and are used to update the probability of each symbol. + */ +void v4l2_vp9_adapt_coef_probs(struct v4l2_vp9_frame_context *probs, + struct v4l2_vp9_frame_symbol_counts *counts, + bool use_128, + bool frame_is_intra); + +/** + * v4l2_vp9_adapt_noncoef_probs() - Perform backward update of vp9 non-coefficients probabilities + * + * @probs: current probabilities values + * @counts: values of symbol counts after the current frame has been decoded + * @reference_mode: specifies the type of inter prediction to be used. See + * &v4l2_vp9_reference_mode for more details + * @interpolation_filter: specifies the filter selection used for performing inter prediction. + * See &v4l2_vp9_interpolation_filter for more details + * @tx_mode: specifies the TX mode. See &v4l2_vp9_tx_mode for more details + * @flags: combination of V4L2_VP9_FRAME_FLAG_* flags + * + * This function performs backward updates of non-coefficients probabilities for the vp9 boolean + * decoder. After a frame has been decoded the counts of how many times a given symbol has + * occurred are known and are used to update the probability of each symbol. + */ +void v4l2_vp9_adapt_noncoef_probs(struct v4l2_vp9_frame_context *probs, + struct v4l2_vp9_frame_symbol_counts *counts, + u8 reference_mode, u8 interpolation_filter, u8 tx_mode, + u32 flags); + +/** + * v4l2_vp9_seg_feat_enabled() - Check if a segmentation feature is enabled + * + * @feature_enabled: array of 8-bit flags (for all segments) + * @feature: id of the feature to check + * @segid: id of the segment to look up + * + * This function returns true if a given feature is active in a given segment. + */ +bool +v4l2_vp9_seg_feat_enabled(const u8 *feature_enabled, + unsigned int feature, + unsigned int segid); + +#endif /* _MEDIA_V4L2_VP9_H */ From f25709c4ff151fbc7dc2e0b7cf5962767a093f68 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Wed, 17 Nov 2021 11:52:56 +0000 Subject: [PATCH 189/397] media: rkvdec: Add the VP9 backend The Rockchip VDEC supports VP9 profile 0 up to 4096x2304@30fps. Add a backend for this new format. Signed-off-by: Boris Brezillon Signed-off-by: Ezequiel Garcia Signed-off-by: Adrian Ratiu Co-developed-by: Andrzej Pietrasiewicz Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/rkvdec/Kconfig | 1 + drivers/staging/media/rkvdec/Makefile | 2 +- drivers/staging/media/rkvdec/rkvdec-vp9.c | 1072 +++++++++++++++++++++ drivers/staging/media/rkvdec/rkvdec.c | 41 +- drivers/staging/media/rkvdec/rkvdec.h | 12 +- 5 files changed, 1121 insertions(+), 7 deletions(-) create mode 100644 drivers/staging/media/rkvdec/rkvdec-vp9.c diff --git a/drivers/staging/media/rkvdec/Kconfig b/drivers/staging/media/rkvdec/Kconfig index c02199b5e0fd..dc7292f346fa 100644 --- a/drivers/staging/media/rkvdec/Kconfig +++ b/drivers/staging/media/rkvdec/Kconfig @@ -9,6 +9,7 @@ config VIDEO_ROCKCHIP_VDEC select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV select V4L2_H264 + select V4L2_VP9 help Support for the Rockchip Video Decoder IP present on Rockchip SoCs, which accelerates video decoding. diff --git a/drivers/staging/media/rkvdec/Makefile b/drivers/staging/media/rkvdec/Makefile index c08fed0a39f9..cb86b429cfaa 100644 --- a/drivers/staging/media/rkvdec/Makefile +++ b/drivers/staging/media/rkvdec/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rockchip-vdec.o -rockchip-vdec-y += rkvdec.o rkvdec-h264.o +rockchip-vdec-y += rkvdec.o rkvdec-h264.o rkvdec-vp9.o diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c new file mode 100644 index 000000000000..311a12656072 --- /dev/null +++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c @@ -0,0 +1,1072 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip Video Decoder VP9 backend + * + * Copyright (C) 2019 Collabora, Ltd. + * Boris Brezillon + * Copyright (C) 2021 Collabora, Ltd. + * Andrzej Pietrasiewicz + * + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Alpha Lin + */ + +/* + * For following the vp9 spec please start reading this driver + * code from rkvdec_vp9_run() followed by rkvdec_vp9_done(). + */ + +#include +#include +#include +#include + +#include "rkvdec.h" +#include "rkvdec-regs.h" + +#define RKVDEC_VP9_PROBE_SIZE 4864 +#define RKVDEC_VP9_COUNT_SIZE 13232 +#define RKVDEC_VP9_MAX_SEGMAP_SIZE 73728 + +struct rkvdec_vp9_intra_mode_probs { + u8 y_mode[105]; + u8 uv_mode[23]; +}; + +struct rkvdec_vp9_intra_only_frame_probs { + u8 coef_intra[4][2][128]; + struct rkvdec_vp9_intra_mode_probs intra_mode[10]; +}; + +struct rkvdec_vp9_inter_frame_probs { + u8 y_mode[4][9]; + u8 comp_mode[5]; + u8 comp_ref[5]; + u8 single_ref[5][2]; + u8 inter_mode[7][3]; + u8 interp_filter[4][2]; + u8 padding0[11]; + u8 coef[2][4][2][128]; + u8 uv_mode_0_2[3][9]; + u8 padding1[5]; + u8 uv_mode_3_5[3][9]; + u8 padding2[5]; + u8 uv_mode_6_8[3][9]; + u8 padding3[5]; + u8 uv_mode_9[9]; + u8 padding4[7]; + u8 padding5[16]; + struct { + u8 joint[3]; + u8 sign[2]; + u8 classes[2][10]; + u8 class0_bit[2]; + u8 bits[2][10]; + u8 class0_fr[2][2][3]; + u8 fr[2][3]; + u8 class0_hp[2]; + u8 hp[2]; + } mv; +}; + +struct rkvdec_vp9_probs { + u8 partition[16][3]; + u8 pred[3]; + u8 tree[7]; + u8 skip[3]; + u8 tx32[2][3]; + u8 tx16[2][2]; + u8 tx8[2][1]; + u8 is_inter[4]; + /* 128 bit alignment */ + u8 padding0[3]; + union { + struct rkvdec_vp9_inter_frame_probs inter; + struct rkvdec_vp9_intra_only_frame_probs intra_only; + }; +}; + +/* Data structure describing auxiliary buffer format. */ +struct rkvdec_vp9_priv_tbl { + struct rkvdec_vp9_probs probs; + u8 segmap[2][RKVDEC_VP9_MAX_SEGMAP_SIZE]; +}; + +struct rkvdec_vp9_refs_counts { + u32 eob[2]; + u32 coeff[3]; +}; + +struct rkvdec_vp9_inter_frame_symbol_counts { + u32 partition[16][4]; + u32 skip[3][2]; + u32 inter[4][2]; + u32 tx32p[2][4]; + u32 tx16p[2][4]; + u32 tx8p[2][2]; + u32 y_mode[4][10]; + u32 uv_mode[10][10]; + u32 comp[5][2]; + u32 comp_ref[5][2]; + u32 single_ref[5][2][2]; + u32 mv_mode[7][4]; + u32 filter[4][3]; + u32 mv_joint[4]; + u32 sign[2][2]; + /* add 1 element for align */ + u32 classes[2][11 + 1]; + u32 class0[2][2]; + u32 bits[2][10][2]; + u32 class0_fp[2][2][4]; + u32 fp[2][4]; + u32 class0_hp[2][2]; + u32 hp[2][2]; + struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6]; +}; + +struct rkvdec_vp9_intra_frame_symbol_counts { + u32 partition[4][4][4]; + u32 skip[3][2]; + u32 intra[4][2]; + u32 tx32p[2][4]; + u32 tx16p[2][4]; + u32 tx8p[2][2]; + struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6]; +}; + +struct rkvdec_vp9_run { + struct rkvdec_run base; + const struct v4l2_ctrl_vp9_frame *decode_params; +}; + +struct rkvdec_vp9_frame_info { + u32 valid : 1; + u32 segmapid : 1; + u32 frame_context_idx : 2; + u32 reference_mode : 2; + u32 tx_mode : 3; + u32 interpolation_filter : 3; + u32 flags; + u64 timestamp; + struct v4l2_vp9_segmentation seg; + struct v4l2_vp9_loop_filter lf; +}; + +struct rkvdec_vp9_ctx { + struct rkvdec_aux_buf priv_tbl; + struct rkvdec_aux_buf count_tbl; + struct v4l2_vp9_frame_symbol_counts inter_cnts; + struct v4l2_vp9_frame_symbol_counts intra_cnts; + struct v4l2_vp9_frame_context probability_tables; + struct v4l2_vp9_frame_context frame_context[4]; + struct rkvdec_vp9_frame_info cur; + struct rkvdec_vp9_frame_info last; +}; + +static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane) +{ + unsigned int idx = 0, byte_count = 0; + int k, m, n; + u8 p; + + for (k = 0; k < 6; k++) { + for (m = 0; m < 6; m++) { + for (n = 0; n < 3; n++) { + p = coef[k][m][n]; + coeff_plane[idx++] = p; + byte_count++; + if (byte_count == 27) { + idx += 5; + byte_count = 0; + } + } + } + } +} + +static void init_intra_only_probs(struct rkvdec_ctx *ctx, + const struct rkvdec_vp9_run *run) +{ + struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; + struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; + struct rkvdec_vp9_intra_only_frame_probs *rkprobs; + const struct v4l2_vp9_frame_context *probs; + unsigned int i, j, k; + + rkprobs = &tbl->probs.intra_only; + probs = &vp9_ctx->probability_tables; + + /* + * intra only 149 x 128 bits ,aligned to 152 x 128 bits coeff related + * prob 64 x 128 bits + */ + for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { + for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) + write_coeff_plane(probs->coef[i][j][0], + rkprobs->coef_intra[i][j]); + } + + /* intra mode prob 80 x 128 bits */ + for (i = 0; i < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob); i++) { + unsigned int byte_count = 0; + int idx = 0; + + /* vp9_kf_y_mode_prob */ + for (j = 0; j < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob[0]); j++) { + for (k = 0; k < ARRAY_SIZE(v4l2_vp9_kf_y_mode_prob[0][0]); + k++) { + u8 val = v4l2_vp9_kf_y_mode_prob[i][j][k]; + + rkprobs->intra_mode[i].y_mode[idx++] = val; + byte_count++; + if (byte_count == 27) { + byte_count = 0; + idx += 5; + } + } + } + + } + + for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob); ++i) { + const u8 *ptr = (const u8 *)v4l2_vp9_kf_uv_mode_prob; + + rkprobs->intra_mode[i / 23].uv_mode[i % 23] = ptr[i]; + } +} + +static void init_inter_probs(struct rkvdec_ctx *ctx, + const struct rkvdec_vp9_run *run) +{ + struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; + struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; + struct rkvdec_vp9_inter_frame_probs *rkprobs; + const struct v4l2_vp9_frame_context *probs; + unsigned int i, j, k; + + rkprobs = &tbl->probs.inter; + probs = &vp9_ctx->probability_tables; + + /* + * inter probs + * 151 x 128 bits, aligned to 152 x 128 bits + * inter only + * intra_y_mode & inter_block info 6 x 128 bits + */ + + memcpy(rkprobs->y_mode, probs->y_mode, sizeof(rkprobs->y_mode)); + memcpy(rkprobs->comp_mode, probs->comp_mode, + sizeof(rkprobs->comp_mode)); + memcpy(rkprobs->comp_ref, probs->comp_ref, + sizeof(rkprobs->comp_ref)); + memcpy(rkprobs->single_ref, probs->single_ref, + sizeof(rkprobs->single_ref)); + memcpy(rkprobs->inter_mode, probs->inter_mode, + sizeof(rkprobs->inter_mode)); + memcpy(rkprobs->interp_filter, probs->interp_filter, + sizeof(rkprobs->interp_filter)); + + /* 128 x 128 bits coeff related */ + for (i = 0; i < ARRAY_SIZE(probs->coef); i++) { + for (j = 0; j < ARRAY_SIZE(probs->coef[0]); j++) { + for (k = 0; k < ARRAY_SIZE(probs->coef[0][0]); k++) + write_coeff_plane(probs->coef[i][j][k], + rkprobs->coef[k][i][j]); + } + } + + /* intra uv mode 6 x 128 */ + memcpy(rkprobs->uv_mode_0_2, &probs->uv_mode[0], + sizeof(rkprobs->uv_mode_0_2)); + memcpy(rkprobs->uv_mode_3_5, &probs->uv_mode[3], + sizeof(rkprobs->uv_mode_3_5)); + memcpy(rkprobs->uv_mode_6_8, &probs->uv_mode[6], + sizeof(rkprobs->uv_mode_6_8)); + memcpy(rkprobs->uv_mode_9, &probs->uv_mode[9], + sizeof(rkprobs->uv_mode_9)); + + /* mv related 6 x 128 */ + memcpy(rkprobs->mv.joint, probs->mv.joint, + sizeof(rkprobs->mv.joint)); + memcpy(rkprobs->mv.sign, probs->mv.sign, + sizeof(rkprobs->mv.sign)); + memcpy(rkprobs->mv.classes, probs->mv.classes, + sizeof(rkprobs->mv.classes)); + memcpy(rkprobs->mv.class0_bit, probs->mv.class0_bit, + sizeof(rkprobs->mv.class0_bit)); + memcpy(rkprobs->mv.bits, probs->mv.bits, + sizeof(rkprobs->mv.bits)); + memcpy(rkprobs->mv.class0_fr, probs->mv.class0_fr, + sizeof(rkprobs->mv.class0_fr)); + memcpy(rkprobs->mv.fr, probs->mv.fr, + sizeof(rkprobs->mv.fr)); + memcpy(rkprobs->mv.class0_hp, probs->mv.class0_hp, + sizeof(rkprobs->mv.class0_hp)); + memcpy(rkprobs->mv.hp, probs->mv.hp, + sizeof(rkprobs->mv.hp)); +} + +static void init_probs(struct rkvdec_ctx *ctx, + const struct rkvdec_vp9_run *run) +{ + const struct v4l2_ctrl_vp9_frame *dec_params; + struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; + struct rkvdec_vp9_priv_tbl *tbl = vp9_ctx->priv_tbl.cpu; + struct rkvdec_vp9_probs *rkprobs = &tbl->probs; + const struct v4l2_vp9_segmentation *seg; + const struct v4l2_vp9_frame_context *probs; + bool intra_only; + + dec_params = run->decode_params; + probs = &vp9_ctx->probability_tables; + seg = &dec_params->seg; + + memset(rkprobs, 0, sizeof(*rkprobs)); + + intra_only = !!(dec_params->flags & + (V4L2_VP9_FRAME_FLAG_KEY_FRAME | + V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); + + /* sb info 5 x 128 bit */ + memcpy(rkprobs->partition, + intra_only ? v4l2_vp9_kf_partition_probs : probs->partition, + sizeof(rkprobs->partition)); + + memcpy(rkprobs->pred, seg->pred_probs, sizeof(rkprobs->pred)); + memcpy(rkprobs->tree, seg->tree_probs, sizeof(rkprobs->tree)); + memcpy(rkprobs->skip, probs->skip, sizeof(rkprobs->skip)); + memcpy(rkprobs->tx32, probs->tx32, sizeof(rkprobs->tx32)); + memcpy(rkprobs->tx16, probs->tx16, sizeof(rkprobs->tx16)); + memcpy(rkprobs->tx8, probs->tx8, sizeof(rkprobs->tx8)); + memcpy(rkprobs->is_inter, probs->is_inter, sizeof(rkprobs->is_inter)); + + if (intra_only) + init_intra_only_probs(ctx, run); + else + init_inter_probs(ctx, run); +} + +struct rkvdec_vp9_ref_reg { + u32 reg_frm_size; + u32 reg_hor_stride; + u32 reg_y_stride; + u32 reg_yuv_stride; + u32 reg_ref_base; +}; + +static struct rkvdec_vp9_ref_reg ref_regs[] = { + { + .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(0), + .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(0), + .reg_y_stride = RKVDEC_VP9_LAST_FRAME_YSTRIDE, + .reg_yuv_stride = RKVDEC_VP9_LAST_FRAME_YUVSTRIDE, + .reg_ref_base = RKVDEC_REG_VP9_LAST_FRAME_BASE, + }, + { + .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(1), + .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(1), + .reg_y_stride = RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE, + .reg_yuv_stride = 0, + .reg_ref_base = RKVDEC_REG_VP9_GOLDEN_FRAME_BASE, + }, + { + .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(2), + .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(2), + .reg_y_stride = RKVDEC_VP9_ALTREF_FRAME_YSTRIDE, + .reg_yuv_stride = 0, + .reg_ref_base = RKVDEC_REG_VP9_ALTREF_FRAME_BASE, + } +}; + +static struct rkvdec_decoded_buffer * +get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp) +{ + struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; + struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; + int buf_idx; + + /* + * If a ref is unused or invalid, address of current destination + * buffer is returned. + */ + buf_idx = vb2_find_timestamp(cap_q, timestamp, 0); + if (buf_idx < 0) + return vb2_to_rkvdec_decoded_buf(&dst->vb2_buf); + + return vb2_to_rkvdec_decoded_buf(vb2_get_buffer(cap_q, buf_idx)); +} + +static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf) +{ + unsigned int aligned_pitch, aligned_height, yuv_len; + + aligned_height = round_up(buf->vp9.height, 64); + aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8; + yuv_len = (aligned_height * aligned_pitch * 3) / 2; + + return vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0) + + yuv_len; +} + +static void config_ref_registers(struct rkvdec_ctx *ctx, + const struct rkvdec_vp9_run *run, + struct rkvdec_decoded_buffer *ref_buf, + struct rkvdec_vp9_ref_reg *ref_reg) +{ + unsigned int aligned_pitch, aligned_height, y_len, yuv_len; + struct rkvdec_dev *rkvdec = ctx->dev; + + aligned_height = round_up(ref_buf->vp9.height, 64); + writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(ref_buf->vp9.width) | + RKVDEC_VP9_FRAMEHEIGHT(ref_buf->vp9.height), + rkvdec->regs + ref_reg->reg_frm_size); + + writel_relaxed(vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0), + rkvdec->regs + ref_reg->reg_ref_base); + + if (&ref_buf->base.vb == run->base.bufs.dst) + return; + + aligned_pitch = round_up(ref_buf->vp9.width * ref_buf->vp9.bit_depth, 512) / 8; + y_len = aligned_height * aligned_pitch; + yuv_len = (y_len * 3) / 2; + + writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) | + RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16), + rkvdec->regs + ref_reg->reg_hor_stride); + writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16), + rkvdec->regs + ref_reg->reg_y_stride); + + if (!ref_reg->reg_yuv_stride) + return; + + writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16), + rkvdec->regs + ref_reg->reg_yuv_stride); +} + +static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid) +{ + struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; + const struct v4l2_vp9_segmentation *seg; + struct rkvdec_dev *rkvdec = ctx->dev; + s16 feature_val; + int feature_id; + u32 val = 0; + + seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg; + feature_id = V4L2_VP9_SEG_LVL_ALT_Q; + if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) { + feature_val = seg->feature_data[segid][feature_id]; + val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) | + RKVDEC_SEGID_FRAME_QP_DELTA(feature_val); + } + + feature_id = V4L2_VP9_SEG_LVL_ALT_L; + if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) { + feature_val = seg->feature_data[segid][feature_id]; + val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) | + RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val); + } + + feature_id = V4L2_VP9_SEG_LVL_REF_FRAME; + if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) { + feature_val = seg->feature_data[segid][feature_id]; + val |= RKVDEC_SEGID_REFERINFO_EN(1) | + RKVDEC_SEGID_REFERINFO(feature_val); + } + + feature_id = V4L2_VP9_SEG_LVL_SKIP; + if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid)) + val |= RKVDEC_SEGID_FRAME_SKIP_EN(1); + + if (!segid && + (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE)) + val |= RKVDEC_SEGID_ABS_DELTA(1); + + writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid)); +} + +static void update_dec_buf_info(struct rkvdec_decoded_buffer *buf, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + buf->vp9.width = dec_params->frame_width_minus_1 + 1; + buf->vp9.height = dec_params->frame_height_minus_1 + 1; + buf->vp9.bit_depth = dec_params->bit_depth; +} + +static void update_ctx_cur_info(struct rkvdec_vp9_ctx *vp9_ctx, + struct rkvdec_decoded_buffer *buf, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + vp9_ctx->cur.valid = true; + vp9_ctx->cur.reference_mode = dec_params->reference_mode; + vp9_ctx->cur.interpolation_filter = dec_params->interpolation_filter; + vp9_ctx->cur.flags = dec_params->flags; + vp9_ctx->cur.timestamp = buf->base.vb.vb2_buf.timestamp; + vp9_ctx->cur.seg = dec_params->seg; + vp9_ctx->cur.lf = dec_params->lf; +} + +static void update_ctx_last_info(struct rkvdec_vp9_ctx *vp9_ctx) +{ + vp9_ctx->last = vp9_ctx->cur; +} + +static void config_registers(struct rkvdec_ctx *ctx, + const struct rkvdec_vp9_run *run) +{ + unsigned int y_len, uv_len, yuv_len, bit_depth, aligned_height, aligned_pitch, stream_len; + const struct v4l2_ctrl_vp9_frame *dec_params; + struct rkvdec_decoded_buffer *ref_bufs[3]; + struct rkvdec_decoded_buffer *dst, *last, *mv_ref; + struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; + u32 val, last_frame_info = 0; + const struct v4l2_vp9_segmentation *seg; + struct rkvdec_dev *rkvdec = ctx->dev; + dma_addr_t addr; + bool intra_only; + unsigned int i; + + dec_params = run->decode_params; + dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf); + ref_bufs[0] = get_ref_buf(ctx, &dst->base.vb, dec_params->last_frame_ts); + ref_bufs[1] = get_ref_buf(ctx, &dst->base.vb, dec_params->golden_frame_ts); + ref_bufs[2] = get_ref_buf(ctx, &dst->base.vb, dec_params->alt_frame_ts); + + if (vp9_ctx->last.valid) + last = get_ref_buf(ctx, &dst->base.vb, vp9_ctx->last.timestamp); + else + last = dst; + + update_dec_buf_info(dst, dec_params); + update_ctx_cur_info(vp9_ctx, dst, dec_params); + seg = &dec_params->seg; + + intra_only = !!(dec_params->flags & + (V4L2_VP9_FRAME_FLAG_KEY_FRAME | + V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); + + writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9), + rkvdec->regs + RKVDEC_REG_SYSCTRL); + + bit_depth = dec_params->bit_depth; + aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64); + + aligned_pitch = round_up(ctx->decoded_fmt.fmt.pix_mp.width * + bit_depth, + 512) / 8; + y_len = aligned_height * aligned_pitch; + uv_len = y_len / 2; + yuv_len = y_len + uv_len; + + writel_relaxed(RKVDEC_Y_HOR_VIRSTRIDE(aligned_pitch / 16) | + RKVDEC_UV_HOR_VIRSTRIDE(aligned_pitch / 16), + rkvdec->regs + RKVDEC_REG_PICPAR); + writel_relaxed(RKVDEC_Y_VIRSTRIDE(y_len / 16), + rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE); + writel_relaxed(RKVDEC_YUV_VIRSTRIDE(yuv_len / 16), + rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE); + + stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0); + writel_relaxed(RKVDEC_STRM_LEN(stream_len), + rkvdec->regs + RKVDEC_REG_STRM_LEN); + + /* + * Reset count buffer, because decoder only output intra related syntax + * counts when decoding intra frame, but update entropy need to update + * all the probabilities. + */ + if (intra_only) + memset(vp9_ctx->count_tbl.cpu, 0, vp9_ctx->count_tbl.size); + + vp9_ctx->cur.segmapid = vp9_ctx->last.segmapid; + if (!intra_only && + !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && + (!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) || + (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP))) + vp9_ctx->cur.segmapid++; + + for (i = 0; i < ARRAY_SIZE(ref_bufs); i++) + config_ref_registers(ctx, run, ref_bufs[i], &ref_regs[i]); + + for (i = 0; i < 8; i++) + config_seg_registers(ctx, i); + + writel_relaxed(RKVDEC_VP9_TX_MODE(vp9_ctx->cur.tx_mode) | + RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode), + rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG); + + if (!intra_only) { + const struct v4l2_vp9_loop_filter *lf; + s8 delta; + + if (vp9_ctx->last.valid) + lf = &vp9_ctx->last.lf; + else + lf = &vp9_ctx->cur.lf; + + val = 0; + for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { + delta = lf->ref_deltas[i]; + val |= RKVDEC_REF_DELTAS_LASTFRAME(i, delta); + } + + writel_relaxed(val, + rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME); + + for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { + delta = lf->mode_deltas[i]; + last_frame_info |= RKVDEC_MODE_DELTAS_LASTFRAME(i, + delta); + } + } + + if (vp9_ctx->last.valid && !intra_only && + vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED) + last_frame_info |= RKVDEC_SEG_EN_LASTFRAME; + + if (vp9_ctx->last.valid && + vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME) + last_frame_info |= RKVDEC_LAST_SHOW_FRAME; + + if (vp9_ctx->last.valid && + vp9_ctx->last.flags & + (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY)) + last_frame_info |= RKVDEC_LAST_INTRA_ONLY; + + if (vp9_ctx->last.valid && + last->vp9.width == dst->vp9.width && + last->vp9.height == dst->vp9.height) + last_frame_info |= RKVDEC_LAST_WIDHHEIGHT_EQCUR; + + writel_relaxed(last_frame_info, + rkvdec->regs + RKVDEC_VP9_INFO_LASTFRAME); + + writel_relaxed(stream_len - dec_params->compressed_header_size - + dec_params->uncompressed_header_size, + rkvdec->regs + RKVDEC_VP9_LASTTILE_SIZE); + + for (i = 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) { + unsigned int refw = ref_bufs[i]->vp9.width; + unsigned int refh = ref_bufs[i]->vp9.height; + u32 hscale, vscale; + + hscale = (refw << 14) / dst->vp9.width; + vscale = (refh << 14) / dst->vp9.height; + writel_relaxed(RKVDEC_VP9_REF_HOR_SCALE(hscale) | + RKVDEC_VP9_REF_VER_SCALE(vscale), + rkvdec->regs + RKVDEC_VP9_REF_SCALE(i)); + } + + addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0); + writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE); + addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0); + writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE); + writel_relaxed(vp9_ctx->priv_tbl.dma + + offsetof(struct rkvdec_vp9_priv_tbl, probs), + rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE); + writel_relaxed(vp9_ctx->count_tbl.dma, + rkvdec->regs + RKVDEC_REG_VP9COUNT_BASE); + + writel_relaxed(vp9_ctx->priv_tbl.dma + + offsetof(struct rkvdec_vp9_priv_tbl, segmap) + + (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid), + rkvdec->regs + RKVDEC_REG_VP9_SEGIDCUR_BASE); + writel_relaxed(vp9_ctx->priv_tbl.dma + + offsetof(struct rkvdec_vp9_priv_tbl, segmap) + + (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)), + rkvdec->regs + RKVDEC_REG_VP9_SEGIDLAST_BASE); + + if (!intra_only && + !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && + vp9_ctx->last.valid) + mv_ref = last; + else + mv_ref = dst; + + writel_relaxed(get_mv_base_addr(mv_ref), + rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE); + + writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width | + (ctx->decoded_fmt.fmt.pix_mp.height << 16), + rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE); +} + +static int validate_dec_params(struct rkvdec_ctx *ctx, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + unsigned int aligned_width, aligned_height; + + /* We only support profile 0. */ + if (dec_params->profile != 0) { + dev_err(ctx->dev->dev, "unsupported profile %d\n", + dec_params->profile); + return -EINVAL; + } + + aligned_width = round_up(dec_params->frame_width_minus_1 + 1, 64); + aligned_height = round_up(dec_params->frame_height_minus_1 + 1, 64); + + /* + * Userspace should update the capture/decoded format when the + * resolution changes. + */ + if (aligned_width != ctx->decoded_fmt.fmt.pix_mp.width || + aligned_height != ctx->decoded_fmt.fmt.pix_mp.height) { + dev_err(ctx->dev->dev, + "unexpected bitstream resolution %dx%d\n", + dec_params->frame_width_minus_1 + 1, + dec_params->frame_height_minus_1 + 1); + return -EINVAL; + } + + return 0; +} + +static int rkvdec_vp9_run_preamble(struct rkvdec_ctx *ctx, + struct rkvdec_vp9_run *run) +{ + const struct v4l2_ctrl_vp9_frame *dec_params; + const struct v4l2_ctrl_vp9_compressed_hdr *prob_updates; + struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; + struct v4l2_ctrl *ctrl; + unsigned int fctx_idx; + int ret; + + /* v4l2-specific stuff */ + rkvdec_run_preamble(ctx, &run->base); + + ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, + V4L2_CID_STATELESS_VP9_FRAME); + if (WARN_ON(!ctrl)) + return -EINVAL; + dec_params = ctrl->p_cur.p; + + ret = validate_dec_params(ctx, dec_params); + if (ret) + return ret; + + run->decode_params = dec_params; + + ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, V4L2_CID_STATELESS_VP9_COMPRESSED_HDR); + if (WARN_ON(!ctrl)) + return -EINVAL; + prob_updates = ctrl->p_cur.p; + vp9_ctx->cur.tx_mode = prob_updates->tx_mode; + + /* + * vp9 stuff + * + * by this point the userspace has done all parts of 6.2 uncompressed_header() + * except this fragment: + * if ( FrameIsIntra || error_resilient_mode ) { + * setup_past_independence ( ) + * if ( frame_type == KEY_FRAME || error_resilient_mode == 1 || + * reset_frame_context == 3 ) { + * for ( i = 0; i < 4; i ++ ) { + * save_probs( i ) + * } + * } else if ( reset_frame_context == 2 ) { + * save_probs( frame_context_idx ) + * } + * frame_context_idx = 0 + * } + */ + fctx_idx = v4l2_vp9_reset_frame_ctx(dec_params, vp9_ctx->frame_context); + vp9_ctx->cur.frame_context_idx = fctx_idx; + + /* 6.1 frame(sz): load_probs() and load_probs2() */ + vp9_ctx->probability_tables = vp9_ctx->frame_context[fctx_idx]; + + /* + * The userspace has also performed 6.3 compressed_header(), but handling the + * probs in a special way. All probs which need updating, except MV-related, + * have been read from the bitstream and translated through inv_map_table[], + * but no 6.3.6 inv_recenter_nonneg(v, m) has been performed. The values passed + * by userspace are either translated values (there are no 0 values in + * inv_map_table[]), or zero to indicate no update. All MV-related probs which need + * updating have been read from the bitstream and (mv_prob << 1) | 1 has been + * performed. The values passed by userspace are either new values + * to replace old ones (the above mentioned shift and bitwise or never result in + * a zero) or zero to indicate no update. + * fw_update_probs() performs actual probs updates or leaves probs as-is + * for values for which a zero was passed from userspace. + */ + v4l2_vp9_fw_update_probs(&vp9_ctx->probability_tables, prob_updates, dec_params); + + return 0; +} + +static int rkvdec_vp9_run(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec = ctx->dev; + struct rkvdec_vp9_run run = { }; + int ret; + + ret = rkvdec_vp9_run_preamble(ctx, &run); + if (ret) { + rkvdec_run_postamble(ctx, &run.base); + return ret; + } + + /* Prepare probs. */ + init_probs(ctx, &run); + + /* Configure hardware registers. */ + config_registers(ctx, &run); + + rkvdec_run_postamble(ctx, &run.base); + + schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); + + writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND); + writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND); + + writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN); + /* Start decoding! */ + writel(RKVDEC_INTERRUPT_DEC_E | RKVDEC_CONFIG_DEC_CLK_GATE_E | + RKVDEC_TIMEOUT_E | RKVDEC_BUF_EMPTY_E, + rkvdec->regs + RKVDEC_REG_INTERRUPT); + + return 0; +} + +#define copy_tx_and_skip(p1, p2) \ +do { \ + memcpy((p1)->tx8, (p2)->tx8, sizeof((p1)->tx8)); \ + memcpy((p1)->tx16, (p2)->tx16, sizeof((p1)->tx16)); \ + memcpy((p1)->tx32, (p2)->tx32, sizeof((p1)->tx32)); \ + memcpy((p1)->skip, (p2)->skip, sizeof((p1)->skip)); \ +} while (0) + +static void rkvdec_vp9_done(struct rkvdec_ctx *ctx, + struct vb2_v4l2_buffer *src_buf, + struct vb2_v4l2_buffer *dst_buf, + enum vb2_buffer_state result) +{ + struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; + unsigned int fctx_idx; + + /* v4l2-specific stuff */ + if (result == VB2_BUF_STATE_ERROR) + goto out_update_last; + + /* + * vp9 stuff + * + * 6.1.2 refresh_probs() + * + * In the spec a complementary condition goes last in 6.1.2 refresh_probs(), + * but it makes no sense to perform all the activities from the first "if" + * there if we actually are not refreshing the frame context. On top of that, + * because of 6.2 uncompressed_header() whenever error_resilient_mode == 1, + * refresh_frame_context == 0. Consequently, if we don't jump to out_update_last + * it means error_resilient_mode must be 0. + */ + if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX)) + goto out_update_last; + + fctx_idx = vp9_ctx->cur.frame_context_idx; + + if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)) { + /* error_resilient_mode == 0 && frame_parallel_decoding_mode == 0 */ + struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables; + bool frame_is_intra = vp9_ctx->cur.flags & + (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY); + struct tx_and_skip { + u8 tx8[2][1]; + u8 tx16[2][2]; + u8 tx32[2][3]; + u8 skip[3]; + } _tx_skip, *tx_skip = &_tx_skip; + struct v4l2_vp9_frame_symbol_counts *counts; + + /* buffer the forward-updated TX and skip probs */ + if (frame_is_intra) + copy_tx_and_skip(tx_skip, probs); + + /* 6.1.2 refresh_probs(): load_probs() and load_probs2() */ + *probs = vp9_ctx->frame_context[fctx_idx]; + + /* if FrameIsIntra then undo the effect of load_probs2() */ + if (frame_is_intra) + copy_tx_and_skip(probs, tx_skip); + + counts = frame_is_intra ? &vp9_ctx->intra_cnts : &vp9_ctx->inter_cnts; + v4l2_vp9_adapt_coef_probs(probs, counts, + !vp9_ctx->last.valid || + vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME, + frame_is_intra); + if (!frame_is_intra) { + const struct rkvdec_vp9_inter_frame_symbol_counts *inter_cnts; + u32 classes[2][11]; + int i; + + inter_cnts = vp9_ctx->count_tbl.cpu; + for (i = 0; i < ARRAY_SIZE(classes); ++i) + memcpy(classes[i], inter_cnts->classes[i], sizeof(classes[0])); + counts->classes = &classes; + + /* load_probs2() already done */ + v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts, + vp9_ctx->cur.reference_mode, + vp9_ctx->cur.interpolation_filter, + vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags); + } + } + + /* 6.1.2 refresh_probs(): save_probs(fctx_idx) */ + vp9_ctx->frame_context[fctx_idx] = vp9_ctx->probability_tables; + +out_update_last: + update_ctx_last_info(vp9_ctx); +} + +static void rkvdec_init_v4l2_vp9_count_tbl(struct rkvdec_ctx *ctx) +{ + struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; + struct rkvdec_vp9_intra_frame_symbol_counts *intra_cnts = vp9_ctx->count_tbl.cpu; + struct rkvdec_vp9_inter_frame_symbol_counts *inter_cnts = vp9_ctx->count_tbl.cpu; + int i, j, k, l, m; + + vp9_ctx->inter_cnts.partition = &inter_cnts->partition; + vp9_ctx->inter_cnts.skip = &inter_cnts->skip; + vp9_ctx->inter_cnts.intra_inter = &inter_cnts->inter; + vp9_ctx->inter_cnts.tx32p = &inter_cnts->tx32p; + vp9_ctx->inter_cnts.tx16p = &inter_cnts->tx16p; + vp9_ctx->inter_cnts.tx8p = &inter_cnts->tx8p; + + vp9_ctx->intra_cnts.partition = (u32 (*)[16][4])(&intra_cnts->partition); + vp9_ctx->intra_cnts.skip = &intra_cnts->skip; + vp9_ctx->intra_cnts.intra_inter = &intra_cnts->intra; + vp9_ctx->intra_cnts.tx32p = &intra_cnts->tx32p; + vp9_ctx->intra_cnts.tx16p = &intra_cnts->tx16p; + vp9_ctx->intra_cnts.tx8p = &intra_cnts->tx8p; + + vp9_ctx->inter_cnts.y_mode = &inter_cnts->y_mode; + vp9_ctx->inter_cnts.uv_mode = &inter_cnts->uv_mode; + vp9_ctx->inter_cnts.comp = &inter_cnts->comp; + vp9_ctx->inter_cnts.comp_ref = &inter_cnts->comp_ref; + vp9_ctx->inter_cnts.single_ref = &inter_cnts->single_ref; + vp9_ctx->inter_cnts.mv_mode = &inter_cnts->mv_mode; + vp9_ctx->inter_cnts.filter = &inter_cnts->filter; + vp9_ctx->inter_cnts.mv_joint = &inter_cnts->mv_joint; + vp9_ctx->inter_cnts.sign = &inter_cnts->sign; + /* + * rk hardware actually uses "u32 classes[2][11 + 1];" + * instead of "u32 classes[2][11];", so this must be explicitly + * copied into vp9_ctx->classes when passing the data to the + * vp9 library function + */ + vp9_ctx->inter_cnts.class0 = &inter_cnts->class0; + vp9_ctx->inter_cnts.bits = &inter_cnts->bits; + vp9_ctx->inter_cnts.class0_fp = &inter_cnts->class0_fp; + vp9_ctx->inter_cnts.fp = &inter_cnts->fp; + vp9_ctx->inter_cnts.class0_hp = &inter_cnts->class0_hp; + vp9_ctx->inter_cnts.hp = &inter_cnts->hp; + +#define INNERMOST_LOOP \ + do { \ + for (m = 0; m < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff[0][0][0][0]); ++m) {\ + vp9_ctx->inter_cnts.coeff[i][j][k][l][m] = \ + &inter_cnts->ref_cnt[k][i][j][l][m].coeff; \ + vp9_ctx->inter_cnts.eob[i][j][k][l][m][0] = \ + &inter_cnts->ref_cnt[k][i][j][l][m].eob[0]; \ + vp9_ctx->inter_cnts.eob[i][j][k][l][m][1] = \ + &inter_cnts->ref_cnt[k][i][j][l][m].eob[1]; \ + \ + vp9_ctx->intra_cnts.coeff[i][j][k][l][m] = \ + &intra_cnts->ref_cnt[k][i][j][l][m].coeff; \ + vp9_ctx->intra_cnts.eob[i][j][k][l][m][0] = \ + &intra_cnts->ref_cnt[k][i][j][l][m].eob[0]; \ + vp9_ctx->intra_cnts.eob[i][j][k][l][m][1] = \ + &intra_cnts->ref_cnt[k][i][j][l][m].eob[1]; \ + } \ + } while (0) + + for (i = 0; i < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff); ++i) + for (j = 0; j < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff[0]); ++j) + for (k = 0; k < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff[0][0]); ++k) + for (l = 0; l < ARRAY_SIZE(vp9_ctx->inter_cnts.coeff[0][0][0]); ++l) + INNERMOST_LOOP; +#undef INNERMOST_LOOP +} + +static int rkvdec_vp9_start(struct rkvdec_ctx *ctx) +{ + struct rkvdec_dev *rkvdec = ctx->dev; + struct rkvdec_vp9_priv_tbl *priv_tbl; + struct rkvdec_vp9_ctx *vp9_ctx; + unsigned char *count_tbl; + int ret; + + vp9_ctx = kzalloc(sizeof(*vp9_ctx), GFP_KERNEL); + if (!vp9_ctx) + return -ENOMEM; + + ctx->priv = vp9_ctx; + + priv_tbl = dma_alloc_coherent(rkvdec->dev, sizeof(*priv_tbl), + &vp9_ctx->priv_tbl.dma, GFP_KERNEL); + if (!priv_tbl) { + ret = -ENOMEM; + goto err_free_ctx; + } + + vp9_ctx->priv_tbl.size = sizeof(*priv_tbl); + vp9_ctx->priv_tbl.cpu = priv_tbl; + memset(priv_tbl, 0, sizeof(*priv_tbl)); + + count_tbl = dma_alloc_coherent(rkvdec->dev, RKVDEC_VP9_COUNT_SIZE, + &vp9_ctx->count_tbl.dma, GFP_KERNEL); + if (!count_tbl) { + ret = -ENOMEM; + goto err_free_priv_tbl; + } + + vp9_ctx->count_tbl.size = RKVDEC_VP9_COUNT_SIZE; + vp9_ctx->count_tbl.cpu = count_tbl; + memset(count_tbl, 0, sizeof(*count_tbl)); + rkvdec_init_v4l2_vp9_count_tbl(ctx); + + return 0; + +err_free_priv_tbl: + dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size, + vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma); + +err_free_ctx: + kfree(vp9_ctx); + return ret; +} + +static void rkvdec_vp9_stop(struct rkvdec_ctx *ctx) +{ + struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv; + struct rkvdec_dev *rkvdec = ctx->dev; + + dma_free_coherent(rkvdec->dev, vp9_ctx->count_tbl.size, + vp9_ctx->count_tbl.cpu, vp9_ctx->count_tbl.dma); + dma_free_coherent(rkvdec->dev, vp9_ctx->priv_tbl.size, + vp9_ctx->priv_tbl.cpu, vp9_ctx->priv_tbl.dma); + kfree(vp9_ctx); +} + +static int rkvdec_vp9_adjust_fmt(struct rkvdec_ctx *ctx, + struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; + + fmt->num_planes = 1; + if (!fmt->plane_fmt[0].sizeimage) + fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * 2; + return 0; +} + +const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops = { + .adjust_fmt = rkvdec_vp9_adjust_fmt, + .start = rkvdec_vp9_start, + .stop = rkvdec_vp9_stop, + .run = rkvdec_vp9_run, + .done = rkvdec_vp9_done, +}; diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c index 4fd4a2907da7..ad2624c30843 100644 --- a/drivers/staging/media/rkvdec/rkvdec.c +++ b/drivers/staging/media/rkvdec/rkvdec.c @@ -99,10 +99,30 @@ static const struct rkvdec_ctrls rkvdec_h264_ctrls = { .num_ctrls = ARRAY_SIZE(rkvdec_h264_ctrl_descs), }; -static const u32 rkvdec_h264_decoded_fmts[] = { +static const u32 rkvdec_h264_vp9_decoded_fmts[] = { V4L2_PIX_FMT_NV12, }; +static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = { + { + .cfg.id = V4L2_CID_STATELESS_VP9_FRAME, + }, + { + .cfg.id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR, + }, + { + .cfg.id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE, + .cfg.min = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .cfg.max = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .cfg.def = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + }, +}; + +static const struct rkvdec_ctrls rkvdec_vp9_ctrls = { + .ctrls = rkvdec_vp9_ctrl_descs, + .num_ctrls = ARRAY_SIZE(rkvdec_vp9_ctrl_descs), +}; + static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { { .fourcc = V4L2_PIX_FMT_H264_SLICE, @@ -116,8 +136,23 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { }, .ctrls = &rkvdec_h264_ctrls, .ops = &rkvdec_h264_fmt_ops, - .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts), - .decoded_fmts = rkvdec_h264_decoded_fmts, + .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_vp9_decoded_fmts), + .decoded_fmts = rkvdec_h264_vp9_decoded_fmts, + }, + { + .fourcc = V4L2_PIX_FMT_VP9_FRAME, + .frmsize = { + .min_width = 64, + .max_width = 4096, + .step_width = 64, + .min_height = 64, + .max_height = 2304, + .step_height = 64, + }, + .ctrls = &rkvdec_vp9_ctrls, + .ops = &rkvdec_vp9_fmt_ops, + .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_vp9_decoded_fmts), + .decoded_fmts = rkvdec_h264_vp9_decoded_fmts, } }; diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h index 52ac3874c5e5..2f4ea1786b93 100644 --- a/drivers/staging/media/rkvdec/rkvdec.h +++ b/drivers/staging/media/rkvdec/rkvdec.h @@ -42,14 +42,18 @@ struct rkvdec_run { struct rkvdec_vp9_decoded_buffer_info { /* Info needed when the decoded frame serves as a reference frame. */ - u16 width; - u16 height; - u32 bit_depth : 4; + unsigned short width; + unsigned short height; + unsigned int bit_depth : 4; }; struct rkvdec_decoded_buffer { /* Must be the first field in this struct. */ struct v4l2_m2m_buffer base; + + union { + struct rkvdec_vp9_decoded_buffer_info vp9; + }; }; static inline struct rkvdec_decoded_buffer * @@ -116,4 +120,6 @@ void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run); extern const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops; +extern const struct rkvdec_coded_fmt_ops rkvdec_vp9_fmt_ops; + #endif /* RKVDEC_H_ */ From 82fb363d5e96bd87e5027d0d2bbecea75870707d Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 16 Nov 2021 14:38:38 +0000 Subject: [PATCH 190/397] media: hantro: Rename registers Add more consistency in the way registers are named. Signed-off-by: Andrzej Pietrasiewicz Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/hantro/hantro_g2_hevc_dec.c | 40 +++++++++---------- drivers/staging/media/hantro/hantro_g2_regs.h | 28 ++++++------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c index 76a921163b9a..abae36f9b418 100644 --- a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c +++ b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c @@ -448,9 +448,9 @@ static int set_ref(struct hantro_ctx *ctx) if (dpb[i].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR) dpb_longterm_e |= BIT(V4L2_HEVC_DPB_ENTRIES_NUM_MAX - 1 - i); - hantro_write_addr(vpu, G2_REG_ADDR_REF(i), luma_addr); - hantro_write_addr(vpu, G2_REG_CHR_REF(i), chroma_addr); - hantro_write_addr(vpu, G2_REG_DMV_REF(i), mv_addr); + hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), luma_addr); + hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), chroma_addr); + hantro_write_addr(vpu, G2_REF_MV_ADDR(i), mv_addr); } luma_addr = hantro_hevc_get_ref_buf(ctx, decode_params->pic_order_cnt_val); @@ -460,20 +460,20 @@ static int set_ref(struct hantro_ctx *ctx) chroma_addr = luma_addr + cr_offset; mv_addr = luma_addr + mv_offset; - hantro_write_addr(vpu, G2_REG_ADDR_REF(i), luma_addr); - hantro_write_addr(vpu, G2_REG_CHR_REF(i), chroma_addr); - hantro_write_addr(vpu, G2_REG_DMV_REF(i++), mv_addr); + hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), luma_addr); + hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), chroma_addr); + hantro_write_addr(vpu, G2_REF_MV_ADDR(i++), mv_addr); - hantro_write_addr(vpu, G2_ADDR_DST, luma_addr); - hantro_write_addr(vpu, G2_ADDR_DST_CHR, chroma_addr); - hantro_write_addr(vpu, G2_ADDR_DST_MV, mv_addr); + hantro_write_addr(vpu, G2_OUT_LUMA_ADDR, luma_addr); + hantro_write_addr(vpu, G2_OUT_CHROMA_ADDR, chroma_addr); + hantro_write_addr(vpu, G2_OUT_MV_ADDR, mv_addr); hantro_hevc_ref_remove_unused(ctx); for (; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) { - hantro_write_addr(vpu, G2_REG_ADDR_REF(i), 0); - hantro_write_addr(vpu, G2_REG_CHR_REF(i), 0); - hantro_write_addr(vpu, G2_REG_DMV_REF(i), 0); + hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), 0); + hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), 0); + hantro_write_addr(vpu, G2_REF_MV_ADDR(i), 0); } hantro_reg_write(vpu, &g2_refer_lterm_e, dpb_longterm_e); @@ -499,7 +499,7 @@ static void set_buffers(struct hantro_ctx *ctx) src_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0); src_buf_len = vb2_plane_size(&src_buf->vb2_buf, 0); - hantro_write_addr(vpu, G2_ADDR_STR, src_dma); + hantro_write_addr(vpu, G2_STREAM_ADDR, src_dma); hantro_reg_write(vpu, &g2_stream_len, src_len); hantro_reg_write(vpu, &g2_strm_buffer_len, src_buf_len); hantro_reg_write(vpu, &g2_strm_start_offset, 0); @@ -508,12 +508,12 @@ static void set_buffers(struct hantro_ctx *ctx) /* Destination (decoded frame) buffer. */ dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf); - hantro_write_addr(vpu, G2_RASTER_SCAN, dst_dma); - hantro_write_addr(vpu, G2_RASTER_SCAN_CHR, dst_dma + cr_offset); - hantro_write_addr(vpu, G2_ADDR_TILE_SIZE, ctx->hevc_dec.tile_sizes.dma); - hantro_write_addr(vpu, G2_TILE_FILTER, ctx->hevc_dec.tile_filter.dma); - hantro_write_addr(vpu, G2_TILE_SAO, ctx->hevc_dec.tile_sao.dma); - hantro_write_addr(vpu, G2_TILE_BSD, ctx->hevc_dec.tile_bsd.dma); + hantro_write_addr(vpu, G2_RS_OUT_LUMA_ADDR, dst_dma); + hantro_write_addr(vpu, G2_RS_OUT_CHROMA_ADDR, dst_dma + cr_offset); + hantro_write_addr(vpu, G2_TILE_SIZES_ADDR, ctx->hevc_dec.tile_sizes.dma); + hantro_write_addr(vpu, G2_TILE_FILTER_ADDR, ctx->hevc_dec.tile_filter.dma); + hantro_write_addr(vpu, G2_TILE_SAO_ADDR, ctx->hevc_dec.tile_sao.dma); + hantro_write_addr(vpu, G2_TILE_BSD_ADDR, ctx->hevc_dec.tile_bsd.dma); } static void prepare_scaling_list_buffer(struct hantro_ctx *ctx) @@ -563,7 +563,7 @@ static void prepare_scaling_list_buffer(struct hantro_ctx *ctx) for (k = 0; k < 8; k++) *p++ = sc->scaling_list_32x32[i][8 * k + j]; - hantro_write_addr(vpu, HEVC_SCALING_LIST, ctx->hevc_dec.scaling_lists.dma); + hantro_write_addr(vpu, G2_HEVC_SCALING_LIST_ADDR, ctx->hevc_dec.scaling_lists.dma); } static void hantro_g2_check_idle(struct hantro_dev *vpu) diff --git a/drivers/staging/media/hantro/hantro_g2_regs.h b/drivers/staging/media/hantro/hantro_g2_regs.h index bb22fa921914..24b18f839ff8 100644 --- a/drivers/staging/media/hantro/hantro_g2_regs.h +++ b/drivers/staging/media/hantro/hantro_g2_regs.h @@ -177,20 +177,20 @@ #define G2_REG_CONFIG_DEC_CLK_GATE_E BIT(16) #define G2_REG_CONFIG_DEC_CLK_GATE_IDLE_E BIT(17) -#define G2_ADDR_DST (G2_SWREG(65)) -#define G2_REG_ADDR_REF(i) (G2_SWREG(67) + ((i) * 0x8)) -#define G2_ADDR_DST_CHR (G2_SWREG(99)) -#define G2_REG_CHR_REF(i) (G2_SWREG(101) + ((i) * 0x8)) -#define G2_ADDR_DST_MV (G2_SWREG(133)) -#define G2_REG_DMV_REF(i) (G2_SWREG(135) + ((i) * 0x8)) -#define G2_ADDR_TILE_SIZE (G2_SWREG(167)) -#define G2_ADDR_STR (G2_SWREG(169)) -#define HEVC_SCALING_LIST (G2_SWREG(171)) -#define G2_RASTER_SCAN (G2_SWREG(175)) -#define G2_RASTER_SCAN_CHR (G2_SWREG(177)) -#define G2_TILE_FILTER (G2_SWREG(179)) -#define G2_TILE_SAO (G2_SWREG(181)) -#define G2_TILE_BSD (G2_SWREG(183)) +#define G2_OUT_LUMA_ADDR (G2_SWREG(65)) +#define G2_REF_LUMA_ADDR(i) (G2_SWREG(67) + ((i) * 0x8)) +#define G2_OUT_CHROMA_ADDR (G2_SWREG(99)) +#define G2_REF_CHROMA_ADDR(i) (G2_SWREG(101) + ((i) * 0x8)) +#define G2_OUT_MV_ADDR (G2_SWREG(133)) +#define G2_REF_MV_ADDR(i) (G2_SWREG(135) + ((i) * 0x8)) +#define G2_TILE_SIZES_ADDR (G2_SWREG(167)) +#define G2_STREAM_ADDR (G2_SWREG(169)) +#define G2_HEVC_SCALING_LIST_ADDR (G2_SWREG(171)) +#define G2_RS_OUT_LUMA_ADDR (G2_SWREG(175)) +#define G2_RS_OUT_CHROMA_ADDR (G2_SWREG(177)) +#define G2_TILE_FILTER_ADDR (G2_SWREG(179)) +#define G2_TILE_SAO_ADDR (G2_SWREG(181)) +#define G2_TILE_BSD_ADDR (G2_SWREG(183)) #define g2_strm_buffer_len G2_DEC_REG(258, 0, 0xffffffff) #define g2_strm_start_offset G2_DEC_REG(259, 0, 0xffffffff) From cb1bbbd4cffd55d166ec9fa5d0ea2afa749ca9cf Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 16 Nov 2021 14:38:39 +0000 Subject: [PATCH 191/397] media: hantro: Prepare for other G2 codecs VeriSilicon Hantro G2 core supports other codecs besides hevc. Factor out some common code in preparation for vp9 support. Signed-off-by: Andrzej Pietrasiewicz Reviewed-by: Benjamin Gaignard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/Makefile | 1 + drivers/staging/media/hantro/hantro.h | 7 +++++ drivers/staging/media/hantro/hantro_drv.c | 5 +++ drivers/staging/media/hantro/hantro_g2.c | 26 ++++++++++++++++ .../staging/media/hantro/hantro_g2_hevc_dec.c | 31 ------------------- drivers/staging/media/hantro/hantro_g2_regs.h | 7 +++++ drivers/staging/media/hantro/hantro_hw.h | 2 ++ 7 files changed, 48 insertions(+), 31 deletions(-) create mode 100644 drivers/staging/media/hantro/hantro_g2.c diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile index 90036831fec4..fe6d84871d07 100644 --- a/drivers/staging/media/hantro/Makefile +++ b/drivers/staging/media/hantro/Makefile @@ -12,6 +12,7 @@ hantro-vpu-y += \ hantro_g1_mpeg2_dec.o \ hantro_g2_hevc_dec.o \ hantro_g1_vp8_dec.o \ + hantro_g2.o \ rockchip_vpu2_hw_jpeg_enc.o \ rockchip_vpu2_hw_h264_dec.o \ rockchip_vpu2_hw_mpeg2_dec.o \ diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index dd5e56765d4e..d91eb2b1c509 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -369,6 +369,13 @@ static inline void vdpu_write(struct hantro_dev *vpu, u32 val, u32 reg) writel(val, vpu->dec_base + reg); } +static inline void hantro_write_addr(struct hantro_dev *vpu, + unsigned long offset, + dma_addr_t addr) +{ + vdpu_write(vpu, addr & 0xffffffff, offset); +} + static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg) { u32 val = readl(vpu->dec_base + reg); diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index fb82b9297a2b..bb72e5e208b7 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -907,6 +907,11 @@ static int hantro_probe(struct platform_device *pdev) vpu->enc_base = vpu->reg_bases[0] + vpu->variant->enc_offset; vpu->dec_base = vpu->reg_bases[0] + vpu->variant->dec_offset; + /** + * TODO: Eventually allow taking advantage of full 64-bit address space. + * Until then we assume the MSB portion of buffers' base addresses is + * always 0 due to this masking operation. + */ ret = dma_set_coherent_mask(vpu->dev, DMA_BIT_MASK(32)); if (ret) { dev_err(vpu->dev, "Could not set DMA coherent mask.\n"); diff --git a/drivers/staging/media/hantro/hantro_g2.c b/drivers/staging/media/hantro/hantro_g2.c new file mode 100644 index 000000000000..6f3e1f797f83 --- /dev/null +++ b/drivers/staging/media/hantro/hantro_g2.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hantro VPU codec driver + * + * Copyright (C) 2021 Collabora Ltd, Andrzej Pietrasiewicz + */ + +#include "hantro_hw.h" +#include "hantro_g2_regs.h" + +void hantro_g2_check_idle(struct hantro_dev *vpu) +{ + int i; + + for (i = 0; i < 3; i++) { + u32 status; + + /* Make sure the VPU is idle */ + status = vdpu_read(vpu, G2_REG_INTERRUPT); + if (status & G2_REG_INTERRUPT_DEC_E) { + dev_warn(vpu->dev, "device still running, aborting"); + status |= G2_REG_INTERRUPT_DEC_ABORT_E | G2_REG_INTERRUPT_DEC_IRQ_DIS; + vdpu_write(vpu, status, G2_REG_INTERRUPT); + } + } +} diff --git a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c index abae36f9b418..f62608b0b408 100644 --- a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c +++ b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c @@ -8,20 +8,6 @@ #include "hantro_hw.h" #include "hantro_g2_regs.h" -#define HEVC_DEC_MODE 0xC - -#define BUS_WIDTH_32 0 -#define BUS_WIDTH_64 1 -#define BUS_WIDTH_128 2 -#define BUS_WIDTH_256 3 - -static inline void hantro_write_addr(struct hantro_dev *vpu, - unsigned long offset, - dma_addr_t addr) -{ - vdpu_write(vpu, addr & 0xffffffff, offset); -} - static void prepare_tile_info_buffer(struct hantro_ctx *ctx) { struct hantro_dev *vpu = ctx->dev; @@ -566,23 +552,6 @@ static void prepare_scaling_list_buffer(struct hantro_ctx *ctx) hantro_write_addr(vpu, G2_HEVC_SCALING_LIST_ADDR, ctx->hevc_dec.scaling_lists.dma); } -static void hantro_g2_check_idle(struct hantro_dev *vpu) -{ - int i; - - for (i = 0; i < 3; i++) { - u32 status; - - /* Make sure the VPU is idle */ - status = vdpu_read(vpu, G2_REG_INTERRUPT); - if (status & G2_REG_INTERRUPT_DEC_E) { - dev_warn(vpu->dev, "device still running, aborting"); - status |= G2_REG_INTERRUPT_DEC_ABORT_E | G2_REG_INTERRUPT_DEC_IRQ_DIS; - vdpu_write(vpu, status, G2_REG_INTERRUPT); - } - } -} - int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx) { struct hantro_dev *vpu = ctx->dev; diff --git a/drivers/staging/media/hantro/hantro_g2_regs.h b/drivers/staging/media/hantro/hantro_g2_regs.h index 24b18f839ff8..136ba6d98a1f 100644 --- a/drivers/staging/media/hantro/hantro_g2_regs.h +++ b/drivers/staging/media/hantro/hantro_g2_regs.h @@ -27,6 +27,13 @@ #define G2_REG_INTERRUPT_DEC_IRQ_DIS BIT(4) #define G2_REG_INTERRUPT_DEC_E BIT(0) +#define HEVC_DEC_MODE 0xc + +#define BUS_WIDTH_32 0 +#define BUS_WIDTH_64 1 +#define BUS_WIDTH_128 2 +#define BUS_WIDTH_256 3 + #define g2_strm_swap G2_DEC_REG(2, 28, 0xf) #define g2_dirmv_swap G2_DEC_REG(2, 20, 0xf) diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 2f85430682d8..1d869abf90b2 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -312,4 +312,6 @@ void hantro_vp8_dec_exit(struct hantro_ctx *ctx); void hantro_vp8_prob_update(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp8_frame *hdr); +void hantro_g2_check_idle(struct hantro_dev *vpu); + #endif /* HANTRO_HW_H_ */ From e2da465455ce48061f726f3a1aad2a3a5a6f547f Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 16 Nov 2021 14:38:40 +0000 Subject: [PATCH 192/397] media: hantro: Support VP9 on the G2 core VeriSilicon Hantro G2 core supports VP9 codec. [hverkuil: add kerneldoc line for HANTRO_MODE_VP9_DEC] Signed-off-by: Andrzej Pietrasiewicz Reviewed-by: Benjamin Gaignard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/Kconfig | 1 + drivers/staging/media/hantro/Makefile | 6 +- drivers/staging/media/hantro/hantro.h | 27 + drivers/staging/media/hantro/hantro_drv.c | 18 +- drivers/staging/media/hantro/hantro_g2_regs.h | 97 ++ .../staging/media/hantro/hantro_g2_vp9_dec.c | 980 ++++++++++++++++++ drivers/staging/media/hantro/hantro_hw.h | 99 ++ drivers/staging/media/hantro/hantro_v4l2.c | 6 + drivers/staging/media/hantro/hantro_vp9.c | 240 +++++ drivers/staging/media/hantro/hantro_vp9.h | 102 ++ drivers/staging/media/hantro/imx8m_vpu_hw.c | 22 +- 11 files changed, 1594 insertions(+), 4 deletions(-) create mode 100644 drivers/staging/media/hantro/hantro_g2_vp9_dec.c create mode 100644 drivers/staging/media/hantro/hantro_vp9.c create mode 100644 drivers/staging/media/hantro/hantro_vp9.h diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig index 20b1f6d7b69c..00a57d88c92e 100644 --- a/drivers/staging/media/hantro/Kconfig +++ b/drivers/staging/media/hantro/Kconfig @@ -9,6 +9,7 @@ config VIDEO_HANTRO select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV select V4L2_H264 + select V4L2_VP9 help Support for the Hantro IP based Video Processing Units present on Rockchip and NXP i.MX8M SoCs, which accelerate video and image diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile index fe6d84871d07..28af0a1ee4bf 100644 --- a/drivers/staging/media/hantro/Makefile +++ b/drivers/staging/media/hantro/Makefile @@ -10,9 +10,10 @@ hantro-vpu-y += \ hantro_g1.o \ hantro_g1_h264_dec.o \ hantro_g1_mpeg2_dec.o \ - hantro_g2_hevc_dec.o \ hantro_g1_vp8_dec.o \ hantro_g2.o \ + hantro_g2_hevc_dec.o \ + hantro_g2_vp9_dec.o \ rockchip_vpu2_hw_jpeg_enc.o \ rockchip_vpu2_hw_h264_dec.o \ rockchip_vpu2_hw_mpeg2_dec.o \ @@ -21,7 +22,8 @@ hantro-vpu-y += \ hantro_h264.o \ hantro_hevc.o \ hantro_mpeg2.o \ - hantro_vp8.o + hantro_vp8.o \ + hantro_vp9.o hantro-vpu-$(CONFIG_VIDEO_HANTRO_IMX8M) += \ imx8m_vpu_hw.o diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index d91eb2b1c509..7da23f7f207a 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -36,6 +36,7 @@ struct hantro_postproc_ops; #define HANTRO_VP8_DECODER BIT(17) #define HANTRO_H264_DECODER BIT(18) #define HANTRO_HEVC_DECODER BIT(19) +#define HANTRO_VP9_DECODER BIT(20) #define HANTRO_DECODERS 0xffff0000 /** @@ -102,6 +103,7 @@ struct hantro_variant { * @HANTRO_MODE_MPEG2_DEC: MPEG-2 decoder. * @HANTRO_MODE_VP8_DEC: VP8 decoder. * @HANTRO_MODE_HEVC_DEC: HEVC decoder. + * @HANTRO_MODE_VP9_DEC: VP9 decoder. */ enum hantro_codec_mode { HANTRO_MODE_NONE = -1, @@ -110,6 +112,7 @@ enum hantro_codec_mode { HANTRO_MODE_MPEG2_DEC, HANTRO_MODE_VP8_DEC, HANTRO_MODE_HEVC_DEC, + HANTRO_MODE_VP9_DEC, }; /* @@ -223,6 +226,7 @@ struct hantro_dev { * @mpeg2_dec: MPEG-2-decoding context. * @vp8_dec: VP8-decoding context. * @hevc_dec: HEVC-decoding context. + * @vp9_dec: VP9-decoding context. */ struct hantro_ctx { struct hantro_dev *dev; @@ -250,6 +254,7 @@ struct hantro_ctx { struct hantro_mpeg2_dec_hw_ctx mpeg2_dec; struct hantro_vp8_dec_hw_ctx vp8_dec; struct hantro_hevc_dec_hw_ctx hevc_dec; + struct hantro_vp9_dec_hw_ctx vp9_dec; }; }; @@ -299,6 +304,22 @@ struct hantro_postproc_regs { struct hantro_reg display_width; }; +struct hantro_vp9_decoded_buffer_info { + /* Info needed when the decoded frame serves as a reference frame. */ + unsigned short width; + unsigned short height; + u32 bit_depth : 4; +}; + +struct hantro_decoded_buffer { + /* Must be the first field in this struct. */ + struct v4l2_m2m_buffer base; + + union { + struct hantro_vp9_decoded_buffer_info vp9; + }; +}; + /* Logging helpers */ /** @@ -436,6 +457,12 @@ hantro_get_dec_buf_addr(struct hantro_ctx *ctx, struct vb2_buffer *vb) return vb2_dma_contig_plane_dma_addr(vb, 0); } +static inline struct hantro_decoded_buffer * +vb2_to_hantro_decoded_buf(struct vb2_buffer *buf) +{ + return container_of(buf, struct hantro_decoded_buffer, base.vb.vb2_buf); +} + void hantro_postproc_disable(struct hantro_ctx *ctx); void hantro_postproc_enable(struct hantro_ctx *ctx); void hantro_postproc_free(struct hantro_ctx *ctx); diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index bb72e5e208b7..ab2467998d29 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -232,7 +232,7 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; dst_vq->drv_priv = ctx; dst_vq->ops = &hantro_queue_ops; - dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + dst_vq->buf_struct_size = sizeof(struct hantro_decoded_buffer); dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; dst_vq->lock = &ctx->dev->vpu_mutex; dst_vq->dev = ctx->dev->v4l2_dev.dev; @@ -263,6 +263,12 @@ static int hantro_try_ctrl(struct v4l2_ctrl *ctrl) if (sps->bit_depth_luma_minus8 != 0) /* Only 8-bit is supported */ return -EINVAL; + } else if (ctrl->id == V4L2_CID_STATELESS_VP9_FRAME) { + const struct v4l2_ctrl_vp9_frame *dec_params = ctrl->p_new.p_vp9_frame; + + /* We only support profile 0 */ + if (dec_params->profile != 0) + return -EINVAL; } return 0; } @@ -461,6 +467,16 @@ static const struct hantro_ctrl controls[] = { .step = 1, .ops = &hantro_hevc_ctrl_ops, }, + }, { + .codec = HANTRO_VP9_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_VP9_FRAME, + }, + }, { + .codec = HANTRO_VP9_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR, + }, }, }; diff --git a/drivers/staging/media/hantro/hantro_g2_regs.h b/drivers/staging/media/hantro/hantro_g2_regs.h index 136ba6d98a1f..9c857dd1ad9b 100644 --- a/drivers/staging/media/hantro/hantro_g2_regs.h +++ b/drivers/staging/media/hantro/hantro_g2_regs.h @@ -28,6 +28,7 @@ #define G2_REG_INTERRUPT_DEC_E BIT(0) #define HEVC_DEC_MODE 0xc +#define VP9_DEC_MODE 0xd #define BUS_WIDTH_32 0 #define BUS_WIDTH_64 1 @@ -49,6 +50,7 @@ #define g2_pic_height_in_cbs G2_DEC_REG(4, 6, 0x1fff) #define g2_num_ref_frames G2_DEC_REG(4, 0, 0x1f) +#define g2_start_bit G2_DEC_REG(5, 25, 0x7f) #define g2_scaling_list_e G2_DEC_REG(5, 24, 0x1) #define g2_cb_qp_offset G2_DEC_REG(5, 19, 0x1f) #define g2_cr_qp_offset G2_DEC_REG(5, 14, 0x1f) @@ -84,6 +86,7 @@ #define g2_bit_depth_y_minus8 G2_DEC_REG(8, 6, 0x3) #define g2_bit_depth_c_minus8 G2_DEC_REG(8, 4, 0x3) #define g2_output_8_bits G2_DEC_REG(8, 3, 0x1) +#define g2_output_format G2_DEC_REG(8, 0, 0x7) #define g2_refidx1_active G2_DEC_REG(9, 19, 0x1f) #define g2_refidx0_active G2_DEC_REG(9, 14, 0x1f) @@ -96,6 +99,14 @@ #define g2_tile_e G2_DEC_REG(10, 1, 0x1) #define g2_entropy_sync_e G2_DEC_REG(10, 0, 0x1) +#define vp9_transform_mode G2_DEC_REG(11, 27, 0x7) +#define vp9_filt_sharpness G2_DEC_REG(11, 21, 0x7) +#define vp9_mcomp_filt_type G2_DEC_REG(11, 8, 0x7) +#define vp9_high_prec_mv_e G2_DEC_REG(11, 7, 0x1) +#define vp9_comp_pred_mode G2_DEC_REG(11, 4, 0x3) +#define vp9_gref_sign_bias G2_DEC_REG(11, 2, 0x1) +#define vp9_aref_sign_bias G2_DEC_REG(11, 0, 0x1) + #define g2_refer_lterm_e G2_DEC_REG(12, 16, 0xffff) #define g2_min_cb_size G2_DEC_REG(12, 13, 0x7) #define g2_max_cb_size G2_DEC_REG(12, 10, 0x7) @@ -154,6 +165,50 @@ #define g2_partial_ctb_y G2_DEC_REG(20, 30, 0x1) #define g2_pic_width_4x4 G2_DEC_REG(20, 16, 0xfff) #define g2_pic_height_4x4 G2_DEC_REG(20, 0, 0xfff) + +#define vp9_qp_delta_y_dc G2_DEC_REG(13, 23, 0x3f) +#define vp9_qp_delta_ch_dc G2_DEC_REG(13, 17, 0x3f) +#define vp9_qp_delta_ch_ac G2_DEC_REG(13, 11, 0x3f) +#define vp9_last_sign_bias G2_DEC_REG(13, 10, 0x1) +#define vp9_lossless_e G2_DEC_REG(13, 9, 0x1) +#define vp9_comp_pred_var_ref1 G2_DEC_REG(13, 7, 0x3) +#define vp9_comp_pred_var_ref0 G2_DEC_REG(13, 5, 0x3) +#define vp9_comp_pred_fixed_ref G2_DEC_REG(13, 3, 0x3) +#define vp9_segment_temp_upd_e G2_DEC_REG(13, 2, 0x1) +#define vp9_segment_upd_e G2_DEC_REG(13, 1, 0x1) +#define vp9_segment_e G2_DEC_REG(13, 0, 0x1) + +#define vp9_filt_level G2_DEC_REG(14, 18, 0x3f) +#define vp9_refpic_seg0 G2_DEC_REG(14, 15, 0x7) +#define vp9_skip_seg0 G2_DEC_REG(14, 14, 0x1) +#define vp9_filt_level_seg0 G2_DEC_REG(14, 8, 0x3f) +#define vp9_quant_seg0 G2_DEC_REG(14, 0, 0xff) + +#define vp9_refpic_seg1 G2_DEC_REG(15, 15, 0x7) +#define vp9_skip_seg1 G2_DEC_REG(15, 14, 0x1) +#define vp9_filt_level_seg1 G2_DEC_REG(15, 8, 0x3f) +#define vp9_quant_seg1 G2_DEC_REG(15, 0, 0xff) + +#define vp9_refpic_seg2 G2_DEC_REG(16, 15, 0x7) +#define vp9_skip_seg2 G2_DEC_REG(16, 14, 0x1) +#define vp9_filt_level_seg2 G2_DEC_REG(16, 8, 0x3f) +#define vp9_quant_seg2 G2_DEC_REG(16, 0, 0xff) + +#define vp9_refpic_seg3 G2_DEC_REG(17, 15, 0x7) +#define vp9_skip_seg3 G2_DEC_REG(17, 14, 0x1) +#define vp9_filt_level_seg3 G2_DEC_REG(17, 8, 0x3f) +#define vp9_quant_seg3 G2_DEC_REG(17, 0, 0xff) + +#define vp9_refpic_seg4 G2_DEC_REG(18, 15, 0x7) +#define vp9_skip_seg4 G2_DEC_REG(18, 14, 0x1) +#define vp9_filt_level_seg4 G2_DEC_REG(18, 8, 0x3f) +#define vp9_quant_seg4 G2_DEC_REG(18, 0, 0xff) + +#define vp9_refpic_seg5 G2_DEC_REG(19, 15, 0x7) +#define vp9_skip_seg5 G2_DEC_REG(19, 14, 0x1) +#define vp9_filt_level_seg5 G2_DEC_REG(19, 8, 0x3f) +#define vp9_quant_seg5 G2_DEC_REG(19, 0, 0xff) + #define hevc_cur_poc_00 G2_DEC_REG(46, 24, 0xff) #define hevc_cur_poc_01 G2_DEC_REG(46, 16, 0xff) #define hevc_cur_poc_02 G2_DEC_REG(46, 8, 0xff) @@ -174,6 +229,44 @@ #define hevc_cur_poc_14 G2_DEC_REG(49, 8, 0xff) #define hevc_cur_poc_15 G2_DEC_REG(49, 0, 0xff) +#define vp9_refpic_seg6 G2_DEC_REG(31, 15, 0x7) +#define vp9_skip_seg6 G2_DEC_REG(31, 14, 0x1) +#define vp9_filt_level_seg6 G2_DEC_REG(31, 8, 0x3f) +#define vp9_quant_seg6 G2_DEC_REG(31, 0, 0xff) + +#define vp9_refpic_seg7 G2_DEC_REG(32, 15, 0x7) +#define vp9_skip_seg7 G2_DEC_REG(32, 14, 0x1) +#define vp9_filt_level_seg7 G2_DEC_REG(32, 8, 0x3f) +#define vp9_quant_seg7 G2_DEC_REG(32, 0, 0xff) + +#define vp9_lref_width G2_DEC_REG(33, 16, 0xffff) +#define vp9_lref_height G2_DEC_REG(33, 0, 0xffff) + +#define vp9_gref_width G2_DEC_REG(34, 16, 0xffff) +#define vp9_gref_height G2_DEC_REG(34, 0, 0xffff) + +#define vp9_aref_width G2_DEC_REG(35, 16, 0xffff) +#define vp9_aref_height G2_DEC_REG(35, 0, 0xffff) + +#define vp9_lref_hor_scale G2_DEC_REG(36, 16, 0xffff) +#define vp9_lref_ver_scale G2_DEC_REG(36, 0, 0xffff) + +#define vp9_gref_hor_scale G2_DEC_REG(37, 16, 0xffff) +#define vp9_gref_ver_scale G2_DEC_REG(37, 0, 0xffff) + +#define vp9_aref_hor_scale G2_DEC_REG(38, 16, 0xffff) +#define vp9_aref_ver_scale G2_DEC_REG(38, 0, 0xffff) + +#define vp9_filt_ref_adj_0 G2_DEC_REG(46, 24, 0x7f) +#define vp9_filt_ref_adj_1 G2_DEC_REG(46, 16, 0x7f) +#define vp9_filt_ref_adj_2 G2_DEC_REG(46, 8, 0x7f) +#define vp9_filt_ref_adj_3 G2_DEC_REG(46, 0, 0x7f) + +#define vp9_filt_mb_adj_0 G2_DEC_REG(47, 24, 0x7f) +#define vp9_filt_mb_adj_1 G2_DEC_REG(47, 16, 0x7f) +#define vp9_filt_mb_adj_2 G2_DEC_REG(47, 8, 0x7f) +#define vp9_filt_mb_adj_3 G2_DEC_REG(47, 0, 0x7f) + #define g2_apf_threshold G2_DEC_REG(55, 0, 0xffff) #define g2_clk_gate_e G2_DEC_REG(58, 16, 0x1) @@ -186,6 +279,8 @@ #define G2_OUT_LUMA_ADDR (G2_SWREG(65)) #define G2_REF_LUMA_ADDR(i) (G2_SWREG(67) + ((i) * 0x8)) +#define G2_VP9_SEGMENT_WRITE_ADDR (G2_SWREG(79)) +#define G2_VP9_SEGMENT_READ_ADDR (G2_SWREG(81)) #define G2_OUT_CHROMA_ADDR (G2_SWREG(99)) #define G2_REF_CHROMA_ADDR(i) (G2_SWREG(101) + ((i) * 0x8)) #define G2_OUT_MV_ADDR (G2_SWREG(133)) @@ -193,6 +288,8 @@ #define G2_TILE_SIZES_ADDR (G2_SWREG(167)) #define G2_STREAM_ADDR (G2_SWREG(169)) #define G2_HEVC_SCALING_LIST_ADDR (G2_SWREG(171)) +#define G2_VP9_CTX_COUNT_ADDR (G2_SWREG(171)) +#define G2_VP9_PROBS_ADDR (G2_SWREG(173)) #define G2_RS_OUT_LUMA_ADDR (G2_SWREG(175)) #define G2_RS_OUT_CHROMA_ADDR (G2_SWREG(177)) #define G2_TILE_FILTER_ADDR (G2_SWREG(179)) diff --git a/drivers/staging/media/hantro/hantro_g2_vp9_dec.c b/drivers/staging/media/hantro/hantro_g2_vp9_dec.c new file mode 100644 index 000000000000..fc55b03a8004 --- /dev/null +++ b/drivers/staging/media/hantro/hantro_g2_vp9_dec.c @@ -0,0 +1,980 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hantro VP9 codec driver + * + * Copyright (C) 2021 Collabora Ltd. + */ +#include "media/videobuf2-core.h" +#include "media/videobuf2-dma-contig.h" +#include "media/videobuf2-v4l2.h" +#include +#include +#include +#include + +#include "hantro.h" +#include "hantro_vp9.h" +#include "hantro_g2_regs.h" + +#define G2_ALIGN 16 + +enum hantro_ref_frames { + INTRA_FRAME = 0, + LAST_FRAME = 1, + GOLDEN_FRAME = 2, + ALTREF_FRAME = 3, + MAX_REF_FRAMES = 4 +}; + +static int start_prepare_run(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame **dec_params) +{ + const struct v4l2_ctrl_vp9_compressed_hdr *prob_updates; + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + struct v4l2_ctrl *ctrl; + unsigned int fctx_idx; + + /* v4l2-specific stuff */ + hantro_start_prepare_run(ctx); + + ctrl = v4l2_ctrl_find(&ctx->ctrl_handler, V4L2_CID_STATELESS_VP9_FRAME); + if (WARN_ON(!ctrl)) + return -EINVAL; + *dec_params = ctrl->p_cur.p; + + ctrl = v4l2_ctrl_find(&ctx->ctrl_handler, V4L2_CID_STATELESS_VP9_COMPRESSED_HDR); + if (WARN_ON(!ctrl)) + return -EINVAL; + prob_updates = ctrl->p_cur.p; + vp9_ctx->cur.tx_mode = prob_updates->tx_mode; + + /* + * vp9 stuff + * + * by this point the userspace has done all parts of 6.2 uncompressed_header() + * except this fragment: + * if ( FrameIsIntra || error_resilient_mode ) { + * setup_past_independence ( ) + * if ( frame_type == KEY_FRAME || error_resilient_mode == 1 || + * reset_frame_context == 3 ) { + * for ( i = 0; i < 4; i ++ ) { + * save_probs( i ) + * } + * } else if ( reset_frame_context == 2 ) { + * save_probs( frame_context_idx ) + * } + * frame_context_idx = 0 + * } + */ + fctx_idx = v4l2_vp9_reset_frame_ctx(*dec_params, vp9_ctx->frame_context); + vp9_ctx->cur.frame_context_idx = fctx_idx; + + /* 6.1 frame(sz): load_probs() and load_probs2() */ + vp9_ctx->probability_tables = vp9_ctx->frame_context[fctx_idx]; + + /* + * The userspace has also performed 6.3 compressed_header(), but handling the + * probs in a special way. All probs which need updating, except MV-related, + * have been read from the bitstream and translated through inv_map_table[], + * but no 6.3.6 inv_recenter_nonneg(v, m) has been performed. The values passed + * by userspace are either translated values (there are no 0 values in + * inv_map_table[]), or zero to indicate no update. All MV-related probs which need + * updating have been read from the bitstream and (mv_prob << 1) | 1 has been + * performed. The values passed by userspace are either new values + * to replace old ones (the above mentioned shift and bitwise or never result in + * a zero) or zero to indicate no update. + * fw_update_probs() performs actual probs updates or leaves probs as-is + * for values for which a zero was passed from userspace. + */ + v4l2_vp9_fw_update_probs(&vp9_ctx->probability_tables, prob_updates, *dec_params); + + return 0; +} + +static size_t chroma_offset(const struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + int bytes_per_pixel = dec_params->bit_depth == 8 ? 1 : 2; + + return ctx->src_fmt.width * ctx->src_fmt.height * bytes_per_pixel; +} + +static size_t mv_offset(const struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + size_t cr_offset = chroma_offset(ctx, dec_params); + + return ALIGN((cr_offset * 3) / 2, G2_ALIGN); +} + +static struct hantro_decoded_buffer * +get_ref_buf(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp) +{ + struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; + struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; + int buf_idx; + + /* + * If a ref is unused or invalid, address of current destination + * buffer is returned. + */ + buf_idx = vb2_find_timestamp(cap_q, timestamp, 0); + if (buf_idx < 0) + return vb2_to_hantro_decoded_buf(&dst->vb2_buf); + + return vb2_to_hantro_decoded_buf(vb2_get_buffer(cap_q, buf_idx)); +} + +static void update_dec_buf_info(struct hantro_decoded_buffer *buf, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + buf->vp9.width = dec_params->frame_width_minus_1 + 1; + buf->vp9.height = dec_params->frame_height_minus_1 + 1; + buf->vp9.bit_depth = dec_params->bit_depth; +} + +static void update_ctx_cur_info(struct hantro_vp9_dec_hw_ctx *vp9_ctx, + struct hantro_decoded_buffer *buf, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + vp9_ctx->cur.valid = true; + vp9_ctx->cur.reference_mode = dec_params->reference_mode; + vp9_ctx->cur.interpolation_filter = dec_params->interpolation_filter; + vp9_ctx->cur.flags = dec_params->flags; + vp9_ctx->cur.timestamp = buf->base.vb.vb2_buf.timestamp; +} + +static void config_output(struct hantro_ctx *ctx, + struct hantro_decoded_buffer *dst, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + dma_addr_t luma_addr, chroma_addr, mv_addr; + + hantro_reg_write(ctx->dev, &g2_out_dis, 0); + hantro_reg_write(ctx->dev, &g2_output_format, 0); + + luma_addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0); + hantro_write_addr(ctx->dev, G2_OUT_LUMA_ADDR, luma_addr); + + chroma_addr = luma_addr + chroma_offset(ctx, dec_params); + hantro_write_addr(ctx->dev, G2_OUT_CHROMA_ADDR, chroma_addr); + + mv_addr = luma_addr + mv_offset(ctx, dec_params); + hantro_write_addr(ctx->dev, G2_OUT_MV_ADDR, mv_addr); +} + +struct hantro_vp9_ref_reg { + const struct hantro_reg width; + const struct hantro_reg height; + const struct hantro_reg hor_scale; + const struct hantro_reg ver_scale; + u32 y_base; + u32 c_base; +}; + +static void config_ref(struct hantro_ctx *ctx, + struct hantro_decoded_buffer *dst, + const struct hantro_vp9_ref_reg *ref_reg, + const struct v4l2_ctrl_vp9_frame *dec_params, + u64 ref_ts) +{ + struct hantro_decoded_buffer *buf; + dma_addr_t luma_addr, chroma_addr; + u32 refw, refh; + + buf = get_ref_buf(ctx, &dst->base.vb, ref_ts); + refw = buf->vp9.width; + refh = buf->vp9.height; + + hantro_reg_write(ctx->dev, &ref_reg->width, refw); + hantro_reg_write(ctx->dev, &ref_reg->height, refh); + + hantro_reg_write(ctx->dev, &ref_reg->hor_scale, (refw << 14) / dst->vp9.width); + hantro_reg_write(ctx->dev, &ref_reg->ver_scale, (refh << 14) / dst->vp9.height); + + luma_addr = vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0); + hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr); + + chroma_addr = luma_addr + chroma_offset(ctx, dec_params); + hantro_write_addr(ctx->dev, ref_reg->c_base, chroma_addr); +} + +static void config_ref_registers(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp9_frame *dec_params, + struct hantro_decoded_buffer *dst, + struct hantro_decoded_buffer *mv_ref) +{ + static const struct hantro_vp9_ref_reg ref_regs[] = { + { + /* Last */ + .width = vp9_lref_width, + .height = vp9_lref_height, + .hor_scale = vp9_lref_hor_scale, + .ver_scale = vp9_lref_ver_scale, + .y_base = G2_REF_LUMA_ADDR(0), + .c_base = G2_REF_CHROMA_ADDR(0), + }, { + /* Golden */ + .width = vp9_gref_width, + .height = vp9_gref_height, + .hor_scale = vp9_gref_hor_scale, + .ver_scale = vp9_gref_ver_scale, + .y_base = G2_REF_LUMA_ADDR(4), + .c_base = G2_REF_CHROMA_ADDR(4), + }, { + /* Altref */ + .width = vp9_aref_width, + .height = vp9_aref_height, + .hor_scale = vp9_aref_hor_scale, + .ver_scale = vp9_aref_ver_scale, + .y_base = G2_REF_LUMA_ADDR(5), + .c_base = G2_REF_CHROMA_ADDR(5), + }, + }; + dma_addr_t mv_addr; + + config_ref(ctx, dst, &ref_regs[0], dec_params, dec_params->last_frame_ts); + config_ref(ctx, dst, &ref_regs[1], dec_params, dec_params->golden_frame_ts); + config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts); + + mv_addr = vb2_dma_contig_plane_dma_addr(&mv_ref->base.vb.vb2_buf, 0) + + mv_offset(ctx, dec_params); + hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr); + + hantro_reg_write(ctx->dev, &vp9_last_sign_bias, + dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_LAST ? 1 : 0); + + hantro_reg_write(ctx->dev, &vp9_gref_sign_bias, + dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_GOLDEN ? 1 : 0); + + hantro_reg_write(ctx->dev, &vp9_aref_sign_bias, + dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_ALT ? 1 : 0); +} + +static void recompute_tile_info(unsigned short *tile_info, unsigned int tiles, unsigned int sbs) +{ + int i; + unsigned int accumulated = 0; + unsigned int next_accumulated; + + for (i = 1; i <= tiles; ++i) { + next_accumulated = i * sbs / tiles; + *tile_info++ = next_accumulated - accumulated; + accumulated = next_accumulated; + } +} + +static void +recompute_tile_rc_info(struct hantro_ctx *ctx, + unsigned int tile_r, unsigned int tile_c, + unsigned int sbs_r, unsigned int sbs_c) +{ + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + + recompute_tile_info(vp9_ctx->tile_r_info, tile_r, sbs_r); + recompute_tile_info(vp9_ctx->tile_c_info, tile_c, sbs_c); + + vp9_ctx->last_tile_r = tile_r; + vp9_ctx->last_tile_c = tile_c; + vp9_ctx->last_sbs_r = sbs_r; + vp9_ctx->last_sbs_c = sbs_c; +} + +static inline unsigned int first_tile_row(unsigned int tile_r, unsigned int sbs_r) +{ + if (tile_r == sbs_r + 1) + return 1; + + if (tile_r == sbs_r + 2) + return 2; + + return 0; +} + +static void +fill_tile_info(struct hantro_ctx *ctx, + unsigned int tile_r, unsigned int tile_c, + unsigned int sbs_r, unsigned int sbs_c, + unsigned short *tile_mem) +{ + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + unsigned int i, j; + bool first = true; + + for (i = first_tile_row(tile_r, sbs_r); i < tile_r; ++i) { + unsigned short r_info = vp9_ctx->tile_r_info[i]; + + if (first) { + if (i > 0) + r_info += vp9_ctx->tile_r_info[0]; + if (i == 2) + r_info += vp9_ctx->tile_r_info[1]; + first = false; + } + for (j = 0; j < tile_c; ++j) { + *tile_mem++ = vp9_ctx->tile_c_info[j]; + *tile_mem++ = r_info; + } + } +} + +static void +config_tiles(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp9_frame *dec_params, + struct hantro_decoded_buffer *dst) +{ + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + struct hantro_aux_buf *misc = &vp9_ctx->misc; + struct hantro_aux_buf *tile_edge = &vp9_ctx->tile_edge; + dma_addr_t addr; + unsigned short *tile_mem; + + addr = misc->dma + vp9_ctx->tile_info_offset; + hantro_write_addr(ctx->dev, G2_TILE_SIZES_ADDR, addr); + + tile_mem = misc->cpu + vp9_ctx->tile_info_offset; + if (dec_params->tile_cols_log2 || dec_params->tile_rows_log2) { + unsigned int tile_r = (1 << dec_params->tile_rows_log2); + unsigned int tile_c = (1 << dec_params->tile_cols_log2); + unsigned int sbs_r = hantro_vp9_num_sbs(dst->vp9.height); + unsigned int sbs_c = hantro_vp9_num_sbs(dst->vp9.width); + + if (tile_r != vp9_ctx->last_tile_r || tile_c != vp9_ctx->last_tile_c || + sbs_r != vp9_ctx->last_sbs_r || sbs_c != vp9_ctx->last_sbs_c) + recompute_tile_rc_info(ctx, tile_r, tile_c, sbs_r, sbs_c); + + fill_tile_info(ctx, tile_r, tile_c, sbs_r, sbs_c, tile_mem); + + hantro_reg_write(ctx->dev, &g2_tile_e, 1); + hantro_reg_write(ctx->dev, &g2_num_tile_cols, tile_c); + hantro_reg_write(ctx->dev, &g2_num_tile_rows, tile_r); + + } else { + tile_mem[0] = hantro_vp9_num_sbs(dst->vp9.width); + tile_mem[1] = hantro_vp9_num_sbs(dst->vp9.height); + + hantro_reg_write(ctx->dev, &g2_tile_e, 0); + hantro_reg_write(ctx->dev, &g2_num_tile_cols, 1); + hantro_reg_write(ctx->dev, &g2_num_tile_rows, 1); + } + + /* provide aux buffers even if no tiles are used */ + addr = tile_edge->dma; + hantro_write_addr(ctx->dev, G2_TILE_FILTER_ADDR, addr); + + addr = tile_edge->dma + vp9_ctx->bsd_ctrl_offset; + hantro_write_addr(ctx->dev, G2_TILE_BSD_ADDR, addr); +} + +static void +update_feat_and_flag(struct hantro_vp9_dec_hw_ctx *vp9_ctx, + const struct v4l2_vp9_segmentation *seg, + unsigned int feature, + unsigned int segid) +{ + u8 mask = V4L2_VP9_SEGMENT_FEATURE_ENABLED(feature); + + vp9_ctx->feature_data[segid][feature] = seg->feature_data[segid][feature]; + vp9_ctx->feature_enabled[segid] &= ~mask; + vp9_ctx->feature_enabled[segid] |= (seg->feature_enabled[segid] & mask); +} + +static inline s16 clip3(s16 x, s16 y, s16 z) +{ + return (z < x) ? x : (z > y) ? y : z; +} + +static s16 feat_val_clip3(s16 feat_val, s16 feature_data, bool absolute, u8 clip) +{ + if (absolute) + return feature_data; + + return clip3(0, 255, feat_val + feature_data); +} + +static void config_segment(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params) +{ + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + const struct v4l2_vp9_segmentation *seg; + s16 feat_val; + unsigned char feat_id; + unsigned int segid; + bool segment_enabled, absolute, update_data; + + static const struct hantro_reg seg_regs[8][V4L2_VP9_SEG_LVL_MAX] = { + { vp9_quant_seg0, vp9_filt_level_seg0, vp9_refpic_seg0, vp9_skip_seg0 }, + { vp9_quant_seg1, vp9_filt_level_seg1, vp9_refpic_seg1, vp9_skip_seg1 }, + { vp9_quant_seg2, vp9_filt_level_seg2, vp9_refpic_seg2, vp9_skip_seg2 }, + { vp9_quant_seg3, vp9_filt_level_seg3, vp9_refpic_seg3, vp9_skip_seg3 }, + { vp9_quant_seg4, vp9_filt_level_seg4, vp9_refpic_seg4, vp9_skip_seg4 }, + { vp9_quant_seg5, vp9_filt_level_seg5, vp9_refpic_seg5, vp9_skip_seg5 }, + { vp9_quant_seg6, vp9_filt_level_seg6, vp9_refpic_seg6, vp9_skip_seg6 }, + { vp9_quant_seg7, vp9_filt_level_seg7, vp9_refpic_seg7, vp9_skip_seg7 }, + }; + + segment_enabled = !!(dec_params->seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED); + hantro_reg_write(ctx->dev, &vp9_segment_e, segment_enabled); + hantro_reg_write(ctx->dev, &vp9_segment_upd_e, + !!(dec_params->seg.flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP)); + hantro_reg_write(ctx->dev, &vp9_segment_temp_upd_e, + !!(dec_params->seg.flags & V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE)); + + seg = &dec_params->seg; + absolute = !!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE); + update_data = !!(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA); + + for (segid = 0; segid < 8; ++segid) { + /* Quantizer segment feature */ + feat_id = V4L2_VP9_SEG_LVL_ALT_Q; + feat_val = dec_params->quant.base_q_idx; + if (segment_enabled) { + if (update_data) + update_feat_and_flag(vp9_ctx, seg, feat_id, segid); + if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid)) + feat_val = feat_val_clip3(feat_val, + vp9_ctx->feature_data[segid][feat_id], + absolute, 255); + } + hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val); + + /* Loop filter segment feature */ + feat_id = V4L2_VP9_SEG_LVL_ALT_L; + feat_val = dec_params->lf.level; + if (segment_enabled) { + if (update_data) + update_feat_and_flag(vp9_ctx, seg, feat_id, segid); + if (v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid)) + feat_val = feat_val_clip3(feat_val, + vp9_ctx->feature_data[segid][feat_id], + absolute, 63); + } + hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val); + + /* Reference frame segment feature */ + feat_id = V4L2_VP9_SEG_LVL_REF_FRAME; + feat_val = 0; + if (segment_enabled) { + if (update_data) + update_feat_and_flag(vp9_ctx, seg, feat_id, segid); + if (!(dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME) && + v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, feat_id, segid)) + feat_val = vp9_ctx->feature_data[segid][feat_id] + 1; + } + hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val); + + /* Skip segment feature */ + feat_id = V4L2_VP9_SEG_LVL_SKIP; + feat_val = 0; + if (segment_enabled) { + if (update_data) + update_feat_and_flag(vp9_ctx, seg, feat_id, segid); + feat_val = v4l2_vp9_seg_feat_enabled(vp9_ctx->feature_enabled, + feat_id, segid) ? 1 : 0; + } + hantro_reg_write(ctx->dev, &seg_regs[segid][feat_id], feat_val); + } +} + +static void config_loop_filter(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params) +{ + bool d = dec_params->lf.flags & V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED; + + hantro_reg_write(ctx->dev, &vp9_filt_level, dec_params->lf.level); + hantro_reg_write(ctx->dev, &g2_out_filtering_dis, dec_params->lf.level == 0); + hantro_reg_write(ctx->dev, &vp9_filt_sharpness, dec_params->lf.sharpness); + + hantro_reg_write(ctx->dev, &vp9_filt_ref_adj_0, d ? dec_params->lf.ref_deltas[0] : 0); + hantro_reg_write(ctx->dev, &vp9_filt_ref_adj_1, d ? dec_params->lf.ref_deltas[1] : 0); + hantro_reg_write(ctx->dev, &vp9_filt_ref_adj_2, d ? dec_params->lf.ref_deltas[2] : 0); + hantro_reg_write(ctx->dev, &vp9_filt_ref_adj_3, d ? dec_params->lf.ref_deltas[3] : 0); + hantro_reg_write(ctx->dev, &vp9_filt_mb_adj_0, d ? dec_params->lf.mode_deltas[0] : 0); + hantro_reg_write(ctx->dev, &vp9_filt_mb_adj_1, d ? dec_params->lf.mode_deltas[1] : 0); +} + +static void config_picture_dimensions(struct hantro_ctx *ctx, struct hantro_decoded_buffer *dst) +{ + u32 pic_w_4x4, pic_h_4x4; + + hantro_reg_write(ctx->dev, &g2_pic_width_in_cbs, (dst->vp9.width + 7) / 8); + hantro_reg_write(ctx->dev, &g2_pic_height_in_cbs, (dst->vp9.height + 7) / 8); + pic_w_4x4 = roundup(dst->vp9.width, 8) >> 2; + pic_h_4x4 = roundup(dst->vp9.height, 8) >> 2; + hantro_reg_write(ctx->dev, &g2_pic_width_4x4, pic_w_4x4); + hantro_reg_write(ctx->dev, &g2_pic_height_4x4, pic_h_4x4); +} + +static void +config_bit_depth(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params) +{ + hantro_reg_write(ctx->dev, &g2_bit_depth_y_minus8, dec_params->bit_depth - 8); + hantro_reg_write(ctx->dev, &g2_bit_depth_c_minus8, dec_params->bit_depth - 8); +} + +static inline bool is_lossless(const struct v4l2_vp9_quantization *quant) +{ + return quant->base_q_idx == 0 && quant->delta_q_uv_ac == 0 && + quant->delta_q_uv_dc == 0 && quant->delta_q_y_dc == 0; +} + +static void +config_quant(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params) +{ + hantro_reg_write(ctx->dev, &vp9_qp_delta_y_dc, dec_params->quant.delta_q_y_dc); + hantro_reg_write(ctx->dev, &vp9_qp_delta_ch_dc, dec_params->quant.delta_q_uv_dc); + hantro_reg_write(ctx->dev, &vp9_qp_delta_ch_ac, dec_params->quant.delta_q_uv_ac); + hantro_reg_write(ctx->dev, &vp9_lossless_e, is_lossless(&dec_params->quant)); +} + +static u32 +hantro_interp_filter_from_v4l2(unsigned int interpolation_filter) +{ + switch (interpolation_filter) { + case V4L2_VP9_INTERP_FILTER_EIGHTTAP: + return 0x1; + case V4L2_VP9_INTERP_FILTER_EIGHTTAP_SMOOTH: + return 0; + case V4L2_VP9_INTERP_FILTER_EIGHTTAP_SHARP: + return 0x2; + case V4L2_VP9_INTERP_FILTER_BILINEAR: + return 0x3; + case V4L2_VP9_INTERP_FILTER_SWITCHABLE: + return 0x4; + } + + return 0; +} + +static void +config_others(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params, + bool intra_only, bool resolution_change) +{ + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + + hantro_reg_write(ctx->dev, &g2_idr_pic_e, intra_only); + + hantro_reg_write(ctx->dev, &vp9_transform_mode, vp9_ctx->cur.tx_mode); + + hantro_reg_write(ctx->dev, &vp9_mcomp_filt_type, intra_only ? + 0 : hantro_interp_filter_from_v4l2(dec_params->interpolation_filter)); + + hantro_reg_write(ctx->dev, &vp9_high_prec_mv_e, + !!(dec_params->flags & V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV)); + + hantro_reg_write(ctx->dev, &vp9_comp_pred_mode, dec_params->reference_mode); + + hantro_reg_write(ctx->dev, &g2_tempor_mvp_e, + !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && + !(dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME) && + !(vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME) && + !(dec_params->flags & V4L2_VP9_FRAME_FLAG_INTRA_ONLY) && + !resolution_change && + vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME + ); + + hantro_reg_write(ctx->dev, &g2_write_mvs_e, + !(dec_params->flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME)); +} + +static void +config_compound_reference(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp9_frame *dec_params) +{ + u32 comp_fixed_ref, comp_var_ref[2]; + bool last_ref_frame_sign_bias; + bool golden_ref_frame_sign_bias; + bool alt_ref_frame_sign_bias; + bool comp_ref_allowed = 0; + + comp_fixed_ref = 0; + comp_var_ref[0] = 0; + comp_var_ref[1] = 0; + + last_ref_frame_sign_bias = dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_LAST; + golden_ref_frame_sign_bias = dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_GOLDEN; + alt_ref_frame_sign_bias = dec_params->ref_frame_sign_bias & V4L2_VP9_SIGN_BIAS_ALT; + + /* 6.3.12 Frame reference mode syntax */ + comp_ref_allowed |= golden_ref_frame_sign_bias != last_ref_frame_sign_bias; + comp_ref_allowed |= alt_ref_frame_sign_bias != last_ref_frame_sign_bias; + + if (comp_ref_allowed) { + if (last_ref_frame_sign_bias == + golden_ref_frame_sign_bias) { + comp_fixed_ref = ALTREF_FRAME; + comp_var_ref[0] = LAST_FRAME; + comp_var_ref[1] = GOLDEN_FRAME; + } else if (last_ref_frame_sign_bias == + alt_ref_frame_sign_bias) { + comp_fixed_ref = GOLDEN_FRAME; + comp_var_ref[0] = LAST_FRAME; + comp_var_ref[1] = ALTREF_FRAME; + } else { + comp_fixed_ref = LAST_FRAME; + comp_var_ref[0] = GOLDEN_FRAME; + comp_var_ref[1] = ALTREF_FRAME; + } + } + + hantro_reg_write(ctx->dev, &vp9_comp_pred_fixed_ref, comp_fixed_ref); + hantro_reg_write(ctx->dev, &vp9_comp_pred_var_ref0, comp_var_ref[0]); + hantro_reg_write(ctx->dev, &vp9_comp_pred_var_ref1, comp_var_ref[1]); +} + +#define INNER_LOOP \ +do { \ + for (m = 0; m < ARRAY_SIZE(adaptive->coef[0][0][0][0]); ++m) { \ + memcpy(adaptive->coef[i][j][k][l][m], \ + probs->coef[i][j][k][l][m], \ + sizeof(probs->coef[i][j][k][l][m])); \ + \ + adaptive->coef[i][j][k][l][m][3] = 0; \ + } \ +} while (0) + +static void config_probs(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params) +{ + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + struct hantro_aux_buf *misc = &vp9_ctx->misc; + struct hantro_g2_all_probs *all_probs = misc->cpu; + struct hantro_g2_probs *adaptive; + struct hantro_g2_mv_probs *mv; + const struct v4l2_vp9_segmentation *seg = &dec_params->seg; + const struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables; + int i, j, k, l, m; + + for (i = 0; i < ARRAY_SIZE(all_probs->kf_y_mode_prob); ++i) + for (j = 0; j < ARRAY_SIZE(all_probs->kf_y_mode_prob[0]); ++j) { + memcpy(all_probs->kf_y_mode_prob[i][j], + v4l2_vp9_kf_y_mode_prob[i][j], + ARRAY_SIZE(all_probs->kf_y_mode_prob[i][j])); + + all_probs->kf_y_mode_prob_tail[i][j][0] = + v4l2_vp9_kf_y_mode_prob[i][j][8]; + } + + memcpy(all_probs->mb_segment_tree_probs, seg->tree_probs, + sizeof(all_probs->mb_segment_tree_probs)); + + memcpy(all_probs->segment_pred_probs, seg->pred_probs, + sizeof(all_probs->segment_pred_probs)); + + for (i = 0; i < ARRAY_SIZE(all_probs->kf_uv_mode_prob); ++i) { + memcpy(all_probs->kf_uv_mode_prob[i], v4l2_vp9_kf_uv_mode_prob[i], + ARRAY_SIZE(all_probs->kf_uv_mode_prob[i])); + + all_probs->kf_uv_mode_prob_tail[i][0] = v4l2_vp9_kf_uv_mode_prob[i][8]; + } + + adaptive = &all_probs->probs; + + for (i = 0; i < ARRAY_SIZE(adaptive->inter_mode); ++i) { + memcpy(adaptive->inter_mode[i], probs->inter_mode[i], + ARRAY_SIZE(probs->inter_mode[i])); + + adaptive->inter_mode[i][3] = 0; + } + + memcpy(adaptive->is_inter, probs->is_inter, sizeof(adaptive->is_inter)); + + for (i = 0; i < ARRAY_SIZE(adaptive->uv_mode); ++i) { + memcpy(adaptive->uv_mode[i], probs->uv_mode[i], + sizeof(adaptive->uv_mode[i])); + adaptive->uv_mode_tail[i][0] = probs->uv_mode[i][8]; + } + + memcpy(adaptive->tx8, probs->tx8, sizeof(adaptive->tx8)); + memcpy(adaptive->tx16, probs->tx16, sizeof(adaptive->tx16)); + memcpy(adaptive->tx32, probs->tx32, sizeof(adaptive->tx32)); + + for (i = 0; i < ARRAY_SIZE(adaptive->y_mode); ++i) { + memcpy(adaptive->y_mode[i], probs->y_mode[i], + ARRAY_SIZE(adaptive->y_mode[i])); + + adaptive->y_mode_tail[i][0] = probs->y_mode[i][8]; + } + + for (i = 0; i < ARRAY_SIZE(adaptive->partition[0]); ++i) { + memcpy(adaptive->partition[0][i], v4l2_vp9_kf_partition_probs[i], + sizeof(v4l2_vp9_kf_partition_probs[i])); + + adaptive->partition[0][i][3] = 0; + } + + for (i = 0; i < ARRAY_SIZE(adaptive->partition[1]); ++i) { + memcpy(adaptive->partition[1][i], probs->partition[i], + sizeof(probs->partition[i])); + + adaptive->partition[1][i][3] = 0; + } + + memcpy(adaptive->interp_filter, probs->interp_filter, + sizeof(adaptive->interp_filter)); + + memcpy(adaptive->comp_mode, probs->comp_mode, sizeof(adaptive->comp_mode)); + + memcpy(adaptive->skip, probs->skip, sizeof(adaptive->skip)); + + mv = &adaptive->mv; + + memcpy(mv->joint, probs->mv.joint, sizeof(mv->joint)); + memcpy(mv->sign, probs->mv.sign, sizeof(mv->sign)); + memcpy(mv->class0_bit, probs->mv.class0_bit, sizeof(mv->class0_bit)); + memcpy(mv->fr, probs->mv.fr, sizeof(mv->fr)); + memcpy(mv->class0_hp, probs->mv.class0_hp, sizeof(mv->class0_hp)); + memcpy(mv->hp, probs->mv.hp, sizeof(mv->hp)); + memcpy(mv->classes, probs->mv.classes, sizeof(mv->classes)); + memcpy(mv->class0_fr, probs->mv.class0_fr, sizeof(mv->class0_fr)); + memcpy(mv->bits, probs->mv.bits, sizeof(mv->bits)); + + memcpy(adaptive->single_ref, probs->single_ref, sizeof(adaptive->single_ref)); + + memcpy(adaptive->comp_ref, probs->comp_ref, sizeof(adaptive->comp_ref)); + + for (i = 0; i < ARRAY_SIZE(adaptive->coef); ++i) + for (j = 0; j < ARRAY_SIZE(adaptive->coef[0]); ++j) + for (k = 0; k < ARRAY_SIZE(adaptive->coef[0][0]); ++k) + for (l = 0; l < ARRAY_SIZE(adaptive->coef[0][0][0]); ++l) + INNER_LOOP; + + hantro_write_addr(ctx->dev, G2_VP9_PROBS_ADDR, misc->dma); +} + +static void config_counts(struct hantro_ctx *ctx) +{ + struct hantro_vp9_dec_hw_ctx *vp9_dec = &ctx->vp9_dec; + struct hantro_aux_buf *misc = &vp9_dec->misc; + dma_addr_t addr = misc->dma + vp9_dec->ctx_counters_offset; + + hantro_write_addr(ctx->dev, G2_VP9_CTX_COUNT_ADDR, addr); +} + +static void config_seg_map(struct hantro_ctx *ctx, + const struct v4l2_ctrl_vp9_frame *dec_params, + bool intra_only, bool update_map) +{ + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + struct hantro_aux_buf *segment_map = &vp9_ctx->segment_map; + dma_addr_t addr; + + if (intra_only || + (dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT)) { + memset(segment_map->cpu, 0, segment_map->size); + memset(vp9_ctx->feature_data, 0, sizeof(vp9_ctx->feature_data)); + memset(vp9_ctx->feature_enabled, 0, sizeof(vp9_ctx->feature_enabled)); + } + + addr = segment_map->dma + vp9_ctx->active_segment * vp9_ctx->segment_map_size; + hantro_write_addr(ctx->dev, G2_VP9_SEGMENT_READ_ADDR, addr); + + addr = segment_map->dma + (1 - vp9_ctx->active_segment) * vp9_ctx->segment_map_size; + hantro_write_addr(ctx->dev, G2_VP9_SEGMENT_WRITE_ADDR, addr); + + if (update_map) + vp9_ctx->active_segment = 1 - vp9_ctx->active_segment; +} + +static void +config_source(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params, + struct vb2_v4l2_buffer *vb2_src) +{ + dma_addr_t stream_base, tmp_addr; + unsigned int headres_size; + u32 src_len, start_bit, src_buf_len; + + headres_size = dec_params->uncompressed_header_size + + dec_params->compressed_header_size; + + stream_base = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0); + hantro_write_addr(ctx->dev, G2_STREAM_ADDR, stream_base); + + tmp_addr = stream_base + headres_size; + start_bit = (tmp_addr & 0xf) * 8; + hantro_reg_write(ctx->dev, &g2_start_bit, start_bit); + + src_len = vb2_get_plane_payload(&vb2_src->vb2_buf, 0); + src_len += start_bit / 8 - headres_size; + hantro_reg_write(ctx->dev, &g2_stream_len, src_len); + + tmp_addr &= ~0xf; + hantro_reg_write(ctx->dev, &g2_strm_start_offset, tmp_addr - stream_base); + src_buf_len = vb2_plane_size(&vb2_src->vb2_buf, 0); + hantro_reg_write(ctx->dev, &g2_strm_buffer_len, src_buf_len); +} + +static void +config_registers(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params, + struct vb2_v4l2_buffer *vb2_src, struct vb2_v4l2_buffer *vb2_dst) +{ + struct hantro_decoded_buffer *dst, *last, *mv_ref; + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + const struct v4l2_vp9_segmentation *seg; + bool intra_only, resolution_change; + + /* vp9 stuff */ + dst = vb2_to_hantro_decoded_buf(&vb2_dst->vb2_buf); + + if (vp9_ctx->last.valid) + last = get_ref_buf(ctx, &dst->base.vb, vp9_ctx->last.timestamp); + else + last = dst; + + update_dec_buf_info(dst, dec_params); + update_ctx_cur_info(vp9_ctx, dst, dec_params); + seg = &dec_params->seg; + + intra_only = !!(dec_params->flags & + (V4L2_VP9_FRAME_FLAG_KEY_FRAME | + V4L2_VP9_FRAME_FLAG_INTRA_ONLY)); + + if (!intra_only && + !(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) && + vp9_ctx->last.valid) + mv_ref = last; + else + mv_ref = dst; + + resolution_change = dst->vp9.width != last->vp9.width || + dst->vp9.height != last->vp9.height; + + /* configure basic registers */ + hantro_reg_write(ctx->dev, &g2_mode, VP9_DEC_MODE); + hantro_reg_write(ctx->dev, &g2_strm_swap, 0xf); + hantro_reg_write(ctx->dev, &g2_dirmv_swap, 0xf); + hantro_reg_write(ctx->dev, &g2_compress_swap, 0xf); + hantro_reg_write(ctx->dev, &g2_buswidth, BUS_WIDTH_128); + hantro_reg_write(ctx->dev, &g2_max_burst, 16); + hantro_reg_write(ctx->dev, &g2_apf_threshold, 8); + hantro_reg_write(ctx->dev, &g2_ref_compress_bypass, 1); + hantro_reg_write(ctx->dev, &g2_clk_gate_e, 1); + hantro_reg_write(ctx->dev, &g2_max_cb_size, 6); + hantro_reg_write(ctx->dev, &g2_min_cb_size, 3); + + config_output(ctx, dst, dec_params); + + if (!intra_only) + config_ref_registers(ctx, dec_params, dst, mv_ref); + + config_tiles(ctx, dec_params, dst); + config_segment(ctx, dec_params); + config_loop_filter(ctx, dec_params); + config_picture_dimensions(ctx, dst); + config_bit_depth(ctx, dec_params); + config_quant(ctx, dec_params); + config_others(ctx, dec_params, intra_only, resolution_change); + config_compound_reference(ctx, dec_params); + config_probs(ctx, dec_params); + config_counts(ctx); + config_seg_map(ctx, dec_params, intra_only, + seg->flags & V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP); + config_source(ctx, dec_params, vb2_src); +} + +int hantro_g2_vp9_dec_run(struct hantro_ctx *ctx) +{ + const struct v4l2_ctrl_vp9_frame *decode_params; + struct vb2_v4l2_buffer *src; + struct vb2_v4l2_buffer *dst; + int ret; + + hantro_g2_check_idle(ctx->dev); + + ret = start_prepare_run(ctx, &decode_params); + if (ret) { + hantro_end_prepare_run(ctx); + return ret; + } + + src = hantro_get_src_buf(ctx); + dst = hantro_get_dst_buf(ctx); + + config_registers(ctx, decode_params, src, dst); + + hantro_end_prepare_run(ctx); + + vdpu_write(ctx->dev, G2_REG_INTERRUPT_DEC_E, G2_REG_INTERRUPT); + + return 0; +} + +#define copy_tx_and_skip(p1, p2) \ +do { \ + memcpy((p1)->tx8, (p2)->tx8, sizeof((p1)->tx8)); \ + memcpy((p1)->tx16, (p2)->tx16, sizeof((p1)->tx16)); \ + memcpy((p1)->tx32, (p2)->tx32, sizeof((p1)->tx32)); \ + memcpy((p1)->skip, (p2)->skip, sizeof((p1)->skip)); \ +} while (0) + +void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx) +{ + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + unsigned int fctx_idx; + + if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX)) + goto out_update_last; + + fctx_idx = vp9_ctx->cur.frame_context_idx; + + if (!(vp9_ctx->cur.flags & V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE)) { + /* error_resilient_mode == 0 && frame_parallel_decoding_mode == 0 */ + struct v4l2_vp9_frame_context *probs = &vp9_ctx->probability_tables; + bool frame_is_intra = vp9_ctx->cur.flags & + (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY); + struct tx_and_skip { + u8 tx8[2][1]; + u8 tx16[2][2]; + u8 tx32[2][3]; + u8 skip[3]; + } _tx_skip, *tx_skip = &_tx_skip; + struct v4l2_vp9_frame_symbol_counts *counts; + struct symbol_counts *hantro_cnts; + u32 tx16p[2][4]; + int i; + + /* buffer the forward-updated TX and skip probs */ + if (frame_is_intra) + copy_tx_and_skip(tx_skip, probs); + + /* 6.1.2 refresh_probs(): load_probs() and load_probs2() */ + *probs = vp9_ctx->frame_context[fctx_idx]; + + /* if FrameIsIntra then undo the effect of load_probs2() */ + if (frame_is_intra) + copy_tx_and_skip(probs, tx_skip); + + counts = &vp9_ctx->cnts; + hantro_cnts = vp9_ctx->misc.cpu + vp9_ctx->ctx_counters_offset; + for (i = 0; i < ARRAY_SIZE(tx16p); ++i) { + memcpy(tx16p[i], + hantro_cnts->tx16x16_count[i], + sizeof(hantro_cnts->tx16x16_count[0])); + tx16p[i][3] = 0; + } + counts->tx16p = &tx16p; + + v4l2_vp9_adapt_coef_probs(probs, counts, + !vp9_ctx->last.valid || + vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_KEY_FRAME, + frame_is_intra); + + if (!frame_is_intra) { + /* load_probs2() already done */ + u32 mv_mode[7][4]; + + for (i = 0; i < ARRAY_SIZE(mv_mode); ++i) { + mv_mode[i][0] = hantro_cnts->inter_mode_counts[i][1][0]; + mv_mode[i][1] = hantro_cnts->inter_mode_counts[i][2][0]; + mv_mode[i][2] = hantro_cnts->inter_mode_counts[i][0][0]; + mv_mode[i][3] = hantro_cnts->inter_mode_counts[i][2][1]; + } + counts->mv_mode = &mv_mode; + v4l2_vp9_adapt_noncoef_probs(&vp9_ctx->probability_tables, counts, + vp9_ctx->cur.reference_mode, + vp9_ctx->cur.interpolation_filter, + vp9_ctx->cur.tx_mode, vp9_ctx->cur.flags); + } + } + + vp9_ctx->frame_context[fctx_idx] = vp9_ctx->probability_tables; + +out_update_last: + vp9_ctx->last = vp9_ctx->cur; +} diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 1d869abf90b2..fe5b51046d33 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #define DEC_8190_ALIGN_MASK 0x07U @@ -165,6 +166,82 @@ struct hantro_vp8_dec_hw_ctx { struct hantro_aux_buf prob_tbl; }; +/** + * struct hantro_vp9_frame_info + * + * @valid: frame info valid flag + * @frame_context_idx: index of frame context + * @reference_mode: inter prediction type + * @tx_mode: transform mode + * @interpolation_filter: filter selection for inter prediction + * @flags: frame flags + * @timestamp: frame timestamp + */ +struct hantro_vp9_frame_info { + u32 valid : 1; + u32 frame_context_idx : 2; + u32 reference_mode : 2; + u32 tx_mode : 3; + u32 interpolation_filter : 3; + u32 flags; + u64 timestamp; +}; + +#define MAX_SB_COLS 64 +#define MAX_SB_ROWS 34 + +/** + * struct hantro_vp9_dec_hw_ctx + * + * @tile_edge: auxiliary DMA buffer for tile edge processing + * @segment_map: auxiliary DMA buffer for segment map + * @misc: auxiliary DMA buffer for tile info, probabilities and hw counters + * @cnts: vp9 library struct for abstracting hw counters access + * @probability_tables: VP9 probability tables implied by the spec + * @frame_context: VP9 frame contexts + * @cur: current frame information + * @last: last frame information + * @bsd_ctrl_offset: bsd offset into tile_edge + * @segment_map_size: size of segment map + * @ctx_counters_offset: hw counters offset into misc + * @tile_info_offset: tile info offset into misc + * @tile_r_info: per-tile information array + * @tile_c_info: per-tile information array + * @last_tile_r: last number of tile rows + * @last_tile_c: last number of tile cols + * @last_sbs_r: last number of superblock rows + * @last_sbs_c: last number of superblock cols + * @active_segment: number of active segment (alternating between 0 and 1) + * @feature_enabled: segmentation feature enabled flags + * @feature_data: segmentation feature data + */ +struct hantro_vp9_dec_hw_ctx { + struct hantro_aux_buf tile_edge; + struct hantro_aux_buf segment_map; + struct hantro_aux_buf misc; + struct v4l2_vp9_frame_symbol_counts cnts; + struct v4l2_vp9_frame_context probability_tables; + struct v4l2_vp9_frame_context frame_context[4]; + struct hantro_vp9_frame_info cur; + struct hantro_vp9_frame_info last; + + unsigned int bsd_ctrl_offset; + unsigned int segment_map_size; + unsigned int ctx_counters_offset; + unsigned int tile_info_offset; + + unsigned short tile_r_info[MAX_SB_ROWS]; + unsigned short tile_c_info[MAX_SB_COLS]; + unsigned int last_tile_r; + unsigned int last_tile_c; + unsigned int last_sbs_r; + unsigned int last_sbs_c; + + unsigned int active_segment; + u8 feature_enabled[8]; + s16 feature_data[8][4]; +}; + /** * struct hantro_postproc_ctx * @@ -271,6 +348,24 @@ void hantro_hevc_ref_remove_unused(struct hantro_ctx *ctx); size_t hantro_hevc_chroma_offset(const struct v4l2_ctrl_hevc_sps *sps); size_t hantro_hevc_motion_vectors_offset(const struct v4l2_ctrl_hevc_sps *sps); +static inline unsigned short hantro_vp9_num_sbs(unsigned short dimension) +{ + return (dimension + 63) / 64; +} + +static inline size_t +hantro_vp9_mv_size(unsigned int width, unsigned int height) +{ + int num_ctbs; + + /* + * There can be up to (CTBs x 64) number of blocks, + * and the motion vector for each block needs 16 bytes. + */ + num_ctbs = hantro_vp9_num_sbs(width) * hantro_vp9_num_sbs(height); + return (num_ctbs * 64) * 16; +} + static inline size_t hantro_h264_mv_size(unsigned int width, unsigned int height) { @@ -312,6 +407,10 @@ void hantro_vp8_dec_exit(struct hantro_ctx *ctx); void hantro_vp8_prob_update(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp8_frame *hdr); +int hantro_g2_vp9_dec_run(struct hantro_ctx *ctx); +void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx); +int hantro_vp9_dec_init(struct hantro_ctx *ctx); +void hantro_vp9_dec_exit(struct hantro_ctx *ctx); void hantro_g2_check_idle(struct hantro_dev *vpu); #endif /* HANTRO_HW_H_ */ diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c index d1f060c55fed..e4b0645ba6fc 100644 --- a/drivers/staging/media/hantro/hantro_v4l2.c +++ b/drivers/staging/media/hantro/hantro_v4l2.c @@ -299,6 +299,11 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, pix_mp->plane_fmt[0].sizeimage += hantro_h264_mv_size(pix_mp->width, pix_mp->height); + else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_VP9_FRAME && + !hantro_needs_postproc(ctx, fmt)) + pix_mp->plane_fmt[0].sizeimage += + hantro_vp9_mv_size(pix_mp->width, + pix_mp->height); } else if (!pix_mp->plane_fmt[0].sizeimage) { /* * For coded formats the application can specify @@ -407,6 +412,7 @@ hantro_update_requires_request(struct hantro_ctx *ctx, u32 fourcc) case V4L2_PIX_FMT_VP8_FRAME: case V4L2_PIX_FMT_H264_SLICE: case V4L2_PIX_FMT_HEVC_SLICE: + case V4L2_PIX_FMT_VP9_FRAME: ctx->fh.m2m_ctx->out_q_ctx.q.requires_requests = true; break; default: diff --git a/drivers/staging/media/hantro/hantro_vp9.c b/drivers/staging/media/hantro/hantro_vp9.c new file mode 100644 index 000000000000..566cd376c097 --- /dev/null +++ b/drivers/staging/media/hantro/hantro_vp9.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hantro VP9 codec driver + * + * Copyright (C) 2021 Collabora Ltd. + */ + +#include +#include + +#include "hantro.h" +#include "hantro_hw.h" +#include "hantro_vp9.h" + +#define POW2(x) (1 << (x)) + +#define MAX_LOG2_TILE_COLUMNS 6 +#define MAX_NUM_TILE_COLS POW2(MAX_LOG2_TILE_COLUMNS) +#define MAX_TILE_COLS 20 +#define MAX_TILE_ROWS 22 + +static size_t hantro_vp9_tile_filter_size(unsigned int height) +{ + u32 h, height32, size; + + h = roundup(height, 8); + + height32 = roundup(h, 64); + size = 24 * height32 * (MAX_NUM_TILE_COLS - 1); /* luma: 8, chroma: 8 + 8 */ + + return size; +} + +static size_t hantro_vp9_bsd_control_size(unsigned int height) +{ + u32 h, height32; + + h = roundup(height, 8); + height32 = roundup(h, 64); + + return 16 * (height32 / 4) * (MAX_NUM_TILE_COLS - 1); +} + +static size_t hantro_vp9_segment_map_size(unsigned int width, unsigned int height) +{ + u32 w, h; + int num_ctbs; + + w = roundup(width, 8); + h = roundup(height, 8); + num_ctbs = ((w + 63) / 64) * ((h + 63) / 64); + + return num_ctbs * 32; +} + +static inline size_t hantro_vp9_prob_tab_size(void) +{ + return roundup(sizeof(struct hantro_g2_all_probs), 16); +} + +static inline size_t hantro_vp9_count_tab_size(void) +{ + return roundup(sizeof(struct symbol_counts), 16); +} + +static inline size_t hantro_vp9_tile_info_size(void) +{ + return roundup((MAX_TILE_COLS * MAX_TILE_ROWS * 4 * sizeof(u16) + 15 + 16) & ~0xf, 16); +} + +static void *get_coeffs_arr(struct symbol_counts *cnts, int i, int j, int k, int l, int m) +{ + if (i == 0) + return &cnts->count_coeffs[j][k][l][m]; + + if (i == 1) + return &cnts->count_coeffs8x8[j][k][l][m]; + + if (i == 2) + return &cnts->count_coeffs16x16[j][k][l][m]; + + if (i == 3) + return &cnts->count_coeffs32x32[j][k][l][m]; + + return NULL; +} + +static void *get_eobs1(struct symbol_counts *cnts, int i, int j, int k, int l, int m) +{ + if (i == 0) + return &cnts->count_coeffs[j][k][l][m][3]; + + if (i == 1) + return &cnts->count_coeffs8x8[j][k][l][m][3]; + + if (i == 2) + return &cnts->count_coeffs16x16[j][k][l][m][3]; + + if (i == 3) + return &cnts->count_coeffs32x32[j][k][l][m][3]; + + return NULL; +} + +#define INNER_LOOP \ + do { \ + for (m = 0; m < ARRAY_SIZE(vp9_ctx->cnts.coeff[i][0][0][0]); ++m) { \ + vp9_ctx->cnts.coeff[i][j][k][l][m] = \ + get_coeffs_arr(cnts, i, j, k, l, m); \ + vp9_ctx->cnts.eob[i][j][k][l][m][0] = \ + &cnts->count_eobs[i][j][k][l][m]; \ + vp9_ctx->cnts.eob[i][j][k][l][m][1] = \ + get_eobs1(cnts, i, j, k, l, m); \ + } \ + } while (0) + +static void init_v4l2_vp9_count_tbl(struct hantro_ctx *ctx) +{ + struct hantro_vp9_dec_hw_ctx *vp9_ctx = &ctx->vp9_dec; + struct symbol_counts *cnts = vp9_ctx->misc.cpu + vp9_ctx->ctx_counters_offset; + int i, j, k, l, m; + + vp9_ctx->cnts.partition = &cnts->partition_counts; + vp9_ctx->cnts.skip = &cnts->mbskip_count; + vp9_ctx->cnts.intra_inter = &cnts->intra_inter_count; + vp9_ctx->cnts.tx32p = &cnts->tx32x32_count; + /* + * g2 hardware uses tx16x16_count[2][3], while the api + * expects tx16p[2][4], so this must be explicitly copied + * into vp9_ctx->cnts.tx16p when passing the data to the + * vp9 library function + */ + vp9_ctx->cnts.tx8p = &cnts->tx8x8_count; + + vp9_ctx->cnts.y_mode = &cnts->sb_ymode_counts; + vp9_ctx->cnts.uv_mode = &cnts->uv_mode_counts; + vp9_ctx->cnts.comp = &cnts->comp_inter_count; + vp9_ctx->cnts.comp_ref = &cnts->comp_ref_count; + vp9_ctx->cnts.single_ref = &cnts->single_ref_count; + vp9_ctx->cnts.filter = &cnts->switchable_interp_counts; + vp9_ctx->cnts.mv_joint = &cnts->mv_counts.joints; + vp9_ctx->cnts.sign = &cnts->mv_counts.sign; + vp9_ctx->cnts.classes = &cnts->mv_counts.classes; + vp9_ctx->cnts.class0 = &cnts->mv_counts.class0; + vp9_ctx->cnts.bits = &cnts->mv_counts.bits; + vp9_ctx->cnts.class0_fp = &cnts->mv_counts.class0_fp; + vp9_ctx->cnts.fp = &cnts->mv_counts.fp; + vp9_ctx->cnts.class0_hp = &cnts->mv_counts.class0_hp; + vp9_ctx->cnts.hp = &cnts->mv_counts.hp; + + for (i = 0; i < ARRAY_SIZE(vp9_ctx->cnts.coeff); ++i) + for (j = 0; j < ARRAY_SIZE(vp9_ctx->cnts.coeff[i]); ++j) + for (k = 0; k < ARRAY_SIZE(vp9_ctx->cnts.coeff[i][0]); ++k) + for (l = 0; l < ARRAY_SIZE(vp9_ctx->cnts.coeff[i][0][0]); ++l) + INNER_LOOP; +} + +int hantro_vp9_dec_init(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + const struct hantro_variant *variant = vpu->variant; + struct hantro_vp9_dec_hw_ctx *vp9_dec = &ctx->vp9_dec; + struct hantro_aux_buf *tile_edge = &vp9_dec->tile_edge; + struct hantro_aux_buf *segment_map = &vp9_dec->segment_map; + struct hantro_aux_buf *misc = &vp9_dec->misc; + u32 i, max_width, max_height, size; + + if (variant->num_dec_fmts < 1) + return -EINVAL; + + for (i = 0; i < variant->num_dec_fmts; ++i) + if (variant->dec_fmts[i].fourcc == V4L2_PIX_FMT_VP9_FRAME) + break; + + if (i == variant->num_dec_fmts) + return -EINVAL; + + max_width = vpu->variant->dec_fmts[i].frmsize.max_width; + max_height = vpu->variant->dec_fmts[i].frmsize.max_height; + + size = hantro_vp9_tile_filter_size(max_height); + vp9_dec->bsd_ctrl_offset = size; + size += hantro_vp9_bsd_control_size(max_height); + + tile_edge->cpu = dma_alloc_coherent(vpu->dev, size, &tile_edge->dma, GFP_KERNEL); + if (!tile_edge->cpu) + return -ENOMEM; + + tile_edge->size = size; + memset(tile_edge->cpu, 0, size); + + size = hantro_vp9_segment_map_size(max_width, max_height); + vp9_dec->segment_map_size = size; + size *= 2; /* we need two areas of this size, used alternately */ + + segment_map->cpu = dma_alloc_coherent(vpu->dev, size, &segment_map->dma, GFP_KERNEL); + if (!segment_map->cpu) + goto err_segment_map; + + segment_map->size = size; + memset(segment_map->cpu, 0, size); + + size = hantro_vp9_prob_tab_size(); + vp9_dec->ctx_counters_offset = size; + size += hantro_vp9_count_tab_size(); + vp9_dec->tile_info_offset = size; + size += hantro_vp9_tile_info_size(); + + misc->cpu = dma_alloc_coherent(vpu->dev, size, &misc->dma, GFP_KERNEL); + if (!misc->cpu) + goto err_misc; + + misc->size = size; + memset(misc->cpu, 0, size); + + init_v4l2_vp9_count_tbl(ctx); + + return 0; + +err_misc: + dma_free_coherent(vpu->dev, segment_map->size, segment_map->cpu, segment_map->dma); + +err_segment_map: + dma_free_coherent(vpu->dev, tile_edge->size, tile_edge->cpu, tile_edge->dma); + + return -ENOMEM; +} + +void hantro_vp9_dec_exit(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_vp9_dec_hw_ctx *vp9_dec = &ctx->vp9_dec; + struct hantro_aux_buf *tile_edge = &vp9_dec->tile_edge; + struct hantro_aux_buf *segment_map = &vp9_dec->segment_map; + struct hantro_aux_buf *misc = &vp9_dec->misc; + + dma_free_coherent(vpu->dev, misc->size, misc->cpu, misc->dma); + dma_free_coherent(vpu->dev, segment_map->size, segment_map->cpu, segment_map->dma); + dma_free_coherent(vpu->dev, tile_edge->size, tile_edge->cpu, tile_edge->dma); +} diff --git a/drivers/staging/media/hantro/hantro_vp9.h b/drivers/staging/media/hantro/hantro_vp9.h new file mode 100644 index 000000000000..26b69275f098 --- /dev/null +++ b/drivers/staging/media/hantro/hantro_vp9.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Hantro VP9 codec driver + * + * Copyright (C) 2021 Collabora Ltd. + */ + +struct hantro_g2_mv_probs { + u8 joint[3]; + u8 sign[2]; + u8 class0_bit[2][1]; + u8 fr[2][3]; + u8 class0_hp[2]; + u8 hp[2]; + u8 classes[2][10]; + u8 class0_fr[2][2][3]; + u8 bits[2][10]; +}; + +struct hantro_g2_probs { + u8 inter_mode[7][4]; + u8 is_inter[4]; + u8 uv_mode[10][8]; + u8 tx8[2][1]; + u8 tx16[2][2]; + u8 tx32[2][3]; + u8 y_mode_tail[4][1]; + u8 y_mode[4][8]; + u8 partition[2][16][4]; /* [keyframe][][], [inter][][] */ + u8 uv_mode_tail[10][1]; + u8 interp_filter[4][2]; + u8 comp_mode[5]; + u8 skip[3]; + + u8 pad1[1]; + + struct hantro_g2_mv_probs mv; + + u8 single_ref[5][2]; + u8 comp_ref[5]; + + u8 pad2[17]; + + u8 coef[4][2][2][6][6][4]; +}; + +struct hantro_g2_all_probs { + u8 kf_y_mode_prob[10][10][8]; + + u8 kf_y_mode_prob_tail[10][10][1]; + u8 ref_pred_probs[3]; + u8 mb_segment_tree_probs[7]; + u8 segment_pred_probs[3]; + u8 ref_scores[4]; + u8 prob_comppred[2]; + + u8 pad1[9]; + + u8 kf_uv_mode_prob[10][8]; + u8 kf_uv_mode_prob_tail[10][1]; + + u8 pad2[6]; + + struct hantro_g2_probs probs; +}; + +struct mv_counts { + u32 joints[4]; + u32 sign[2][2]; + u32 classes[2][11]; + u32 class0[2][2]; + u32 bits[2][10][2]; + u32 class0_fp[2][2][4]; + u32 fp[2][4]; + u32 class0_hp[2][2]; + u32 hp[2][2]; +}; + +struct symbol_counts { + u32 inter_mode_counts[7][3][2]; + u32 sb_ymode_counts[4][10]; + u32 uv_mode_counts[10][10]; + u32 partition_counts[16][4]; + u32 switchable_interp_counts[4][3]; + u32 intra_inter_count[4][2]; + u32 comp_inter_count[5][2]; + u32 single_ref_count[5][2][2]; + u32 comp_ref_count[5][2]; + u32 tx32x32_count[2][4]; + u32 tx16x16_count[2][3]; + u32 tx8x8_count[2][2]; + u32 mbskip_count[3][2]; + + struct mv_counts mv_counts; + + u32 count_coeffs[2][2][6][6][4]; + u32 count_coeffs8x8[2][2][6][6][4]; + u32 count_coeffs16x16[2][2][6][6][4]; + u32 count_coeffs32x32[2][2][6][6][4]; + + u32 count_eobs[4][2][2][6][6]; +}; diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c index a40b161e5956..455a107ffb02 100644 --- a/drivers/staging/media/hantro/imx8m_vpu_hw.c +++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c @@ -150,6 +150,19 @@ static const struct hantro_fmt imx8m_vpu_g2_dec_fmts[] = { .step_height = MB_DIM, }, }, + { + .fourcc = V4L2_PIX_FMT_VP9_FRAME, + .codec_mode = HANTRO_MODE_VP9_DEC, + .max_depth = 2, + .frmsize = { + .min_width = 48, + .max_width = 3840, + .step_width = MB_DIM, + .min_height = 48, + .max_height = 2160, + .step_height = MB_DIM, + }, + }, }; static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id) @@ -241,6 +254,13 @@ static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = { .init = hantro_hevc_dec_init, .exit = hantro_hevc_dec_exit, }, + [HANTRO_MODE_VP9_DEC] = { + .run = hantro_g2_vp9_dec_run, + .done = hantro_g2_vp9_dec_done, + .reset = imx8m_vpu_g2_reset, + .init = hantro_vp9_dec_init, + .exit = hantro_vp9_dec_exit, + }, }; /* @@ -281,7 +301,7 @@ const struct hantro_variant imx8mq_vpu_g2_variant = { .dec_offset = 0x0, .dec_fmts = imx8m_vpu_g2_dec_fmts, .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_g2_dec_fmts), - .codec = HANTRO_HEVC_DECODER, + .codec = HANTRO_HEVC_DECODER | HANTRO_VP9_DECODER, .codec_ops = imx8mq_vpu_g2_codec_ops, .init = imx8mq_vpu_hw_init, .runtime_resume = imx8mq_runtime_resume, From be1b49f576a80167162707b90151d8a55bf567be Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 16 Nov 2021 14:38:41 +0000 Subject: [PATCH 193/397] media: hantro: Staticize a struct in postprocessor code The struct is not used outside this file, so it can be static. Signed-off-by: Andrzej Pietrasiewicz Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_postproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c index 4549aec08feb..89de43021779 100644 --- a/drivers/staging/media/hantro/hantro_postproc.c +++ b/drivers/staging/media/hantro/hantro_postproc.c @@ -33,7 +33,7 @@ #define VPU_PP_OUT_RGB 0x0 #define VPU_PP_OUT_YUYV 0x3 -const struct hantro_postproc_regs hantro_g1_postproc_regs = { +static const struct hantro_postproc_regs hantro_g1_postproc_regs = { .pipeline_en = {G1_REG_PP_INTERRUPT, 1, 0x1}, .max_burst = {G1_REG_PP_DEV_CONFIG, 0, 0x1f}, .clk_gate = {G1_REG_PP_DEV_CONFIG, 1, 0x1}, From 0d2517b3765aa331aee0a95f9b8072062d6bb7e5 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Tue, 16 Nov 2021 14:38:42 +0000 Subject: [PATCH 194/397] media: hantro: Support NV12 on the G2 core The G2 decoder block produces NV12 4x4 tiled format (NV12_4L4). Enable the G2 post-processor block, in order to produce regular NV12. The logic in hantro_postproc.c is leveraged to take care of allocating the extra buffers and configure the post-processor, which is significantly simpler than the one on the G1. Signed-off-by: Ezequiel Garcia Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/hantro/hantro_g2_vp9_dec.c | 6 ++-- drivers/staging/media/hantro/hantro_hw.h | 1 + .../staging/media/hantro/hantro_postproc.c | 31 +++++++++++++++++++ drivers/staging/media/hantro/imx8m_vpu_hw.c | 11 +++++++ 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_g2_vp9_dec.c b/drivers/staging/media/hantro/hantro_g2_vp9_dec.c index fc55b03a8004..e04242d10fa2 100644 --- a/drivers/staging/media/hantro/hantro_g2_vp9_dec.c +++ b/drivers/staging/media/hantro/hantro_g2_vp9_dec.c @@ -152,7 +152,7 @@ static void config_output(struct hantro_ctx *ctx, hantro_reg_write(ctx->dev, &g2_out_dis, 0); hantro_reg_write(ctx->dev, &g2_output_format, 0); - luma_addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0); + luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf); hantro_write_addr(ctx->dev, G2_OUT_LUMA_ADDR, luma_addr); chroma_addr = luma_addr + chroma_offset(ctx, dec_params); @@ -191,7 +191,7 @@ static void config_ref(struct hantro_ctx *ctx, hantro_reg_write(ctx->dev, &ref_reg->hor_scale, (refw << 14) / dst->vp9.width); hantro_reg_write(ctx->dev, &ref_reg->ver_scale, (refh << 14) / dst->vp9.height); - luma_addr = vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0); + luma_addr = hantro_get_dec_buf_addr(ctx, &buf->base.vb.vb2_buf); hantro_write_addr(ctx->dev, ref_reg->y_base, luma_addr); chroma_addr = luma_addr + chroma_offset(ctx, dec_params); @@ -236,7 +236,7 @@ static void config_ref_registers(struct hantro_ctx *ctx, config_ref(ctx, dst, &ref_regs[1], dec_params, dec_params->golden_frame_ts); config_ref(ctx, dst, &ref_regs[2], dec_params, dec_params->alt_frame_ts); - mv_addr = vb2_dma_contig_plane_dma_addr(&mv_ref->base.vb.vb2_buf, 0) + + mv_addr = hantro_get_dec_buf_addr(ctx, &mv_ref->base.vb.vb2_buf) + mv_offset(ctx, dec_params); hantro_write_addr(ctx->dev, G2_REF_MV_ADDR(0), mv_addr); diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index fe5b51046d33..dbe51303724b 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -310,6 +310,7 @@ extern const struct hantro_variant rk3399_vpu_variant; extern const struct hantro_variant sama5d4_vdec_variant; extern const struct hantro_postproc_ops hantro_g1_postproc_ops; +extern const struct hantro_postproc_ops hantro_g2_postproc_ops; extern const u32 hantro_vp8_dec_mc_filter[8][6]; diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c index 89de43021779..a7774ad4c445 100644 --- a/drivers/staging/media/hantro/hantro_postproc.c +++ b/drivers/staging/media/hantro/hantro_postproc.c @@ -11,6 +11,7 @@ #include "hantro.h" #include "hantro_hw.h" #include "hantro_g1_regs.h" +#include "hantro_g2_regs.h" #define HANTRO_PP_REG_WRITE(vpu, reg_name, val) \ { \ @@ -99,6 +100,21 @@ static void hantro_postproc_g1_enable(struct hantro_ctx *ctx) HANTRO_PP_REG_WRITE(vpu, display_width, ctx->dst_fmt.width); } +static void hantro_postproc_g2_enable(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *dst_buf; + size_t chroma_offset = ctx->dst_fmt.width * ctx->dst_fmt.height; + dma_addr_t dst_dma; + + dst_buf = hantro_get_dst_buf(ctx); + dst_dma = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + + hantro_write_addr(vpu, G2_RS_OUT_LUMA_ADDR, dst_dma); + hantro_write_addr(vpu, G2_RS_OUT_CHROMA_ADDR, dst_dma + chroma_offset); + hantro_reg_write(vpu, &g2_out_rs_e, 1); +} + void hantro_postproc_free(struct hantro_ctx *ctx) { struct hantro_dev *vpu = ctx->dev; @@ -127,6 +143,9 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_H264_SLICE) buf_size += hantro_h264_mv_size(ctx->dst_fmt.width, ctx->dst_fmt.height); + else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_VP9_FRAME) + buf_size += hantro_vp9_mv_size(ctx->dst_fmt.width, + ctx->dst_fmt.height); for (i = 0; i < num_buffers; ++i) { struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; @@ -152,6 +171,13 @@ static void hantro_postproc_g1_disable(struct hantro_ctx *ctx) HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x0); } +static void hantro_postproc_g2_disable(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + + hantro_reg_write(vpu, &g2_out_rs_e, 0); +} + void hantro_postproc_disable(struct hantro_ctx *ctx) { struct hantro_dev *vpu = ctx->dev; @@ -172,3 +198,8 @@ const struct hantro_postproc_ops hantro_g1_postproc_ops = { .enable = hantro_postproc_g1_enable, .disable = hantro_postproc_g1_disable, }; + +const struct hantro_postproc_ops hantro_g2_postproc_ops = { + .enable = hantro_postproc_g2_enable, + .disable = hantro_postproc_g2_disable, +}; diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c index 455a107ffb02..1a43f6fceef9 100644 --- a/drivers/staging/media/hantro/imx8m_vpu_hw.c +++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c @@ -132,6 +132,14 @@ static const struct hantro_fmt imx8m_vpu_dec_fmts[] = { }, }; +static const struct hantro_fmt imx8m_vpu_g2_postproc_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12, + .codec_mode = HANTRO_MODE_NONE, + .postprocessed = true, + }, +}; + static const struct hantro_fmt imx8m_vpu_g2_dec_fmts[] = { { .fourcc = V4L2_PIX_FMT_NV12_4L4, @@ -301,6 +309,9 @@ const struct hantro_variant imx8mq_vpu_g2_variant = { .dec_offset = 0x0, .dec_fmts = imx8m_vpu_g2_dec_fmts, .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_g2_dec_fmts), + .postproc_fmts = imx8m_vpu_g2_postproc_fmts, + .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_g2_postproc_fmts), + .postproc_ops = &hantro_g2_postproc_ops, .codec = HANTRO_HEVC_DECODER | HANTRO_VP9_DECODER, .codec_ops = imx8mq_vpu_g2_codec_ops, .init = imx8mq_vpu_hw_init, From 140dfc36fbd3b759a47e972774b362894f43911f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 08:24:03 +0000 Subject: [PATCH 195/397] media: cx25821: drop duplicated i2c_slave_did_ack() This function is defined twice, one at cx25821-i2c and the other inside cx25821-core. It turns that only the first is actually used inside the code. This causes a clang warning. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx25821/cx25821-core.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index 40c10ca94def..3078a39f0b95 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -337,13 +337,6 @@ static int cx25821_risc_decode(u32 risc) return incr[risc >> 28] ? incr[risc >> 28] : 1; } -static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) -{ - struct cx25821_i2c *bus = i2c_adap->algo_data; - struct cx25821_dev *dev = bus->dev; - return cx_read(bus->reg_stat) & 0x01; -} - static void cx25821_registers_init(struct cx25821_dev *dev) { u32 tmp; From 9543b4e3206621e1e45f7e3a5841359a3a53686d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 08:29:50 +0000 Subject: [PATCH 196/397] media: ivtv: drop an unused macro The macro p_to_snd_ivtv_card() is just a variant for container_of(), not actually used inside the code. So, drop it. This address a clang warning. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ivtv/ivtv-alsa-main.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c index 4cefdb2e4d40..9e13a7128a53 100644 --- a/drivers/media/pci/ivtv/ivtv-alsa-main.c +++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c @@ -48,12 +48,6 @@ struct snd_ivtv_card *to_snd_ivtv_card(struct v4l2_device *v4l2_dev) return to_ivtv(v4l2_dev)->alsa; } -static inline -struct snd_ivtv_card *p_to_snd_ivtv_card(struct v4l2_device **v4l2_dev) -{ - return container_of(v4l2_dev, struct snd_ivtv_card, v4l2_dev); -} - static void snd_ivtv_card_free(struct snd_ivtv_card *itvsc) { if (itvsc == NULL) From 1f1517fafda598839a02e39968c5063ddcfa51fc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 08:32:02 +0000 Subject: [PATCH 197/397] media: cx18: drop an unused macro The macro p_to_snd_cx18_card() is just a variant for container_of(), not actually used inside the code. So, drop it. This address a clang warning. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx18/cx18-alsa-main.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c index 9a82e68303b6..9dc361886284 100644 --- a/drivers/media/pci/cx18/cx18-alsa-main.c +++ b/drivers/media/pci/cx18/cx18-alsa-main.c @@ -51,12 +51,6 @@ struct snd_cx18_card *to_snd_cx18_card(struct v4l2_device *v4l2_dev) return to_cx18(v4l2_dev)->alsa; } -static inline -struct snd_cx18_card *p_to_snd_cx18_card(struct v4l2_device **v4l2_dev) -{ - return container_of(v4l2_dev, struct snd_cx18_card, v4l2_dev); -} - static void snd_cx18_card_free(struct snd_cx18_card *cxsc) { if (cxsc == NULL) From a62d2f710799263709db82f251e30c73886cc3af Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 08:34:26 +0000 Subject: [PATCH 198/397] media: stb6100: mark a currently unused function as such The stb6100_normalise_regs() function is not used with current boards, but the driver says that some devices could need it. Ok, we could simply drop it, but as there's a macro to mark unused functions, use it. This should shut up a clang warning. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb6100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c index d541d6613610..698866c4f15a 100644 --- a/drivers/media/dvb-frontends/stb6100.c +++ b/drivers/media/dvb-frontends/stb6100.c @@ -110,7 +110,7 @@ static const struct stb6100_regmask stb6100_template[] = { /* * Currently unused. Some boards might need it in the future */ -static inline void stb6100_normalise_regs(u8 regs[]) +static __always_unused inline void stb6100_normalise_regs(u8 regs[]) { int i; From a057d92a36faabb66a0305d3e4c17d7a98166932 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 08:42:08 +0000 Subject: [PATCH 199/397] media: mc: drop an unused debug function The gobj_type() function translates the media object type into a name, being useful for debugging purposes. It is currently not used. So, drop it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/mc/mc-entity.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c index f40f41977142..c02340698ad6 100644 --- a/drivers/media/mc/mc-entity.c +++ b/drivers/media/mc/mc-entity.c @@ -14,22 +14,6 @@ #include #include -static inline const char *gobj_type(enum media_gobj_type type) -{ - switch (type) { - case MEDIA_GRAPH_ENTITY: - return "entity"; - case MEDIA_GRAPH_PAD: - return "pad"; - case MEDIA_GRAPH_LINK: - return "link"; - case MEDIA_GRAPH_INTF_DEVNODE: - return "intf-devnode"; - default: - return "unknown"; - } -} - static inline const char *intf_type(struct media_interface *intf) { switch (intf->type) { From ea28f3f1d2058b03a811c1ac0f8d1de49dee646d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 08:59:53 +0000 Subject: [PATCH 200/397] media: dvb-core: dvb_frontend: address some clang warnings The typecasts at the dvb-core generate clang warnings when W=1 is enabled. The warns are harmless, but they cause the build to break with CONFIG_WERROR, so do the cast on a way that it won't produce warnings anymore. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 8fc59f3cfb6c..48e735cdbe6b 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -2554,8 +2554,7 @@ static int dvb_frontend_handle_ioctl(struct file *file, case FE_DISEQC_SEND_BURST: if (fe->ops.diseqc_send_burst) { - err = fe->ops.diseqc_send_burst(fe, - (enum fe_sec_mini_cmd)parg); + err = fe->ops.diseqc_send_burst(fe, (long)parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } @@ -2563,9 +2562,8 @@ static int dvb_frontend_handle_ioctl(struct file *file, case FE_SET_TONE: if (fe->ops.set_tone) { - err = fe->ops.set_tone(fe, - (enum fe_sec_tone_mode)parg); - fepriv->tone = (enum fe_sec_tone_mode)parg; + fepriv->tone = (long)parg; + err = fe->ops.set_tone(fe, fepriv->tone); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } @@ -2573,9 +2571,8 @@ static int dvb_frontend_handle_ioctl(struct file *file, case FE_SET_VOLTAGE: if (fe->ops.set_voltage) { - err = fe->ops.set_voltage(fe, - (enum fe_sec_voltage)parg); - fepriv->voltage = (enum fe_sec_voltage)parg; + fepriv->voltage = (long)parg; + err = fe->ops.set_voltage(fe, fepriv->voltage); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } From 0338d9c2ffc61b3a70d42e469dfba95f88b6a7f9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 09:05:51 +0000 Subject: [PATCH 201/397] media: cx25840: drop some unused inline functions Solve some clang warnings about unused functions by dropping some time-conversion inline funcs that aren't used anywhere. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/cx25840/cx25840-ir.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c index 2cf3e6a1f9e1..9d7d1d149f1a 100644 --- a/drivers/media/i2c/cx25840/cx25840-ir.c +++ b/drivers/media/i2c/cx25840/cx25840-ir.c @@ -136,19 +136,6 @@ static inline u16 count_to_clock_divider(unsigned int d) return (u16) d; } -static inline u16 ns_to_clock_divider(unsigned int ns) -{ - return count_to_clock_divider( - DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ / 1000000 * ns, 1000)); -} - -static inline unsigned int clock_divider_to_ns(unsigned int divider) -{ - /* Period of the Rx or Tx clock in ns */ - return DIV_ROUND_CLOSEST((divider + 1) * 1000, - CX25840_IR_REFCLK_FREQ / 1000000); -} - static inline u16 carrier_freq_to_clock_divider(unsigned int freq) { return count_to_clock_divider( @@ -160,13 +147,6 @@ static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider) return DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, (divider + 1) * 16); } -static inline u16 freq_to_clock_divider(unsigned int freq, - unsigned int rollovers) -{ - return count_to_clock_divider( - DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, freq * rollovers)); -} - static inline unsigned int clock_divider_to_freq(unsigned int divider, unsigned int rollovers) { From 5f73dcec407612eb308699a5d8182d70916210b0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 09:07:24 +0000 Subject: [PATCH 202/397] media: marvell-ccic: drop to_cam() unused function This function is an alias for container_of() that it is currently not used, causing clang warnings. So, drop it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/cafe-driver.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c index b61b9d9551af..03dcf8bf705e 100644 --- a/drivers/media/platform/marvell-ccic/cafe-driver.c +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c @@ -139,13 +139,6 @@ struct cafe_camera { */ #define CAFE_SMBUS_TIMEOUT (HZ) /* generous */ -static inline struct cafe_camera *to_cam(struct v4l2_device *dev) -{ - struct mcam_camera *m = container_of(dev, struct mcam_camera, v4l2_dev); - return container_of(m, struct cafe_camera, mcam); -} - - static int cafe_smbus_write_done(struct mcam_camera *mcam) { unsigned long flags; From b61010bc5db5beee0ce0f56c316aae3e5de0bfee Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 09:08:47 +0000 Subject: [PATCH 203/397] media: omap3isp: mark isp_isr_dbg as __maybe_unused This function is only used for debugging purposes. When DEBUG is disabled, it becomes unused, causing a clang warning with W=1. Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 6de377ce281d..4c937f3f323e 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -476,7 +476,8 @@ void omap3isp_hist_dma_done(struct isp_device *isp) } } -static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus) +static inline void __maybe_unused isp_isr_dbg(struct isp_device *isp, + u32 irqstatus) { static const char *name[] = { "CSIA_IRQ", From c9ae8eed446322fc2d1c9e6bf4ac78b4e5686cad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 09:20:50 +0000 Subject: [PATCH 204/397] media: omap3isp: avoid warnings at IS_OUT_OF_BOUNDS() Clang with W=1 produces the following warnings: drivers/media/platform/omap3isp/isph3a_af.c:173:6: error: result of comparison of constant 256 with expression of type '__u8' (aka 'unsigned char') is always false [-Werror,-Wtautological-constant-out-of-range-compare] if (IS_OUT_OF_BOUNDS(paxel_cfg->height, OMAP3ISP_AF_PAXEL_HEIGHT_MIN, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/media/platform/omap3isp/isph3a_af.c:24:33: note: expanded from macro 'IS_OUT_OF_BOUNDS' (((value) < (min)) || ((value) > (max))) ~~~~~~~ ^ ~~~~~ drivers/media/platform/omap3isp/isph3a_af.c:179:6: error: result of comparison of constant 256 with expression of type '__u8' (aka 'unsigned char') is always false [-Werror,-Wtautological-constant-out-of-range-compare] if (IS_OUT_OF_BOUNDS(paxel_cfg->width, OMAP3ISP_AF_PAXEL_WIDTH_MIN, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/media/platform/omap3isp/isph3a_af.c:24:33: note: expanded from macro 'IS_OUT_OF_BOUNDS' (((value) < (min)) || ((value) > (max))) ~~~~~~~ ^ ~~~~~ 2 errors generated. Use a typecast to avoid such warnings. Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isph3a_af.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/omap3isp/isph3a_af.c b/drivers/media/platform/omap3isp/isph3a_af.c index a65cfdfa9637..de7b116d0122 100644 --- a/drivers/media/platform/omap3isp/isph3a_af.c +++ b/drivers/media/platform/omap3isp/isph3a_af.c @@ -21,7 +21,7 @@ #include "ispstat.h" #define IS_OUT_OF_BOUNDS(value, min, max) \ - (((value) < (min)) || ((value) > (max))) + ((((unsigned int)value) < (min)) || (((unsigned int)value) > (max))) static void h3a_af_setup_regs(struct ispstat *af, void *priv) { From f16ce2e275bbe38582e6bb9416c9c7c92bb42f95 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 09:49:19 +0000 Subject: [PATCH 205/397] media: adv7842: get rid of two unused functions Those functions just call a V4L2 core macro, and aren't used anywhere. Get rid of them, in order to avoid clang warnings with W=1. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7842.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 7f8acbdf0db4..9d6eed0f8281 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -256,21 +256,11 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd; } -static inline unsigned hblanking(const struct v4l2_bt_timings *t) -{ - return V4L2_DV_BT_BLANKING_WIDTH(t); -} - static inline unsigned htotal(const struct v4l2_bt_timings *t) { return V4L2_DV_BT_FRAME_WIDTH(t); } -static inline unsigned vblanking(const struct v4l2_bt_timings *t) -{ - return V4L2_DV_BT_BLANKING_HEIGHT(t); -} - static inline unsigned vtotal(const struct v4l2_bt_timings *t) { return V4L2_DV_BT_FRAME_HEIGHT(t); From 8efe1d7c0023ce124fa9984095f5bc7198c71c82 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 09:53:02 +0000 Subject: [PATCH 206/397] media: saa7134-go7007: get rid of to_state() function This is just an alias for container_of() and it is used only on a commented code. The commented code actually is an issue that require fixes, so, move the container_of() call to the commented code, and drop the unused function. This way, a fix for the function could be added later without needing to re-add to_state() function. This fixes a clang W=1 warning. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-go7007.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-go7007.c b/drivers/media/pci/saa7134/saa7134-go7007.c index f319edb39c0e..da83893ffee9 100644 --- a/drivers/media/pci/saa7134/saa7134-go7007.c +++ b/drivers/media/pci/saa7134/saa7134-go7007.c @@ -56,11 +56,6 @@ struct saa7134_go7007 { dma_addr_t bottom_dma; }; -static inline struct saa7134_go7007 *to_state(struct v4l2_subdev *sd) -{ - return container_of(sd, struct saa7134_go7007, sd); -} - static const struct go7007_board_info board_voyager = { .flags = 0, .sensor_flags = GO7007_SENSOR_656 | @@ -385,7 +380,7 @@ MODULE_FIRMWARE("go7007/go7007tv.bin"); static int saa7134_go7007_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) { #if 0 - struct saa7134_go7007 *saa = to_state(sd); + struct saa7134_go7007 *saa = container_of(sd, struct saa7134_go7007, sd); struct saa7134_dev *dev = saa->dev; return saa7134_s_std_internal(dev, NULL, norm); From 53dd3f0a7fed09d716cdf856dca049a22c891a2a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 12:14:23 +0000 Subject: [PATCH 207/397] media: davinci: get rid of an unused function vpif_get_default_field() seems to be some left-over from a past code that sets the field order. Reviewed-by: Nathan Chancellor Reviewed-by: Lad Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index ae92e2c206d0..aba105fa7ef9 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -618,17 +618,6 @@ static void vpif_calculate_offsets(struct channel_obj *ch) ch->vpifparams.video_params.stdid = vpifparams->std_info.stdid; } -/** - * vpif_get_default_field() - Get default field type based on interface - * @iface: ptr to vpif interface - */ -static inline enum v4l2_field vpif_get_default_field( - struct vpif_interface *iface) -{ - return (iface->if_type == VPIF_IF_RAW_BAYER) ? V4L2_FIELD_NONE : - V4L2_FIELD_INTERLACED; -} - /** * vpif_config_addr() - function to configure buffer address in vpif * @ch: channel ptr From 5fadfc31a7cc55f8e0e1e4d4b67c365f11623dca Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 12:26:19 +0000 Subject: [PATCH 208/397] media: drxd: drop offset var from DownloadMicrocode() The offset is not needed, and it is never used, as the pointer itself is already incremented. So, drop it, in order to solve a W=1 clang warning. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxd_hard.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c index a7eb81df88c2..9860cae65f1c 100644 --- a/drivers/media/dvb-frontends/drxd_hard.c +++ b/drivers/media/dvb-frontends/drxd_hard.c @@ -914,44 +914,36 @@ static int DownloadMicrocode(struct drxd_state *state, u32 Address; u16 nBlocks; u16 BlockSize; - u32 offset = 0; int i, status = 0; pSrc = (u8 *) pMCImage; /* We're not using Flags */ /* Flags = (pSrc[0] << 8) | pSrc[1]; */ pSrc += sizeof(u16); - offset += sizeof(u16); nBlocks = (pSrc[0] << 8) | pSrc[1]; pSrc += sizeof(u16); - offset += sizeof(u16); for (i = 0; i < nBlocks; i++) { Address = (pSrc[0] << 24) | (pSrc[1] << 16) | (pSrc[2] << 8) | pSrc[3]; pSrc += sizeof(u32); - offset += sizeof(u32); BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16); pSrc += sizeof(u16); - offset += sizeof(u16); /* We're not using Flags */ /* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */ pSrc += sizeof(u16); - offset += sizeof(u16); /* We're not using BlockCRC */ /* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */ pSrc += sizeof(u16); - offset += sizeof(u16); status = WriteBlock(state, Address, BlockSize, pSrc, DRX_I2C_CLEARCRC); if (status < 0) break; pSrc += BlockSize; - offset += BlockSize; } return status; From 1cef39421974c5b76dc72a12b2bc94ec1cd811a3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 12:27:48 +0000 Subject: [PATCH 209/397] media: drxk: drop operation_mode from set_dvbt() This var is set, but never used. So, drop it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk_hard.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index d7fc2595f15b..9430295a8175 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -3720,7 +3720,6 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, { u16 cmd_result = 0; u16 transmission_params = 0; - u16 operation_mode = 0; u32 iqm_rc_rate_ofs = 0; u32 bandwidth = 0; u16 param1; @@ -3759,10 +3758,8 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, /* mode */ switch (state->props.transmission_mode) { case TRANSMISSION_MODE_AUTO: - default: - operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; - fallthrough; /* try first guess DRX_FFTMODE_8K */ case TRANSMISSION_MODE_8K: + default: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; break; case TRANSMISSION_MODE_2K: @@ -3773,9 +3770,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, /* guard */ switch (state->props.guard_interval) { default: - case GUARD_INTERVAL_AUTO: - operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; - fallthrough; /* try first guess DRX_GUARD_1DIV4 */ + case GUARD_INTERVAL_AUTO: /* try first guess DRX_GUARD_1DIV4 */ case GUARD_INTERVAL_1_4: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; break; @@ -3794,11 +3789,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, switch (state->props.hierarchy) { case HIERARCHY_AUTO: case HIERARCHY_NONE: - default: - operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; - /* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ - /* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ - fallthrough; + default: /* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ case HIERARCHY_1: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; break; @@ -3814,9 +3805,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, /* modulation */ switch (state->props.modulation) { case QAM_AUTO: - default: - operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; - fallthrough; /* try first guess DRX_CONSTELLATION_QAM64 */ + default: /* try first guess DRX_CONSTELLATION_QAM64 */ case QAM_64: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; break; @@ -3857,9 +3846,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, /* coderate */ switch (state->props.code_rate_HP) { case FEC_AUTO: - default: - operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; - fallthrough; /* try first guess DRX_CODERATE_2DIV3 */ + default: /* try first guess DRX_CODERATE_2DIV3 */ case FEC_2_3: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; break; From c41898e84dade305c13d2073c785009d6414631d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 12:29:13 +0000 Subject: [PATCH 210/397] media: m88ds3103: drop reg11 calculus from m88ds3103b_select_mclk() This value is never used at the code. So, drop it. Solves a W=1 clang warning. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/m88ds3103.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index 02e8aa11e36e..bce0f42f3d19 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -451,7 +451,7 @@ static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev) static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) { - u8 reg11 = 0x0A, reg15, reg16, reg1D, reg1E, reg1F, tmp; + u8 reg15, reg16, reg1D, reg1E, reg1F, tmp; u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0; u16 pll_div_fb, N; u32 div; @@ -480,8 +480,6 @@ static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) div /= mclk_khz; if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) { - reg11 |= 0x02; - if (div <= 32) { N = 2; @@ -532,8 +530,6 @@ static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) else if ((f3 < 8) && (f3 != 0)) f3 = 8; } else { - reg11 &= ~0x02; - if (div <= 32) { N = 2; From 68cfde02cc21045708ad1ebe604527ec18d5e01c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 12:30:55 +0000 Subject: [PATCH 211/397] media: si21xx: report eventual errors at set_frontend If an error occurs while setting the registers at set_frontend, it is silently ignored. Yet, the variable status is updated. Change the logic to return an error if it fails to write values to the registers. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si21xx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb-frontends/si21xx.c b/drivers/media/dvb-frontends/si21xx.c index e31eb2c5cc4c..001b23588389 100644 --- a/drivers/media/dvb-frontends/si21xx.c +++ b/drivers/media/dvb-frontends/si21xx.c @@ -711,7 +711,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe) int i; bool inband_interferer_div2[ALLOWABLE_FS_COUNT]; bool inband_interferer_div4[ALLOWABLE_FS_COUNT]; - int status; + int status = 0; /* allowable sample rates for ADC in MHz */ int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195, @@ -747,8 +747,6 @@ static int si21xx_set_frontend(struct dvb_frontend *fe) rf_freq = 10 * c->frequency ; data_rate = c->symbol_rate / 100; - status = PASS; - band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200) + (data_rate * 135)) / 200; @@ -832,6 +830,9 @@ static int si21xx_set_frontend(struct dvb_frontend *fe) state->fs = sample_rate;/*ADC MHz*/ si21xx_setacquire(fe, c->symbol_rate, c->fec_inner); + if (status) + return -EREMOTEIO; + return 0; } From 02d6276f10082a6b1277fbd8a9909929cabf759e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 11:21:47 +0000 Subject: [PATCH 212/397] media: solo6x10: mark unused functions as such There are several unused helper macros there, meant to parse some fields. As those actually help to document the hardware, the better is to keep them. However, it generates clang warnings with W=1, causing build to break with CONFIG_WERROR. So, add __always_unused to fix such warnings. Acked-by: Ismael Luceno Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c index 0abcad4e84fa..7766cadb73ea 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c @@ -391,12 +391,12 @@ static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip, } /* Extract values from VOP header - VE_STATUSxx */ -static inline int vop_interlaced(const vop_header *vh) +static inline __always_unused int vop_interlaced(const vop_header *vh) { return (__le32_to_cpu((*vh)[0]) >> 30) & 1; } -static inline u8 vop_channel(const vop_header *vh) +static inline __always_unused u8 vop_channel(const vop_header *vh) { return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F; } @@ -411,12 +411,12 @@ static inline u32 vop_mpeg_size(const vop_header *vh) return __le32_to_cpu((*vh)[0]) & 0xFFFFF; } -static inline u8 vop_hsize(const vop_header *vh) +static inline u8 __always_unused vop_hsize(const vop_header *vh) { return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF; } -static inline u8 vop_vsize(const vop_header *vh) +static inline u8 __always_unused vop_vsize(const vop_header *vh) { return __le32_to_cpu((*vh)[1]) & 0xFF; } @@ -436,12 +436,12 @@ static inline u32 vop_jpeg_size(const vop_header *vh) return __le32_to_cpu((*vh)[4]) & 0xFFFFF; } -static inline u32 vop_sec(const vop_header *vh) +static inline u32 __always_unused vop_sec(const vop_header *vh) { return __le32_to_cpu((*vh)[5]); } -static inline u32 vop_usec(const vop_header *vh) +static inline __always_unused u32 vop_usec(const vop_header *vh) { return __le32_to_cpu((*vh)[6]); } From 12c762e087a064ff40854ff7da86dd9f49084cc1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 11:24:38 +0000 Subject: [PATCH 213/397] media: si470x: fix printk warnings with clang Clang doesn't like "%hu" on macros: drivers/media/radio/si470x/radio-si470x-i2c.c:414:4: error: format specifies type 'unsigned short' but the argument has type 'int' [-Werror,-Wformat] drivers/media/radio/si470x/radio-si470x-i2c.c:417:4: error: format specifies type 'unsigned short' but the argument has type 'int' [-Werror,-Wformat] Besides that, changeset cbacb5ab0aa0 ("docs: printk-formats: Stop encouraging use of unnecessary %h[xudi] and %hh[xudi]") dropped recomendation of using %h. So, just replace them with "%u". Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x-i2c.c | 4 ++-- drivers/media/radio/si470x/radio-si470x-usb.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index a972c0705ac7..7ea7c6326f53 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -410,10 +410,10 @@ static int si470x_i2c_probe(struct i2c_client *client) radio->registers[DEVICEID], radio->registers[SI_CHIPID]); if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) { dev_warn(&client->dev, - "This driver is known to work with firmware version %hu,\n", + "This driver is known to work with firmware version %u,\n", RADIO_FW_VERSION); dev_warn(&client->dev, - "but the device has firmware version %hu.\n", + "but the device has firmware version %u.\n", radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE); version_warning = 1; } diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 3f8634a46573..1e70e6971fe4 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -681,10 +681,10 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->registers[DEVICEID], radio->registers[SI_CHIPID]); if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) { dev_warn(&intf->dev, - "This driver is known to work with firmware version %hu,\n", + "This driver is known to work with firmware version %u,\n", RADIO_FW_VERSION); dev_warn(&intf->dev, - "but the device has firmware version %hu.\n", + "but the device has firmware version %u.\n", radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE); version_warning = 1; } @@ -698,10 +698,10 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->software_version, radio->hardware_version); if (radio->hardware_version < RADIO_HW_VERSION) { dev_warn(&intf->dev, - "This driver is known to work with hardware version %hu,\n", + "This driver is known to work with hardware version %u,\n", RADIO_HW_VERSION); dev_warn(&intf->dev, - "but the device has hardware version %hu.\n", + "but the device has hardware version %u.\n", radio->hardware_version); version_warning = 1; } From d5aa19c9fd775a11a56db2380e3b451d42c50e8e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Nov 2021 12:38:06 +0100 Subject: [PATCH 214/397] media: si470x: consolidate multiple printk's When the version warning is given, multiple dev_warn() are called. Consolidate the ones that could be merged altogether. Suggested-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x-i2c.c | 17 +++-------------- drivers/media/radio/si470x/radio-si470x-usb.c | 16 +++++----------- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 7ea7c6326f53..bdb13c974b02 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -334,7 +334,6 @@ static int si470x_i2c_probe(struct i2c_client *client) { struct si470x_device *radio; int retval = 0; - unsigned char version_warning = 0; /* private data allocation and initialization */ radio = devm_kzalloc(&client->dev, sizeof(*radio), GFP_KERNEL); @@ -410,20 +409,10 @@ static int si470x_i2c_probe(struct i2c_client *client) radio->registers[DEVICEID], radio->registers[SI_CHIPID]); if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) { dev_warn(&client->dev, - "This driver is known to work with firmware version %u,\n", - RADIO_FW_VERSION); - dev_warn(&client->dev, - "but the device has firmware version %u.\n", + "This driver is known to work with firmware version %u, but the device has firmware version %u.\n" + "If you have some trouble using this driver, please report to V4L ML at linux-media@vger.kernel.org\n", + RADIO_FW_VERSION, radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE); - version_warning = 1; - } - - /* give out version warning */ - if (version_warning == 1) { - dev_warn(&client->dev, - "If you have some trouble using this driver,\n"); - dev_warn(&client->dev, - "please report to V4L ML at linux-media@vger.kernel.org\n"); } /* set initial frequency */ diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 1e70e6971fe4..6b2768623c88 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -681,10 +681,8 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->registers[DEVICEID], radio->registers[SI_CHIPID]); if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) { dev_warn(&intf->dev, - "This driver is known to work with firmware version %u,\n", - RADIO_FW_VERSION); - dev_warn(&intf->dev, - "but the device has firmware version %u.\n", + "This driver is known to work with firmware version %u, but the device has firmware version %u.\n", + RADIO_FW_VERSION, radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE); version_warning = 1; } @@ -698,10 +696,8 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->software_version, radio->hardware_version); if (radio->hardware_version < RADIO_HW_VERSION) { dev_warn(&intf->dev, - "This driver is known to work with hardware version %u,\n", - RADIO_HW_VERSION); - dev_warn(&intf->dev, - "but the device has hardware version %u.\n", + "This driver is known to work with hardware version %u, but the device has hardware version %u.\n", + RADIO_HW_VERSION, radio->hardware_version); version_warning = 1; } @@ -709,9 +705,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, /* give out version warning */ if (version_warning == 1) { dev_warn(&intf->dev, - "If you have some trouble using this driver,\n"); - dev_warn(&intf->dev, - "please report to V4L ML at linux-media@vger.kernel.org\n"); + "If you have some trouble using this driver, please report to V4L ML at linux-media@vger.kernel.org\n"); } /* set led to connect state */ From 3fb246476f8c0556747301ba7497f135068225a8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 11:27:22 +0000 Subject: [PATCH 215/397] media: radio-si476x: drop a container_of() abstraction macro This isn't used anywhere. So, drop it. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-si476x.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index b39a68f83c5f..0bf99e1cd1d8 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -312,12 +312,6 @@ struct si476x_radio { u32 audmode; }; -static inline struct si476x_radio * -v4l2_dev_to_radio(struct v4l2_device *d) -{ - return container_of(d, struct si476x_radio, v4l2dev); -} - static inline struct si476x_radio * v4l2_ctrl_handler_to_radio(struct v4l2_ctrl_handler *d) { From 77e956027c1912082d3749350d0066be99921d12 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2021 12:01:48 +0000 Subject: [PATCH 216/397] media: lmedm04: don't ignore errors when setting a filter Solves a clang warning. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/lmedm04.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index fe4d886442a4..8a34e6c0d6a6 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -423,6 +423,9 @@ static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) mutex_unlock(&d->i2c_mutex); + if (ret) + return -EREMOTEIO; + return 0; } From 091b15db22e40e7865ba32b1392e3a7a1ee9e852 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 11:37:36 +0000 Subject: [PATCH 217/397] media: au0828-i2c: drop a duplicated function This function is not used, so, just drop it. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-i2c.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c index 708f01ab47fa..749f90d73b5b 100644 --- a/drivers/media/usb/au0828/au0828-i2c.c +++ b/drivers/media/usb/au0828/au0828-i2c.c @@ -23,13 +23,6 @@ MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); #define I2C_WAIT_DELAY 25 #define I2C_WAIT_RETRY 1000 -static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_NO_WRITE_ACK ? 0 : 1; -} - static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap) { struct au0828_dev *dev = i2c_adap->algo_data; From 12f3d83673c4800aebdd96efb366a04d2d636596 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 11:42:49 +0000 Subject: [PATCH 218/397] media: adv7604: mark unused functions as such There are several unused helper macros there, meant to parse some fields. As those actually help to document the hardware, the better is to keep them. However, it generates clang warnings with W=1, causing build to break with CONFIG_WERROR. So, add __always_unused to fix such warnings. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 44768b59a6ff..a2fa408d2d9f 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -398,14 +398,14 @@ static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val); } -static inline int avlink_read(struct v4l2_subdev *sd, u8 reg) +static inline int __always_unused avlink_read(struct v4l2_subdev *sd, u8 reg) { struct adv76xx_state *state = to_state(sd); return adv76xx_read_check(state, ADV7604_PAGE_AVLINK, reg); } -static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val) +static inline int __always_unused avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val) { struct adv76xx_state *state = to_state(sd); @@ -439,14 +439,14 @@ static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg) return adv76xx_read_check(state, ADV76XX_PAGE_INFOFRAME, reg); } -static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val) +static inline int __always_unused infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val) { struct adv76xx_state *state = to_state(sd); return regmap_write(state->regmap[ADV76XX_PAGE_INFOFRAME], reg, val); } -static inline int afe_read(struct v4l2_subdev *sd, u8 reg) +static inline int __always_unused afe_read(struct v4l2_subdev *sd, u8 reg) { struct adv76xx_state *state = to_state(sd); @@ -479,14 +479,14 @@ static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 return rep_write(sd, reg, (rep_read(sd, reg) & ~mask) | val); } -static inline int edid_read(struct v4l2_subdev *sd, u8 reg) +static inline int __always_unused edid_read(struct v4l2_subdev *sd, u8 reg) { struct adv76xx_state *state = to_state(sd); return adv76xx_read_check(state, ADV76XX_PAGE_EDID, reg); } -static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val) +static inline int __always_unused edid_write(struct v4l2_subdev *sd, u8 reg, u8 val) { struct adv76xx_state *state = to_state(sd); @@ -570,7 +570,7 @@ static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val); } -static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val) +static inline int __always_unused test_write(struct v4l2_subdev *sd, u8 reg, u8 val) { struct adv76xx_state *state = to_state(sd); @@ -601,14 +601,14 @@ static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 v return cp_write(sd, reg, (cp_read(sd, reg) & ~mask) | val); } -static inline int vdp_read(struct v4l2_subdev *sd, u8 reg) +static inline int __always_unused vdp_read(struct v4l2_subdev *sd, u8 reg) { struct adv76xx_state *state = to_state(sd); return adv76xx_read_check(state, ADV7604_PAGE_VDP, reg); } -static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) +static inline int __always_unused vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) { struct adv76xx_state *state = to_state(sd); From 6c0adaf907775578868812197a06785de8b262e3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 11:45:26 +0000 Subject: [PATCH 219/397] media: adv7511: drop unused functions Those are aliases for another function and not used at the current implementation. So, just drop it. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7511-v4l2.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/media/i2c/adv7511-v4l2.c b/drivers/media/i2c/adv7511-v4l2.c index 41f4e749a859..8e13cae40ec5 100644 --- a/drivers/media/i2c/adv7511-v4l2.c +++ b/drivers/media/i2c/adv7511-v4l2.c @@ -270,28 +270,6 @@ static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg) return adv_smbus_read_byte_data(state->i2c_pktmem, reg); } -static int adv7511_pktmem_wr(struct v4l2_subdev *sd, u8 reg, u8 val) -{ - struct adv7511_state *state = get_adv7511_state(sd); - int ret; - int i; - - for (i = 0; i < 3; i++) { - ret = i2c_smbus_write_byte_data(state->i2c_pktmem, reg, val); - if (ret == 0) - return 0; - } - v4l2_err(sd, "%s: i2c write error\n", __func__); - return ret; -} - -/* To set specific bits in the register, a clear-mask is given (to be AND-ed), - and then the value-mask (to be OR-ed). */ -static inline void adv7511_pktmem_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask) -{ - adv7511_pktmem_wr(sd, reg, (adv7511_pktmem_rd(sd, reg) & clr_mask) | val_mask); -} - static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd) { return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT; From 1804eba4eb613c6125260c320d98d21035fcae70 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 11:48:45 +0000 Subject: [PATCH 220/397] media: imx290: mark read reg function as __always_unused Such function is currently unused, but could be needed in the future. So, keep it, marking it as __always_unused, in order to avoid a clang W=1 error. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/imx290.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c index bf7a6c37ca5d..99f2a50d39a4 100644 --- a/drivers/media/i2c/imx290.c +++ b/drivers/media/i2c/imx290.c @@ -363,7 +363,7 @@ static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd) return container_of(_sd, struct imx290, sd); } -static inline int imx290_read_reg(struct imx290 *imx290, u16 addr, u8 *value) +static inline int __always_unused imx290_read_reg(struct imx290 *imx290, u16 addr, u8 *value) { unsigned int regval; int ret; From 820ef3aa40482703030761bf58266d3d8b1544cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 11:54:15 +0000 Subject: [PATCH 221/397] media: davinci: vpbe_osd: mark read reg function as __always_unused Such function is currently unused, but could be needed in the future. So, keep it, marking it as __always_unused, in order to avoid a clang W=1 error. Reviewed-by: Lad Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpbe_osd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c index 91b571a0ac2c..32f7ef547c82 100644 --- a/drivers/media/platform/davinci/vpbe_osd.c +++ b/drivers/media/platform/davinci/vpbe_osd.c @@ -45,7 +45,7 @@ static const struct platform_device_id vpbe_osd_devtype[] = { MODULE_DEVICE_TABLE(platform, vpbe_osd_devtype); /* register access routines */ -static inline u32 osd_read(struct osd_state *sd, u32 offset) +static inline u32 __always_unused osd_read(struct osd_state *sd, u32 offset) { struct osd_state *osd = sd; From 7225436dd8cb481b560e2a52088d0f829887a8cf Mon Sep 17 00:00:00 2001 From: Robert Foss Date: Mon, 11 Oct 2021 14:13:01 +0200 Subject: [PATCH 222/397] media: camss: Remove unused static function vfe_reg_clr() is not used in camss-vfe-170.c, and can be removed. Signed-off-by: Robert Foss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/camss/camss-vfe-170.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-vfe-170.c b/drivers/media/platform/qcom/camss/camss-vfe-170.c index 5c083d70d495..f524af712a84 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-170.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-170.c @@ -191,13 +191,6 @@ static u32 vfe_hw_version(struct vfe_device *vfe) return hw_version; } -static inline void vfe_reg_clr(struct vfe_device *vfe, u32 reg, u32 clr_bits) -{ - u32 bits = readl_relaxed(vfe->base + reg); - - writel_relaxed(bits & ~clr_bits, vfe->base + reg); -} - static inline void vfe_reg_set(struct vfe_device *vfe, u32 reg, u32 set_bits) { u32 bits = readl_relaxed(vfe->base + reg); From 440aae04f38bf5f5fe620783fd9effa57a0a9ae4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 11:56:50 +0000 Subject: [PATCH 223/397] media: mtk-mdp: address a clang warning The typecasts at the dvb-core generate clang warnings when W=1 is enabled. Such warning is harmless, but it causes the build to break with CONFIG_WERROR and W=1 with clang, so do the cast on a way that it won't produce warnings anymore. Reviewed-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-mdp/mtk_mdp_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c index 976aa1f4829b..3d38793aaa25 100644 --- a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c @@ -148,7 +148,7 @@ static int mtk_mdp_probe(struct platform_device *pdev) continue; } - comp_type = (enum mtk_mdp_comp_type)of_id->data; + comp_type = (uintptr_t)of_id->data; comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL); if (!comp) { From 675599009abc973b21a5a459799f34123562f517 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 12:07:01 +0000 Subject: [PATCH 224/397] media: cobalt: drop an unused variable The clock_control value is read but never actually used. Based on a comment at the code, it has to be reset at the function. So, drop the variable that stores its value. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cobalt/cobalt-cpld.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/pci/cobalt/cobalt-cpld.c b/drivers/media/pci/cobalt/cobalt-cpld.c index 3d8026483ac3..fad882459d23 100644 --- a/drivers/media/pci/cobalt/cobalt-cpld.c +++ b/drivers/media/pci/cobalt/cobalt-cpld.c @@ -236,7 +236,6 @@ bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out) u8 n1, hsdiv; u8 regs[6]; int found = 0; - u16 clock_ctrl; int retries = 3; for (i = 0; i < ARRAY_SIZE(multipliers); i++) { @@ -260,9 +259,7 @@ bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out) hsdiv = multipliers[i_best].hsdiv - 4; rfreq = div_u64(dco << 28, f_xtal); - clock_ctrl = cpld_read(cobalt, SI570_CLOCK_CTRL); - clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL; - clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN; + cpld_read(cobalt, SI570_CLOCK_CTRL); regs[0] = (hsdiv << 5) | (n1 >> 2); regs[1] = ((n1 & 0x3) << 6) | (rfreq >> 32); From bd0d78ada27770bbddfd24e74f4136507f64736c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Nov 2021 20:06:42 +0100 Subject: [PATCH 225/397] media: mxl5005s: drop some dead code As reported by clang (with W=1), the ctrlVal var is never used. Yet, there are even some loops to estimate it. As this is dead code, remove it. If ever needed, someone could revert this patch. Reviewed-by: Nathan Chancellor Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/mxl5005s.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/media/tuners/mxl5005s.c b/drivers/media/tuners/mxl5005s.c index f6e82a8e7d37..ab4c43df9d18 100644 --- a/drivers/media/tuners/mxl5005s.c +++ b/drivers/media/tuners/mxl5005s.c @@ -3414,9 +3414,8 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup) { struct mxl5005s_state *state = fe->tuner_priv; - u16 i, j, k; + u16 i, j; u32 highLimit; - u32 ctrlVal; if (controlGroup == 1) /* Initial Control */ { @@ -3432,9 +3431,6 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, (u8)(state->Init_Ctrl[i].bit[j]), (u8)((value>>j) & 0x01)); } - ctrlVal = 0; - for (k = 0; k < state->Init_Ctrl[i].size; k++) - ctrlVal += state->Init_Ctrl[i].val[k] * (1 << k); } else return -1; } @@ -3454,9 +3450,6 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, (u8)(state->CH_Ctrl[i].bit[j]), (u8)((value>>j) & 0x01)); } - ctrlVal = 0; - for (k = 0; k < state->CH_Ctrl[i].size; k++) - ctrlVal += state->CH_Ctrl[i].val[k] * (1 << k); } else return -1; } @@ -3477,11 +3470,6 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, (u8)(state->MXL_Ctrl[i].bit[j]), (u8)((value>>j) & 0x01)); } - ctrlVal = 0; - for (k = 0; k < state->MXL_Ctrl[i].size; k++) - ctrlVal += state-> - MXL_Ctrl[i].val[k] * - (1 << k); } else return -1; } From 60f9462cfa608dbd6b7e68da8c30940163a87a65 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Tue, 2 Nov 2021 12:02:43 +0100 Subject: [PATCH 226/397] media: i2c: max9286: Depend on VIDEO_V4L2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MAX9286 has not explicitly declared a dependency upon VIDEO_V4L2. While this dependency has likely always been met by configurations including it, the device does use V4L2 core, and should depend upon it. Add VIDEO_V4L2 as a dependency to match other drivers and prevent failures when compile testing. Signed-off-by: Kieran Bingham Reviewed-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index d6a5d4ca439a..e9cfedf561d3 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -469,6 +469,7 @@ config VIDEO_VPX3220 config VIDEO_MAX9286 tristate "Maxim MAX9286 GMSL deserializer support" depends on I2C && I2C_MUX + depends on VIDEO_V4L2 depends on OF_GPIO select V4L2_FWNODE select VIDEO_V4L2_SUBDEV_API From da653498c20ba5b185214d8ae43b4e8e9594f520 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Wed, 17 Nov 2021 16:40:09 +0100 Subject: [PATCH 227/397] media: i2c: imx274: fix s_frame_interval runtime resume not requested pm_runtime_resume_and_get should be called when the s_frame_interval is called. The driver will try to access device registers to configure VMAX, coarse time and exposure. Currently if the runtime is not resumed, this fails: # media-ctl -d /dev/media0 --set-v4l2 '"IMX274 1-001a":0[fmt:SRGGB10_1X10/3840x2 160@1/10]' IMX274 1-001a: imx274_binning_goodness: ask 3840x2160, size 3840x2160, goodness 0 IMX274 1-001a: imx274_binning_goodness: ask 3840x2160, size 1920x1080, goodness -3000 IMX274 1-001a: imx274_binning_goodness: ask 3840x2160, size 1280x720, goodness -4000 IMX274 1-001a: imx274_binning_goodness: ask 3840x2160, size 1280x540, goodness -4180 IMX274 1-001a: __imx274_change_compose: selected 1x1 binning IMX274 1-001a: imx274_set_frame_interval: input frame interval = 1 / 10 IMX274 1-001a: imx274_read_mbreg : addr 0x300e, val=0x1 (2 bytes) IMX274 1-001a: imx274_set_frame_interval : register SVR = 1 IMX274 1-001a: imx274_read_mbreg : addr 0x30f6, val=0x6a8 (2 bytes) IMX274 1-001a: imx274_set_frame_interval : register HMAX = 1704 IMX274 1-001a: imx274_set_frame_length : input length = 2112 IMX274 1-001a: imx274_write_mbreg : i2c bulk write failed, 30f8 = 884 (3 bytes) IMX274 1-001a: imx274_set_frame_length error = -121 IMX274 1-001a: imx274_set_frame_interval error = -121 Unable to setup formats: Remote I/O error (121) The device is not resumed thus the remote I/O error. Setting the frame interval works at streaming time, because pm_runtime_resume_and_get is called at s_stream time before sensor setup. The failure happens when only the s_frame_interval is called separately independently on streaming time. Fixes: ad97bc37426c ("media: i2c: imx274: Add IMX274 power on and off sequence") Signed-off-by: Eugen Hristev Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/imx274.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 0dce92872176..4d9b64c61f60 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -1367,6 +1367,10 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd, int min, max, def; int ret; + ret = pm_runtime_resume_and_get(&imx274->client->dev); + if (ret < 0) + return ret; + mutex_lock(&imx274->lock); ret = imx274_set_frame_interval(imx274, fi->interval); @@ -1398,6 +1402,7 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd, unlock: mutex_unlock(&imx274->lock); + pm_runtime_put(&imx274->client->dev); return ret; } From 4e05d5f24b2c0cdb8adb3c3b93dc05fe7facae66 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Thu, 18 Nov 2021 08:17:15 +0100 Subject: [PATCH 228/397] media: i2c: imx274: fix trivial typo expsoure/exposure Fix typo expsoure/exposure Fixes: 0985dd306f72 ("media: imx274: V4l2 driver for Sony imx274 CMOS sensor") Signed-off-by: Eugen Hristev Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/imx274.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 4d9b64c61f60..5312cf3e855d 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -1462,7 +1462,7 @@ static int imx274_s_stream(struct v4l2_subdev *sd, int on) goto fail; /* - * update frame rate & expsoure. if the last mode is different, + * update frame rate & exposure. if the last mode is different, * HMAX could be changed. As the result, frame rate & exposure * are changed. * gain is not affected. From 358ed66bfcdaec6de70e27c747887604b9ea2e6e Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Thu, 18 Nov 2021 13:51:51 +0100 Subject: [PATCH 229/397] media: i2c: imx274: fix trivial typo obainted/obtained Fix typo obainted/obtained. Fixes: 0985dd306f72 ("media: imx274: V4l2 driver for Sony imx274 CMOS sensor") Signed-off-by: Eugen Hristev Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/imx274.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 5312cf3e855d..2e804e3b70c4 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -1499,7 +1499,7 @@ fail: /* * imx274_get_frame_length - Function for obtaining current frame length * @priv: Pointer to device structure - * @val: Pointer to obainted value + * @val: Pointer to obtained value * * frame_length = vmax x (svr + 1), in unit of hmax. * From 7218905afd1a830ba86a30389cd080d9e00b7000 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Thu, 18 Nov 2021 16:40:09 +0100 Subject: [PATCH 230/397] media: i2c: imx274: implement enum_mbus_code Current driver supports only SRGGB 10 bit RAW bayer format. Add the enum_mbus_code implementation to report this format supported. # v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-mbus-codes ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0) 0x300f: MEDIA_BUS_FMT_SRGGB10_1X10 # Signed-off-by: Eugen Hristev Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/imx274.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 2e804e3b70c4..25a4ef8f6187 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -1909,7 +1909,21 @@ fail: return err; } +static int imx274_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index > 0) + return -EINVAL; + + /* only supported format in the driver is Raw 10 bits SRGGB */ + code->code = MEDIA_BUS_FMT_SRGGB10_1X10; + + return 0; +} + static const struct v4l2_subdev_pad_ops imx274_pad_ops = { + .enum_mbus_code = imx274_enum_mbus_code, .get_fmt = imx274_get_fmt, .set_fmt = imx274_set_fmt, .get_selection = imx274_get_selection, From a5f0900246818c1eb7c98e324a898afa9af69e90 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 00:56:11 +0100 Subject: [PATCH 231/397] media: ipu3-cio2: Toggle sensor streaming in pm runtime ops The .suspend() and .resume() runtime_pm operations for the ipu3-cio2 driver currently do not handle the sensor's stream. Setting .s_stream() on or off for the sensor subdev means that sensors will pause and resume the stream at the appropriate time even if their drivers don't implement those operations. Reviewed-by: Kieran Bingham Signed-off-by: Daniel Scally Tested-by: Jean-Michel Hautbois Reviewed-by: Jean-Michel Hautbois Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c index 356ea966cf8d..e2874fee9530 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c @@ -1966,12 +1966,19 @@ static int __maybe_unused cio2_suspend(struct device *dev) struct pci_dev *pci_dev = to_pci_dev(dev); struct cio2_device *cio2 = pci_get_drvdata(pci_dev); struct cio2_queue *q = cio2->cur_queue; + int r; dev_dbg(dev, "cio2 suspend\n"); if (!cio2->streaming) return 0; /* Stop stream */ + r = v4l2_subdev_call(q->sensor, video, s_stream, 0); + if (r) { + dev_err(dev, "failed to stop sensor streaming\n"); + return r; + } + cio2_hw_exit(cio2, q); synchronize_irq(pci_dev->irq); @@ -2005,8 +2012,16 @@ static int __maybe_unused cio2_resume(struct device *dev) } r = cio2_hw_init(cio2, q); - if (r) + if (r) { dev_err(dev, "fail to init cio2 hw\n"); + return r; + } + + r = v4l2_subdev_call(q->sensor, video, s_stream, 1); + if (r) { + dev_err(dev, "fail to start sensor streaming\n"); + cio2_hw_exit(cio2, q); + } return r; } From 89aef879cb537061f7a0948210fc00c5f1b5dfb4 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 00:56:12 +0100 Subject: [PATCH 232/397] media: i2c: Add support for ov5693 sensor The OV5693 is a 5 Mpx CMOS image sensor, connected via MIPI CSI-2. The chip is capable of a single lane configuration, but currently only two lanes are supported. Most of the sensor's features are supported, with the main exception being the lens correction algorithm. The driver provides all mandatory, optional and recommended V4L2 controls for maximum compatibility with libcamera. [mchehab: fixed a coding style warning] Signed-off-by: Daniel Scally Tested-by: Jean-Michel Hautbois Reviewed-by: Jean-Michel Hautbois Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 7 + drivers/media/i2c/Kconfig | 11 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/ov5693.c | 1537 ++++++++++++++++++++++++++++++++++++ 4 files changed, 1556 insertions(+) create mode 100644 drivers/media/i2c/ov5693.c diff --git a/MAINTAINERS b/MAINTAINERS index 8eea24d54624..c869091df7f9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14107,6 +14107,13 @@ S: Maintained T: git git://linuxtv.org/media_tree.git F: drivers/media/i2c/ov5675.c +OMNIVISION OV5693 SENSOR DRIVER +M: Daniel Scally +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: drivers/media/i2c/ov5693.c + OMNIVISION OV5695 SENSOR DRIVER M: Shunqian Zheng L: linux-media@vger.kernel.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index e9cfedf561d3..69c56e24a612 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1059,6 +1059,17 @@ config VIDEO_OV5675 To compile this driver as a module, choose M here: the module will be called ov5675. +config VIDEO_OV5693 + tristate "OmniVision OV5693 sensor support" + depends on I2C && VIDEO_V4L2 + select V4L2_FWNODE + help + This is a Video4Linux2 sensor driver for the OmniVision + OV5693 camera. + + To compile this driver as a module, choose M here: the + module will be called ov5693. + config VIDEO_OV5695 tristate "OmniVision OV5695 sensor support" depends on I2C && VIDEO_V4L2 diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 4d4fe08d7a6a..b01f6cd05ee8 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -75,6 +75,7 @@ obj-$(CONFIG_VIDEO_OV5647) += ov5647.o obj-$(CONFIG_VIDEO_OV5648) += ov5648.o obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV5675) += ov5675.o +obj-$(CONFIG_VIDEO_OV5693) += ov5693.o obj-$(CONFIG_VIDEO_OV5695) += ov5695.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7251) += ov7251.o diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c new file mode 100644 index 000000000000..2784fcf67f3b --- /dev/null +++ b/drivers/media/i2c/ov5693.c @@ -0,0 +1,1537 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2013 Intel Corporation. All Rights Reserved. + * + * Adapted from the atomisp-ov5693 driver, with contributions from: + * + * Daniel Scally + * Jean-Michel Hautbois + * Fabian Wuthrich + * Tsuchiya Yuto + * Jordan Hand + * Jake Day + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OV5693_REG_8BIT(n) ((1 << 16) | (n)) +#define OV5693_REG_16BIT(n) ((2 << 16) | (n)) +#define OV5693_REG_24BIT(n) ((3 << 16) | (n)) +#define OV5693_REG_SIZE_SHIFT 16 +#define OV5693_REG_ADDR_MASK 0xffff + +/* System Control */ +#define OV5693_SW_RESET_REG OV5693_REG_8BIT(0x0103) +#define OV5693_SW_STREAM_REG OV5693_REG_8BIT(0x0100) +#define OV5693_START_STREAMING 0x01 +#define OV5693_STOP_STREAMING 0x00 +#define OV5693_SW_RESET 0x01 + +#define OV5693_REG_CHIP_ID OV5693_REG_16BIT(0x300a) +/* Yes, this is right. The datasheet for the OV5693 gives its ID as 0x5690 */ +#define OV5693_CHIP_ID 0x5690 + +/* Exposure */ +#define OV5693_EXPOSURE_CTRL_REG OV5693_REG_24BIT(0x3500) +#define OV5693_EXPOSURE_CTRL_MASK GENMASK(19, 4) +#define OV5693_INTEGRATION_TIME_MARGIN 8 +#define OV5693_EXPOSURE_MIN 1 +#define OV5693_EXPOSURE_STEP 1 + +/* Analogue Gain */ +#define OV5693_GAIN_CTRL_REG OV5693_REG_16BIT(0x350a) +#define OV5693_GAIN_CTRL_MASK GENMASK(10, 4) +#define OV5693_GAIN_MIN 1 +#define OV5693_GAIN_MAX 127 +#define OV5693_GAIN_DEF 8 +#define OV5693_GAIN_STEP 1 + +/* Digital Gain */ +#define OV5693_MWB_RED_GAIN_REG OV5693_REG_16BIT(0x3400) +#define OV5693_MWB_GREEN_GAIN_REG OV5693_REG_16BIT(0x3402) +#define OV5693_MWB_BLUE_GAIN_REG OV5693_REG_16BIT(0x3404) +#define OV5693_MWB_GAIN_MASK GENMASK(11, 0) +#define OV5693_MWB_GAIN_MAX 0x0fff +#define OV5693_DIGITAL_GAIN_MIN 1 +#define OV5693_DIGITAL_GAIN_MAX 4095 +#define OV5693_DIGITAL_GAIN_DEF 1024 +#define OV5693_DIGITAL_GAIN_STEP 1 + +/* Timing and Format */ +#define OV5693_CROP_START_X_REG OV5693_REG_16BIT(0x3800) +#define OV5693_CROP_START_Y_REG OV5693_REG_16BIT(0x3802) +#define OV5693_CROP_END_X_REG OV5693_REG_16BIT(0x3804) +#define OV5693_CROP_END_Y_REG OV5693_REG_16BIT(0x3806) +#define OV5693_OUTPUT_SIZE_X_REG OV5693_REG_16BIT(0x3808) +#define OV5693_OUTPUT_SIZE_Y_REG OV5693_REG_16BIT(0x380a) + +#define OV5693_TIMING_HTS_REG OV5693_REG_16BIT(0x380c) +#define OV5693_FIXED_PPL 2688U +#define OV5693_TIMING_VTS_REG OV5693_REG_16BIT(0x380e) +#define OV5693_TIMING_MAX_VTS 0xffff +#define OV5693_TIMING_MIN_VTS 0x04 + +#define OV5693_OFFSET_START_X_REG OV5693_REG_16BIT(0x3810) +#define OV5693_OFFSET_START_Y_REG OV5693_REG_16BIT(0x3812) + +#define OV5693_SUB_INC_X_REG OV5693_REG_8BIT(0x3814) +#define OV5693_SUB_INC_Y_REG OV5693_REG_8BIT(0x3815) + +#define OV5693_FORMAT1_REG OV5693_REG_8BIT(0x3820) +#define OV5693_FORMAT1_FLIP_VERT_ISP_EN BIT(6) +#define OV5693_FORMAT1_FLIP_VERT_SENSOR_EN BIT(1) +#define OV5693_FORMAT1_VBIN_EN BIT(0) +#define OV5693_FORMAT2_REG OV5693_REG_8BIT(0x3821) +#define OV5693_FORMAT2_HDR_EN BIT(7) +#define OV5693_FORMAT2_FLIP_HORZ_ISP_EN BIT(2) +#define OV5693_FORMAT2_FLIP_HORZ_SENSOR_EN BIT(1) +#define OV5693_FORMAT2_HBIN_EN BIT(0) + +#define OV5693_ISP_CTRL2_REG OV5693_REG_8BIT(0x5002) +#define OV5693_ISP_SCALE_ENABLE BIT(7) + +/* Pixel Array */ +#define OV5693_NATIVE_WIDTH 2624 +#define OV5693_NATIVE_HEIGHT 1956 +#define OV5693_NATIVE_START_LEFT 0 +#define OV5693_NATIVE_START_TOP 0 +#define OV5693_ACTIVE_WIDTH 2592 +#define OV5693_ACTIVE_HEIGHT 1944 +#define OV5693_ACTIVE_START_LEFT 16 +#define OV5693_ACTIVE_START_TOP 6 +#define OV5693_MIN_CROP_WIDTH 2 +#define OV5693_MIN_CROP_HEIGHT 2 + +/* Test Pattern */ +#define OV5693_TEST_PATTERN_REG OV5693_REG_8BIT(0x5e00) +#define OV5693_TEST_PATTERN_ENABLE BIT(7) +#define OV5693_TEST_PATTERN_ROLLING BIT(6) +#define OV5693_TEST_PATTERN_RANDOM 0x01 +#define OV5693_TEST_PATTERN_BARS 0x00 + +/* System Frequencies */ +#define OV5693_XVCLK_FREQ 19200000 +#define OV5693_LINK_FREQ_419_2MHZ 419200000 +#define OV5693_PIXEL_RATE 167680000 + +/* Miscellaneous */ +#define OV5693_NUM_SUPPLIES 2 + +#define to_ov5693_sensor(x) container_of(x, struct ov5693_device, sd) + +struct ov5693_reg { + u32 reg; + u8 val; +}; + +struct ov5693_reg_list { + u32 num_regs; + const struct ov5693_reg *regs; +}; + +struct ov5693_device { + struct i2c_client *client; + struct device *dev; + + /* Protect against concurrent changes to controls */ + struct mutex lock; + + struct gpio_desc *reset; + struct gpio_desc *powerdown; + struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES]; + struct clk *clk; + + struct ov5693_mode { + struct v4l2_rect crop; + struct v4l2_mbus_framefmt format; + bool binning_x; + bool binning_y; + unsigned int inc_x_odd; + unsigned int inc_y_odd; + unsigned int vts; + } mode; + bool streaming; + + struct v4l2_subdev sd; + struct media_pad pad; + + struct ov5693_v4l2_ctrls { + struct v4l2_ctrl_handler handler; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *analogue_gain; + struct v4l2_ctrl *digital_gain; + struct v4l2_ctrl *hflip; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *test_pattern; + } ctrls; +}; + +static const struct ov5693_reg ov5693_global_regs[] = { + {OV5693_REG_8BIT(0x3016), 0xf0}, + {OV5693_REG_8BIT(0x3017), 0xf0}, + {OV5693_REG_8BIT(0x3018), 0xf0}, + {OV5693_REG_8BIT(0x3022), 0x01}, + {OV5693_REG_8BIT(0x3028), 0x44}, + {OV5693_REG_8BIT(0x3098), 0x02}, + {OV5693_REG_8BIT(0x3099), 0x19}, + {OV5693_REG_8BIT(0x309a), 0x02}, + {OV5693_REG_8BIT(0x309b), 0x01}, + {OV5693_REG_8BIT(0x309c), 0x00}, + {OV5693_REG_8BIT(0x30a0), 0xd2}, + {OV5693_REG_8BIT(0x30a2), 0x01}, + {OV5693_REG_8BIT(0x30b2), 0x00}, + {OV5693_REG_8BIT(0x30b3), 0x83}, + {OV5693_REG_8BIT(0x30b4), 0x03}, + {OV5693_REG_8BIT(0x30b5), 0x04}, + {OV5693_REG_8BIT(0x30b6), 0x01}, + {OV5693_REG_8BIT(0x3080), 0x01}, + {OV5693_REG_8BIT(0x3104), 0x21}, + {OV5693_REG_8BIT(0x3106), 0x00}, + {OV5693_REG_8BIT(0x3406), 0x01}, + {OV5693_REG_8BIT(0x3503), 0x07}, + {OV5693_REG_8BIT(0x350b), 0x40}, + {OV5693_REG_8BIT(0x3601), 0x0a}, + {OV5693_REG_8BIT(0x3602), 0x38}, + {OV5693_REG_8BIT(0x3612), 0x80}, + {OV5693_REG_8BIT(0x3620), 0x54}, + {OV5693_REG_8BIT(0x3621), 0xc7}, + {OV5693_REG_8BIT(0x3622), 0x0f}, + {OV5693_REG_8BIT(0x3625), 0x10}, + {OV5693_REG_8BIT(0x3630), 0x55}, + {OV5693_REG_8BIT(0x3631), 0xf4}, + {OV5693_REG_8BIT(0x3632), 0x00}, + {OV5693_REG_8BIT(0x3633), 0x34}, + {OV5693_REG_8BIT(0x3634), 0x02}, + {OV5693_REG_8BIT(0x364d), 0x0d}, + {OV5693_REG_8BIT(0x364f), 0xdd}, + {OV5693_REG_8BIT(0x3660), 0x04}, + {OV5693_REG_8BIT(0x3662), 0x10}, + {OV5693_REG_8BIT(0x3663), 0xf1}, + {OV5693_REG_8BIT(0x3665), 0x00}, + {OV5693_REG_8BIT(0x3666), 0x20}, + {OV5693_REG_8BIT(0x3667), 0x00}, + {OV5693_REG_8BIT(0x366a), 0x80}, + {OV5693_REG_8BIT(0x3680), 0xe0}, + {OV5693_REG_8BIT(0x3681), 0x00}, + {OV5693_REG_8BIT(0x3700), 0x42}, + {OV5693_REG_8BIT(0x3701), 0x14}, + {OV5693_REG_8BIT(0x3702), 0xa0}, + {OV5693_REG_8BIT(0x3703), 0xd8}, + {OV5693_REG_8BIT(0x3704), 0x78}, + {OV5693_REG_8BIT(0x3705), 0x02}, + {OV5693_REG_8BIT(0x370a), 0x00}, + {OV5693_REG_8BIT(0x370b), 0x20}, + {OV5693_REG_8BIT(0x370c), 0x0c}, + {OV5693_REG_8BIT(0x370d), 0x11}, + {OV5693_REG_8BIT(0x370e), 0x00}, + {OV5693_REG_8BIT(0x370f), 0x40}, + {OV5693_REG_8BIT(0x3710), 0x00}, + {OV5693_REG_8BIT(0x371a), 0x1c}, + {OV5693_REG_8BIT(0x371b), 0x05}, + {OV5693_REG_8BIT(0x371c), 0x01}, + {OV5693_REG_8BIT(0x371e), 0xa1}, + {OV5693_REG_8BIT(0x371f), 0x0c}, + {OV5693_REG_8BIT(0x3721), 0x00}, + {OV5693_REG_8BIT(0x3724), 0x10}, + {OV5693_REG_8BIT(0x3726), 0x00}, + {OV5693_REG_8BIT(0x372a), 0x01}, + {OV5693_REG_8BIT(0x3730), 0x10}, + {OV5693_REG_8BIT(0x3738), 0x22}, + {OV5693_REG_8BIT(0x3739), 0xe5}, + {OV5693_REG_8BIT(0x373a), 0x50}, + {OV5693_REG_8BIT(0x373b), 0x02}, + {OV5693_REG_8BIT(0x373c), 0x41}, + {OV5693_REG_8BIT(0x373f), 0x02}, + {OV5693_REG_8BIT(0x3740), 0x42}, + {OV5693_REG_8BIT(0x3741), 0x02}, + {OV5693_REG_8BIT(0x3742), 0x18}, + {OV5693_REG_8BIT(0x3743), 0x01}, + {OV5693_REG_8BIT(0x3744), 0x02}, + {OV5693_REG_8BIT(0x3747), 0x10}, + {OV5693_REG_8BIT(0x374c), 0x04}, + {OV5693_REG_8BIT(0x3751), 0xf0}, + {OV5693_REG_8BIT(0x3752), 0x00}, + {OV5693_REG_8BIT(0x3753), 0x00}, + {OV5693_REG_8BIT(0x3754), 0xc0}, + {OV5693_REG_8BIT(0x3755), 0x00}, + {OV5693_REG_8BIT(0x3756), 0x1a}, + {OV5693_REG_8BIT(0x3758), 0x00}, + {OV5693_REG_8BIT(0x3759), 0x0f}, + {OV5693_REG_8BIT(0x376b), 0x44}, + {OV5693_REG_8BIT(0x375c), 0x04}, + {OV5693_REG_8BIT(0x3774), 0x10}, + {OV5693_REG_8BIT(0x3776), 0x00}, + {OV5693_REG_8BIT(0x377f), 0x08}, + {OV5693_REG_8BIT(0x3780), 0x22}, + {OV5693_REG_8BIT(0x3781), 0x0c}, + {OV5693_REG_8BIT(0x3784), 0x2c}, + {OV5693_REG_8BIT(0x3785), 0x1e}, + {OV5693_REG_8BIT(0x378f), 0xf5}, + {OV5693_REG_8BIT(0x3791), 0xb0}, + {OV5693_REG_8BIT(0x3795), 0x00}, + {OV5693_REG_8BIT(0x3796), 0x64}, + {OV5693_REG_8BIT(0x3797), 0x11}, + {OV5693_REG_8BIT(0x3798), 0x30}, + {OV5693_REG_8BIT(0x3799), 0x41}, + {OV5693_REG_8BIT(0x379a), 0x07}, + {OV5693_REG_8BIT(0x379b), 0xb0}, + {OV5693_REG_8BIT(0x379c), 0x0c}, + {OV5693_REG_8BIT(0x3a04), 0x06}, + {OV5693_REG_8BIT(0x3a05), 0x14}, + {OV5693_REG_8BIT(0x3e07), 0x20}, + {OV5693_REG_8BIT(0x4000), 0x08}, + {OV5693_REG_8BIT(0x4001), 0x04}, + {OV5693_REG_8BIT(0x4004), 0x08}, + {OV5693_REG_8BIT(0x4006), 0x20}, + {OV5693_REG_8BIT(0x4008), 0x24}, + {OV5693_REG_8BIT(0x4009), 0x10}, + {OV5693_REG_8BIT(0x4058), 0x00}, + {OV5693_REG_8BIT(0x4101), 0xb2}, + {OV5693_REG_8BIT(0x4307), 0x31}, + {OV5693_REG_8BIT(0x4511), 0x05}, + {OV5693_REG_8BIT(0x4512), 0x01}, + {OV5693_REG_8BIT(0x481f), 0x30}, + {OV5693_REG_8BIT(0x4826), 0x2c}, + {OV5693_REG_8BIT(0x4d02), 0xfd}, + {OV5693_REG_8BIT(0x4d03), 0xf5}, + {OV5693_REG_8BIT(0x4d04), 0x0c}, + {OV5693_REG_8BIT(0x4d05), 0xcc}, + {OV5693_REG_8BIT(0x4837), 0x0a}, + {OV5693_REG_8BIT(0x5003), 0x20}, + {OV5693_REG_8BIT(0x5013), 0x00}, + {OV5693_REG_8BIT(0x5842), 0x01}, + {OV5693_REG_8BIT(0x5843), 0x2b}, + {OV5693_REG_8BIT(0x5844), 0x01}, + {OV5693_REG_8BIT(0x5845), 0x92}, + {OV5693_REG_8BIT(0x5846), 0x01}, + {OV5693_REG_8BIT(0x5847), 0x8f}, + {OV5693_REG_8BIT(0x5848), 0x01}, + {OV5693_REG_8BIT(0x5849), 0x0c}, + {OV5693_REG_8BIT(0x5e10), 0x0c}, + {OV5693_REG_8BIT(0x3820), 0x00}, + {OV5693_REG_8BIT(0x3821), 0x1e}, + {OV5693_REG_8BIT(0x5041), 0x14} +}; + +static const struct ov5693_reg_list ov5693_global_setting = { + .num_regs = ARRAY_SIZE(ov5693_global_regs), + .regs = ov5693_global_regs, +}; + +static const struct v4l2_rect ov5693_default_crop = { + .left = OV5693_ACTIVE_START_LEFT, + .top = OV5693_ACTIVE_START_TOP, + .width = OV5693_ACTIVE_WIDTH, + .height = OV5693_ACTIVE_HEIGHT, +}; + +static const struct v4l2_mbus_framefmt ov5693_default_fmt = { + .width = OV5693_ACTIVE_WIDTH, + .height = OV5693_ACTIVE_HEIGHT, + .code = MEDIA_BUS_FMT_SBGGR10_1X10, +}; + +static const s64 link_freq_menu_items[] = { + OV5693_LINK_FREQ_419_2MHZ +}; + +static const char * const ov5693_supply_names[] = { + "avdd", + "dovdd", +}; + +static const char * const ov5693_test_pattern_menu[] = { + "Disabled", + "Random Data", + "Colour Bars", + "Colour Bars with Rolling Bar" +}; + +static const u8 ov5693_test_pattern_bits[] = { + 0, + OV5693_TEST_PATTERN_ENABLE | OV5693_TEST_PATTERN_RANDOM, + OV5693_TEST_PATTERN_ENABLE | OV5693_TEST_PATTERN_BARS, + OV5693_TEST_PATTERN_ENABLE | OV5693_TEST_PATTERN_BARS | + OV5693_TEST_PATTERN_ROLLING, +}; + +/* I2C I/O Operations */ + +static int ov5693_read_reg(struct ov5693_device *ov5693, u32 addr, u32 *value) +{ + struct i2c_client *client = ov5693->client; + __be16 reg; + u8 val[4]; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = (u8 *)®, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .buf = (u8 *)&val, + }, + }; + unsigned int len = ((addr >> OV5693_REG_SIZE_SHIFT) & 3); + unsigned int i; + int ret; + + reg = cpu_to_be16(addr & OV5693_REG_ADDR_MASK); + + msg[1].len = len; + + ret = i2c_transfer(client->adapter, msg, 2); + if (ret < 0) + return dev_err_probe(&client->dev, ret, + "Failed to read register 0x%04x: %d\n", + addr & OV5693_REG_ADDR_MASK, ret); + + *value = 0; + for (i = 0; i < len; ++i) { + *value <<= 8; + *value |= val[i]; + } + + return 0; +} + +static void ov5693_write_reg(struct ov5693_device *ov5693, u32 addr, u32 value, + int *error) +{ + struct i2c_client *client = ov5693->client; + struct { + __be16 reg; + u8 val[4]; + } __packed buf; + struct i2c_msg msg = { + .addr = client->addr, + .buf = (u8 *)&buf, + }; + unsigned int len = ((addr >> OV5693_REG_SIZE_SHIFT) & 3); + unsigned int i; + int ret; + + if (*error < 0) + return; + + buf.reg = cpu_to_be16(addr & OV5693_REG_ADDR_MASK); + for (i = 0; i < len; ++i) { + buf.val[len - i - 1] = value & 0xff; + value >>= 8; + } + + msg.len = len + 2; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) { + dev_err(&client->dev, "Failed to write register 0x%04x: %d\n", + addr & OV5693_REG_ADDR_MASK, ret); + *error = ret; + } +} + +static int ov5693_write_reg_array(struct ov5693_device *ov5693, + const struct ov5693_reg_list *reglist) +{ + unsigned int i; + int ret = 0; + + for (i = 0; i < reglist->num_regs; i++) + ov5693_write_reg(ov5693, reglist->regs[i].reg, + reglist->regs[i].val, &ret); + + return ret; +} + +static int ov5693_update_bits(struct ov5693_device *ov5693, u32 address, + u32 mask, u32 bits) +{ + u32 value = 0; + int ret; + + ret = ov5693_read_reg(ov5693, address, &value); + if (ret) + return ret; + + value &= ~mask; + value |= bits; + + ov5693_write_reg(ov5693, address, value, &ret); + + return ret; +} + +/* V4L2 Controls Functions */ + +static int ov5693_flip_vert_configure(struct ov5693_device *ov5693, + bool enable) +{ + u8 bits = OV5693_FORMAT1_FLIP_VERT_ISP_EN | + OV5693_FORMAT1_FLIP_VERT_SENSOR_EN; + int ret; + + ret = ov5693_update_bits(ov5693, OV5693_FORMAT1_REG, bits, + enable ? bits : 0); + if (ret) + return ret; + + return 0; +} + +static int ov5693_flip_horz_configure(struct ov5693_device *ov5693, + bool enable) +{ + u8 bits = OV5693_FORMAT2_FLIP_HORZ_ISP_EN | + OV5693_FORMAT2_FLIP_HORZ_SENSOR_EN; + int ret; + + ret = ov5693_update_bits(ov5693, OV5693_FORMAT2_REG, bits, + enable ? bits : 0); + if (ret) + return ret; + + return 0; +} + +static int ov5693_get_exposure(struct ov5693_device *ov5693, s32 *value) +{ + u32 exposure; + int ret; + + ret = ov5693_read_reg(ov5693, OV5693_EXPOSURE_CTRL_REG, &exposure); + if (ret) + return ret; + + /* The lowest 4 bits are unsupported fractional bits */ + *value = exposure >> 4; + + return 0; +} + +static int ov5693_exposure_configure(struct ov5693_device *ov5693, + u32 exposure) +{ + int ret = 0; + + exposure = (exposure << 4) & OV5693_EXPOSURE_CTRL_MASK; + + ov5693_write_reg(ov5693, OV5693_EXPOSURE_CTRL_REG, exposure, &ret); + + return ret; +} + +static int ov5693_get_gain(struct ov5693_device *ov5693, u32 *gain) +{ + u32 value; + int ret; + + ret = ov5693_read_reg(ov5693, OV5693_GAIN_CTRL_REG, &value); + if (ret) + return ret; + + /* As with exposure, the lowest 4 bits are fractional bits. */ + *gain = value >> 4; + + return ret; +} + +static int ov5693_digital_gain_configure(struct ov5693_device *ov5693, + u32 gain) +{ + int ret = 0; + + gain &= OV5693_MWB_GAIN_MASK; + + ov5693_write_reg(ov5693, OV5693_MWB_RED_GAIN_REG, gain, &ret); + ov5693_write_reg(ov5693, OV5693_MWB_GREEN_GAIN_REG, gain, &ret); + ov5693_write_reg(ov5693, OV5693_MWB_BLUE_GAIN_REG, gain, &ret); + + return ret; +} + +static int ov5693_analog_gain_configure(struct ov5693_device *ov5693, u32 gain) +{ + int ret = 0; + + gain = (gain << 4) & OV5693_GAIN_CTRL_MASK; + + ov5693_write_reg(ov5693, OV5693_GAIN_CTRL_REG, gain, &ret); + + return ret; +} + +static int ov5693_vts_configure(struct ov5693_device *ov5693, u32 vblank) +{ + u16 vts = ov5693->mode.format.height + vblank; + int ret = 0; + + ov5693_write_reg(ov5693, OV5693_TIMING_VTS_REG, vts, &ret); + + return ret; +} + +static int ov5693_test_pattern_configure(struct ov5693_device *ov5693, u32 idx) +{ + int ret = 0; + + ov5693_write_reg(ov5693, OV5693_TEST_PATTERN_REG, + ov5693_test_pattern_bits[idx], &ret); + + return ret; +} + +static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov5693_device *ov5693 = + container_of(ctrl->handler, struct ov5693_device, ctrls.handler); + int ret = 0; + + /* If VBLANK is altered we need to update exposure to compensate */ + if (ctrl->id == V4L2_CID_VBLANK) { + int exposure_max; + + exposure_max = ov5693->mode.format.height + ctrl->val - + OV5693_INTEGRATION_TIME_MARGIN; + __v4l2_ctrl_modify_range(ov5693->ctrls.exposure, + ov5693->ctrls.exposure->minimum, + exposure_max, + ov5693->ctrls.exposure->step, + min(ov5693->ctrls.exposure->val, + exposure_max)); + } + + /* Only apply changes to the controls if the device is powered up */ + if (!pm_runtime_get_if_in_use(ov5693->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + ret = ov5693_exposure_configure(ov5693, ctrl->val); + break; + case V4L2_CID_ANALOGUE_GAIN: + ret = ov5693_analog_gain_configure(ov5693, ctrl->val); + break; + case V4L2_CID_DIGITAL_GAIN: + ret = ov5693_digital_gain_configure(ov5693, ctrl->val); + break; + case V4L2_CID_HFLIP: + ret = ov5693_flip_horz_configure(ov5693, !!ctrl->val); + break; + case V4L2_CID_VFLIP: + ret = ov5693_flip_vert_configure(ov5693, !!ctrl->val); + break; + case V4L2_CID_VBLANK: + ret = ov5693_vts_configure(ov5693, ctrl->val); + break; + case V4L2_CID_TEST_PATTERN: + ret = ov5693_test_pattern_configure(ov5693, ctrl->val); + break; + default: + ret = -EINVAL; + } + + pm_runtime_put(ov5693->dev); + + return ret; +} + +static int ov5693_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov5693_device *ov5693 = container_of(ctrl->handler, + struct ov5693_device, + ctrls.handler); + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE_ABSOLUTE: + return ov5693_get_exposure(ov5693, &ctrl->val); + case V4L2_CID_AUTOGAIN: + return ov5693_get_gain(ov5693, &ctrl->val); + default: + return -EINVAL; + } +} + +static const struct v4l2_ctrl_ops ov5693_ctrl_ops = { + .s_ctrl = ov5693_s_ctrl, + .g_volatile_ctrl = ov5693_g_volatile_ctrl +}; + +/* System Control Functions */ + +static int ov5693_mode_configure(struct ov5693_device *ov5693) +{ + const struct ov5693_mode *mode = &ov5693->mode; + int ret = 0; + + /* Crop Start X */ + ov5693_write_reg(ov5693, OV5693_CROP_START_X_REG, mode->crop.left, + &ret); + + /* Offset X */ + ov5693_write_reg(ov5693, OV5693_OFFSET_START_X_REG, 0, &ret); + + /* Output Size X */ + ov5693_write_reg(ov5693, OV5693_OUTPUT_SIZE_X_REG, mode->format.width, + &ret); + + /* Crop End X */ + ov5693_write_reg(ov5693, OV5693_CROP_END_X_REG, + mode->crop.left + mode->crop.width, &ret); + + /* Horizontal Total Size */ + ov5693_write_reg(ov5693, OV5693_TIMING_HTS_REG, OV5693_FIXED_PPL, + &ret); + + /* Crop Start Y */ + ov5693_write_reg(ov5693, OV5693_CROP_START_Y_REG, mode->crop.top, + &ret); + + /* Offset Y */ + ov5693_write_reg(ov5693, OV5693_OFFSET_START_Y_REG, 0, &ret); + + /* Output Size Y */ + ov5693_write_reg(ov5693, OV5693_OUTPUT_SIZE_Y_REG, mode->format.height, + &ret); + + /* Crop End Y */ + ov5693_write_reg(ov5693, OV5693_CROP_END_Y_REG, + mode->crop.top + mode->crop.height, &ret); + + /* Subsample X increase */ + ov5693_write_reg(ov5693, OV5693_SUB_INC_X_REG, + ((mode->inc_x_odd << 4) & 0xf0) | 0x01, &ret); + /* Subsample Y increase */ + ov5693_write_reg(ov5693, OV5693_SUB_INC_Y_REG, + ((mode->inc_y_odd << 4) & 0xf0) | 0x01, &ret); + + if (ret) + return ret; + + /* Binning */ + ret = ov5693_update_bits(ov5693, OV5693_FORMAT1_REG, + OV5693_FORMAT1_VBIN_EN, + mode->binning_y ? OV5693_FORMAT1_VBIN_EN : 0); + if (ret) + return ret; + + ret = ov5693_update_bits(ov5693, OV5693_FORMAT2_REG, + OV5693_FORMAT2_HBIN_EN, + mode->binning_x ? OV5693_FORMAT2_HBIN_EN : 0); + + return ret; +} + +static int ov5693_enable_streaming(struct ov5693_device *ov5693, bool enable) +{ + int ret = 0; + + ov5693_write_reg(ov5693, OV5693_SW_STREAM_REG, + enable ? OV5693_START_STREAMING : + OV5693_STOP_STREAMING, &ret); + + return ret; +} + +static int ov5693_sw_reset(struct ov5693_device *ov5693) +{ + int ret = 0; + + ov5693_write_reg(ov5693, OV5693_SW_RESET_REG, OV5693_SW_RESET, &ret); + + return ret; +} + +static int ov5693_sensor_init(struct ov5693_device *ov5693) +{ + int ret; + + ret = ov5693_sw_reset(ov5693); + if (ret) + return dev_err_probe(ov5693->dev, ret, + "software reset error\n"); + + ret = ov5693_write_reg_array(ov5693, &ov5693_global_setting); + if (ret) + return dev_err_probe(ov5693->dev, ret, + "global settings error\n"); + + ret = ov5693_mode_configure(ov5693); + if (ret) + return dev_err_probe(ov5693->dev, ret, + "mode configure error\n"); + + ret = ov5693_enable_streaming(ov5693, false); + if (ret) + dev_err(ov5693->dev, "stop streaming error\n"); + + return ret; +} + +static void ov5693_sensor_powerdown(struct ov5693_device *ov5693) +{ + gpiod_set_value_cansleep(ov5693->reset, 1); + gpiod_set_value_cansleep(ov5693->powerdown, 1); + + regulator_bulk_disable(OV5693_NUM_SUPPLIES, ov5693->supplies); + + clk_disable_unprepare(ov5693->clk); +} + +static int ov5693_sensor_powerup(struct ov5693_device *ov5693) +{ + int ret; + + gpiod_set_value_cansleep(ov5693->reset, 1); + gpiod_set_value_cansleep(ov5693->powerdown, 1); + + ret = clk_prepare_enable(ov5693->clk); + if (ret) { + dev_err(ov5693->dev, "Failed to enable clk\n"); + goto fail_power; + } + + ret = regulator_bulk_enable(OV5693_NUM_SUPPLIES, ov5693->supplies); + if (ret) { + dev_err(ov5693->dev, "Failed to enable regulators\n"); + goto fail_power; + } + + gpiod_set_value_cansleep(ov5693->powerdown, 0); + gpiod_set_value_cansleep(ov5693->reset, 0); + + usleep_range(5000, 7500); + + return 0; + +fail_power: + ov5693_sensor_powerdown(ov5693); + return ret; +} + +static int __maybe_unused ov5693_sensor_suspend(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + + ov5693_sensor_powerdown(ov5693); + + return 0; +} + +static int __maybe_unused ov5693_sensor_resume(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + int ret; + + mutex_lock(&ov5693->lock); + + ret = ov5693_sensor_powerup(ov5693); + if (ret) + goto out_unlock; + + ret = ov5693_sensor_init(ov5693); + if (ret) { + dev_err(dev, "ov5693 sensor init failure\n"); + goto err_power; + } + + goto out_unlock; + +err_power: + ov5693_sensor_powerdown(ov5693); +out_unlock: + mutex_unlock(&ov5693->lock); + return ret; +} + +static int ov5693_detect(struct ov5693_device *ov5693) +{ + int ret; + u32 id; + + ret = ov5693_read_reg(ov5693, OV5693_REG_CHIP_ID, &id); + if (ret) + return ret; + + if (id != OV5693_CHIP_ID) + return dev_err_probe(ov5693->dev, -ENODEV, + "sensor ID mismatch. Found 0x%04x\n", id); + + return 0; +} + +/* V4L2 Framework callbacks */ + +static unsigned int __ov5693_calc_vts(u32 height) +{ + /* + * We need to set a sensible default VTS for whatever format height we + * happen to be given from set_fmt(). This function just targets + * an even multiple of 30fps. + */ + + unsigned int tgt_fps; + + tgt_fps = rounddown(OV5693_PIXEL_RATE / OV5693_FIXED_PPL / height, 30); + + return ALIGN_DOWN(OV5693_PIXEL_RATE / OV5693_FIXED_PPL / tgt_fps, 2); +} + +static struct v4l2_mbus_framefmt * +__ov5693_get_pad_format(struct ov5693_device *ov5693, + struct v4l2_subdev_state *state, + unsigned int pad, enum v4l2_subdev_format_whence which) +{ + switch (which) { + case V4L2_SUBDEV_FORMAT_TRY: + return v4l2_subdev_get_try_format(&ov5693->sd, state, pad); + case V4L2_SUBDEV_FORMAT_ACTIVE: + return &ov5693->mode.format; + default: + return NULL; + } +} + +static struct v4l2_rect * +__ov5693_get_pad_crop(struct ov5693_device *ov5693, + struct v4l2_subdev_state *state, + unsigned int pad, enum v4l2_subdev_format_whence which) +{ + switch (which) { + case V4L2_SUBDEV_FORMAT_TRY: + return v4l2_subdev_get_try_crop(&ov5693->sd, state, pad); + case V4L2_SUBDEV_FORMAT_ACTIVE: + return &ov5693->mode.crop; + } + + return NULL; +} + +static int ov5693_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *format) +{ + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + + format->format = ov5693->mode.format; + + return 0; +} + +static int ov5693_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *format) +{ + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + const struct v4l2_rect *crop; + struct v4l2_mbus_framefmt *fmt; + unsigned int hratio, vratio; + unsigned int width, height; + unsigned int hblank; + int exposure_max; + int ret = 0; + + crop = __ov5693_get_pad_crop(ov5693, state, format->pad, format->which); + + /* + * Align to two to simplify the binning calculations below, and clamp + * the requested format at the crop rectangle + */ + width = clamp_t(unsigned int, ALIGN(format->format.width, 2), + OV5693_MIN_CROP_WIDTH, crop->width); + height = clamp_t(unsigned int, ALIGN(format->format.height, 2), + OV5693_MIN_CROP_HEIGHT, crop->height); + + /* + * We can only support setting either the dimensions of the crop rect + * or those dimensions binned (separately) by a factor of two. + */ + hratio = clamp_t(unsigned int, + DIV_ROUND_CLOSEST(crop->width, width), 1, 2); + vratio = clamp_t(unsigned int, + DIV_ROUND_CLOSEST(crop->height, height), 1, 2); + + fmt = __ov5693_get_pad_format(ov5693, state, format->pad, + format->which); + + fmt->width = crop->width / hratio; + fmt->height = crop->height / vratio; + fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; + + format->format = *fmt; + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) + return ret; + + mutex_lock(&ov5693->lock); + + ov5693->mode.binning_x = hratio > 1 ? true : false; + ov5693->mode.inc_x_odd = hratio > 1 ? 3 : 1; + ov5693->mode.binning_y = vratio > 1 ? true : false; + ov5693->mode.inc_y_odd = vratio > 1 ? 3 : 1; + + ov5693->mode.vts = __ov5693_calc_vts(fmt->height); + + __v4l2_ctrl_modify_range(ov5693->ctrls.vblank, + OV5693_TIMING_MIN_VTS, + OV5693_TIMING_MAX_VTS - fmt->height, + 1, ov5693->mode.vts - fmt->height); + __v4l2_ctrl_s_ctrl(ov5693->ctrls.vblank, + ov5693->mode.vts - fmt->height); + + hblank = OV5693_FIXED_PPL - fmt->width; + __v4l2_ctrl_modify_range(ov5693->ctrls.hblank, hblank, hblank, 1, + hblank); + + exposure_max = ov5693->mode.vts - OV5693_INTEGRATION_TIME_MARGIN; + __v4l2_ctrl_modify_range(ov5693->ctrls.exposure, + ov5693->ctrls.exposure->minimum, exposure_max, + ov5693->ctrls.exposure->step, + min(ov5693->ctrls.exposure->val, + exposure_max)); + + mutex_unlock(&ov5693->lock); + return ret; +} + +static int ov5693_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + mutex_lock(&ov5693->lock); + sel->r = *__ov5693_get_pad_crop(ov5693, state, sel->pad, + sel->which); + mutex_unlock(&ov5693->lock); + break; + case V4L2_SEL_TGT_NATIVE_SIZE: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = OV5693_NATIVE_WIDTH; + sel->r.height = OV5693_NATIVE_HEIGHT; + break; + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + sel->r.top = OV5693_ACTIVE_START_TOP; + sel->r.left = OV5693_ACTIVE_START_LEFT; + sel->r.width = OV5693_ACTIVE_WIDTH; + sel->r.height = OV5693_ACTIVE_HEIGHT; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ov5693_set_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + struct v4l2_mbus_framefmt *format; + struct v4l2_rect *__crop; + struct v4l2_rect rect; + + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + /* + * Clamp the boundaries of the crop rectangle to the size of the sensor + * pixel array. Align to multiples of 2 to ensure Bayer pattern isn't + * disrupted. + */ + rect.left = clamp(ALIGN(sel->r.left, 2), OV5693_NATIVE_START_LEFT, + OV5693_NATIVE_WIDTH); + rect.top = clamp(ALIGN(sel->r.top, 2), OV5693_NATIVE_START_TOP, + OV5693_NATIVE_HEIGHT); + rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), + OV5693_MIN_CROP_WIDTH, OV5693_NATIVE_WIDTH); + rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), + OV5693_MIN_CROP_HEIGHT, OV5693_NATIVE_HEIGHT); + + /* Make sure the crop rectangle isn't outside the bounds of the array */ + rect.width = min_t(unsigned int, rect.width, + OV5693_NATIVE_WIDTH - rect.left); + rect.height = min_t(unsigned int, rect.height, + OV5693_NATIVE_HEIGHT - rect.top); + + __crop = __ov5693_get_pad_crop(ov5693, state, sel->pad, sel->which); + + if (rect.width != __crop->width || rect.height != __crop->height) { + /* + * Reset the output image size if the crop rectangle size has + * been modified. + */ + format = __ov5693_get_pad_format(ov5693, state, sel->pad, + sel->which); + format->width = rect.width; + format->height = rect.height; + } + + *__crop = rect; + sel->r = rect; + + return 0; +} + +static int ov5693_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + int ret; + + if (enable) { + ret = pm_runtime_get_sync(ov5693->dev); + if (ret < 0) + goto err_power_down; + + mutex_lock(&ov5693->lock); + ret = __v4l2_ctrl_handler_setup(&ov5693->ctrls.handler); + if (ret) { + mutex_unlock(&ov5693->lock); + goto err_power_down; + } + + ret = ov5693_enable_streaming(ov5693, true); + mutex_unlock(&ov5693->lock); + } else { + mutex_lock(&ov5693->lock); + ret = ov5693_enable_streaming(ov5693, false); + mutex_unlock(&ov5693->lock); + } + if (ret) + goto err_power_down; + + ov5693->streaming = !!enable; + + if (!enable) + pm_runtime_put(ov5693->dev); + + return 0; +err_power_down: + pm_runtime_put_noidle(ov5693->dev); + return ret; +} + +static int ov5693_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval) +{ + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + unsigned int framesize = OV5693_FIXED_PPL * (ov5693->mode.format.height + + ov5693->ctrls.vblank->val); + unsigned int fps = DIV_ROUND_CLOSEST(OV5693_PIXEL_RATE, framesize); + + interval->interval.numerator = 1; + interval->interval.denominator = fps; + + return 0; +} + +static int ov5693_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_mbus_code_enum *code) +{ + /* Only a single mbus format is supported */ + if (code->index > 0) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_SBGGR10_1X10; + return 0; +} + +static int ov5693_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + struct v4l2_rect *__crop; + + if (fse->index > 1 || fse->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + __crop = __ov5693_get_pad_crop(ov5693, state, fse->pad, fse->which); + if (!__crop) + return -EINVAL; + + fse->min_width = __crop->width / (fse->index + 1); + fse->min_height = __crop->height / (fse->index + 1); + fse->max_width = fse->min_width; + fse->max_height = fse->min_height; + + return 0; +} + +static const struct v4l2_subdev_video_ops ov5693_video_ops = { + .s_stream = ov5693_s_stream, + .g_frame_interval = ov5693_g_frame_interval, +}; + +static const struct v4l2_subdev_pad_ops ov5693_pad_ops = { + .enum_mbus_code = ov5693_enum_mbus_code, + .enum_frame_size = ov5693_enum_frame_size, + .get_fmt = ov5693_get_fmt, + .set_fmt = ov5693_set_fmt, + .get_selection = ov5693_get_selection, + .set_selection = ov5693_set_selection, +}; + +static const struct v4l2_subdev_ops ov5693_ops = { + .video = &ov5693_video_ops, + .pad = &ov5693_pad_ops, +}; + +/* Sensor and Driver Configuration Functions */ + +static int ov5693_init_controls(struct ov5693_device *ov5693) +{ + const struct v4l2_ctrl_ops *ops = &ov5693_ctrl_ops; + struct ov5693_v4l2_ctrls *ctrls = &ov5693->ctrls; + struct v4l2_fwnode_device_properties props; + int vblank_max, vblank_def; + int exposure_max; + int hblank; + int ret; + + ret = v4l2_ctrl_handler_init(&ctrls->handler, 12); + if (ret) + return ret; + + /* link freq */ + ctrls->link_freq = v4l2_ctrl_new_int_menu(&ctrls->handler, + NULL, V4L2_CID_LINK_FREQ, + 0, 0, link_freq_menu_items); + if (ctrls->link_freq) + ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + /* pixel rate */ + ctrls->pixel_rate = v4l2_ctrl_new_std(&ctrls->handler, NULL, + V4L2_CID_PIXEL_RATE, 0, + OV5693_PIXEL_RATE, 1, + OV5693_PIXEL_RATE); + + /* Exposure */ + exposure_max = ov5693->mode.vts - OV5693_INTEGRATION_TIME_MARGIN; + ctrls->exposure = v4l2_ctrl_new_std(&ctrls->handler, ops, + V4L2_CID_EXPOSURE, + OV5693_EXPOSURE_MIN, exposure_max, + OV5693_EXPOSURE_STEP, exposure_max); + + /* Gain */ + ctrls->analogue_gain = v4l2_ctrl_new_std(&ctrls->handler, + ops, V4L2_CID_ANALOGUE_GAIN, + OV5693_GAIN_MIN, + OV5693_GAIN_MAX, + OV5693_GAIN_STEP, + OV5693_GAIN_DEF); + + ctrls->digital_gain = v4l2_ctrl_new_std(&ctrls->handler, ops, + V4L2_CID_DIGITAL_GAIN, + OV5693_DIGITAL_GAIN_MIN, + OV5693_DIGITAL_GAIN_MAX, + OV5693_DIGITAL_GAIN_STEP, + OV5693_DIGITAL_GAIN_DEF); + + /* Flip */ + ctrls->hflip = v4l2_ctrl_new_std(&ctrls->handler, ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + + ctrls->vflip = v4l2_ctrl_new_std(&ctrls->handler, ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + hblank = OV5693_FIXED_PPL - ov5693->mode.format.width; + ctrls->hblank = v4l2_ctrl_new_std(&ctrls->handler, ops, + V4L2_CID_HBLANK, hblank, + hblank, 1, hblank); + + if (ctrls->hblank) + ctrls->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + vblank_max = OV5693_TIMING_MAX_VTS - ov5693->mode.format.height; + vblank_def = ov5693->mode.vts - ov5693->mode.format.height; + ctrls->vblank = v4l2_ctrl_new_std(&ctrls->handler, ops, + V4L2_CID_VBLANK, + OV5693_TIMING_MIN_VTS, + vblank_max, 1, vblank_def); + + ctrls->test_pattern = v4l2_ctrl_new_std_menu_items( + &ctrls->handler, ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ov5693_test_pattern_menu) - 1, + 0, 0, ov5693_test_pattern_menu); + + if (ctrls->handler.error) { + dev_err(ov5693->dev, "Error initialising v4l2 ctrls\n"); + ret = ctrls->handler.error; + goto err_free_handler; + } + + /* set properties from fwnode (e.g. rotation, orientation) */ + ret = v4l2_fwnode_device_parse(ov5693->dev, &props); + if (ret) + goto err_free_handler; + + ret = v4l2_ctrl_new_fwnode_properties(&ctrls->handler, ops, + &props); + if (ret) + goto err_free_handler; + + /* Use same lock for controls as for everything else. */ + ctrls->handler.lock = &ov5693->lock; + ov5693->sd.ctrl_handler = &ctrls->handler; + + return 0; + +err_free_handler: + v4l2_ctrl_handler_free(&ctrls->handler); + return ret; +} + +static int ov5693_configure_gpios(struct ov5693_device *ov5693) +{ + ov5693->reset = devm_gpiod_get_optional(ov5693->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(ov5693->reset)) { + dev_err(ov5693->dev, "Error fetching reset GPIO\n"); + return PTR_ERR(ov5693->reset); + } + + ov5693->powerdown = devm_gpiod_get_optional(ov5693->dev, "powerdown", + GPIOD_OUT_HIGH); + if (IS_ERR(ov5693->powerdown)) { + dev_err(ov5693->dev, "Error fetching powerdown GPIO\n"); + return PTR_ERR(ov5693->powerdown); + } + + return 0; +} + +static int ov5693_get_regulators(struct ov5693_device *ov5693) +{ + unsigned int i; + + for (i = 0; i < OV5693_NUM_SUPPLIES; i++) + ov5693->supplies[i].supply = ov5693_supply_names[i]; + + return devm_regulator_bulk_get(ov5693->dev, OV5693_NUM_SUPPLIES, + ov5693->supplies); +} + +static int ov5693_check_hwcfg(struct ov5693_device *ov5693) +{ + struct fwnode_handle *fwnode = dev_fwnode(ov5693->dev); + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + struct fwnode_handle *endpoint; + unsigned int i; + int ret; + + endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!endpoint) + return -EPROBE_DEFER; /* Could be provided by cio2-bridge */ + + ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &bus_cfg); + fwnode_handle_put(endpoint); + if (ret) + return ret; + + if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) { + dev_err(ov5693->dev, "only a 2-lane CSI2 config is supported"); + ret = -EINVAL; + goto out_free_bus_cfg; + } + + if (!bus_cfg.nr_of_link_frequencies) { + dev_err(ov5693->dev, "no link frequencies defined\n"); + ret = -EINVAL; + goto out_free_bus_cfg; + } + + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) + if (bus_cfg.link_frequencies[i] == OV5693_LINK_FREQ_419_2MHZ) + break; + + if (i == bus_cfg.nr_of_link_frequencies) { + dev_err(ov5693->dev, "supported link freq %ull not found\n", + OV5693_LINK_FREQ_419_2MHZ); + ret = -EINVAL; + goto out_free_bus_cfg; + } + +out_free_bus_cfg: + v4l2_fwnode_endpoint_free(&bus_cfg); + + return ret; +} + +static int ov5693_probe(struct i2c_client *client) +{ + struct ov5693_device *ov5693; + u32 clk_rate; + int ret = 0; + + ov5693 = devm_kzalloc(&client->dev, sizeof(*ov5693), GFP_KERNEL); + if (!ov5693) + return -ENOMEM; + + ov5693->client = client; + ov5693->dev = &client->dev; + + ret = ov5693_check_hwcfg(ov5693); + if (ret) + return ret; + + mutex_init(&ov5693->lock); + + v4l2_i2c_subdev_init(&ov5693->sd, client, &ov5693_ops); + + ov5693->clk = devm_clk_get(&client->dev, "xvclk"); + if (IS_ERR(ov5693->clk)) { + dev_err(&client->dev, "Error getting clock\n"); + return PTR_ERR(ov5693->clk); + } + + clk_rate = clk_get_rate(ov5693->clk); + if (clk_rate != OV5693_XVCLK_FREQ) + dev_warn(&client->dev, "Found clk freq %u, expected %u\n", + clk_rate, OV5693_XVCLK_FREQ); + + ret = ov5693_configure_gpios(ov5693); + if (ret) + return ret; + + ret = ov5693_get_regulators(ov5693); + if (ret) + return dev_err_probe(&client->dev, ret, + "Error fetching regulators\n"); + + ov5693->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + ov5693->pad.flags = MEDIA_PAD_FL_SOURCE; + ov5693->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + + ov5693->mode.crop = ov5693_default_crop; + ov5693->mode.format = ov5693_default_fmt; + ov5693->mode.vts = __ov5693_calc_vts(ov5693->mode.format.height); + + ret = ov5693_init_controls(ov5693); + if (ret) + return ret; + + ret = media_entity_pads_init(&ov5693->sd.entity, 1, &ov5693->pad); + if (ret) + goto err_ctrl_handler_free; + + /* + * We need the driver to work in the event that pm runtime is disable in + * the kernel, so power up and verify the chip now. In the event that + * runtime pm is disabled this will leave the chip on, so that streaming + * will work. + */ + + ret = ov5693_sensor_powerup(ov5693); + if (ret) + goto err_media_entity_cleanup; + + ret = ov5693_detect(ov5693); + if (ret) + goto err_powerdown; + + pm_runtime_set_active(&client->dev); + pm_runtime_get_noresume(&client->dev); + pm_runtime_enable(&client->dev); + + ret = v4l2_async_register_subdev_sensor(&ov5693->sd); + if (ret) { + dev_err(&client->dev, "failed to register V4L2 subdev: %d", + ret); + goto err_pm_runtime; + } + + pm_runtime_set_autosuspend_delay(&client->dev, 1000); + pm_runtime_use_autosuspend(&client->dev); + pm_runtime_put_autosuspend(&client->dev); + + return ret; + +err_pm_runtime: + pm_runtime_disable(&client->dev); + pm_runtime_put_noidle(&client->dev); +err_powerdown: + ov5693_sensor_powerdown(ov5693); +err_media_entity_cleanup: + media_entity_cleanup(&ov5693->sd.entity); +err_ctrl_handler_free: + v4l2_ctrl_handler_free(&ov5693->ctrls.handler); + + return ret; +} + +static int ov5693_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov5693_device *ov5693 = to_ov5693_sensor(sd); + + v4l2_async_unregister_subdev(sd); + media_entity_cleanup(&ov5693->sd.entity); + v4l2_ctrl_handler_free(&ov5693->ctrls.handler); + mutex_destroy(&ov5693->lock); + + /* + * Disable runtime PM. In case runtime PM is disabled in the kernel, + * make sure to turn power off manually. + */ + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + ov5693_sensor_powerdown(ov5693); + pm_runtime_set_suspended(&client->dev); + + return 0; +} + +static const struct dev_pm_ops ov5693_pm_ops = { + SET_RUNTIME_PM_OPS(ov5693_sensor_suspend, ov5693_sensor_resume, NULL) +}; + +static const struct acpi_device_id ov5693_acpi_match[] = { + {"INT33BE"}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, ov5693_acpi_match); + +static struct i2c_driver ov5693_driver = { + .driver = { + .name = "ov5693", + .acpi_match_table = ov5693_acpi_match, + .pm = &ov5693_pm_ops, + }, + .probe_new = ov5693_probe, + .remove = ov5693_remove, +}; +module_i2c_driver(ov5693_driver); + +MODULE_DESCRIPTION("A low-level driver for OmniVision 5693 sensors"); +MODULE_LICENSE("GPL"); From 887bda234082423b84a63ef09dbda7fd106074e5 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 00:56:13 +0100 Subject: [PATCH 233/397] media: ipu3-cio2: Add link freq for INT33BE entry Add a link frequency to the cio2-bridge table of supported sensors. This means that the driver can parse supported link frequencies from firmware in the usual way and validate that it can accommodate them. Signed-off-by: Daniel Scally Tested-by: Jean-Michel Hautbois Reviewed-by: Jean-Michel Hautbois Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 0b586b4e537e..b4b8930d795c 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -21,7 +21,7 @@ */ static const struct cio2_sensor_config cio2_supported_sensors[] = { /* Omnivision OV5693 */ - CIO2_SENSOR_CONFIG("INT33BE", 0), + CIO2_SENSOR_CONFIG("INT33BE", 1, 419200000), /* Omnivision OV2680 */ CIO2_SENSOR_CONFIG("OVTI2680", 0), }; From d2484fbf780762f6f9cc3abb7a07ee42dca2eaa3 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:01 +0100 Subject: [PATCH 234/397] media: i2c: Re-order runtime pm initialisation The kerneldoc for pm_runtime_set_suspended() says: "It is not valid to call this function for devices with runtime PM enabled" To satisfy that requirement, re-order the calls so that pm_runtime_enable() is the last one. Fixes: 11c0d8fdccc5 ("media: i2c: Add support for the OV8865 image sensor") Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index ce50f3ea87b8..490832cdb831 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2897,8 +2897,8 @@ static int ov8865_probe(struct i2c_client *client) /* Runtime PM */ - pm_runtime_enable(sensor->dev); pm_runtime_set_suspended(sensor->dev); + pm_runtime_enable(sensor->dev); /* V4L2 subdev register */ From 6e1c9bc9ae96e57bcd8807174f2c0f44f9ef7938 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 23 Nov 2021 01:00:02 +0100 Subject: [PATCH 235/397] media: i2c: ov8865: Fix lockdep error ov8865_state_init() calls ov8865_state_mipi_configure() which uses __v4l2_ctrl_s_ctrl[_int64](). This means that sensor->mutex (which is also sensor->ctrls.handler.lock) must be locked before calling ov8865_state_init(). Note ov8865_state_mipi_configure() is also used in other places where the lock is already held so it cannot be changed itself. This fixes the following lockdep kernel WARN: [ 13.233421] WARNING: CPU: 0 PID: 8 at drivers/media/v4l2-core/v4l2-ctrls-api.c:833 __v4l2_ctrl_s_ctrl+0x4d/0x60 [videodev] ... [ 13.234063] Call Trace: [ 13.234074] ov8865_state_configure+0x98b/0xc00 [ov8865] [ 13.234095] ov8865_probe+0x4b1/0x54c [ov8865] [ 13.234117] i2c_device_probe+0x13c/0x2d0 Fixes: 11c0d8fdccc5 ("media: i2c: Add support for the OV8865 image sensor") Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 490832cdb831..fe064e716ea8 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2891,7 +2891,9 @@ static int ov8865_probe(struct i2c_client *client) if (ret) goto error_mutex; + mutex_lock(&sensor->mutex); ret = ov8865_state_init(sensor); + mutex_unlock(&sensor->mutex); if (ret) goto error_ctrls; From dc69bc7a2e09791d8466202a5b10b14400191116 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:03 +0100 Subject: [PATCH 236/397] media: i2c: Add ACPI support to ov8865 The ov8865 sensor is sometimes found on x86 platforms enumerated via ACPI. Add an ACPI match table to the driver so that it's probed on those platforms. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index fe064e716ea8..9f1c0d66c4f9 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -2948,6 +2949,12 @@ static const struct dev_pm_ops ov8865_pm_ops = { SET_RUNTIME_PM_OPS(ov8865_suspend, ov8865_resume, NULL) }; +static const struct acpi_device_id ov8865_acpi_match[] = { + {"INT347A"}, + { } +}; +MODULE_DEVICE_TABLE(acpi, ov8865_acpi_match); + static const struct of_device_id ov8865_of_match[] = { { .compatible = "ovti,ov8865" }, { } @@ -2958,6 +2965,7 @@ static struct i2c_driver ov8865_driver = { .driver = { .name = "ov8865", .of_match_table = ov8865_of_match, + .acpi_match_table = ov8865_acpi_match, .pm = &ov8865_pm_ops, }, .probe_new = ov8865_probe, From 651d1f2040ac46d87c67cfe512bbd7668c34fec6 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:04 +0100 Subject: [PATCH 237/397] media: i2c: Fix incorrect value in comment The PLL configuration defined here sets 72MHz (which is correct), not 80MHz. Correct the comment. Reviewed-by: Paul Kocialkowski Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 9f1c0d66c4f9..a6372a0989e1 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -713,7 +713,7 @@ static const struct ov8865_pll2_config ov8865_pll2_config_native = { /* * EXTCLK = 24 MHz * DAC_CLK = 360 MHz - * SCLK = 80 MHz + * SCLK = 72 MHz */ static const struct ov8865_pll2_config ov8865_pll2_config_binning = { From ba0c8045ea62e4870883570c65d86f1bc06eaa4c Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:05 +0100 Subject: [PATCH 238/397] media: i2c: Defer probe if not endpoint found The ov8865 driver is one of those that can be connected to a CIO2 device by the cio2-bridge code. This means that the absence of an endpoint for this device is not necessarily fatal, as one might be built by the cio2-bridge when it probes. Return -EPROBE_DEFER if no endpoint is found rather than a fatal error. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index a6372a0989e1..68fdb1ce1e94 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2796,10 +2796,8 @@ static int ov8865_probe(struct i2c_client *client) /* Graph Endpoint */ handle = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); - if (!handle) { - dev_err(dev, "unable to find endpoint node\n"); - return -EINVAL; - } + if (!handle) + return -EPROBE_DEFER; sensor->endpoint.bus_type = V4L2_MBUS_CSI2_DPHY; From 73dcffeb2ff98e8181b43e9d9faad042ddcb7f60 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:06 +0100 Subject: [PATCH 239/397] media: i2c: Support 19.2MHz input clock in ov8865 The ov8865 driver as written expects a 24MHz input clock, but the sensor is sometimes found on x86 platforms with a 19.2MHz input clock supplied. Add a set of PLL configurations to the driver to support that rate too. As ACPI doesn't auto-configure the clock rate, check for a clock-frequency during probe and set that rate if one is found. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 195 +++++++++++++++++++++++++++---------- 1 file changed, 143 insertions(+), 52 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 68fdb1ce1e94..e52e43bd7787 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -21,10 +21,6 @@ #include #include -/* Clock rate */ - -#define OV8865_EXTCLK_RATE 24000000 - /* Register definitions */ /* System */ @@ -567,6 +563,25 @@ struct ov8865_sclk_config { unsigned int sclk_div; }; +struct ov8865_pll_configs { + const struct ov8865_pll1_config *pll1_config; + const struct ov8865_pll2_config *pll2_config_native; + const struct ov8865_pll2_config *pll2_config_binning; +}; + +/* Clock rate */ + +enum extclk_rate { + OV8865_19_2_MHZ, + OV8865_24_MHZ, + OV8865_NUM_SUPPORTED_RATES +}; + +static const unsigned long supported_extclk_rates[] = { + [OV8865_19_2_MHZ] = 19200000, + [OV8865_24_MHZ] = 24000000, +}; + /* * General formulas for (array-centered) mode calculation: * - photo_array_width = 3296 @@ -635,9 +650,7 @@ struct ov8865_mode { struct v4l2_fract frame_interval; - const struct ov8865_pll1_config *pll1_config; - const struct ov8865_pll2_config *pll2_config; - const struct ov8865_sclk_config *sclk_config; + bool pll2_binning; const struct ov8865_register_value *register_values; unsigned int register_values_count; @@ -665,6 +678,9 @@ struct ov8865_sensor { struct regulator *avdd; struct regulator *dvdd; struct regulator *dovdd; + + unsigned long extclk_rate; + const struct ov8865_pll_configs *pll_configs; struct clk *extclk; struct v4l2_fwnode_endpoint endpoint; @@ -680,43 +696,70 @@ struct ov8865_sensor { /* Static definitions */ /* - * EXTCLK = 24 MHz * PHY_SCLK = 720 MHz * MIPI_PCLK = 90 MHz */ -static const struct ov8865_pll1_config ov8865_pll1_config_native = { - .pll_pre_div_half = 1, - .pll_pre_div = 0, - .pll_mul = 30, - .m_div = 1, - .mipi_div = 3, - .pclk_div = 1, - .sys_pre_div = 1, - .sys_div = 2, + +static const struct ov8865_pll1_config ov8865_pll1_config_native_19_2mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 2, + .pll_mul = 75, + .m_div = 1, + .mipi_div = 3, + .pclk_div = 1, + .sys_pre_div = 1, + .sys_div = 2, +}; + +static const struct ov8865_pll1_config ov8865_pll1_config_native_24mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 0, + .pll_mul = 30, + .m_div = 1, + .mipi_div = 3, + .pclk_div = 1, + .sys_pre_div = 1, + .sys_div = 2, }; /* - * EXTCLK = 24 MHz * DAC_CLK = 360 MHz * SCLK = 144 MHz */ -static const struct ov8865_pll2_config ov8865_pll2_config_native = { - .pll_pre_div_half = 1, - .pll_pre_div = 0, - .pll_mul = 30, - .dac_div = 2, - .sys_pre_div = 5, - .sys_div = 0, +static const struct ov8865_pll2_config ov8865_pll2_config_native_19_2mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 5, + .pll_mul = 75, + .dac_div = 1, + .sys_pre_div = 1, + .sys_div = 3, +}; + +static const struct ov8865_pll2_config ov8865_pll2_config_native_24mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 0, + .pll_mul = 30, + .dac_div = 2, + .sys_pre_div = 5, + .sys_div = 0, }; /* - * EXTCLK = 24 MHz * DAC_CLK = 360 MHz * SCLK = 72 MHz */ -static const struct ov8865_pll2_config ov8865_pll2_config_binning = { +static const struct ov8865_pll2_config ov8865_pll2_config_binning_19_2mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 2, + .pll_mul = 75, + .dac_div = 2, + .sys_pre_div = 10, + .sys_div = 0, +}; + +static const struct ov8865_pll2_config ov8865_pll2_config_binning_24mhz = { .pll_pre_div_half = 1, .pll_pre_div = 0, .pll_mul = 30, @@ -725,6 +768,23 @@ static const struct ov8865_pll2_config ov8865_pll2_config_binning = { .sys_div = 0, }; +static const struct ov8865_pll_configs ov8865_pll_configs_19_2mhz = { + .pll1_config = &ov8865_pll1_config_native_19_2mhz, + .pll2_config_native = &ov8865_pll2_config_native_19_2mhz, + .pll2_config_binning = &ov8865_pll2_config_binning_19_2mhz, +}; + +static const struct ov8865_pll_configs ov8865_pll_configs_24mhz = { + .pll1_config = &ov8865_pll1_config_native_24mhz, + .pll2_config_native = &ov8865_pll2_config_native_24mhz, + .pll2_config_binning = &ov8865_pll2_config_binning_24mhz, +}; + +static const struct ov8865_pll_configs *ov8865_pll_configs[] = { + &ov8865_pll_configs_19_2mhz, + &ov8865_pll_configs_24mhz, +}; + static const struct ov8865_sclk_config ov8865_sclk_config_native = { .sys_sel = 1, .sclk_sel = 0, @@ -934,9 +994,7 @@ static const struct ov8865_mode ov8865_modes[] = { .frame_interval = { 1, 30 }, /* PLL */ - .pll1_config = &ov8865_pll1_config_native, - .pll2_config = &ov8865_pll2_config_native, - .sclk_config = &ov8865_sclk_config_native, + .pll2_binning = false, /* Registers */ .register_values = ov8865_register_values_native, @@ -990,9 +1048,7 @@ static const struct ov8865_mode ov8865_modes[] = { .frame_interval = { 1, 30 }, /* PLL */ - .pll1_config = &ov8865_pll1_config_native, - .pll2_config = &ov8865_pll2_config_native, - .sclk_config = &ov8865_sclk_config_native, + .pll2_binning = false, /* Registers */ .register_values = ov8865_register_values_native, @@ -1050,9 +1106,7 @@ static const struct ov8865_mode ov8865_modes[] = { .frame_interval = { 1, 30 }, /* PLL */ - .pll1_config = &ov8865_pll1_config_native, - .pll2_config = &ov8865_pll2_config_binning, - .sclk_config = &ov8865_sclk_config_native, + .pll2_binning = true, /* Registers */ .register_values = ov8865_register_values_binning, @@ -1116,9 +1170,7 @@ static const struct ov8865_mode ov8865_modes[] = { .frame_interval = { 1, 90 }, /* PLL */ - .pll1_config = &ov8865_pll1_config_native, - .pll2_config = &ov8865_pll2_config_binning, - .sclk_config = &ov8865_sclk_config_native, + .pll2_binning = true, /* Registers */ .register_values = ov8865_register_values_binning, @@ -1513,12 +1565,11 @@ static int ov8865_isp_configure(struct ov8865_sensor *sensor) static unsigned long ov8865_mode_pll1_rate(struct ov8865_sensor *sensor, const struct ov8865_mode *mode) { - const struct ov8865_pll1_config *config = mode->pll1_config; - unsigned long extclk_rate; + const struct ov8865_pll1_config *config; unsigned long pll1_rate; - extclk_rate = clk_get_rate(sensor->extclk); - pll1_rate = extclk_rate * config->pll_mul / config->pll_pre_div_half; + config = sensor->pll_configs->pll1_config; + pll1_rate = sensor->extclk_rate * config->pll_mul / config->pll_pre_div_half; switch (config->pll_pre_div) { case 0: @@ -1552,10 +1603,12 @@ static int ov8865_mode_pll1_configure(struct ov8865_sensor *sensor, const struct ov8865_mode *mode, u32 mbus_code) { - const struct ov8865_pll1_config *config = mode->pll1_config; + const struct ov8865_pll1_config *config; u8 value; int ret; + config = sensor->pll_configs->pll1_config; + switch (mbus_code) { case MEDIA_BUS_FMT_SBGGR10_1X10: value = OV8865_MIPI_BIT_SEL(10); @@ -1622,9 +1675,12 @@ static int ov8865_mode_pll1_configure(struct ov8865_sensor *sensor, static int ov8865_mode_pll2_configure(struct ov8865_sensor *sensor, const struct ov8865_mode *mode) { - const struct ov8865_pll2_config *config = mode->pll2_config; + const struct ov8865_pll2_config *config; int ret; + config = mode->pll2_binning ? sensor->pll_configs->pll2_config_binning : + sensor->pll_configs->pll2_config_native; + ret = ov8865_write(sensor, OV8865_PLL_CTRL12_REG, OV8865_PLL_CTRL12_PRE_DIV_HALF(config->pll_pre_div_half) | OV8865_PLL_CTRL12_DAC_DIV(config->dac_div)); @@ -1658,7 +1714,7 @@ static int ov8865_mode_pll2_configure(struct ov8865_sensor *sensor, static int ov8865_mode_sclk_configure(struct ov8865_sensor *sensor, const struct ov8865_mode *mode) { - const struct ov8865_sclk_config *config = mode->sclk_config; + const struct ov8865_sclk_config *config = &ov8865_sclk_config_native; int ret; ret = ov8865_write(sensor, OV8865_CLK_SEL0_REG, @@ -2053,9 +2109,11 @@ static int ov8865_mode_configure(struct ov8865_sensor *sensor, static unsigned long ov8865_mode_mipi_clk_rate(struct ov8865_sensor *sensor, const struct ov8865_mode *mode) { - const struct ov8865_pll1_config *config = mode->pll1_config; + const struct ov8865_pll1_config *config; unsigned long pll1_rate; + config = sensor->pll_configs->pll1_config; + pll1_rate = ov8865_mode_pll1_rate(sensor, mode); return pll1_rate / config->m_div / 2; @@ -2783,7 +2841,8 @@ static int ov8865_probe(struct i2c_client *client) struct ov8865_sensor *sensor; struct v4l2_subdev *subdev; struct media_pad *pad; - unsigned long rate; + unsigned int rate = 0; + unsigned int i; int ret; sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); @@ -2852,19 +2911,51 @@ static int ov8865_probe(struct i2c_client *client) /* External Clock */ sensor->extclk = devm_clk_get(dev, NULL); - if (IS_ERR(sensor->extclk)) { + if (PTR_ERR(sensor->extclk) == -ENOENT) { + dev_info(dev, "no external clock found, continuing...\n"); + sensor->extclk = NULL; + } else if (IS_ERR(sensor->extclk)) { dev_err(dev, "failed to get external clock\n"); ret = PTR_ERR(sensor->extclk); goto error_endpoint; } - rate = clk_get_rate(sensor->extclk); - if (rate != OV8865_EXTCLK_RATE) { - dev_err(dev, "clock rate %lu Hz is unsupported\n", rate); + /* + * We could have either a 24MHz or 19.2MHz clock rate from either dt or + * ACPI...but we also need to support the weird IPU3 case which will + * have an external clock AND a clock-frequency property. Check for the + * clock-frequency property and if found, set that rate if we managed + * to acquire a clock. This should cover the ACPI case. If the system + * uses devicetree then the configured rate should already be set, so + * we can just read it. + */ + ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", + &rate); + if (!ret && sensor->extclk) { + ret = clk_set_rate(sensor->extclk, rate); + if (ret) + return dev_err_probe(dev, ret, + "failed to set clock rate\n"); + } else if (ret && !sensor->extclk) { + return dev_err_probe(dev, ret, "invalid clock config\n"); + } + + sensor->extclk_rate = rate ? rate : clk_get_rate(sensor->extclk); + + for (i = 0; i < ARRAY_SIZE(supported_extclk_rates); i++) { + if (sensor->extclk_rate == supported_extclk_rates[i]) + break; + } + + if (i == ARRAY_SIZE(supported_extclk_rates)) { + dev_err(dev, "clock rate %lu Hz is unsupported\n", + sensor->extclk_rate); ret = -EINVAL; goto error_endpoint; } + sensor->pll_configs = ov8865_pll_configs[i]; + /* Subdev, entity and pad */ subdev = &sensor->subdev; From acd25e220921de232b027c677668c93aa6ba5d15 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:07 +0100 Subject: [PATCH 240/397] media: i2c: Add .get_selection() support to ov8865 The ov8865 driver's v4l2_subdev_pad_ops currently does not include .get_selection() - add support for that callback. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index e52e43bd7787..87e34ad9c9a6 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -450,6 +450,15 @@ #define OV8865_PRE_CTRL0_PATTERN_COLOR_SQUARES 2 #define OV8865_PRE_CTRL0_PATTERN_BLACK 3 +/* Pixel Array */ + +#define OV8865_NATIVE_WIDTH 3296 +#define OV8865_NATIVE_HEIGHT 2528 +#define OV8865_ACTIVE_START_TOP 32 +#define OV8865_ACTIVE_START_LEFT 80 +#define OV8865_ACTIVE_WIDTH 3264 +#define OV8865_ACTIVE_HEIGHT 2448 + /* Macros */ #define ov8865_subdev_sensor(s) \ @@ -2756,12 +2765,67 @@ static int ov8865_enum_frame_interval(struct v4l2_subdev *subdev, return 0; } +static void +__ov8865_get_pad_crop(struct ov8865_sensor *sensor, + struct v4l2_subdev_state *state, unsigned int pad, + enum v4l2_subdev_format_whence which, struct v4l2_rect *r) +{ + const struct ov8865_mode *mode = sensor->state.mode; + + switch (which) { + case V4L2_SUBDEV_FORMAT_TRY: + *r = *v4l2_subdev_get_try_crop(&sensor->subdev, state, pad); + break; + case V4L2_SUBDEV_FORMAT_ACTIVE: + r->height = mode->output_size_y; + r->width = mode->output_size_x; + r->top = (OV8865_NATIVE_HEIGHT - mode->output_size_y) / 2; + r->left = (OV8865_NATIVE_WIDTH - mode->output_size_x) / 2; + break; + } +} + +static int ov8865_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev); + + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + mutex_lock(&sensor->mutex); + __ov8865_get_pad_crop(sensor, state, sel->pad, + sel->which, &sel->r); + mutex_unlock(&sensor->mutex); + break; + case V4L2_SEL_TGT_NATIVE_SIZE: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = OV8865_NATIVE_WIDTH; + sel->r.height = OV8865_NATIVE_HEIGHT; + break; + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + sel->r.top = OV8865_ACTIVE_START_TOP; + sel->r.left = OV8865_ACTIVE_START_LEFT; + sel->r.width = OV8865_ACTIVE_WIDTH; + sel->r.height = OV8865_ACTIVE_HEIGHT; + break; + default: + return -EINVAL; + } + + return 0; +} + static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = { .enum_mbus_code = ov8865_enum_mbus_code, .get_fmt = ov8865_get_fmt, .set_fmt = ov8865_set_fmt, .enum_frame_size = ov8865_enum_frame_size, .enum_frame_interval = ov8865_enum_frame_interval, + .get_selection = ov8865_get_selection, + .set_selection = ov8865_get_selection, }; static const struct v4l2_subdev_ops ov8865_subdev_ops = { From d938b2f29be6ad5eb1b04c5bf0e3afa4348e9195 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:08 +0100 Subject: [PATCH 241/397] media: i2c: Switch control to V4L2_CID_ANALOGUE_GAIN The V4L2_CID_GAIN control for this driver configures registers that the datasheet specifies as analogue gain. Switch the control's ID to V4L2_CID_ANALOGUE_GAIN. Reviewed-by: Paul Kocialkowski Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 87e34ad9c9a6..2d5b7b8c2c9e 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2150,7 +2150,7 @@ static int ov8865_exposure_configure(struct ov8865_sensor *sensor, u32 exposure) /* Gain */ -static int ov8865_gain_configure(struct ov8865_sensor *sensor, u32 gain) +static int ov8865_analog_gain_configure(struct ov8865_sensor *sensor, u32 gain) { int ret; @@ -2460,8 +2460,8 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) if (ret) return ret; break; - case V4L2_CID_GAIN: - ret = ov8865_gain_configure(sensor, ctrl->val); + case V4L2_CID_ANALOGUE_GAIN: + ret = ov8865_analog_gain_configure(sensor, ctrl->val); if (ret) return ret; break; @@ -2506,7 +2506,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) /* Gain */ - v4l2_ctrl_new_std(handler, ops, V4L2_CID_GAIN, 128, 8191, 128, 128); + v4l2_ctrl_new_std(handler, ops, V4L2_CID_ANALOGUE_GAIN, 128, 8191, 128, + 128); /* White Balance */ From 9293aafe3745f2a2bb678a14eb589af4e6ee5ffe Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:09 +0100 Subject: [PATCH 242/397] media: i2c: Add vblank control to ov8865 Add a V4L2_CID_VBLANK control to the ov8865 driver. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 2d5b7b8c2c9e..27043b9426a1 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -183,6 +183,8 @@ #define OV8865_VTS_H(v) (((v) & GENMASK(11, 8)) >> 8) #define OV8865_VTS_L_REG 0x380f #define OV8865_VTS_L(v) ((v) & GENMASK(7, 0)) +#define OV8865_TIMING_MAX_VTS 0xffff +#define OV8865_TIMING_MIN_VTS 0x04 #define OV8865_OFFSET_X_H_REG 0x3810 #define OV8865_OFFSET_X_H(v) (((v) & GENMASK(15, 8)) >> 8) #define OV8865_OFFSET_X_L_REG 0x3811 @@ -675,6 +677,7 @@ struct ov8865_state { struct ov8865_ctrls { struct v4l2_ctrl *link_freq; struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *vblank; struct v4l2_ctrl_handler handler; }; @@ -2225,6 +2228,20 @@ static int ov8865_test_pattern_configure(struct ov8865_sensor *sensor, ov8865_test_pattern_bits[index]); } +/* Blanking */ + +static int ov8865_vts_configure(struct ov8865_sensor *sensor, u32 vblank) +{ + u16 vts = sensor->state.mode->output_size_y + vblank; + int ret; + + ret = ov8865_write(sensor, OV8865_VTS_H_REG, OV8865_VTS_H(vts)); + if (ret) + return ret; + + return ov8865_write(sensor, OV8865_VTS_L_REG, OV8865_VTS_L(vts)); +} + /* State */ static int ov8865_state_mipi_configure(struct ov8865_sensor *sensor, @@ -2476,6 +2493,8 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_TEST_PATTERN: index = (unsigned int)ctrl->val; return ov8865_test_pattern_configure(sensor, index); + case V4L2_CID_VBLANK: + return ov8865_vts_configure(sensor, ctrl->val); default: return -EINVAL; } @@ -2492,6 +2511,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) struct ov8865_ctrls *ctrls = &sensor->ctrls; struct v4l2_ctrl_handler *handler = &ctrls->handler; const struct v4l2_ctrl_ops *ops = &ov8865_ctrl_ops; + const struct ov8865_mode *mode = &ov8865_modes[0]; + unsigned int vblank_max, vblank_def; int ret; v4l2_ctrl_handler_init(handler, 32); @@ -2528,6 +2549,13 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) ARRAY_SIZE(ov8865_test_pattern_menu) - 1, 0, 0, ov8865_test_pattern_menu); + /* Blanking */ + vblank_max = OV8865_TIMING_MAX_VTS - mode->output_size_y; + vblank_def = mode->vts - mode->output_size_y; + ctrls->vblank = v4l2_ctrl_new_std(handler, ops, V4L2_CID_VBLANK, + OV8865_TIMING_MIN_VTS, vblank_max, 1, + vblank_def); + /* MIPI CSI-2 */ ctrls->link_freq = @@ -2708,6 +2736,10 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, sensor->state.mbus_code != mbus_code) ret = ov8865_state_configure(sensor, mode, mbus_code); + __v4l2_ctrl_modify_range(sensor->ctrls.vblank, OV8865_TIMING_MIN_VTS, + OV8865_TIMING_MAX_VTS - mode->output_size_y, + 1, mode->vts - mode->output_size_y); + complete: mutex_unlock(&sensor->mutex); From d84d4ceea91e07dfed58fd8e7bb6b29264c195c9 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:10 +0100 Subject: [PATCH 243/397] media: i2c: Add hblank control to ov8865 Add a V4L2_CID_HBLANK control to the ov8865 driver. This is read only with timing control intended to be done via vblanking alone. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 27043b9426a1..f1ee0e425adf 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -677,6 +677,7 @@ struct ov8865_state { struct ov8865_ctrls { struct v4l2_ctrl *link_freq; struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *hblank; struct v4l2_ctrl *vblank; struct v4l2_ctrl_handler handler; @@ -2513,6 +2514,7 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) const struct v4l2_ctrl_ops *ops = &ov8865_ctrl_ops; const struct ov8865_mode *mode = &ov8865_modes[0]; unsigned int vblank_max, vblank_def; + unsigned int hblank; int ret; v4l2_ctrl_handler_init(handler, 32); @@ -2550,6 +2552,13 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) 0, 0, ov8865_test_pattern_menu); /* Blanking */ + hblank = mode->hts - mode->output_size_x; + ctrls->hblank = v4l2_ctrl_new_std(handler, ops, V4L2_CID_HBLANK, hblank, + hblank, 1, hblank); + + if (ctrls->hblank) + ctrls->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + vblank_max = OV8865_TIMING_MAX_VTS - mode->output_size_y; vblank_def = mode->vts - mode->output_size_y; ctrls->vblank = v4l2_ctrl_new_std(handler, ops, V4L2_CID_VBLANK, @@ -2696,6 +2705,7 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, struct v4l2_mbus_framefmt *mbus_format = &format->format; const struct ov8865_mode *mode; u32 mbus_code = 0; + unsigned int hblank; unsigned int index; int ret = 0; @@ -2740,6 +2750,10 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, OV8865_TIMING_MAX_VTS - mode->output_size_y, 1, mode->vts - mode->output_size_y); + hblank = mode->hts - mode->output_size_x; + __v4l2_ctrl_modify_range(sensor->ctrls.hblank, hblank, hblank, 1, + hblank); + complete: mutex_unlock(&sensor->mutex); From 295786e53516ba1792b5ff1deb9dfffff4040255 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:11 +0100 Subject: [PATCH 244/397] media: i2c: Update HTS values in ov8865 The HTS values for some of the modes in the ov8865 driver are a bit unusual, coming in lower than the output_size_x is set to. It seems like they might be calculated to fit the desired framerate into a configuration with just two data lanes. To bring this more in line with expected behaviour, raise the HTS values above the output_size_x. The corollary of that change is that the hardcoded frame intervals against the modes no longer make sense, so remove those entirely. Update the .g/s_frame_interval() callbacks to calculate the frame interval based on the current mode and the vblank and hblank settings. The implementation of the .enum_frame_interval() callback is no longer suitable since the possible frame rate is now a continuous range depending on the vblank control setting, so remove that callback entirely. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 65 +++++++------------------------------- 1 file changed, 11 insertions(+), 54 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index f1ee0e425adf..f4a899e463de 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -659,8 +659,6 @@ struct ov8865_mode { unsigned int blc_anchor_right_start; unsigned int blc_anchor_right_end; - struct v4l2_fract frame_interval; - bool pll2_binning; const struct ov8865_register_value *register_values; @@ -964,7 +962,7 @@ static const struct ov8865_mode ov8865_modes[] = { { /* Horizontal */ .output_size_x = 3264, - .hts = 1944, + .hts = 3888, /* Vertical */ .output_size_y = 2448, @@ -1003,9 +1001,6 @@ static const struct ov8865_mode ov8865_modes[] = { .blc_anchor_right_start = 1984, .blc_anchor_right_end = 2239, - /* Frame Interval */ - .frame_interval = { 1, 30 }, - /* PLL */ .pll2_binning = false, @@ -1018,11 +1013,11 @@ static const struct ov8865_mode ov8865_modes[] = { { /* Horizontal */ .output_size_x = 3264, - .hts = 2582, + .hts = 3888, /* Vertical */ .output_size_y = 1836, - .vts = 2002, + .vts = 2470, .size_auto = true, .size_auto_boundary_x = 8, @@ -1057,9 +1052,6 @@ static const struct ov8865_mode ov8865_modes[] = { .blc_anchor_right_start = 1984, .blc_anchor_right_end = 2239, - /* Frame Interval */ - .frame_interval = { 1, 30 }, - /* PLL */ .pll2_binning = false, @@ -1115,9 +1107,6 @@ static const struct ov8865_mode ov8865_modes[] = { .blc_anchor_right_start = 992, .blc_anchor_right_end = 1119, - /* Frame Interval */ - .frame_interval = { 1, 30 }, - /* PLL */ .pll2_binning = true, @@ -1179,9 +1168,6 @@ static const struct ov8865_mode ov8865_modes[] = { .blc_anchor_right_start = 992, .blc_anchor_right_end = 1119, - /* Frame Interval */ - .frame_interval = { 1, 90 }, - /* PLL */ .pll2_binning = true, @@ -2628,11 +2614,18 @@ static int ov8865_g_frame_interval(struct v4l2_subdev *subdev, { struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev); const struct ov8865_mode *mode; + unsigned int framesize; + unsigned int fps; mutex_lock(&sensor->mutex); mode = sensor->state.mode; - interval->interval = mode->frame_interval; + framesize = mode->hts * (mode->output_size_y + + sensor->ctrls.vblank->val); + fps = DIV_ROUND_CLOSEST(sensor->ctrls.pixel_rate->val, framesize); + + interval->interval.numerator = 1; + interval->interval.denominator = fps; mutex_unlock(&sensor->mutex); @@ -2777,41 +2770,6 @@ static int ov8865_enum_frame_size(struct v4l2_subdev *subdev, return 0; } -static int ov8865_enum_frame_interval(struct v4l2_subdev *subdev, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_interval_enum *interval_enum) -{ - const struct ov8865_mode *mode = NULL; - unsigned int mode_index; - unsigned int interval_index; - - if (interval_enum->index > 0) - return -EINVAL; - /* - * Multiple modes with the same dimensions may have different frame - * intervals, so look up each relevant mode. - */ - for (mode_index = 0, interval_index = 0; - mode_index < ARRAY_SIZE(ov8865_modes); mode_index++) { - mode = &ov8865_modes[mode_index]; - - if (mode->output_size_x == interval_enum->width && - mode->output_size_y == interval_enum->height) { - if (interval_index == interval_enum->index) - break; - - interval_index++; - } - } - - if (mode_index == ARRAY_SIZE(ov8865_modes)) - return -EINVAL; - - interval_enum->interval = mode->frame_interval; - - return 0; -} - static void __ov8865_get_pad_crop(struct ov8865_sensor *sensor, struct v4l2_subdev_state *state, unsigned int pad, @@ -2870,7 +2828,6 @@ static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = { .get_fmt = ov8865_get_fmt, .set_fmt = ov8865_set_fmt, .enum_frame_size = ov8865_enum_frame_size, - .enum_frame_interval = ov8865_enum_frame_interval, .get_selection = ov8865_get_selection, .set_selection = ov8865_get_selection, }; From ca28690ebe19f55fedb8ecb374f10a0d88a7366c Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:12 +0100 Subject: [PATCH 245/397] media: i2c: cap exposure at height + vblank in ov8865 Exposure limits depend on the total height; when vblank is altered (and thus the total height is altered), change the exposure limits to reflect the new cap. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index f4a899e463de..811438c44b58 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -143,6 +143,7 @@ #define OV8865_EXPOSURE_CTRL_L_REG 0x3502 #define OV8865_EXPOSURE_CTRL_L(v) ((v) & GENMASK(7, 0)) #define OV8865_EXPOSURE_GAIN_MANUAL_REG 0x3503 +#define OV8865_INTEGRATION_TIME_MARGIN 8 #define OV8865_GAIN_CTRL_H_REG 0x3508 #define OV8865_GAIN_CTRL_H(v) (((v) & GENMASK(12, 8)) >> 8) @@ -677,6 +678,7 @@ struct ov8865_ctrls { struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *hblank; struct v4l2_ctrl *vblank; + struct v4l2_ctrl *exposure; struct v4l2_ctrl_handler handler; }; @@ -2454,6 +2456,20 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) unsigned int index; int ret; + /* If VBLANK is altered we need to update exposure to compensate */ + if (ctrl->id == V4L2_CID_VBLANK) { + int exposure_max; + + exposure_max = sensor->state.mode->output_size_y + ctrl->val - + OV8865_INTEGRATION_TIME_MARGIN; + __v4l2_ctrl_modify_range(sensor->ctrls.exposure, + sensor->ctrls.exposure->minimum, + exposure_max, + sensor->ctrls.exposure->step, + min(sensor->ctrls.exposure->val, + exposure_max)); + } + /* Wait for the sensor to be on before setting controls. */ if (pm_runtime_suspended(sensor->dev)) return 0; @@ -2510,8 +2526,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) /* Exposure */ - v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 16, 1048575, 16, - 512); + ctrls->exposure = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 16, + 1048575, 16, 512); /* Gain */ @@ -2700,6 +2716,7 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, u32 mbus_code = 0; unsigned int hblank; unsigned int index; + int exposure_max; int ret = 0; mutex_lock(&sensor->mutex); @@ -2747,6 +2764,13 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, __v4l2_ctrl_modify_range(sensor->ctrls.hblank, hblank, hblank, 1, hblank); + exposure_max = mode->vts - OV8865_INTEGRATION_TIME_MARGIN; + __v4l2_ctrl_modify_range(sensor->ctrls.exposure, + sensor->ctrls.exposure->minimum, exposure_max, + sensor->ctrls.exposure->step, + min(sensor->ctrls.exposure->val, + exposure_max)); + complete: mutex_unlock(&sensor->mutex); From 6eecfb34d3c4811686689f3dde657ad62d0b583b Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:13 +0100 Subject: [PATCH 246/397] media: i2c: Add controls from fwnode to ov8865 Add V4L2_CID_CAMERA_ORIENTATION and V4L2_CID_CAMERA_SENSOR_ROTATION controls to the ov8865 driver by attempting to parse them from firmware. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 811438c44b58..45b569f1e7c0 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2515,6 +2515,7 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) struct v4l2_ctrl_handler *handler = &ctrls->handler; const struct v4l2_ctrl_ops *ops = &ov8865_ctrl_ops; const struct ov8865_mode *mode = &ov8865_modes[0]; + struct v4l2_fwnode_device_properties props; unsigned int vblank_max, vblank_def; unsigned int hblank; int ret; @@ -2578,6 +2579,15 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1); + /* set properties from fwnode (e.g. rotation, orientation) */ + ret = v4l2_fwnode_device_parse(sensor->dev, &props); + if (ret) + goto error_ctrls; + + ret = v4l2_ctrl_new_fwnode_properties(handler, ops, &props); + if (ret) + goto error_ctrls; + if (handler->error) { ret = handler->error; goto error_ctrls; From e15ddc9644a11ab51da709f866a2b939ac383a7a Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:14 +0100 Subject: [PATCH 247/397] media: i2c: Switch exposure control unit to lines The ov8865 driver currently has the unit of the V4L2_CID_EXPOSURE control as 1/16th of a line. This is what the sensor expects, but isn't very intuitive. Switch the control to be in units of a line and simply do the 16x multiplication before passing the value to the sensor. The datasheet for this sensor gives minimum exposure as 2 lines, so take the opportunity to correct the lower bounds of the control. Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 45b569f1e7c0..1cc9f78bb97a 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2126,6 +2126,9 @@ static int ov8865_exposure_configure(struct ov8865_sensor *sensor, u32 exposure) { int ret; + /* The sensor stores exposure in units of 1/16th of a line */ + exposure *= 16; + ret = ov8865_write(sensor, OV8865_EXPOSURE_CTRL_HH_REG, OV8865_EXPOSURE_CTRL_HH(exposure)); if (ret) @@ -2527,8 +2530,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) /* Exposure */ - ctrls->exposure = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 16, - 1048575, 16, 512); + ctrls->exposure = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 2, + 65535, 1, 32); /* Gain */ From 91f08141d3aba858278d0c8e61bc8aa84af51cac Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:15 +0100 Subject: [PATCH 248/397] media: i2c: Use dev_err_probe() in ov8865 There is a chance that regulator_get() returns -EPROBE_DEFER, in which case printing an error message is undesirable. To avoid spurious messages in dmesg in the event that -EPROBE_DEFER is returned, use dev_err_probe() on error paths for regulator_get(). Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 46 +++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 1cc9f78bb97a..1aa577dba0a3 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2957,6 +2957,26 @@ static int ov8865_probe(struct i2c_client *client) sensor->dev = dev; sensor->i2c_client = client; + /* Regulators */ + + /* DVDD: digital core */ + sensor->dvdd = devm_regulator_get(dev, "dvdd"); + if (IS_ERR(sensor->dvdd)) + return dev_err_probe(dev, PTR_ERR(sensor->dvdd), + "cannot get DVDD regulator\n"); + + /* DOVDD: digital I/O */ + sensor->dovdd = devm_regulator_get(dev, "dovdd"); + if (IS_ERR(sensor->dovdd)) + return dev_err_probe(dev, PTR_ERR(sensor->dovdd), + "cannot get DOVDD regulator\n"); + + /* AVDD: analog */ + sensor->avdd = devm_regulator_get(dev, "avdd"); + if (IS_ERR(sensor->avdd)) + return dev_err_probe(dev, PTR_ERR(sensor->avdd), + "cannot get AVDD (analog) regulator\n"); + /* Graph Endpoint */ handle = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); @@ -2987,32 +3007,6 @@ static int ov8865_probe(struct i2c_client *client) goto error_endpoint; } - /* Regulators */ - - /* DVDD: digital core */ - sensor->dvdd = devm_regulator_get(dev, "dvdd"); - if (IS_ERR(sensor->dvdd)) { - dev_err(dev, "cannot get DVDD (digital core) regulator\n"); - ret = PTR_ERR(sensor->dvdd); - goto error_endpoint; - } - - /* DOVDD: digital I/O */ - sensor->dovdd = devm_regulator_get(dev, "dovdd"); - if (IS_ERR(sensor->dovdd)) { - dev_err(dev, "cannot get DOVDD (digital I/O) regulator\n"); - ret = PTR_ERR(sensor->dovdd); - goto error_endpoint; - } - - /* AVDD: analog */ - sensor->avdd = devm_regulator_get(dev, "avdd"); - if (IS_ERR(sensor->avdd)) { - dev_err(dev, "cannot get AVDD (analog) regulator\n"); - ret = PTR_ERR(sensor->avdd); - goto error_endpoint; - } - /* External Clock */ sensor->extclk = devm_clk_get(dev, NULL); From 3fdd94e2bfa3a05a9a1ef7c49c7dccb10ebafdfb Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:16 +0100 Subject: [PATCH 249/397] media: i2c: Fix max gain in ov8865 The maximum gain figure in the v4l2 ctrl is wrong. The field is 12 bits wide, which is where the 8191 figure comes from, but the datasheet is specific that maximum gain is 16x (the low seven bits are fractional, so 16x gain is 2048) Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 1aa577dba0a3..ebdb20d3fe9d 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2535,7 +2535,7 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) /* Gain */ - v4l2_ctrl_new_std(handler, ops, V4L2_CID_ANALOGUE_GAIN, 128, 8191, 128, + v4l2_ctrl_new_std(handler, ops, V4L2_CID_ANALOGUE_GAIN, 128, 2048, 128, 128); /* White Balance */ From 46b33f6a0e82d0ea3f5dfac19a2ebefba80741fb Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 23 Nov 2021 01:00:17 +0100 Subject: [PATCH 250/397] media: ipu3-cio2: Add INT347A to cio2-bridge ACPI _HID INT347A represents the OV8865 sensor, the driver for which can support the platforms that the cio2-bridge serves. Add it to the array of supported sensors so the bridge will connect the sensor to the CIO2 device. Reviewed-by: Andy Shevchenko Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index b4b8930d795c..1cbbcbf4e157 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -22,6 +22,8 @@ static const struct cio2_sensor_config cio2_supported_sensors[] = { /* Omnivision OV5693 */ CIO2_SENSOR_CONFIG("INT33BE", 1, 419200000), + /* Omnivision OV8865 */ + CIO2_SENSOR_CONFIG("INT347A", 1, 360000000), /* Omnivision OV2680 */ CIO2_SENSOR_CONFIG("OVTI2680", 0), }; From 57de5bb2bd2104d518227b9203e6fccbb1e63ad4 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Tue, 23 Nov 2021 12:15:20 +0100 Subject: [PATCH 251/397] media: i2c: imx274: simplify probe function by adding local variable dev Simplify probe function by adding a local variable dev instead of using &client->dev all the time. Signed-off-by: Eugen Hristev Reviewed-by: Luca Ceresoli Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/imx274.c | 39 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 25a4ef8f6187..e31f006b10d9 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -1961,23 +1961,23 @@ static int imx274_probe(struct i2c_client *client) { struct v4l2_subdev *sd; struct stimx274 *imx274; + struct device *dev = &client->dev; int ret; /* initialize imx274 */ - imx274 = devm_kzalloc(&client->dev, sizeof(*imx274), GFP_KERNEL); + imx274 = devm_kzalloc(dev, sizeof(*imx274), GFP_KERNEL); if (!imx274) return -ENOMEM; mutex_init(&imx274->lock); - imx274->inck = devm_clk_get_optional(&client->dev, "inck"); + imx274->inck = devm_clk_get_optional(dev, "inck"); if (IS_ERR(imx274->inck)) return PTR_ERR(imx274->inck); - ret = imx274_regulators_get(&client->dev, imx274); + ret = imx274_regulators_get(dev, imx274); if (ret) { - dev_err(&client->dev, - "Failed to get power regulators, err: %d\n", ret); + dev_err(dev, "Failed to get power regulators, err: %d\n", ret); return ret; } @@ -1996,7 +1996,7 @@ static int imx274_probe(struct i2c_client *client) /* initialize regmap */ imx274->regmap = devm_regmap_init_i2c(client, &imx274_regmap_config); if (IS_ERR(imx274->regmap)) { - dev_err(&client->dev, + dev_err(dev, "regmap init failed: %ld\n", PTR_ERR(imx274->regmap)); ret = -ENODEV; goto err_regmap; @@ -2013,34 +2013,32 @@ static int imx274_probe(struct i2c_client *client) sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; ret = media_entity_pads_init(&sd->entity, 1, &imx274->pad); if (ret < 0) { - dev_err(&client->dev, + dev_err(dev, "%s : media entity init Failed %d\n", __func__, ret); goto err_regmap; } /* initialize sensor reset gpio */ - imx274->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + imx274->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(imx274->reset_gpio)) { if (PTR_ERR(imx274->reset_gpio) != -EPROBE_DEFER) - dev_err(&client->dev, "Reset GPIO not setup in DT"); + dev_err(dev, "Reset GPIO not setup in DT"); ret = PTR_ERR(imx274->reset_gpio); goto err_me; } /* power on the sensor */ - ret = imx274_power_on(&client->dev); + ret = imx274_power_on(dev); if (ret < 0) { - dev_err(&client->dev, - "%s : imx274 power on failed\n", __func__); + dev_err(dev, "%s : imx274 power on failed\n", __func__); goto err_me; } /* initialize controls */ ret = v4l2_ctrl_handler_init(&imx274->ctrls.handler, 4); if (ret < 0) { - dev_err(&client->dev, - "%s : ctrl handler init Failed\n", __func__); + dev_err(dev, "%s : ctrl handler init Failed\n", __func__); goto err_power_off; } @@ -2083,23 +2081,22 @@ static int imx274_probe(struct i2c_client *client) /* register subdevice */ ret = v4l2_async_register_subdev(sd); if (ret < 0) { - dev_err(&client->dev, - "%s : v4l2_async_register_subdev failed %d\n", + dev_err(dev, "%s : v4l2_async_register_subdev failed %d\n", __func__, ret); goto err_ctrls; } - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); - dev_info(&client->dev, "imx274 : imx274 probe success !\n"); + dev_info(dev, "imx274 : imx274 probe success !\n"); return 0; err_ctrls: v4l2_ctrl_handler_free(&imx274->ctrls.handler); err_power_off: - imx274_power_off(&client->dev); + imx274_power_off(dev); err_me: media_entity_cleanup(&sd->entity); err_regmap: From 0abb8f9052ef1b143e78cfe6349a18ffec35e499 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Tue, 23 Nov 2021 13:04:21 +0100 Subject: [PATCH 252/397] media: i2c: imx274: implement fwnode parsing Implement fwnode parsing at probe time. Check if the bus and number of lanes are supported. Signed-off-by: Eugen Hristev Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/imx274.c | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index e31f006b10d9..2aa15b9c23cc 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -27,6 +27,7 @@ #include #include +#include #include /* @@ -1957,6 +1958,41 @@ static const struct i2c_device_id imx274_id[] = { }; MODULE_DEVICE_TABLE(i2c, imx274_id); +static int imx274_fwnode_parse(struct device *dev) +{ + struct fwnode_handle *endpoint; + /* Only CSI2 is supported */ + struct v4l2_fwnode_endpoint ep = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + int ret; + + endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); + if (!endpoint) { + dev_err(dev, "Endpoint node not found\n"); + return -EINVAL; + } + + ret = v4l2_fwnode_endpoint_parse(endpoint, &ep); + fwnode_handle_put(endpoint); + if (ret == -ENXIO) { + dev_err(dev, "Unsupported bus type, should be CSI2\n"); + return ret; + } else if (ret) { + dev_err(dev, "Parsing endpoint node failed %d\n", ret); + return ret; + } + + /* Check number of data lanes, only 4 lanes supported */ + if (ep.bus.mipi_csi2.num_data_lanes != 4) { + dev_err(dev, "Invalid data lanes: %d\n", + ep.bus.mipi_csi2.num_data_lanes); + return -EINVAL; + } + + return 0; +} + static int imx274_probe(struct i2c_client *client) { struct v4l2_subdev *sd; @@ -1971,6 +2007,10 @@ static int imx274_probe(struct i2c_client *client) mutex_init(&imx274->lock); + ret = imx274_fwnode_parse(dev); + if (ret) + return ret; + imx274->inck = devm_clk_get_optional(dev, "inck"); if (IS_ERR(imx274->inck)) return PTR_ERR(imx274->inck); From 4ce875a80319653e5dc52960b29d49369180206d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 14 Jul 2021 13:17:12 +0200 Subject: [PATCH 253/397] media: dt-bindings: media: renesas,jpu: Convert to json-schema Convert the Renesas JPEG Processing Unit Device Tree binding documentation to json-schema. Document missing properties. Update the example to match reality. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Reviewed-by: Mikhail Ulyanov Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/renesas,jpu.txt | 25 ------- .../bindings/media/renesas,jpu.yaml | 65 +++++++++++++++++++ 2 files changed, 65 insertions(+), 25 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/renesas,jpu.txt create mode 100644 Documentation/devicetree/bindings/media/renesas,jpu.yaml diff --git a/Documentation/devicetree/bindings/media/renesas,jpu.txt b/Documentation/devicetree/bindings/media/renesas,jpu.txt deleted file mode 100644 index d3436e5190f9..000000000000 --- a/Documentation/devicetree/bindings/media/renesas,jpu.txt +++ /dev/null @@ -1,25 +0,0 @@ -* Renesas JPEG Processing Unit - -The JPEG processing unit (JPU) incorporates the JPEG codec with an encoding -and decoding function conforming to the JPEG baseline process, so that the JPU -can encode image data and decode JPEG data quickly. - -Required properties: -- compatible: "renesas,jpu-", "renesas,rcar-gen2-jpu" as fallback. - Examples with soctypes are: - - "renesas,jpu-r8a7790" for R-Car H2 - - "renesas,jpu-r8a7791" for R-Car M2-W - - "renesas,jpu-r8a7792" for R-Car V2H - - "renesas,jpu-r8a7793" for R-Car M2-N - - - reg: Base address and length of the registers block for the JPU. - - interrupts: JPU interrupt specifier. - - clocks: A phandle + clock-specifier pair for the JPU functional clock. - -Example: R8A7790 (R-Car H2) JPU node - jpeg-codec@fe980000 { - compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu"; - reg = <0 0xfe980000 0 0x10300>; - interrupts = <0 272 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp1_clks R8A7790_CLK_JPU>; - }; diff --git a/Documentation/devicetree/bindings/media/renesas,jpu.yaml b/Documentation/devicetree/bindings/media/renesas,jpu.yaml new file mode 100644 index 000000000000..2f55968e864f --- /dev/null +++ b/Documentation/devicetree/bindings/media/renesas,jpu.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/renesas,jpu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas JPEG Processing Unit + +maintainers: + - Mikhail Ulyanov + +description: + The JPEG processing unit (JPU) incorporates the JPEG codec with an encoding + and decoding function conforming to the JPEG baseline process, so that the + JPU can encode image data and decode JPEG data quickly. + +properties: + compatible: + items: + - enum: + - renesas,jpu-r8a7790 # R-Car H2 + - renesas,jpu-r8a7791 # R-Car M2-W + - renesas,jpu-r8a7792 # R-Car V2H + - renesas,jpu-r8a7793 # R-Car M2-N + - const: renesas,rcar-gen2-jpu # R-Car Gen2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - power-domains + - resets + +additionalProperties: false + +examples: + - | + #include + #include + #include + + jpeg-codec@fe980000 { + compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu"; + reg = <0xfe980000 0x10300>; + interrupts = ; + clocks = <&cpg CPG_MOD 106>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 106>; + }; From cee44d4fbacbbdfe62697ec94e76c6e4f726c5df Mon Sep 17 00:00:00 2001 From: Suresh Udipi Date: Fri, 13 Aug 2021 17:07:54 +0200 Subject: [PATCH 254/397] media: rcar-csi2: Correct the selection of hsfreqrange MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hsfreqrange should be chosen based on the calculated mbps which is closer to the default bit rate and within the range as per table[1]. But current calculation always selects first value which is greater than or equal to the calculated mbps which may lead to chosing a wrong range in some cases. For example for 360 mbps for H3/M3N Existing logic selects Calculated value 360Mbps : Default 400Mbps Range [368.125 -433.125 mbps] This hsfreqrange is out of range. The logic is changed to get the default value which is closest to the calculated value [1] Calculated value 360Mbps : Default 350Mbps Range [320.625 -380.625 mpbs] [1] specs r19uh0105ej0200-r-car-3rd-generation.pdf [Table 25.9] Please note that According to Renesas in Table 25.9 the range for 220 default value is corrected as below |Range (Mbps) | Default Bit rate (Mbps) | ----------------------------------------------- | 197.125-244.125 | 220 | ----------------------------------------------- Fixes: 769afd212b16 ("media: rcar-csi2: add Renesas R-Car MIPI CSI-2 receiver driver") Signed-off-by: Suresh Udipi Signed-off-by: Kazuyoshi Akiyama Signed-off-by: Michael Rodin Reviewed-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-csi2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 11848d0c4a55..436b7be96920 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -542,16 +542,23 @@ static int rcsi2_wait_phy_start(struct rcar_csi2 *priv, static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps) { const struct rcsi2_mbps_reg *hsfreq; + const struct rcsi2_mbps_reg *hsfreq_prev = NULL; - for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++) + for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++) { if (hsfreq->mbps >= mbps) break; + hsfreq_prev = hsfreq; + } if (!hsfreq->mbps) { dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps); return -ERANGE; } + if (hsfreq_prev && + ((mbps - hsfreq_prev->mbps) <= (hsfreq->mbps - mbps))) + hsfreq = hsfreq_prev; + rcsi2_write(priv, PHYPLL_REG, PHYPLL_HSFREQRANGE(hsfreq->reg)); return 0; From ebeefe26859ec58c2a8bbb83896f26ebc389a29f Mon Sep 17 00:00:00 2001 From: Suresh Udipi Date: Fri, 13 Aug 2021 17:07:55 +0200 Subject: [PATCH 255/397] media: rcar-csi2: Add warning for PHY speed less than minimum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a warning message when the selected PHY speed is less than supported minimum PHY speed given in the hsfreq table[1]. For raspberry pi camera capture on Kingfisher board with resolution 640x480, the calculated PHY speed is 48 mbps which is less than the minimum PHY speed 80 Mbps from the table[1]. But in this cases capture is successful. [1] specs r19uh0105ej0200-r-car-3rd-generation.pdf [Table 25.9] Signed-off-by: Suresh Udipi Signed-off-by: Michael Rodin Reviewed-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-csi2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 436b7be96920..db119a002414 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -544,6 +544,10 @@ static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps) const struct rcsi2_mbps_reg *hsfreq; const struct rcsi2_mbps_reg *hsfreq_prev = NULL; + if (mbps < priv->info->hsfreqrange->mbps) + dev_warn(priv->dev, "%u Mbps less than min PHY speed %u Mbps", + mbps, priv->info->hsfreqrange->mbps); + for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++) { if (hsfreq->mbps >= mbps) break; From 549cc89cd09a85aaa16dc07ef3db811d5cf9bcb1 Mon Sep 17 00:00:00 2001 From: Suresh Udipi Date: Fri, 13 Aug 2021 17:07:56 +0200 Subject: [PATCH 256/397] media: rcar-csi2: Optimize the selection PHTW register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHTW register is selected based on default bit rate from Table[1]. for the bit rates less than or equal to 250. Currently first value of default bit rate which is greater than or equal to the caculated mbps is selected. This selection can be further improved by selecting the default bit rate which is nearest to the calculated value. [1] specs r19uh0105ej0200-r-car-3rd-generation.pdf [Table 25.12] Fixes: 769afd212b16 ("media: rcar-csi2: add Renesas R-Car MIPI CSI-2 receiver driver") Signed-off-by: Suresh Udipi Signed-off-by: Michael Rodin Reviewed-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-csi2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index db119a002414..e2c4ab69a477 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -1108,10 +1108,17 @@ static int rcsi2_phtw_write_mbps(struct rcar_csi2 *priv, unsigned int mbps, const struct rcsi2_mbps_reg *values, u16 code) { const struct rcsi2_mbps_reg *value; + const struct rcsi2_mbps_reg *prev_value = NULL; - for (value = values; value->mbps; value++) + for (value = values; value->mbps; value++) { if (value->mbps >= mbps) break; + prev_value = value; + } + + if (prev_value && + ((mbps - prev_value->mbps) <= (value->mbps - mbps))) + value = prev_value; if (!value->mbps) { dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps); From ed2f97ad4b21072f849cf4ae6645d1f2b1d3f550 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 8 Oct 2021 15:10:14 +0200 Subject: [PATCH 257/397] media: imx-pxp: Initialize the spinlock prior to using it After devm_request_threaded_irq() is called there is a chance that an interrupt may occur before the spinlock is initialized, which will trigger a kernel oops. To prevent that, move the initialization of the spinlock prior to requesting the interrupts. Fixes: 51abcf7fdb70 ("media: imx-pxp: add i.MX Pixel Pipeline driver") Signed-off-by: Fabio Estevam Reviewed-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/imx-pxp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/imx-pxp.c b/drivers/media/platform/imx-pxp.c index 723b096fedd1..b7174778db53 100644 --- a/drivers/media/platform/imx-pxp.c +++ b/drivers/media/platform/imx-pxp.c @@ -1659,6 +1659,8 @@ static int pxp_probe(struct platform_device *pdev) if (irq < 0) return irq; + spin_lock_init(&dev->irqlock); + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, pxp_irq_handler, IRQF_ONESHOT, dev_name(&pdev->dev), dev); if (ret < 0) { @@ -1676,8 +1678,6 @@ static int pxp_probe(struct platform_device *pdev) goto err_clk; } - spin_lock_init(&dev->irqlock); - ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) goto err_clk; From 8197b071915a5229c9359b1a232936109d27dc1f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 8 Oct 2021 15:10:15 +0200 Subject: [PATCH 258/397] media: imx-pxp: Add rotation support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PXP allows clockwise rotation of 0°, 90°, 180° and 270°. Add support for it. Tested on a imx6ull-evk. For example, to rotate 90° the following Gstreamer pipeline can be used: gst-launch-1.0 videotestsrc ! video/x-raw,width=640,height=480 ! \ v4l2convert extra-controls=cid,rotate=90 ! \ video/x-raw,width=120,height=160 ! fbdevsink Signed-off-by: Fabio Estevam Reviewed-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/imx-pxp.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/imx-pxp.c b/drivers/media/platform/imx-pxp.c index b7174778db53..689ae5e6ac62 100644 --- a/drivers/media/platform/imx-pxp.c +++ b/drivers/media/platform/imx-pxp.c @@ -211,6 +211,7 @@ struct pxp_ctx { /* Processing mode */ int mode; u8 alpha_component; + u8 rotation; enum v4l2_colorspace colorspace; enum v4l2_xfer_func xfer_func; @@ -767,14 +768,20 @@ static int pxp_start(struct pxp_ctx *ctx, struct vb2_v4l2_buffer *in_vb, V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_TSTAMP_SRC_MASK); - /* Rotation disabled, 8x8 block size */ + /* 8x8 block size */ ctrl = BF_PXP_CTRL_VFLIP0(!!(ctx->mode & MEM2MEM_VFLIP)) | - BF_PXP_CTRL_HFLIP0(!!(ctx->mode & MEM2MEM_HFLIP)); + BF_PXP_CTRL_HFLIP0(!!(ctx->mode & MEM2MEM_HFLIP)) | + BF_PXP_CTRL_ROTATE0(ctx->rotation); /* Always write alpha value as V4L2_CID_ALPHA_COMPONENT */ out_ctrl = BF_PXP_OUT_CTRL_ALPHA(ctx->alpha_component) | BF_PXP_OUT_CTRL_ALPHA_OUTPUT(1) | pxp_v4l2_pix_fmt_to_out_format(dst_fourcc); out_buf = p_out; + + if (ctx->rotation == BV_PXP_CTRL_ROTATE0__ROT_90 || + ctx->rotation == BV_PXP_CTRL_ROTATE0__ROT_270) + swap(dst_width, dst_height); + switch (dst_fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: @@ -1297,6 +1304,21 @@ static int pxp_s_fmt_vid_out(struct file *file, void *priv, return 0; } +static u8 pxp_degrees_to_rot_mode(u32 degrees) +{ + switch (degrees) { + case 90: + return BV_PXP_CTRL_ROTATE0__ROT_90; + case 180: + return BV_PXP_CTRL_ROTATE0__ROT_180; + case 270: + return BV_PXP_CTRL_ROTATE0__ROT_270; + case 0: + default: + return BV_PXP_CTRL_ROTATE0__ROT_0; + } +} + static int pxp_s_ctrl(struct v4l2_ctrl *ctrl) { struct pxp_ctx *ctx = @@ -1317,6 +1339,10 @@ static int pxp_s_ctrl(struct v4l2_ctrl *ctrl) ctx->mode &= ~MEM2MEM_VFLIP; break; + case V4L2_CID_ROTATE: + ctx->rotation = pxp_degrees_to_rot_mode(ctrl->val); + break; + case V4L2_CID_ALPHA_COMPONENT: ctx->alpha_component = ctrl->val; break; @@ -1524,6 +1550,7 @@ static int pxp_open(struct file *file) v4l2_ctrl_handler_init(hdl, 4); v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0); v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255); if (hdl->error) { From 61b20ddec90075b0fd33394e0425fd01e627a0a9 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Tue, 12 Oct 2021 23:47:03 +0200 Subject: [PATCH 259/397] media: imx: Constify static struct v4l2_m2m_ops The only usage of m2m_ops is to pass its address to v4l2_m2m_init(), which takes a pointer to const v4l2_m2m_ops as argument. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn Reviewed-by: Philipp Zabel Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-csc-scaler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx-media-csc-scaler.c b/drivers/staging/media/imx/imx-media-csc-scaler.c index eb6da9b9d8ba..1fd39a2fca98 100644 --- a/drivers/staging/media/imx/imx-media-csc-scaler.c +++ b/drivers/staging/media/imx/imx-media-csc-scaler.c @@ -820,7 +820,7 @@ static const struct v4l2_file_operations ipu_csc_scaler_fops = { .mmap = v4l2_m2m_fop_mmap, }; -static struct v4l2_m2m_ops m2m_ops = { +static const struct v4l2_m2m_ops m2m_ops = { .device_run = device_run, .job_abort = job_abort, }; From 30162960165fe608f505d2564a9abc8514ffb7df Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Wed, 13 Oct 2021 00:11:44 +0200 Subject: [PATCH 260/397] media: staging: media: rkvdec: Constify static struct v4l2_m2m_ops The only usage of rkvdec_m2m_ops is to pass its address to v4l2_m2m_init(), which takes a pointer to const v4l2_m2m_ops as argument. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn Reviewed-by: Ezequiel Garcia Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/rkvdec/rkvdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c index ad2624c30843..c0cf3488f970 100644 --- a/drivers/staging/media/rkvdec/rkvdec.c +++ b/drivers/staging/media/rkvdec/rkvdec.c @@ -712,7 +712,7 @@ static void rkvdec_device_run(void *priv) rkvdec_job_finish(ctx, VB2_BUF_STATE_ERROR); } -static struct v4l2_m2m_ops rkvdec_m2m_ops = { +static const struct v4l2_m2m_ops rkvdec_m2m_ops = { .device_run = rkvdec_device_run, }; From ef054e345ed8c79ce1121a3599b5a2dfd78e57a0 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 15 Oct 2021 11:58:55 +0200 Subject: [PATCH 261/397] media: si470x-i2c: fix possible memory leak in si470x_i2c_probe() n the 'radio->hdl.error' error handling, ctrl handler allocated by v4l2_ctrl_new_std() does not released, and caused memory leak as follows: unreferenced object 0xffff888033d54200 (size 256): comm "i2c-si470x-19", pid 909, jiffies 4294914203 (age 8.072s) hex dump (first 32 bytes): e8 69 11 03 80 88 ff ff 00 46 d5 33 80 88 ff ff .i.......F.3.... 10 42 d5 33 80 88 ff ff 10 42 d5 33 80 88 ff ff .B.3.....B.3.... backtrace: [<00000000086bd4ed>] __kmalloc_node+0x1eb/0x360 [<00000000bdb68871>] kvmalloc_node+0x66/0x120 [<00000000fac74e4c>] v4l2_ctrl_new+0x7b9/0x1c60 [videodev] [<00000000693bf940>] v4l2_ctrl_new_std+0x19b/0x270 [videodev] [<00000000c0cb91bc>] si470x_i2c_probe+0x2d3/0x9a0 [radio_si470x_i2c] [<0000000056a6f01f>] i2c_device_probe+0x4d8/0xbe0 Fix the error handling path to avoid memory leak. Reported-by: Hulk Robot Fixes: 8c081b6f9a9b ("media: radio: Critical v4l2 registration...") Signed-off-by: Yang Yingliang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x-i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index bdb13c974b02..59b3d77e282d 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -367,7 +367,7 @@ static int si470x_i2c_probe(struct i2c_client *client) if (radio->hdl.error) { retval = radio->hdl.error; dev_err(&client->dev, "couldn't register control\n"); - goto err_dev; + goto err_all; } /* video device initialization */ @@ -452,7 +452,6 @@ static int si470x_i2c_probe(struct i2c_client *client) return 0; err_all: v4l2_ctrl_handler_free(&radio->hdl); -err_dev: v4l2_device_unregister(&radio->v4l2_dev); err_initial: return retval; From 4cfe98e647b1be8ac9ff06562959cf833b43e608 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Mon, 18 Oct 2021 11:14:27 +0200 Subject: [PATCH 262/397] media: docs: dev-decoder: add restrictions about CAPTURE buffers CAPTURE buffers might be read by the hardware after they are dequeued, which goes against the general idea that userspace has full control over dequeued buffers. Explain why and document the restrictions that this implies for userspace. Signed-off-by: Alexandre Courbot Acked-by: Tomasz Figa Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../userspace-api/media/v4l/dev-decoder.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/dev-decoder.rst b/Documentation/userspace-api/media/v4l/dev-decoder.rst index 5b9b83feeceb..3cf2b496f2d0 100644 --- a/Documentation/userspace-api/media/v4l/dev-decoder.rst +++ b/Documentation/userspace-api/media/v4l/dev-decoder.rst @@ -752,6 +752,23 @@ available to dequeue. Specifically: buffers are out-of-order compared to the ``OUTPUT`` buffers): ``CAPTURE`` timestamps will not retain the order of ``OUTPUT`` timestamps. +.. note:: + + The backing memory of ``CAPTURE`` buffers that are used as reference frames + by the stream may be read by the hardware even after they are dequeued. + Consequently, the client should avoid writing into this memory while the + ``CAPTURE`` queue is streaming. Failure to observe this may result in + corruption of decoded frames. + + Similarly, when using a memory type other than ``V4L2_MEMORY_MMAP``, the + client should make sure that each ``CAPTURE`` buffer is always queued with + the same backing memory for as long as the ``CAPTURE`` queue is streaming. + The reason for this is that V4L2 buffer indices can be used by drivers to + identify frames. Thus, if the backing memory of a reference frame is + submitted under a different buffer ID, the driver may misidentify it and + decode a new frame into it while it is still in use, resulting in corruption + of the following frames. + During the decoding, the decoder may initiate one of the special sequences, as listed below. The sequences will result in the decoder returning all the ``CAPTURE`` buffers that originated from all the ``OUTPUT`` buffers processed From 9175fb663af3df20a1bab5b5ac4b87b4460dddae Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 18 Oct 2021 23:13:53 +0200 Subject: [PATCH 263/397] media: MAINTAINERS: Update email of Andrzej Hajda MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beside updating email, the patch updates maintainers of Samsung drivers. Signed-off-by: Andrzej Hajda Acked-by: Marek Szyprowski Acked-by: Łukasz Stelmach Acked-by: Neil Armstrong Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .mailmap | 1 + MAINTAINERS | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.mailmap b/.mailmap index 14314e3c5d5e..f4051a214c38 100644 --- a/.mailmap +++ b/.mailmap @@ -42,6 +42,7 @@ Andrew Vasquez Andrey Konovalov Andrey Ryabinin Andrey Ryabinin +Andrzej Hajda Andy Adamson Antoine Tenart Antoine Tenart diff --git a/MAINTAINERS b/MAINTAINERS index c869091df7f9..24a64ca49237 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2569,7 +2569,7 @@ N: s3c64xx N: s5pv210 ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT -M: Andrzej Hajda +M: Łukasz Stelmach L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-media@vger.kernel.org S: Maintained @@ -2593,7 +2593,8 @@ S: Maintained F: drivers/media/platform/s5p-jpeg/ ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT -M: Andrzej Hajda +M: Marek Szyprowski +M: Andrzej Hajda L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-media@vger.kernel.org S: Maintained @@ -6300,7 +6301,7 @@ F: Documentation/devicetree/bindings/display/atmel/ F: drivers/gpu/drm/atmel-hlcdc/ DRM DRIVERS FOR BRIDGE CHIPS -M: Andrzej Hajda +M: Andrzej Hajda M: Neil Armstrong M: Robert Foss R: Laurent Pinchart @@ -16824,13 +16825,15 @@ F: Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml F: drivers/nfc/s3fwrn5 SAMSUNG S5C73M3 CAMERA DRIVER -M: Andrzej Hajda +M: Sylwester Nawrocki +M: Andrzej Hajda L: linux-media@vger.kernel.org S: Supported F: drivers/media/i2c/s5c73m3/* SAMSUNG S5K5BAF CAMERA DRIVER -M: Andrzej Hajda +M: Sylwester Nawrocki +M: Andrzej Hajda L: linux-media@vger.kernel.org S: Supported F: drivers/media/i2c/s5k5baf.c From fb394f3fc8c32564d15e48f29e89b736b68441cd Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Tue, 19 Oct 2021 05:00:29 +0200 Subject: [PATCH 264/397] media: driver: hva: add pm_runtime_disable in the error handling code of hva_hw_probe In the error handling code of hva_hw_probe, it fails to invoke pm_runtime_disable in many error sites. Fix this by adding a label err_disable with pm_runtime_disable and adjust one goto from label err_clk to err_disable. Signed-off-by: Dongliang Mu Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sti/hva/hva-hw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/sti/hva/hva-hw.c b/drivers/media/platform/sti/hva/hva-hw.c index 15e8f83b1b56..fe4ea2e7f37e 100644 --- a/drivers/media/platform/sti/hva/hva-hw.c +++ b/drivers/media/platform/sti/hva/hva-hw.c @@ -385,7 +385,7 @@ int hva_hw_probe(struct platform_device *pdev, struct hva_dev *hva) ret = pm_runtime_resume_and_get(dev); if (ret < 0) { dev_err(dev, "%s failed to set PM\n", HVA_PREFIX); - goto err_clk; + goto err_disable; } /* check IP hardware version */ @@ -403,6 +403,8 @@ int hva_hw_probe(struct platform_device *pdev, struct hva_dev *hva) err_pm: pm_runtime_put(dev); +err_disable: + pm_runtime_disable(dev); err_clk: if (hva->clk) clk_unprepare(hva->clk); From 0529c0f55da87a338a07f3394f55c4873a937be6 Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Tue, 19 Oct 2021 05:08:08 +0200 Subject: [PATCH 265/397] media: driver: bdisp: add pm_runtime_disable in the error handling code In the error handling code of bdisp_probe, it fails to invoke pm_runtime_disable in many error sites. Fix this by adding pm_runtime_disable at the label err_remove. Signed-off-by: Dongliang Mu Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sti/bdisp/bdisp-v4l2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c index 7d467f2ba072..01ce7b711774 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c @@ -1394,6 +1394,7 @@ err_filter: err_pm: pm_runtime_put(dev); err_remove: + pm_runtime_disable(dev); bdisp_debugfs_remove(bdisp); v4l2_device_unregister(&bdisp->v4l2_dev); err_clk: From d5e9bddb28057615fed653dcfa25f96896b1ff04 Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Tue, 19 Oct 2021 05:39:52 +0200 Subject: [PATCH 266/397] media: driver: s3c_camif: move s3c_camif_unregister_subdev out of camif_unregister_media_entities In the error handling of s3c_camif_probe, s3c_camif_unregister_subdev may be executed twice, one is from camif_unregister_media_entities. Although there is sanity check about the registration status, it is not good to call s3c_camif_unregister_subdev twice in the error handling code. Fix this by moving s3c_camif_unregister_subdev out of camif_unregister_media_entities, and add a s3c_camif_unregister_subdev in the s3c_camif_remove. Signed-off-by: Dongliang Mu Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s3c-camif/camif-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index 32892ab359ee..6e8ef86566b7 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c @@ -291,7 +291,6 @@ static void camif_unregister_media_entities(struct camif_dev *camif) { camif_unregister_video_nodes(camif); camif_unregister_sensor(camif); - s3c_camif_unregister_subdev(camif); } /* @@ -520,6 +519,7 @@ static int s3c_camif_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); camif_clk_put(camif); + s3c_camif_unregister_subdev(camif); pdata->gpio_put(); return 0; From af88c2adbb72a09ab1bb5c37ba388c98fecca69b Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Thu, 21 Oct 2021 05:09:38 +0200 Subject: [PATCH 267/397] media: rcar_fdp1: Fix the correct variable assignments In the function fdp1_probe(), when get irq failed, the function platform_get_irq() log an error message, so remove redundant message here. And the variable type of "ret" is int, the "fdp1->irq" is unsigned int, when irq failed, this place maybe wrong, thus fix it. Signed-off-by: Tang Bin Reviewed-by: Geert Uytterhoeven Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar_fdp1.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/rcar_fdp1.c b/drivers/media/platform/rcar_fdp1.c index 19de3c19bcca..37ecf489d112 100644 --- a/drivers/media/platform/rcar_fdp1.c +++ b/drivers/media/platform/rcar_fdp1.c @@ -2287,11 +2287,10 @@ static int fdp1_probe(struct platform_device *pdev) return PTR_ERR(fdp1->regs); /* Interrupt service routine registration */ - fdp1->irq = ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, "cannot find IRQ\n"); + ret = platform_get_irq(pdev, 0); + if (ret < 0) return ret; - } + fdp1->irq = ret; ret = devm_request_irq(&pdev->dev, fdp1->irq, fdp1_irq_handler, 0, dev_name(&pdev->dev), fdp1); From fadecf79cf8ef9bd3b8dcd0a82455b2c94c4d5c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 21 Oct 2021 08:25:47 +0200 Subject: [PATCH 268/397] media: s5c73m3: Drop empty spi_driver remove callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A driver with a remove callback that just returns 0 behaves identically to a driver with no remove callback at all. So simplify accordingly. Signed-off-by: Uwe Kleine-König Reviewed-by: Kieran Bingham Reviewed-by: Andrzej Hajda Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-spi.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c index c102c6bbc118..7fe61187a2f8 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c @@ -130,16 +130,10 @@ static int s5c73m3_spi_probe(struct spi_device *spi) return 0; } -static int s5c73m3_spi_remove(struct spi_device *spi) -{ - return 0; -} - int s5c73m3_register_spi_driver(struct s5c73m3 *state) { struct spi_driver *spidrv = &state->spidrv; - spidrv->remove = s5c73m3_spi_remove; spidrv->probe = s5c73m3_spi_probe; spidrv->driver.name = S5C73M3_SPI_DRV_NAME; spidrv->driver.of_match_table = s5c73m3_spi_ids; From 89ab2d39643e5ce2b122baa1e76176d1bd984cec Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 11 Nov 2021 11:56:29 +0100 Subject: [PATCH 269/397] media: vb2: frame_vector.c: don't overwrite error code get_vaddr_frames() first calls pin_user_pages_fast() and if that fails tries follow_pfn(). But if that also fails, then the error code from pin_user_pages_fast() is overwritten with the error code from follow_pfn(). Specifically if pin_user_pages_fast() returns -ENOMEM, then follow_pfn() will overwrite that with -EINVAL, which is very confusing. So store the error code from pin_user_pages_fast() and return that if follow_pfn() returns -EINVAL. -EINVAL indicates that the page is unsuitable for follow_pfn, so pin_user_pages_fast() was the correct call to make, and that error code should be returned instead. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/videobuf2/frame_vector.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/videobuf2/frame_vector.c b/drivers/media/common/videobuf2/frame_vector.c index ce879f6f8f82..542dde9d2609 100644 --- a/drivers/media/common/videobuf2/frame_vector.c +++ b/drivers/media/common/videobuf2/frame_vector.c @@ -37,6 +37,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames, { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; + int ret_pin_user_pages_fast = 0; int ret = 0; int err; @@ -56,6 +57,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames, vec->is_pfns = false; goto out_unlocked; } + ret_pin_user_pages_fast = ret; mmap_read_lock(mm); vec->got_ref = false; @@ -71,7 +73,18 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames, while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) { err = follow_pfn(vma, start, &nums[ret]); if (err) { - if (ret == 0) + if (ret) + goto out; + // If follow_pfn() returns -EINVAL, then this + // is not an IO mapping or a raw PFN mapping. + // In that case, return the original error from + // pin_user_pages_fast(). Otherwise this + // function would return -EINVAL when + // pin_user_pages_fast() returned -ENOMEM, + // which makes debugging hard. + if (err == -EINVAL && ret_pin_user_pages_fast) + ret = ret_pin_user_pages_fast; + else ret = err; goto out; } From 615c6f28b9ad7efc9bfbef2cafc6a0c5bc0c21e0 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 11 Nov 2021 14:17:51 +0100 Subject: [PATCH 270/397] media: mtk-vcodec: Fix an error handling path in 'mtk_vcodec_probe()' In case of error the 'media_device_init()' call is not balanced by a corresponding 'media_device_cleanup()' call. Add it, when needed, as already done in the remove function. Fixes: 118add98f80e ("media: mtk-vcodec: vdec: add media device if using stateless api") Signed-off-by: Christophe JAILLET Acked-by: Tzung-Bi Shih Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c index 68abb1422c40..5d72fce154d8 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c @@ -358,6 +358,8 @@ err_media_reg: if (dev->vdec_pdata->uses_stateless_api) v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec); err_reg_cont: + if (dev->vdec_pdata->uses_stateless_api) + media_device_cleanup(&dev->mdev_dec); destroy_workqueue(dev->decode_workqueue); err_event_workq: v4l2_m2m_release(dev->m2m_dev_dec); From 41479adb5e52998ecf690b46164fffea3f5d65fd Mon Sep 17 00:00:00 2001 From: James Cowgill Date: Thu, 11 Nov 2021 23:01:08 +0100 Subject: [PATCH 271/397] media: hantro: Avoid global variable for jpeg quantization tables On a system with multiple encoders present, it's possible for two encoders to write to the global luma and chroma quantization tables at the same time if they both submit a JPEG frame to be encoded. Avoid this race by moving the tables into the `jpeg_ctx` structure which is stored on the stack. Signed-off-by: James Cowgill Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/hantro/hantro_h1_jpeg_enc.c | 5 ++- drivers/staging/media/hantro/hantro_jpeg.c | 31 ++++++------------- drivers/staging/media/hantro/hantro_jpeg.h | 4 ++- .../media/hantro/rockchip_vpu2_hw_jpeg_enc.c | 5 ++- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c index 56cf261a8e95..20dafd6eb6b9 100644 --- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c @@ -113,9 +113,8 @@ int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) hantro_h1_set_src_img_ctrl(vpu, ctx); hantro_h1_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf); - hantro_h1_jpeg_enc_set_qtable(vpu, - hantro_jpeg_get_qtable(0), - hantro_jpeg_get_qtable(1)); + hantro_h1_jpeg_enc_set_qtable(vpu, jpeg_ctx.hw_luma_qtable, + jpeg_ctx.hw_chroma_qtable); reg = H1_REG_AXI_CTRL_OUTPUT_SWAP16 | H1_REG_AXI_CTRL_INPUT_SWAP16 diff --git a/drivers/staging/media/hantro/hantro_jpeg.c b/drivers/staging/media/hantro/hantro_jpeg.c index 36c140fc6a36..df62fbdff7c9 100644 --- a/drivers/staging/media/hantro/hantro_jpeg.c +++ b/drivers/staging/media/hantro/hantro_jpeg.c @@ -36,8 +36,6 @@ static const unsigned char luma_q_table[] = { 0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0x63 }; -static unsigned char luma_q_table_reordered[ARRAY_SIZE(luma_q_table)]; - static const unsigned char chroma_q_table[] = { 0x11, 0x12, 0x18, 0x2f, 0x63, 0x63, 0x63, 0x63, 0x12, 0x15, 0x1a, 0x42, 0x63, 0x63, 0x63, 0x63, @@ -49,8 +47,6 @@ static const unsigned char chroma_q_table[] = { 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 }; -static unsigned char chroma_q_table_reordered[ARRAY_SIZE(chroma_q_table)]; - static const unsigned char zigzag[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, @@ -277,7 +273,7 @@ jpeg_scale_quant_table(unsigned char *file_q_tab, } } -static void jpeg_set_quality(unsigned char *buffer, int quality) +static void jpeg_set_quality(struct hantro_jpeg_ctx *ctx) { int scale; @@ -285,24 +281,15 @@ static void jpeg_set_quality(unsigned char *buffer, int quality) * Non-linear scaling factor: * [5,50] -> [1000..100], [51,100] -> [98..0] */ - if (quality < 50) - scale = 5000 / quality; + if (ctx->quality < 50) + scale = 5000 / ctx->quality; else - scale = 200 - 2 * quality; + scale = 200 - 2 * ctx->quality; - jpeg_scale_quant_table(buffer + LUMA_QUANT_OFF, - luma_q_table_reordered, - luma_q_table, scale); - jpeg_scale_quant_table(buffer + CHROMA_QUANT_OFF, - chroma_q_table_reordered, - chroma_q_table, scale); -} - -unsigned char *hantro_jpeg_get_qtable(int index) -{ - if (index == 0) - return luma_q_table_reordered; - return chroma_q_table_reordered; + jpeg_scale_quant_table(ctx->buffer + LUMA_QUANT_OFF, + ctx->hw_luma_qtable, luma_q_table, scale); + jpeg_scale_quant_table(ctx->buffer + CHROMA_QUANT_OFF, + ctx->hw_chroma_qtable, chroma_q_table, scale); } void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx) @@ -324,7 +311,7 @@ void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx) memcpy(buf + HUFF_CHROMA_AC_OFF, chroma_ac_table, sizeof(chroma_ac_table)); - jpeg_set_quality(buf, ctx->quality); + jpeg_set_quality(ctx); } int hantro_jpeg_enc_init(struct hantro_ctx *ctx) diff --git a/drivers/staging/media/hantro/hantro_jpeg.h b/drivers/staging/media/hantro/hantro_jpeg.h index 9474a00277f8..035ab25b803f 100644 --- a/drivers/staging/media/hantro/hantro_jpeg.h +++ b/drivers/staging/media/hantro/hantro_jpeg.h @@ -1,13 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0+ */ #define JPEG_HEADER_SIZE 601 +#define JPEG_QUANT_SIZE 64 struct hantro_jpeg_ctx { int width; int height; int quality; unsigned char *buffer; + unsigned char hw_luma_qtable[JPEG_QUANT_SIZE]; + unsigned char hw_chroma_qtable[JPEG_QUANT_SIZE]; }; -unsigned char *hantro_jpeg_get_qtable(int index); void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx); diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c index 991213ce1610..37f9707c3691 100644 --- a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c +++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c @@ -143,9 +143,8 @@ int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx) rockchip_vpu2_set_src_img_ctrl(vpu, ctx); rockchip_vpu2_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf); - rockchip_vpu2_jpeg_enc_set_qtable(vpu, - hantro_jpeg_get_qtable(0), - hantro_jpeg_get_qtable(1)); + rockchip_vpu2_jpeg_enc_set_qtable(vpu, jpeg_ctx.hw_luma_qtable, + jpeg_ctx.hw_chroma_qtable); reg = VEPU_REG_OUTPUT_SWAP32 | VEPU_REG_OUTPUT_SWAP16 From aee3c1436383da18f5b0306abc7d2d70bbf0612c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Sun, 14 Nov 2021 23:47:30 +0100 Subject: [PATCH 272/397] media: staging: tegra-vde: Support reference picture marking Tegra114 and Tegra124 support reference picture marking, which will cause BSEV to write picture marking data to SDRAM. Make sure there is a valid destination address for that data to avoid error messages from the memory controller. [digetx@gmail.com: added BO support and moved secure BO allocation to kernel] Tested-by: Anton Bambura # T114 ASUS TF701T Signed-off-by: Thierry Reding Co-developed-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/tegra-vde/vde.c | 124 +++++++++++++++++++++++++- drivers/staging/media/tegra-vde/vde.h | 18 ++++ 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/tegra-vde/vde.c b/drivers/staging/media/tegra-vde/vde.c index ed4c1250b303..9c0699867082 100644 --- a/drivers/staging/media/tegra-vde/vde.c +++ b/drivers/staging/media/tegra-vde/vde.c @@ -84,6 +84,96 @@ static int tegra_vde_wait_mbe(struct tegra_vde *vde) (tmp >= 0x10), 1, 100); } +static int tegra_vde_alloc_bo(struct tegra_vde *vde, + struct tegra_vde_bo **ret_bo, + enum dma_data_direction dma_dir, + size_t size) +{ + struct device *dev = vde->miscdev.parent; + struct tegra_vde_bo *bo; + int err; + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); + if (!bo) + return -ENOMEM; + + bo->vde = vde; + bo->size = size; + bo->dma_dir = dma_dir; + bo->dma_attrs = DMA_ATTR_WRITE_COMBINE | + DMA_ATTR_NO_KERNEL_MAPPING; + + if (!vde->domain) + bo->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS; + + bo->dma_cookie = dma_alloc_attrs(dev, bo->size, &bo->dma_handle, + GFP_KERNEL, bo->dma_attrs); + if (!bo->dma_cookie) { + dev_err(dev, "Failed to allocate DMA buffer of size: %zu\n", + bo->size); + err = -ENOMEM; + goto free_bo; + } + + err = dma_get_sgtable_attrs(dev, &bo->sgt, bo->dma_cookie, + bo->dma_handle, bo->size, bo->dma_attrs); + if (err) { + dev_err(dev, "Failed to get DMA buffer SG table: %d\n", err); + goto free_attrs; + } + + err = dma_map_sgtable(dev, &bo->sgt, bo->dma_dir, bo->dma_attrs); + if (err) { + dev_err(dev, "Failed to map DMA buffer SG table: %d\n", err); + goto free_table; + } + + if (vde->domain) { + err = tegra_vde_iommu_map(vde, &bo->sgt, &bo->iova, bo->size); + if (err) { + dev_err(dev, "Failed to map DMA buffer IOVA: %d\n", err); + goto unmap_sgtable; + } + + bo->dma_addr = iova_dma_addr(&vde->iova, bo->iova); + } else { + bo->dma_addr = sg_dma_address(bo->sgt.sgl); + } + + *ret_bo = bo; + + return 0; + +unmap_sgtable: + dma_unmap_sgtable(dev, &bo->sgt, bo->dma_dir, bo->dma_attrs); +free_table: + sg_free_table(&bo->sgt); +free_attrs: + dma_free_attrs(dev, bo->size, bo->dma_cookie, bo->dma_handle, + bo->dma_attrs); +free_bo: + kfree(bo); + + return err; +} + +static void tegra_vde_free_bo(struct tegra_vde_bo *bo) +{ + struct tegra_vde *vde = bo->vde; + struct device *dev = vde->miscdev.parent; + + if (vde->domain) + tegra_vde_iommu_unmap(vde, bo->iova); + + dma_unmap_sgtable(dev, &bo->sgt, bo->dma_dir, bo->dma_attrs); + + sg_free_table(&bo->sgt); + + dma_free_attrs(dev, bo->size, bo->dma_cookie, bo->dma_handle, + bo->dma_attrs); + kfree(bo); +} + static int tegra_vde_setup_mbe_frame_idx(struct tegra_vde *vde, unsigned int refs_nb, bool setup_refs) @@ -424,6 +514,9 @@ static int tegra_vde_setup_hw_context(struct tegra_vde *vde, tegra_vde_writel(vde, bitstream_data_addr, vde->sxe, 0x6C); + if (vde->soc->supports_ref_pic_marking) + tegra_vde_writel(vde, vde->secure_bo->dma_addr, vde->sxe, 0x7c); + value = 0x10000005; value |= ctx->pic_width_in_mbs << 11; value |= ctx->pic_height_in_mbs << 3; @@ -958,6 +1051,8 @@ static int tegra_vde_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vde); + vde->soc = of_device_get_match_data(&pdev->dev); + vde->sxe = devm_platform_ioremap_resource_byname(pdev, "sxe"); if (IS_ERR(vde->sxe)) return PTR_ERR(vde->sxe); @@ -1077,6 +1172,12 @@ static int tegra_vde_probe(struct platform_device *pdev) pm_runtime_put(dev); + err = tegra_vde_alloc_bo(vde, &vde->secure_bo, DMA_FROM_DEVICE, 4096); + if (err) { + dev_err(dev, "Failed to allocate secure BO: %d\n", err); + goto err_pm_runtime; + } + return 0; err_pm_runtime: @@ -1100,6 +1201,8 @@ static int tegra_vde_remove(struct platform_device *pdev) struct tegra_vde *vde = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; + tegra_vde_free_bo(vde->secure_bo); + /* * As it increments RPM usage_count even on errors, we don't need to * check the returned code here. @@ -1173,8 +1276,27 @@ static const struct dev_pm_ops tegra_vde_pm_ops = { tegra_vde_pm_resume) }; +static const struct tegra_vde_soc tegra124_vde_soc = { + .supports_ref_pic_marking = true, +}; + +static const struct tegra_vde_soc tegra114_vde_soc = { + .supports_ref_pic_marking = true, +}; + +static const struct tegra_vde_soc tegra30_vde_soc = { + .supports_ref_pic_marking = false, +}; + +static const struct tegra_vde_soc tegra20_vde_soc = { + .supports_ref_pic_marking = false, +}; + static const struct of_device_id tegra_vde_of_match[] = { - { .compatible = "nvidia,tegra20-vde", }, + { .compatible = "nvidia,tegra124-vde", .data = &tegra124_vde_soc }, + { .compatible = "nvidia,tegra114-vde", .data = &tegra114_vde_soc }, + { .compatible = "nvidia,tegra30-vde", .data = &tegra30_vde_soc }, + { .compatible = "nvidia,tegra20-vde", .data = &tegra20_vde_soc }, { }, }; MODULE_DEVICE_TABLE(of, tegra_vde_of_match); diff --git a/drivers/staging/media/tegra-vde/vde.h b/drivers/staging/media/tegra-vde/vde.h index 5561291b0c88..bbd42b8d9991 100644 --- a/drivers/staging/media/tegra-vde/vde.h +++ b/drivers/staging/media/tegra-vde/vde.h @@ -24,6 +24,22 @@ struct iommu_domain; struct reset_control; struct dma_buf_attachment; +struct tegra_vde_soc { + bool supports_ref_pic_marking; +}; + +struct tegra_vde_bo { + struct iova *iova; + struct sg_table sgt; + struct tegra_vde *vde; + enum dma_data_direction dma_dir; + unsigned long dma_attrs; + dma_addr_t dma_handle; + dma_addr_t dma_addr; + void *dma_cookie; + size_t size; +}; + struct tegra_vde { void __iomem *sxe; void __iomem *bsev; @@ -48,6 +64,8 @@ struct tegra_vde { struct iova_domain iova; struct iova *iova_resv_static_addresses; struct iova *iova_resv_last_page; + const struct tegra_vde_soc *soc; + struct tegra_vde_bo *secure_bo; dma_addr_t iram_lists_addr; u32 *iram; }; From 439c827e06f169b50fce271fe5ddb46bf9f88c5e Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Sun, 14 Nov 2021 23:47:31 +0100 Subject: [PATCH 273/397] media: staging: tegra-vde: Properly mark invalid entries Entries in the reference picture list are marked as invalid by setting the frame ID to 0x3f. Signed-off-by: Thierry Reding Signed-off-by: Dmitry Osipenko Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/tegra-vde/vde.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/tegra-vde/vde.c b/drivers/staging/media/tegra-vde/vde.c index 9c0699867082..73a42336f37a 100644 --- a/drivers/staging/media/tegra-vde/vde.c +++ b/drivers/staging/media/tegra-vde/vde.c @@ -339,7 +339,7 @@ static void tegra_vde_setup_iram_tables(struct tegra_vde *vde, value |= frame->frame_num; } else { aux_addr = 0x6ADEAD00; - value = 0; + value = 0x3f; } tegra_vde_setup_iram_entry(vde, 0, i, value, aux_addr); From 0de2412b7d404806ce609e00b758336283b54631 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Nov 2021 23:47:32 +0100 Subject: [PATCH 274/397] media: staging: tegra-vde: Reorder misc device registration Register misc device in the end of driver's probing since device should become visible to userspace once driver is fully prepared. Do the opposite in case of driver removal. This is a minor improvement that doesn't solve any problem, but makes code more consistent. Signed-off-by: Dmitry Osipenko Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/tegra-vde/vde.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/staging/media/tegra-vde/vde.c b/drivers/staging/media/tegra-vde/vde.c index 73a42336f37a..7dc4833e71de 100644 --- a/drivers/staging/media/tegra-vde/vde.c +++ b/drivers/staging/media/tegra-vde/vde.c @@ -1151,12 +1151,6 @@ static int tegra_vde_probe(struct platform_device *pdev) goto err_gen_free; } - err = misc_register(&vde->miscdev); - if (err) { - dev_err(dev, "Failed to register misc device: %d\n", err); - goto err_deinit_iommu; - } - pm_runtime_enable(dev); pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, 300); @@ -1178,15 +1172,20 @@ static int tegra_vde_probe(struct platform_device *pdev) goto err_pm_runtime; } + err = misc_register(&vde->miscdev); + if (err) { + dev_err(dev, "Failed to register misc device: %d\n", err); + goto err_free_secure_bo; + } + return 0; +err_free_secure_bo: + tegra_vde_free_bo(vde->secure_bo); err_pm_runtime: - misc_deregister(&vde->miscdev); - pm_runtime_dont_use_autosuspend(dev); pm_runtime_disable(dev); -err_deinit_iommu: tegra_vde_iommu_deinit(vde); err_gen_free: @@ -1201,6 +1200,8 @@ static int tegra_vde_remove(struct platform_device *pdev) struct tegra_vde *vde = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; + misc_deregister(&vde->miscdev); + tegra_vde_free_bo(vde->secure_bo); /* @@ -1219,8 +1220,6 @@ static int tegra_vde_remove(struct platform_device *pdev) pm_runtime_put_noidle(dev); clk_disable_unprepare(vde->clk); - misc_deregister(&vde->miscdev); - tegra_vde_dmabuf_cache_unmap_all(vde); tegra_vde_iommu_deinit(vde); From 3fa23824fe82a41301f53e025a693104c12f5364 Mon Sep 17 00:00:00 2001 From: Guo Zhengkui Date: Mon, 15 Nov 2021 07:54:58 +0100 Subject: [PATCH 275/397] media: imx: fix boolreturn.cocci warning: Fix following boolreturn.cocci warning: ./drivers/staging/media/imx/imx-media-csi.c:153:9-10: WARNING: return of 0/1 in function 'requires_passthrough' with return type bool. Signed-off-by: Guo Zhengkui Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-csi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 1caa100be33d..bd7f156f2d52 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -150,7 +150,7 @@ static inline bool requires_passthrough(struct v4l2_fwnode_endpoint *ep, const struct imx_media_pixfmt *incc) { if (ep->bus_type == V4L2_MBUS_BT656) // including BT.1120 - return 0; + return false; return incc->bayer || is_parallel_16bit_bus(ep) || (is_parallel_bus(ep) && From 92f1b2496313915c45a98b302274fb20e90d33be Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Tue, 16 Nov 2021 02:47:26 +0100 Subject: [PATCH 276/397] media: mtk-jpeg: Remove unnecessary print function dev_err() The print function dev_err() is redundant because platform_get_irq() already prints an error. Signed-off-by: Xu Wang Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c index af994b9913a6..f332beb06d51 100644 --- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c +++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c @@ -1361,10 +1361,8 @@ static int mtk_jpeg_probe(struct platform_device *pdev) } jpeg_irq = platform_get_irq(pdev, 0); - if (jpeg_irq < 0) { - dev_err(&pdev->dev, "Failed to get jpeg_irq %d.\n", jpeg_irq); + if (jpeg_irq < 0) return jpeg_irq; - } ret = devm_request_irq(&pdev->dev, jpeg_irq, jpeg->variant->irq_handler, 0, pdev->name, jpeg); From 9f89c881bffbdffe4060ffaef3489a2830a6dd9c Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 17 Nov 2021 14:06:30 +0100 Subject: [PATCH 277/397] media: mtk-vcodec: call v4l2_m2m_ctx_release first when file is released The func v4l2_m2m_ctx_release waits for currently running jobs to finish and then stop streaming both queues and frees the buffers. All this should be done before the call to mtk_vcodec_enc_release which frees the encoder handler. This fixes null-pointer dereference bug: [ 638.028076] Mem abort info: [ 638.030932] ESR = 0x96000004 [ 638.033978] EC = 0x25: DABT (current EL), IL = 32 bits [ 638.039293] SET = 0, FnV = 0 [ 638.042338] EA = 0, S1PTW = 0 [ 638.045474] FSC = 0x04: level 0 translation fault [ 638.050349] Data abort info: [ 638.053224] ISV = 0, ISS = 0x00000004 [ 638.057055] CM = 0, WnR = 0 [ 638.060018] user pgtable: 4k pages, 48-bit VAs, pgdp=000000012b6db000 [ 638.066485] [00000000000001a0] pgd=0000000000000000, p4d=0000000000000000 [ 638.073277] Internal error: Oops: 96000004 [#1] SMP [ 638.078145] Modules linked in: rfkill mtk_vcodec_dec mtk_vcodec_enc uvcvideo mtk_mdp mtk_vcodec_common videobuf2_dma_contig v4l2_h264 cdc_ether v4l2_mem2mem videobuf2_vmalloc usbnet videobuf2_memops videobuf2_v4l2 r8152 videobuf2_common videodev cros_ec_sensors cros_ec_sensors_core industrialio_triggered_buffer kfifo_buf elan_i2c elants_i2c sbs_battery mc cros_usbpd_charger cros_ec_chardev cros_usbpd_logger crct10dif_ce mtk_vpu fuse ip_tables x_tables ipv6 [ 638.118583] CPU: 0 PID: 212 Comm: kworker/u8:5 Not tainted 5.15.0-06427-g58a1d4dcfc74-dirty #109 [ 638.127357] Hardware name: Google Elm (DT) [ 638.131444] Workqueue: mtk-vcodec-enc mtk_venc_worker [mtk_vcodec_enc] [ 638.137974] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 638.144925] pc : vp8_enc_encode+0x34/0x2b0 [mtk_vcodec_enc] [ 638.150493] lr : venc_if_encode+0xac/0x1b0 [mtk_vcodec_enc] [ 638.156060] sp : ffff8000124d3c40 [ 638.159364] x29: ffff8000124d3c40 x28: 0000000000000000 x27: 0000000000000000 [ 638.166493] x26: 0000000000000000 x25: ffff0000e7f252d0 x24: ffff8000124d3d58 [ 638.173621] x23: ffff8000124d3d58 x22: ffff8000124d3d60 x21: 0000000000000001 [ 638.180750] x20: ffff80001137e000 x19: 0000000000000000 x18: 0000000000000001 [ 638.187878] x17: 000000040044ffff x16: 00400032b5503510 x15: 0000000000000000 [ 638.195006] x14: ffff8000118536c0 x13: ffff8000ee1da000 x12: 0000000030d4d91d [ 638.202134] x11: 0000000000000000 x10: 0000000000000980 x9 : ffff8000124d3b20 [ 638.209262] x8 : ffff0000c18d4ea0 x7 : ffff0000c18d44c0 x6 : ffff0000c18d44c0 [ 638.216391] x5 : ffff80000904a3b0 x4 : ffff8000124d3d58 x3 : ffff8000124d3d60 [ 638.223519] x2 : ffff8000124d3d78 x1 : 0000000000000001 x0 : ffff80001137efb8 [ 638.230648] Call trace: [ 638.233084] vp8_enc_encode+0x34/0x2b0 [mtk_vcodec_enc] [ 638.238304] venc_if_encode+0xac/0x1b0 [mtk_vcodec_enc] [ 638.243525] mtk_venc_worker+0x110/0x250 [mtk_vcodec_enc] [ 638.248918] process_one_work+0x1f8/0x498 [ 638.252923] worker_thread+0x140/0x538 [ 638.256664] kthread+0x148/0x158 [ 638.259884] ret_from_fork+0x10/0x20 [ 638.263455] Code: f90023f9 2a0103f5 aa0303f6 aa0403f8 (f940d277) [ 638.269538] ---[ end trace e374fc10f8e181f5 ]--- [gst-master] root@debian:~/gst-build# [ 638.019193] Unable to handle kernel NULL pointer dereference at virtual address 00000000000001a0 Fixes: 4e855a6efa547 ("[media] vcodec: mediatek: Add Mediatek V4L2 Video Encoder Driver") Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index b576f44ce505..fa7b495c778b 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -214,11 +214,11 @@ static int fops_vcodec_release(struct file *file) mtk_v4l2_debug(1, "[%d] encoder", ctx->id); mutex_lock(&dev->dev_mutex); + v4l2_m2m_ctx_release(ctx->m2m_ctx); mtk_vcodec_enc_release(ctx); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); - v4l2_m2m_ctx_release(ctx->m2m_ctx); list_del_init(&ctx->list); kfree(ctx); From 71c789760ff9ba4b687c2f8aa828045ca525c517 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 17 Nov 2021 14:06:32 +0100 Subject: [PATCH 278/397] media: mtk-vcodec: fix debugging defines The mtk-vcodec uses some internal defined debug formats for printing. This patch fixes some things in those defines: 1. use the 'pr_fmt' define to print function name and line. 2. remove 'if(DEBUG)' condition for the defines. This condition prevents the debugs from being shown in case of dynamic debugs. Instead replace 'pr_info' with 'pr_debug' 3. remove module parameters that enable/disable debug. There is no reason for the driver to have those params. Having those params require the user to explicitly set them when user wants to see debug prints instead of using the global debugs setting as expected by drivers to conform. In addition to that, fix some warnings about debug formatting [hverkuil: used %zu instead of %lu for sizeof() arguments] Signed-off-by: Dafna Hirschfeld Reported-by: kernel test robot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 3 -- .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 3 -- .../platform/mtk-vcodec/mtk_vcodec_util.c | 10 ----- .../platform/mtk-vcodec/mtk_vcodec_util.h | 45 +++++-------------- .../mtk-vcodec/vdec/vdec_h264_req_if.c | 4 +- 5 files changed, 12 insertions(+), 53 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c index 5d72fce154d8..40c39e1e596b 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c @@ -28,9 +28,6 @@ #define VDEC_IRQ_CLR 0x10 #define VDEC_IRQ_CFG_REG 0xa4 -module_param(mtk_v4l2_dbg_level, int, 0644); -module_param(mtk_vcodec_dbg, bool, 0644); - /* Wake up context wait_queue */ static void wake_up_ctx(struct mtk_vcodec_ctx *ctx) { diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index fa7b495c778b..aeaecb8d416e 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -23,9 +23,6 @@ #include "mtk_vcodec_util.h" #include "mtk_vcodec_fw.h" -module_param(mtk_v4l2_dbg_level, int, S_IRUGO | S_IWUSR); -module_param(mtk_vcodec_dbg, bool, S_IRUGO | S_IWUSR); - static const struct mtk_video_fmt mtk_video_formats_output[] = { { .fourcc = V4L2_PIX_FMT_NV12M, diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c index ac5973b6735f..5bac820a47fc 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c @@ -10,16 +10,6 @@ #include "mtk_vcodec_drv.h" #include "mtk_vcodec_util.h" -/* For encoder, this will enable logs in venc/*/ -bool mtk_vcodec_dbg; -EXPORT_SYMBOL(mtk_vcodec_dbg); - -/* The log level of v4l2 encoder or decoder driver. - * That is, files under mtk-vcodec/. - */ -int mtk_v4l2_dbg_level; -EXPORT_SYMBOL(mtk_v4l2_dbg_level); - void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data, unsigned int reg_idx) { diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h index b999d7b84ed1..87c3d6d4bfa7 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h @@ -25,54 +25,29 @@ struct mtk_vcodec_fb { struct mtk_vcodec_ctx; struct mtk_vcodec_dev; -extern int mtk_v4l2_dbg_level; -extern bool mtk_vcodec_dbg; - +#undef pr_fmt +#define pr_fmt(fmt) "%s(),%d: " fmt, __func__, __LINE__ #define mtk_v4l2_err(fmt, args...) \ - pr_err("[MTK_V4L2][ERROR] %s:%d: " fmt "\n", __func__, __LINE__, \ - ##args) + pr_err("[MTK_V4L2][ERROR] " fmt "\n", ##args) -#define mtk_vcodec_err(h, fmt, args...) \ - pr_err("[MTK_VCODEC][ERROR][%d]: %s() " fmt "\n", \ - ((struct mtk_vcodec_ctx *)h->ctx)->id, __func__, ##args) +#define mtk_vcodec_err(h, fmt, args...) \ + pr_err("[MTK_VCODEC][ERROR][%d]: " fmt "\n", \ + ((struct mtk_vcodec_ctx *)(h)->ctx)->id, ##args) -#if defined(DEBUG) - -#define mtk_v4l2_debug(level, fmt, args...) \ - do { \ - if (mtk_v4l2_dbg_level >= level) \ - pr_info("[MTK_V4L2] level=%d %s(),%d: " fmt "\n",\ - level, __func__, __LINE__, ##args); \ - } while (0) +#define mtk_v4l2_debug(level, fmt, args...) pr_debug(fmt, ##args) #define mtk_v4l2_debug_enter() mtk_v4l2_debug(3, "+") #define mtk_v4l2_debug_leave() mtk_v4l2_debug(3, "-") -#define mtk_vcodec_debug(h, fmt, args...) \ - do { \ - if (mtk_vcodec_dbg) \ - pr_info("[MTK_VCODEC][%d]: %s() " fmt "\n", \ - ((struct mtk_vcodec_ctx *)h->ctx)->id, \ - __func__, ##args); \ - } while (0) +#define mtk_vcodec_debug(h, fmt, args...) \ + pr_debug("[MTK_VCODEC][%d]: " fmt "\n", \ + ((struct mtk_vcodec_ctx *)(h)->ctx)->id, ##args) #define mtk_vcodec_debug_enter(h) mtk_vcodec_debug(h, "+") #define mtk_vcodec_debug_leave(h) mtk_vcodec_debug(h, "-") -#else - -#define mtk_v4l2_debug(level, fmt, args...) {} -#define mtk_v4l2_debug_enter() {} -#define mtk_v4l2_debug_leave() {} - -#define mtk_vcodec_debug(h, fmt, args...) {} -#define mtk_vcodec_debug_enter(h) {} -#define mtk_vcodec_debug_leave(h) {} - -#endif - void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data, unsigned int reg_idx); int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data, diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_req_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_req_if.c index 5a7eefe639a8..fada4d146703 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_req_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_req_if.c @@ -527,7 +527,7 @@ static int alloc_mv_buf(struct vdec_h264_slice_inst *inst, struct mtk_vcodec_mem *mem = NULL; unsigned int buf_sz = get_mv_buf_size(pic->buf_w, pic->buf_h); - mtk_v4l2_debug(3, "size = 0x%lx", buf_sz); + mtk_v4l2_debug(3, "size = 0x%x", buf_sz); for (i = 0; i < H264_MAX_MV_NUM; i++) { mem = &inst->mv_buf[i]; if (mem->va) @@ -637,7 +637,7 @@ static int vdec_h264_slice_init(struct mtk_vcodec_ctx *ctx) if (err) goto error_deinit; - mtk_vcodec_debug(inst, "struct size = %d,%d,%d,%d\n", + mtk_vcodec_debug(inst, "struct size = %zu,%zu,%zu,%zu\n", sizeof(struct mtk_h264_sps_param), sizeof(struct mtk_h264_pps_param), sizeof(struct mtk_h264_dec_slice_param), From ba0b00e7930b477eba4cf1de1b62ae68949911b7 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 17 Nov 2021 14:06:33 +0100 Subject: [PATCH 279/397] media: mtk-vcodec: replace func vidioc_try_fmt with two funcs for out/cap The function vidioc_try_fmt has a big 'if-else' for the capture and output cases. There is hardly any code outside of that condition. It is therefore better to split that functions into two different functions, one for each case. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../platform/mtk-vcodec/mtk_vcodec_enc.c | 141 +++++++++--------- 1 file changed, 68 insertions(+), 73 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index 7232dc053c64..435743942ad9 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -264,87 +264,82 @@ static struct mtk_q_data *mtk_venc_get_q_data(struct mtk_vcodec_ctx *ctx, return &ctx->q_data[MTK_Q_DATA_DST]; } +static void vidioc_try_fmt_cap(struct v4l2_format *f) +{ + f->fmt.pix_mp.field = V4L2_FIELD_NONE; + f->fmt.pix_mp.num_planes = 1; + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; + f->fmt.pix_mp.flags = 0; +} + /* V4L2 specification suggests the driver corrects the format struct if any of * the dimensions is unsupported */ -static int vidioc_try_fmt(struct mtk_vcodec_ctx *ctx, struct v4l2_format *f, - const struct mtk_video_fmt *fmt) +static int vidioc_try_fmt_out(struct mtk_vcodec_ctx *ctx, struct v4l2_format *f, + const struct mtk_video_fmt *fmt) { struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; + int tmp_w, tmp_h; + unsigned int max_width, max_height; pix_fmt_mp->field = V4L2_FIELD_NONE; - if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - pix_fmt_mp->num_planes = 1; - pix_fmt_mp->plane_fmt[0].bytesperline = 0; - } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - int tmp_w, tmp_h; - unsigned int max_width, max_height; + if (ctx->dev->enc_capability & MTK_VENC_4K_CAPABILITY_ENABLE) { + max_width = MTK_VENC_4K_MAX_W; + max_height = MTK_VENC_4K_MAX_H; + } else { + max_width = MTK_VENC_HD_MAX_W; + max_height = MTK_VENC_HD_MAX_H; + } - if (ctx->dev->enc_capability & MTK_VENC_4K_CAPABILITY_ENABLE) { - max_width = MTK_VENC_4K_MAX_W; - max_height = MTK_VENC_4K_MAX_H; - } else { - max_width = MTK_VENC_HD_MAX_W; - max_height = MTK_VENC_HD_MAX_H; - } + pix_fmt_mp->height = clamp(pix_fmt_mp->height, MTK_VENC_MIN_H, max_height); + pix_fmt_mp->width = clamp(pix_fmt_mp->width, MTK_VENC_MIN_W, max_width); - pix_fmt_mp->height = clamp(pix_fmt_mp->height, - MTK_VENC_MIN_H, - max_height); - pix_fmt_mp->width = clamp(pix_fmt_mp->width, - MTK_VENC_MIN_W, - max_width); + /* find next closer width align 16, heign align 32, size align + * 64 rectangle + */ + tmp_w = pix_fmt_mp->width; + tmp_h = pix_fmt_mp->height; + v4l_bound_align_image(&pix_fmt_mp->width, + MTK_VENC_MIN_W, + max_width, 4, + &pix_fmt_mp->height, + MTK_VENC_MIN_H, + max_height, 5, 6); - /* find next closer width align 16, heign align 32, size align - * 64 rectangle - */ - tmp_w = pix_fmt_mp->width; - tmp_h = pix_fmt_mp->height; - v4l_bound_align_image(&pix_fmt_mp->width, - MTK_VENC_MIN_W, - max_width, 4, - &pix_fmt_mp->height, - MTK_VENC_MIN_H, - max_height, 5, 6); + if (pix_fmt_mp->width < tmp_w && (pix_fmt_mp->width + 16) <= max_width) + pix_fmt_mp->width += 16; + if (pix_fmt_mp->height < tmp_h && (pix_fmt_mp->height + 32) <= max_height) + pix_fmt_mp->height += 32; - if (pix_fmt_mp->width < tmp_w && - (pix_fmt_mp->width + 16) <= max_width) - pix_fmt_mp->width += 16; - if (pix_fmt_mp->height < tmp_h && - (pix_fmt_mp->height + 32) <= max_height) - pix_fmt_mp->height += 32; + mtk_v4l2_debug(0, "before resize w=%d, h=%d, after resize w=%d, h=%d, sizeimage=%d %d", + tmp_w, tmp_h, pix_fmt_mp->width, + pix_fmt_mp->height, + pix_fmt_mp->plane_fmt[0].sizeimage, + pix_fmt_mp->plane_fmt[1].sizeimage); - mtk_v4l2_debug(0, - "before resize width=%d, height=%d, after resize width=%d, height=%d, sizeimage=%d %d", - tmp_w, tmp_h, pix_fmt_mp->width, - pix_fmt_mp->height, - pix_fmt_mp->plane_fmt[0].sizeimage, - pix_fmt_mp->plane_fmt[1].sizeimage); + pix_fmt_mp->num_planes = fmt->num_planes; + pix_fmt_mp->plane_fmt[0].sizeimage = + pix_fmt_mp->width * pix_fmt_mp->height + + ((ALIGN(pix_fmt_mp->width, 16) * 2) * 16); + pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width; - pix_fmt_mp->num_planes = fmt->num_planes; - pix_fmt_mp->plane_fmt[0].sizeimage = - pix_fmt_mp->width * pix_fmt_mp->height + - ((ALIGN(pix_fmt_mp->width, 16) * 2) * 16); - pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width; - - if (pix_fmt_mp->num_planes == 2) { - pix_fmt_mp->plane_fmt[1].sizeimage = - (pix_fmt_mp->width * pix_fmt_mp->height) / 2 + - (ALIGN(pix_fmt_mp->width, 16) * 16); - pix_fmt_mp->plane_fmt[2].sizeimage = 0; - pix_fmt_mp->plane_fmt[1].bytesperline = - pix_fmt_mp->width; - pix_fmt_mp->plane_fmt[2].bytesperline = 0; - } else if (pix_fmt_mp->num_planes == 3) { - pix_fmt_mp->plane_fmt[1].sizeimage = - pix_fmt_mp->plane_fmt[2].sizeimage = - (pix_fmt_mp->width * pix_fmt_mp->height) / 4 + - ((ALIGN(pix_fmt_mp->width, 16) / 2) * 16); - pix_fmt_mp->plane_fmt[1].bytesperline = - pix_fmt_mp->plane_fmt[2].bytesperline = - pix_fmt_mp->width / 2; - } + if (pix_fmt_mp->num_planes == 2) { + pix_fmt_mp->plane_fmt[1].sizeimage = + (pix_fmt_mp->width * pix_fmt_mp->height) / 2 + + (ALIGN(pix_fmt_mp->width, 16) * 16); + pix_fmt_mp->plane_fmt[2].sizeimage = 0; + pix_fmt_mp->plane_fmt[1].bytesperline = + pix_fmt_mp->width; + pix_fmt_mp->plane_fmt[2].bytesperline = 0; + } else if (pix_fmt_mp->num_planes == 3) { + pix_fmt_mp->plane_fmt[1].sizeimage = + pix_fmt_mp->plane_fmt[2].sizeimage = + (pix_fmt_mp->width * pix_fmt_mp->height) / 4 + + ((ALIGN(pix_fmt_mp->width, 16) / 2) * 16); + pix_fmt_mp->plane_fmt[1].bytesperline = + pix_fmt_mp->plane_fmt[2].bytesperline = + pix_fmt_mp->width / 2; } pix_fmt_mp->flags = 0; @@ -433,9 +428,7 @@ static int vidioc_venc_s_fmt_cap(struct file *file, void *priv, } q_data->fmt = fmt; - ret = vidioc_try_fmt(ctx, f, q_data->fmt); - if (ret) - return ret; + vidioc_try_fmt_cap(f); q_data->coded_width = f->fmt.pix_mp.width; q_data->coded_height = f->fmt.pix_mp.height; @@ -495,7 +488,7 @@ static int vidioc_venc_s_fmt_out(struct file *file, void *priv, f->fmt.pix.pixelformat = fmt->fourcc; } - ret = vidioc_try_fmt(ctx, f, fmt); + ret = vidioc_try_fmt_out(ctx, f, fmt); if (ret) return ret; @@ -573,7 +566,9 @@ static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv, f->fmt.pix_mp.quantization = ctx->quantization; f->fmt.pix_mp.xfer_func = ctx->xfer_func; - return vidioc_try_fmt(ctx, f, fmt); + vidioc_try_fmt_cap(f); + + return 0; } static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, @@ -595,7 +590,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; } - return vidioc_try_fmt(ctx, f, fmt); + return vidioc_try_fmt_out(ctx, f, fmt); } static int vidioc_venc_g_selection(struct file *file, void *priv, From b80811546495ee7fd56d16b0fe978f3921f12175 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 17 Nov 2021 14:06:34 +0100 Subject: [PATCH 280/397] media: mtk-vcodec: don't check return val of mtk_venc_get_q_data The function mtk_venc_get_q_data always returns a reference so there is no need to check if the return value is null. In addition move the q_data initialization to the declaration Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../platform/mtk-vcodec/mtk_vcodec_enc.c | 39 ++++--------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index 435743942ad9..03f905555d56 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -400,7 +400,7 @@ static int vidioc_venc_s_fmt_cap(struct file *file, void *priv, struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; struct vb2_queue *vq; - struct mtk_q_data *q_data; + struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, f->type); int i, ret; const struct mtk_video_fmt *fmt; @@ -415,12 +415,6 @@ static int vidioc_venc_s_fmt_cap(struct file *file, void *priv, return -EBUSY; } - q_data = mtk_venc_get_q_data(ctx, f->type); - if (!q_data) { - mtk_v4l2_err("fail to get q data"); - return -EINVAL; - } - fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata); if (!fmt) { fmt = &ctx->dev->venc_pdata->capture_formats[0]; @@ -461,7 +455,7 @@ static int vidioc_venc_s_fmt_out(struct file *file, void *priv, struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata; struct vb2_queue *vq; - struct mtk_q_data *q_data; + struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, f->type); int ret, i; const struct mtk_video_fmt *fmt; @@ -476,12 +470,6 @@ static int vidioc_venc_s_fmt_out(struct file *file, void *priv, return -EBUSY; } - q_data = mtk_venc_get_q_data(ctx, f->type); - if (!q_data) { - mtk_v4l2_err("fail to get q data"); - return -EINVAL; - } - fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata); if (!fmt) { fmt = &ctx->dev->venc_pdata->output_formats[0]; @@ -521,14 +509,13 @@ static int vidioc_venc_g_fmt(struct file *file, void *priv, struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); struct vb2_queue *vq; - struct mtk_q_data *q_data; + struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, f->type); int i; vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); if (!vq) return -EINVAL; - q_data = mtk_venc_get_q_data(ctx, f->type); pix->width = q_data->coded_width; pix->height = q_data->coded_height; @@ -597,15 +584,11 @@ static int vidioc_venc_g_selection(struct file *file, void *priv, struct v4l2_selection *s) { struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); - struct mtk_q_data *q_data; + struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, s->type); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; - q_data = mtk_venc_get_q_data(ctx, s->type); - if (!q_data) - return -EINVAL; - switch (s->target) { case V4L2_SEL_TGT_CROP_DEFAULT: case V4L2_SEL_TGT_CROP_BOUNDS: @@ -631,15 +614,11 @@ static int vidioc_venc_s_selection(struct file *file, void *priv, struct v4l2_selection *s) { struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); - struct mtk_q_data *q_data; + struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, s->type); if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; - q_data = mtk_venc_get_q_data(ctx, s->type); - if (!q_data) - return -EINVAL; - switch (s->target) { case V4L2_SEL_TGT_CROP: /* Only support crop from (0,0) */ @@ -806,11 +785,9 @@ static int vb2ops_venc_queue_setup(struct vb2_queue *vq, struct device *alloc_devs[]) { struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vq); - struct mtk_q_data *q_data; + struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, vq->type); unsigned int i; - q_data = mtk_venc_get_q_data(ctx, vq->type); - if (q_data == NULL) return -EINVAL; @@ -830,11 +807,9 @@ static int vb2ops_venc_queue_setup(struct vb2_queue *vq, static int vb2ops_venc_buf_prepare(struct vb2_buffer *vb) { struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); - struct mtk_q_data *q_data; + struct mtk_q_data *q_data = mtk_venc_get_q_data(ctx, vb->vb2_queue->type); int i; - q_data = mtk_venc_get_q_data(ctx, vb->vb2_queue->type); - for (i = 0; i < q_data->fmt->num_planes; i++) { if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) { mtk_v4l2_err("data will not fit into plane %d (%lu < %d)", From 230d683ae04894933720425c8dead9508a09ebc3 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 19 Nov 2021 08:46:54 +0100 Subject: [PATCH 281/397] media: hantro: Hook up RK3399 JPEG encoder output The JPEG encoder found in the Hantro H1 encoder block only produces a raw entropy-encoded scan. The driver is responsible for building a JPEG compliant bitstream and placing the entropy-encoded scan in it. Right now the driver uses a bounce buffer for the hardware to output the raw scan to. In commit e765dba11ec2 ("hantro: Move hantro_enc_buf_finish to JPEG codec_ops.done"), the code that copies the raw scan from the bounce buffer to the capture buffer was moved, but was only hooked up for the Hantro H1 (then RK3288) variant. The RK3399 variant was broken, producing a JPEG bitstream without the scan, and the capture buffer's .bytesused field unset. Fix this by duplicating the code that is executed when the JPEG encoder finishes encoding a frame. As the encoded length is read back from hardware, and the variants having different register layouts, the code is duplicated rather than shared. Fixes: e765dba11ec2 ("hantro: Move hantro_enc_buf_finish to JPEG codec_ops.done") Signed-off-by: Chen-Yu Tsai Tested-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/hantro/hantro_h1_jpeg_enc.c | 2 +- drivers/staging/media/hantro/hantro_hw.h | 3 ++- .../media/hantro/rockchip_vpu2_hw_jpeg_enc.c | 17 +++++++++++++++++ drivers/staging/media/hantro/rockchip_vpu_hw.c | 5 +++-- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c index 20dafd6eb6b9..1450013d3685 100644 --- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c @@ -139,7 +139,7 @@ int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) return 0; } -void hantro_jpeg_enc_done(struct hantro_ctx *ctx) +void hantro_h1_jpeg_enc_done(struct hantro_ctx *ctx) { struct hantro_dev *vpu = ctx->dev; u32 bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8; diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index dbe51303724b..cff817ca8d22 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -328,7 +328,8 @@ int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx); int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx); int hantro_jpeg_enc_init(struct hantro_ctx *ctx); void hantro_jpeg_enc_exit(struct hantro_ctx *ctx); -void hantro_jpeg_enc_done(struct hantro_ctx *ctx); +void hantro_h1_jpeg_enc_done(struct hantro_ctx *ctx); +void rockchip_vpu2_jpeg_enc_done(struct hantro_ctx *ctx); dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, unsigned int dpb_idx); diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c index 37f9707c3691..4df16f59fb97 100644 --- a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c +++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c @@ -170,3 +170,20 @@ int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx) return 0; } + +void rockchip_vpu2_jpeg_enc_done(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + u32 bytesused = vepu_read(vpu, VEPU_REG_STR_BUF_LIMIT) / 8; + struct vb2_v4l2_buffer *dst_buf = hantro_get_dst_buf(ctx); + + /* + * TODO: Rework the JPEG encoder to eliminate the need + * for a bounce buffer. + */ + memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) + + ctx->vpu_dst_fmt->header_size, + ctx->jpeg_enc.bounce_buffer.cpu, bytesused); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, + ctx->vpu_dst_fmt->header_size + bytesused); +} diff --git a/drivers/staging/media/hantro/rockchip_vpu_hw.c b/drivers/staging/media/hantro/rockchip_vpu_hw.c index f372f767d4ff..c203b606e6e7 100644 --- a/drivers/staging/media/hantro/rockchip_vpu_hw.c +++ b/drivers/staging/media/hantro/rockchip_vpu_hw.c @@ -344,7 +344,7 @@ static const struct hantro_codec_ops rk3066_vpu_codec_ops[] = { .run = hantro_h1_jpeg_enc_run, .reset = rockchip_vpu1_enc_reset, .init = hantro_jpeg_enc_init, - .done = hantro_jpeg_enc_done, + .done = hantro_h1_jpeg_enc_done, .exit = hantro_jpeg_enc_exit, }, [HANTRO_MODE_H264_DEC] = { @@ -372,7 +372,7 @@ static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = { .run = hantro_h1_jpeg_enc_run, .reset = rockchip_vpu1_enc_reset, .init = hantro_jpeg_enc_init, - .done = hantro_jpeg_enc_done, + .done = hantro_h1_jpeg_enc_done, .exit = hantro_jpeg_enc_exit, }, [HANTRO_MODE_H264_DEC] = { @@ -400,6 +400,7 @@ static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = { .run = rockchip_vpu2_jpeg_enc_run, .reset = rockchip_vpu2_enc_reset, .init = hantro_jpeg_enc_init, + .done = rockchip_vpu2_jpeg_enc_done, .exit = hantro_jpeg_enc_exit, }, [HANTRO_MODE_H264_DEC] = { From 1a59cd88f55068710f6549bee548846661673780 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 19 Nov 2021 11:41:20 +0100 Subject: [PATCH 282/397] media: coda: fix CODA960 JPEG encoder buffer overflow Stop the CODA960 JPEG encoder from overflowing capture buffers. The bitstream buffer overflow interrupt doesn't seem to be connected, so this has to be handled via timeout instead. Reported-by: Martin Weber Fixes: 96f6f62c4656 ("media: coda: jpeg: add CODA960 JPEG encoder support") Tested-by: Martin Weber Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 8 +++++--- drivers/media/platform/coda/coda-jpeg.c | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 3cfd4368e9a9..3cd47ba26357 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1543,11 +1543,13 @@ static void coda_pic_run_work(struct work_struct *work) if (!wait_for_completion_timeout(&ctx->completion, msecs_to_jiffies(1000))) { - dev_err(dev->dev, "CODA PIC_RUN timeout\n"); + if (ctx->use_bit) { + dev_err(dev->dev, "CODA PIC_RUN timeout\n"); - ctx->hold = true; + ctx->hold = true; - coda_hw_reset(ctx); + coda_hw_reset(ctx); + } if (ctx->ops->run_timeout) ctx->ops->run_timeout(ctx); diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c index b11cfbe166dd..a72f4655e5ad 100644 --- a/drivers/media/platform/coda/coda-jpeg.c +++ b/drivers/media/platform/coda/coda-jpeg.c @@ -1127,7 +1127,8 @@ static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx) coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR); coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR); coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR); - coda_write(dev, 0, CODA9_REG_JPEG_BBC_STRM_CTRL); + coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256), + CODA9_REG_JPEG_BBC_STRM_CTRL); coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL); coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR); coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER); @@ -1257,6 +1258,23 @@ static void coda9_jpeg_finish_encode(struct coda_ctx *ctx) coda_hw_reset(ctx); } +static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx) +{ + struct coda_dev *dev = ctx->dev; + u32 end_addr, wr_ptr; + + /* Handle missing BBC overflow interrupt via timeout */ + end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR); + wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR); + if (wr_ptr >= end_addr - 256) { + v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n"); + coda9_jpeg_finish_encode(ctx); + return; + } + + coda_hw_reset(ctx); +} + static void coda9_jpeg_release(struct coda_ctx *ctx) { int i; @@ -1276,6 +1294,7 @@ const struct coda_context_ops coda9_jpeg_encode_ops = { .start_streaming = coda9_jpeg_start_encoding, .prepare_run = coda9_jpeg_prepare_encode, .finish_run = coda9_jpeg_finish_encode, + .run_timeout = coda9_jpeg_encode_timeout, .release = coda9_jpeg_release, }; From 2ddd03309433d39852945c2f85d36e796c558793 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 Nov 2021 11:38:57 +0100 Subject: [PATCH 283/397] media: cec: safely unhook lists in cec_data smatch warns about data->list not being removed from list: drivers/media/cec/core/cec-adap.c:926 cec_transmit_msg_fh() warn: '&data->list' not removed from list It is a false warning, but it doesn't hurt to make the code more robust and safely unhook data->list and data->xfer_list together with a WARN_ON if this is actually ever needed (this really shouldn't happen). Note that fixing the data->list warning just replaced it with a new similar warning for data->xfer_list, so both needed to be addressed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/core/cec-adap.c | 8 +++++++- drivers/media/cec/core/cec-api.c | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c index 79fa36de8a04..da73eb50cce2 100644 --- a/drivers/media/cec/core/cec-adap.c +++ b/drivers/media/cec/core/cec-adap.c @@ -342,7 +342,7 @@ static void cec_data_completed(struct cec_data *data) * Without that we would be referring to a closed filehandle. */ if (data->fh) - list_del(&data->xfer_list); + list_del_init(&data->xfer_list); if (data->blocking) { /* @@ -898,6 +898,8 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, if (fh) list_add_tail(&data->xfer_list, &fh->xfer_list); + else + INIT_LIST_HEAD(&data->xfer_list); list_add_tail(&data->list, &adap->transmit_queue); adap->transmit_queue_sz++; @@ -923,6 +925,10 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, /* The transmit completed (possibly with an error) */ *msg = data->msg; + if (WARN_ON(!list_empty(&data->list))) + list_del(&data->list); + if (WARN_ON(!list_empty(&data->xfer_list))) + list_del(&data->xfer_list); kfree(data); return 0; } diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c index 769e6b4cddce..0edb7142afdb 100644 --- a/drivers/media/cec/core/cec-api.c +++ b/drivers/media/cec/core/cec-api.c @@ -669,7 +669,7 @@ static int cec_release(struct inode *inode, struct file *filp) data->blocking = false; data->fh = NULL; - list_del(&data->xfer_list); + list_del_init(&data->xfer_list); } mutex_unlock(&adap->lock); while (!list_empty(&fh->msgs)) { From 339df438759a1e92de91896173c426a59692d5d0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 Nov 2021 11:34:24 +0100 Subject: [PATCH 284/397] media: pvrusb2: fix inconsistent indenting Fix these smatch warnings: drivers/media/usb/pvrusb2/pvrusb2-encoder.c:288 pvr2_encoder_cmd() warn: inconsistent indenting drivers/media/usb/pvrusb2/pvrusb2-hdw.c:1730 pvr2_hdw_set_streaming() warn: inconsistent indenting drivers/media/usb/pvrusb2/pvrusb2-hdw.c:3461 pvr2_hdw_cpufw_set_enabled() warn: inconsistent indenting drivers/media/usb/pvrusb2/pvrusb2-hdw.c:3501 pvr2_hdw_cpufw_get() warn: inconsistent indenting Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-encoder.c | 4 +-- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 33 +++++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-encoder.c b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c index f6005d1296ef..c8102772344b 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c @@ -188,8 +188,8 @@ static int pvr2_encoder_cmd(void *ctxt, } - LOCK_TAKE(hdw->ctl_lock); while (1) { - + LOCK_TAKE(hdw->ctl_lock); + while (1) { if (!hdw->state_encoder_ok) { ret = -EIO; break; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 3915d551d59e..cd7b118d5929 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -1718,16 +1718,16 @@ int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw) int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag) { int ret,st; - LOCK_TAKE(hdw->big_lock); do { - pvr2_hdw_untrip_unlocked(hdw); - if ((!enable_flag) != !(hdw->state_pipeline_req)) { - hdw->state_pipeline_req = enable_flag != 0; - pvr2_trace(PVR2_TRACE_START_STOP, - "/*--TRACE_STREAM--*/ %s", - enable_flag ? "enable" : "disable"); - } - pvr2_hdw_state_sched(hdw); - } while (0); LOCK_GIVE(hdw->big_lock); + LOCK_TAKE(hdw->big_lock); + pvr2_hdw_untrip_unlocked(hdw); + if (!enable_flag != !hdw->state_pipeline_req) { + hdw->state_pipeline_req = enable_flag != 0; + pvr2_trace(PVR2_TRACE_START_STOP, + "/*--TRACE_STREAM--*/ %s", + enable_flag ? "enable" : "disable"); + } + pvr2_hdw_state_sched(hdw); + LOCK_GIVE(hdw->big_lock); if ((ret = pvr2_hdw_wait(hdw,0)) < 0) return ret; if (enable_flag) { while ((st = hdw->master_state) != PVR2_STATE_RUN) { @@ -3394,7 +3394,8 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int ret; u16 address; unsigned int pipe; - LOCK_TAKE(hdw->big_lock); do { + LOCK_TAKE(hdw->big_lock); + do { if ((hdw->fw_buffer == NULL) == !enable_flag) break; if (!enable_flag) { @@ -3457,8 +3458,8 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, pvr2_trace(PVR2_TRACE_FIRMWARE, "Done sucking down EEPROM contents"); } - - } while (0); LOCK_GIVE(hdw->big_lock); + } while (0); + LOCK_GIVE(hdw->big_lock); } @@ -3473,7 +3474,8 @@ int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs, char *buf,unsigned int cnt) { int ret = -EINVAL; - LOCK_TAKE(hdw->big_lock); do { + LOCK_TAKE(hdw->big_lock); + do { if (!buf) break; if (!cnt) break; @@ -3498,7 +3500,8 @@ int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs, "Read firmware data offs=%d cnt=%d", offs,cnt); ret = cnt; - } while (0); LOCK_GIVE(hdw->big_lock); + } while (0); + LOCK_GIVE(hdw->big_lock); return ret; } From d2ad087a0920ba5955634bf78cc8511bf120b758 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Mar 2021 09:12:47 +0100 Subject: [PATCH 285/397] media: omap3isp.h: fix kernel-doc warnings Add missing documentation for two field. This fixes these kernel-doc warnings: drivers/media/platform/omap3isp/omap3isp.h:107: warning: Function parameter or member 'vp_clk_pol' not described in 'isp_ccp2_cfg' drivers/media/platform/omap3isp/omap3isp.h:107: warning: Function parameter or member 'lanecfg' not described in 'isp_ccp2_cfg' Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/omap3isp.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/omap3isp/omap3isp.h b/drivers/media/platform/omap3isp/omap3isp.h index 214f94c46a9d..4a003c8263ed 100644 --- a/drivers/media/platform/omap3isp/omap3isp.h +++ b/drivers/media/platform/omap3isp/omap3isp.h @@ -95,6 +95,8 @@ struct isp_csiphy_lanes_cfg { * ISP_CCP2_PHY_DATA_CLOCK - Data/clock physical layer * ISP_CCP2_PHY_DATA_STROBE - Data/strobe physical layer * @vpclk_div: Video port output clock control + * @vp_clk_pol: Video port output clock polarity + * @lanecfg: CCP2/CSI2 lane configuration */ struct isp_ccp2_cfg { unsigned int strobe_clk_pol:1; From be25b0435b430ac4545b340488c3b5d4b24975f5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 25 Nov 2021 11:15:12 +0100 Subject: [PATCH 286/397] media: libv4l-introduction.rst: fix undefined label V4L2_PIX_FMT_HM12 was redefined to V4L2_PIX_FMT_NV12_16L16, so use the new name in libv4l-introduction.rst. This fixes this warning: libv4l-introduction.rst:27: WARNING: undefined label: v4l2-pix-fmt-hm12 Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/userspace-api/media/v4l/libv4l-introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/userspace-api/media/v4l/libv4l-introduction.rst b/Documentation/userspace-api/media/v4l/libv4l-introduction.rst index 05690f2358ce..90215313b965 100644 --- a/Documentation/userspace-api/media/v4l/libv4l-introduction.rst +++ b/Documentation/userspace-api/media/v4l/libv4l-introduction.rst @@ -26,7 +26,7 @@ found in V4L2 drivers into a few common RGB and YUY formats. It currently accepts the following V4L2 driver formats: :ref:`V4L2_PIX_FMT_BGR24 `, -:ref:`V4L2_PIX_FMT_HM12 `, +:ref:`V4L2_PIX_FMT_NV12_16L16 `, :ref:`V4L2_PIX_FMT_JPEG `, :ref:`V4L2_PIX_FMT_MJPEG `, :ref:`V4L2_PIX_FMT_MR97310A `, From b1f9bb8020783a48151e3a2864fbdc70548566dd Mon Sep 17 00:00:00 2001 From: Mansur Alisha Shaik Date: Wed, 27 Oct 2021 08:21:12 +0200 Subject: [PATCH 287/397] media: venus: correct low power frequency calculation for encoder In exististing implimentation, in min_loaded_core() for low_power vpp frequency value is considering as vpp_freq instead of low_power_freq. Fixed this by correcting vpp frequency calculation for encoder. Fixes: 3cfe5815ce0e (media: venus: Enable low power setting for encoder) Signed-off-by: Mansur Alisha Shaik Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/pm_helpers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index cedc664ba755..184f0cea2fdb 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -587,8 +587,8 @@ min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load, bool lo if (inst->session_type == VIDC_SESSION_TYPE_DEC) vpp_freq = inst_pos->clk_data.vpp_freq; else if (inst->session_type == VIDC_SESSION_TYPE_ENC) - vpp_freq = low_power ? inst_pos->clk_data.vpp_freq : - inst_pos->clk_data.low_power_freq; + vpp_freq = low_power ? inst_pos->clk_data.low_power_freq : + inst_pos->clk_data.vpp_freq; else continue; From 91f2b7d269e5c885c38c7ffa261f5276bd42f907 Mon Sep 17 00:00:00 2001 From: Mansur Alisha Shaik Date: Mon, 8 Nov 2021 06:48:51 +0100 Subject: [PATCH 288/397] media: venus: avoid calling core_clk_setrate() concurrently during concurrent video sessions In existing implementation, core_clk_setrate() is getting called concurrently in concurrent video sessions. Before the previous call to core_clk_setrate returns, new call to core_clk_setrate is invoked from another video session running concurrently. This results in latest calculated frequency being set (higher/lower) instead of actual frequency required for that video session. It also results in stability crashes mention below. These resources are specific to video core, hence keeping under core lock would ensure that they are estimated for all running video sessions and called once for the video core. Crash logs: [ 1.900089] WARNING: CPU: 4 PID: 1 at drivers/opp/debugfs.c:33 opp_debug_remove_one+0x2c/0x48 [ 1.908493] Modules linked in: [ 1.911524] CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.10.67 #35 f8edb8c30cf2dd6838495dd9ef9be47af7f5f60c [ 1.921036] Hardware name: Qualcomm Technologies, Inc. sc7280 IDP SKU2 platform (DT) [ 1.928673] pstate: 60800009 (nZCv daif -PAN +UAO -TCO BTYPE=--) [ 1.934608] pc : opp_debug_remove_one+0x2c/0x48 [ 1.939080] lr : opp_debug_remove_one+0x2c/0x48 [ 1.943560] sp : ffffffc011d7b7f0 [ 1.946836] pmr_save: 000000e0 [ 1.949854] x29: ffffffc011d7b7f0 x28: ffffffc010733bbc [ 1.955104] x27: ffffffc010733ba8 x26: ffffff8083cedd00 [ 1.960355] x25: 0000000000000001 x24: 0000000000000000 [ 1.965603] x23: ffffff8083cc2878 x22: ffffff8083ceb900 [ 1.970852] x21: ffffff8083ceb910 x20: ffffff8083cc2800 [ 1.976101] x19: ffffff8083ceb900 x18: 00000000ffff0a10 [ 1.981352] x17: ffffff80837a5620 x16: 00000000000000ec [ 1.986601] x15: ffffffc010519ad4 x14: 0000000000000003 [ 1.991849] x13: 0000000000000004 x12: 0000000000000001 [ 1.997100] x11: c0000000ffffdfff x10: 00000000ffffffff [ 2.002348] x9 : d2627c580300dc00 x8 : d2627c580300dc00 [ 2.007596] x7 : 0720072007200720 x6 : ffffff80802ecf00 [ 2.012845] x5 : 0000000000190004 x4 : 0000000000000000 [ 2.018094] x3 : ffffffc011d7b478 x2 : ffffffc011d7b480 [ 2.023343] x1 : 00000000ffffdfff x0 : 0000000000000017 [ 2.028594] Call trace: [ 2.031022] opp_debug_remove_one+0x2c/0x48 [ 2.035160] dev_pm_opp_put+0x94/0xb0 [ 2.038780] _opp_remove_all+0x7c/0xc8 [ 2.042486] _opp_remove_all_static+0x54/0x7c [ 2.046796] dev_pm_opp_remove_table+0x74/0x98 [ 2.051183] devm_pm_opp_of_table_release+0x18/0x24 [ 2.056001] devm_action_release+0x1c/0x28 [ 2.060053] release_nodes+0x23c/0x2b8 [ 2.063760] devres_release_group+0xcc/0xd0 [ 2.067900] component_bind+0xac/0x168 [ 2.071608] component_bind_all+0x98/0x124 [ 2.075664] msm_drm_bind+0x1e8/0x678 [ 2.079287] try_to_bring_up_master+0x60/0x134 [ 2.083674] component_master_add_with_match+0xd8/0x120 [ 2.088834] msm_pdev_probe+0x20c/0x2a0 [ 2.092629] platform_drv_probe+0x9c/0xbc [ 2.096598] really_probe+0x11c/0x46c [ 2.100217] driver_probe_device+0x8c/0xf0 [ 2.104270] device_driver_attach+0x54/0x78 [ 2.108407] __driver_attach+0x48/0x148 [ 2.112201] bus_for_each_dev+0x88/0xd4 [ 2.115998] driver_attach+0x2c/0x38 [ 2.119534] bus_add_driver+0x10c/0x200 [ 2.123330] driver_register+0x6c/0x104 [ 2.127122] __platform_driver_register+0x4c/0x58 [ 2.131767] msm_drm_register+0x6c/0x70 [ 2.135560] do_one_initcall+0x64/0x23c [ 2.139357] do_initcall_level+0xac/0x15c [ 2.143321] do_initcalls+0x5c/0x9c [ 2.146778] do_basic_setup+0x2c/0x38 [ 2.150401] kernel_init_freeable+0xf8/0x15c [ 2.154622] kernel_init+0x1c/0x11c [ 2.158079] ret_from_fork+0x10/0x30 [ 2.161615] ---[ end trace a2cc45a0f784b212 ]--- [ 2.166272] Removing OPP: 300000000 Signed-off-by: Mansur Alisha Shaik Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/qcom/venus/pm_helpers.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index 184f0cea2fdb..cb48c5ff3dee 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -163,14 +163,12 @@ static u32 load_per_type(struct venus_core *core, u32 session_type) struct venus_inst *inst = NULL; u32 mbs_per_sec = 0; - mutex_lock(&core->lock); list_for_each_entry(inst, &core->instances, list) { if (inst->session_type != session_type) continue; mbs_per_sec += load_per_instance(inst); } - mutex_unlock(&core->lock); return mbs_per_sec; } @@ -219,14 +217,12 @@ static int load_scale_bw(struct venus_core *core) struct venus_inst *inst = NULL; u32 mbs_per_sec, avg, peak, total_avg = 0, total_peak = 0; - mutex_lock(&core->lock); list_for_each_entry(inst, &core->instances, list) { mbs_per_sec = load_per_instance(inst); mbs_to_bw(inst, mbs_per_sec, &avg, &peak); total_avg += avg; total_peak += peak; } - mutex_unlock(&core->lock); /* * keep minimum bandwidth vote for "video-mem" path, @@ -253,8 +249,9 @@ static int load_scale_v1(struct venus_inst *inst) struct device *dev = core->dev; u32 mbs_per_sec; unsigned int i; - int ret; + int ret = 0; + mutex_lock(&core->lock); mbs_per_sec = load_per_type(core, VIDC_SESSION_TYPE_ENC) + load_per_type(core, VIDC_SESSION_TYPE_DEC); @@ -279,17 +276,19 @@ set_freq: if (ret) { dev_err(dev, "failed to set clock rate %lu (%d)\n", freq, ret); - return ret; + goto exit; } ret = load_scale_bw(core); if (ret) { dev_err(dev, "failed to set bandwidth (%d)\n", ret); - return ret; + goto exit; } - return 0; +exit: + mutex_unlock(&core->lock); + return ret; } static int core_get_v1(struct venus_core *core) @@ -1116,13 +1115,13 @@ static int load_scale_v4(struct venus_inst *inst) struct device *dev = core->dev; unsigned long freq = 0, freq_core1 = 0, freq_core2 = 0; unsigned long filled_len = 0; - int i, ret; + int i, ret = 0; for (i = 0; i < inst->num_input_bufs; i++) filled_len = max(filled_len, inst->payloads[i]); if (inst->session_type == VIDC_SESSION_TYPE_DEC && !filled_len) - return 0; + return ret; freq = calculate_inst_freq(inst, filled_len); inst->clk_data.freq = freq; @@ -1138,7 +1137,6 @@ static int load_scale_v4(struct venus_inst *inst) freq_core2 += inst->clk_data.freq; } } - mutex_unlock(&core->lock); freq = max(freq_core1, freq_core2); @@ -1163,17 +1161,19 @@ set_freq: if (ret) { dev_err(dev, "failed to set clock rate %lu (%d)\n", freq, ret); - return ret; + goto exit; } ret = load_scale_bw(core); if (ret) { dev_err(dev, "failed to set bandwidth (%d)\n", ret); - return ret; + goto exit; } - return 0; +exit: + mutex_unlock(&core->lock); + return ret; } static const struct venus_pm_ops pm_ops_v4 = { From e4debea9be7d5db52bc6a565a4c02c3c6560d093 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 12 Aug 2021 07:14:22 +0200 Subject: [PATCH 289/397] media: venus: core: Fix a potential NULL pointer dereference in an error handling path The normal path of the function makes the assumption that 'pm_ops->core_power' may be NULL. We should make the same assumption in the error handling path or a NULL pointer dereference may occur. Add the missing test before calling 'pm_ops->core_power' Fixes: 9e8efdb57879 ("media: venus: core: vote for video-mem path") Signed-off-by: Christophe JAILLET Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index f5fa81896012..fd32385485fa 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -473,7 +473,8 @@ static __maybe_unused int venus_runtime_suspend(struct device *dev) err_video_path: icc_set_bw(core->cpucfg_path, kbps_to_icc(1000), 0); err_cpucfg_path: - pm_ops->core_power(core, POWER_ON); + if (pm_ops->core_power) + pm_ops->core_power(core, POWER_ON); return ret; } From 8cc7a1b2aca067397a016cdb971a5e6ad9b640c7 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 19 Aug 2021 22:05:28 +0200 Subject: [PATCH 290/397] media: venus: core: Fix a resource leak in the error handling path of 'venus_probe()' A successful 'of_platform_populate()' call should be balanced by a corresponding 'of_platform_depopulate()' call in the error handling path of the probe, as already done in the remove function. A successful 'venus_firmware_init()' call should be balanced by a corresponding 'venus_firmware_deinit()' call in the error handling path of the probe, as already done in the remove function. Update the error handling path accordingly. Fixes: f9799fcce4bb ("media: venus: firmware: register separate platform_device for firmware loader") Signed-off-by: Christophe JAILLET Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index fd32385485fa..877eca125803 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -350,11 +350,11 @@ static int venus_probe(struct platform_device *pdev) ret = venus_firmware_init(core); if (ret) - goto err_runtime_disable; + goto err_of_depopulate; ret = venus_boot(core); if (ret) - goto err_runtime_disable; + goto err_firmware_deinit; ret = hfi_core_resume(core, true); if (ret) @@ -386,6 +386,10 @@ err_dev_unregister: v4l2_device_unregister(&core->v4l2_dev); err_venus_shutdown: venus_shutdown(core); +err_firmware_deinit: + venus_firmware_deinit(core); +err_of_depopulate: + of_platform_depopulate(dev); err_runtime_disable: pm_runtime_put_noidle(dev); pm_runtime_set_suspended(dev); From 4b065060555b14c7a9b86c013a1c9bee8e8b6fbd Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 17 Sep 2021 13:49:30 +0200 Subject: [PATCH 291/397] media: uvcvideo: Fix memory leak of object map on error exit path Currently when the allocation of map->name fails the error exit path does not kfree the previously allocated object map. Fix this by setting ret to -ENOMEM and taking the free_map exit error path to ensure map is kfree'd. Addresses-Coverity: ("Resource leak") Fixes: 70fa906d6fce ("media: uvcvideo: Use control names from framework") Signed-off-by: Colin Ian King Reviewed-by: Ricardo Ribalda Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_v4l2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f4e4aff8ddf7..711556d13d03 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -44,8 +44,10 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain, if (v4l2_ctrl_get_name(map->id) == NULL) { map->name = kmemdup(xmap->name, sizeof(xmap->name), GFP_KERNEL); - if (!map->name) - return -ENOMEM; + if (!map->name) { + ret = -ENOMEM; + goto free_map; + } } memcpy(map->entity, xmap->entity, sizeof(map->entity)); map->selector = xmap->selector; From 8aa637bf6d70d2fb2ad4d708d8b9dd02b1c095df Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 26 Oct 2021 11:55:11 +0200 Subject: [PATCH 292/397] media: uvcvideo: fix division by zero at stream start Add the missing bulk-endpoint max-packet sanity check to uvc_video_start_transfer() to avoid division by zero in uvc_alloc_urb_buffers() in case a malicious device has broken descriptors (or when doing descriptor fuzz testing). Note that USB core will reject URBs submitted for endpoints with zero wMaxPacketSize but that drivers doing packet-size calculations still need to handle this (cf. commit 2548288b4fb0 ("USB: Fix: Don't skip endpoint descriptors with maxpacket=0")). Fixes: c0efd232929c ("V4L/DVB (8145a): USB Video Class driver") Cc: stable@vger.kernel.org # 2.6.26 Signed-off-by: Johan Hovold Reviewed-by: Kieran Bingham Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_video.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 9f37eaf28ce7..1b4cc934109e 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -1963,6 +1963,10 @@ static int uvc_video_start_transfer(struct uvc_streaming *stream, if (ep == NULL) return -EIO; + /* Reject broken descriptors. */ + if (usb_endpoint_maxp(&ep->desc) == 0) + return -EIO; + ret = uvc_init_video_bulk(stream, ep, gfp_flags); } From e82822fae93ffc2b48362bfbcdef2ad00eaf944b Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Fri, 12 Nov 2021 20:57:10 +0100 Subject: [PATCH 293/397] media: uvcvideo: Set the colorspace as sRGB if undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Never return V4L2_COLORSPACE_DEFAULT. From the standard: """ In the absence of this descriptor, or in the case of “Unspecified” values within the descriptor, color matching defaults will be assumed. The color matching defaults are compliant with sRGB since the BT.709 transfer function and the sRGB transfer function are very similar. """ Signed-off-by: Ricardo Ribalda Tested-by: James Hilliard Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 7c007426e082..57152648d8ae 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -256,7 +256,7 @@ static struct uvc_format_desc *uvc_format_by_guid(const u8 guid[16]) static enum v4l2_colorspace uvc_colorspace(const u8 primaries) { static const enum v4l2_colorspace colorprimaries[] = { - V4L2_COLORSPACE_DEFAULT, /* Unspecified */ + V4L2_COLORSPACE_SRGB, /* Unspecified */ V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_470_SYSTEM_M, V4L2_COLORSPACE_470_SYSTEM_BG, @@ -267,7 +267,7 @@ static enum v4l2_colorspace uvc_colorspace(const u8 primaries) if (primaries < ARRAY_SIZE(colorprimaries)) return colorprimaries[primaries]; - return V4L2_COLORSPACE_DEFAULT; /* Reserved */ + return V4L2_COLORSPACE_SRGB; /* Reserved */ } static enum v4l2_xfer_func uvc_xfer_func(const u8 transfer_characteristics) @@ -769,6 +769,8 @@ static int uvc_parse_format(struct uvc_device *dev, buflen -= buffer[0]; buffer += buffer[0]; + } else { + format->colorspace = V4L2_COLORSPACE_SRGB; } return buffer - start; From c8ed7d2f614cd8b315981d116c7a2fb01829500d Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Sun, 14 Nov 2021 09:52:36 +0100 Subject: [PATCH 294/397] media: uvcvideo: Increase UVC_CTRL_CONTROL_TIMEOUT to 5 seconds. Some uvc devices appear to require the maximum allowed USB timeout for GET_CUR/SET_CUR requests. So lets just bump the UVC control timeout to 5 seconds which is the same as the usb ctrl get/set defaults: USB_CTRL_GET_TIMEOUT 5000 USB_CTRL_SET_TIMEOUT 5000 It fixes the following runtime warnings: Failed to query (GET_CUR) UVC control 11 on unit 2: -110 (exp. 1). Failed to query (SET_CUR) UVC control 3 on unit 2: -110 (exp. 2). Signed-off-by: James Hilliard Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvcvideo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 2e5366143b81..143230b3275b 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -189,7 +189,7 @@ /* Maximum status buffer size in bytes of interrupt URB. */ #define UVC_MAX_STATUS_SIZE 16 -#define UVC_CTRL_CONTROL_TIMEOUT 500 +#define UVC_CTRL_CONTROL_TIMEOUT 5000 #define UVC_CTRL_STREAMING_TIMEOUT 5000 /* Maximum allowed number of control mappings per device */ From f0577b1b6394f954903fcc67e12fe9e7001dafd6 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Wed, 1 Dec 2021 06:22:17 +0100 Subject: [PATCH 295/397] media: uvcvideo: Avoid invalid memory access If mappings points to an invalid memory, we will be invalid accessing it. Solve it by initializing the value of the variable mapping and by changing the order in the conditional statement (to avoid accessing mapping->id if not needed). Fix: kasan: GPF could be caused by NULL-ptr deref or user memory access general protection fault: 0000 [#1] PREEMPT SMP KASAN NOPTI Fixes: 6350d6a4ed487 ("media: uvcvideo: Set error_idx during ctrl_commit errors") Signed-off-by: Ricardo Ribalda Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 30bfe9069a1f..9a25d6029255 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1638,7 +1638,7 @@ static int uvc_ctrl_find_ctrl_idx(struct uvc_entity *entity, struct v4l2_ext_controls *ctrls, struct uvc_control *uvc_control) { - struct uvc_control_mapping *mapping; + struct uvc_control_mapping *mapping = NULL; struct uvc_control *ctrl_found; unsigned int i; From 414d3b49d9fd4a0bb16a13d929027847fd094f3f Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Wed, 1 Dec 2021 06:22:18 +0100 Subject: [PATCH 296/397] media: uvcvideo: Avoid returning invalid controls If the memory where ctrl_found is placed has the value of uvc_ctrl and __uvc_find_control does not find the control we will return an invalid index. Fixes: 6350d6a4ed487 ("media: uvcvideo: Set error_idx during ctrl_commit errors") Signed-off-by: Ricardo Ribalda Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 9a25d6029255..b4f6edf968bc 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1639,7 +1639,7 @@ static int uvc_ctrl_find_ctrl_idx(struct uvc_entity *entity, struct uvc_control *uvc_control) { struct uvc_control_mapping *mapping = NULL; - struct uvc_control *ctrl_found; + struct uvc_control *ctrl_found = NULL; unsigned int i; if (!entity) From b925c1fdea01e1a96348d2aa75b5c74adc8d3187 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 19 Nov 2021 04:15:17 +0100 Subject: [PATCH 297/397] media: dt-bindings: media: Add compatible for D1 D1 contains a video engine similar to the one in other sunxi SoCs. Add a compatible for it. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Acked-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../bindings/media/allwinner,sun4i-a10-video-engine.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml index c34303b87a5b..c3de96d10396 100644 --- a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml +++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml @@ -20,6 +20,7 @@ properties: - allwinner,sun8i-h3-video-engine - allwinner,sun8i-v3s-video-engine - allwinner,sun8i-r40-video-engine + - allwinner,sun20i-d1-video-engine - allwinner,sun50i-a64-video-engine - allwinner,sun50i-h5-video-engine - allwinner,sun50i-h6-video-engine From 8f852ab8c39b1639d53b67548268785d47eca11f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 19 Nov 2021 04:15:18 +0100 Subject: [PATCH 298/397] media: cedrus: Add support for the D1 variant D1 has a unique variant of the video engine, which appears to drop the VP8 support found on most earlier variants. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/sunxi/cedrus/cedrus.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index c76fc97d97a0..4a4b714b0f26 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -580,6 +580,14 @@ static const struct cedrus_variant sun8i_r40_cedrus_variant = { .mod_rate = 297000000, }; +static const struct cedrus_variant sun20i_d1_cedrus_variant = { + .capabilities = CEDRUS_CAPABILITY_UNTILED | + CEDRUS_CAPABILITY_MPEG2_DEC | + CEDRUS_CAPABILITY_H264_DEC | + CEDRUS_CAPABILITY_H265_DEC, + .mod_rate = 432000000, +}; + static const struct cedrus_variant sun50i_a64_cedrus_variant = { .capabilities = CEDRUS_CAPABILITY_UNTILED | CEDRUS_CAPABILITY_MPEG2_DEC | @@ -637,6 +645,10 @@ static const struct of_device_id cedrus_dt_match[] = { .compatible = "allwinner,sun8i-r40-video-engine", .data = &sun8i_r40_cedrus_variant, }, + { + .compatible = "allwinner,sun20i-d1-video-engine", + .data = &sun20i_d1_cedrus_variant, + }, { .compatible = "allwinner,sun50i-a64-video-engine", .data = &sun50i_a64_cedrus_variant, From 30334d3d99e992c0d85791eed92e7196002f4d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 23 Nov 2021 16:54:43 +0100 Subject: [PATCH 299/397] media: rcar-vin: Add check for completed capture before completing buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before reading which slot was captured to by examining the module status (VnMS) register, make sure something was captured at all by examining the interrupt status register (VnINTS). Failing this a buffer maybe completed before it was captured too. Signed-off-by: Niklas Söderlund Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-dma.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 79bb9081853f..8136bc75e7c4 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -111,6 +111,9 @@ #define VNIE_FIE (1 << 4) #define VNIE_EFE (1 << 1) +/* Video n Interrupt Status Register bits */ +#define VNINTS_FIS (1 << 4) + /* Video n Data Mode Register bits */ #define VNDMR_A8BIT(n) (((n) & 0xff) << 24) #define VNDMR_A8BIT_MASK (0xff << 24) @@ -1005,6 +1008,10 @@ static irqreturn_t rvin_irq(int irq, void *data) rvin_ack_interrupt(vin); handled = 1; + /* Nothing to do if nothing was captured. */ + if (!(int_status & VNINTS_FIS)) + goto done; + /* Nothing to do if capture status is 'STOPPED' */ if (vin->state == STOPPED) { vin_dbg(vin, "IRQ while state stopped\n"); From d912740881d5f7c13247ec714e9bc59b7cc1aace Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 25 Nov 2021 16:42:10 +0100 Subject: [PATCH 300/397] media: hantro: drop unused vb2 headers hantro_v4l2.c includes media/videobuf2-dma-sg.h, which isn't used. And in fact, hantro doesn't use the vb2_dma_sg_memops at all, so this is confusing. Just drop both videobuf2 headers, they are not needed here. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_v4l2.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c index e4b0645ba6fc..c319f0e5fe60 100644 --- a/drivers/staging/media/hantro/hantro_v4l2.c +++ b/drivers/staging/media/hantro/hantro_v4l2.c @@ -23,8 +23,6 @@ #include #include #include -#include -#include #include "hantro.h" #include "hantro_hw.h" From da6911f330d40cfe115a37249e47643eff555e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Fri, 26 Nov 2021 00:02:57 +0100 Subject: [PATCH 301/397] media: rcar-vin: Update format alignment constraints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change fixes two issues with the size constraints for buffers. - There is no width alignment constraint for RGB formats. Prior to this change they were treated as YUV and as a result were more restricted than needed. Add a new check to differentiate between the two. - The minimum width and height supported is 5x2, not 2x4, this is an artifact from the driver's soc-camera days. Fix this incorrect assumption. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-v4l2.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index a5bfa76fdac6..2e60b9fce03b 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -179,20 +179,27 @@ static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix) break; } - /* HW limit width to a multiple of 32 (2^5) for NV12/16 else 2 (2^1) */ + /* Hardware limits width alignment based on format. */ switch (pix->pixelformat) { + /* Multiple of 32 (2^5) for NV12/16. */ case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV16: walign = 5; break; - default: + /* Multiple of 2 (2^1) for YUV. */ + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: walign = 1; break; + /* No multiple for RGB. */ + default: + walign = 0; + break; } /* Limit to VIN capabilities */ - v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign, - &pix->height, 4, vin->info->max_height, 2, 0); + v4l_bound_align_image(&pix->width, 5, vin->info->max_width, walign, + &pix->height, 2, vin->info->max_height, 0, 0); pix->bytesperline = rvin_format_bytesperline(vin, pix); pix->sizeimage = rvin_format_sizeimage(pix); From 0d7b74ef8df409f43f64e4193b36dc5b3f38029e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sun, 28 Nov 2021 14:24:26 +0100 Subject: [PATCH 302/397] media: rcar-csi2: Suppress bind and unbind nodes in sysfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v4l2-async framework's subdev notifiers do not behave correctly if a device in the middle of the pipeline is unbound and then rebound. The v4l2-subdevices upstream from the device being rebound gets confused as they receive no notification of the device unbound and can't cleanup their state and when they are rebound to the new v4l2-subdev notifier they try to reinitialize their internal state, this may include things as trying to create links that already exists and in some cases crash the system, for example the adv748x. This should be solved in the v4l2-async framework, but as a stop-gap measure suppress the bind and unbind sysfs nodes for the rcar-csi2 driver so it can't be used to crash the system. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-csi2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index e2c4ab69a477..8c939cb3073d 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -1516,6 +1516,7 @@ static struct platform_driver rcar_csi2_pdrv = { .probe = rcsi2_probe, .driver = { .name = "rcar-csi2", + .suppress_bind_attrs = true, .of_match_table = rcar_csi2_of_table, }, }; From e37e82188bc9114a9e285d003569dcad5f6d5612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sun, 28 Nov 2021 14:24:47 +0100 Subject: [PATCH 303/397] media: rcar-vin: Disallow unbinding and binding of individual VINs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VIN driver have an internal concept of capture groups that covers multiple instances of the driver. This is handled using the shared media graph and a single notifier shared between all VIN instances. This design do not work well if an individual VIN where to be unbound on its own. The design could be improved up on to allow for this but would require large changes in the v4l2-async framework. To avoid the situation suppress the bind and unbind nodes in sysfs. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 1d92cc8ede8f..6d4cffdbf47a 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -1620,6 +1620,7 @@ static SIMPLE_DEV_PM_OPS(rvin_pm_ops, rvin_suspend, rvin_resume); static struct platform_driver rcar_vin_driver = { .driver = { .name = "rcar-vin", + .suppress_bind_attrs = true, .pm = &rvin_pm_ops, .of_match_table = rvin_of_id_table, }, From 468613a67bcbc9ef63fe13ec7214c34e5c7b96ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sun, 28 Nov 2021 14:24:59 +0100 Subject: [PATCH 304/397] media: rcar-vin: Do not hold the group lock when unregistering notifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to hold the group lock when unregistering the notifier, but doing so triggers a warning about a possible cyclic lock dependency. The lock warning cover the case where a subdevice is about to be bound to the notifier at the same time as it's unregistered. The locking for this scenario is handled in the v4l2-async framework so it's safe to remove the lock in the driver. This match the locking logic in the driver for when the notifier in question is registered. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 6d4cffdbf47a..0186ae235113 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -349,12 +349,10 @@ out: static void rvin_group_notifier_cleanup(struct rvin_dev *vin) { - mutex_lock(&vin->group->lock); if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) { v4l2_async_nf_unregister(&vin->group->notifier); v4l2_async_nf_cleanup(&vin->group->notifier); } - mutex_unlock(&vin->group->lock); } static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port, From 8dbdcc7269a83305ee9d677b75064d3530a48ee2 Mon Sep 17 00:00:00 2001 From: Zhou Qingyang Date: Tue, 30 Nov 2021 16:38:05 +0100 Subject: [PATCH 305/397] media: dib8000: Fix a memleak in dib8000_init() In dib8000_init(), the variable fe is not freed or passed out on the failure of dib8000_identify(&state->i2c), which could lead to a memleak. Fix this bug by adding a kfree of fe in the error path. This bug was found by a static analyzer. The analysis employs differential checking to identify inconsistent security operations (e.g., checks or kfrees) between two code paths and confirms that the inconsistent operations are not recovered in the current function or the callers, so they constitute bugs. Note that, as a bug found by static analysis, it can be a false positive or hard to trigger. Multiple researchers have cross-reviewed the bug. Builds with CONFIG_DVB_DIB8000=m show no new warnings, and our static analyzer no longer warns about this code. Fixes: 77e2c0f5d471 ("V4L/DVB (12900): DiB8000: added support for DiBcom ISDB-T/ISDB-Tsb demodulator DiB8000") Signed-off-by: Zhou Qingyang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/dib8000.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index bb02354a48b8..d67f2dd997d0 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -4473,8 +4473,10 @@ static struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_ad state->timf_default = cfg->pll->timf; - if (dib8000_identify(&state->i2c) == 0) + if (dib8000_identify(&state->i2c) == 0) { + kfree(fe); goto error; + } dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr); From 348df8035301dd212e3cc2860efe4c86cb0d3303 Mon Sep 17 00:00:00 2001 From: Zhou Qingyang Date: Tue, 30 Nov 2021 17:25:49 +0100 Subject: [PATCH 306/397] media: saa7146: hexium_orion: Fix a NULL pointer dereference in hexium_attach() In hexium_attach(dev, info), saa7146_vv_init() is called to allocate a new memory for dev->vv_data. In hexium_detach(), saa7146_vv_release() will be called and there is a dereference of dev->vv_data in saa7146_vv_release(), which could lead to a NULL pointer dereference on failure of saa7146_vv_init() according to the following logic. Both hexium_attach() and hexium_detach() are callback functions of the variable 'extension', so there exists a possible call chain directly from hexium_attach() to hexium_detach(): hexium_attach(dev, info) -- fail to alloc memory to dev->vv_data | in saa7146_vv_init(). | | hexium_detach() -- a dereference of dev->vv_data in saa7146_vv_release() Fix this bug by adding a check of saa7146_vv_init(). This bug was found by a static analyzer. The analysis employs differential checking to identify inconsistent security operations (e.g., checks or kfrees) between two code paths and confirms that the inconsistent operations are not recovered in the current function or the callers, so they constitute bugs. Note that, as a bug found by static analysis, it can be a false positive or hard to trigger. Multiple researchers have cross-reviewed the bug. Builds with CONFIG_VIDEO_HEXIUM_ORION=m show no new warnings, and our static analyzer no longer warns about this code. Signed-off-by: Zhou Qingyang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7146/hexium_orion.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c index 39d14c179d22..2eb4bee16b71 100644 --- a/drivers/media/pci/saa7146/hexium_orion.c +++ b/drivers/media/pci/saa7146/hexium_orion.c @@ -355,10 +355,16 @@ static struct saa7146_ext_vv vv_data; static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { struct hexium *hexium = (struct hexium *) dev->ext_priv; + int ret; DEB_EE("\n"); - saa7146_vv_init(dev, &vv_data); + ret = saa7146_vv_init(dev, &vv_data); + if (ret) { + pr_err("Error in saa7146_vv_init()\n"); + return ret; + } + vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input; vv_data.vid_ops.vidioc_g_input = vidioc_g_input; vv_data.vid_ops.vidioc_s_input = vidioc_s_input; From 0407c49ebe330333478440157c640fffd986f41b Mon Sep 17 00:00:00 2001 From: Zhou Qingyang Date: Tue, 30 Nov 2021 17:34:44 +0100 Subject: [PATCH 307/397] media: saa7146: mxb: Fix a NULL pointer dereference in mxb_attach() In mxb_attach(dev, info), saa7146_vv_init() is called to allocate a new memory for dev->vv_data. saa7146_vv_release() will be called on failure of mxb_probe(dev). There is a dereference of dev->vv_data in saa7146_vv_release(), which could lead to a NULL pointer dereference on failure of saa7146_vv_init(). Fix this bug by adding a check of saa7146_vv_init(). This bug was found by a static analyzer. The analysis employs differential checking to identify inconsistent security operations (e.g., checks or kfrees) between two code paths and confirms that the inconsistent operations are not recovered in the current function or the callers, so they constitute bugs. Note that, as a bug found by static analysis, it can be a false positive or hard to trigger. Multiple researchers have cross-reviewed the bug. Builds with CONFIG_VIDEO_MXB=m show no new warnings, and our static analyzer no longer warns about this code. Fixes: 03b1930efd3c ("V4L/DVB: saa7146: fix regression of the av7110/budget-av driver") Signed-off-by: Zhou Qingyang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7146/mxb.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index 73fc901ecf3d..bf0b9b0914cd 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -683,10 +683,16 @@ static struct saa7146_ext_vv vv_data; static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { struct mxb *mxb; + int ret; DEB_EE("dev:%p\n", dev); - saa7146_vv_init(dev, &vv_data); + ret = saa7146_vv_init(dev, &vv_data); + if (ret) { + ERR("Error in saa7146_vv_init()"); + return ret; + } + if (mxb_probe(dev)) { saa7146_vv_release(dev); return -1; From cf56f4f2a4ec7370b28e05cb4d228ffa7b65abbd Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Tue, 30 Nov 2021 22:27:00 +0100 Subject: [PATCH 308/397] media: s5p-jpeg: Constify struct v4l2_m2m_ops The only usage of the v4l2_m2m_ops structs is to pass their address to v4l2_m2m_init() which takes a pointer to const struct v4l2_m2m_ops as argument. Make them const to allow the compiler to put them in read-only memory. Signed-off-by: Rikard Falkeborn Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-jpeg/jpeg-core.c | 6 +++--- drivers/media/platform/s5p-jpeg/jpeg-core.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index ebdfd24e9cd5..a8d9159d5ed8 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2425,17 +2425,17 @@ static int s5p_jpeg_job_ready(void *priv) return 1; } -static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = { +static const struct v4l2_m2m_ops s5p_jpeg_m2m_ops = { .device_run = s5p_jpeg_device_run, .job_ready = s5p_jpeg_job_ready, }; -static struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = { +static const struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = { .device_run = exynos3250_jpeg_device_run, .job_ready = s5p_jpeg_job_ready, }; -static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = { +static const struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = { .device_run = exynos4_jpeg_device_run, .job_ready = s5p_jpeg_job_ready, }; diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h index 8473a019bb5f..4a5fb1b15455 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h @@ -142,7 +142,7 @@ struct s5p_jpeg_variant { unsigned int hw3250_compat:1; unsigned int htbl_reinit:1; unsigned int hw_ex4_compat:1; - struct v4l2_m2m_ops *m2m_ops; + const struct v4l2_m2m_ops *m2m_ops; irqreturn_t (*jpeg_irq)(int irq, void *priv); const char *clk_names[JPEG_MAX_CLOCKS]; int num_clocks; From 3a2e4b193690ff2e44e95856d90bdeaf337211f6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Dec 2021 13:28:55 +0100 Subject: [PATCH 309/397] media: cec-pin: drop unused 'enabled' field from struct cec_pin This field is only set, but never used. Drop it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/core/cec-pin-priv.h | 1 - drivers/media/cec/core/cec-pin.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/media/cec/core/cec-pin-priv.h b/drivers/media/cec/core/cec-pin-priv.h index fb101f15865c..7bad5a0b7cb7 100644 --- a/drivers/media/cec/core/cec-pin-priv.h +++ b/drivers/media/cec/core/cec-pin-priv.h @@ -170,7 +170,6 @@ struct cec_pin { ktime_t ts; unsigned int wait_usecs; u16 la_mask; - bool enabled; bool monitor_all; bool rx_eom; bool enable_irq_failed; diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c index a60b6f03a6a1..2b6459df1e94 100644 --- a/drivers/media/cec/core/cec-pin.c +++ b/drivers/media/cec/core/cec-pin.c @@ -1111,7 +1111,6 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable) { struct cec_pin *pin = adap->pin; - pin->enabled = enable; if (enable) { atomic_set(&pin->work_pin_num_events, 0); pin->work_pin_events_rd = pin->work_pin_events_wr = 0; From 713bdfa10b5957053811470d298def9537d9ff13 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Dec 2021 13:41:25 +0100 Subject: [PATCH 310/397] media: cec-pin: fix interrupt en/disable handling The en/disable_irq() functions keep track of the 'depth': i.e. if interrupts are disabled twice, then it needs to enable_irq() calls to enable them again. The cec-pin framework didn't take this into accound and could disable irqs multiple times, and it expected that a single enable_irq() would enable them again. Move all calls to en/disable_irq() to the kthread where it is easy to keep track of the current irq state and ensure that multiple en/disable_irq calls never happen. If interrupts where disabled twice, then they would never turn on again, leaving the CEC adapter in a dead state. Signed-off-by: Hans Verkuil Fixes: 865463fc03ed (media: cec-pin: add error injection support) Cc: Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/core/cec-pin.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c index 2b6459df1e94..21f0f749713e 100644 --- a/drivers/media/cec/core/cec-pin.c +++ b/drivers/media/cec/core/cec-pin.c @@ -1033,6 +1033,7 @@ static int cec_pin_thread_func(void *_adap) { struct cec_adapter *adap = _adap; struct cec_pin *pin = adap->pin; + bool irq_enabled = false; for (;;) { wait_event_interruptible(pin->kthread_waitq, @@ -1060,6 +1061,7 @@ static int cec_pin_thread_func(void *_adap) ns_to_ktime(pin->work_rx_msg.rx_ts)); msg->len = 0; } + if (pin->work_tx_status) { unsigned int tx_status = pin->work_tx_status; @@ -1083,27 +1085,39 @@ static int cec_pin_thread_func(void *_adap) switch (atomic_xchg(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED)) { case CEC_PIN_IRQ_DISABLE: - pin->ops->disable_irq(adap); + if (irq_enabled) { + pin->ops->disable_irq(adap); + irq_enabled = false; + } cec_pin_high(pin); cec_pin_to_idle(pin); hrtimer_start(&pin->timer, ns_to_ktime(0), HRTIMER_MODE_REL); break; case CEC_PIN_IRQ_ENABLE: + if (irq_enabled) + break; pin->enable_irq_failed = !pin->ops->enable_irq(adap); if (pin->enable_irq_failed) { cec_pin_to_idle(pin); hrtimer_start(&pin->timer, ns_to_ktime(0), HRTIMER_MODE_REL); + } else { + irq_enabled = true; } break; default: break; } - if (kthread_should_stop()) break; } + if (pin->ops->disable_irq && irq_enabled) + pin->ops->disable_irq(adap); + hrtimer_cancel(&pin->timer); + cec_pin_read(pin); + cec_pin_to_idle(pin); + pin->state = CEC_ST_OFF; return 0; } @@ -1129,13 +1143,7 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable) hrtimer_start(&pin->timer, ns_to_ktime(0), HRTIMER_MODE_REL); } else { - if (pin->ops->disable_irq) - pin->ops->disable_irq(adap); - hrtimer_cancel(&pin->timer); kthread_stop(pin->kthread); - cec_pin_read(pin); - cec_pin_to_idle(pin); - pin->state = CEC_ST_OFF; } return 0; } @@ -1156,11 +1164,8 @@ void cec_pin_start_timer(struct cec_pin *pin) if (pin->state != CEC_ST_RX_IRQ) return; - atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED); - pin->ops->disable_irq(pin->adap); - cec_pin_high(pin); - cec_pin_to_idle(pin); - hrtimer_start(&pin->timer, ns_to_ktime(0), HRTIMER_MODE_REL); + atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_DISABLE); + wake_up_interruptible(&pin->kthread_waitq); } static int cec_pin_adap_transmit(struct cec_adapter *adap, u8 attempts, From a9e6107616bb8108aa4fc22584a05e69761a91f7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Dec 2021 13:41:26 +0100 Subject: [PATCH 311/397] media: cec: fix a deadlock situation The cec_devnode struct has a lock meant to serialize access to the fields of this struct. This lock is taken during device node (un)registration and when opening or releasing a filehandle to the device node. When the last open filehandle is closed the cec adapter might be disabled by calling the adap_enable driver callback with the devnode.lock held. However, if during that callback a message or event arrives then the driver will call one of the cec_queue_event() variants in cec-adap.c, and those will take the same devnode.lock to walk the open filehandle list. This obviously causes a deadlock. This is quite easy to reproduce with the cec-gpio driver since that uses the cec-pin framework which generated lots of events and uses a kernel thread for the processing, so when adap_enable is called the thread is still running and can generate events. But I suspect that it might also happen with other drivers if an interrupt arrives signaling e.g. a received message before adap_enable had a chance to disable the interrupts. This patch adds a new mutex to serialize access to the fhs list. When adap_enable() is called the devnode.lock mutex is held, but not devnode.lock_fhs. The event functions in cec-adap.c will now use devnode.lock_fhs instead of devnode.lock, ensuring that it is safe to call those functions from the adap_enable callback. This specific issue only happens if the last open filehandle is closed and the physical address is invalid. This is not something that happens during normal operation, but it does happen when monitoring CEC traffic (e.g. cec-ctl --monitor) with an unconfigured CEC adapter. Signed-off-by: Hans Verkuil Cc: # for v5.13 and up Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/core/cec-adap.c | 38 +++++++++++++++++-------------- drivers/media/cec/core/cec-api.c | 6 +++++ drivers/media/cec/core/cec-core.c | 3 +++ include/media/cec.h | 11 +++++++-- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c index 0546650b3853..2e12331c12a9 100644 --- a/drivers/media/cec/core/cec-adap.c +++ b/drivers/media/cec/core/cec-adap.c @@ -161,10 +161,10 @@ static void cec_queue_event(struct cec_adapter *adap, u64 ts = ktime_get_ns(); struct cec_fh *fh; - mutex_lock(&adap->devnode.lock); + mutex_lock(&adap->devnode.lock_fhs); list_for_each_entry(fh, &adap->devnode.fhs, list) cec_queue_event_fh(fh, ev, ts); - mutex_unlock(&adap->devnode.lock); + mutex_unlock(&adap->devnode.lock_fhs); } /* Notify userspace that the CEC pin changed state at the given time. */ @@ -178,11 +178,12 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high, }; struct cec_fh *fh; - mutex_lock(&adap->devnode.lock); - list_for_each_entry(fh, &adap->devnode.fhs, list) + mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) { if (fh->mode_follower == CEC_MODE_MONITOR_PIN) cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); - mutex_unlock(&adap->devnode.lock); + } + mutex_unlock(&adap->devnode.lock_fhs); } EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event); @@ -195,10 +196,10 @@ void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts) }; struct cec_fh *fh; - mutex_lock(&adap->devnode.lock); + mutex_lock(&adap->devnode.lock_fhs); list_for_each_entry(fh, &adap->devnode.fhs, list) cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); - mutex_unlock(&adap->devnode.lock); + mutex_unlock(&adap->devnode.lock_fhs); } EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event); @@ -211,10 +212,10 @@ void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts) }; struct cec_fh *fh; - mutex_lock(&adap->devnode.lock); + mutex_lock(&adap->devnode.lock_fhs); list_for_each_entry(fh, &adap->devnode.fhs, list) cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); - mutex_unlock(&adap->devnode.lock); + mutex_unlock(&adap->devnode.lock_fhs); } EXPORT_SYMBOL_GPL(cec_queue_pin_5v_event); @@ -286,12 +287,12 @@ static void cec_queue_msg_monitor(struct cec_adapter *adap, u32 monitor_mode = valid_la ? CEC_MODE_MONITOR : CEC_MODE_MONITOR_ALL; - mutex_lock(&adap->devnode.lock); + mutex_lock(&adap->devnode.lock_fhs); list_for_each_entry(fh, &adap->devnode.fhs, list) { if (fh->mode_follower >= monitor_mode) cec_queue_msg_fh(fh, msg); } - mutex_unlock(&adap->devnode.lock); + mutex_unlock(&adap->devnode.lock_fhs); } /* @@ -302,12 +303,12 @@ static void cec_queue_msg_followers(struct cec_adapter *adap, { struct cec_fh *fh; - mutex_lock(&adap->devnode.lock); + mutex_lock(&adap->devnode.lock_fhs); list_for_each_entry(fh, &adap->devnode.fhs, list) { if (fh->mode_follower == CEC_MODE_FOLLOWER) cec_queue_msg_fh(fh, msg); } - mutex_unlock(&adap->devnode.lock); + mutex_unlock(&adap->devnode.lock_fhs); } /* Notify userspace of an adapter state change. */ @@ -1579,6 +1580,7 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) /* Disabling monitor all mode should always succeed */ if (adap->monitor_all_cnt) WARN_ON(call_op(adap, adap_monitor_all_enable, false)); + /* serialize adap_enable */ mutex_lock(&adap->devnode.lock); if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) { WARN_ON(adap->ops->adap_enable(adap, false)); @@ -1590,14 +1592,16 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) return; } + /* serialize adap_enable */ mutex_lock(&adap->devnode.lock); adap->last_initiator = 0xff; adap->transmit_in_progress = false; - if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) && - adap->ops->adap_enable(adap, true)) { - mutex_unlock(&adap->devnode.lock); - return; + if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) { + if (adap->ops->adap_enable(adap, true)) { + mutex_unlock(&adap->devnode.lock); + return; + } } if (adap->monitor_all_cnt && diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c index 0edb7142afdb..d72ad48c9898 100644 --- a/drivers/media/cec/core/cec-api.c +++ b/drivers/media/cec/core/cec-api.c @@ -586,6 +586,7 @@ static int cec_open(struct inode *inode, struct file *filp) return err; } + /* serialize adap_enable */ mutex_lock(&devnode->lock); if (list_empty(&devnode->fhs) && !adap->needs_hpd && @@ -624,7 +625,9 @@ static int cec_open(struct inode *inode, struct file *filp) } #endif + mutex_lock(&devnode->lock_fhs); list_add(&fh->list, &devnode->fhs); + mutex_unlock(&devnode->lock_fhs); mutex_unlock(&devnode->lock); return 0; @@ -653,8 +656,11 @@ static int cec_release(struct inode *inode, struct file *filp) cec_monitor_all_cnt_dec(adap); mutex_unlock(&adap->lock); + /* serialize adap_enable */ mutex_lock(&devnode->lock); + mutex_lock(&devnode->lock_fhs); list_del(&fh->list); + mutex_unlock(&devnode->lock_fhs); if (cec_is_registered(adap) && list_empty(&devnode->fhs) && !adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) { WARN_ON(adap->ops->adap_enable(adap, false)); diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c index 551689d371a7..ec67065d5202 100644 --- a/drivers/media/cec/core/cec-core.c +++ b/drivers/media/cec/core/cec-core.c @@ -169,8 +169,10 @@ static void cec_devnode_unregister(struct cec_adapter *adap) devnode->registered = false; devnode->unregistered = true; + mutex_lock(&devnode->lock_fhs); list_for_each_entry(fh, &devnode->fhs, list) wake_up_interruptible(&fh->wait); + mutex_unlock(&devnode->lock_fhs); mutex_unlock(&devnode->lock); @@ -272,6 +274,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, /* adap->devnode initialization */ INIT_LIST_HEAD(&adap->devnode.fhs); + mutex_init(&adap->devnode.lock_fhs); mutex_init(&adap->devnode.lock); adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name); diff --git a/include/media/cec.h b/include/media/cec.h index 208c9613c07e..77346f757036 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -26,13 +26,17 @@ * @dev: cec device * @cdev: cec character device * @minor: device node minor number + * @lock: lock to serialize open/release and registration * @registered: the device was correctly registered * @unregistered: the device was unregistered + * @lock_fhs: lock to control access to @fhs * @fhs: the list of open filehandles (cec_fh) - * @lock: lock to control access to this structure * * This structure represents a cec-related device node. * + * To add or remove filehandles from @fhs the @lock must be taken first, + * followed by @lock_fhs. It is safe to access @fhs if either lock is held. + * * The @parent is a physical device. It must be set by core or device drivers * before registering the node. */ @@ -43,10 +47,13 @@ struct cec_devnode { /* device info */ int minor; + /* serialize open/release and registration */ + struct mutex lock; bool registered; bool unregistered; + /* protect access to fhs */ + struct mutex lock_fhs; struct list_head fhs; - struct mutex lock; }; struct cec_adapter; From 05fd87b8d9a6070f4ac9858cfd644e15a3e9c569 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 1 Dec 2021 23:56:50 +0100 Subject: [PATCH 312/397] media: replace setting of bytesused with vb2_set_plane_payload In many places the bytesused field of struct vb2_buffer is set directly. Replace that with the function call vb2_set_plane_payload Signed-off-by: Dafna Hirschfeld Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/allegro-dvt/allegro-core.c | 2 +- drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 10 +++++----- drivers/media/test-drivers/vicodec/vicodec-core.c | 2 +- drivers/media/usb/go7007/go7007-driver.c | 2 +- drivers/staging/media/meson/vdec/vdec_helpers.c | 10 +++++----- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c index c8156da33043..4a3d06c70e34 100644 --- a/drivers/media/platform/allegro-dvt/allegro-core.c +++ b/drivers/media/platform/allegro-dvt/allegro-core.c @@ -2815,7 +2815,7 @@ static void allegro_buf_queue(struct vb2_buffer *vb) unsigned int i; for (i = 0; i < vb->num_planes; i++) - vb->planes[i].bytesused = 0; + vb2_set_plane_payload(vb, i, 0); vbuf->field = V4L2_FIELD_NONE; vbuf->sequence = channel->csequence++; diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index 03f905555d56..ffb046eec610 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -936,7 +936,7 @@ static void vb2ops_venc_stop_streaming(struct vb2_queue *q) if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) { - dst_buf->vb2_buf.planes[0].bytesused = 0; + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0); v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); } /* STREAMOFF on the CAPTURE queue completes any ongoing flush */ @@ -1045,7 +1045,7 @@ static int mtk_venc_encode_header(void *priv) NULL, &bs_buf, &enc_result); if (ret) { - dst_buf->vb2_buf.planes[0].bytesused = 0; + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0); ctx->state = MTK_STATE_ABORT; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); mtk_v4l2_err("venc_if_encode failed=%d", ret); @@ -1060,7 +1060,7 @@ static int mtk_venc_encode_header(void *priv) } ctx->state = MTK_STATE_HEADER; - dst_buf->vb2_buf.planes[0].bytesused = enc_result.bs_size; + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, enc_result.bs_size); v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); return 0; @@ -1209,12 +1209,12 @@ static void mtk_venc_worker(struct work_struct *work) if (ret) { v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); - dst_buf->vb2_buf.planes[0].bytesused = 0; + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0); v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); mtk_v4l2_err("venc_if_encode failed=%d", ret); } else { v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); - dst_buf->vb2_buf.planes[0].bytesused = enc_result.bs_size; + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, enc_result.bs_size); v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); mtk_v4l2_debug(2, "venc_if_encode bs size=%d", enc_result.bs_size); diff --git a/drivers/media/test-drivers/vicodec/vicodec-core.c b/drivers/media/test-drivers/vicodec/vicodec-core.c index 33f1c893c1b6..be43f7d32df9 100644 --- a/drivers/media/test-drivers/vicodec/vicodec-core.c +++ b/drivers/media/test-drivers/vicodec/vicodec-core.c @@ -1443,7 +1443,7 @@ static void vicodec_buf_queue(struct vb2_buffer *vb) unsigned int i; for (i = 0; i < vb->num_planes; i++) - vb->planes[i].bytesused = 0; + vb2_set_plane_payload(vb, i, 0); vbuf->field = V4L2_FIELD_NONE; vbuf->sequence = diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c index 6650eab913d8..0c24e2984304 100644 --- a/drivers/media/usb/go7007/go7007-driver.c +++ b/drivers/media/usb/go7007/go7007-driver.c @@ -516,7 +516,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) if (vb && vb->vb.vb2_buf.planes[0].bytesused >= GO7007_BUF_SIZE - 3) { v4l2_info(&go->v4l2_dev, "dropping oversized frame\n"); - vb->vb.vb2_buf.planes[0].bytesused = 0; + vb2_set_plane_payload(&vb->vb.vb2_buf, 0, 0); vb->frame_offset = 0; vb->modet_active = 0; vb = go->active_buf = NULL; diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.c b/drivers/staging/media/meson/vdec/vdec_helpers.c index b9125c295d1d..203d7afa085d 100644 --- a/drivers/staging/media/meson/vdec/vdec_helpers.c +++ b/drivers/staging/media/meson/vdec/vdec_helpers.c @@ -276,13 +276,13 @@ static void dst_buf_done(struct amvdec_session *sess, switch (sess->pixfmt_cap) { case V4L2_PIX_FMT_NV12M: - vbuf->vb2_buf.planes[0].bytesused = output_size; - vbuf->vb2_buf.planes[1].bytesused = output_size / 2; + vb2_set_plane_payload(&vbuf->vb2_buf, 0, output_size); + vb2_set_plane_payload(&vbuf->vb2_buf, 1, output_size / 2); break; case V4L2_PIX_FMT_YUV420M: - vbuf->vb2_buf.planes[0].bytesused = output_size; - vbuf->vb2_buf.planes[1].bytesused = output_size / 4; - vbuf->vb2_buf.planes[2].bytesused = output_size / 4; + vb2_set_plane_payload(&vbuf->vb2_buf, 0, output_size); + vb2_set_plane_payload(&vbuf->vb2_buf, 1, output_size / 4); + vb2_set_plane_payload(&vbuf->vb2_buf, 2, output_size / 4); break; } From ee1806beff85d4f1a3d7f22aa1bcdc8ffb59b36c Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 1 Dec 2021 23:56:51 +0100 Subject: [PATCH 313/397] media: videobuf2: add WARN_ON_ONCE if bytesused is bigger than buffer length In function vb2_set_plane_payload, report if the given bytesused is bigger than the buffer size, and clamp it to the buffer size. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/videobuf2-core.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 2467284e5f26..5468b633b9d2 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -1155,8 +1155,15 @@ static inline void *vb2_get_drv_priv(struct vb2_queue *q) static inline void vb2_set_plane_payload(struct vb2_buffer *vb, unsigned int plane_no, unsigned long size) { - if (plane_no < vb->num_planes) + /* + * size must never be larger than the buffer length, so + * warn and clamp to the buffer length if that's the case. + */ + if (plane_no < vb->num_planes) { + if (WARN_ON_ONCE(size > vb->planes[plane_no].length)) + size = vb->planes[plane_no].length; vb->planes[plane_no].bytesused = size; + } } /** From 1ace494fd0ebea8581012f1b621c2b66b4b2671b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 30 Nov 2021 00:06:26 +0100 Subject: [PATCH 314/397] media: atomisp: make array idx_map static const Don't populate the array idx_map on the stack but instead make it static const. Also makes the object code smaller by 16 bytes. Link: https://lore.kernel.org/linux-media/20211129230626.549090-1-colin.i.king@gmail.com Signed-off-by: Colin Ian King Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css_params.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c index 41ed8e4600ff..09f87c285b8d 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/sh_css_params.c @@ -3399,7 +3399,7 @@ sh_css_params_write_to_ddr_internal( if (params->config_changed[IA_CSS_MACC_ID] && binary->info->sp.enable.macc) { unsigned int i, j, idx; - unsigned int idx_map[] = { + static const unsigned int idx_map[] = { 0, 1, 3, 2, 6, 7, 5, 4, 12, 13, 15, 14, 10, 11, 9, 8 }; From ac56760a8bbb4e654b2fd54e5de79dd5d72f937d Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Wed, 1 Dec 2021 15:19:04 +0100 Subject: [PATCH 315/397] media: atomisp: fix "variable dereferenced before check 'asd'" There are two occurrences where the variable 'asd' is dereferenced before check. Fix this issue by using the variable after the check. Link: https://lore.kernel.org/linux-media/20211122074122.GA6581@kili/ Link: https://lore.kernel.org/linux-media/20211201141904.47231-1-kitakar@gmail.com Reported-by: Dan Carpenter Signed-off-by: Tsuchiya Yuto Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 3 ++- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 5a90cc31cd1a..97d5a528969b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -5185,7 +5185,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, int (*configure_pp_input)(struct atomisp_sub_device *asd, unsigned int width, unsigned int height) = configure_pp_input_nop; - u16 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); + u16 stream_index; const struct atomisp_in_fmt_conv *fc; int ret, i; @@ -5194,6 +5194,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, __func__, vdev->name); return -EINVAL; } + stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); v4l2_fh_init(&fh.vfh, vdev); diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 562789c75299..8fd470efd658 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1182,7 +1182,7 @@ int __atomisp_reqbufs(struct file *file, void *fh, struct ia_css_frame *frame; struct videobuf_vmalloc_memory *vm_mem; u16 source_pad = atomisp_subdev_source_pad(vdev); - u16 stream_id = atomisp_source_pad_to_stream_id(asd, source_pad); + u16 stream_id; int ret = 0, i = 0; if (!asd) { @@ -1190,6 +1190,7 @@ int __atomisp_reqbufs(struct file *file, void *fh, __func__, vdev->name); return -EINVAL; } + stream_id = atomisp_source_pad_to_stream_id(asd, source_pad); if (req->count == 0) { mutex_lock(&pipe->capq.vb_lock); From ebedc6ce3c3cf17904af5529d5e3ee82e3e987a0 Mon Sep 17 00:00:00 2001 From: Akira Yokosawa Date: Sat, 4 Dec 2021 04:37:35 +0100 Subject: [PATCH 316/397] media: docs: media: Fix imbalance of LaTeX group The beginning part of the "existing HSV/HSL formats" table (line 7742) reads: .. raw:: latex \begingroup \tiny \setlength{\tabcolsep}{2pt} However, the ending part (line 7834) reads: .. raw:: latex \normalsize Fix the imbalance by replacing the \normalsize with \endgroup. Note: Actually, the imbalance is harmless and just results in an informative message near the bottom of userspace-api.log: (\end occurred inside a group at level 1) ### semi simple group (level 1) entered at line 70696 (\begingroup) ### bottom level Link: https://lore.kernel.org/linux-media/b3eeec4d-1a34-0a1a-3097-1ddea3b5f1c8@gmail.com Signed-off-by: Akira Yokosawa Cc: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- Documentation/userspace-api/media/v4l/subdev-formats.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst index bd68588b2683..0cbc045d5df6 100644 --- a/Documentation/userspace-api/media/v4l/subdev-formats.rst +++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst @@ -7833,7 +7833,7 @@ The following table lists existing HSV/HSL formats. .. raw:: latex - \normalsize + \endgroup JPEG Compressed Formats From 00a7bba084bacaabcdb5cbd7bc9b3f1fd1b50d29 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 5 Dec 2021 01:37:45 +0100 Subject: [PATCH 317/397] media: c8sectpfe: remove redundant assignment to pointer tsin Pointer tsin is being assigned a value that is never read. The assignment is redundant and can be removed. Link: https://lore.kernel.org/linux-media/20211205003745.227491-1-colin.i.king@gmail.com Cc: kernel-janitors@vger.kernel.org Signed-off-by: Colin Ian King Reviewed-by: Patrice Chotard Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c index 02dc78bd7fab..e1f520903248 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c @@ -930,12 +930,8 @@ static int configure_channels(struct c8sectpfei *fei) /* iterate round each tsin and configure memdma descriptor and IB hw */ for_each_child_of_node(np, child) { - - tsin = fei->channel_data[index]; - ret = configure_memdma_and_inputblock(fei, fei->channel_data[index]); - if (ret) { dev_err(fei->dev, "configure_memdma_and_inputblock failed\n"); From a6441ea29cb2c9314654e093a1cd8020b9b851c8 Mon Sep 17 00:00:00 2001 From: Robert Schlabbach Date: Wed, 1 Dec 2021 22:08:43 +0100 Subject: [PATCH 318/397] media: si2157: Fix "warm" tuner state detection Commit e955f959ac52 ("media: si2157: Better check for running tuner in init") completely broke the "warm" tuner detection of the si2157 driver due to a simple endian error: The Si2157 CRYSTAL_TRIM property code is 0x0402 and needs to be transmitted LSB first. However, it was inserted MSB first, causing the warm detection to always fail and spam the kernel log with tuner initialization messages each time the DVB frontend device was closed and reopened: [ 312.215682] si2157 16-0060: found a 'Silicon Labs Si2157-A30' [ 312.264334] si2157 16-0060: firmware version: 3.0.5 [ 342.248593] si2157 16-0060: found a 'Silicon Labs Si2157-A30' [ 342.295743] si2157 16-0060: firmware version: 3.0.5 [ 372.328574] si2157 16-0060: found a 'Silicon Labs Si2157-A30' [ 372.385035] si2157 16-0060: firmware version: 3.0.5 Also, the reinitializations were observed disturb _other_ tuners on multi-tuner cards such as the Hauppauge WinTV-QuadHD, leading to missed or errored packets when one of the other DVB frontend devices on that card was opened. Fix the order of the property code bytes to make the warm detection work again, also reducing the tuner initialization message in the kernel log to once per power-on, as well as fixing the interference with other tuners. Link: https://lore.kernel.org/linux-media/trinity-2a86eb9d-6264-4387-95e1-ba7b79a4050f-1638392923493@3c-app-gmx-bap03 Fixes: e955f959ac52 ("media: si2157: Better check for running tuner in init") Reported-by: Robert Schlabbach Signed-off-by: Robert Schlabbach Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index fefb2625f655..75ddf7ed1faf 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -90,7 +90,7 @@ static int si2157_init(struct dvb_frontend *fe) dev_dbg(&client->dev, "\n"); /* Try to get Xtal trim property, to verify tuner still running */ - memcpy(cmd.args, "\x15\x00\x04\x02", 4); + memcpy(cmd.args, "\x15\x00\x02\x04", 4); cmd.wlen = 4; cmd.rlen = 4; ret = si2157_cmd_execute(client, &cmd); From ebd80fbf6d8308340b5ce2dcb9cc403ba82b0693 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 23 Nov 2021 10:06:45 +0100 Subject: [PATCH 319/397] media: media si2168: Fix spelling mistake "previsously" -> "previously" There is a spelling mistake in a dev_dbg message. Fix it. Link: https://lore.kernel.org/linux-media/20211123090645.165299-1-colin.i.king@gmail.com Cc: kernel-janitors@vger.kernel.org, linux-kernel@vger.kernel.org Signed-off-by: Colin Ian King Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2168.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 8a3c41a80c03..196e028a6617 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -549,7 +549,7 @@ static int si2168_resume(struct dvb_frontend *fe) * device untouched. */ if (dev->initialized) { - dev_dbg(&client->dev, "previsously initialized, call si2168_init()\n"); + dev_dbg(&client->dev, "previously initialized, call si2168_init()\n"); return si2168_init(fe); } dev_dbg(&client->dev, "not initialized yet, skipping init on resume\n"); From 3da3ee3f0d50d4019628081918515e05bde51792 Mon Sep 17 00:00:00 2001 From: Daniel Kamil Kozar Date: Sat, 20 Nov 2021 00:44:01 +0100 Subject: [PATCH 320/397] media: Print chip type explicitly when loading the Rafael Micro r820t module The module currently prints only "Rafael Micro r820t successfully identified" when successfully loaded, which might be misleading as the module actually supports various chip types. Link: https://lore.kernel.org/linux-media/20211119234401.271193-1-dkk089@gmail.com Cc: linux-kernel@vger.kernel.org, Daniel Kamil Kozar Signed-off-by: Daniel Kamil Kozar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/r820t.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index aed2f130ec74..b9a7590aeec6 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -326,6 +326,26 @@ static int r820t_xtal_capacitor[][2] = { { 0x10, XTAL_HIGH_CAP_0P }, }; +static const char *r820t_chip_enum_to_str(enum r820t_chip chip) +{ + switch (chip) { + case CHIP_R820T: + return "R820T"; + case CHIP_R620D: + return "R620D"; + case CHIP_R828D: + return "R828D"; + case CHIP_R828: + return "R828"; + case CHIP_R828S: + return "R828S"; + case CHIP_R820C: + return "R820C"; + default: + return ""; + } +} + /* * I2C read/write code and shadow registers logic */ @@ -2355,7 +2375,9 @@ struct dvb_frontend *r820t_attach(struct dvb_frontend *fe, if (rc < 0) goto err; - tuner_info("Rafael Micro r820t successfully identified\n"); + tuner_info( + "Rafael Micro r820t successfully identified, chip type: %s\n", + r820t_chip_enum_to_str(cfg->rafael_chip)); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); From 48f45c2a969b5a012fda468350706c3a479f0707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 26 Oct 2021 21:40:10 +0200 Subject: [PATCH 321/397] media: tua9001: Improve messages in .remove's error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If disabling the hardware fails the driver propagates the error code to the i2c core. However this only results in a generic error message; the device still disappears. So instead emit a message that better describes the actual problem than the i2c core's "remove failed (ESOMETHING), will be ignored" and return 0 to suppress the generic message. Link: https://lore.kernel.org/linux-media/20211026194010.109029-1-u.kleine-koenig@pengutronix.de Cc: linux-media@vger.kernel.org, kernel@pengutronix.de Signed-off-by: Uwe Kleine-König Reviewed-by: Kieran Bingham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/tua9001.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c index 5e3625e75620..af7d5ea1f77e 100644 --- a/drivers/media/tuners/tua9001.c +++ b/drivers/media/tuners/tua9001.c @@ -240,14 +240,10 @@ static int tua9001_remove(struct i2c_client *client) DVB_FRONTEND_COMPONENT_TUNER, TUA9001_CMD_CEN, 0); if (ret) - goto err_kfree; + dev_err(&client->dev, "Tuner disable failed (%pe)\n", ERR_PTR(ret)); } kfree(dev); return 0; -err_kfree: - kfree(dev); - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; } static const struct i2c_device_id tua9001_id_table[] = { From 61b738e938ef091e0c4c4e8eadeaf27502732e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 12 Oct 2021 17:39:32 +0200 Subject: [PATCH 322/397] media: cxd2880: Eliminate dead code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An spi remove callback is never called with an spi_device pointer that is NULL. Also it is only called for devices that probed successfully. As cxd2880_spi_probe() always sets driver data, spi_get_drvdata() cannot be NULL. Also the return value of spi remove callbacks is ignored anyway and not freeing resources in .remove() is a bad idea. Link: https://lore.kernel.org/linux-media/20211012153945.2651412-8-u.kleine-koenig@pengutronix.de Cc: Mark Brown , kernel@pengutronix.de, linux-media@vger.kernel.org, linux-spi@vger.kernel.org Signed-off-by: Uwe Kleine-König Signed-off-by: Mauro Carvalho Chehab --- drivers/media/spi/cxd2880-spi.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/media/spi/cxd2880-spi.c b/drivers/media/spi/cxd2880-spi.c index 506f52c1af10..6f2a66bc87fb 100644 --- a/drivers/media/spi/cxd2880-spi.c +++ b/drivers/media/spi/cxd2880-spi.c @@ -628,19 +628,8 @@ fail_regulator: static int cxd2880_spi_remove(struct spi_device *spi) { - struct cxd2880_dvb_spi *dvb_spi; + struct cxd2880_dvb_spi *dvb_spi = spi_get_drvdata(spi); - if (!spi) { - pr_err("invalid arg\n"); - return -EINVAL; - } - - dvb_spi = spi_get_drvdata(spi); - - if (!dvb_spi) { - pr_err("failed\n"); - return -EINVAL; - } dvb_spi->demux.dmx.remove_frontend(&dvb_spi->demux.dmx, &dvb_spi->dmx_fe); dvb_dmxdev_release(&dvb_spi->dmxdev); From a2ab06d7c4d6bfd0b545a768247a70463e977e27 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Dec 2021 15:34:19 +0100 Subject: [PATCH 323/397] media: m920x: don't use stack on USB reads Using stack-allocated pointers for USB message data don't work. This driver is almost OK with that, except for the I2C read logic. Fix it by using a temporary read buffer, just like on all other calls to m920x_read(). Link: https://lore.kernel.org/all/ccc99e48-de4f-045e-0fe4-61e3118e3f74@mida.se/ Reported-by: rkardell@mida.se Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/m920x.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c index 4bb5b82599a7..691e05833db1 100644 --- a/drivers/media/usb/dvb-usb/m920x.c +++ b/drivers/media/usb/dvb-usb/m920x.c @@ -274,6 +274,13 @@ static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu /* Should check for ack here, if we knew how. */ } if (msg[i].flags & I2C_M_RD) { + char *read = kmalloc(1, GFP_KERNEL); + if (!read) { + ret = -ENOMEM; + kfree(read); + goto unlock; + } + for (j = 0; j < msg[i].len; j++) { /* Last byte of transaction? * Send STOP, otherwise send ACK. */ @@ -281,9 +288,12 @@ static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu if ((ret = m920x_read(d->udev, M9206_I2C, 0x0, 0x20 | stop, - &msg[i].buf[j], 1)) != 0) + read, 1)) != 0) goto unlock; + msg[i].buf[j] = read[0]; } + + kfree(read); } else { for (j = 0; j < msg[i].len; j++) { /* Last byte of transaction? Then send STOP. */ From 051d3b5437af602a9541c6ef2f233a60990eab7b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 17 Sep 2021 11:21:32 +0200 Subject: [PATCH 324/397] media: siano: remove duplicate USB device IDs The devices 0x187f,0x0202 and 0x187f,0x0301 are already on the list. Link: https://lore.kernel.org/linux-media/20210917092132.19576-1-krzysztof.kozlowski@canonical.com Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/siano/smsusb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index df4c5dcba39c..fe9c7b3a950e 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -661,10 +661,6 @@ static const struct usb_device_id smsusb_id_table[] = { .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0x5590), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, - { USB_DEVICE(0x187f, 0x0202), - .driver_info = SMS1XXX_BOARD_SIANO_NICE }, - { USB_DEVICE(0x187f, 0x0301), - .driver_info = SMS1XXX_BOARD_SIANO_VENICE }, { USB_DEVICE(0x2040, 0xb900), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0xb910), From e67219b0496b795c9e4e9da53098a1ff302af313 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Thu, 16 Sep 2021 04:00:05 +0200 Subject: [PATCH 325/397] media: b2c2: flexcop: Convert to SPDX identifier use SPDX-License-Identifier instead of a verbose license text Link: https://lore.kernel.org/linux-media/20210916020006.8497-1-caihuoqing@baidu.com CC: Mauro Carvalho Chehab , , Signed-off-by: Cai Huoqing Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/b2c2/flexcop.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/media/common/b2c2/flexcop.c b/drivers/media/common/b2c2/flexcop.c index cbaa61f10d5f..e7a88a2d248c 100644 --- a/drivers/media/common/b2c2/flexcop.c +++ b/drivers/media/common/b2c2/flexcop.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * flexcop.c - main module part @@ -15,16 +16,6 @@ * Uwe Bugla, uwe.bugla at gmx.de (doing tests, restyling code, writing docu) * Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac * filtering) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include "flexcop.h" From 9b4d7b5c81a2578e080da33b5cddc3149fa611aa Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Thu, 3 Jun 2021 09:10:09 +0200 Subject: [PATCH 326/397] media: bttv: use DEVICE_ATTR_RO() helper macro Use DEVICE_ATTR_RO() helper macro instead of DEVICE_ATTR(), which is simpler and more readable. Due to the name of the read function of the sysfs attribute is normalized, there is a natural association. Link: https://lore.kernel.org/linux-media/20210603071009.11438-1-thunder.leizhen@huawei.com Signed-off-by: Zhen Lei Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 0e9df8b35ac6..8cc9bec43688 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -170,14 +170,14 @@ MODULE_VERSION(BTTV_VERSION); /* ----------------------------------------------------------------------- */ /* sysfs */ -static ssize_t show_card(struct device *cd, +static ssize_t card_show(struct device *cd, struct device_attribute *attr, char *buf) { struct video_device *vfd = to_video_device(cd); struct bttv *btv = video_get_drvdata(vfd); return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } -static DEVICE_ATTR(card, S_IRUGO, show_card, NULL); +static DEVICE_ATTR_RO(card); /* ----------------------------------------------------------------------- */ /* dvb auto-load setup */ From 9d9bcae47fd5a0b827521f65ab7d10a218eacc37 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:44 +0100 Subject: [PATCH 327/397] ACPI: delay enumeration of devices with a _DEP pointing to an INT3472 device The clk and regulator frameworks expect clk/regulator consumer-devices to have info about the consumed clks/regulators described in the device's fw_node. To work around cases where this info is not present in the firmware tables, which is often the case on x86/ACPI devices, both frameworks allow the provider-driver to attach info about consumers to the clks/regulators when registering these. This causes problems with the probe ordering wrt drivers for consumers of these clks/regulators. Since the lookups are only registered when the provider-driver binds, trying to get these clks/regulators before then results in a -ENOENT error for clks and a dummy regulator for regulators. One case where we hit this issue is camera sensors such as e.g. the OV8865 sensor found on the Microsoft Surface Go. The sensor uses clks, regulators and GPIOs provided by a TPS68470 PMIC which is described in an INT3472 ACPI device. There is special platform code handling this and setting platform_data with the necessary consumer info on the MFD cells instantiated for the PMIC under: drivers/platform/x86/intel/int3472. For this to work properly the ov8865 driver must not bind to the I2C-client for the OV8865 sensor until after the TPS68470 PMIC gpio, regulator and clk MFD cells have all been fully setup. The OV8865 on the Microsoft Surface Go is just one example, all X86 devices using the Intel IPU3 camera block found on recent Intel SoCs have similar issues where there is an INT3472 HID ACPI-device, which describes the clks and regulators, and the driver for this INT3472 device must be fully initialized before the sensor driver (any sensor driver) binds for things to work properly. On these devices the ACPI nodes describing the sensors all have a _DEP dependency on the matching INT3472 ACPI device (there is one per sensor). This allows solving the probe-ordering problem by delaying the enumeration (instantiation of the I2C-client in the ov8865 example) of ACPI-devices which have a _DEP dependency on an INT3472 device. The new acpi_dev_ready_for_enumeration() helper used for this is also exported because for devices, which have the enumeration_by_parent flag set, the parent-driver will do its own scan of child ACPI devices and it will try to enumerate those during its probe(). Code doing this such as e.g. the i2c-core-acpi.c code must call this new helper to ensure that it too delays the enumeration until all the _DEP dependencies are met on devices which have the new honor_deps flag set. Acked-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211203102857.44539-2-hdegoede@redhat.com --- drivers/acpi/scan.c | 37 +++++++++++++++++++++++++++++++++---- include/acpi/acpi_bus.h | 5 ++++- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a50f1967c73d..010ef0b28374 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -797,6 +797,12 @@ static const char * const acpi_ignore_dep_ids[] = { NULL }; +/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */ +static const char * const acpi_honor_dep_ids[] = { + "INT3472", /* Camera sensor PMIC / clk and regulator info */ + NULL +}; + static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) { struct acpi_device *device = NULL; @@ -1762,8 +1768,12 @@ static void acpi_scan_dep_init(struct acpi_device *adev) struct acpi_dep_data *dep; list_for_each_entry(dep, &acpi_dep_list, node) { - if (dep->consumer == adev->handle) + if (dep->consumer == adev->handle) { + if (dep->honor_dep) + adev->flags.honor_deps = 1; + adev->dep_unmet++; + } } } @@ -1967,7 +1977,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) for (count = 0, i = 0; i < dep_devices.count; i++) { struct acpi_device_info *info; struct acpi_dep_data *dep; - bool skip; + bool skip, honor_dep; status = acpi_get_object_info(dep_devices.handles[i], &info); if (ACPI_FAILURE(status)) { @@ -1976,6 +1986,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) } skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids); + honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids); kfree(info); if (skip) @@ -1989,6 +2000,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) dep->supplier = dep_devices.handles[i]; dep->consumer = handle; + dep->honor_dep = honor_dep; mutex_lock(&acpi_dep_list_lock); list_add_tail(&dep->node , &acpi_dep_list); @@ -2155,8 +2167,8 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass) register_dock_dependent_device(device, ejd); acpi_bus_get_status(device); - /* Skip devices that are not present. */ - if (!acpi_device_is_present(device)) { + /* Skip devices that are not ready for enumeration (e.g. not present) */ + if (!acpi_dev_ready_for_enumeration(device)) { device->flags.initialized = false; acpi_device_clear_enumerated(device); device->flags.power_manageable = 0; @@ -2318,6 +2330,23 @@ void acpi_dev_clear_dependencies(struct acpi_device *supplier) } EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies); +/** + * acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration + * @device: Pointer to the &struct acpi_device to check + * + * Check if the device is present and has no unmet dependencies. + * + * Return true if the device is ready for enumeratino. Otherwise, return false. + */ +bool acpi_dev_ready_for_enumeration(const struct acpi_device *device) +{ + if (device->flags.honor_deps && device->dep_unmet) + return false; + + return acpi_device_is_present(device); +} +EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration); + /** * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier * @supplier: Pointer to the dependee device diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 480f9207a4c6..2f93ecf05dac 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -202,7 +202,8 @@ struct acpi_device_flags { u32 coherent_dma:1; u32 cca_seen:1; u32 enumeration_by_parent:1; - u32 reserved:19; + u32 honor_deps:1; + u32 reserved:18; }; /* File System */ @@ -285,6 +286,7 @@ struct acpi_dep_data { struct list_head node; acpi_handle supplier; acpi_handle consumer; + bool honor_dep; }; /* Performance Management */ @@ -693,6 +695,7 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev) bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2); void acpi_dev_clear_dependencies(struct acpi_device *supplier); +bool acpi_dev_ready_for_enumeration(const struct acpi_device *device); struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier); struct acpi_device * acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv); From fb90e58f7c4e406d510f301e156e2056a4357130 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:45 +0100 Subject: [PATCH 328/397] i2c: acpi: Use acpi_dev_ready_for_enumeration() helper The clk and regulator frameworks expect clk/regulator consumer-devices to have info about the consumed clks/regulators described in the device's fw_node. To work around cases where this info is not present in the firmware tables, which is often the case on x86/ACPI devices, both frameworks allow the provider-driver to attach info about consumers to the clks/regulators when registering these. This causes problems with the probe ordering wrt drivers for consumers of these clks/regulators. Since the lookups are only registered when the provider-driver binds, trying to get these clks/regulators before then results in a -ENOENT error for clks and a dummy regulator for regulators. To ensure the correct probe-ordering the ACPI core has code to defer the enumeration of consumers affected by this until the providers are ready. Call the new acpi_dev_ready_for_enumeration() helper to avoid enumerating / instantiating i2c-clients too early. Acked-by: Wolfram Sang Acked-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko Acked-by: Mika Westerberg Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211203102857.44539-3-hdegoede@redhat.com --- drivers/i2c/i2c-core-acpi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 92c1cc07ed46..04338cbd08a9 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -144,9 +144,12 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev, struct list_head resource_list; int ret; - if (acpi_bus_get_status(adev) || !adev->status.present) + if (acpi_bus_get_status(adev)) return -EINVAL; + if (!acpi_dev_ready_for_enumeration(adev)) + return -ENODEV; + if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0) return -ENODEV; From c537be0bfad6337f2afd618fe252c03217191405 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:46 +0100 Subject: [PATCH 329/397] i2c: acpi: Add i2c_acpi_new_device_by_fwnode() function Change i2c_acpi_new_device() into i2c_acpi_new_device_by_fwnode() and add a static inline wrapper providing the old i2c_acpi_new_device() behavior. This is necessary because in some cases we may only have access to the fwnode / acpi_device and not to the matching physical-node struct device *. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Acked-by: Mika Westerberg Acked-by: Wolfram Sang Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211203102857.44539-4-hdegoede@redhat.com --- drivers/i2c/i2c-core-acpi.c | 17 +++++++++++------ include/linux/i2c.h | 17 +++++++++++++---- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 04338cbd08a9..c87ce2276007 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -476,8 +476,8 @@ struct notifier_block i2c_acpi_notifier = { }; /** - * i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource - * @dev: Device owning the ACPI resources to get the client from + * i2c_acpi_new_device_by_fwnode - Create i2c-client for the Nth I2cSerialBus resource + * @fwnode: fwnode with the ACPI resources to get the client from * @index: Index of ACPI resource to get * @info: describes the I2C device; note this is modified (addr gets set) * Context: can sleep @@ -493,15 +493,20 @@ struct notifier_block i2c_acpi_notifier = { * Returns a pointer to the new i2c-client, or error pointer in case of failure. * Specifically, -EPROBE_DEFER is returned if the adapter is not found. */ -struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, - struct i2c_board_info *info) +struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode, + int index, + struct i2c_board_info *info) { - struct acpi_device *adev = ACPI_COMPANION(dev); struct i2c_acpi_lookup lookup; struct i2c_adapter *adapter; + struct acpi_device *adev; LIST_HEAD(resource_list); int ret; + adev = to_acpi_device_node(fwnode); + if (!adev) + return ERR_PTR(-ENODEV); + memset(&lookup, 0, sizeof(lookup)); lookup.info = info; lookup.device_handle = acpi_device_handle(adev); @@ -523,7 +528,7 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, return i2c_new_client_device(adapter, info); } -EXPORT_SYMBOL_GPL(i2c_acpi_new_device); +EXPORT_SYMBOL_GPL(i2c_acpi_new_device_by_fwnode); bool i2c_acpi_waive_d0_probe(struct device *dev) { diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 16119ac1aa97..7d4f52ceb7b5 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -1025,8 +1025,9 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, struct acpi_resource_i2c_serialbus **i2c); int i2c_acpi_client_count(struct acpi_device *adev); u32 i2c_acpi_find_bus_speed(struct device *dev); -struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, - struct i2c_board_info *info); +struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode, + int index, + struct i2c_board_info *info); struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle); bool i2c_acpi_waive_d0_probe(struct device *dev); #else @@ -1043,8 +1044,9 @@ static inline u32 i2c_acpi_find_bus_speed(struct device *dev) { return 0; } -static inline struct i2c_client *i2c_acpi_new_device(struct device *dev, - int index, struct i2c_board_info *info) +static inline struct i2c_client *i2c_acpi_new_device_by_fwnode( + struct fwnode_handle *fwnode, int index, + struct i2c_board_info *info) { return ERR_PTR(-ENODEV); } @@ -1058,4 +1060,11 @@ static inline bool i2c_acpi_waive_d0_probe(struct device *dev) } #endif /* CONFIG_ACPI */ +static inline struct i2c_client *i2c_acpi_new_device(struct device *dev, + int index, + struct i2c_board_info *info) +{ + return i2c_acpi_new_device_by_fwnode(dev_fwnode(dev), index, info); +} + #endif /* _LINUX_I2C_H */ From 9dfa374cc6d04d2515adc21c39e356b64ee45a29 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:47 +0100 Subject: [PATCH 330/397] platform_data: Add linux/platform_data/tps68470.h file The clk and regulator frameworks expect clk/regulator consumer-devices to have info about the consumed clks/regulators described in the device's fw_node. To work around cases where this info is not present in the firmware tables, which is often the case on x86/ACPI devices, both frameworks allow the provider-driver to attach info about consumers to the provider-device during probe/registration of the provider device. The TI TPS68470 PMIC is used x86/ACPI devices with the consumer-info missing from the ACPI tables. Thus the tps68470-clk and tps68470-regulator drivers must provide the consumer-info at probe time. Define tps68470_clk_platform_data and tps68470_regulator_platform_data structs to allow the x86 platform code to pass the necessary consumer info to these drivers. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211203102857.44539-5-hdegoede@redhat.com --- include/linux/platform_data/tps68470.h | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 include/linux/platform_data/tps68470.h diff --git a/include/linux/platform_data/tps68470.h b/include/linux/platform_data/tps68470.h new file mode 100644 index 000000000000..126d082c3f2e --- /dev/null +++ b/include/linux/platform_data/tps68470.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * TI TPS68470 PMIC platform data definition. + * + * Copyright (c) 2021 Red Hat Inc. + * + * Red Hat authors: + * Hans de Goede + */ +#ifndef __PDATA_TPS68470_H +#define __PDATA_TPS68470_H + +enum tps68470_regulators { + TPS68470_CORE, + TPS68470_ANA, + TPS68470_VCM, + TPS68470_VIO, + TPS68470_VSIO, + TPS68470_AUX1, + TPS68470_AUX2, + TPS68470_NUM_REGULATORS +}; + +struct regulator_init_data; + +struct tps68470_regulator_platform_data { + const struct regulator_init_data *reg_init_data[TPS68470_NUM_REGULATORS]; +}; + +struct tps68470_clk_platform_data { + const char *consumer_dev_name; + const char *consumer_con_id; +}; + +#endif From a2f9fbc247eea0ad1b0b59bc29bec144c5ead03c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:50 +0100 Subject: [PATCH 331/397] platform/x86: int3472: Split into 2 drivers The intel_skl_int3472.ko module contains 2 separate drivers, the int3472_discrete platform driver and the int3472_tps68470 I2C-driver. These 2 drivers contain very little shared code, only skl_int3472_get_acpi_buffer() and skl_int3472_fill_cldb() are shared. Split the module into 2 drivers, linking the little shared code directly into both. This will allow us to add soft-module dependencies for the tps68470 clk, gpio and regulator drivers to the new intel_skl_int3472_tps68470.ko to help with probe ordering issues without causing these modules to get loaded on boards which only use the int3472_discrete platform driver. While at it also rename the .c and .h files to remove the cumbersome intel_skl_int3472_ prefix. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211203102857.44539-8-hdegoede@redhat.com --- drivers/platform/x86/intel/int3472/Makefile | 9 +- ...lk_and_regulator.c => clk_and_regulator.c} | 2 +- drivers/platform/x86/intel/int3472/common.c | 54 +++++++++ .../{intel_skl_int3472_common.h => common.h} | 3 - ...ntel_skl_int3472_discrete.c => discrete.c} | 28 ++++- .../intel/int3472/intel_skl_int3472_common.c | 106 ------------------ ...ntel_skl_int3472_tps68470.c => tps68470.c} | 23 +++- 7 files changed, 105 insertions(+), 120 deletions(-) rename drivers/platform/x86/intel/int3472/{intel_skl_int3472_clk_and_regulator.c => clk_and_regulator.c} (99%) create mode 100644 drivers/platform/x86/intel/int3472/common.c rename drivers/platform/x86/intel/int3472/{intel_skl_int3472_common.h => common.h} (94%) rename drivers/platform/x86/intel/int3472/{intel_skl_int3472_discrete.c => discrete.c} (93%) delete mode 100644 drivers/platform/x86/intel/int3472/intel_skl_int3472_common.c rename drivers/platform/x86/intel/int3472/{intel_skl_int3472_tps68470.c => tps68470.c} (85%) diff --git a/drivers/platform/x86/intel/int3472/Makefile b/drivers/platform/x86/intel/int3472/Makefile index 2362e04db18d..771e720528a0 100644 --- a/drivers/platform/x86/intel/int3472/Makefile +++ b/drivers/platform/x86/intel/int3472/Makefile @@ -1,5 +1,4 @@ -obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472.o -intel_skl_int3472-y := intel_skl_int3472_common.o \ - intel_skl_int3472_discrete.o \ - intel_skl_int3472_tps68470.o \ - intel_skl_int3472_clk_and_regulator.o +obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472_discrete.o \ + intel_skl_int3472_tps68470.o +intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o common.o +intel_skl_int3472_tps68470-y := tps68470.o common.o diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c similarity index 99% rename from drivers/platform/x86/intel/int3472/intel_skl_int3472_clk_and_regulator.c rename to drivers/platform/x86/intel/int3472/clk_and_regulator.c index 1700e7557a82..1cf958983e86 100644 --- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_clk_and_regulator.c +++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c @@ -9,7 +9,7 @@ #include #include -#include "intel_skl_int3472_common.h" +#include "common.h" /* * The regulators have to have .ops to be valid, but the only ops we actually diff --git a/drivers/platform/x86/intel/int3472/common.c b/drivers/platform/x86/intel/int3472/common.c new file mode 100644 index 000000000000..350655a9515b --- /dev/null +++ b/drivers/platform/x86/intel/int3472/common.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Author: Dan Scally */ + +#include +#include + +#include "common.h" + +union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_handle handle = adev->handle; + union acpi_object *obj; + acpi_status status; + + status = acpi_evaluate_object(handle, id, NULL, &buffer); + if (ACPI_FAILURE(status)) + return ERR_PTR(-ENODEV); + + obj = buffer.pointer; + if (!obj) + return ERR_PTR(-ENODEV); + + if (obj->type != ACPI_TYPE_BUFFER) { + acpi_handle_err(handle, "%s object is not an ACPI buffer\n", id); + kfree(obj); + return ERR_PTR(-EINVAL); + } + + return obj; +} + +int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb) +{ + union acpi_object *obj; + int ret; + + obj = skl_int3472_get_acpi_buffer(adev, "CLDB"); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + if (obj->buffer.length > sizeof(*cldb)) { + acpi_handle_err(adev->handle, "The CLDB buffer is too large\n"); + ret = -EINVAL; + goto out_free_obj; + } + + memcpy(cldb, obj->buffer.pointer, obj->buffer.length); + ret = 0; + +out_free_obj: + kfree(obj); + return ret; +} diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.h b/drivers/platform/x86/intel/int3472/common.h similarity index 94% rename from drivers/platform/x86/intel/int3472/intel_skl_int3472_common.h rename to drivers/platform/x86/intel/int3472/common.h index 714fde73b524..d14944ee8586 100644 --- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.h +++ b/drivers/platform/x86/intel/int3472/common.h @@ -105,9 +105,6 @@ struct int3472_discrete_device { struct gpiod_lookup_table gpios; }; -int skl_int3472_discrete_probe(struct platform_device *pdev); -int skl_int3472_discrete_remove(struct platform_device *pdev); -int skl_int3472_tps68470_probe(struct i2c_client *client); union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id); int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb); diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c b/drivers/platform/x86/intel/int3472/discrete.c similarity index 93% rename from drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c rename to drivers/platform/x86/intel/int3472/discrete.c index e59d79c7e82f..d2e8a87a077e 100644 --- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -14,7 +14,7 @@ #include #include -#include "intel_skl_int3472_common.h" +#include "common.h" /* * 79234640-9e10-4fea-a5c1-b5aa8b19756f @@ -332,7 +332,9 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472) return 0; } -int skl_int3472_discrete_probe(struct platform_device *pdev) +static int skl_int3472_discrete_remove(struct platform_device *pdev); + +static int skl_int3472_discrete_probe(struct platform_device *pdev) { struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); struct int3472_discrete_device *int3472; @@ -395,7 +397,7 @@ err_put_sensor: return ret; } -int skl_int3472_discrete_remove(struct platform_device *pdev) +static int skl_int3472_discrete_remove(struct platform_device *pdev) { struct int3472_discrete_device *int3472 = platform_get_drvdata(pdev); @@ -411,3 +413,23 @@ int skl_int3472_discrete_remove(struct platform_device *pdev) return 0; } + +static const struct acpi_device_id int3472_device_id[] = { + { "INT3472", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, int3472_device_id); + +static struct platform_driver int3472_discrete = { + .driver = { + .name = "int3472-discrete", + .acpi_match_table = int3472_device_id, + }, + .probe = skl_int3472_discrete_probe, + .remove = skl_int3472_discrete_remove, +}; +module_platform_driver(int3472_discrete); + +MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Discrete Device Driver"); +MODULE_AUTHOR("Daniel Scally "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.c b/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.c deleted file mode 100644 index 497e74fba75f..000000000000 --- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.c +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Author: Dan Scally */ - -#include -#include -#include -#include - -#include "intel_skl_int3472_common.h" - -union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_handle handle = adev->handle; - union acpi_object *obj; - acpi_status status; - - status = acpi_evaluate_object(handle, id, NULL, &buffer); - if (ACPI_FAILURE(status)) - return ERR_PTR(-ENODEV); - - obj = buffer.pointer; - if (!obj) - return ERR_PTR(-ENODEV); - - if (obj->type != ACPI_TYPE_BUFFER) { - acpi_handle_err(handle, "%s object is not an ACPI buffer\n", id); - kfree(obj); - return ERR_PTR(-EINVAL); - } - - return obj; -} - -int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb) -{ - union acpi_object *obj; - int ret; - - obj = skl_int3472_get_acpi_buffer(adev, "CLDB"); - if (IS_ERR(obj)) - return PTR_ERR(obj); - - if (obj->buffer.length > sizeof(*cldb)) { - acpi_handle_err(adev->handle, "The CLDB buffer is too large\n"); - ret = -EINVAL; - goto out_free_obj; - } - - memcpy(cldb, obj->buffer.pointer, obj->buffer.length); - ret = 0; - -out_free_obj: - kfree(obj); - return ret; -} - -static const struct acpi_device_id int3472_device_id[] = { - { "INT3472", 0 }, - { } -}; -MODULE_DEVICE_TABLE(acpi, int3472_device_id); - -static struct platform_driver int3472_discrete = { - .driver = { - .name = "int3472-discrete", - .acpi_match_table = int3472_device_id, - }, - .probe = skl_int3472_discrete_probe, - .remove = skl_int3472_discrete_remove, -}; - -static struct i2c_driver int3472_tps68470 = { - .driver = { - .name = "int3472-tps68470", - .acpi_match_table = int3472_device_id, - }, - .probe_new = skl_int3472_tps68470_probe, -}; - -static int skl_int3472_init(void) -{ - int ret; - - ret = platform_driver_register(&int3472_discrete); - if (ret) - return ret; - - ret = i2c_register_driver(THIS_MODULE, &int3472_tps68470); - if (ret) - platform_driver_unregister(&int3472_discrete); - - return ret; -} -module_init(skl_int3472_init); - -static void skl_int3472_exit(void) -{ - platform_driver_unregister(&int3472_discrete); - i2c_del_driver(&int3472_tps68470); -} -module_exit(skl_int3472_exit); - -MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Device Driver"); -MODULE_AUTHOR("Daniel Scally "); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c similarity index 85% rename from drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c rename to drivers/platform/x86/intel/int3472/tps68470.c index c05b4cf502fe..fd3bef449137 100644 --- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c +++ b/drivers/platform/x86/intel/int3472/tps68470.c @@ -7,7 +7,7 @@ #include #include -#include "intel_skl_int3472_common.h" +#include "common.h" #define DESIGNED_FOR_CHROMEOS 1 #define DESIGNED_FOR_WINDOWS 2 @@ -95,7 +95,7 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev) return DESIGNED_FOR_WINDOWS; } -int skl_int3472_tps68470_probe(struct i2c_client *client) +static int skl_int3472_tps68470_probe(struct i2c_client *client) { struct acpi_device *adev = ACPI_COMPANION(&client->dev); struct regmap *regmap; @@ -135,3 +135,22 @@ int skl_int3472_tps68470_probe(struct i2c_client *client) return ret; } + +static const struct acpi_device_id int3472_device_id[] = { + { "INT3472", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, int3472_device_id); + +static struct i2c_driver int3472_tps68470 = { + .driver = { + .name = "int3472-tps68470", + .acpi_match_table = int3472_device_id, + }, + .probe_new = skl_int3472_tps68470_probe, +}; +module_i2c_driver(int3472_tps68470); + +MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver"); +MODULE_AUTHOR("Daniel Scally "); +MODULE_LICENSE("GPL v2"); From 71102bc7964342f0aaf1faf7aa384678b1207848 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:51 +0100 Subject: [PATCH 332/397] platform/x86: int3472: Add get_sensor_adev_and_name() helper The discrete.c code is not the only code which needs to lookup the acpi_device and device-name for the sensor for which the INT3472 ACPI-device is a GPIO/clk/regulator provider. The tps68470.c code also needs this functionality, so factor this out into a new get_sensor_adev_and_name() helper. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211203102857.44539-9-hdegoede@redhat.com --- drivers/platform/x86/intel/int3472/common.c | 28 +++++++++++++++++++ drivers/platform/x86/intel/int3472/common.h | 3 ++ drivers/platform/x86/intel/int3472/discrete.c | 22 +++------------ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/drivers/platform/x86/intel/int3472/common.c b/drivers/platform/x86/intel/int3472/common.c index 350655a9515b..77cf058e4168 100644 --- a/drivers/platform/x86/intel/int3472/common.c +++ b/drivers/platform/x86/intel/int3472/common.c @@ -52,3 +52,31 @@ out_free_obj: kfree(obj); return ret; } + +/* sensor_adev_ret may be NULL, name_ret must not be NULL */ +int skl_int3472_get_sensor_adev_and_name(struct device *dev, + struct acpi_device **sensor_adev_ret, + const char **name_ret) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + struct acpi_device *sensor; + int ret = 0; + + sensor = acpi_dev_get_first_consumer_dev(adev); + if (!sensor) { + dev_err(dev, "INT3472 seems to have no dependents.\n"); + return -ENODEV; + } + + *name_ret = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT, + acpi_dev_name(sensor)); + if (!*name_ret) + ret = -ENOMEM; + + if (ret == 0 && sensor_adev_ret) + *sensor_adev_ret = sensor; + else + acpi_dev_put(sensor); + + return ret; +} diff --git a/drivers/platform/x86/intel/int3472/common.h b/drivers/platform/x86/intel/int3472/common.h index d14944ee8586..53270d19c73a 100644 --- a/drivers/platform/x86/intel/int3472/common.h +++ b/drivers/platform/x86/intel/int3472/common.h @@ -108,6 +108,9 @@ struct int3472_discrete_device { union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id); int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb); +int skl_int3472_get_sensor_adev_and_name(struct device *dev, + struct acpi_device **sensor_adev_ret, + const char **name_ret); int skl_int3472_register_clock(struct int3472_discrete_device *int3472); void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472); diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c index d2e8a87a077e..ff2bdbb8722c 100644 --- a/drivers/platform/x86/intel/int3472/discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -363,19 +363,10 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) int3472->dev = &pdev->dev; platform_set_drvdata(pdev, int3472); - int3472->sensor = acpi_dev_get_first_consumer_dev(adev); - if (!int3472->sensor) { - dev_err(&pdev->dev, "INT3472 seems to have no dependents.\n"); - return -ENODEV; - } - - int3472->sensor_name = devm_kasprintf(int3472->dev, GFP_KERNEL, - I2C_DEV_NAME_FORMAT, - acpi_dev_name(int3472->sensor)); - if (!int3472->sensor_name) { - ret = -ENOMEM; - goto err_put_sensor; - } + ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor, + &int3472->sensor_name); + if (ret) + return ret; /* * Initialising this list means we can call gpiod_remove_lookup_table() @@ -390,11 +381,6 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) } return 0; - -err_put_sensor: - acpi_dev_put(int3472->sensor); - - return ret; } static int skl_int3472_discrete_remove(struct platform_device *pdev) From d3d76ae139a7ba2162ab86f54f722d4da8c3bc95 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:52 +0100 Subject: [PATCH 333/397] platform/x86: int3472: Pass tps68470_clk_platform_data to the tps68470-regulator MFD-cell Pass tps68470_clk_platform_data to the tps68470-clk MFD-cell, so that sensors which use the TPS68470 can find their clock. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211203102857.44539-10-hdegoede@redhat.com --- drivers/platform/x86/intel/int3472/tps68470.c | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c index fd3bef449137..d0a3659a34ea 100644 --- a/drivers/platform/x86/intel/int3472/tps68470.c +++ b/drivers/platform/x86/intel/int3472/tps68470.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "common.h" @@ -12,17 +13,13 @@ #define DESIGNED_FOR_CHROMEOS 1 #define DESIGNED_FOR_WINDOWS 2 +#define TPS68470_WIN_MFD_CELL_COUNT 3 + static const struct mfd_cell tps68470_cros[] = { { .name = "tps68470-gpio" }, { .name = "tps68470_pmic_opregion" }, }; -static const struct mfd_cell tps68470_win[] = { - { .name = "tps68470-gpio" }, - { .name = "tps68470-clk" }, - { .name = "tps68470-regulator" }, -}; - static const struct regmap_config tps68470_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -98,10 +95,17 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev) static int skl_int3472_tps68470_probe(struct i2c_client *client) { struct acpi_device *adev = ACPI_COMPANION(&client->dev); + struct tps68470_clk_platform_data clk_pdata = {}; + struct mfd_cell *cells; struct regmap *regmap; int device_type; int ret; + ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL, + &clk_pdata.consumer_dev_name); + if (ret) + return ret; + regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config); if (IS_ERR(regmap)) { dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap)); @@ -119,9 +123,26 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) device_type = skl_int3472_tps68470_calc_type(adev); switch (device_type) { case DESIGNED_FOR_WINDOWS: + cells = kcalloc(TPS68470_WIN_MFD_CELL_COUNT, sizeof(*cells), GFP_KERNEL); + if (!cells) + return -ENOMEM; + + /* + * The order of the cells matters here! The clk must be first + * because the regulator depends on it. The gpios must be last, + * acpi_gpiochip_add() calls acpi_dev_clear_dependencies() and + * the clk + regulators must be ready when this happens. + */ + cells[0].name = "tps68470-clk"; + cells[0].platform_data = &clk_pdata; + cells[0].pdata_size = sizeof(clk_pdata); + cells[1].name = "tps68470-regulator"; + cells[2].name = "tps68470-gpio"; + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, - tps68470_win, ARRAY_SIZE(tps68470_win), + cells, TPS68470_WIN_MFD_CELL_COUNT, NULL, 0, NULL); + kfree(cells); break; case DESIGNED_FOR_CHROMEOS: ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, From 19d8d6e36b4b7aa2a9a9cb64687572a1d9f234bf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:53 +0100 Subject: [PATCH 334/397] platform/x86: int3472: Pass tps68470_regulator_platform_data to the tps68470-regulator MFD-cell Pass tps68470_regulator_platform_data to the tps68470-regulator MFD-cell, specifying the voltages of the various regulators and tying the regulators to the sensor supplies so that sensors which use the TPS68470 can find their regulators. Since the voltages and supply connections are board-specific, this introduces a DMI matches int3472_tps68470_board_data struct which contains the necessary per-board info. This per-board info also includes GPIO lookup information for the sensor IO lines which may be connected to the tps68470 GPIOs. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211203102857.44539-11-hdegoede@redhat.com --- drivers/platform/x86/intel/int3472/Makefile | 2 +- drivers/platform/x86/intel/int3472/tps68470.c | 28 ++++ drivers/platform/x86/intel/int3472/tps68470.h | 25 +++ .../x86/intel/int3472/tps68470_board_data.c | 145 ++++++++++++++++++ 4 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 drivers/platform/x86/intel/int3472/tps68470.h create mode 100644 drivers/platform/x86/intel/int3472/tps68470_board_data.c diff --git a/drivers/platform/x86/intel/int3472/Makefile b/drivers/platform/x86/intel/int3472/Makefile index 771e720528a0..cfec7784c5c9 100644 --- a/drivers/platform/x86/intel/int3472/Makefile +++ b/drivers/platform/x86/intel/int3472/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472_discrete.o \ intel_skl_int3472_tps68470.o intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o common.o -intel_skl_int3472_tps68470-y := tps68470.o common.o +intel_skl_int3472_tps68470-y := tps68470.o tps68470_board_data.o common.o diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c index d0a3659a34ea..64b961fe628c 100644 --- a/drivers/platform/x86/intel/int3472/tps68470.c +++ b/drivers/platform/x86/intel/int3472/tps68470.c @@ -2,13 +2,16 @@ /* Author: Dan Scally */ #include +#include #include #include #include #include #include +#include #include "common.h" +#include "tps68470.h" #define DESIGNED_FOR_CHROMEOS 1 #define DESIGNED_FOR_WINDOWS 2 @@ -95,6 +98,7 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev) static int skl_int3472_tps68470_probe(struct i2c_client *client) { struct acpi_device *adev = ACPI_COMPANION(&client->dev); + const struct int3472_tps68470_board_data *board_data; struct tps68470_clk_platform_data clk_pdata = {}; struct mfd_cell *cells; struct regmap *regmap; @@ -123,6 +127,10 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) device_type = skl_int3472_tps68470_calc_type(adev); switch (device_type) { case DESIGNED_FOR_WINDOWS: + board_data = int3472_tps68470_get_board_data(dev_name(&client->dev)); + if (!board_data) + return dev_err_probe(&client->dev, -ENODEV, "No board-data found for this model\n"); + cells = kcalloc(TPS68470_WIN_MFD_CELL_COUNT, sizeof(*cells), GFP_KERNEL); if (!cells) return -ENOMEM; @@ -137,12 +145,20 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) cells[0].platform_data = &clk_pdata; cells[0].pdata_size = sizeof(clk_pdata); cells[1].name = "tps68470-regulator"; + cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata; + cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data); cells[2].name = "tps68470-gpio"; + gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table); + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, cells, TPS68470_WIN_MFD_CELL_COUNT, NULL, 0, NULL); kfree(cells); + + if (ret) + gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); + break; case DESIGNED_FOR_CHROMEOS: ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, @@ -157,6 +173,17 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) return ret; } +static int skl_int3472_tps68470_remove(struct i2c_client *client) +{ + const struct int3472_tps68470_board_data *board_data; + + board_data = int3472_tps68470_get_board_data(dev_name(&client->dev)); + if (board_data) + gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); + + return 0; +} + static const struct acpi_device_id int3472_device_id[] = { { "INT3472", 0 }, { } @@ -169,6 +196,7 @@ static struct i2c_driver int3472_tps68470 = { .acpi_match_table = int3472_device_id, }, .probe_new = skl_int3472_tps68470_probe, + .remove = skl_int3472_tps68470_remove, }; module_i2c_driver(int3472_tps68470); diff --git a/drivers/platform/x86/intel/int3472/tps68470.h b/drivers/platform/x86/intel/int3472/tps68470.h new file mode 100644 index 000000000000..cfd33eb62740 --- /dev/null +++ b/drivers/platform/x86/intel/int3472/tps68470.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * TI TPS68470 PMIC platform data definition. + * + * Copyright (c) 2021 Red Hat Inc. + * + * Red Hat authors: + * Hans de Goede + */ + +#ifndef _INTEL_SKL_INT3472_TPS68470_H +#define _INTEL_SKL_INT3472_TPS68470_H + +struct gpiod_lookup_table; +struct tps68470_regulator_platform_data; + +struct int3472_tps68470_board_data { + const char *dev_name; + struct gpiod_lookup_table *tps68470_gpio_lookup_table; + const struct tps68470_regulator_platform_data *tps68470_regulator_pdata; +}; + +const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name); + +#endif diff --git a/drivers/platform/x86/intel/int3472/tps68470_board_data.c b/drivers/platform/x86/intel/int3472/tps68470_board_data.c new file mode 100644 index 000000000000..faa5570f6e6b --- /dev/null +++ b/drivers/platform/x86/intel/int3472/tps68470_board_data.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TI TPS68470 PMIC platform data definition. + * + * Copyright (c) 2021 Dan Scally + * Copyright (c) 2021 Red Hat Inc. + * + * Red Hat authors: + * Hans de Goede + */ + +#include +#include +#include +#include +#include "tps68470.h" + +static struct regulator_consumer_supply int347a_core_consumer_supplies[] = { + REGULATOR_SUPPLY("dvdd", "i2c-INT347A:00"), +}; + +static struct regulator_consumer_supply int347a_ana_consumer_supplies[] = { + REGULATOR_SUPPLY("avdd", "i2c-INT347A:00"), +}; + +static struct regulator_consumer_supply int347a_vcm_consumer_supplies[] = { + REGULATOR_SUPPLY("vdd", "i2c-INT347A:00-VCM"), +}; + +static struct regulator_consumer_supply int347a_vsio_consumer_supplies[] = { + REGULATOR_SUPPLY("dovdd", "i2c-INT347A:00"), + REGULATOR_SUPPLY("vsio", "i2c-INT347A:00-VCM"), +}; + +static const struct regulator_init_data surface_go_tps68470_core_reg_init_data = { + .constraints = { + .min_uV = 1200000, + .max_uV = 1200000, + .apply_uV = true, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_core_consumer_supplies), + .consumer_supplies = int347a_core_consumer_supplies, +}; + +static const struct regulator_init_data surface_go_tps68470_ana_reg_init_data = { + .constraints = { + .min_uV = 2815200, + .max_uV = 2815200, + .apply_uV = true, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_ana_consumer_supplies), + .consumer_supplies = int347a_ana_consumer_supplies, +}; + +static const struct regulator_init_data surface_go_tps68470_vcm_reg_init_data = { + .constraints = { + .min_uV = 2815200, + .max_uV = 2815200, + .apply_uV = true, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_vcm_consumer_supplies), + .consumer_supplies = int347a_vcm_consumer_supplies, +}; + +/* Ensure the always-on VIO regulator has the same voltage as VSIO */ +static const struct regulator_init_data surface_go_tps68470_vio_reg_init_data = { + .constraints = { + .min_uV = 1800600, + .max_uV = 1800600, + .apply_uV = true, + .always_on = true, + }, +}; + +static const struct regulator_init_data surface_go_tps68470_vsio_reg_init_data = { + .constraints = { + .min_uV = 1800600, + .max_uV = 1800600, + .apply_uV = true, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(int347a_vsio_consumer_supplies), + .consumer_supplies = int347a_vsio_consumer_supplies, +}; + +static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = { + .reg_init_data = { + [TPS68470_CORE] = &surface_go_tps68470_core_reg_init_data, + [TPS68470_ANA] = &surface_go_tps68470_ana_reg_init_data, + [TPS68470_VCM] = &surface_go_tps68470_vcm_reg_init_data, + [TPS68470_VIO] = &surface_go_tps68470_vio_reg_init_data, + [TPS68470_VSIO] = &surface_go_tps68470_vsio_reg_init_data, + }, +}; + +static struct gpiod_lookup_table surface_go_tps68470_gpios = { + .dev_id = "i2c-INT347A:00", + .table = { + GPIO_LOOKUP("tps68470-gpio", 9, "reset", GPIO_ACTIVE_LOW), + GPIO_LOOKUP("tps68470-gpio", 7, "powerdown", GPIO_ACTIVE_LOW) + } +}; + +static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = { + .dev_name = "i2c-INT3472:05", + .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios, + .tps68470_regulator_pdata = &surface_go_tps68470_pdata, +}; + +static const struct dmi_system_id int3472_tps68470_board_data_table[] = { + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go"), + }, + .driver_data = (void *)&surface_go_tps68470_board_data, + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go 2"), + }, + .driver_data = (void *)&surface_go_tps68470_board_data, + }, + { } +}; + +const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name) +{ + const struct int3472_tps68470_board_data *board_data; + const struct dmi_system_id *match; + + for (match = dmi_first_match(int3472_tps68470_board_data_table); + match; + match = dmi_first_match(match + 1)) { + board_data = match->driver_data; + if (strcmp(board_data->dev_name, dev_name) == 0) + return board_data; + } + + return NULL; +} From 97c2259ec7757ec24a90f0ef8fc5ea7fa1c6acca Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:54 +0100 Subject: [PATCH 335/397] platform/x86: int3472: Deal with probe ordering issues The clk and regulator frameworks expect clk/regulator consumer-devices to have info about the consumed clks/regulators described in the device's fw_node. To work around this info missing from the ACPI tables on devices where the int3472 driver is used, the int3472 MFD-cell drivers attach info about consumers to the clks/regulators when registering these. This causes problems with the probe ordering wrt drivers for consumers of these clks/regulators. Since the lookups are only registered when the provider-driver binds, trying to get these clks/regulators before then results in a -ENOENT error for clks and a dummy regulator for regulators. All the sensor ACPI fw-nodes have a _DEP dependency on the INT3472 ACPI fw-node, so to work around these probe ordering issues the ACPI core / i2c-code does not instantiate the I2C-clients for any ACPI devices which have a _DEP dependency on an INT3472 ACPI device until all _DEP-s are met. This relies on acpi_dev_clear_dependencies() getting called by the driver for the _DEP-s when they are ready, add a acpi_dev_clear_dependencies() call to the discrete.c probe code. In the tps68470 case calling acpi_dev_clear_dependencies() is already done by the acpi_gpiochip_add() call done by the driver for the GPIO MFD cell (The GPIO cell is deliberately the last cell created to make sure the clk + regulator cells are already instantiated when this happens). However for proper probe ordering, the clk/regulator cells must not just be instantiated the must be fully ready (the clks + regulators must be registered with their subsystems). Add MODULE_SOFTDEP dependencies for the clk and regulator drivers for the instantiated MFD-cells so that these are loaded before us and so that they bind immediately when the platform-devs are instantiated. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211203102857.44539-12-hdegoede@redhat.com --- drivers/platform/x86/intel/int3472/discrete.c | 1 + drivers/platform/x86/intel/int3472/tps68470.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c index ff2bdbb8722c..5b514fa01a97 100644 --- a/drivers/platform/x86/intel/int3472/discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -380,6 +380,7 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) return ret; } + acpi_dev_clear_dependencies(adev); return 0; } diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c index 64b961fe628c..22f61b47f9e5 100644 --- a/drivers/platform/x86/intel/int3472/tps68470.c +++ b/drivers/platform/x86/intel/int3472/tps68470.c @@ -170,6 +170,11 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) return device_type; } + /* + * No acpi_dev_clear_dependencies() here, since the acpi_gpiochip_add() + * for the GPIO cell already does this. + */ + return ret; } @@ -203,3 +208,4 @@ module_i2c_driver(int3472_tps68470); MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver"); MODULE_AUTHOR("Daniel Scally "); MODULE_LICENSE("GPL v2"); +MODULE_SOFTDEP("pre: clk-tps68470 tps68470-regulator"); From 74747dda582dc7ddd8aac6841954e84b0d28e56c Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sat, 27 Nov 2021 12:46:58 +0100 Subject: [PATCH 336/397] media: lirc: always send timeout reports Without timeout reports, it is impossible to decode many protocols since it is not known when the transmission ends. timeout reports are sent by default, but can be turned off. There is no reason to turn them off, and I cannot find any software which does this, so we can safely remove it. This makes the ioctl LIRC_SET_REC_TIMEOUT_REPORTS a no-op. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- .../userspace-api/media/lirc.h.rst.exceptions | 2 + .../userspace-api/media/rc/lirc-dev-intro.rst | 8 ++- .../userspace-api/media/rc/lirc-func.rst | 1 - .../media/rc/lirc-set-rec-timeout-reports.rst | 49 ------------------- drivers/media/rc/lirc_dev.c | 5 -- include/media/rc-core.h | 2 - 6 files changed, 5 insertions(+), 62 deletions(-) delete mode 100644 Documentation/userspace-api/media/rc/lirc-set-rec-timeout-reports.rst diff --git a/Documentation/userspace-api/media/lirc.h.rst.exceptions b/Documentation/userspace-api/media/lirc.h.rst.exceptions index e74b73cd0e9e..ec86e82d026d 100644 --- a/Documentation/userspace-api/media/lirc.h.rst.exceptions +++ b/Documentation/userspace-api/media/lirc.h.rst.exceptions @@ -33,6 +33,7 @@ ignore define LIRC_CAN_SET_REC_DUTY_CYCLE # Obsolete ioctls ignore ioctl LIRC_GET_LENGTH +ignore ioctl LIRC_SET_REC_TIMEOUT_REPORTS # rc protocols @@ -73,6 +74,7 @@ ignore define PULSE_MASK ignore define LIRC_MODE2_SPACE ignore define LIRC_MODE2_PULSE +ignore define LIRC_MODE2_TIMEOUT ignore define LIRC_VALUE_MASK ignore define LIRC_MODE2_MASK diff --git a/Documentation/userspace-api/media/rc/lirc-dev-intro.rst b/Documentation/userspace-api/media/rc/lirc-dev-intro.rst index c88973732282..9a5e5f0aae11 100644 --- a/Documentation/userspace-api/media/rc/lirc-dev-intro.rst +++ b/Documentation/userspace-api/media/rc/lirc-dev-intro.rst @@ -117,11 +117,9 @@ on the following table. ``LIRC_MODE2_TIMEOUT`` - If timeout reports are enabled with - :ref:`lirc_set_rec_timeout_reports`, when the timeout set with - :ref:`lirc_set_rec_timeout` expires due to no IR being detected, - this packet will be sent, with the number of microseconds with - no IR. + When the timeout set with :ref:`lirc_set_rec_timeout` expires due + to no IR being detected, this packet will be sent, with the number + of microseconds with no IR. .. _lirc-mode-pulse: diff --git a/Documentation/userspace-api/media/rc/lirc-func.rst b/Documentation/userspace-api/media/rc/lirc-func.rst index 793f295d3ac9..5c84888f1eca 100644 --- a/Documentation/userspace-api/media/rc/lirc-func.rst +++ b/Documentation/userspace-api/media/rc/lirc-func.rst @@ -22,6 +22,5 @@ LIRC Function Reference lirc-set-rec-carrier-range lirc-set-send-carrier lirc-set-transmitter-mask - lirc-set-rec-timeout-reports lirc-set-measure-carrier-mode lirc-set-wideband-receiver diff --git a/Documentation/userspace-api/media/rc/lirc-set-rec-timeout-reports.rst b/Documentation/userspace-api/media/rc/lirc-set-rec-timeout-reports.rst deleted file mode 100644 index aebe81012939..000000000000 --- a/Documentation/userspace-api/media/rc/lirc-set-rec-timeout-reports.rst +++ /dev/null @@ -1,49 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later -.. c:namespace:: RC - -.. _lirc_set_rec_timeout_reports: - -********************************** -ioctl LIRC_SET_REC_TIMEOUT_REPORTS -********************************** - -Name -==== - -LIRC_SET_REC_TIMEOUT_REPORTS - enable or disable timeout reports for IR receive - -Synopsis -======== - -.. c:macro:: LIRC_SET_REC_TIMEOUT_REPORTS - -``int ioctl(int fd, LIRC_SET_REC_TIMEOUT_REPORTS, __u32 *enable)`` - -Arguments -========= - -``fd`` - File descriptor returned by open(). - -``enable`` - enable = 1 means enable timeout report, enable = 0 means disable timeout - reports. - -Description -=========== - -.. _lirc-mode2-timeout: - -Enable or disable timeout reports for IR receive. By default, timeout reports -should be turned off. - -.. note:: - - This ioctl is only valid for :ref:`LIRC_MODE_MODE2 `. - -Return Value -============ - -On success 0 is returned, on error -1 and the ``errno`` variable is set -appropriately. The generic error codes are described at the -:ref:`Generic Error Codes ` chapter. diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 7f591ff5269d..c7c5157725f8 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -102,8 +102,6 @@ void lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev) spin_lock_irqsave(&dev->lirc_fh_lock, flags); list_for_each_entry(fh, &dev->lirc_fh, list) { - if (LIRC_IS_TIMEOUT(sample) && !fh->send_timeout_reports) - continue; if (kfifo_put(&fh->rawir, sample)) wake_up_poll(&fh->wait_poll, EPOLLIN | EPOLLRDNORM); } @@ -166,7 +164,6 @@ static int lirc_open(struct inode *inode, struct file *file) fh->send_mode = LIRC_MODE_PULSE; fh->rc = dev; - fh->send_timeout_reports = true; if (dev->driver_type == RC_DRIVER_SCANCODE) fh->rec_mode = LIRC_MODE_SCANCODE; @@ -570,8 +567,6 @@ static long lirc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LIRC_SET_REC_TIMEOUT_REPORTS: if (dev->driver_type != RC_DRIVER_IR_RAW) ret = -ENOTTY; - else - fh->send_timeout_reports = !!val; break; default: diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 8c5b7978e1d9..ab9d3b7cd799 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -59,7 +59,6 @@ enum rc_filter_type { * @rc: rcdev for this lirc chardev * @carrier_low: when setting the carrier range, first the low end must be * set with an ioctl and then the high end with another ioctl - * @send_timeout_reports: report timeouts in lirc raw IR. * @rawir: queue for incoming raw IR * @scancodes: queue for incoming decoded scancodes * @wait_poll: poll struct for lirc device @@ -72,7 +71,6 @@ struct lirc_fh { struct list_head list; struct rc_dev *rc; int carrier_low; - bool send_timeout_reports; DECLARE_KFIFO_PTR(rawir, unsigned int); DECLARE_KFIFO_PTR(scancodes, struct lirc_scancode); wait_queue_head_t wait_poll; From b820c2cf0e8d81e5d7c7a547239ca199d0acefcd Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sat, 27 Nov 2021 14:53:49 +0100 Subject: [PATCH 337/397] media: iguanair: no need for reset after IR receiver enable An IR reset is only used when the IR hardware reports an error. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/iguanair.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index 84949baf9f6b..f8d080e41f4c 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c @@ -262,9 +262,6 @@ static int iguanair_receiver(struct iguanair *ir, bool enable) ir->packet->header.direction = DIR_OUT; ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF; - if (enable) - ir_raw_event_reset(ir->rc); - return iguanair_send(ir, sizeof(ir->packet->header)); } From 26748c0d86c2d06b6e3f595bfd843ff2f246ce97 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sat, 27 Nov 2021 18:55:51 +0100 Subject: [PATCH 338/397] media: winbond-cir: no need for reset after resume An IR reset is only used when the IR hardware reports an error. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/winbond-cir.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index aed23ca0fa6c..94efb035d21b 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c @@ -997,7 +997,6 @@ wbcir_resume(struct pnp_dev *device) struct wbcir_data *data = pnp_get_drvdata(device); wbcir_init_hw(data); - ir_raw_event_reset(data->dev); enable_irq(data->irq); led_classdev_resume(&data->led); From 8fede658e7ddb605bbd68ed38067ddb0af033db4 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Tue, 30 Nov 2021 23:58:19 +0100 Subject: [PATCH 339/397] media: igorplugusb: receiver overflow should be reported Without this, some IR will be missing mid-stream and we might decode something which never really occurred. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/igorplugusb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c index effaa5751d6c..3e9988ee785f 100644 --- a/drivers/media/rc/igorplugusb.c +++ b/drivers/media/rc/igorplugusb.c @@ -64,9 +64,11 @@ static void igorplugusb_irdata(struct igorplugusb *ir, unsigned len) if (start >= len) { dev_err(ir->dev, "receive overflow invalid: %u", overflow); } else { - if (overflow > 0) + if (overflow > 0) { dev_warn(ir->dev, "receive overflow, at least %u lost", overflow); + ir_raw_event_reset(ir->rc); + } do { rawir.duration = ir->buf_in[i] * 85; From 4bed9306050497f49cbe77b842f0d812f4f27593 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 5 Dec 2021 18:06:30 +0100 Subject: [PATCH 340/397] media: streamzap: remove unnecessary ir_raw_event_reset and handle There is no reason to have a reset after an IR timeout. Calling ir_raw_event_handle() twice for the same interrupt has no affect. Fixes: 56b0ec30c4bc ("[media] rc/streamzap: fix reporting response times") Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/streamzap.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 1cc5ebb85b6c..76f5c72501c4 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -244,8 +244,6 @@ static void streamzap_callback(struct urb *urb) sz->idle = true; if (sz->timeout_enabled) sz_push(sz, rawir); - ir_raw_event_handle(sz->rdev); - ir_raw_event_reset(sz->rdev); } else { sz_push_full_space(sz, sz->buf_in[i]); } From 7a25e6849ad73de5aa01d62da43071bc02b8530c Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 5 Dec 2021 18:10:36 +0100 Subject: [PATCH 341/397] media: streamzap: no need for usb pid/vid in device name The usb pid/vid can be found elsewhere, the idVendor/idProduct usb sysfs files for example. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/streamzap.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 76f5c72501c4..1de4ce1b2033 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -88,7 +88,6 @@ struct streamzap_ir { ktime_t signal_start; bool timeout_enabled; - char name[128]; char phys[64]; }; @@ -277,13 +276,10 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) goto out; } - snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared Receiver (%04x:%04x)", - le16_to_cpu(sz->usbdev->descriptor.idVendor), - le16_to_cpu(sz->usbdev->descriptor.idProduct)); usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); strlcat(sz->phys, "/input0", sizeof(sz->phys)); - rdev->device_name = sz->name; + rdev->device_name = "Streamzap PC Remote Infrared Receiver"; rdev->input_phys = sz->phys; usb_to_input_id(sz->usbdev, &rdev->input_id); rdev->dev.parent = dev; From 35088717ad24140b6ab0ec00ef357709be607526 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Sun, 5 Dec 2021 22:38:20 +0100 Subject: [PATCH 342/397] media: streamzap: less chatter Remove superfluous messages which add no information. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/streamzap.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 1de4ce1b2033..4d3670d2a913 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -26,7 +26,6 @@ #include #include -#define DRIVER_VERSION "1.61" #define DRIVER_NAME "streamzap" #define DRIVER_DESC "Streamzap Remote Control driver" @@ -271,10 +270,8 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) int ret; rdev = rc_allocate_device(RC_DRIVER_IR_RAW); - if (!rdev) { - dev_err(dev, "remote dev allocation failed\n"); + if (!rdev) goto out; - } usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); strlcat(sz->phys, "/input0", sizeof(sz->phys)); @@ -315,7 +312,6 @@ static int streamzap_probe(struct usb_interface *intf, struct usb_device *usbdev = interface_to_usbdev(intf); struct usb_host_interface *iface_host; struct streamzap_ir *sz = NULL; - char buf[63], name[128] = ""; int retval = -ENOMEM; int pipe, maxp; @@ -374,17 +370,6 @@ static int streamzap_probe(struct usb_interface *intf, sz->dev = &intf->dev; sz->buf_in_len = maxp; - if (usbdev->descriptor.iManufacturer - && usb_string(usbdev, usbdev->descriptor.iManufacturer, - buf, sizeof(buf)) > 0) - strscpy(name, buf, sizeof(name)); - - if (usbdev->descriptor.iProduct - && usb_string(usbdev, usbdev->descriptor.iProduct, - buf, sizeof(buf)) > 0) - snprintf(name + strlen(name), sizeof(name) - strlen(name), - " %s", buf); - sz->rdev = streamzap_init_rc_dev(sz); if (!sz->rdev) goto rc_dev_fail; @@ -415,9 +400,6 @@ static int streamzap_probe(struct usb_interface *intf, if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) dev_err(sz->dev, "urb submit failed\n"); - dev_info(sz->dev, "Registered %s on usb%d:%d\n", name, - usbdev->bus->busnum, usbdev->devnum); - return 0; rc_dev_fail: From 4df69e46c352df9bdbe859824da33428a3ce8a1d Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 6 Dec 2021 11:59:41 +0100 Subject: [PATCH 343/397] media: streamzap: remove unused struct members These struct members do not serve any purpose. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/streamzap.c | 37 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 4d3670d2a913..244a80acacac 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -66,9 +66,6 @@ struct streamzap_ir { struct device *dev; /* usb */ - struct usb_device *usbdev; - struct usb_interface *interface; - struct usb_endpoint_descriptor *endpoint; struct urb *urb_in; /* buffer & dma */ @@ -85,7 +82,6 @@ struct streamzap_ir { /* start time of signal; necessary for gap tracking */ ktime_t signal_last; ktime_t signal_start; - bool timeout_enabled; char phys[64]; }; @@ -240,8 +236,7 @@ static void streamzap_callback(struct urb *urb) .duration = sz->rdev->timeout }; sz->idle = true; - if (sz->timeout_enabled) - sz_push(sz, rawir); + sz_push(sz, rawir); } else { sz_push_full_space(sz, sz->buf_in[i]); } @@ -263,7 +258,8 @@ static void streamzap_callback(struct urb *urb) usb_submit_urb(urb, GFP_ATOMIC); } -static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) +static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz, + struct usb_device *usbdev) { struct rc_dev *rdev; struct device *dev = sz->dev; @@ -273,12 +269,12 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) if (!rdev) goto out; - usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); + usb_make_path(usbdev, sz->phys, sizeof(sz->phys)); strlcat(sz->phys, "/input0", sizeof(sz->phys)); rdev->device_name = "Streamzap PC Remote Infrared Receiver"; rdev->input_phys = sz->phys; - usb_to_input_id(sz->usbdev, &rdev->input_id); + usb_to_input_id(usbdev, &rdev->input_id); rdev->dev.parent = dev; rdev->priv = sz; rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; @@ -310,6 +306,7 @@ static int streamzap_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *usbdev = interface_to_usbdev(intf); + struct usb_endpoint_descriptor *endpoint; struct usb_host_interface *iface_host; struct streamzap_ir *sz = NULL; int retval = -ENOMEM; @@ -320,9 +317,6 @@ static int streamzap_probe(struct usb_interface *intf, if (!sz) return -ENOMEM; - sz->usbdev = usbdev; - sz->interface = intf; - /* Check to ensure endpoint information matches requirements */ iface_host = intf->cur_altsetting; @@ -333,22 +327,22 @@ static int streamzap_probe(struct usb_interface *intf, goto free_sz; } - sz->endpoint = &(iface_host->endpoint[0].desc); - if (!usb_endpoint_dir_in(sz->endpoint)) { + endpoint = &iface_host->endpoint[0].desc; + if (!usb_endpoint_dir_in(endpoint)) { dev_err(&intf->dev, "%s: endpoint doesn't match input device 02%02x\n", - __func__, sz->endpoint->bEndpointAddress); + __func__, endpoint->bEndpointAddress); retval = -ENODEV; goto free_sz; } - if (!usb_endpoint_xfer_int(sz->endpoint)) { + if (!usb_endpoint_xfer_int(endpoint)) { dev_err(&intf->dev, "%s: endpoint attributes don't match xfer 02%02x\n", - __func__, sz->endpoint->bmAttributes); + __func__, endpoint->bmAttributes); retval = -ENODEV; goto free_sz; } - pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress); + pipe = usb_rcvintpipe(usbdev, endpoint->bEndpointAddress); maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe)); if (maxp == 0) { @@ -370,14 +364,13 @@ static int streamzap_probe(struct usb_interface *intf, sz->dev = &intf->dev; sz->buf_in_len = maxp; - sz->rdev = streamzap_init_rc_dev(sz); + sz->rdev = streamzap_init_rc_dev(sz, usbdev); if (!sz->rdev) goto rc_dev_fail; sz->idle = true; sz->decoder_state = PulseSpace; /* FIXME: don't yet have a way to set this */ - sz->timeout_enabled = true; sz->rdev->timeout = SZ_TIMEOUT * SZ_RESOLUTION; #if 0 /* not yet supported, depends on patches from maxim */ @@ -390,8 +383,7 @@ static int streamzap_probe(struct usb_interface *intf, /* Complete final initialisations */ usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in, - maxp, (usb_complete_t)streamzap_callback, - sz, sz->endpoint->bInterval); + maxp, streamzap_callback, sz, endpoint->bInterval); sz->urb_in->transfer_dma = sz->dma_in; sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -432,7 +424,6 @@ static void streamzap_disconnect(struct usb_interface *interface) if (!sz) return; - sz->usbdev = NULL; rc_unregister_device(sz->rdev); usb_kill_urb(sz->urb_in); usb_free_urb(sz->urb_in); From 8b3179b7212c4e3a087708aa1d9b21c4015eeec4 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 6 Dec 2021 12:03:47 +0100 Subject: [PATCH 344/397] media: streamzap: remove redundant gap calculations The lirc core already introduces gaps, so there is no need for this in the driver. Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/streamzap.c | 55 ++++++------------------------------ 1 file changed, 8 insertions(+), 47 deletions(-) diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 244a80acacac..16ba85d7c090 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -75,13 +74,6 @@ struct streamzap_ir { /* track what state we're in */ enum StreamzapDecoderState decoder_state; - /* tracks whether we are currently receiving some signal */ - bool idle; - /* sum of signal lengths received since signal start */ - unsigned long sum; - /* start time of signal; necessary for gap tracking */ - ktime_t signal_last; - ktime_t signal_start; char phys[64]; }; @@ -115,37 +107,11 @@ static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir) static void sz_push_full_pulse(struct streamzap_ir *sz, unsigned char value) { - struct ir_raw_event rawir = {}; + struct ir_raw_event rawir = { + .pulse = true, + .duration = value * SZ_RESOLUTION + SZ_RESOLUTION / 2, + }; - if (sz->idle) { - int delta; - - sz->signal_last = sz->signal_start; - sz->signal_start = ktime_get_real(); - - delta = ktime_us_delta(sz->signal_start, sz->signal_last); - rawir.pulse = false; - if (delta > (15 * USEC_PER_SEC)) { - /* really long time */ - rawir.duration = IR_MAX_DURATION; - } else { - rawir.duration = delta; - rawir.duration -= sz->sum; - rawir.duration = (rawir.duration > IR_MAX_DURATION) ? - IR_MAX_DURATION : rawir.duration; - } - sz_push(sz, rawir); - - sz->idle = false; - sz->sum = 0; - } - - rawir.pulse = true; - rawir.duration = ((int) value) * SZ_RESOLUTION; - rawir.duration += SZ_RESOLUTION / 2; - sz->sum += rawir.duration; - rawir.duration = (rawir.duration > IR_MAX_DURATION) ? - IR_MAX_DURATION : rawir.duration; sz_push(sz, rawir); } @@ -158,12 +124,11 @@ static void sz_push_half_pulse(struct streamzap_ir *sz, static void sz_push_full_space(struct streamzap_ir *sz, unsigned char value) { - struct ir_raw_event rawir = {}; + struct ir_raw_event rawir = { + .pulse = false, + .duration = value * SZ_RESOLUTION + SZ_RESOLUTION / 2, + }; - rawir.pulse = false; - rawir.duration = ((int) value) * SZ_RESOLUTION; - rawir.duration += SZ_RESOLUTION / 2; - sz->sum += rawir.duration; sz_push(sz, rawir); } @@ -235,7 +200,6 @@ static void streamzap_callback(struct urb *urb) .pulse = false, .duration = sz->rdev->timeout }; - sz->idle = true; sz_push(sz, rawir); } else { sz_push_full_space(sz, sz->buf_in[i]); @@ -368,7 +332,6 @@ static int streamzap_probe(struct usb_interface *intf, if (!sz->rdev) goto rc_dev_fail; - sz->idle = true; sz->decoder_state = PulseSpace; /* FIXME: don't yet have a way to set this */ sz->rdev->timeout = SZ_TIMEOUT * SZ_RESOLUTION; @@ -379,8 +342,6 @@ static int streamzap_probe(struct usb_interface *intf, sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION; #endif - sz->signal_start = ktime_get_real(); - /* Complete final initialisations */ usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in, maxp, streamzap_callback, sz, endpoint->bInterval); From 4c1aaf097b83cf48381fcb5f0a5fdf0de318e3a5 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 8 Dec 2021 17:44:18 +0100 Subject: [PATCH 345/397] media: hantro: Fix G2/HEVC negotiated pixelformat G2/HEVC is broken because driver capture queue pixelformat ioctl G_FMT returns VT12 while G2/HEVC always generate NV12 frames: video1: VIDIOC_S_FMT: type=vid-out-mplane, width=2560, height=1600, format=S265 little-endian (0x35363253), field=none, colorspace=0, num_planes=1, flags=0x0, ycbcr_enc=0, quantization=0, xfer_func=0 plane 0: bytesperline=0 sizeimage=6144000 video1: VIDIOC_S_EXT_CTRLS: which=0x0, count=1, error_idx=0, request_fd=0, name=HEVC Sequence Parameter Set, id/size=0x990cf0/32 video1: VIDIOC_G_FMT: type=vid-cap-mplane, width=2560, height=1600, format=VT12 little-endian (0x32315456), field=none, colorspace=0, num_planes=1, flags=0x0, ycbcr_enc=0, quantization=0, xfer_func=0 plane 0: bytesperline=2560 sizeimage=6144000 video1: VIDIOC_ENUM_FMT: index=0, type=vid-cap-mplane, flags=0x0, pixelformat=NV12 little-endian (0x3231564e), mbus_code=0x0000, description='Y/CbCr 4:2:0' video1: VIDIOC_ENUM_FMT: error -22: index=1, type=vid-cap-mplane, flags=0x0, pixelformat=.... little-endian (0x00000000), mbus_code=0x0000, description='' video1: VIDIOC_G_FMT: type=vid-cap-mplane, width=2560, height=1600, format=VT12 little-endian (0x32315456), field=none, colorspace=0, num_planes=1, flags=0x0, ycbcr_enc=0, quantization=0, xfer_func=0 Use the postprocessor functions introduced by Hantro G2/VP9 codec series to fix the issue and remove duplicated buffer management. This allow Hantro G2/HEVC to produce NV12_4L4 and NV12. Fluster scores are 77/147 for HEVC and 129/303 for VP9 (no regression). Beauty, Jockey and ShakeNDry bitstreams from UVG (http://ultravideo.fi/) set have also been tested. Fixes: 53a3e71095c5 ("media: hantro: Simplify postprocessor") Signed-off-by: Benjamin Gaignard Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/hantro/hantro_g2_hevc_dec.c | 25 +++--- drivers/staging/media/hantro/hantro_hevc.c | 79 +++---------------- drivers/staging/media/hantro/hantro_hw.h | 11 +++ .../staging/media/hantro/hantro_postproc.c | 3 + drivers/staging/media/hantro/hantro_v4l2.c | 19 ++--- 5 files changed, 41 insertions(+), 96 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c index f62608b0b408..99d8ea7543da 100644 --- a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c +++ b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c @@ -354,6 +354,8 @@ static int set_ref(struct hantro_ctx *ctx) const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb; dma_addr_t luma_addr, chroma_addr, mv_addr = 0; struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_dst; + struct hantro_decoded_buffer *dst; size_t cr_offset = hantro_hevc_chroma_offset(sps); size_t mv_offset = hantro_hevc_motion_vectors_offset(sps); u32 max_ref_frames; @@ -439,10 +441,15 @@ static int set_ref(struct hantro_ctx *ctx) hantro_write_addr(vpu, G2_REF_MV_ADDR(i), mv_addr); } - luma_addr = hantro_hevc_get_ref_buf(ctx, decode_params->pic_order_cnt_val); + vb2_dst = hantro_get_dst_buf(ctx); + dst = vb2_to_hantro_decoded_buf(&vb2_dst->vb2_buf); + luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf); if (!luma_addr) return -ENOMEM; + if (hantro_hevc_add_ref_buf(ctx, decode_params->pic_order_cnt_val, luma_addr)) + return -EINVAL; + chroma_addr = luma_addr + cr_offset; mv_addr = luma_addr + mv_offset; @@ -469,16 +476,12 @@ static int set_ref(struct hantro_ctx *ctx) static void set_buffers(struct hantro_ctx *ctx) { - struct vb2_v4l2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *src_buf; struct hantro_dev *vpu = ctx->dev; - const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls; - const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps; - size_t cr_offset = hantro_hevc_chroma_offset(sps); - dma_addr_t src_dma, dst_dma; + dma_addr_t src_dma; u32 src_len, src_buf_len; src_buf = hantro_get_src_buf(ctx); - dst_buf = hantro_get_dst_buf(ctx); /* Source (stream) buffer. */ src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); @@ -491,11 +494,6 @@ static void set_buffers(struct hantro_ctx *ctx) hantro_reg_write(vpu, &g2_strm_start_offset, 0); hantro_reg_write(vpu, &g2_write_mvs_e, 1); - /* Destination (decoded frame) buffer. */ - dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf); - - hantro_write_addr(vpu, G2_RS_OUT_LUMA_ADDR, dst_dma); - hantro_write_addr(vpu, G2_RS_OUT_CHROMA_ADDR, dst_dma + cr_offset); hantro_write_addr(vpu, G2_TILE_SIZES_ADDR, ctx->hevc_dec.tile_sizes.dma); hantro_write_addr(vpu, G2_TILE_FILTER_ADDR, ctx->hevc_dec.tile_filter.dma); hantro_write_addr(vpu, G2_TILE_SAO_ADDR, ctx->hevc_dec.tile_sao.dma); @@ -588,9 +586,6 @@ int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx) /* Don't compress buffers */ hantro_reg_write(vpu, &g2_ref_compress_bypass, 1); - /* use NV12 as output format */ - hantro_reg_write(vpu, &g2_out_rs_e, 1); - /* Bus width and max burst */ hantro_reg_write(vpu, &g2_buswidth, BUS_WIDTH_128); hantro_reg_write(vpu, &g2_max_burst, 16); diff --git a/drivers/staging/media/hantro/hantro_hevc.c b/drivers/staging/media/hantro/hantro_hevc.c index ee03123e7704..b49a41d7ae91 100644 --- a/drivers/staging/media/hantro/hantro_hevc.c +++ b/drivers/staging/media/hantro/hantro_hevc.c @@ -44,47 +44,6 @@ size_t hantro_hevc_motion_vectors_offset(const struct v4l2_ctrl_hevc_sps *sps) return ALIGN((cr_offset * 3) / 2, G2_ALIGN); } -static size_t hantro_hevc_mv_size(const struct v4l2_ctrl_hevc_sps *sps) -{ - u32 min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3; - u32 ctb_log2_size_y = min_cb_log2_size_y + sps->log2_diff_max_min_luma_coding_block_size; - u32 pic_width_in_ctbs_y = (sps->pic_width_in_luma_samples + (1 << ctb_log2_size_y) - 1) - >> ctb_log2_size_y; - u32 pic_height_in_ctbs_y = (sps->pic_height_in_luma_samples + (1 << ctb_log2_size_y) - 1) - >> ctb_log2_size_y; - size_t mv_size; - - mv_size = pic_width_in_ctbs_y * pic_height_in_ctbs_y * - (1 << (2 * (ctb_log2_size_y - 4))) * 16; - - vpu_debug(4, "%dx%d (CTBs) %zu MV bytes\n", - pic_width_in_ctbs_y, pic_height_in_ctbs_y, mv_size); - - return mv_size; -} - -static size_t hantro_hevc_ref_size(struct hantro_ctx *ctx) -{ - const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls; - const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps; - - return hantro_hevc_motion_vectors_offset(sps) + hantro_hevc_mv_size(sps); -} - -static void hantro_hevc_ref_free(struct hantro_ctx *ctx) -{ - struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; - struct hantro_dev *vpu = ctx->dev; - int i; - - for (i = 0; i < NUM_REF_PICTURES; i++) { - if (hevc_dec->ref_bufs[i].cpu) - dma_free_coherent(vpu->dev, hevc_dec->ref_bufs[i].size, - hevc_dec->ref_bufs[i].cpu, - hevc_dec->ref_bufs[i].dma); - } -} - static void hantro_hevc_ref_init(struct hantro_ctx *ctx) { struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; @@ -108,37 +67,25 @@ dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, } } - /* Allocate a new reference buffer */ + return 0; +} + +int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr) +{ + struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; + int i; + + /* Add a new reference buffer */ for (i = 0; i < NUM_REF_PICTURES; i++) { if (hevc_dec->ref_bufs_poc[i] == UNUSED_REF) { - if (!hevc_dec->ref_bufs[i].cpu) { - struct hantro_dev *vpu = ctx->dev; - - /* - * Allocate the space needed for the raw data + - * motion vector data. Optimizations could be to - * allocate raw data in non coherent memory and only - * clear the motion vector data. - */ - hevc_dec->ref_bufs[i].cpu = - dma_alloc_coherent(vpu->dev, - hantro_hevc_ref_size(ctx), - &hevc_dec->ref_bufs[i].dma, - GFP_KERNEL); - if (!hevc_dec->ref_bufs[i].cpu) - return 0; - - hevc_dec->ref_bufs[i].size = hantro_hevc_ref_size(ctx); - } hevc_dec->ref_bufs_used |= 1 << i; - memset(hevc_dec->ref_bufs[i].cpu, 0, hantro_hevc_ref_size(ctx)); hevc_dec->ref_bufs_poc[i] = poc; - - return hevc_dec->ref_bufs[i].dma; + hevc_dec->ref_bufs[i].dma = addr; + return 0; } } - return 0; + return -EINVAL; } void hantro_hevc_ref_remove_unused(struct hantro_ctx *ctx) @@ -314,8 +261,6 @@ void hantro_hevc_dec_exit(struct hantro_ctx *ctx) hevc_dec->tile_bsd.cpu, hevc_dec->tile_bsd.dma); hevc_dec->tile_bsd.cpu = NULL; - - hantro_hevc_ref_free(ctx); } int hantro_hevc_dec_init(struct hantro_ctx *ctx) diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index cff817ca8d22..a018748fc4bf 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -346,6 +346,7 @@ void hantro_hevc_dec_exit(struct hantro_ctx *ctx); int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx); int hantro_hevc_dec_prepare_run(struct hantro_ctx *ctx); dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, int poc); +int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr); void hantro_hevc_ref_remove_unused(struct hantro_ctx *ctx); size_t hantro_hevc_chroma_offset(const struct v4l2_ctrl_hevc_sps *sps); size_t hantro_hevc_motion_vectors_offset(const struct v4l2_ctrl_hevc_sps *sps); @@ -395,6 +396,16 @@ hantro_h264_mv_size(unsigned int width, unsigned int height) return 64 * MB_WIDTH(width) * MB_WIDTH(height) + 32; } +static inline size_t +hantro_hevc_mv_size(unsigned int width, unsigned int height) +{ + /* + * A CTB can be 64x64, 32x32 or 16x16. + * Allocated memory for the "worse" case: 16x16 + */ + return width * height / 16; +} + int hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx); int rockchip_vpu2_mpeg2_dec_run(struct hantro_ctx *ctx); void hantro_mpeg2_dec_copy_qtable(u8 *qtable, diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c index a7774ad4c445..248abe5423f0 100644 --- a/drivers/staging/media/hantro/hantro_postproc.c +++ b/drivers/staging/media/hantro/hantro_postproc.c @@ -146,6 +146,9 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_VP9_FRAME) buf_size += hantro_vp9_mv_size(ctx->dst_fmt.width, ctx->dst_fmt.height); + else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE) + buf_size += hantro_hevc_mv_size(ctx->dst_fmt.width, + ctx->dst_fmt.height); for (i = 0; i < num_buffers; ++i) { struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c index c319f0e5fe60..e595905b3bd7 100644 --- a/drivers/staging/media/hantro/hantro_v4l2.c +++ b/drivers/staging/media/hantro/hantro_v4l2.c @@ -148,20 +148,6 @@ static int vidioc_enum_fmt(struct file *file, void *priv, unsigned int num_fmts, i, j = 0; bool skip_mode_none; - /* - * The HEVC decoder on the G2 core needs a little quirk to offer NV12 - * only on the capture side. Once the post-processor logic is used, - * we will be able to expose NV12_4L4 and NV12 as the other cases, - * and therefore remove this quirk. - */ - if (capture && ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE) { - if (f->index == 0) { - f->pixelformat = V4L2_PIX_FMT_NV12; - return 0; - } - return -EINVAL; - } - /* * When dealing with an encoder: * - on the capture side we want to filter out all MODE_NONE formats. @@ -302,6 +288,11 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, pix_mp->plane_fmt[0].sizeimage += hantro_vp9_mv_size(pix_mp->width, pix_mp->height); + else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE && + !hantro_needs_postproc(ctx, fmt)) + pix_mp->plane_fmt[0].sizeimage += + hantro_hevc_mv_size(pix_mp->width, + pix_mp->height); } else if (!pix_mp->plane_fmt[0].sizeimage) { /* * For coded formats the application can specify From 8cc464fdcaaef1a38423c79c29df96db397d8b69 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 26 Nov 2021 09:04:42 +0100 Subject: [PATCH 346/397] media: max96712: Depend on VIDEO_V4L2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Depend on VIDEO_V4L2 for the driver actually depends on it, failing to compile otherwise. Signed-off-by: Sakari Ailus Reviewed-by: Kieran Bingham Reviewed-by: Niklas Söderlund Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/max96712/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/media/max96712/Kconfig b/drivers/staging/media/max96712/Kconfig index 258d47644cbd..acde14fd5c4d 100644 --- a/drivers/staging/media/max96712/Kconfig +++ b/drivers/staging/media/max96712/Kconfig @@ -3,6 +3,7 @@ config VIDEO_MAX96712 tristate "Maxim MAX96712 Quad GMSL2 Deserializer support" depends on I2C depends on OF_GPIO + depends on VIDEO_V4L2 select V4L2_FWNODE select VIDEO_V4L2_SUBDEV_API select MEDIA_CONTROLLER From 9de63c91962b65f8fe2eab1748d9d85621fee08d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 2 Dec 2021 22:03:35 +0100 Subject: [PATCH 347/397] media: i2c: max9286: Get rid of duplicate of_node assignment GPIO library does copy the of_node from the parent device of the GPIO chip, there is no need to repeat this in the individual drivers. Remove assignment here. For the details one may look into the of_gpio_dev_init() implementation. Signed-off-by: Andy Shevchenko Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/max9286.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 7c663fd587bb..a662d3aa0641 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -1055,7 +1055,6 @@ static int max9286_register_gpio(struct max9286_priv *priv) gpio->label = dev_name(dev); gpio->parent = dev; gpio->owner = THIS_MODULE; - gpio->of_node = dev->of_node; gpio->ngpio = 2; gpio->base = -1; gpio->set = max9286_gpio_set; From c00d65e6df8dfe98a595c79eb6ed0ea1067ba565 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Mon, 29 Nov 2021 12:27:06 +0100 Subject: [PATCH 348/397] media: imx6-mipi-csi2: use pre_streamon callback to set sensor into LP11 Step 5 expects that the sensor is in LP11 mode. Use the new pre_streamon callback to signal the sensor that it should switch into LP11. Signed-off-by: Michael Tretter Reviewed-by: Philipp Zabel Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx6-mipi-csi2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c index a0941fc2907b..558b256ac935 100644 --- a/drivers/staging/media/imx/imx6-mipi-csi2.c +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c @@ -382,13 +382,17 @@ static int csi2_start(struct csi2_dev *csi2) csi2_enable(csi2, true); /* Step 5 */ + ret = v4l2_subdev_call(csi2->src_sd, video, pre_streamon, + V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP); + if (ret && ret != -ENOIOCTLCMD) + goto err_assert_reset; csi2_dphy_wait_stopstate(csi2, lanes); /* Step 6 */ ret = v4l2_subdev_call(csi2->src_sd, video, s_stream, 1); ret = (ret && ret != -ENOIOCTLCMD) ? ret : 0; if (ret) - goto err_assert_reset; + goto err_stop_lp11; /* Step 7 */ ret = csi2_dphy_wait_clock_lane(csi2); @@ -399,6 +403,8 @@ static int csi2_start(struct csi2_dev *csi2) err_stop_upstream: v4l2_subdev_call(csi2->src_sd, video, s_stream, 0); +err_stop_lp11: + v4l2_subdev_call(csi2->src_sd, video, post_streamoff); err_assert_reset: csi2_enable(csi2, false); err_disable_clk: @@ -410,6 +416,7 @@ static void csi2_stop(struct csi2_dev *csi2) { /* stop upstream */ v4l2_subdev_call(csi2->src_sd, video, s_stream, 0); + v4l2_subdev_call(csi2->src_sd, video, post_streamoff); csi2_enable(csi2, false); clk_disable_unprepare(csi2->pix_clk); From 589a9f0eb799f77de2c09583bf5bad221fa5d685 Mon Sep 17 00:00:00 2001 From: Anton Vasilyev Date: Thu, 22 Aug 2019 12:41:47 +0200 Subject: [PATCH 349/397] media: dw2102: Fix use after free dvb_usb_device_init stores parts of properties at d->props and d->desc and uses it on dvb_usb_device_exit. Free of properties on module probe leads to use after free. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204597 The patch makes properties static instead of allocated on heap to prevent memleak and use after free. Also fixes s421_properties.devices initialization to have 2 element instead of 6 copied from p7500_properties. [mchehab: fix function call alignments] Link: https://lore.kernel.org/linux-media/20190822104147.4420-1-vasilyev@ispras.ru Signed-off-by: Anton Vasilyev Fixes: 299c7007e936 ("media: dw2102: Fix memleak on sequence of probes") Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 342 ++++++++++++++++++----------- 1 file changed, 217 insertions(+), 125 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index f0e686b05dc6..ca75ebdc10b3 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -2150,46 +2150,153 @@ static struct dvb_usb_device_properties s6x0_properties = { } }; -static const struct dvb_usb_device_description d1100 = { - "Prof 1100 USB ", - {&dw2102_table[PROF_1100], NULL}, - {NULL}, +static struct dvb_usb_device_properties p1100_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + .size_of_priv = sizeof(struct dw2102_state), + .firmware = P1100_FIRMWARE, + .no_reconnect = 1, + + .i2c_algo = &s6x0_i2c_algo, + .rc.core = { + .rc_interval = 150, + .rc_codes = RC_MAP_TBS_NEC, + .module_name = "dw2102", + .allowed_protos = RC_PROTO_BIT_NEC, + .rc_query = prof_rc_query, + }, + + .generic_bulk_ctrl_endpoint = 0x81, + .num_adapters = 1, + .download_firmware = dw2102_load_firmware, + .read_mac_address = s6x0_read_mac_address, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .frontend_attach = stv0288_frontend_attach, + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } }, + } + }, + .num_device_descs = 1, + .devices = { + {"Prof 1100 USB ", + {&dw2102_table[PROF_1100], NULL}, + {NULL}, + }, + } }; -static const struct dvb_usb_device_description d660 = { - "TeVii S660 USB", - {&dw2102_table[TEVII_S660], NULL}, - {NULL}, +static struct dvb_usb_device_properties s660_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + .size_of_priv = sizeof(struct dw2102_state), + .firmware = S660_FIRMWARE, + .no_reconnect = 1, + + .i2c_algo = &s6x0_i2c_algo, + .rc.core = { + .rc_interval = 150, + .rc_codes = RC_MAP_TEVII_NEC, + .module_name = "dw2102", + .allowed_protos = RC_PROTO_BIT_NEC, + .rc_query = dw2102_rc_query, + }, + + .generic_bulk_ctrl_endpoint = 0x81, + .num_adapters = 1, + .download_firmware = dw2102_load_firmware, + .read_mac_address = s6x0_read_mac_address, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .frontend_attach = ds3000_frontend_attach, + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } }, + } + }, + .num_device_descs = 3, + .devices = { + {"TeVii S660 USB", + {&dw2102_table[TEVII_S660], NULL}, + {NULL}, + }, + {"TeVii S480.1 USB", + {&dw2102_table[TEVII_S480_1], NULL}, + {NULL}, + }, + {"TeVii S480.2 USB", + {&dw2102_table[TEVII_S480_2], NULL}, + {NULL}, + }, + } }; -static const struct dvb_usb_device_description d480_1 = { - "TeVii S480.1 USB", - {&dw2102_table[TEVII_S480_1], NULL}, - {NULL}, -}; +static struct dvb_usb_device_properties p7500_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + .size_of_priv = sizeof(struct dw2102_state), + .firmware = P7500_FIRMWARE, + .no_reconnect = 1, -static const struct dvb_usb_device_description d480_2 = { - "TeVii S480.2 USB", - {&dw2102_table[TEVII_S480_2], NULL}, - {NULL}, -}; + .i2c_algo = &s6x0_i2c_algo, + .rc.core = { + .rc_interval = 150, + .rc_codes = RC_MAP_TBS_NEC, + .module_name = "dw2102", + .allowed_protos = RC_PROTO_BIT_NEC, + .rc_query = prof_rc_query, + }, -static const struct dvb_usb_device_description d7500 = { - "Prof 7500 USB DVB-S2", - {&dw2102_table[PROF_7500], NULL}, - {NULL}, -}; - -static const struct dvb_usb_device_description d421 = { - "TeVii S421 PCI", - {&dw2102_table[TEVII_S421], NULL}, - {NULL}, -}; - -static const struct dvb_usb_device_description d632 = { - "TeVii S632 USB", - {&dw2102_table[TEVII_S632], NULL}, - {NULL}, + .generic_bulk_ctrl_endpoint = 0x81, + .num_adapters = 1, + .download_firmware = dw2102_load_firmware, + .read_mac_address = s6x0_read_mac_address, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .frontend_attach = prof_7500_frontend_attach, + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } }, + } + }, + .num_device_descs = 1, + .devices = { + {"Prof 7500 USB DVB-S2", + {&dw2102_table[PROF_7500], NULL}, + {NULL}, + }, + } }; static struct dvb_usb_device_properties su3000_properties = { @@ -2273,6 +2380,59 @@ static struct dvb_usb_device_properties su3000_properties = { } }; +static struct dvb_usb_device_properties s421_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + .size_of_priv = sizeof(struct dw2102_state), + .power_ctrl = su3000_power_ctrl, + .num_adapters = 1, + .identify_state = su3000_identify_state, + .i2c_algo = &su3000_i2c_algo, + + .rc.core = { + .rc_interval = 150, + .rc_codes = RC_MAP_SU3000, + .module_name = "dw2102", + .allowed_protos = RC_PROTO_BIT_RC5, + .rc_query = su3000_rc_query, + }, + + .read_mac_address = su3000_read_mac_address, + + .generic_bulk_ctrl_endpoint = 0x01, + + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .streaming_ctrl = su3000_streaming_ctrl, + .frontend_attach = m88rs2000_frontend_attach, + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + } + } }, + } + }, + .num_device_descs = 2, + .devices = { + { "TeVii S421 PCI", + { &dw2102_table[TEVII_S421], NULL }, + { NULL }, + }, + { "TeVii S632 USB", + { &dw2102_table[TEVII_S632], NULL }, + { NULL }, + }, + } +}; + static struct dvb_usb_device_properties t220_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, @@ -2390,101 +2550,33 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = { static int dw2102_probe(struct usb_interface *intf, const struct usb_device_id *id) { - int retval = -ENOMEM; - struct dvb_usb_device_properties *p1100; - struct dvb_usb_device_properties *s660; - struct dvb_usb_device_properties *p7500; - struct dvb_usb_device_properties *s421; - - p1100 = kmemdup(&s6x0_properties, - sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!p1100) - goto err0; - - /* copy default structure */ - /* fill only different fields */ - p1100->firmware = P1100_FIRMWARE; - p1100->devices[0] = d1100; - p1100->rc.core.rc_query = prof_rc_query; - p1100->rc.core.rc_codes = RC_MAP_TBS_NEC; - p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach; - - s660 = kmemdup(&s6x0_properties, - sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!s660) - goto err1; - - s660->firmware = S660_FIRMWARE; - s660->num_device_descs = 3; - s660->devices[0] = d660; - s660->devices[1] = d480_1; - s660->devices[2] = d480_2; - s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach; - - p7500 = kmemdup(&s6x0_properties, - sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!p7500) - goto err2; - - p7500->firmware = P7500_FIRMWARE; - p7500->devices[0] = d7500; - p7500->rc.core.rc_query = prof_rc_query; - p7500->rc.core.rc_codes = RC_MAP_TBS_NEC; - p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach; - - - s421 = kmemdup(&su3000_properties, - sizeof(struct dvb_usb_device_properties), GFP_KERNEL); - if (!s421) - goto err3; - - s421->num_device_descs = 2; - s421->devices[0] = d421; - s421->devices[1] = d632; - s421->adapter->fe[0].frontend_attach = m88rs2000_frontend_attach; - - if (0 == dvb_usb_device_init(intf, &dw2102_properties, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, &dw2104_properties, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, &dw3101_properties, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, &s6x0_properties, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, p1100, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, s660, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, p7500, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, s421, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, &su3000_properties, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, &t220_properties, - THIS_MODULE, NULL, adapter_nr) || - 0 == dvb_usb_device_init(intf, &tt_s2_4600_properties, - THIS_MODULE, NULL, adapter_nr)) { - - /* clean up copied properties */ - kfree(s421); - kfree(p7500); - kfree(s660); - kfree(p1100); + if (!(dvb_usb_device_init(intf, &dw2102_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &dw2104_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &dw3101_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &s6x0_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &p1100_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &s660_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &p7500_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &s421_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &su3000_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &t220_properties, + THIS_MODULE, NULL, adapter_nr) && + dvb_usb_device_init(intf, &tt_s2_4600_properties, + THIS_MODULE, NULL, adapter_nr))) { return 0; } - retval = -ENODEV; - kfree(s421); -err3: - kfree(p7500); -err2: - kfree(s660); -err1: - kfree(p1100); -err0: - return retval; + return -ENODEV; } static void dw2102_disconnect(struct usb_interface *intf) From a9c976b18a4b66d7109826c60e951959d2b529fe Mon Sep 17 00:00:00 2001 From: Evgeny Novikov Date: Sat, 14 Aug 2021 17:57:42 +0200 Subject: [PATCH 350/397] media: pt3: Switch to using functions pcim_* and devm_* pt3_probe() did not free one of IO mappings in case when one of them was successful while another one failed. The patch fixed that by using functions pcim_*. Also, it simplifies error handling through switching to devm_* functions. Found by Linux Driver Verification project (linuxtesting.org). Link: https://lore.kernel.org/linux-media/20210814155742.11392-1-novikov@ispras.ru Signed-off-by: Evgeny Novikov Co-developed-by: Kirill Shilimanov Signed-off-by: Kirill Shilimanov Reviewed-by: Andy Shevchenko Tested-by: Akihiro Tsukada Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/pt3/pt3.c | 58 +++++++++---------------------------- 1 file changed, 14 insertions(+), 44 deletions(-) diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c index c0bc86793355..0d51bdf01f43 100644 --- a/drivers/media/pci/pt3/pt3.c +++ b/drivers/media/pci/pt3/pt3.c @@ -685,12 +685,6 @@ static void pt3_remove(struct pci_dev *pdev) for (i = PT3_NUM_FE - 1; i >= 0; i--) pt3_cleanup_adapter(pt3, i); i2c_del_adapter(&pt3->i2c_adap); - kfree(pt3->i2c_buf); - pci_iounmap(pt3->pdev, pt3->regs[0]); - pci_iounmap(pt3->pdev, pt3->regs[1]); - pci_release_regions(pdev); - pci_disable_device(pdev); - kfree(pt3); } static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -704,14 +698,14 @@ static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_read_config_byte(pdev, PCI_REVISION_ID, &rev) || rev != 1) return -ENODEV; - ret = pci_enable_device(pdev); + ret = pcim_enable_device(pdev); if (ret < 0) return -ENODEV; pci_set_master(pdev); - ret = pci_request_regions(pdev, DRV_NAME); + ret = pcim_iomap_regions(pdev, BIT(0) | BIT(2), DRV_NAME); if (ret < 0) - goto err_disable_device; + return ret; ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); if (ret == 0) @@ -722,42 +716,32 @@ static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); else { dev_err(&pdev->dev, "Failed to set DMA mask\n"); - goto err_release_regions; + return ret; } dev_info(&pdev->dev, "Use 32bit DMA\n"); } - pt3 = kzalloc(sizeof(*pt3), GFP_KERNEL); - if (!pt3) { - ret = -ENOMEM; - goto err_release_regions; - } + pt3 = devm_kzalloc(&pdev->dev, sizeof(*pt3), GFP_KERNEL); + if (!pt3) + return -ENOMEM; pci_set_drvdata(pdev, pt3); pt3->pdev = pdev; mutex_init(&pt3->lock); - pt3->regs[0] = pci_ioremap_bar(pdev, 0); - pt3->regs[1] = pci_ioremap_bar(pdev, 2); - if (pt3->regs[0] == NULL || pt3->regs[1] == NULL) { - dev_err(&pdev->dev, "Failed to ioremap\n"); - ret = -ENOMEM; - goto err_kfree; - } + pt3->regs[0] = pcim_iomap_table(pdev)[0]; + pt3->regs[1] = pcim_iomap_table(pdev)[2]; ver = ioread32(pt3->regs[0] + REG_VERSION); if ((ver >> 16) != 0x0301) { dev_warn(&pdev->dev, "PT%d, I/F-ver.:%d not supported\n", ver >> 24, (ver & 0x00ff0000) >> 16); - ret = -ENODEV; - goto err_iounmap; + return -ENODEV; } pt3->num_bufs = clamp_val(num_bufs, MIN_DATA_BUFS, MAX_DATA_BUFS); - pt3->i2c_buf = kmalloc(sizeof(*pt3->i2c_buf), GFP_KERNEL); - if (pt3->i2c_buf == NULL) { - ret = -ENOMEM; - goto err_iounmap; - } + pt3->i2c_buf = devm_kmalloc(&pdev->dev, sizeof(*pt3->i2c_buf), GFP_KERNEL); + if (!pt3->i2c_buf) + return -ENOMEM; i2c = &pt3->i2c_adap; i2c->owner = THIS_MODULE; i2c->algo = &pt3_i2c_algo; @@ -767,7 +751,7 @@ static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i2c_set_adapdata(i2c, pt3); ret = i2c_add_adapter(i2c); if (ret < 0) - goto err_i2cbuf; + return ret; for (i = 0; i < PT3_NUM_FE; i++) { ret = pt3_alloc_adapter(pt3, i); @@ -799,21 +783,7 @@ err_cleanup_adapters: while (i >= 0) pt3_cleanup_adapter(pt3, i--); i2c_del_adapter(i2c); -err_i2cbuf: - kfree(pt3->i2c_buf); -err_iounmap: - if (pt3->regs[0]) - pci_iounmap(pdev, pt3->regs[0]); - if (pt3->regs[1]) - pci_iounmap(pdev, pt3->regs[1]); -err_kfree: - kfree(pt3); -err_release_regions: - pci_release_regions(pdev); -err_disable_device: - pci_disable_device(pdev); return ret; - } static const struct pci_device_id pt3_id_table[] = { From c2611e479f5d9b05108270e1ab423955486b4457 Mon Sep 17 00:00:00 2001 From: Mikhail Rudenko Date: Sun, 10 Oct 2021 19:54:57 +0200 Subject: [PATCH 351/397] media: rockchip: rkisp1: use device name for debugfs subdir name While testing Rockchip RK3399 with both ISPs enabled, a dmesg error was observed: ``` [ 15.559141] debugfs: Directory 'rkisp1' with parent '/' already present! ``` Fix it by using the device name for the debugfs subdirectory name instead of the driver name, thus preventing name collision. Link: https://lore.kernel.org/linux-media/20211010175457.438627-1-mike.rudenko@gmail.com Signed-off-by: Mikhail Rudenko Reviewed-by: Ezequiel Garcia Reviewed-by: Kieran Bingham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c index 50b166c49a03..3f5cfa7eb937 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c @@ -462,7 +462,7 @@ static void rkisp1_debug_init(struct rkisp1_device *rkisp1) { struct rkisp1_debug *debug = &rkisp1->debug; - debug->debugfs_dir = debugfs_create_dir(RKISP1_DRIVER_NAME, NULL); + debug->debugfs_dir = debugfs_create_dir(dev_name(rkisp1->dev), NULL); debugfs_create_ulong("data_loss", 0444, debug->debugfs_dir, &debug->data_loss); debugfs_create_ulong("outform_size_err", 0444, debug->debugfs_dir, From 3d5831a40d3464eea158180eb12cbd81c5edfb6a Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Tue, 26 Oct 2021 13:23:48 +0200 Subject: [PATCH 352/397] media: msi001: fix possible null-ptr-deref in msi001_probe() I got a null-ptr-deref report: BUG: kernel NULL pointer dereference, address: 0000000000000060 ... RIP: 0010:v4l2_ctrl_auto_cluster+0x57/0x270 ... Call Trace: msi001_probe+0x13b/0x24b [msi001] spi_probe+0xeb/0x130 ... do_syscall_64+0x35/0xb0 In msi001_probe(), if the creation of control for bandwidth_auto fails, there will be a null-ptr-deref issue when it is used in v4l2_ctrl_auto_cluster(). Check dev->hdl.error before v4l2_ctrl_auto_cluster() to fix this bug. Link: https://lore.kernel.org/linux-media/20211026112348.2878040-1-wanghai38@huawei.com Fixes: 93203dd6c7c4 ("[media] msi001: Mirics MSi001 silicon tuner driver") Reported-by: Hulk Robot Signed-off-by: Wang Hai Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/msi001.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/tuners/msi001.c b/drivers/media/tuners/msi001.c index 78e6fd600d8e..44247049a319 100644 --- a/drivers/media/tuners/msi001.c +++ b/drivers/media/tuners/msi001.c @@ -442,6 +442,13 @@ static int msi001_probe(struct spi_device *spi) V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops, V4L2_CID_RF_TUNER_BANDWIDTH, 200000, 8000000, 1, 200000); + if (dev->hdl.error) { + ret = dev->hdl.error; + dev_err(&spi->dev, "Could not initialize controls\n"); + /* control init failed, free handler */ + goto err_ctrl_handler_free; + } + v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false); dev->lna_gain = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops, V4L2_CID_RF_TUNER_LNA_GAIN, 0, 1, 1, 1); From 34b1df99a5d4a6f3c354fd5ff0ddfbf4f67db2bc Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Sat, 27 Nov 2021 10:49:44 +0100 Subject: [PATCH 353/397] media: staging: max96712: Constify static v4l2_subdev_ops The only usage of max96712_subdev_ops is to pass its address to v4l2_i2c_subdev_init() which takes a pointer to const struct v4l2_subdev_ops as argument. Make it const to allow the compiler to put it in read-only memory. Link: https://lore.kernel.org/linux-media/20211127094945.27985-1-rikard.falkeborn@gmail.com Signed-off-by: Rikard Falkeborn Reviewed-by: Niklas S\xF6derlund Reviewed-by: Kieran Bingham Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/max96712/max96712.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c index 847e2ffd4f53..9bc72d9a858b 100644 --- a/drivers/staging/media/max96712/max96712.c +++ b/drivers/staging/media/max96712/max96712.c @@ -250,7 +250,7 @@ static const struct v4l2_subdev_pad_ops max96712_pad_ops = { .set_fmt = max96712_get_pad_format, }; -static struct v4l2_subdev_ops max96712_subdev_ops = { +static const struct v4l2_subdev_ops max96712_subdev_ops = { .video = &max96712_video_ops, .pad = &max96712_pad_ops, }; From ce560ee5c51d32b450ac453fceeee58a2683019b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Wed, 1 Dec 2021 23:19:40 +0100 Subject: [PATCH 354/397] media: mc: mc-entity.c: Use bitmap_zalloc() when applicable 'ent_enum->bmap' is a bitmap. So use 'bitmap_zalloc()' to simplify code, improve the semantic and avoid some open-coded arithmetic in allocator arguments. Also change the corresponding 'kfree()' into 'bitmap_free()' to keep consistency. While at it, remove a useless 'bitmap_zero()'. Link: https://lore.kernel.org/linux-media/b11f646dda189f490c06bf671f64a2cc0af4d45c.1638397089.git.christophe.jaillet@wanadoo.fr Signed-off-by: Christophe JAILLET Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/mc/mc-entity.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c index c02340698ad6..b411f9796191 100644 --- a/drivers/media/mc/mc-entity.c +++ b/drivers/media/mc/mc-entity.c @@ -48,12 +48,10 @@ __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum, int idx_max) { idx_max = ALIGN(idx_max, BITS_PER_LONG); - ent_enum->bmap = kcalloc(idx_max / BITS_PER_LONG, sizeof(long), - GFP_KERNEL); + ent_enum->bmap = bitmap_zalloc(idx_max, GFP_KERNEL); if (!ent_enum->bmap) return -ENOMEM; - bitmap_zero(ent_enum->bmap, idx_max); ent_enum->idx_max = idx_max; return 0; @@ -62,7 +60,7 @@ EXPORT_SYMBOL_GPL(__media_entity_enum_init); void media_entity_enum_cleanup(struct media_entity_enum *ent_enum) { - kfree(ent_enum->bmap); + bitmap_free(ent_enum->bmap); } EXPORT_SYMBOL_GPL(media_entity_enum_cleanup); From 3af86b046933ba513d08399dba0d4d8b50d607d0 Mon Sep 17 00:00:00 2001 From: Zhou Qingyang Date: Fri, 3 Dec 2021 16:40:30 +0100 Subject: [PATCH 355/397] media: saa7146: hexium_gemini: Fix a NULL pointer dereference in hexium_attach() In hexium_attach(dev, info), saa7146_vv_init() is called to allocate a new memory for dev->vv_data. saa7146_vv_release() will be called on failure of saa7146_register_device(). There is a dereference of dev->vv_data in saa7146_vv_release(), which could lead to a NULL pointer dereference on failure of saa7146_vv_init(). Fix this bug by adding a check of saa7146_vv_init(). This bug was found by a static analyzer. The analysis employs differential checking to identify inconsistent security operations (e.g., checks or kfrees) between two code paths and confirms that the inconsistent operations are not recovered in the current function or the callers, so they constitute bugs. Note that, as a bug found by static analysis, it can be a false positive or hard to trigger. Multiple researchers have cross-reviewed the bug. Builds with CONFIG_VIDEO_HEXIUM_GEMINI=m show no new warnings, and our static analyzer no longer warns about this code. Link: https://lore.kernel.org/linux-media/20211203154030.111210-1-zhou1615@umn.edu Signed-off-by: Zhou Qingyang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146/saa7146_fops.c | 2 +- drivers/media/pci/saa7146/hexium_gemini.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index baf5772c52a9..be3215977714 100644 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c @@ -521,7 +521,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) ERR("out of memory. aborting.\n"); kfree(vv); v4l2_ctrl_handler_free(hdl); - return -1; + return -ENOMEM; } saa7146_video_uops.init(dev,vv); diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c index 2214c74bbbf1..3947701cd6c7 100644 --- a/drivers/media/pci/saa7146/hexium_gemini.c +++ b/drivers/media/pci/saa7146/hexium_gemini.c @@ -284,7 +284,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d hexium_set_input(hexium, 0); hexium->cur_input = 0; - saa7146_vv_init(dev, &vv_data); + ret = saa7146_vv_init(dev, &vv_data); + if (ret) { + i2c_del_adapter(&hexium->i2c_adapter); + kfree(hexium); + return ret; + } vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input; vv_data.vid_ops.vidioc_g_input = vidioc_g_input; From f4217069cd11635bf397ca1b6488ceb8c7bc66ab Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Dec 2021 14:52:28 +0100 Subject: [PATCH 356/397] media: saa7146: fix error logic at saa7146_vv_init() As the first thing this function does is to call v4l2_device_register(), it should call v4l2_device_unregister() if an error occurs, the same way as done at saa7146_vv_release(). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146/saa7146_fops.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index be3215977714..e9a15de6126e 100644 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c @@ -487,6 +487,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) if (hdl->error) { err = hdl->error; v4l2_ctrl_handler_free(hdl); + v4l2_device_unregister(&dev->v4l2_dev); return err; } dev->v4l2_dev.ctrl_handler = hdl; @@ -495,6 +496,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) if (vv == NULL) { ERR("out of memory. aborting.\n"); v4l2_ctrl_handler_free(hdl); + v4l2_device_unregister(&dev->v4l2_dev); return -ENOMEM; } ext_vv->vid_ops = saa7146_video_ioctl_ops; @@ -521,6 +523,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) ERR("out of memory. aborting.\n"); kfree(vv); v4l2_ctrl_handler_free(hdl); + v4l2_device_unregister(&dev->v4l2_dev); return -ENOMEM; } From f66dcb32af19faf49cc4a9222c3152b10c6ec84a Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Tue, 7 Dec 2021 01:38:37 +0100 Subject: [PATCH 357/397] media: Revert "media: uvcvideo: Set unique vdev name based in type" A lot of userspace depends on a descriptive name for vdev. Without this patch, users have a hard time figuring out which camera shall they use for their video conferencing. This reverts commit e3f60e7e1a2b451f538f9926763432249bcf39c4. Link: https://lore.kernel.org/linux-media/20211207003840.1212374-2-ribalda@chromium.org Cc: Fixes: e3f60e7e1a2b ("media: uvcvideo: Set unique vdev name based in type") Reported-by: Nicolas Dufresne Signed-off-by: Ricardo Ribalda Reviewed-by: Laurent Pinchart Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 57152648d8ae..5f394d4efc21 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2195,7 +2195,6 @@ int uvc_register_video_device(struct uvc_device *dev, const struct v4l2_file_operations *fops, const struct v4l2_ioctl_ops *ioctl_ops) { - const char *name; int ret; /* Initialize the video buffers queue. */ @@ -2224,20 +2223,16 @@ int uvc_register_video_device(struct uvc_device *dev, case V4L2_BUF_TYPE_VIDEO_CAPTURE: default: vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - name = "Video Capture"; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; - name = "Video Output"; break; case V4L2_BUF_TYPE_META_CAPTURE: vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; - name = "Metadata"; break; } - snprintf(vdev->name, sizeof(vdev->name), "%s %u", name, - stream->header.bTerminalLink); + strscpy(vdev->name, dev->name, sizeof(vdev->name)); /* * Set the driver data before calling video_register_device, otherwise From 213173d958a3b07169d697faac8bb4b7ae88db49 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 5 Dec 2021 01:17:17 +0100 Subject: [PATCH 358/397] media: saa7146: remove redundant assignments of i to zero The variable i is assigned the value 0 and each time the value is never read after it has been assigned. The assignments are redundant and can be removed. Link: https://lore.kernel.org/linux-media/20211205001717.178416-1-colin.i.king@gmail.com Signed-off-by: Colin Ian King Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7146/mxb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index bf0b9b0914cd..7ded8f5b05cb 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -340,7 +340,7 @@ static int mxb_init_done(struct saa7146_dev* dev) struct tuner_setup tun_setup; v4l2_std_id std = V4L2_STD_PAL_BG; - int i = 0, err = 0; + int i, err = 0; /* mute audio on tea6420s */ tea6420_route(mxb, 6); @@ -349,7 +349,6 @@ static int mxb_init_done(struct saa7146_dev* dev) saa7111a_call(mxb, video, s_std, std); /* select tuner-output on saa7111a */ - i = 0; saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0, SAA7111_FMT_CCIR, 0); From e0471a623c86f698ac2e7c9a4af6c53d9040e514 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 5 Dec 2021 01:22:42 +0100 Subject: [PATCH 359/397] media: davinci: remove redundant assignment to pointer common Pointer common is being assigned a value in a for-loop and the pointer is never read afterwards. The assignment is redundant and can be removed. Link: https://lore.kernel.org/linux-media/20211205002242.202769-1-colin.i.king@gmail.com Signed-off-by: Colin Ian King Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index aba105fa7ef9..8fe55374c5a3 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -1467,7 +1467,6 @@ probe_out: for (k = 0; k < j; k++) { /* Get the pointer to the channel object */ ch = vpif_obj.dev[k]; - common = &ch->common[k]; /* Unregister video device */ video_unregister_device(&ch->video_dev); } From 43f0633f89947df57fe0b5025bdd741768007708 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Mon, 6 Dec 2021 03:22:01 +0100 Subject: [PATCH 360/397] media: coda/imx-vdoa: Handle dma_set_coherent_mask error codes The return value of dma_set_coherent_mask() is not always 0. To catch the exception in case that dma is not support the mask. Link: https://lore.kernel.org/linux-media/20211206022201.1639460-1-jiasheng@iscas.ac.cn Fixes: b0444f18e0b1 ("[media] coda: add i.MX6 VDOA driver") Signed-off-by: Jiasheng Jiang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/imx-vdoa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/coda/imx-vdoa.c b/drivers/media/platform/coda/imx-vdoa.c index 6996d4571e36..00643f37b3e6 100644 --- a/drivers/media/platform/coda/imx-vdoa.c +++ b/drivers/media/platform/coda/imx-vdoa.c @@ -287,7 +287,11 @@ static int vdoa_probe(struct platform_device *pdev) struct resource *res; int ret; - dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "DMA enable failed\n"); + return ret; + } vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL); if (!vdoa) From 232c297a4e86fba1e2497012b1fcde6018d46f50 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 8 Dec 2021 08:35:44 +0100 Subject: [PATCH 361/397] media: c8sectpfe: fix double free in configure_channels() The configure_channels() function has a double free because configure_memdma_and_inputblock() calls free_input_block() and then it's called again in the error handling code. Link: https://lore.kernel.org/linux-media/20211208073544.GA22020@kili Fixes: c5f5d0f99794 ("[media] c8sectpfe: STiH407/10 Linux DVB demux support") Signed-off-by: Dan Carpenter Reviewed-by: Patrice Chotard Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c index e1f520903248..7bb1384e4bad 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c @@ -925,7 +925,6 @@ static int c8sectpfe_remove(struct platform_device *pdev) static int configure_channels(struct c8sectpfei *fei) { int index = 0, ret; - struct channel_info *tsin; struct device_node *child, *np = fei->dev->of_node; /* iterate round each tsin and configure memdma descriptor and IB hw */ @@ -943,10 +942,9 @@ static int configure_channels(struct c8sectpfei *fei) return 0; err_unmap: - for (index = 0; index < fei->tsin_count; index++) { - tsin = fei->channel_data[index]; - free_input_block(fei, tsin); - } + while (--index >= 0) + free_input_block(fei, fei->channel_data[index]); + return ret; } From df78b858e773967112b4444400fb7bb5bd7a9d8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Wed, 8 Dec 2021 13:17:56 +0100 Subject: [PATCH 362/397] media: i2c: max9286: Use dev_err_probe() helper Use the dev_err_probe() helper, instead of open-coding the same operation. While at it retrieve the error once and use it from 'ret' instead of retrieving it twice. Link: https://lore.kernel.org/linux-media/20211208121756.3051565-1-niklas.soderlund+renesas@ragnatech.se Suggested-by: Geert Uytterhoeven Signed-off-by: Niklas S\xF6derlund Reviewed-by: Geert Uytterhoeven Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/max9286.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index a662d3aa0641..eb2b8e42335b 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -1294,11 +1294,9 @@ static int max9286_probe(struct i2c_client *client) priv->regulator = devm_regulator_get(&client->dev, "poc"); if (IS_ERR(priv->regulator)) { - if (PTR_ERR(priv->regulator) != -EPROBE_DEFER) - dev_err(&client->dev, - "Unable to get PoC regulator (%ld)\n", - PTR_ERR(priv->regulator)); ret = PTR_ERR(priv->regulator); + dev_err_probe(&client->dev, ret, + "Unable to get PoC regulator\n"); goto err_powerdown; } From 5d6db4aa3c85e5dd76a7c48073472c70e68b8d13 Mon Sep 17 00:00:00 2001 From: chiminghao Date: Thu, 9 Dec 2021 02:50:09 +0100 Subject: [PATCH 363/397] media: drivers:usb:remove unneeded variable return value form directly instead of taking this in another redundant variable. Link: https://lore.kernel.org/linux-media/20211209015009.409428-1-chi.minghao@zte.com.cn Reported-by: Zeal Robot Signed-off-by: chiminghao Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/m5602/m5602_s5k83a.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c index 4504d615b1e4..8ef010a87445 100644 --- a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c +++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c @@ -407,25 +407,21 @@ static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) { - int err; u8 data[1]; struct sd *sd = (struct sd *) gspca_dev; data[0] = val; - err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1); - return err; + return m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1); } static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val) { - int err; u8 data[2]; struct sd *sd = (struct sd *) gspca_dev; data[0] = 0; data[1] = val; - err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2); - return err; + return m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2); } static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, From 9dd2444f2395f0b9edb4901be3909891ea51a1d9 Mon Sep 17 00:00:00 2001 From: Minghao Chi Date: Fri, 10 Dec 2021 03:47:21 +0100 Subject: [PATCH 364/397] media: vidtv: remove unneeded variable make code cleaner return value form directly instead of taking this in another redundant variable. Link: https://lore.kernel.org/linux-media/20211210024721.425145-1-chi.minghao@zte.com.cn Reported-by: Zeal Robot Signed-off-by: Minghao Chi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/test-drivers/vidtv/vidtv_psi.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/media/test-drivers/vidtv/vidtv_psi.c b/drivers/media/test-drivers/vidtv/vidtv_psi.c index c11ac8dca73d..a5875380ef40 100644 --- a/drivers/media/test-drivers/vidtv/vidtv_psi.c +++ b/drivers/media/test-drivers/vidtv/vidtv_psi.c @@ -94,34 +94,28 @@ static void vidtv_psi_update_version_num(struct vidtv_psi_table_header *h) static u16 vidtv_psi_get_sec_len(struct vidtv_psi_table_header *h) { u16 mask; - u16 ret; mask = GENMASK(11, 0); - ret = be16_to_cpu(h->bitfield) & mask; - return ret; + return be16_to_cpu(h->bitfield) & mask; } u16 vidtv_psi_get_pat_program_pid(struct vidtv_psi_table_pat_program *p) { u16 mask; - u16 ret; mask = GENMASK(12, 0); - ret = be16_to_cpu(p->bitfield) & mask; - return ret; + return be16_to_cpu(p->bitfield) & mask; } u16 vidtv_psi_pmt_stream_get_elem_pid(struct vidtv_psi_table_pmt_stream *s) { u16 mask; - u16 ret; mask = GENMASK(12, 0); - ret = be16_to_cpu(s->bitfield) & mask; - return ret; + return be16_to_cpu(s->bitfield) & mask; } static void vidtv_psi_set_desc_loop_len(__be16 *bitfield, u16 new_len, From 391137c04ec3ab3d27aa4e3081427f490655ec6f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 10 Dec 2021 13:02:01 +0100 Subject: [PATCH 365/397] media: dmxdev: drop unneeded inclusion from other headers There is no evidence we need kernel.h inclusion in certain headers. Drop unneeded inclusion from other headers. Link: https://lore.kernel.org/linux-media/20211210120201.35635-1-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- include/media/dmxdev.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/media/dmxdev.h b/include/media/dmxdev.h index baafa3b8aca4..63219a699370 100644 --- a/include/media/dmxdev.h +++ b/include/media/dmxdev.h @@ -21,7 +21,6 @@ #include #include -#include #include #include #include From 309247892818a5e3075e611570dcdc01183a74c5 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Sun, 12 Dec 2021 08:09:18 +0100 Subject: [PATCH 366/397] media: ivtv: no need to initialise statics to 0 Static variables do not need to be initialised to 0, because compiler will initialise all uninitialised statics to 0. Thus, remove the unneeded initializations. Link: https://lore.kernel.org/linux-media/20211212070918.289617-1-wangborong@cdjrlc.com Signed-off-by: Jason Wang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ivtv/ivtvfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c index 2c43ebf83966..00ac94d4ab19 100644 --- a/drivers/media/pci/ivtv/ivtvfb.c +++ b/drivers/media/pci/ivtv/ivtvfb.c @@ -42,7 +42,7 @@ /* card parameters */ static int ivtvfb_card_id = -1; -static int ivtvfb_debug = 0; +static int ivtvfb_debug; static bool ivtvfb_force_pat = IS_ENABLED(CONFIG_VIDEO_FB_IVTV_FORCE_PAT); static bool osd_laced; static int osd_depth; From 3f81fc9b2ba495d913d16db95c4f04c6becf7701 Mon Sep 17 00:00:00 2001 From: gushengxian Date: Wed, 26 May 2021 09:55:27 +0200 Subject: [PATCH 367/397] media: b2c2-flexcop-usb: fix some whitespace coding style On some places, there's a missing whitespace. Link: https://lore.kernel.org/linux-media/20210526075527.302903-1-13145886936@163.com Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, gushengxian Signed-off-by: gushengxian Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/b2c2/flexcop-usb.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index bfeb92d93de3..7835bb0f32fc 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -171,7 +171,7 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, return ret; } -#define bytes_left_to_read_on_page(paddr,buflen) \ +#define bytes_left_to_read_on_page(paddr, buflen) \ ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \ ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK))) @@ -179,11 +179,11 @@ static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb, flexcop_usb_request_t req, flexcop_usb_mem_page_t page_start, u32 addr, int extended, u8 *buf, u32 len) { - int i,ret = 0; + int i, ret = 0; u16 wMax; u32 pagechunk = 0; - switch(req) { + switch (req) { case B2C2_USB_READ_V8_MEM: wMax = USB_MEM_READ_MAX; break; @@ -341,8 +341,8 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, b = fc_usb->tmp_buffer; l = fc_usb->tmp_buffer_length; } else { - b=buffer; - l=buffer_length; + b = buffer; + l = buffer_length; } while (l >= 190) { @@ -368,7 +368,7 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, } } - if (l>0) + if (l > 0) memcpy(fc_usb->tmp_buffer, b, l); fc_usb->tmp_buffer_length = l; } @@ -399,7 +399,7 @@ static void flexcop_usb_urb_complete(struct urb *urb) urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; } - usb_submit_urb(urb,GFP_ATOMIC); + usb_submit_urb(urb, GFP_ATOMIC); } static int flexcop_usb_stream_control(struct flexcop_device *fc, int onoff) @@ -413,7 +413,7 @@ static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb) int i; for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) if (fc_usb->iso_urb[i] != NULL) { - deb_ts("unlinking/killing urb no. %d\n",i); + deb_ts("unlinking/killing urb no. %d\n", i); usb_kill_urb(fc_usb->iso_urb[i]); usb_free_urb(fc_usb->iso_urb[i]); } @@ -483,7 +483,7 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) err("submitting urb %d failed with %d.", i, ret); goto urb_error; } - deb_ts("submitted urb no. %d.\n",i); + deb_ts("submitted urb no. %d.\n", i); } /* SRAM */ From 2ae5d7e5416982c585a8b8d9d330501a4fbc6c10 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 8 Dec 2021 10:23:45 +0100 Subject: [PATCH 368/397] media: si2157: move firmware load to a separate function Split the firmware load code from si2157_init, in order to help to add further changes at the way firmware is handled on this device. No functional changes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 96 ++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 75ddf7ed1faf..481a5db7fb69 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -76,16 +76,63 @@ err_mutex_unlock: return ret; } -static int si2157_init(struct dvb_frontend *fe) +static int si2157_load_firmware(struct dvb_frontend *fe, + const char *fw_name) { struct i2c_client *client = fe->tuner_priv; - struct si2157_dev *dev = i2c_get_clientdata(client); - struct dtv_frontend_properties *c = &fe->dtv_property_cache; + const struct firmware *fw; int ret, len, remaining; struct si2157_cmd cmd; - const struct firmware *fw; - const char *fw_name; + + /* request the firmware, this will block and timeout */ + ret = request_firmware(&fw, fw_name, &client->dev); + if (ret) + return ret; + + /* firmware should be n chunks of 17 bytes */ + if (fw->size % 17 != 0) { + dev_err(&client->dev, "firmware file '%s' is invalid\n", + fw_name); + ret = -EINVAL; + goto err_release_firmware; + } + + dev_info(&client->dev, "downloading firmware from file '%s'\n", + fw_name); + + for (remaining = fw->size; remaining > 0; remaining -= 17) { + len = fw->data[fw->size - remaining]; + if (len > SI2157_ARGLEN) { + dev_err(&client->dev, "Bad firmware length\n"); + ret = -EINVAL; + goto err_release_firmware; + } + memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); + cmd.wlen = len; + cmd.rlen = 1; + ret = si2157_cmd_execute(client, &cmd); + if (ret) { + dev_err(&client->dev, "firmware download failed %d\n", + ret); + goto err_release_firmware; + } + } + +err_release_firmware: + release_firmware(fw); + + return ret; +} + +static int si2157_init(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct i2c_client *client = fe->tuner_priv; + struct si2157_dev *dev = i2c_get_clientdata(client); unsigned int chip_id, xtal_trim; + struct si2157_cmd cmd; + const char *fw_name; + int ret; dev_dbg(&client->dev, "\n"); @@ -181,45 +228,13 @@ static int si2157_init(struct dvb_frontend *fe) if (fw_name == NULL) goto skip_fw_download; - /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_name, &client->dev); + ret = si2157_load_firmware(fe, fw_name); if (ret) { dev_err(&client->dev, "firmware file '%s' not found\n", - fw_name); + fw_name); goto err; } - /* firmware should be n chunks of 17 bytes */ - if (fw->size % 17 != 0) { - dev_err(&client->dev, "firmware file '%s' is invalid\n", - fw_name); - ret = -EINVAL; - goto err_release_firmware; - } - - dev_info(&client->dev, "downloading firmware from file '%s'\n", - fw_name); - - for (remaining = fw->size; remaining > 0; remaining -= 17) { - len = fw->data[fw->size - remaining]; - if (len > SI2157_ARGLEN) { - dev_err(&client->dev, "Bad firmware length\n"); - ret = -EINVAL; - goto err_release_firmware; - } - memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len); - cmd.wlen = len; - cmd.rlen = 1; - ret = si2157_cmd_execute(client, &cmd); - if (ret) { - dev_err(&client->dev, "firmware download failed %d\n", - ret); - goto err_release_firmware; - } - } - - release_firmware(fw); - skip_fw_download: /* reboot the tuner with new firmware? */ memcpy(cmd.args, "\x01\x01", 2); @@ -270,8 +285,7 @@ warm: dev->active = true; return 0; -err_release_firmware: - release_firmware(fw); + err: dev_dbg(&client->dev, "failed=%d\n", ret); return ret; From 48dde945e7f856f622bd68c076f8a6b5d524d19e Mon Sep 17 00:00:00 2001 From: Robert Schlabbach Date: Wed, 1 Dec 2021 22:10:58 +0100 Subject: [PATCH 369/397] media: si2157: Add optional firmware download The Si2157 (A30) is functional with the ROM firmware 3.0.5, but can also be patched at runtime, e.g. to firmware 3.1.3. However, although a firmware filename for its firmware patch exists, that has only been used for the Si2177 (A30) so far (which indeed takes the binary identical firmware patch). Add support for downloading firmware patches into the Si2157 (A30), but make it optional, so that initialization can succeed with and without a firmware patch being available. Keep the use of request_firmware() for this purpose rather than firmware_request_nowarn(), so that the warning in the log makes users aware that it is possible to provide a firmware for this tuner. The firmware patch is probably also optional for other (if not all) tuners supported by the driver, but since I do not have the others available to test, they are kept mandatory for now to avoid regressions. Signed-off-by: Robert Schlabbach Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 481a5db7fb69..ed28672c060d 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -130,6 +130,7 @@ static int si2157_init(struct dvb_frontend *fe) struct i2c_client *client = fe->tuner_priv; struct si2157_dev *dev = i2c_get_clientdata(client); unsigned int chip_id, xtal_trim; + unsigned int fw_required; struct si2157_cmd cmd; const char *fw_name; int ret; @@ -198,6 +199,10 @@ static int si2157_init(struct dvb_frontend *fe) #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0) #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0) + /* assume firmware is required, unless verified not to be */ + /* only the SI2157_A30 has been verified not to yet */ + fw_required = true; + switch (chip_id) { case SI2158_A20: case SI2148_A20: @@ -206,10 +211,13 @@ static int si2157_init(struct dvb_frontend *fe) case SI2141_A10: fw_name = SI2141_A10_FIRMWARE; break; + case SI2157_A30: + fw_name = SI2157_A30_FIRMWARE; + fw_required = false; + break; case SI2177_A30: fw_name = SI2157_A30_FIRMWARE; break; - case SI2157_A30: case SI2147_A30: case SI2146_A10: fw_name = NULL; @@ -230,6 +238,9 @@ static int si2157_init(struct dvb_frontend *fe) ret = si2157_load_firmware(fe, fw_name); if (ret) { + if (!fw_required) + goto skip_fw_download; + dev_err(&client->dev, "firmware file '%s' not found\n", fw_name); goto err; From 7c2d8ee486b9ebd462dcd0aea1969758522f4c3a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 8 Dec 2021 10:46:59 +0100 Subject: [PATCH 370/397] media: si2157: rework the firmware load logic Loading a firmware file should not be mandatory, as devices could work with an eeprom firmware, if available. Yet, using the eeprom firmware could lead into unpredictable results, so the best is to warn about that. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index ed28672c060d..5f4ae8593864 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -129,8 +129,9 @@ static int si2157_init(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct i2c_client *client = fe->tuner_priv; struct si2157_dev *dev = i2c_get_clientdata(client); + bool warn_firmware_not_loaded = false; unsigned int chip_id, xtal_trim; - unsigned int fw_required; + bool fw_required = true; struct si2157_cmd cmd; const char *fw_name; int ret; @@ -199,10 +200,6 @@ static int si2157_init(struct dvb_frontend *fe) #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0) #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0) - /* assume firmware is required, unless verified not to be */ - /* only the SI2157_A30 has been verified not to yet */ - fw_required = true; - switch (chip_id) { case SI2158_A20: case SI2148_A20: @@ -212,9 +209,8 @@ static int si2157_init(struct dvb_frontend *fe) fw_name = SI2141_A10_FIRMWARE; break; case SI2157_A30: - fw_name = SI2157_A30_FIRMWARE; fw_required = false; - break; + fallthrough; case SI2177_A30: fw_name = SI2157_A30_FIRMWARE; break; @@ -237,12 +233,11 @@ static int si2157_init(struct dvb_frontend *fe) goto skip_fw_download; ret = si2157_load_firmware(fe, fw_name); - if (ret) { - if (!fw_required) - goto skip_fw_download; - - dev_err(&client->dev, "firmware file '%s' not found\n", - fw_name); + if (fw_required && ret == -ENOENT) + warn_firmware_not_loaded = true; + else if (ret < 0) { + dev_err(&client->dev, "error %d when loading firmware file '%s'\n", + ret, fw_name); goto err; } @@ -263,6 +258,11 @@ skip_fw_download: if (ret) goto err; + if (warn_firmware_not_loaded) { + dev_warn(&client->dev, "firmware file '%s' not found. Using firmware from eeprom.\n", + fw_name); + warn_firmware_not_loaded = false; + } dev_info(&client->dev, "firmware version: %c.%c.%d\n", cmd.args[6], cmd.args[7], cmd.args[8]); @@ -298,6 +298,11 @@ warm: return 0; err: + if (warn_firmware_not_loaded) + dev_err(&client->dev, + "firmware file '%s' not found. Can't continue without a firmware.\n", + fw_name); + dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } From 1c35ba3bf97213538b82067acc0f23f18e652226 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 9 Dec 2021 11:56:01 +0100 Subject: [PATCH 371/397] media: si2157: use a different namespace for firmware Each chip at the si21xx TER family seems to have a different firmware, with seems to actually be a patch against the ROM code. Rework the code in order to use different firmware files depending on the chip ID and rom ID. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 180 ++++++++++++++++------------- drivers/media/tuners/si2157_priv.h | 31 +++++ 2 files changed, 132 insertions(+), 79 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 5f4ae8593864..bb590395e81a 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -76,6 +76,19 @@ err_mutex_unlock: return ret; } +static const struct si2157_tuner_info si2157_tuners[] = { + { SI2141, false, 0x60, SI2141_60_FIRMWARE, SI2141_A10_FIRMWARE }, + { SI2141, false, 0x61, SI2141_61_FIRMWARE, SI2141_A10_FIRMWARE }, + { SI2146, false, 0x11, SI2146_11_FIRMWARE, NULL }, + { SI2147, false, 0x50, SI2147_50_FIRMWARE, NULL }, + { SI2148, true, 0x32, SI2148_32_FIRMWARE, SI2158_A20_FIRMWARE }, + { SI2148, true, 0x33, SI2148_33_FIRMWARE, SI2158_A20_FIRMWARE }, + { SI2157, false, 0x50, SI2157_50_FIRMWARE, SI2157_A30_FIRMWARE }, + { SI2158, false, 0x50, SI2158_50_FIRMWARE, SI2158_A20_FIRMWARE }, + { SI2158, false, 0x51, SI2158_51_FIRMWARE, SI2158_A20_FIRMWARE }, + { SI2177, false, 0x50, SI2177_50_FIRMWARE, SI2157_A30_FIRMWARE }, +}; + static int si2157_load_firmware(struct dvb_frontend *fe, const char *fw_name) { @@ -85,7 +98,7 @@ static int si2157_load_firmware(struct dvb_frontend *fe, struct si2157_cmd cmd; /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_name, &client->dev); + ret = firmware_request_nowarn(&fw, fw_name, &client->dev); if (ret) return ret; @@ -124,16 +137,86 @@ err_release_firmware: return ret; } +static int si2157_find_and_load_firmware(struct dvb_frontend *fe) +{ + struct i2c_client *client = fe->tuner_priv; + struct si2157_dev *dev = i2c_get_clientdata(client); + const char *fw_alt_name = NULL; + unsigned char part_id, rom_id; + const char *fw_name = NULL; + struct si2157_cmd cmd; + bool required = true; + int ret, i; + + if (dev->dont_load_firmware) { + dev_info(&client->dev, + "device is buggy, skipping firmware download\n"); + return 0; + } + + /* query chip revision */ + memcpy(cmd.args, "\x02", 1); + cmd.wlen = 1; + cmd.rlen = 13; + ret = si2157_cmd_execute(client, &cmd); + if (ret) + return ret; + + part_id = cmd.args[2]; + rom_id = cmd.args[12]; + + for (i = 0; i < ARRAY_SIZE(si2157_tuners); i++) { + if (si2157_tuners[i].part_id != part_id) + continue; + required = si2157_tuners[i].required; + fw_alt_name = si2157_tuners[i].fw_alt_name; + + /* Both part and rom ID match */ + if (si2157_tuners[i].rom_id == rom_id) { + fw_name = si2157_tuners[i].fw_name; + break; + } + } + + if (!fw_name && !fw_alt_name) { + dev_err(&client->dev, + "unknown chip version Si21%d-%c%c%c ROM 0x%02x\n", + part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id); + return -EINVAL; + } + + dev_info(&client->dev, + "found a 'Silicon Labs Si21%d-%c%c%c ROM 0x%02x'\n", + part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id); + + if (fw_name) + ret = si2157_load_firmware(fe, fw_name); + else + ret = -ENOENT; + + /* Try alternate name, if any */ + if (ret == -ENOENT && fw_alt_name) + ret = si2157_load_firmware(fe, fw_alt_name); + + if (ret == -ENOENT) { + if (!required) { + dev_info(&client->dev, "Using ROM firmware.\n"); + return 0; + } + dev_err(&client->dev, "Can't continue without a firmware.\n"); + } else if (ret < 0) { + dev_err(&client->dev, "error %d when loading firmware\n", ret); + } + return ret; +} + static int si2157_init(struct dvb_frontend *fe) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct i2c_client *client = fe->tuner_priv; struct si2157_dev *dev = i2c_get_clientdata(client); - bool warn_firmware_not_loaded = false; - unsigned int chip_id, xtal_trim; - bool fw_required = true; + unsigned int xtal_trim; struct si2157_cmd cmd; - const char *fw_name; int ret; dev_dbg(&client->dev, "\n"); @@ -176,72 +259,11 @@ static int si2157_init(struct dvb_frontend *fe) goto err; } - if (dev->dont_load_firmware) { - dev_info(&client->dev, "device is buggy, skipping firmware download\n"); - goto skip_fw_download; - } - - /* query chip revision */ - memcpy(cmd.args, "\x02", 1); - cmd.wlen = 1; - cmd.rlen = 13; - ret = si2157_cmd_execute(client, &cmd); - if (ret) + /* Try to load the firmware */ + ret = si2157_find_and_load_firmware(fe); + if (ret < 0) goto err; - chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 | - cmd.args[4] << 0; - - #define SI2177_A30 ('A' << 24 | 77 << 16 | '3' << 8 | '0' << 0) - #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0) - #define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0) - #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0) - #define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0) - #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0) - #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0) - - switch (chip_id) { - case SI2158_A20: - case SI2148_A20: - fw_name = SI2158_A20_FIRMWARE; - break; - case SI2141_A10: - fw_name = SI2141_A10_FIRMWARE; - break; - case SI2157_A30: - fw_required = false; - fallthrough; - case SI2177_A30: - fw_name = SI2157_A30_FIRMWARE; - break; - case SI2147_A30: - case SI2146_A10: - fw_name = NULL; - break; - default: - dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n", - cmd.args[2], cmd.args[1], - cmd.args[3], cmd.args[4]); - ret = -EINVAL; - goto err; - } - - dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n", - cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); - - if (fw_name == NULL) - goto skip_fw_download; - - ret = si2157_load_firmware(fe, fw_name); - if (fw_required && ret == -ENOENT) - warn_firmware_not_loaded = true; - else if (ret < 0) { - dev_err(&client->dev, "error %d when loading firmware file '%s'\n", - ret, fw_name); - goto err; - } - -skip_fw_download: /* reboot the tuner with new firmware? */ memcpy(cmd.args, "\x01\x01", 2); cmd.wlen = 2; @@ -258,11 +280,6 @@ skip_fw_download: if (ret) goto err; - if (warn_firmware_not_loaded) { - dev_warn(&client->dev, "firmware file '%s' not found. Using firmware from eeprom.\n", - fw_name); - warn_firmware_not_loaded = false; - } dev_info(&client->dev, "firmware version: %c.%c.%d\n", cmd.args[6], cmd.args[7], cmd.args[8]); @@ -298,11 +315,6 @@ warm: return 0; err: - if (warn_firmware_not_loaded) - dev_err(&client->dev, - "firmware file '%s' not found. Can't continue without a firmware.\n", - fw_name); - dev_dbg(&client->dev, "failed=%d\n", ret); return ret; } @@ -968,3 +980,13 @@ MODULE_LICENSE("GPL"); MODULE_FIRMWARE(SI2158_A20_FIRMWARE); MODULE_FIRMWARE(SI2141_A10_FIRMWARE); MODULE_FIRMWARE(SI2157_A30_FIRMWARE); +MODULE_FIRMWARE(SI2141_60_FIRMWARE); +MODULE_FIRMWARE(SI2141_61_FIRMWARE); +MODULE_FIRMWARE(SI2146_11_FIRMWARE); +MODULE_FIRMWARE(SI2147_50_FIRMWARE); +MODULE_FIRMWARE(SI2148_32_FIRMWARE); +MODULE_FIRMWARE(SI2148_33_FIRMWARE); +MODULE_FIRMWARE(SI2157_50_FIRMWARE); +MODULE_FIRMWARE(SI2158_50_FIRMWARE); +MODULE_FIRMWARE(SI2158_51_FIRMWARE); +MODULE_FIRMWARE(SI2177_50_FIRMWARE); diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h index ef4796098931..0db21b082ba9 100644 --- a/drivers/media/tuners/si2157_priv.h +++ b/drivers/media/tuners/si2157_priv.h @@ -41,6 +41,23 @@ struct si2157_dev { }; +enum si2157_part_id { + SI2141 = 41, + SI2146 = 46, + SI2147 = 47, + SI2148 = 48, + SI2157 = 57, + SI2158 = 58, + SI2177 = 77, +}; + +struct si2157_tuner_info { + enum si2157_part_id part_id; + unsigned char rom_id; + bool required; + const char *fw_name, *fw_alt_name; +}; + #define SI2157_CHIPTYPE_SI2157 0 #define SI2157_CHIPTYPE_SI2146 1 #define SI2157_CHIPTYPE_SI2141 2 @@ -54,7 +71,21 @@ struct si2157_cmd { unsigned rlen; }; +/* Old firmware namespace */ #define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw" #define SI2141_A10_FIRMWARE "dvb-tuner-si2141-a10-01.fw" #define SI2157_A30_FIRMWARE "dvb-tuner-si2157-a30-01.fw" + +/* New firmware namespace */ +#define SI2141_60_FIRMWARE "dvb_driver_si2141_rom60.fw" +#define SI2141_61_FIRMWARE "dvb_driver_si2141_rom61.fw" +#define SI2146_11_FIRMWARE "dvb_driver_si2146_rom11.fw" +#define SI2147_50_FIRMWARE "dvb_driver_si2147_rom50.fw" +#define SI2148_32_FIRMWARE "dvb_driver_si2148_rom32.fw" +#define SI2148_33_FIRMWARE "dvb_driver_si2148_rom33.fw" +#define SI2157_50_FIRMWARE "dvb_driver_si2157_rom50.fw" +#define SI2158_50_FIRMWARE "dvb_driver_si2178_rom50.fw" +#define SI2158_51_FIRMWARE "dvb_driver_si2158_rom51.fw" +#define SI2177_50_FIRMWARE "dvb_driver_si2177_rom50.fw" + #endif From 805d5a089673cdab794bad561f239384d3f3cc78 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Dec 2021 08:55:20 +0100 Subject: [PATCH 372/397] media: si2157: get rid of chiptype data The driver should be capable of autodetecting its type, so no need to pass it via device driver's data. While here, improve documentation of some of the part_id specific code. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 45 ++++++++++++++++++------------ drivers/media/tuners/si2157_priv.h | 7 +---- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index bb590395e81a..7e44cba67c38 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -185,6 +185,9 @@ static int si2157_find_and_load_firmware(struct dvb_frontend *fe) return -EINVAL; } + /* Update the part id based on device's report */ + dev->part_id = part_id; + dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c ROM 0x%02x'\n", part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id); @@ -235,10 +238,12 @@ static int si2157_init(struct dvb_frontend *fe) dev->if_frequency = 0; /* we no longer know current tuner state */ /* power up */ - if (dev->chiptype == SI2157_CHIPTYPE_SI2146) { + if (dev->part_id == SI2146) { + /* clock_mode = XTAL, clock_freq = 24MHz */ memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9); cmd.wlen = 9; - } else if (dev->chiptype == SI2157_CHIPTYPE_SI2141) { + } else if (dev->part_id == SI2141) { + /* clock_mode: XTAL, xout enabled */ memcpy(cmd.args, "\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 10); cmd.wlen = 10; } else { @@ -247,11 +252,11 @@ static int si2157_init(struct dvb_frontend *fe) } cmd.rlen = 1; ret = si2157_cmd_execute(client, &cmd); - if (ret && (dev->chiptype != SI2157_CHIPTYPE_SI2141 || ret != -EAGAIN)) + if (ret && (dev->part_id != SI2141 || ret != -EAGAIN)) goto err; - /* Si2141 needs a second command before it answers the revision query */ - if (dev->chiptype == SI2157_CHIPTYPE_SI2141) { + /* Si2141 needs a wake up command */ + if (dev->part_id == SI2141) { memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7); cmd.wlen = 7; ret = si2157_cmd_execute(client, &cmd); @@ -493,7 +498,8 @@ static int si2157_set_params(struct dvb_frontend *fe) if (ret) goto err; - if (dev->chiptype == SI2157_CHIPTYPE_SI2146) + /* On SI2146, set DTV AGC source to DLIF_AGC_3DB */ + if (dev->part_id == SI2146) memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6); else memcpy(cmd.args, "\x14\x00\x02\x07\x00\x00", 6); @@ -560,9 +566,9 @@ static int si2157_set_analog_params(struct dvb_frontend *fe, u8 color = 0; /* 0=NTSC/PAL, 0x10=SECAM */ u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */ - if (dev->chiptype != SI2157_CHIPTYPE_SI2157) { - dev_info(&client->dev, "Analog tuning not supported for chiptype=%u\n", - dev->chiptype); + if (dev->part_id != SI2157) { + dev_info(&client->dev, "Analog tuning not supported yet for Si21%d\n", + dev->part_id); ret = -EINVAL; goto err; } @@ -874,7 +880,7 @@ static int si2157_probe(struct i2c_client *client, dev->inversion = cfg->inversion; dev->dont_load_firmware = cfg->dont_load_firmware; dev->if_port = cfg->if_port; - dev->chiptype = (u8)id->driver_data; + dev->part_id = (u8)id->driver_data; dev->if_frequency = 5000000; /* default value of property 0x0706 */ mutex_init(&dev->i2c_mutex); INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work); @@ -917,10 +923,8 @@ static int si2157_probe(struct i2c_client *client, } #endif - dev_info(&client->dev, "Silicon Labs %s successfully attached\n", - dev->chiptype == SI2157_CHIPTYPE_SI2141 ? "Si2141" : - dev->chiptype == SI2157_CHIPTYPE_SI2146 ? - "Si2146" : "Si2147/2148/2157/2158"); + dev_info(&client->dev, "Silicon Labs Si21%d successfully attached\n", + dev->part_id); return 0; @@ -953,11 +957,16 @@ static int si2157_remove(struct i2c_client *client) return 0; } +/* + * The part_id used here will only be used on buggy devices that don't + * accept firmware uploads. Non-buggy devices should just use "si2157" for + * all SiLabs TER tuners, as the driver should auto-detect it. + */ static const struct i2c_device_id si2157_id_table[] = { - {"si2157", SI2157_CHIPTYPE_SI2157}, - {"si2146", SI2157_CHIPTYPE_SI2146}, - {"si2141", SI2157_CHIPTYPE_SI2141}, - {"si2177", SI2157_CHIPTYPE_SI2177}, + {"si2157", SI2157}, + {"si2146", SI2146}, + {"si2141", SI2141}, + {"si2177", SI2177}, {} }; MODULE_DEVICE_TABLE(i2c, si2157_id_table); diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h index 0db21b082ba9..df17a5f03561 100644 --- a/drivers/media/tuners/si2157_priv.h +++ b/drivers/media/tuners/si2157_priv.h @@ -26,7 +26,7 @@ struct si2157_dev { unsigned int active:1; unsigned int inversion:1; unsigned int dont_load_firmware:1; - u8 chiptype; + u8 part_id; u8 if_port; u32 if_frequency; u32 bandwidth; @@ -58,11 +58,6 @@ struct si2157_tuner_info { const char *fw_name, *fw_alt_name; }; -#define SI2157_CHIPTYPE_SI2157 0 -#define SI2157_CHIPTYPE_SI2146 1 -#define SI2157_CHIPTYPE_SI2141 2 -#define SI2157_CHIPTYPE_SI2177 3 - /* firmware command struct */ #define SI2157_ARGLEN 30 struct si2157_cmd { From 6446a22a16699fdebb8a9fa4a8157bb54bf30514 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Dec 2021 13:16:32 +0100 Subject: [PATCH 373/397] media: si2157: add support for ISDB-T and DTMB Those two delivery systems are supported by some of the si2146 tuners, but the current code is missing the setup for those. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 7e44cba67c38..aeecb38b147f 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -483,6 +483,12 @@ static int si2157_set_params(struct dvb_frontend *fe) case SYS_DVBC_ANNEX_A: delivery_system = 0x30; break; + case SYS_ISDBT: + delivery_system = 0x40; + break; + case SYS_DTMB: + delivery_system = 0x60; + break; default: ret = -EINVAL; goto err; From 98c65a3dac95b54bc105e29d492ce18c49353e67 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Dec 2021 13:37:54 +0100 Subject: [PATCH 374/397] media: si2157: add support for 1.7MHz and 6.1 MHz Some tuners allow setting the bandwidth filter to 1.7MHz and 6.1 MHz. Add support for it upstream, as the narrower is the bandwidth filter, the better. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 4 ++++ drivers/media/tuners/si2157_priv.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index aeecb38b147f..2d3937af4f5f 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -458,8 +458,12 @@ static int si2157_set_params(struct dvb_frontend *fe) goto err; } + if (SUPPORTS_1700KHz(dev) && c->bandwidth_hz <= 1700000) + bandwidth = 0x09; if (c->bandwidth_hz <= 6000000) bandwidth = 0x06; + if (SUPPORTS_1700KHz(dev) && c->bandwidth_hz <= 6100000) + bandwidth = 0x10; else if (c->bandwidth_hz <= 7000000) bandwidth = 0x07; else if (c->bandwidth_hz <= 8000000) diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h index df17a5f03561..24849c8ed398 100644 --- a/drivers/media/tuners/si2157_priv.h +++ b/drivers/media/tuners/si2157_priv.h @@ -66,6 +66,11 @@ struct si2157_cmd { unsigned rlen; }; +#define SUPPORTS_1700KHz(dev) (((dev)->part_id == SI2141) || \ + ((dev)->part_id == SI2147) || \ + ((dev)->part_id == SI2157) || \ + ((dev)->part_id == SI2177)) + /* Old firmware namespace */ #define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw" #define SI2141_A10_FIRMWARE "dvb-tuner-si2141-a10-01.fw" From b9aafbd46eb92b3174781661c33bdb2c17d484f1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Dec 2021 13:52:42 +0100 Subject: [PATCH 375/397] media: si2157: add ATV support for si2158 This device also supports ATV, as it has the same API for setting analog TV tuning parameters. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 2 +- drivers/media/tuners/si2157_priv.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 2d3937af4f5f..481c5c3b577d 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -576,7 +576,7 @@ static int si2157_set_analog_params(struct dvb_frontend *fe, u8 color = 0; /* 0=NTSC/PAL, 0x10=SECAM */ u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */ - if (dev->part_id != SI2157) { + if (!SUPPORTS_ATV_IF(dev)) { dev_info(&client->dev, "Analog tuning not supported yet for Si21%d\n", dev->part_id); ret = -EINVAL; diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h index 24849c8ed398..8579e80f7af7 100644 --- a/drivers/media/tuners/si2157_priv.h +++ b/drivers/media/tuners/si2157_priv.h @@ -71,6 +71,9 @@ struct si2157_cmd { ((dev)->part_id == SI2157) || \ ((dev)->part_id == SI2177)) +#define SUPPORTS_ATV_IF(dev) (((dev)->part_id == SI2157) || \ + ((dev)->part_id == SI2158)) + /* Old firmware namespace */ #define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw" #define SI2141_A10_FIRMWARE "dvb-tuner-si2141-a10-01.fw" From 5fcec420cc86c340a8226ffbaafed8dde6d7df08 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 14 Dec 2021 17:13:31 +0100 Subject: [PATCH 376/397] media: Update Intel-submitted camera sensor driver contacts Hyungwoo's e-mail no longer works so I presume he's left the company. Drop Hyungwoo as maintainer on ov5670 driver and remove his e-mail from other sensor drivers. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 1 - drivers/media/i2c/imx319.c | 2 +- drivers/media/i2c/imx355.c | 2 +- drivers/media/i2c/ov13858.c | 2 +- drivers/media/i2c/ov5670.c | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 38235471fed0..79fd8a012893 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14106,7 +14106,6 @@ F: drivers/media/i2c/ov5647.c OMNIVISION OV5670 SENSOR DRIVER M: Chiranjeevi Rapolu -M: Hyungwoo Yang L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c index daa976858e29..a2b5a34de76b 100644 --- a/drivers/media/i2c/imx319.c +++ b/drivers/media/i2c/imx319.c @@ -2565,6 +2565,6 @@ module_i2c_driver(imx319_i2c_driver); MODULE_AUTHOR("Qiu, Tianshu "); MODULE_AUTHOR("Rapolu, Chiranjeevi "); MODULE_AUTHOR("Bingbu Cao "); -MODULE_AUTHOR("Yang, Hyungwoo "); +MODULE_AUTHOR("Yang, Hyungwoo"); MODULE_DESCRIPTION("Sony imx319 sensor driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c index cb51c81786bd..3922b9305978 100644 --- a/drivers/media/i2c/imx355.c +++ b/drivers/media/i2c/imx355.c @@ -1851,6 +1851,6 @@ module_i2c_driver(imx355_i2c_driver); MODULE_AUTHOR("Qiu, Tianshu "); MODULE_AUTHOR("Rapolu, Chiranjeevi "); MODULE_AUTHOR("Bingbu Cao "); -MODULE_AUTHOR("Yang, Hyungwoo "); +MODULE_AUTHOR("Yang, Hyungwoo"); MODULE_DESCRIPTION("Sony imx355 sensor driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c index b4d22f5d9933..d5fe67c763f7 100644 --- a/drivers/media/i2c/ov13858.c +++ b/drivers/media/i2c/ov13858.c @@ -1818,6 +1818,6 @@ module_i2c_driver(ov13858_i2c_driver); MODULE_AUTHOR("Kan, Chris "); MODULE_AUTHOR("Rapolu, Chiranjeevi "); -MODULE_AUTHOR("Yang, Hyungwoo "); +MODULE_AUTHOR("Yang, Hyungwoo"); MODULE_DESCRIPTION("Omnivision ov13858 sensor driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index 251f459ab484..165cb34ca202 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -2585,6 +2585,6 @@ static struct i2c_driver ov5670_i2c_driver = { module_i2c_driver(ov5670_i2c_driver); MODULE_AUTHOR("Rapolu, Chiranjeevi "); -MODULE_AUTHOR("Yang, Hyungwoo "); +MODULE_AUTHOR("Yang, Hyungwoo"); MODULE_DESCRIPTION("Omnivision ov5670 sensor driver"); MODULE_LICENSE("GPL v2"); From 6ab7030039241c2667f5a7ad94935878279c9370 Mon Sep 17 00:00:00 2001 From: Jean-Michel Hautbois Date: Tue, 5 Oct 2021 22:20:19 +0200 Subject: [PATCH 377/397] media: staging: ipu3-imgu: add the AWB memory layout While parsing the RAW AWB metadata, the AWB layout was missing to fully understand which byte corresponds to which feature. Make the field names and usage explicit, as it is used by the userspace applications. [Sakari Ailus: Changed wording of sat_ratio field as per review comments, fixed a whitespace issue.] Signed-off-by: Jean-Michel Hautbois Reviewed-by: Laurent Pinchart Reviewed-by: Bingbu Cao Reviewed-by: Tomasz Figa Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../media/ipu3/include/uapi/intel-ipu3.h | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h b/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h index a3ffd486d291..dbdd015ce220 100644 --- a/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h +++ b/drivers/staging/media/ipu3/include/uapi/intel-ipu3.h @@ -67,17 +67,39 @@ struct ipu3_uapi_grid_config { __u16 y_end; } __packed; +/** + * struct ipu3_uapi_awb_set_item - Memory layout for each cell in AWB + * + * @Gr_avg: Green average for red lines in the cell. + * @R_avg: Red average in the cell. + * @B_avg: Blue average in the cell. + * @Gb_avg: Green average for blue lines in the cell. + * @sat_ratio: Percentage of pixels over the thresholds specified in + * ipu3_uapi_awb_config_s, coded from 0 to 255. + * @padding0: Unused byte for padding. + * @padding1: Unused byte for padding. + * @padding2: Unused byte for padding. + */ +struct ipu3_uapi_awb_set_item { + __u8 Gr_avg; + __u8 R_avg; + __u8 B_avg; + __u8 Gb_avg; + __u8 sat_ratio; + __u8 padding0; + __u8 padding1; + __u8 padding2; +} __attribute__((packed)); + /* * The grid based data is divided into "slices" called set, each slice of setX * refers to ipu3_uapi_grid_config width * height_per_slice. */ #define IPU3_UAPI_AWB_MAX_SETS 60 /* Based on grid size 80 * 60 and cell size 16 x 16 */ -#define IPU3_UAPI_AWB_SET_SIZE 1280 -#define IPU3_UAPI_AWB_MD_ITEM_SIZE 8 +#define IPU3_UAPI_AWB_SET_SIZE 160 #define IPU3_UAPI_AWB_SPARE_FOR_BUBBLES \ - (IPU3_UAPI_MAX_BUBBLE_SIZE * IPU3_UAPI_MAX_STRIPES * \ - IPU3_UAPI_AWB_MD_ITEM_SIZE) + (IPU3_UAPI_MAX_BUBBLE_SIZE * IPU3_UAPI_MAX_STRIPES) #define IPU3_UAPI_AWB_MAX_BUFFER_SIZE \ (IPU3_UAPI_AWB_MAX_SETS * \ (IPU3_UAPI_AWB_SET_SIZE + IPU3_UAPI_AWB_SPARE_FOR_BUBBLES)) @@ -89,7 +111,7 @@ struct ipu3_uapi_grid_config { * the average values for each color channel. */ struct ipu3_uapi_awb_raw_buffer { - __u8 meta_data[IPU3_UAPI_AWB_MAX_BUFFER_SIZE] + struct ipu3_uapi_awb_set_item meta_data[IPU3_UAPI_AWB_MAX_BUFFER_SIZE] __attribute__((aligned(32))); } __packed; From cbe0b3af73bf72fad197756f026084404e2bcdc7 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 15 Dec 2021 09:38:48 +0100 Subject: [PATCH 378/397] media: ov8865: Disable only enabled regulators on error path If powering on the sensor failed, the entire power-off sequence was run independently of how far the power-on sequence proceeded before the error. This lead to disabling regulators and/or clock that was not enabled. Fix this by disabling only clocks and regulators that were enabled previously. Fixes: 11c0d8fdccc5 ("media: i2c: Add support for the OV8865 image sensor") Cc: stable@vger.kernel.org Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8865.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index ebdb20d3fe9d..d9d016cfa9ac 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2407,27 +2407,27 @@ static int ov8865_sensor_power(struct ov8865_sensor *sensor, bool on) if (ret) { dev_err(sensor->dev, "failed to enable DOVDD regulator\n"); - goto disable; + return ret; } ret = regulator_enable(sensor->avdd); if (ret) { dev_err(sensor->dev, "failed to enable AVDD regulator\n"); - goto disable; + goto disable_dovdd; } ret = regulator_enable(sensor->dvdd); if (ret) { dev_err(sensor->dev, "failed to enable DVDD regulator\n"); - goto disable; + goto disable_avdd; } ret = clk_prepare_enable(sensor->extclk); if (ret) { dev_err(sensor->dev, "failed to enable EXTCLK clock\n"); - goto disable; + goto disable_dvdd; } gpiod_set_value_cansleep(sensor->reset, 0); @@ -2436,14 +2436,16 @@ static int ov8865_sensor_power(struct ov8865_sensor *sensor, bool on) /* Time to enter streaming mode according to power timings. */ usleep_range(10000, 12000); } else { -disable: gpiod_set_value_cansleep(sensor->powerdown, 1); gpiod_set_value_cansleep(sensor->reset, 1); clk_disable_unprepare(sensor->extclk); +disable_dvdd: regulator_disable(sensor->dvdd); +disable_avdd: regulator_disable(sensor->avdd); +disable_dovdd: regulator_disable(sensor->dovdd); } From 0e014f1a8d546fb591c46c461fdb35244294daa1 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Wed, 15 Dec 2021 12:08:58 +0100 Subject: [PATCH 379/397] media: ov8856: support device probe in non-zero ACPI D state Tell ACPI device PM code that the driver supports the device being in non-zero ACPI D state when the driver's probe function is entered. Also do identification on the first access of the device, whether in probe or when starting streaming. Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov8856.c | 162 ++++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 73 deletions(-) diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c index c6c6050cda1a..8785764b7a74 100644 --- a/drivers/media/i2c/ov8856.c +++ b/drivers/media/i2c/ov8856.c @@ -1445,6 +1445,9 @@ struct ov8856 { const struct ov8856_lane_cfg *priv_lane; u8 modes_size; + + /* True if the device has been identified */ + bool identified; }; struct ov8856_lane_cfg { @@ -1685,6 +1688,71 @@ static int ov8856_write_reg_list(struct ov8856 *ov8856, return 0; } +static int ov8856_identify_module(struct ov8856 *ov8856) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd); + int ret; + u32 val; + + if (ov8856->identified) + return 0; + + ret = ov8856_read_reg(ov8856, OV8856_REG_CHIP_ID, + OV8856_REG_VALUE_24BIT, &val); + if (ret) + return ret; + + if (val != OV8856_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x", + OV8856_CHIP_ID, val); + return -ENXIO; + } + + ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT, + OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING); + if (ret) + return ret; + + ret = ov8856_write_reg(ov8856, OV8856_OTP_MODE_CTRL, + OV8856_REG_VALUE_08BIT, OV8856_OTP_MODE_AUTO); + if (ret) { + dev_err(&client->dev, "failed to set otp mode"); + return ret; + } + + ret = ov8856_write_reg(ov8856, OV8856_OTP_LOAD_CTRL, + OV8856_REG_VALUE_08BIT, + OV8856_OTP_LOAD_CTRL_ENABLE); + if (ret) { + dev_err(&client->dev, "failed to enable load control"); + return ret; + } + + ret = ov8856_read_reg(ov8856, OV8856_MODULE_REVISION, + OV8856_REG_VALUE_08BIT, &val); + if (ret) { + dev_err(&client->dev, "failed to read module revision"); + return ret; + } + + dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n", + val, + val == OV8856_2A_MODULE ? "2A" : + val == OV8856_1B_MODULE ? "1B" : "unknown revision", + client->addr); + + ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT, + OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY); + if (ret) { + dev_err(&client->dev, "failed to exit streaming mode"); + return ret; + } + + ov8856->identified = true; + + return 0; +} + static int ov8856_update_digital_gain(struct ov8856 *ov8856, u32 d_gain) { int ret; @@ -1969,6 +2037,10 @@ static int ov8856_start_streaming(struct ov8856 *ov8856) const struct ov8856_reg_list *reg_list; int link_freq_index, ret; + ret = ov8856_identify_module(ov8856); + if (ret) + return ret; + link_freq_index = ov8856->cur_mode->link_freq_index; reg_list = &ov8856->priv_lane->link_freq_configs[link_freq_index].reg_list; @@ -2276,65 +2348,6 @@ static const struct v4l2_subdev_internal_ops ov8856_internal_ops = { .open = ov8856_open, }; -static int ov8856_identify_module(struct ov8856 *ov8856) -{ - struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd); - int ret; - u32 val; - - ret = ov8856_read_reg(ov8856, OV8856_REG_CHIP_ID, - OV8856_REG_VALUE_24BIT, &val); - if (ret) - return ret; - - if (val != OV8856_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", - OV8856_CHIP_ID, val); - return -ENXIO; - } - - ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT, - OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING); - if (ret) - return ret; - - ret = ov8856_write_reg(ov8856, OV8856_OTP_MODE_CTRL, - OV8856_REG_VALUE_08BIT, OV8856_OTP_MODE_AUTO); - if (ret) { - dev_err(&client->dev, "failed to set otp mode"); - return ret; - } - - ret = ov8856_write_reg(ov8856, OV8856_OTP_LOAD_CTRL, - OV8856_REG_VALUE_08BIT, - OV8856_OTP_LOAD_CTRL_ENABLE); - if (ret) { - dev_err(&client->dev, "failed to enable load control"); - return ret; - } - - ret = ov8856_read_reg(ov8856, OV8856_MODULE_REVISION, - OV8856_REG_VALUE_08BIT, &val); - if (ret) { - dev_err(&client->dev, "failed to read module revision"); - return ret; - } - - dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n", - val, - val == OV8856_2A_MODULE ? "2A" : - val == OV8856_1B_MODULE ? "1B" : "unknown revision", - client->addr); - - ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT, - OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY); - if (ret) { - dev_err(&client->dev, "failed to exit streaming mode"); - return ret; - } - - return 0; -} static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev) { @@ -2458,6 +2471,7 @@ static int ov8856_probe(struct i2c_client *client) { struct ov8856 *ov8856; int ret; + bool full_power; ov8856 = devm_kzalloc(&client->dev, sizeof(*ov8856), GFP_KERNEL); if (!ov8856) @@ -2472,16 +2486,19 @@ static int ov8856_probe(struct i2c_client *client) v4l2_i2c_subdev_init(&ov8856->sd, client, &ov8856_subdev_ops); - ret = __ov8856_power_on(ov8856); - if (ret) { - dev_err(&client->dev, "failed to power on\n"); - return ret; - } + full_power = acpi_dev_state_d0(&client->dev); + if (full_power) { + ret = __ov8856_power_on(ov8856); + if (ret) { + dev_err(&client->dev, "failed to power on\n"); + return ret; + } - ret = ov8856_identify_module(ov8856); - if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); - goto probe_power_off; + ret = ov8856_identify_module(ov8856); + if (ret) { + dev_err(&client->dev, "failed to find sensor: %d", ret); + goto probe_power_off; + } } mutex_init(&ov8856->mutex); @@ -2511,11 +2528,9 @@ static int ov8856_probe(struct i2c_client *client) goto probe_error_media_entity_cleanup; } - /* - * Device is already turned on by i2c-core with ACPI domain PM. - * Enable runtime PM and turn off the device. - */ - pm_runtime_set_active(&client->dev); + /* Set the device's state to active if it's in D0 state. */ + if (full_power) + pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); @@ -2562,6 +2577,7 @@ static struct i2c_driver ov8856_i2c_driver = { }, .probe_new = ov8856_probe, .remove = ov8856_remove, + .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; module_i2c_driver(ov8856_i2c_driver); From 1e583b56e5e7469efd4c8ac184daa56944840e72 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 15 Dec 2021 12:08:59 +0100 Subject: [PATCH 380/397] media: ov5670: Support device probe in non-zero ACPI D state Tell ACPI device PM code that the driver supports the device being in non-zero ACPI D state when the driver's probe function is entered. Also do identification on the first access of the device, whether in probe or when starting streaming. Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov5670.c | 78 ++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index 165cb34ca202..02f75c18e480 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -1833,6 +1833,8 @@ struct ov5670 { /* Streaming on/off */ bool streaming; + /* True if the device has been identified */ + bool identified; }; #define to_ov5670(_sd) container_of(_sd, struct ov5670, sd) @@ -2273,6 +2275,32 @@ static int ov5670_get_skip_frames(struct v4l2_subdev *sd, u32 *frames) return 0; } +/* Verify chip ID */ +static int ov5670_identify_module(struct ov5670 *ov5670) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); + int ret; + u32 val; + + if (ov5670->identified) + return 0; + + ret = ov5670_read_reg(ov5670, OV5670_REG_CHIP_ID, + OV5670_REG_VALUE_24BIT, &val); + if (ret) + return ret; + + if (val != OV5670_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + OV5670_CHIP_ID, val); + return -ENXIO; + } + + ov5670->identified = true; + + return 0; +} + /* Prepare streaming by writing default values and customized values */ static int ov5670_start_streaming(struct ov5670 *ov5670) { @@ -2281,6 +2309,10 @@ static int ov5670_start_streaming(struct ov5670 *ov5670) int link_freq_index; int ret; + ret = ov5670_identify_module(ov5670); + if (ret) + return ret; + /* Get out of from software reset */ ret = ov5670_write_reg(ov5670, OV5670_REG_SOFTWARE_RST, OV5670_REG_VALUE_08BIT, OV5670_SOFTWARE_RST); @@ -2400,27 +2432,6 @@ static int __maybe_unused ov5670_resume(struct device *dev) return 0; } -/* Verify chip ID */ -static int ov5670_identify_module(struct ov5670 *ov5670) -{ - struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd); - int ret; - u32 val; - - ret = ov5670_read_reg(ov5670, OV5670_REG_CHIP_ID, - OV5670_REG_VALUE_24BIT, &val); - if (ret) - return ret; - - if (val != OV5670_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", - OV5670_CHIP_ID, val); - return -ENXIO; - } - - return 0; -} - static const struct v4l2_subdev_core_ops ov5670_core_ops = { .log_status = v4l2_ctrl_subdev_log_status, .subscribe_event = v4l2_ctrl_subdev_subscribe_event, @@ -2462,6 +2473,7 @@ static int ov5670_probe(struct i2c_client *client) struct ov5670 *ov5670; const char *err_msg; u32 input_clk = 0; + bool full_power; int ret; device_property_read_u32(&client->dev, "clock-frequency", &input_clk); @@ -2478,11 +2490,14 @@ static int ov5670_probe(struct i2c_client *client) /* Initialize subdev */ v4l2_i2c_subdev_init(&ov5670->sd, client, &ov5670_subdev_ops); - /* Check module identity */ - ret = ov5670_identify_module(ov5670); - if (ret) { - err_msg = "ov5670_identify_module() error"; - goto error_print; + full_power = acpi_dev_state_d0(&client->dev); + if (full_power) { + /* Check module identity */ + ret = ov5670_identify_module(ov5670); + if (ret) { + err_msg = "ov5670_identify_module() error"; + goto error_print; + } } mutex_init(&ov5670->mutex); @@ -2519,11 +2534,9 @@ static int ov5670_probe(struct i2c_client *client) ov5670->streaming = false; - /* - * Device is already turned on by i2c-core with ACPI domain PM. - * Enable runtime PM and turn off the device. - */ - pm_runtime_set_active(&client->dev); + /* Set the device's state to active if it's in D0 state. */ + if (full_power) + pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); @@ -2565,7 +2578,7 @@ static const struct dev_pm_ops ov5670_pm_ops = { #ifdef CONFIG_ACPI static const struct acpi_device_id ov5670_acpi_ids[] = { - {"INT3479"}, + { "INT3479" }, { /* sentinel */ } }; @@ -2580,6 +2593,7 @@ static struct i2c_driver ov5670_i2c_driver = { }, .probe_new = ov5670_probe, .remove = ov5670_remove, + .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; module_i2c_driver(ov5670_i2c_driver); From ada2c4f54d0ae933c4f257abf604849ef0f6de4a Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Wed, 15 Dec 2021 12:09:00 +0100 Subject: [PATCH 381/397] media: ov2740: support device probe in non-zero ACPI D state Tell ACPI device PM code that the driver supports the device being in non-zero ACPI D state when the driver's probe function is entered. Also do identification on the first access of the device, whether in probe or when starting streaming. Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov2740.c | 69 +++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c index 934c9d65cb09..bab720c7c1de 100644 --- a/drivers/media/i2c/ov2740.c +++ b/drivers/media/i2c/ov2740.c @@ -345,6 +345,9 @@ struct ov2740 { /* NVM data inforamtion */ struct nvm_data *nvm; + + /* True if the device has been identified */ + bool identified; }; static inline struct ov2740 *to_ov2740(struct v4l2_subdev *subdev) @@ -440,6 +443,30 @@ static int ov2740_write_reg_list(struct ov2740 *ov2740, return 0; } +static int ov2740_identify_module(struct ov2740 *ov2740) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); + int ret; + u32 val; + + if (ov2740->identified) + return 0; + + ret = ov2740_read_reg(ov2740, OV2740_REG_CHIP_ID, 3, &val); + if (ret) + return ret; + + if (val != OV2740_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x", + OV2740_CHIP_ID, val); + return -ENXIO; + } + + ov2740->identified = true; + + return 0; +} + static int ov2740_update_digital_gain(struct ov2740 *ov2740, u32 d_gain) { int ret = 0; @@ -724,6 +751,10 @@ static int ov2740_start_streaming(struct ov2740 *ov2740) int link_freq_index; int ret = 0; + ret = ov2740_identify_module(ov2740); + if (ret) + return ret; + ov2740_load_otp_data(nvm); link_freq_index = ov2740->cur_mode->link_freq_index; @@ -956,25 +987,6 @@ static const struct v4l2_subdev_internal_ops ov2740_internal_ops = { .open = ov2740_open, }; -static int ov2740_identify_module(struct ov2740 *ov2740) -{ - struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd); - int ret; - u32 val; - - ret = ov2740_read_reg(ov2740, OV2740_REG_CHIP_ID, 3, &val); - if (ret) - return ret; - - if (val != OV2740_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", - OV2740_CHIP_ID, val); - return -ENXIO; - } - - return 0; -} - static int ov2740_check_hwcfg(struct device *dev) { struct fwnode_handle *ep; @@ -1137,6 +1149,7 @@ static int ov2740_probe(struct i2c_client *client) { struct ov2740 *ov2740; int ret = 0; + bool full_power; ret = ov2740_check_hwcfg(&client->dev); if (ret) { @@ -1149,6 +1162,15 @@ static int ov2740_probe(struct i2c_client *client) if (!ov2740) return -ENOMEM; + full_power = acpi_dev_state_d0(&client->dev); + if (full_power) { + ret = ov2740_identify_module(ov2740); + if (ret) { + dev_err(&client->dev, "failed to find sensor: %d", ret); + return ret; + } + } + v4l2_i2c_subdev_init(&ov2740->sd, client, &ov2740_subdev_ops); ret = ov2740_identify_module(ov2740); if (ret) { @@ -1186,11 +1208,9 @@ static int ov2740_probe(struct i2c_client *client) if (ret) dev_warn(&client->dev, "register nvmem failed, ret %d\n", ret); - /* - * Device is already turned on by i2c-core with ACPI domain PM. - * Enable runtime PM and turn off the device. - */ - pm_runtime_set_active(&client->dev); + /* Set the device's state to active if it's in D0 state. */ + if (full_power) + pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); @@ -1225,6 +1245,7 @@ static struct i2c_driver ov2740_i2c_driver = { }, .probe_new = ov2740_probe, .remove = ov2740_remove, + .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; module_i2c_driver(ov2740_i2c_driver); From 56ca3be85f3d33d050e65027c63ccad4425581c9 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Wed, 15 Dec 2021 12:09:01 +0100 Subject: [PATCH 382/397] media: imx208: Support device probe in non-zero ACPI D state Tell ACPI device PM code that the driver supports the device being in non-zero ACPI D state when the driver's probe function is entered. Also do identification on the first access of the device, whether in probe or when starting streaming. Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/imx208.c | 82 ++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/drivers/media/i2c/imx208.c b/drivers/media/i2c/imx208.c index 6f3d9c1b5879..b9516b2f1c15 100644 --- a/drivers/media/i2c/imx208.c +++ b/drivers/media/i2c/imx208.c @@ -296,6 +296,9 @@ struct imx208 { /* OTP data */ bool otp_read; char otp_data[IMX208_OTP_SIZE]; + + /* True if the device has been identified */ + bool identified; }; static inline struct imx208 *to_imx208(struct v4l2_subdev *_sd) @@ -619,6 +622,34 @@ static int imx208_set_pad_format(struct v4l2_subdev *sd, return 0; } +static int imx208_identify_module(struct imx208 *imx208) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd); + int ret; + u32 val; + + if (imx208->identified) + return 0; + + ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID, + 2, &val); + if (ret) { + dev_err(&client->dev, "failed to read chip id %x\n", + IMX208_CHIP_ID); + return ret; + } + + if (val != IMX208_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + IMX208_CHIP_ID, val); + return -EIO; + } + + imx208->identified = true; + + return 0; +} + /* Start streaming */ static int imx208_start_streaming(struct imx208 *imx208) { @@ -626,6 +657,10 @@ static int imx208_start_streaming(struct imx208 *imx208) const struct imx208_reg_list *reg_list; int ret, link_freq_index; + ret = imx208_identify_module(imx208); + if (ret) + return ret; + /* Setup PLL */ link_freq_index = imx208->cur_mode->link_freq_index; reg_list = &link_freq_configs[link_freq_index].reg_list; @@ -752,29 +787,6 @@ error: } /* Verify chip ID */ -static int imx208_identify_module(struct imx208 *imx208) -{ - struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd); - int ret; - u32 val; - - ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID, - 2, &val); - if (ret) { - dev_err(&client->dev, "failed to read chip id %x\n", - IMX208_CHIP_ID); - return ret; - } - - if (val != IMX208_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x\n", - IMX208_CHIP_ID, val); - return -EIO; - } - - return 0; -} - static const struct v4l2_subdev_video_ops imx208_video_ops = { .s_stream = imx208_set_stream, }; @@ -813,6 +825,10 @@ static int imx208_read_otp(struct imx208 *imx208) goto out_unlock; } + ret = imx208_identify_module(imx208); + if (ret) + goto out_pm_put; + /* Write register address */ msgs[0].addr = client->addr; msgs[0].flags = 0; @@ -831,6 +847,7 @@ static int imx208_read_otp(struct imx208 *imx208) ret = 0; } +out_pm_put: pm_runtime_put(&client->dev); out_unlock: @@ -961,6 +978,7 @@ static int imx208_probe(struct i2c_client *client) { struct imx208 *imx208; int ret; + bool full_power; u32 val = 0; device_property_read_u32(&client->dev, "clock-frequency", &val); @@ -978,11 +996,14 @@ static int imx208_probe(struct i2c_client *client) /* Initialize subdev */ v4l2_i2c_subdev_init(&imx208->sd, client, &imx208_subdev_ops); - /* Check module identity */ - ret = imx208_identify_module(imx208); - if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); - goto error_probe; + full_power = acpi_dev_state_d0(&client->dev); + if (full_power) { + /* Check module identity */ + ret = imx208_identify_module(imx208); + if (ret) { + dev_err(&client->dev, "failed to find sensor: %d", ret); + goto error_probe; + } } /* Set default mode to max resolution */ @@ -1017,7 +1038,9 @@ static int imx208_probe(struct i2c_client *client) goto error_async_subdev; } - pm_runtime_set_active(&client->dev); + /* Set the device's state to active if it's in D0 state. */ + if (full_power) + pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); @@ -1077,6 +1100,7 @@ static struct i2c_driver imx208_i2c_driver = { }, .probe_new = imx208_probe, .remove = imx208_remove, + .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; module_i2c_driver(imx208_i2c_driver); From 5525fd86ef7888f1eb279f27806ac9d4bb4303c2 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Wed, 15 Dec 2021 12:09:02 +0100 Subject: [PATCH 383/397] media: ov5675: Support device probe in non-zero ACPI D state Tell ACPI device PM code that the driver supports the device being in non-zero ACPI D state when the driver's probe function is entered. Also do identification on the first access of the device, whether in probe or when starting streaming. Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov5675.c | 71 ++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c index da5850b7ad07..00925850fa7c 100644 --- a/drivers/media/i2c/ov5675.c +++ b/drivers/media/i2c/ov5675.c @@ -493,6 +493,9 @@ struct ov5675 { /* Streaming on/off */ bool streaming; + + /* True if the device has been identified */ + bool identified; }; static u64 to_pixel_rate(u32 f_index) @@ -808,12 +811,41 @@ static void ov5675_update_pad_format(const struct ov5675_mode *mode, fmt->field = V4L2_FIELD_NONE; } +static int ov5675_identify_module(struct ov5675 *ov5675) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd); + int ret; + u32 val; + + if (ov5675->identified) + return 0; + + ret = ov5675_read_reg(ov5675, OV5675_REG_CHIP_ID, + OV5675_REG_VALUE_24BIT, &val); + if (ret) + return ret; + + if (val != OV5675_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x", + OV5675_CHIP_ID, val); + return -ENXIO; + } + + ov5675->identified = true; + + return 0; +} + static int ov5675_start_streaming(struct ov5675 *ov5675) { struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd); const struct ov5675_reg_list *reg_list; int link_freq_index, ret; + ret = ov5675_identify_module(ov5675); + if (ret) + return ret; + link_freq_index = ov5675->cur_mode->link_freq_index; reg_list = &link_freq_configs[link_freq_index].reg_list; ret = ov5675_write_reg_list(ov5675, reg_list); @@ -1048,26 +1080,6 @@ static const struct v4l2_subdev_internal_ops ov5675_internal_ops = { .open = ov5675_open, }; -static int ov5675_identify_module(struct ov5675 *ov5675) -{ - struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd); - int ret; - u32 val; - - ret = ov5675_read_reg(ov5675, OV5675_REG_CHIP_ID, - OV5675_REG_VALUE_24BIT, &val); - if (ret) - return ret; - - if (val != OV5675_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", - OV5675_CHIP_ID, val); - return -ENXIO; - } - - return 0; -} - static int ov5675_check_hwcfg(struct device *dev) { struct fwnode_handle *ep; @@ -1154,6 +1166,7 @@ static int ov5675_remove(struct i2c_client *client) static int ov5675_probe(struct i2c_client *client) { struct ov5675 *ov5675; + bool full_power; int ret; ret = ov5675_check_hwcfg(&client->dev); @@ -1168,10 +1181,14 @@ static int ov5675_probe(struct i2c_client *client) return -ENOMEM; v4l2_i2c_subdev_init(&ov5675->sd, client, &ov5675_subdev_ops); - ret = ov5675_identify_module(ov5675); - if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); - return ret; + + full_power = acpi_dev_state_d0(&client->dev); + if (full_power) { + ret = ov5675_identify_module(ov5675); + if (ret) { + dev_err(&client->dev, "failed to find sensor: %d", ret); + return ret; + } } mutex_init(&ov5675->mutex); @@ -1204,7 +1221,10 @@ static int ov5675_probe(struct i2c_client *client) * Device is already turned on by i2c-core with ACPI domain PM. * Enable runtime PM and turn off the device. */ - pm_runtime_set_active(&client->dev); + + /* Set the device's state to active if it's in D0 state. */ + if (full_power) + pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); @@ -1241,6 +1261,7 @@ static struct i2c_driver ov5675_i2c_driver = { }, .probe_new = ov5675_probe, .remove = ov5675_remove, + .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; module_i2c_driver(ov5675_i2c_driver); From d1d2ed5925c370ac09fa6efd39f5f569f562e5b7 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Wed, 15 Dec 2021 12:09:03 +0100 Subject: [PATCH 384/397] media: hi556: Support device probe in non-zero ACPI D state Tell ACPI device PM code that the driver supports the device being in non-zero ACPI D state when the driver's probe function is entered. Also do identification on the first access of the device, whether in probe or when starting streaming. Signed-off-by: Bingbu Cao Signed-off-by: Kao, Arec Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/hi556.c | 70 +++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c index 8db1cbedc1fd..055d1aa8410e 100644 --- a/drivers/media/i2c/hi556.c +++ b/drivers/media/i2c/hi556.c @@ -495,6 +495,9 @@ struct hi556 { /* Streaming on/off */ bool streaming; + + /* True if the device has been identified */ + bool identified; }; static u64 to_pixel_rate(u32 f_index) @@ -757,12 +760,41 @@ static void hi556_assign_pad_format(const struct hi556_mode *mode, fmt->field = V4L2_FIELD_NONE; } +static int hi556_identify_module(struct hi556 *hi556) +{ + struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); + int ret; + u32 val; + + if (hi556->identified) + return 0; + + ret = hi556_read_reg(hi556, HI556_REG_CHIP_ID, + HI556_REG_VALUE_16BIT, &val); + if (ret) + return ret; + + if (val != HI556_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x", + HI556_CHIP_ID, val); + return -ENXIO; + } + + hi556->identified = true; + + return 0; +} + static int hi556_start_streaming(struct hi556 *hi556) { struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); const struct hi556_reg_list *reg_list; int link_freq_index, ret; + ret = hi556_identify_module(hi556); + if (ret) + return ret; + link_freq_index = hi556->cur_mode->link_freq_index; reg_list = &link_freq_configs[link_freq_index].reg_list; ret = hi556_write_reg_list(hi556, reg_list); @@ -1001,26 +1033,6 @@ static const struct v4l2_subdev_internal_ops hi556_internal_ops = { .open = hi556_open, }; -static int hi556_identify_module(struct hi556 *hi556) -{ - struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd); - int ret; - u32 val; - - ret = hi556_read_reg(hi556, HI556_REG_CHIP_ID, - HI556_REG_VALUE_16BIT, &val); - if (ret) - return ret; - - if (val != HI556_CHIP_ID) { - dev_err(&client->dev, "chip id mismatch: %x!=%x", - HI556_CHIP_ID, val); - return -ENXIO; - } - - return 0; -} - static int hi556_check_hwcfg(struct device *dev) { struct fwnode_handle *ep; @@ -1106,6 +1118,7 @@ static int hi556_remove(struct i2c_client *client) static int hi556_probe(struct i2c_client *client) { struct hi556 *hi556; + bool full_power; int ret; ret = hi556_check_hwcfg(&client->dev); @@ -1120,10 +1133,14 @@ static int hi556_probe(struct i2c_client *client) return -ENOMEM; v4l2_i2c_subdev_init(&hi556->sd, client, &hi556_subdev_ops); - ret = hi556_identify_module(hi556); - if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); - return ret; + + full_power = acpi_dev_state_d0(&client->dev); + if (full_power) { + ret = hi556_identify_module(hi556); + if (ret) { + dev_err(&client->dev, "failed to find sensor: %d", ret); + return ret; + } } mutex_init(&hi556->mutex); @@ -1152,7 +1169,9 @@ static int hi556_probe(struct i2c_client *client) goto probe_error_media_entity_cleanup; } - pm_runtime_set_active(&client->dev); + /* Set the device's state to active if it's in D0 state. */ + if (full_power) + pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); @@ -1189,6 +1208,7 @@ static struct i2c_driver hi556_i2c_driver = { }, .probe_new = hi556_probe, .remove = hi556_remove, + .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; module_i2c_driver(hi556_i2c_driver); From e1cc0a05539a115690e5d327dd1b40c15a59e19f Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 9 Nov 2021 14:10:12 +0100 Subject: [PATCH 385/397] media: i2c: hi846: check return value of regulator_bulk_disable() regulator_bulk_disable can fail and thus suspend() can. Handle that error gracefully. Signed-off-by: Martin Kepplinger Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/hi846.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index 48909faeced4..47fa0324f7fb 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -1656,7 +1656,7 @@ err_reg: return ret; } -static void hi846_power_off(struct hi846 *hi846) +static int hi846_power_off(struct hi846 *hi846) { if (hi846->rst_gpio) gpiod_set_value_cansleep(hi846->rst_gpio, 1); @@ -1665,7 +1665,7 @@ static void hi846_power_off(struct hi846 *hi846) gpiod_set_value_cansleep(hi846->shutdown_gpio, 1); clk_disable_unprepare(hi846->clock); - regulator_bulk_disable(HI846_NUM_SUPPLIES, hi846->supplies); + return regulator_bulk_disable(HI846_NUM_SUPPLIES, hi846->supplies); } static int __maybe_unused hi846_suspend(struct device *dev) @@ -1677,9 +1677,7 @@ static int __maybe_unused hi846_suspend(struct device *dev) if (hi846->streaming) hi846_stop_streaming(hi846); - hi846_power_off(hi846); - - return 0; + return hi846_power_off(hi846); } static int __maybe_unused hi846_resume(struct device *dev) From 69a187456d106a351e0b13f98efc0f2e8b42b2a2 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 9 Nov 2021 14:10:13 +0100 Subject: [PATCH 386/397] media: i2c: hi846: use pm_runtime_force_suspend/resume for system suspend In cases like this when controlling regulators and clocks the suspend() and resume() functions are meant to be called balanced toggling the behaviour. It's wrong to use the same suspend function for runtime and system suspend in this case and leads to errors like [ 77.718890] Failed to disable vddd: -EIO Use pm_runtime_force_* helpers in order to support system suspend properly when runtime pm is already implemented and fix this. Signed-off-by: Martin Kepplinger Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/hi846.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index 47fa0324f7fb..ad35c3ff3611 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -2162,7 +2162,11 @@ static int hi846_remove(struct i2c_client *client) return 0; } -static UNIVERSAL_DEV_PM_OPS(hi846_pm_ops, hi846_suspend, hi846_resume, NULL); +static const struct dev_pm_ops hi846_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(hi846_suspend, hi846_resume, NULL) +}; static const struct of_device_id hi846_of_match[] = { { .compatible = "hynix,hi846", }, From 37af43b250fda6162005d47bf7c959c70d52b107 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 29 Nov 2021 19:26:25 +0100 Subject: [PATCH 387/397] media: hantro: Fix probe func error path If clocks for some reason couldn't be enabled, probe function returns immediately, without disabling PM. This obviously leaves PM ref counters unbalanced. Fix that by jumping to appropriate error path, so effects of PM functions are reversed. Fixes: 775fec69008d ("media: add Rockchip VPU JPEG encoder driver") Signed-off-by: Jernej Skrabec Acked-by: Andrzej Pietrasiewicz Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index ab2467998d29..3d3107a39dae 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -981,7 +981,7 @@ static int hantro_probe(struct platform_device *pdev) ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks); if (ret) { dev_err(&pdev->dev, "Failed to prepare clocks\n"); - return ret; + goto err_pm_disable; } ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev); @@ -1037,6 +1037,7 @@ err_v4l2_unreg: v4l2_device_unregister(&vpu->v4l2_dev); err_clk_unprepare: clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks); +err_pm_disable: pm_runtime_dont_use_autosuspend(vpu->dev); pm_runtime_disable(vpu->dev); return ret; From ea71631b7129828c0da4f9d40ec172b7b2c24105 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 29 Nov 2021 19:26:26 +0100 Subject: [PATCH 388/397] media: hantro: add support for reset lines Some SoCs like Allwinner H6 use reset lines for resetting Hantro G2. Add support for them. Signed-off-by: Jernej Skrabec Reviewed-by: Andrzej Pietrasiewicz Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro.h | 3 +++ drivers/staging/media/hantro/hantro_drv.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index 7da23f7f207a..33eb3e092cc1 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -171,6 +172,7 @@ hantro_vdev_to_func(struct video_device *vdev) * @dev: Pointer to device for convenient logging using * dev_ macros. * @clocks: Array of clock handles. + * @resets: Array of reset handles. * @reg_bases: Mapped addresses of VPU registers. * @enc_base: Mapped address of VPU encoder register for convenience. * @dec_base: Mapped address of VPU decoder register for convenience. @@ -190,6 +192,7 @@ struct hantro_dev { struct platform_device *pdev; struct device *dev; struct clk_bulk_data *clocks; + struct reset_control *resets; void __iomem **reg_bases; void __iomem *enc_base; void __iomem *dec_base; diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 3d3107a39dae..770f4ce71d29 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -905,6 +905,10 @@ static int hantro_probe(struct platform_device *pdev) return PTR_ERR(vpu->clocks[0].clk); } + vpu->resets = devm_reset_control_array_get(&pdev->dev, false, true); + if (IS_ERR(vpu->resets)) + return PTR_ERR(vpu->resets); + num_bases = vpu->variant->num_regs ?: 1; vpu->reg_bases = devm_kcalloc(&pdev->dev, num_bases, sizeof(*vpu->reg_bases), GFP_KERNEL); @@ -978,10 +982,16 @@ static int hantro_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(vpu->dev); pm_runtime_enable(vpu->dev); + ret = reset_control_deassert(vpu->resets); + if (ret) { + dev_err(&pdev->dev, "Failed to deassert resets\n"); + goto err_pm_disable; + } + ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks); if (ret) { dev_err(&pdev->dev, "Failed to prepare clocks\n"); - goto err_pm_disable; + goto err_rst_assert; } ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev); @@ -1037,6 +1047,8 @@ err_v4l2_unreg: v4l2_device_unregister(&vpu->v4l2_dev); err_clk_unprepare: clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks); +err_rst_assert: + reset_control_assert(vpu->resets); err_pm_disable: pm_runtime_dont_use_autosuspend(vpu->dev); pm_runtime_disable(vpu->dev); @@ -1056,6 +1068,7 @@ static int hantro_remove(struct platform_device *pdev) v4l2_m2m_release(vpu->m2m_dev); v4l2_device_unregister(&vpu->v4l2_dev); clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks); + reset_control_assert(vpu->resets); pm_runtime_dont_use_autosuspend(vpu->dev); pm_runtime_disable(vpu->dev); return 0; From e67a09d199cb9348bec1398bcc9c363fc04e226a Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 29 Nov 2021 19:26:27 +0100 Subject: [PATCH 389/397] media: hantro: vp9: use double buffering if needed Some G2 variants need double buffering to be enabled in order to work correctly, like that found in Allwinner H6 SoC. Add platform quirk for that. Reviewed-by: Andrzej Pietrasiewicz Signed-off-by: Jernej Skrabec Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro.h | 2 ++ drivers/staging/media/hantro/hantro_g2_regs.h | 1 + drivers/staging/media/hantro/hantro_g2_vp9_dec.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index 33eb3e092cc1..d03824fa3222 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -73,6 +73,7 @@ struct hantro_irq { * @num_clocks: number of clocks in the array * @reg_names: array of register range names * @num_regs: number of register range names in the array + * @double_buffer: core needs double buffering */ struct hantro_variant { unsigned int enc_offset; @@ -94,6 +95,7 @@ struct hantro_variant { int num_clocks; const char * const *reg_names; int num_regs; + unsigned int double_buffer : 1; }; /** diff --git a/drivers/staging/media/hantro/hantro_g2_regs.h b/drivers/staging/media/hantro/hantro_g2_regs.h index 9c857dd1ad9b..15a391a4650e 100644 --- a/drivers/staging/media/hantro/hantro_g2_regs.h +++ b/drivers/staging/media/hantro/hantro_g2_regs.h @@ -270,6 +270,7 @@ #define g2_apf_threshold G2_DEC_REG(55, 0, 0xffff) #define g2_clk_gate_e G2_DEC_REG(58, 16, 0x1) +#define g2_double_buffer_e G2_DEC_REG(58, 15, 0x1) #define g2_buswidth G2_DEC_REG(58, 8, 0x7) #define g2_max_burst G2_DEC_REG(58, 0, 0xff) diff --git a/drivers/staging/media/hantro/hantro_g2_vp9_dec.c b/drivers/staging/media/hantro/hantro_g2_vp9_dec.c index e04242d10fa2..d4fc649a4da1 100644 --- a/drivers/staging/media/hantro/hantro_g2_vp9_dec.c +++ b/drivers/staging/media/hantro/hantro_g2_vp9_dec.c @@ -847,6 +847,8 @@ config_registers(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_p hantro_reg_write(ctx->dev, &g2_clk_gate_e, 1); hantro_reg_write(ctx->dev, &g2_max_cb_size, 6); hantro_reg_write(ctx->dev, &g2_min_cb_size, 3); + if (ctx->dev->variant->double_buffer) + hantro_reg_write(ctx->dev, &g2_double_buffer_e, 1); config_output(ctx, dst, dec_params); From 6a7c3219576055d0f11e563ef5ddb3d058172e72 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 29 Nov 2021 19:26:28 +0100 Subject: [PATCH 390/397] media: hantro: vp9: add support for legacy register set Some older G2 cores uses slightly different register set for HEVC and VP9. Since vast majority of registers and logic is the same, it doesn't make sense to introduce another drivers. Add legacy_regs quirk and implement only VP9 changes for now. HEVC changes will be introduced later, if needed. Reviewed-by: Andrzej Pietrasiewicz Signed-off-by: Jernej Skrabec Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro.h | 2 + drivers/staging/media/hantro/hantro_g2_regs.h | 16 ++++ .../staging/media/hantro/hantro_g2_vp9_dec.c | 74 ++++++++++++++----- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index d03824fa3222..83ed25d9657b 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -74,6 +74,7 @@ struct hantro_irq { * @reg_names: array of register range names * @num_regs: number of register range names in the array * @double_buffer: core needs double buffering + * @legacy_regs: core uses legacy register set */ struct hantro_variant { unsigned int enc_offset; @@ -96,6 +97,7 @@ struct hantro_variant { const char * const *reg_names; int num_regs; unsigned int double_buffer : 1; + unsigned int legacy_regs : 1; }; /** diff --git a/drivers/staging/media/hantro/hantro_g2_regs.h b/drivers/staging/media/hantro/hantro_g2_regs.h index 15a391a4650e..b7c6f9877b9d 100644 --- a/drivers/staging/media/hantro/hantro_g2_regs.h +++ b/drivers/staging/media/hantro/hantro_g2_regs.h @@ -36,7 +36,13 @@ #define BUS_WIDTH_256 3 #define g2_strm_swap G2_DEC_REG(2, 28, 0xf) +#define g2_strm_swap_old G2_DEC_REG(2, 27, 0x1f) +#define g2_pic_swap G2_DEC_REG(2, 22, 0x1f) #define g2_dirmv_swap G2_DEC_REG(2, 20, 0xf) +#define g2_dirmv_swap_old G2_DEC_REG(2, 17, 0x1f) +#define g2_tab0_swap_old G2_DEC_REG(2, 12, 0x1f) +#define g2_tab1_swap_old G2_DEC_REG(2, 7, 0x1f) +#define g2_tab2_swap_old G2_DEC_REG(2, 2, 0x1f) #define g2_mode G2_DEC_REG(3, 27, 0x1f) #define g2_compress_swap G2_DEC_REG(3, 20, 0xf) @@ -45,6 +51,8 @@ #define g2_out_dis G2_DEC_REG(3, 15, 0x1) #define g2_out_filtering_dis G2_DEC_REG(3, 14, 0x1) #define g2_write_mvs_e G2_DEC_REG(3, 12, 0x1) +#define g2_tab3_swap_old G2_DEC_REG(3, 7, 0x1f) +#define g2_rscan_swap G2_DEC_REG(3, 2, 0x1f) #define g2_pic_width_in_cbs G2_DEC_REG(4, 19, 0x1fff) #define g2_pic_height_in_cbs G2_DEC_REG(4, 6, 0x1fff) @@ -58,6 +66,7 @@ #define g2_tempor_mvp_e G2_DEC_REG(5, 11, 0x1) #define g2_max_cu_qpd_depth G2_DEC_REG(5, 5, 0x3f) #define g2_cu_qpd_e G2_DEC_REG(5, 4, 0x1) +#define g2_pix_shift G2_DEC_REG(5, 0, 0xf) #define g2_stream_len G2_DEC_REG(6, 0, 0xffffffff) @@ -80,21 +89,28 @@ #define g2_const_intra_e G2_DEC_REG(8, 31, 0x1) #define g2_filt_ctrl_pres G2_DEC_REG(8, 30, 0x1) +#define g2_bit_depth_y G2_DEC_REG(8, 21, 0xf) +#define g2_bit_depth_c G2_DEC_REG(8, 17, 0xf) #define g2_idr_pic_e G2_DEC_REG(8, 16, 0x1) #define g2_bit_depth_pcm_y G2_DEC_REG(8, 12, 0xf) #define g2_bit_depth_pcm_c G2_DEC_REG(8, 8, 0xf) #define g2_bit_depth_y_minus8 G2_DEC_REG(8, 6, 0x3) #define g2_bit_depth_c_minus8 G2_DEC_REG(8, 4, 0x3) +#define g2_rs_out_bit_depth G2_DEC_REG(8, 4, 0xf) #define g2_output_8_bits G2_DEC_REG(8, 3, 0x1) #define g2_output_format G2_DEC_REG(8, 0, 0x7) +#define g2_pp_pix_shift G2_DEC_REG(8, 0, 0xf) #define g2_refidx1_active G2_DEC_REG(9, 19, 0x1f) #define g2_refidx0_active G2_DEC_REG(9, 14, 0x1f) #define g2_hdr_skip_length G2_DEC_REG(9, 0, 0x3fff) #define g2_start_code_e G2_DEC_REG(10, 31, 0x1) +#define g2_init_qp_old G2_DEC_REG(10, 25, 0x3f) #define g2_init_qp G2_DEC_REG(10, 24, 0x3f) +#define g2_num_tile_cols_old G2_DEC_REG(10, 20, 0x1f) #define g2_num_tile_cols G2_DEC_REG(10, 19, 0x1f) +#define g2_num_tile_rows_old G2_DEC_REG(10, 15, 0x1f) #define g2_num_tile_rows G2_DEC_REG(10, 14, 0x1f) #define g2_tile_e G2_DEC_REG(10, 1, 0x1) #define g2_entropy_sync_e G2_DEC_REG(10, 0, 0x1) diff --git a/drivers/staging/media/hantro/hantro_g2_vp9_dec.c b/drivers/staging/media/hantro/hantro_g2_vp9_dec.c index d4fc649a4da1..91c21b634fab 100644 --- a/drivers/staging/media/hantro/hantro_g2_vp9_dec.c +++ b/drivers/staging/media/hantro/hantro_g2_vp9_dec.c @@ -150,7 +150,8 @@ static void config_output(struct hantro_ctx *ctx, dma_addr_t luma_addr, chroma_addr, mv_addr; hantro_reg_write(ctx->dev, &g2_out_dis, 0); - hantro_reg_write(ctx->dev, &g2_output_format, 0); + if (!ctx->dev->variant->legacy_regs) + hantro_reg_write(ctx->dev, &g2_output_format, 0); luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf); hantro_write_addr(ctx->dev, G2_OUT_LUMA_ADDR, luma_addr); @@ -327,6 +328,7 @@ config_tiles(struct hantro_ctx *ctx, struct hantro_aux_buf *tile_edge = &vp9_ctx->tile_edge; dma_addr_t addr; unsigned short *tile_mem; + unsigned int rows, cols; addr = misc->dma + vp9_ctx->tile_info_offset; hantro_write_addr(ctx->dev, G2_TILE_SIZES_ADDR, addr); @@ -344,17 +346,24 @@ config_tiles(struct hantro_ctx *ctx, fill_tile_info(ctx, tile_r, tile_c, sbs_r, sbs_c, tile_mem); + cols = tile_c; + rows = tile_r; hantro_reg_write(ctx->dev, &g2_tile_e, 1); - hantro_reg_write(ctx->dev, &g2_num_tile_cols, tile_c); - hantro_reg_write(ctx->dev, &g2_num_tile_rows, tile_r); - } else { tile_mem[0] = hantro_vp9_num_sbs(dst->vp9.width); tile_mem[1] = hantro_vp9_num_sbs(dst->vp9.height); + cols = 1; + rows = 1; hantro_reg_write(ctx->dev, &g2_tile_e, 0); - hantro_reg_write(ctx->dev, &g2_num_tile_cols, 1); - hantro_reg_write(ctx->dev, &g2_num_tile_rows, 1); + } + + if (ctx->dev->variant->legacy_regs) { + hantro_reg_write(ctx->dev, &g2_num_tile_cols_old, cols); + hantro_reg_write(ctx->dev, &g2_num_tile_rows_old, rows); + } else { + hantro_reg_write(ctx->dev, &g2_num_tile_cols, cols); + hantro_reg_write(ctx->dev, &g2_num_tile_rows, rows); } /* provide aux buffers even if no tiles are used */ @@ -505,8 +514,22 @@ static void config_picture_dimensions(struct hantro_ctx *ctx, struct hantro_deco static void config_bit_depth(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_params) { - hantro_reg_write(ctx->dev, &g2_bit_depth_y_minus8, dec_params->bit_depth - 8); - hantro_reg_write(ctx->dev, &g2_bit_depth_c_minus8, dec_params->bit_depth - 8); + if (ctx->dev->variant->legacy_regs) { + u8 pp_shift = 0; + + hantro_reg_write(ctx->dev, &g2_bit_depth_y, dec_params->bit_depth); + hantro_reg_write(ctx->dev, &g2_bit_depth_c, dec_params->bit_depth); + hantro_reg_write(ctx->dev, &g2_rs_out_bit_depth, dec_params->bit_depth); + + if (dec_params->bit_depth > 8) + pp_shift = 16 - dec_params->bit_depth; + + hantro_reg_write(ctx->dev, &g2_pp_pix_shift, pp_shift); + hantro_reg_write(ctx->dev, &g2_pix_shift, 0); + } else { + hantro_reg_write(ctx->dev, &g2_bit_depth_y_minus8, dec_params->bit_depth - 8); + hantro_reg_write(ctx->dev, &g2_bit_depth_c_minus8, dec_params->bit_depth - 8); + } } static inline bool is_lossless(const struct v4l2_vp9_quantization *quant) @@ -784,9 +807,13 @@ config_source(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_para + dec_params->compressed_header_size; stream_base = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0); - hantro_write_addr(ctx->dev, G2_STREAM_ADDR, stream_base); tmp_addr = stream_base + headres_size; + if (ctx->dev->variant->legacy_regs) + hantro_write_addr(ctx->dev, G2_STREAM_ADDR, (tmp_addr & ~0xf)); + else + hantro_write_addr(ctx->dev, G2_STREAM_ADDR, stream_base); + start_bit = (tmp_addr & 0xf) * 8; hantro_reg_write(ctx->dev, &g2_start_bit, start_bit); @@ -794,10 +821,12 @@ config_source(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_para src_len += start_bit / 8 - headres_size; hantro_reg_write(ctx->dev, &g2_stream_len, src_len); - tmp_addr &= ~0xf; - hantro_reg_write(ctx->dev, &g2_strm_start_offset, tmp_addr - stream_base); - src_buf_len = vb2_plane_size(&vb2_src->vb2_buf, 0); - hantro_reg_write(ctx->dev, &g2_strm_buffer_len, src_buf_len); + if (!ctx->dev->variant->legacy_regs) { + tmp_addr &= ~0xf; + hantro_reg_write(ctx->dev, &g2_strm_start_offset, tmp_addr - stream_base); + src_buf_len = vb2_plane_size(&vb2_src->vb2_buf, 0); + hantro_reg_write(ctx->dev, &g2_strm_buffer_len, src_buf_len); + } } static void @@ -837,13 +866,24 @@ config_registers(struct hantro_ctx *ctx, const struct v4l2_ctrl_vp9_frame *dec_p /* configure basic registers */ hantro_reg_write(ctx->dev, &g2_mode, VP9_DEC_MODE); - hantro_reg_write(ctx->dev, &g2_strm_swap, 0xf); - hantro_reg_write(ctx->dev, &g2_dirmv_swap, 0xf); - hantro_reg_write(ctx->dev, &g2_compress_swap, 0xf); + if (!ctx->dev->variant->legacy_regs) { + hantro_reg_write(ctx->dev, &g2_strm_swap, 0xf); + hantro_reg_write(ctx->dev, &g2_dirmv_swap, 0xf); + hantro_reg_write(ctx->dev, &g2_compress_swap, 0xf); + hantro_reg_write(ctx->dev, &g2_ref_compress_bypass, 1); + } else { + hantro_reg_write(ctx->dev, &g2_strm_swap_old, 0x1f); + hantro_reg_write(ctx->dev, &g2_pic_swap, 0x10); + hantro_reg_write(ctx->dev, &g2_dirmv_swap_old, 0x10); + hantro_reg_write(ctx->dev, &g2_tab0_swap_old, 0x10); + hantro_reg_write(ctx->dev, &g2_tab1_swap_old, 0x10); + hantro_reg_write(ctx->dev, &g2_tab2_swap_old, 0x10); + hantro_reg_write(ctx->dev, &g2_tab3_swap_old, 0x10); + hantro_reg_write(ctx->dev, &g2_rscan_swap, 0x10); + } hantro_reg_write(ctx->dev, &g2_buswidth, BUS_WIDTH_128); hantro_reg_write(ctx->dev, &g2_max_burst, 16); hantro_reg_write(ctx->dev, &g2_apf_threshold, 8); - hantro_reg_write(ctx->dev, &g2_ref_compress_bypass, 1); hantro_reg_write(ctx->dev, &g2_clk_gate_e, 1); hantro_reg_write(ctx->dev, &g2_max_cb_size, 6); hantro_reg_write(ctx->dev, &g2_min_cb_size, 3); From 3c5b218c3606840048a9cacae4a29692ab1afc7c Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 29 Nov 2021 19:26:29 +0100 Subject: [PATCH 391/397] media: hantro: move postproc enablement for old cores Older G2 cores, like that in Allwinner H6, seem to have issue with latching postproc register values if this is first thing done in job. Moving that to the end solves the issue. Signed-off-by: Jernej Skrabec Reviewed-by: Andrzej Pietrasiewicz Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro.h | 2 ++ drivers/staging/media/hantro/hantro_drv.c | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index 83ed25d9657b..06d0f3597694 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -75,6 +75,7 @@ struct hantro_irq { * @num_regs: number of register range names in the array * @double_buffer: core needs double buffering * @legacy_regs: core uses legacy register set + * @late_postproc: postproc must be set up at the end of the job */ struct hantro_variant { unsigned int enc_offset; @@ -98,6 +99,7 @@ struct hantro_variant { int num_regs; unsigned int double_buffer : 1; unsigned int legacy_regs : 1; + unsigned int late_postproc : 1; }; /** diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 770f4ce71d29..33bf78be145b 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -130,7 +130,7 @@ void hantro_start_prepare_run(struct hantro_ctx *ctx) v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, &ctx->ctrl_handler); - if (!ctx->is_encoder) { + if (!ctx->is_encoder && !ctx->dev->variant->late_postproc) { if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) hantro_postproc_enable(ctx); else @@ -142,6 +142,13 @@ void hantro_end_prepare_run(struct hantro_ctx *ctx) { struct vb2_v4l2_buffer *src_buf; + if (!ctx->is_encoder && ctx->dev->variant->late_postproc) { + if (hantro_needs_postproc(ctx, ctx->vpu_dst_fmt)) + hantro_postproc_enable(ctx); + else + hantro_postproc_disable(ctx); + } + src_buf = hantro_get_src_buf(ctx); v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, &ctx->ctrl_handler); From 3385c514ecc5a021782ce4347f8be8d3b1fcd595 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 29 Nov 2021 19:26:30 +0100 Subject: [PATCH 392/397] media: hantro: Convert imx8m_vpu_g2_irq to helper It turns out that imx8m_vpu_g2_irq() doesn't depend on any platform specifics and can be used with other G2 platform drivers too. Move it to common code. Signed-off-by: Jernej Skrabec Reviewed-by: Andrzej Pietrasiewicz Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/hantro_g2.c | 18 ++++++++++++++++++ drivers/staging/media/hantro/hantro_hw.h | 1 + drivers/staging/media/hantro/imx8m_vpu_hw.c | 20 +------------------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/drivers/staging/media/hantro/hantro_g2.c b/drivers/staging/media/hantro/hantro_g2.c index 6f3e1f797f83..ee5f14c5f8f2 100644 --- a/drivers/staging/media/hantro/hantro_g2.c +++ b/drivers/staging/media/hantro/hantro_g2.c @@ -24,3 +24,21 @@ void hantro_g2_check_idle(struct hantro_dev *vpu) } } } + +irqreturn_t hantro_g2_irq(int irq, void *dev_id) +{ + struct hantro_dev *vpu = dev_id; + enum vb2_buffer_state state; + u32 status; + + status = vdpu_read(vpu, G2_REG_INTERRUPT); + state = (status & G2_REG_INTERRUPT_DEC_RDY_INT) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + + vdpu_write(vpu, 0, G2_REG_INTERRUPT); + vdpu_write(vpu, G2_REG_CONFIG_DEC_CLK_GATE_E, G2_REG_CONFIG); + + hantro_irq_done(vpu, state); + + return IRQ_HANDLED; +} diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index a018748fc4bf..175b64e587c6 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -425,5 +425,6 @@ void hantro_g2_vp9_dec_done(struct hantro_ctx *ctx); int hantro_vp9_dec_init(struct hantro_ctx *ctx); void hantro_vp9_dec_exit(struct hantro_ctx *ctx); void hantro_g2_check_idle(struct hantro_dev *vpu); +irqreturn_t hantro_g2_irq(int irq, void *dev_id); #endif /* HANTRO_HW_H_ */ diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c index 1a43f6fceef9..f5991b8e553a 100644 --- a/drivers/staging/media/hantro/imx8m_vpu_hw.c +++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c @@ -191,24 +191,6 @@ static irqreturn_t imx8m_vpu_g1_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t imx8m_vpu_g2_irq(int irq, void *dev_id) -{ - struct hantro_dev *vpu = dev_id; - enum vb2_buffer_state state; - u32 status; - - status = vdpu_read(vpu, G2_REG_INTERRUPT); - state = (status & G2_REG_INTERRUPT_DEC_RDY_INT) ? - VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; - - vdpu_write(vpu, 0, G2_REG_INTERRUPT); - vdpu_write(vpu, G2_REG_CONFIG_DEC_CLK_GATE_E, G2_REG_CONFIG); - - hantro_irq_done(vpu, state); - - return IRQ_HANDLED; -} - static int imx8mq_vpu_hw_init(struct hantro_dev *vpu) { vpu->ctrl_base = vpu->reg_bases[vpu->variant->num_regs - 1]; @@ -280,7 +262,7 @@ static const struct hantro_irq imx8mq_irqs[] = { }; static const struct hantro_irq imx8mq_g2_irqs[] = { - { "g2", imx8m_vpu_g2_irq }, + { "g2", hantro_g2_irq }, }; static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" }; From fd6be12716c4f8a90173f52b3ea248b04956c5a9 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 29 Nov 2021 19:26:31 +0100 Subject: [PATCH 393/397] media: dt-bindings: allwinner: document H6 Hantro G2 binding Allwinner H6 contains older Hantro G2 core, primarly used for VP9 video decoding. It's unclear for now if HEVC is also supported. Describe its binding. Signed-off-by: Jernej Skrabec Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/allwinner,sun50i-h6-vpu-g2.yaml | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun50i-h6-vpu-g2.yaml diff --git a/Documentation/devicetree/bindings/media/allwinner,sun50i-h6-vpu-g2.yaml b/Documentation/devicetree/bindings/media/allwinner,sun50i-h6-vpu-g2.yaml new file mode 100644 index 000000000000..24d7bf21499e --- /dev/null +++ b/Documentation/devicetree/bindings/media/allwinner,sun50i-h6-vpu-g2.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) + +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/media/allwinner,sun50i-h6-vpu-g2.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Hantro G2 VPU codec implemented on Allwinner H6 SoC + +maintainers: + - Jernej Skrabec + +description: + Hantro G2 video decode accelerator present on Allwinner H6 SoC. + +properties: + compatible: + const: allwinner,sun50i-h6-vpu-g2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + + clock-names: + items: + - const: bus + - const: mod + + resets: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + +additionalProperties: false + +examples: + - | + #include + #include + #include + + video-codec-g2@1c00000 { + compatible = "allwinner,sun50i-h6-vpu-g2"; + reg = <0x01c00000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_VP9>, <&ccu CLK_VP9>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_VP9>; + }; + +... From 86790a4fdf4b3d1ad96cd0f8c4e10bad878243d8 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 29 Nov 2021 19:26:32 +0100 Subject: [PATCH 394/397] media: hantro: Add support for Allwinner H6 Allwinner H6 has a Hantro G2 core used for VP9 decoding. It's not clear at this time if HEVC is also supported or not. Signed-off-by: Jernej Skrabec Acked-by: Andrzej Pietrasiewicz Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/hantro/Kconfig | 10 ++- drivers/staging/media/hantro/Makefile | 3 + drivers/staging/media/hantro/hantro_drv.c | 3 + drivers/staging/media/hantro/hantro_hw.h | 1 + drivers/staging/media/hantro/sunxi_vpu_hw.c | 86 +++++++++++++++++++++ 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/media/hantro/sunxi_vpu_hw.c diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig index 00a57d88c92e..3c5d833322c8 100644 --- a/drivers/staging/media/hantro/Kconfig +++ b/drivers/staging/media/hantro/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config VIDEO_HANTRO tristate "Hantro VPU driver" - depends on ARCH_MXC || ARCH_ROCKCHIP || ARCH_AT91 || COMPILE_TEST + depends on ARCH_MXC || ARCH_ROCKCHIP || ARCH_AT91 || ARCH_SUNXI || COMPILE_TEST depends on VIDEO_DEV && VIDEO_V4L2 select MEDIA_CONTROLLER select MEDIA_CONTROLLER_REQUEST_API @@ -40,3 +40,11 @@ config VIDEO_HANTRO_ROCKCHIP default y help Enable support for RK3288, RK3328, and RK3399 SoCs. + +config VIDEO_HANTRO_SUNXI + bool "Hantro VPU Allwinner support" + depends on VIDEO_HANTRO + depends on ARCH_SUNXI || COMPILE_TEST + default y + help + Enable support for H6 SoC. diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile index 28af0a1ee4bf..ebd5ede7bef7 100644 --- a/drivers/staging/media/hantro/Makefile +++ b/drivers/staging/media/hantro/Makefile @@ -33,3 +33,6 @@ hantro-vpu-$(CONFIG_VIDEO_HANTRO_SAMA5D4) += \ hantro-vpu-$(CONFIG_VIDEO_HANTRO_ROCKCHIP) += \ rockchip_vpu_hw.o + +hantro-vpu-$(CONFIG_VIDEO_HANTRO_SUNXI) += \ + sunxi_vpu_hw.o diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 33bf78be145b..6a51f39dde56 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -620,6 +620,9 @@ static const struct of_device_id of_hantro_match[] = { #endif #ifdef CONFIG_VIDEO_HANTRO_SAMA5D4 { .compatible = "microchip,sama5d4-vdec", .data = &sama5d4_vdec_variant, }, +#endif +#ifdef CONFIG_VIDEO_HANTRO_SUNXI + { .compatible = "allwinner,sun50i-h6-vpu-g2", .data = &sunxi_vpu_variant, }, #endif { /* sentinel */ } }; diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 175b64e587c6..4a19ae8940b9 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -308,6 +308,7 @@ extern const struct hantro_variant rk3288_vpu_variant; extern const struct hantro_variant rk3328_vpu_variant; extern const struct hantro_variant rk3399_vpu_variant; extern const struct hantro_variant sama5d4_vdec_variant; +extern const struct hantro_variant sunxi_vpu_variant; extern const struct hantro_postproc_ops hantro_g1_postproc_ops; extern const struct hantro_postproc_ops hantro_g2_postproc_ops; diff --git a/drivers/staging/media/hantro/sunxi_vpu_hw.c b/drivers/staging/media/hantro/sunxi_vpu_hw.c new file mode 100644 index 000000000000..90633406c4eb --- /dev/null +++ b/drivers/staging/media/hantro/sunxi_vpu_hw.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Allwinner Hantro G2 VPU codec driver + * + * Copyright (C) 2021 Jernej Skrabec + */ + +#include + +#include "hantro.h" + +static const struct hantro_fmt sunxi_vpu_postproc_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12, + .codec_mode = HANTRO_MODE_NONE, + .postprocessed = true, + }, +}; + +static const struct hantro_fmt sunxi_vpu_dec_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12_4L4, + .codec_mode = HANTRO_MODE_NONE, + }, + { + .fourcc = V4L2_PIX_FMT_VP9_FRAME, + .codec_mode = HANTRO_MODE_VP9_DEC, + .max_depth = 2, + .frmsize = { + .min_width = 48, + .max_width = 3840, + .step_width = MB_DIM, + .min_height = 48, + .max_height = 2160, + .step_height = MB_DIM, + }, + }, +}; + +static int sunxi_vpu_hw_init(struct hantro_dev *vpu) +{ + clk_set_rate(vpu->clocks[0].clk, 300000000); + + return 0; +} + +static void sunxi_vpu_reset(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + + reset_control_reset(vpu->resets); +} + +static const struct hantro_codec_ops sunxi_vpu_codec_ops[] = { + [HANTRO_MODE_VP9_DEC] = { + .run = hantro_g2_vp9_dec_run, + .done = hantro_g2_vp9_dec_done, + .reset = sunxi_vpu_reset, + .init = hantro_vp9_dec_init, + .exit = hantro_vp9_dec_exit, + }, +}; + +static const struct hantro_irq sunxi_irqs[] = { + { NULL, hantro_g2_irq }, +}; + +static const char * const sunxi_clk_names[] = { "mod", "bus" }; + +const struct hantro_variant sunxi_vpu_variant = { + .dec_fmts = sunxi_vpu_dec_fmts, + .num_dec_fmts = ARRAY_SIZE(sunxi_vpu_dec_fmts), + .postproc_fmts = sunxi_vpu_postproc_fmts, + .num_postproc_fmts = ARRAY_SIZE(sunxi_vpu_postproc_fmts), + .postproc_ops = &hantro_g2_postproc_ops, + .codec = HANTRO_VP9_DECODER, + .codec_ops = sunxi_vpu_codec_ops, + .init = sunxi_vpu_hw_init, + .irqs = sunxi_irqs, + .num_irqs = ARRAY_SIZE(sunxi_irqs), + .clk_names = sunxi_clk_names, + .num_clocks = ARRAY_SIZE(sunxi_clk_names), + .double_buffer = 1, + .legacy_regs = 1, + .late_postproc = 1, +}; From ae971ccae9de3c6ec6507a9ddc7fb10c03234b8b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:55 +0100 Subject: [PATCH 395/397] media: ipu3-cio2: Defer probing until the PMIC is fully setup On devices where things are not fully describe in devicetree (1) and where the code thus falls back to calling cio2_bridge_init(), the i2c-clients for any VCMs also need to be instantiated manually. The VCM can be probed by its driver as soon as the code instantiates the i2c-client and this probing must not happen before the PMIC is fully setup. Make cio2_bridge_init() return -EPROBE_DEFER when the PMIC is not fully-setup, deferring the probe of the ipu3-cio2 driver. This is a preparation patch for adding VCM enumeration support to the ipu3-cio2-bridge code. 1) Through embedding of devicetree info in the ACPI tables Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 1cbbcbf4e157..c805916d0909 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -308,6 +308,40 @@ err_unregister_sensors: return ret; } +/* + * The VCM cannot be probed until the PMIC is completely setup. We cannot rely + * on -EPROBE_DEFER for this, since the consumer<->supplier relations between + * the VCM and regulators/clks are not described in ACPI, instead they are + * passed as board-data to the PMIC drivers. Since -PROBE_DEFER does not work + * for the clks/regulators the VCM i2c-clients must not be instantiated until + * the PMIC is fully setup. + * + * The sensor/VCM ACPI device has an ACPI _DEP on the PMIC, check this using the + * acpi_dev_ready_for_enumeration() helper, like the i2c-core-acpi code does + * for the sensors. + */ +static int cio2_bridge_sensors_are_ready(void) +{ + struct acpi_device *adev; + bool ready = true; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) { + const struct cio2_sensor_config *cfg = + &cio2_supported_sensors[i]; + + for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { + if (!adev->status.enabled) + continue; + + if (!acpi_dev_ready_for_enumeration(adev)) + ready = false; + } + } + + return ready; +} + int cio2_bridge_init(struct pci_dev *cio2) { struct device *dev = &cio2->dev; @@ -316,6 +350,9 @@ int cio2_bridge_init(struct pci_dev *cio2) unsigned int i; int ret; + if (!cio2_bridge_sensors_are_ready()) + return -EPROBE_DEFER; + bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); if (!bridge) return -ENOMEM; From fc2c204538a9fbfe2cd0c55a6e102275014cb9a1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:56 +0100 Subject: [PATCH 396/397] media: ipu3-cio2: Call cio2_bridge_init() before anything else Since cio2_bridge_init() may now return -EPROBE_DEFER it is best to call it before anything else. Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c index e2874fee9530..0e9b0503b62a 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c @@ -1713,11 +1713,6 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, struct cio2_device *cio2; int r; - cio2 = devm_kzalloc(dev, sizeof(*cio2), GFP_KERNEL); - if (!cio2) - return -ENOMEM; - cio2->pci_dev = pci_dev; - /* * On some platforms no connections to sensors are defined in firmware, * if the device has no endpoints then we can try to build those as @@ -1735,6 +1730,11 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, return r; } + cio2 = devm_kzalloc(dev, sizeof(*cio2), GFP_KERNEL); + if (!cio2) + return -ENOMEM; + cio2->pci_dev = pci_dev; + r = pcim_enable_device(pci_dev); if (r) { dev_err(dev, "failed to enable device (%d)\n", r); From 68b9bcc8a534cd11fe55f8bc82f948aae7d81b3c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 3 Dec 2021 11:28:57 +0100 Subject: [PATCH 397/397] media: ipu3-cio2: Add support for instantiating i2c-clients for VCMs Some sensors come with a variable-focus lens where the lens focus is controller by a VCM (Voice Coil Motor). If there is a VCM for the lens-focus, and if so which one, is described on the vcm_type field of the ACPI SSDB table. These VCMs are a second I2C device listed as an extra I2cSerialBusV2 resource in the same ACPI device as the sensor. The i2c-core-acpi.c code only instantiates an i2c-client for the first I2cSerialBusV2 resource. Add support for instantiating an i2c-client for the VCM with the type of the i2c-client set based on the SSDB vcm_type field. Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 55 ++++++++++++++++++++++ drivers/media/pci/intel/ipu3/cio2-bridge.h | 16 ++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index c805916d0909..7ccb7b6eaa82 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,18 @@ static const struct cio2_property_names prop_names = { .link_frequencies = "link-frequencies", }; +static const char * const cio2_vcm_types[] = { + "ad5823", + "dw9714", + "ad5816", + "dw9719", + "dw9718", + "dw9806b", + "wv517s", + "lc898122xa", + "lc898212axb", +}; + static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id, void *data, u32 size) { @@ -134,6 +147,12 @@ static void cio2_bridge_create_fwnode_properties( sensor->dev_properties[2] = PROPERTY_ENTRY_U32( sensor->prop_names.orientation, orientation); + if (sensor->ssdb.vcmtype) { + sensor->vcm_ref[0] = + SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]); + sensor->dev_properties[3] = + PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref); + } sensor->ep_properties[0] = PROPERTY_ENTRY_U32( sensor->prop_names.bus_type, @@ -195,6 +214,33 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, sensor->node_names.endpoint, &nodes[SWNODE_CIO2_PORT], sensor->cio2_properties); + if (sensor->ssdb.vcmtype) + nodes[SWNODE_VCM] = + NODE_VCM(cio2_vcm_types[sensor->ssdb.vcmtype - 1]); +} + +static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor) +{ + struct i2c_board_info board_info = { }; + char name[16]; + + if (!sensor->ssdb.vcmtype) + return; + + snprintf(name, sizeof(name), "%s-VCM", acpi_dev_name(sensor->adev)); + board_info.dev_name = name; + strscpy(board_info.type, cio2_vcm_types[sensor->ssdb.vcmtype - 1], + ARRAY_SIZE(board_info.type)); + board_info.swnode = &sensor->swnodes[SWNODE_VCM]; + + sensor->vcm_i2c_client = + i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(sensor->adev), + 1, &board_info); + if (IS_ERR(sensor->vcm_i2c_client)) { + dev_warn(&sensor->adev->dev, "Error instantiation VCM i2c-client: %ld\n", + PTR_ERR(sensor->vcm_i2c_client)); + sensor->vcm_i2c_client = NULL; + } } static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) @@ -207,6 +253,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) software_node_unregister_nodes(sensor->swnodes); ACPI_FREE(sensor->pld); acpi_dev_put(sensor->adev); + i2c_unregister_device(sensor->vcm_i2c_client); } } @@ -239,6 +286,12 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, if (ret) goto err_put_adev; + if (sensor->ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) { + dev_warn(&adev->dev, "Unknown VCM type %d\n", + sensor->ssdb.vcmtype); + sensor->ssdb.vcmtype = 0; + } + status = acpi_get_physical_device_location(adev->handle, &sensor->pld); if (ACPI_FAILURE(status)) { ret = -ENODEV; @@ -269,6 +322,8 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, sensor->adev = acpi_dev_get(adev); adev->fwnode.secondary = fwnode; + cio2_bridge_instantiate_vcm_i2c_client(sensor); + dev_info(&cio2->dev, "Found supported sensor %s\n", acpi_dev_name(adev)); diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h index 202c7d494f7a..4418cbd08208 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h @@ -8,6 +8,8 @@ #include "ipu3-cio2.h" +struct i2c_client; + #define CIO2_HID "INT343E" #define CIO2_MAX_LANES 4 #define MAX_NUM_LINK_FREQS 3 @@ -42,12 +44,19 @@ .properties = _PROPS, \ } +#define NODE_VCM(_TYPE) \ + (const struct software_node) { \ + .name = _TYPE, \ + } + enum cio2_sensor_swnodes { SWNODE_SENSOR_HID, SWNODE_SENSOR_PORT, SWNODE_SENSOR_ENDPOINT, SWNODE_CIO2_PORT, SWNODE_CIO2_ENDPOINT, + /* Must be last because it is optional / maybe empty */ + SWNODE_VCM, SWNODE_COUNT }; @@ -106,8 +115,10 @@ struct cio2_sensor_config { struct cio2_sensor { char name[ACPI_ID_LEN]; struct acpi_device *adev; + struct i2c_client *vcm_i2c_client; - struct software_node swnodes[6]; + /* SWNODE_COUNT + 1 for terminating empty node */ + struct software_node swnodes[SWNODE_COUNT + 1]; struct cio2_node_names node_names; struct cio2_sensor_ssdb ssdb; @@ -115,10 +126,11 @@ struct cio2_sensor { struct cio2_property_names prop_names; struct property_entry ep_properties[5]; - struct property_entry dev_properties[4]; + struct property_entry dev_properties[5]; struct property_entry cio2_properties[3]; struct software_node_ref_args local_ref[1]; struct software_node_ref_args remote_ref[1]; + struct software_node_ref_args vcm_ref[1]; }; struct cio2_bridge {