From: Balakrishnan Sambath <balakrishnan.s@microchip.com>
To: Eugen Hristev <ehristev@kernel.org>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Hans Verkuil <hverkuil@kernel.org>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Kieran Bingham <kieran.bingham@ideasonboard.com>,
Sakari Ailus <sakari.ailus@linux.intel.com>,
Balamanikandan Gunasundar
<balamanikandan.gunasundar@microchip.com>,
<stable@vger.kernel.org>, <linux-media@vger.kernel.org>,
<linux-kernel@vger.kernel.org>,
"Balakrishnan Sambath" <balakrishnan.s@microchip.com>
Subject: [PATCH v6 09/12] media: microchip-isc: add SAMA7G5 hue and saturation controls
Date: Wed, 3 Jun 2026 12:28:52 +0530 [thread overview]
Message-ID: <20260603-microchip-isc-fixes-v6-9-8c3d7474a768@microchip.com> (raw)
In-Reply-To: <20260603-microchip-isc-fixes-v6-0-8c3d7474a768@microchip.com>
The CBHS (Contrast/Brightness/Hue/Saturation) block on SAMA7G5
operates in YCbCr space; expose hue and saturation as V4L2 controls.
Hue and saturation act on chroma, so they are active only when the
output format is YUV. The SAMA5D2 has only the CBC block (no
hue/saturation), so the controls are gated on a new has_cbhs flag.
Saturation uses the Q4 fixed-point range 0..127 with default 16
(1.0x) directly matching the CBHS_SAT register field. The control
state is initialised to neutral at probe so the first config_cbc()
write after streaming starts does not produce a grayscale image.
Co-developed-by: Balamanikandan Gunasundar <balamanikandan.gunasundar@microchip.com>
Signed-off-by: Balamanikandan Gunasundar <balamanikandan.gunasundar@microchip.com>
Signed-off-by: Balakrishnan Sambath <balakrishnan.s@microchip.com>
---
.../media/platform/microchip/microchip-isc-base.c | 70 +++++++++++++++++++++-
.../media/platform/microchip/microchip-isc-regs.h | 11 ++--
drivers/media/platform/microchip/microchip-isc.h | 7 +++
.../platform/microchip/microchip-sama5d2-isc.c | 3 +-
.../platform/microchip/microchip-sama7g5-isc.c | 9 +--
5 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/drivers/media/platform/microchip/microchip-isc-base.c b/drivers/media/platform/microchip/microchip-isc-base.c
index 04187127070d..3a941757906a 100644
--- a/drivers/media/platform/microchip/microchip-isc-base.c
+++ b/drivers/media/platform/microchip/microchip-isc-base.c
@@ -859,6 +859,46 @@ static int isc_try_configure_pipeline(struct isc_device *isc)
return 0;
}
+static bool isc_format_is_yuv(u32 fourcc)
+{
+ switch (fourcc) {
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/*
+ * isc_update_cbhs_ctrls() - Activate/deactivate CBHS controls
+ *
+ * Called from isc_set_fmt(), isc_link_validate(), and isc_ctrl_init().
+ * At isc_ctrl_init() time isc->config.bits_pipeline is zero (no format
+ * has been negotiated yet), so all CBHS controls are initially marked
+ * inactive. They become active once a format that includes CBHS in the
+ * pipeline is configured via VIDIOC_S_FMT or link validation. Hue and
+ * saturation operate in YCbCr space, so they activate only when the
+ * output format is YUV.
+ */
+static void isc_update_cbhs_ctrls(struct isc_device *isc)
+{
+ bool cbhs_active = isc->config.bits_pipeline & CBHS_ENABLE;
+ bool chroma_active = cbhs_active && isc_format_is_yuv(isc->config.fourcc);
+
+ if (isc->brightness_ctrl)
+ v4l2_ctrl_activate(isc->brightness_ctrl, cbhs_active);
+ if (isc->contrast_ctrl)
+ v4l2_ctrl_activate(isc->contrast_ctrl, cbhs_active);
+ if (isc->hue_ctrl)
+ v4l2_ctrl_activate(isc->hue_ctrl, chroma_active);
+ if (isc->saturation_ctrl)
+ v4l2_ctrl_activate(isc->saturation_ctrl, chroma_active);
+}
+
static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f)
{
struct v4l2_pix_format *pixfmt = &f->fmt.pix;
@@ -902,6 +942,7 @@ static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f)
/* make the try configuration active */
isc->config = isc->try_config;
isc->fmt = isc->try_fmt;
+ isc_update_cbhs_ctrls(isc);
dev_dbg(isc->dev, "ISC set_fmt to %.4s @%dx%d\n",
(char *)&f->fmt.pix.pixelformat,
@@ -989,6 +1030,7 @@ static int isc_link_validate(struct media_link *link)
return ret;
isc->config = isc->try_config;
+ isc_update_cbhs_ctrls(isc);
dev_dbg(isc->dev, "New ISC configuration in place\n");
@@ -1457,6 +1499,14 @@ static int isc_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_CONTRAST:
ctrls->contrast = ctrl->val & ISC_CBC_CONTRAST_MASK;
break;
+ case V4L2_CID_HUE:
+ if (isc->has_cbhs)
+ ctrls->hue = ctrl->val & ISC_CBHS_HUE_MASK;
+ break;
+ case V4L2_CID_SATURATION:
+ if (isc->has_cbhs)
+ ctrls->saturation = ctrl->val & ISC_CBHS_SAT_MASK;
+ break;
case V4L2_CID_GAMMA:
ctrls->gamma_index = ctrl->val;
break;
@@ -1646,7 +1696,24 @@ static int isc_ctrl_init(struct isc_device *isc)
ctrls->brightness = 0;
- v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -1024, 1023, 1, 0);
+ isc->brightness_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS,
+ -1024, 1023, 1, 0);
+ if (isc->has_cbhs) {
+ /*
+ * CBHS_HUE is a signed 9-bit value in degrees.
+ * CBHS_SAT is Q4 unsigned 7-bit, 16 = 1.0x.
+ * Initialize the kernel-side state to neutral here so the
+ * first config_cbc() call after streaming starts does not
+ * write zero (grayscale) to the hardware.
+ */
+ ctrls->hue = 0;
+ ctrls->saturation = 16;
+ isc->hue_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HUE,
+ -180, 180, 1, 0);
+ isc->saturation_ctrl = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_SATURATION,
+ 0, 127, 1, 16);
+ }
v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAMMA, 0, isc->gamma_max, 1,
isc->gamma_default);
isc->awb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops,
@@ -1665,6 +1732,7 @@ static int isc_ctrl_init(struct isc_device *isc)
}
v4l2_ctrl_activate(isc->do_wb_ctrl, false);
+ isc_update_cbhs_ctrls(isc);
isc->r_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_gain_ctrl, NULL);
isc->b_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_gain_ctrl, NULL);
diff --git a/drivers/media/platform/microchip/microchip-isc-regs.h b/drivers/media/platform/microchip/microchip-isc-regs.h
index e77e1d9a1db8..7f5c2e50e74b 100644
--- a/drivers/media/platform/microchip/microchip-isc-regs.h
+++ b/drivers/media/platform/microchip/microchip-isc-regs.h
@@ -268,10 +268,13 @@
#define ISC_CBC_CONTRAST 0x000003c0
#define ISC_CBC_CONTRAST_MASK GENMASK(11, 0)
-/* Hue Register */
-#define ISC_CBCHS_HUE 0x4e0
-/* Saturation Register */
-#define ISC_CBCHS_SAT 0x4e4
+/* Hue Register: signed 9-bit two's complement, covers -180 to +180 degrees */
+#define ISC_CBHS_HUE 0x4e0
+#define ISC_CBHS_HUE_MASK GENMASK(8, 0)
+
+/* Saturation Register: unsigned Q4 fixed-point (1.0 = 16, V4L2 range 0..127) */
+#define ISC_CBHS_SAT 0x4e4
+#define ISC_CBHS_SAT_MASK GENMASK(6, 0)
/* Offset for SUB422 register specific to sama5d2 product */
#define ISC_SAMA5D2_SUB422_OFFSET 0
diff --git a/drivers/media/platform/microchip/microchip-isc.h b/drivers/media/platform/microchip/microchip-isc.h
index 2282ef7dd596..1ecefe990f00 100644
--- a/drivers/media/platform/microchip/microchip-isc.h
+++ b/drivers/media/platform/microchip/microchip-isc.h
@@ -139,6 +139,8 @@ struct isc_ctrls {
u32 brightness;
u32 contrast;
+ u32 hue;
+ u32 saturation;
u8 gamma_index;
#define ISC_WB_NONE 0
#define ISC_WB_AUTO 1
@@ -336,6 +338,10 @@ struct isc_device {
struct v4l2_ctrl *b_off_ctrl;
struct v4l2_ctrl *gr_off_ctrl;
struct v4l2_ctrl *gb_off_ctrl;
+ struct v4l2_ctrl *brightness_ctrl;
+ struct v4l2_ctrl *contrast_ctrl;
+ struct v4l2_ctrl *hue_ctrl;
+ struct v4l2_ctrl *saturation_ctrl;
};
#define GAMMA_ENTRIES 64
@@ -343,6 +349,7 @@ struct isc_device {
const u32 (*gamma_table)[GAMMA_ENTRIES];
u32 gamma_max;
u32 gamma_default;
+ bool has_cbhs;
u32 max_width;
u32 max_height;
diff --git a/drivers/media/platform/microchip/microchip-sama5d2-isc.c b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
index 9fa8413c74c7..4b8279fba560 100644
--- a/drivers/media/platform/microchip/microchip-sama5d2-isc.c
+++ b/drivers/media/platform/microchip/microchip-sama5d2-isc.c
@@ -264,7 +264,8 @@ static void isc_sama5d2_config_ctrls(struct isc_device *isc,
ctrls->contrast = 256;
- v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 256);
+ isc->contrast_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST,
+ -2048, 2047, 1, 256);
}
static void isc_sama5d2_config_dpc(struct isc_device *isc)
diff --git a/drivers/media/platform/microchip/microchip-sama7g5-isc.c b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
index ac21fe1dade0..e6ccdd465805 100644
--- a/drivers/media/platform/microchip/microchip-sama7g5-isc.c
+++ b/drivers/media/platform/microchip/microchip-sama7g5-isc.c
@@ -257,9 +257,8 @@ static void isc_sama7g5_config_cbc(struct isc_device *isc)
/* Configure what is set via v4l2 ctrls */
regmap_write(regmap, ISC_CBC_BRIGHT + isc->offsets.cbc, isc->ctrls.brightness);
regmap_write(regmap, ISC_CBC_CONTRAST + isc->offsets.cbc, isc->ctrls.contrast);
- /* Configure Hue and Saturation as neutral midpoint */
- regmap_write(regmap, ISC_CBCHS_HUE, 0);
- regmap_write(regmap, ISC_CBCHS_SAT, (1 << 4));
+ regmap_write(regmap, ISC_CBHS_HUE, isc->ctrls.hue);
+ regmap_write(regmap, ISC_CBHS_SAT, isc->ctrls.saturation);
}
static void isc_sama7g5_config_cc(struct isc_device *isc)
@@ -283,7 +282,8 @@ static void isc_sama7g5_config_ctrls(struct isc_device *isc,
ctrls->contrast = 16;
- v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 16);
+ isc->contrast_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST,
+ -2048, 2047, 1, 16);
}
static void isc_sama7g5_config_dpc(struct isc_device *isc)
@@ -463,6 +463,7 @@ static int microchip_xisc_probe(struct platform_device *pdev)
isc->gamma_max = 2;
/* Index 1 in the SAMA7G5 table is gamma 1/2.2 (sRGB). */
isc->gamma_default = 1;
+ isc->has_cbhs = true;
if (of_machine_is_compatible("microchip,sam9x7")) {
isc->max_width = ISC_SAM9X7_MAX_SUPPORT_WIDTH;
--
2.34.1
next prev parent reply other threads:[~2026-06-03 6:59 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-03 6:58 [PATCH v6 00/12] media: microchip-isc: fixes and enhancements Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 01/12] media: microchip-isc: fix SBGGR10 Bayer pattern Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 02/12] media: microchip-isc: fix WB offset and gain register field masking Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 03/12] media: microchip-isc: fix race condition on stream stop Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 04/12] media: microchip-isc: fix PM runtime leak in AWB work handler Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 05/12] media: microchip-isc: add driver documentation Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 06/12] media: microchip-isc: set SAM9X7 maximum resolution to 2560x1920 Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 07/12] media: microchip-isc: configure DPC and pipeline for SAMA7G5 Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 08/12] media: microchip-isc: add gamma 1.8 and 2.4 correction curves Balakrishnan Sambath
2026-06-03 6:58 ` Balakrishnan Sambath [this message]
2026-06-03 6:58 ` [PATCH v6 10/12] media: microchip-isc: use weighted averages for Grey World AWB Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 11/12] media: microchip-isc: smooth AWB gains with EMA filter Balakrishnan Sambath
2026-06-03 6:58 ` [PATCH v6 12/12] media: microchip-isc: scale DPC black level to sensor bit depth Balakrishnan Sambath
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260603-microchip-isc-fixes-v6-9-8c3d7474a768@microchip.com \
--to=balakrishnan.s@microchip.com \
--cc=balamanikandan.gunasundar@microchip.com \
--cc=ehristev@kernel.org \
--cc=hverkuil@kernel.org \
--cc=kieran.bingham@ideasonboard.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=sakari.ailus@linux.intel.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®