[PATCH RFC 2/4] media: qcom: camss: vfe: Describe the IFE pixel pipe per version

From: William Bright

Date: Tue Oct 13 2026 - 04:49:12 EST


The SM8550 IFE 780 runs the same pixel pipe register map as the
SM8650 IFE 880 but holds its WB gain in a different format.

Pass the pipe a small description of what differs between the IFEs
that run it, starting with the WB gain value for full scale, and keep
the IFE 880 on its current 4.0. No functional change.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: William Bright <william.bright@xxxxxxxxxxx>
---
drivers/media/platform/qcom/camss/camss-vfe-780.c | 8 +++++++-
drivers/media/platform/qcom/camss/camss-vfe-880-pp.c | 20 +++++++++++++-------
drivers/media/platform/qcom/camss/camss-vfe-880-pp.h | 10 +++++++++-
3 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/qcom/camss/camss-vfe-780.c b/drivers/media/platform/qcom/camss/camss-vfe-780.c
index 6d483f917d15..c2ffe39f929a 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-780.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-780.c
@@ -236,12 +236,18 @@ static inline void vfe_reg_update_clear(struct vfe_device *vfe,
* Program the pixel pipe outside output_lock, before the write masters and
* the IPP reg update that latches both.
*/
+static const struct vfe_pp_desc *vfe_pp_desc(struct vfe_device *vfe)
+{
+ return &vfe_pp_desc_880;
+}
+
static void vfe_line_prepare(struct vfe_line *line)
{
struct v4l2_pix_format_mplane *pix = &line->output[0].video_out.active_fmt.fmt.pix_mp;
+ struct vfe_device *vfe = to_vfe(line);

if (line->is_pix && pix->pixelformat == V4L2_PIX_FMT_NV12)
- vfe_880_setup_pixel_pipe(to_vfe(line), pix->width, pix->height);
+ vfe_880_setup_pixel_pipe(vfe, vfe_pp_desc(vfe), pix->width, pix->height);
}

static const struct camss_video_ops vfe_video_ops_780 = {
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-880-pp.c b/drivers/media/platform/qcom/camss/camss-vfe-880-pp.c
index 9b4bdad6d396..f962016ef3c6 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-880-pp.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-880-pp.c
@@ -313,8 +313,13 @@ static void vfe_setup_chroma_downscale_nv12(struct vfe_device *vfe, u32 w, u32 h
writel_relaxed(0x00000000, vfe->base + IFE_DOWNSCALE_MN_C_VID_OUT_DOWNSCALE_MN_C_V_PHASE_CFG);
}

-/* Demosaic + WB: sub offsets 0, gains 4.0, add offsets 0 */
-static void vfe_setup_demosaic(struct vfe_device *vfe)
+/* IFE 880: Q10 gain of 4.0 */
+const struct vfe_pp_desc vfe_pp_desc_880 = {
+ .wb_gain = 0x00001000,
+};
+
+/* Demosaic + WB: sub offsets 0, full scale gains, add offsets 0 */
+static void vfe_setup_demosaic(struct vfe_device *vfe, const struct vfe_pp_desc *desc)
{
writel_relaxed(0x00000001, vfe->base + IFE_DEMOSAIC_MODULE_CFG);
writel_relaxed(0x00000080, vfe->base + IFE_DEMOSAIC_INTERP_COEFF_CFG_0);
@@ -322,9 +327,9 @@ static void vfe_setup_demosaic(struct vfe_device *vfe)
writel_relaxed(0x00000040, vfe->base + IFE_DEMOSAIC_INTERP_CLASSIFIER_CFG_0);
writel_relaxed(0x00000066, vfe->base + IFE_DEMOSAIC_INTERP_CLASSIFIER_CFG_1);
writel_relaxed(0x00000001, vfe->base + IFE_WB_GAIN_MODULE_CFG);
- writel_relaxed(0x00001000, vfe->base + IFE_WB_GAIN_WB_CFG_0);
- writel_relaxed(0x00001000, vfe->base + IFE_WB_GAIN_WB_CFG_1);
- writel_relaxed(0x00001000, vfe->base + IFE_WB_GAIN_WB_CFG_2);
+ writel_relaxed(desc->wb_gain, vfe->base + IFE_WB_GAIN_WB_CFG_0);
+ writel_relaxed(desc->wb_gain, vfe->base + IFE_WB_GAIN_WB_CFG_1);
+ writel_relaxed(desc->wb_gain, vfe->base + IFE_WB_GAIN_WB_CFG_2);
writel_relaxed(0x00000000, vfe->base + IFE_WB_GAIN_WB_OFFSET_CFG_0);
writel_relaxed(0x00000000, vfe->base + IFE_WB_GAIN_WB_OFFSET_CFG_1);
writel_relaxed(0x00000000, vfe->base + IFE_WB_GAIN_WB_OFFSET_CFG_2);
@@ -611,11 +616,12 @@ static void vfe_setup_ds16(struct vfe_device *vfe, u32 w, u32 h)
}

/* Called from vfe_line_prepare() for NV12, ahead of the write masters and the IPP reg update */
-void vfe_880_setup_pixel_pipe(struct vfe_device *vfe, u32 w, u32 h)
+void vfe_880_setup_pixel_pipe(struct vfe_device *vfe, const struct vfe_pp_desc *desc,
+ u32 w, u32 h)
{
vfe_setup_core_config(vfe);
vfe_setup_chroma_downscale_nv12(vfe, w, h);
- vfe_setup_demosaic(vfe);
+ vfe_setup_demosaic(vfe, desc);
vfe_setup_color_correction(vfe);
vfe_setup_gamma_luts(vfe);
vfe_setup_color_transform(vfe);
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-880-pp.h b/drivers/media/platform/qcom/camss/camss-vfe-880-pp.h
index e033880e5534..fe3a604c579d 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-880-pp.h
+++ b/drivers/media/platform/qcom/camss/camss-vfe-880-pp.h
@@ -6,7 +6,15 @@

struct vfe_device;

-void vfe_880_setup_pixel_pipe(struct vfe_device *vfe, u32 width, u32 height);
+/* What differs between the IFEs that run this pixel pipe */
+struct vfe_pp_desc {
+ u32 wb_gain; /* WB gain register value for full scale */
+};
+
+extern const struct vfe_pp_desc vfe_pp_desc_880;
+
+void vfe_880_setup_pixel_pipe(struct vfe_device *vfe, const struct vfe_pp_desc *desc,
+ u32 width, u32 height);
void vfe_880_set_aec_bhist_region(struct vfe_device *vfe, u32 h_offset,
u32 v_offset, u32 h_num, u32 v_num);


--
2.43.0