[PATCH 19/74] media: qcom: camss: vfe: Represent output as an array instead of a singleton
From: Bryan O'Donoghue
Date: Mon Oct 05 2026 - 13:29:56 EST
In order to instantiate multiple v4l2 sub-devices off of one "PIX" device
we need to represent more than one output per IFE. Right now the
representation between an IFE line and an output is 1:1. That simple link
works fine for the case of a raw data dump however, for multiple SOURCE and
SINK pads connected to a PIX device, we will require more outputs.
The first low-intervention step is to represent the existing singleton
output as one instance of an array of outputs. Since container_of() won't
work on an array element as input, introduce a line pointer to the output
structure to make that linkage back between output and line.
Signed-off-by: Bryan O'Donoghue <bod@xxxxxxxxxx>
---
drivers/media/platform/qcom/camss/camss-vfe-17x.c | 4 ++--
drivers/media/platform/qcom/camss/camss-vfe-4-1.c | 4 ++--
drivers/media/platform/qcom/camss/camss-vfe-4-7.c | 4 ++--
drivers/media/platform/qcom/camss/camss-vfe-4-8.c | 4 ++--
drivers/media/platform/qcom/camss/camss-vfe-480.c | 6 ++---
drivers/media/platform/qcom/camss/camss-vfe-gen1.c | 16 ++++++-------
drivers/media/platform/qcom/camss/camss-vfe.c | 26 +++++++++++++---------
drivers/media/platform/qcom/camss/camss-vfe.h | 6 ++++-
8 files changed, 39 insertions(+), 31 deletions(-)
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-17x.c b/drivers/media/platform/qcom/camss/camss-vfe-17x.c
index e5ee7e717b3bc..d2dc2acc9d234 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-17x.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-17x.c
@@ -490,7 +490,7 @@ static void vfe_isr_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)
spin_lock_irqsave(&vfe->output_lock, flags);
vfe->res->hw_ops->reg_update_clear(vfe, line_id);
- output = &vfe->line[line_id].output;
+ output = &vfe->line[line_id].output[0];
if (output->wait_reg_update) {
output->wait_reg_update = 0;
@@ -521,7 +521,7 @@ static void vfe_isr_wm_done(struct vfe_device *vfe, u8 wm)
"Received wm done for unmapped index\n");
goto out_unlock;
}
- output = &vfe->line[vfe->wm_output_map[wm]].output;
+ output = &vfe->line[vfe->wm_output_map[wm]].output[0];
ready_buf = output->buf[0];
if (!ready_buf) {
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
index 9cf1ccdb2fe7c..a2a91217a3cf8 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
@@ -475,7 +475,7 @@ static void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm,
static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
u8 enable)
{
- struct vfe_line *line = container_of(output, struct vfe_line, output);
+ struct vfe_line *line = output->line;
u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
u32 reg;
unsigned int i;
@@ -555,7 +555,7 @@ static void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm,
static void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp,
enum vfe_line_id line_id, u8 enable)
{
- struct vfe_output *output = &vfe->line[line_id].output;
+ struct vfe_output *output = &vfe->line[line_id].output[0];
unsigned int i;
u32 irq_en0;
u32 irq_en1;
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-7.c b/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
index 76729607db02d..2eb4c3d505ebf 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
@@ -565,7 +565,7 @@ static void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm,
static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
u8 enable)
{
- struct vfe_line *line = container_of(output, struct vfe_line, output);
+ struct vfe_line *line = output->line;
u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
u32 reg;
@@ -706,7 +706,7 @@ static void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm,
static void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp,
enum vfe_line_id line_id, u8 enable)
{
- struct vfe_output *output = &vfe->line[line_id].output;
+ struct vfe_output *output = &vfe->line[line_id].output[0];
unsigned int i;
u32 irq_en0;
u32 irq_en1;
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-8.c b/drivers/media/platform/qcom/camss/camss-vfe-4-8.c
index b2f7d855d8dd0..3166660d864ec 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-4-8.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-4-8.c
@@ -536,7 +536,7 @@ static void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm,
static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
u8 enable)
{
- struct vfe_line *line = container_of(output, struct vfe_line, output);
+ struct vfe_line *line = output->line;
u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
u32 reg;
@@ -678,7 +678,7 @@ static void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm,
static void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp,
enum vfe_line_id line_id, u8 enable)
{
- struct vfe_output *output = &vfe->line[line_id].output;
+ struct vfe_output *output = &vfe->line[line_id].output[0];
unsigned int i;
u32 irq_en0;
u32 irq_en1;
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-480.c b/drivers/media/platform/qcom/camss/camss-vfe-480.c
index d73f733fde045..616d80ae1da74 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-480.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-480.c
@@ -164,8 +164,8 @@ static void vfe_enable_irq(struct vfe_device *vfe)
for (i = 0; i < MAX_VFE_OUTPUT_LINES; i++) {
/* Enable IRQ for newly added lines, but also keep already running lines's IRQ */
- if (vfe->line[i].output.state == VFE_OUTPUT_RESERVED ||
- vfe->line[i].output.state == VFE_OUTPUT_ON) {
+ if (vfe->line[i].output[0].state == VFE_OUTPUT_RESERVED ||
+ vfe->line[i].output[0].state == VFE_OUTPUT_ON) {
bus_irq_mask |= BUS_IRQ_MASK_0_RDI_RUP(vfe, i)
| BUS_IRQ_MASK_0_COMP_DONE(vfe, RDI_COMP_GROUP(i));
}
@@ -242,7 +242,7 @@ static void vfe_isr_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)
spin_lock_irqsave(&vfe->output_lock, flags);
vfe_reg_update_clear(vfe, line_id);
- output = &vfe->line[line_id].output;
+ output = &vfe->line[line_id].output[0];
if (output->wait_reg_update) {
output->wait_reg_update = 0;
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen1.c b/drivers/media/platform/qcom/camss/camss-vfe-gen1.c
index d84a375e33187..3e3d103e0d09d 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-gen1.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-gen1.c
@@ -36,7 +36,7 @@ int vfe_gen1_halt(struct vfe_device *vfe)
static int vfe_disable_output(struct vfe_line *line)
{
struct vfe_device *vfe = to_vfe(line);
- struct vfe_output *output = &line->output;
+ struct vfe_output *output = &line->output[0];
const struct vfe_hw_ops *ops = vfe->res->hw_ops;
unsigned long flags;
unsigned long time;
@@ -162,13 +162,13 @@ static void vfe_output_frame_drop(struct vfe_device *vfe,
vfe->ops_gen1->wm_set_framedrop_pattern(vfe, output->wm_idx[i], drop_pattern);
}
- vfe->res->hw_ops->reg_update(vfe, container_of(output, struct vfe_line, output)->id);
+ vfe->res->hw_ops->reg_update(vfe, output->line->id);
}
static int vfe_enable_output(struct vfe_line *line)
{
struct vfe_device *vfe = to_vfe(line);
- struct vfe_output *output = &line->output;
+ struct vfe_output *output = &line->output[0];
const struct vfe_hw_ops *ops = vfe->res->hw_ops;
struct media_pad *sensor_pad;
unsigned long flags;
@@ -289,7 +289,7 @@ static int vfe_get_output(struct vfe_line *line)
spin_lock_irqsave(&vfe->output_lock, flags);
- output = &line->output;
+ output = &line->output[0];
if (output->state > VFE_OUTPUT_RESERVED) {
dev_err(vfe->camss->dev, "Output is running\n");
goto error;
@@ -526,7 +526,7 @@ static void vfe_isr_sof(struct vfe_device *vfe, enum vfe_line_id line_id)
unsigned long flags;
spin_lock_irqsave(&vfe->output_lock, flags);
- output = &vfe->line[line_id].output;
+ output = &vfe->line[line_id].output[0];
if (output->gen1.wait_sof) {
output->gen1.wait_sof = 0;
complete(&output->sof);
@@ -548,7 +548,7 @@ static void vfe_isr_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)
spin_lock_irqsave(&vfe->output_lock, flags);
vfe->res->hw_ops->reg_update_clear(vfe, line_id);
- output = &line->output;
+ output = &line->output[0];
if (output->wait_reg_update) {
output->wait_reg_update = 0;
@@ -625,7 +625,7 @@ static void vfe_isr_wm_done(struct vfe_device *vfe, u8 wm)
"Received wm done for unmapped index\n");
goto out_unlock;
}
- output = &vfe->line[vfe->wm_output_map[wm]].output;
+ output = &vfe->line[vfe->wm_output_map[wm]].output[0];
if (output->gen1.active_buf == active_index && 0) {
dev_err_ratelimited(vfe->camss->dev,
@@ -693,7 +693,7 @@ static int vfe_queue_buffer(struct camss_video *vid, struct camss_buffer *buf)
struct vfe_output *output;
unsigned long flags;
- output = &line->output;
+ output = &line->output[0];
spin_lock_irqsave(&vfe->output_lock, flags);
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
index c95fe5b0b05fc..54ab906b01a82 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe.c
@@ -604,7 +604,7 @@ void vfe_buf_done(struct vfe_device *vfe, int wm)
"Received wm done for unmapped index\n");
goto out_unlock;
}
- output = &vfe->line[vfe->wm_output_map[wm]].output;
+ output = &vfe->line[vfe->wm_output_map[wm]].output[0];
ready_buf = output->buf[0];
if (!ready_buf) {
@@ -645,7 +645,7 @@ void vfe_buf_done(struct vfe_device *vfe, int wm)
int vfe_enable_output_v2(struct vfe_line *line)
{
struct vfe_device *vfe = to_vfe(line);
- struct vfe_output *output = &line->output;
+ struct vfe_output *output = &line->output[0];
const struct vfe_hw_ops *ops = vfe->res->hw_ops;
struct media_pad *sensor_pad;
unsigned long flags;
@@ -719,7 +719,7 @@ int vfe_queue_buffer_v2(struct camss_video *vid,
struct vfe_output *output;
unsigned long flags;
- output = &line->output;
+ output = &line->output[0];
spin_lock_irqsave(&vfe->output_lock, flags);
@@ -798,7 +798,7 @@ int vfe_get_output_v2(struct vfe_line *line)
spin_lock_irqsave(&vfe->output_lock, flags);
- output = &line->output;
+ output = &line->output[0];
if (output->state > VFE_OUTPUT_RESERVED) {
dev_err(vfe->camss->dev, "Output is running\n");
goto error;
@@ -849,7 +849,7 @@ static void vfe_init_outputs(struct vfe_device *vfe)
int i;
for (i = 0; i < vfe->res->line_num; i++) {
- struct vfe_output *output = &vfe->line[i].output;
+ struct vfe_output *output = &vfe->line[i].output[0];
output->state = VFE_OUTPUT_OFF;
output->buf[0] = NULL;
@@ -933,7 +933,7 @@ static void vfe_buf_flush_pending(struct vfe_output *output,
int vfe_put_output(struct vfe_line *line)
{
struct vfe_device *vfe = to_vfe(line);
- struct vfe_output *output = &line->output;
+ struct vfe_output *output = &line->output[0];
unsigned long flags;
unsigned int i;
@@ -951,7 +951,7 @@ int vfe_put_output(struct vfe_line *line)
static int vfe_disable_output(struct vfe_line *line)
{
struct vfe_device *vfe = to_vfe(line);
- struct vfe_output *output = &line->output;
+ struct vfe_output *output = &line->output[0];
unsigned long flags;
unsigned int i;
@@ -1325,7 +1325,7 @@ int vfe_flush_buffers(struct camss_video *vid,
struct vfe_output *output;
unsigned long flags;
- output = &line->output;
+ output = &line->output[0];
spin_lock_irqsave(&vfe->output_lock, flags);
@@ -1387,7 +1387,7 @@ static int vfe_set_stream(struct v4l2_subdev *sd, int enable)
int ret;
if (enable) {
- line->output.state = VFE_OUTPUT_RESERVED;
+ line->output[0].state = VFE_OUTPUT_RESERVED;
ret = vfe->res->hw_ops->vfe_enable(line);
if (ret < 0)
dev_err(vfe->camss->dev,
@@ -2055,8 +2055,12 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
l->video_out.camss = camss;
l->id = i;
- init_completion(&l->output.sof);
- init_completion(&l->output.reg_update);
+
+ l->num_outputs = 1;
+ l->output[0].line = l;
+
+ init_completion(&l->output[0].sof);
+ init_completion(&l->output[0].reg_update);
if (i == VFE_LINE_PIX) {
l->nformats = res->vfe.formats_pix->nformats;
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h
index 98d403a71cf95..e043ef4468626 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.h
+++ b/drivers/media/platform/qcom/camss/camss-vfe.h
@@ -22,6 +22,7 @@
#define MSM_VFE_PAD_SINK 0
#define MSM_VFE_PAD_SRC 1
#define MSM_VFE_PADS_NUM 2
+#define MSM_VFE_NUM_OUTPUTS 1
#define MSM_VFE_IMAGE_MASTERS_NUM 7
#define MSM_VFE_COMPOSITE_IRQ_NUM 4
@@ -102,6 +103,8 @@ struct vfe_output {
int wait_reg_update;
struct completion sof;
struct completion reg_update;
+
+ struct vfe_line *line;
};
struct vfe_line {
@@ -112,7 +115,8 @@ struct vfe_line {
struct v4l2_rect compose;
struct v4l2_rect crop;
struct camss_video video_out;
- struct vfe_output output;
+ struct vfe_output output[MSM_VFE_NUM_OUTPUTS];
+ u32 num_outputs;
const struct camss_format_info *formats;
unsigned int nformats;
};
--
2.55.0