mirror of
https://github.com/torvalds/linux.git
synced 2026-10-17 05:44:18 +02:00
Add an in-tree AVMatrix HWS PCIe capture driver. The driver supports up to four HDMI inputs and exposes the video capture path through V4L2 with vb2-dma-contig streaming, DV timings, and per-input controls. Audio support is intentionally omitted from this submission. This patch also adds the MAINTAINERS entry for the new driver. This driver is derived from a GPL out-of-tree driver. Changes since v6: - v6 accidently contained legacy history, resubmitting with latest - remove an unused mode-change label reported by W=1 Changes since v5: - keep queue_setup() and alloc_sizeimage on the logical sizeimage value - drop the dead queue_setup() fallback that rebuilt pix.sizeimage on the fly - clarify that hws_calc_sizeimage() models the packed-YUYV-only path - add Assisted-by attribution for Codex Changes since v4: - replace plain 64-bit elapsed-time divisions in debug logging with div_u64() so i386 module builds do not emit __udivdi3 references Changes since v3: - fold the MAINTAINERS update into this patch so per-patch CI sees the new file pattern - wrap the validation text for checkpatch Changes since v2: - keep scratch DMA allocation on a single probe-owned path - avoid double-freeing V4L2 control handlers on register unwind - drop the extra per-node resolution sysfs ABI - turn live geometry changes into explicit SOURCE_CHANGE renegotiation - report live DV timings and reject attempts to retime a live source - stop advertising RESOLUTION source changes for fps-only updates - keep live fps state across harmless S_FMT restarts - stop exposing an unvalidated DV RX power-present signal - clean the imported sources for checkpatch and W=1 builds Validation: - build-tested with W=1 against a local kernel build tree - compiled the driver with ARCH=i386 allmodconfig and verified the resulting hws_pci.o, hws_video.o, and hws.o do not reference __udivdi3 - v4l2-compliance 1.33.0-5459 from v4l-utils commit 4a0d2c3b4f523406cb9a6f4c541ef14f72f19f3d on /dev/video2: 48 tests succeeded, 0 failed, 1 warning DV_RX_POWER_PRESENT is intentionally left unsupported in this revision because current hardware evidence does not expose a validated receiver-side power-detect signal distinct from active video presence. Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202604020522.z22eZuW8-lkp@intel.com/ Assisted-by: Codex:gpt-5.5 Signed-off-by: Ben Hoff <hoff.benjamin.k@gmail.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
174 lines
3.6 KiB
C
174 lines
3.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
#ifndef HWS_PCIE_H
|
|
#define HWS_PCIE_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/compiler.h>
|
|
#include <linux/dma-mapping.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/list.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/sizes.h>
|
|
#include <linux/atomic.h>
|
|
|
|
#include <media/v4l2-ctrls.h>
|
|
#include <media/v4l2-device.h>
|
|
#include <media/v4l2-dv-timings.h>
|
|
#include <media/videobuf2-dma-sg.h>
|
|
|
|
#include "hws_reg.h"
|
|
|
|
struct hwsmem_param {
|
|
u32 index;
|
|
u32 type;
|
|
u32 status;
|
|
};
|
|
|
|
struct hws_pix_state {
|
|
u32 width;
|
|
u32 height;
|
|
u32 fourcc; /* V4L2_PIX_FMT_* (YUYV only here) */
|
|
u32 bytesperline; /* stride */
|
|
u32 sizeimage; /* full frame */
|
|
enum v4l2_field field; /* V4L2_FIELD_NONE or INTERLACED */
|
|
enum v4l2_colorspace colorspace; /* e.g., REC709 */
|
|
enum v4l2_ycbcr_encoding ycbcr_enc; /* V4L2_YCBCR_ENC_DEFAULT */
|
|
enum v4l2_quantization quantization; /* V4L2_QUANTIZATION_LIM_RANGE */
|
|
enum v4l2_xfer_func xfer_func; /* V4L2_XFER_FUNC_DEFAULT */
|
|
bool interlaced; /* cached hardware state */
|
|
u32 half_size; /* hardware half-frame size */
|
|
};
|
|
|
|
#define UNSET (-1U)
|
|
|
|
struct hws_pcie_dev;
|
|
struct hws_adapter;
|
|
struct hws_video;
|
|
|
|
struct hwsvideo_buffer {
|
|
struct vb2_v4l2_buffer vb;
|
|
struct list_head list;
|
|
int slot;
|
|
};
|
|
|
|
struct hws_video {
|
|
/* Linkage */
|
|
struct hws_pcie_dev *parent;
|
|
struct video_device *video_device;
|
|
|
|
struct vb2_queue buffer_queue;
|
|
struct list_head capture_queue;
|
|
struct hwsvideo_buffer *active;
|
|
struct hwsvideo_buffer *next_prepared;
|
|
|
|
/* Locking */
|
|
struct mutex state_lock;
|
|
spinlock_t irq_lock; /* Protects capture_queue and active buffers. */
|
|
|
|
/* Indices */
|
|
int channel_index;
|
|
|
|
/* Color controls */
|
|
int current_brightness;
|
|
int current_contrast;
|
|
int current_saturation;
|
|
int current_hue;
|
|
|
|
/* V4L2 controls */
|
|
struct v4l2_ctrl_handler control_handler;
|
|
struct v4l2_ctrl *ctrl_brightness;
|
|
struct v4l2_ctrl *ctrl_contrast;
|
|
struct v4l2_ctrl *ctrl_saturation;
|
|
struct v4l2_ctrl *ctrl_hue;
|
|
|
|
/* Capture queue status */
|
|
struct hws_pix_state pix;
|
|
struct v4l2_dv_timings cur_dv_timings; /* last configured/notified DV timings */
|
|
u32 current_fps; /* Hz, updated by mode changes, not by read-only queries */
|
|
|
|
/* Per-channel capture state */
|
|
bool cap_active;
|
|
bool stop_requested;
|
|
u8 last_buf_half_toggle;
|
|
bool half_seen;
|
|
atomic_t sequence_number;
|
|
u32 queued_count;
|
|
|
|
/* Timeout and error handling */
|
|
u32 timeout_count;
|
|
u32 error_count;
|
|
|
|
bool window_valid;
|
|
u32 last_dma_hi;
|
|
u32 last_dma_page;
|
|
u32 last_pci_addr;
|
|
u32 last_half16;
|
|
|
|
/* Misc counters */
|
|
int signal_loss_cnt;
|
|
};
|
|
|
|
static inline void hws_set_current_dv_timings(struct hws_video *vid,
|
|
u32 width, u32 height,
|
|
bool interlaced)
|
|
{
|
|
if (!vid)
|
|
return;
|
|
|
|
vid->cur_dv_timings = (struct v4l2_dv_timings) {
|
|
.type = V4L2_DV_BT_656_1120,
|
|
.bt = {
|
|
.width = width,
|
|
.height = height,
|
|
.interlaced = interlaced,
|
|
},
|
|
};
|
|
}
|
|
|
|
struct hws_scratch_dma {
|
|
void *cpu;
|
|
dma_addr_t dma;
|
|
size_t size;
|
|
};
|
|
|
|
struct hws_pcie_dev {
|
|
/* Core objects */
|
|
struct pci_dev *pdev;
|
|
struct hws_video video[MAX_VID_CHANNELS];
|
|
|
|
/* BAR and workqueues */
|
|
void __iomem *bar0_base;
|
|
|
|
/* Device identity and capabilities */
|
|
u16 vendor_id;
|
|
u16 device_id;
|
|
u16 device_ver;
|
|
u16 hw_ver;
|
|
u32 sub_ver;
|
|
u32 port_id;
|
|
/* Tri-state support flag used by set_video_format_size(). */
|
|
u32 support_yv12;
|
|
u32 max_hw_video_buf_sz;
|
|
u8 max_channels;
|
|
u8 cur_max_video_ch;
|
|
bool start_run;
|
|
|
|
bool buf_allocated;
|
|
|
|
/* V4L2 framework objects */
|
|
struct v4l2_device v4l2_device;
|
|
|
|
/* Kernel thread */
|
|
struct task_struct *main_task;
|
|
struct hws_scratch_dma scratch_vid[MAX_VID_CHANNELS];
|
|
|
|
bool suspended;
|
|
int irq;
|
|
|
|
/* Error flags */
|
|
int pci_lost;
|
|
};
|
|
|
|
#endif
|