From nobody Tue Dec 16 03:23:38 2025 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 76B182D8376; Wed, 13 Aug 2025 07:21:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069674; cv=none; b=QUDzGjoA3XOOyPocDTnWKQe6P8Xhfwc0QRQbqV4sPWMia6bntTi2VQfKbXN47FNhcHQelwHsc8R3EAVr2wbDrbLM9oHHuAUMip7Y0q1d1zKwU1Q64Pr54xOvhLDe+qtlER2Wx3YKlHvAklLbxxVNagsxvVkcnNcOLw2jkZycxdU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069674; c=relaxed/simple; bh=tCbtHP0l24CdZOmNuW2EwX1W3haahawiSHSblfoGjP0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=t1MPTK7gNvfLaGScewPA9SEFS/y550VB8sgJCbmXlDXFEz8HhccZuSXq17HRV99pnD0Qi7MnlAatJcCvPuM3UmBmM9IGKBXJ4UeygLBMs5ghCKgVUKKVFkVSzvEs81gU+uQGC4djzLBO7sB2/eIVJ6yX2caO6m3Uz4uMYa1JU24= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=Pml5g5LR; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Pml5g5LR" Received: from mail.ideasonboard.com (unknown [IPv6:2401:4900:1c66:bd1a:669e:3dcb:5a6b:a905]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 152123A4; Wed, 13 Aug 2025 09:20:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1755069617; bh=tCbtHP0l24CdZOmNuW2EwX1W3haahawiSHSblfoGjP0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Pml5g5LRsTB1+9iZGFeax8cxer27Z3VGI3rz6jXn8rAnNmGjnYQh6okWm8M0MLkK7 Sb5+kWCgyEBiCesBBdcpn6qHDUjjMFr9lS7fW+hZN57pASeXuWWijMhfIgdb6yi10r VdmaHBf/ziL7/cRS8sbSvHEM1Yuy3tJluacWdQZ8= From: Jai Luthra Date: Wed, 13 Aug 2025 12:50:32 +0530 Subject: [PATCH 1/6] media: imx335: Rectify name of mode struct Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250813-imx335_binning-v1-1-a42b687d8541@ideasonboard.com> References: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> In-Reply-To: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> To: Kieran Bingham , Sakari Ailus , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Jai Luthra , Umang Jain , Tommaso Merciai X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1462; i=jai.luthra@ideasonboard.com; h=from:subject:message-id; bh=dvqqAX7Bxitse8vWjXeACNLn21gxhCs2yMl5pE/naOw=; b=owEBbQKS/ZANAwAKAUPekfkkmnFFAcsmYgBonDzVvlwaDGun4c/DdflZCC8Ju6YQ9Iqs2qhCN Bx3kHa/k+eJAjMEAAEKAB0WIQRN4NgY5dV16NRar8VD3pH5JJpxRQUCaJw81QAKCRBD3pH5JJpx RdmkD/9pSi94I8BDh17WAskTbs2EL92Wv0TQBl7G5msuvlRrztFs2iATFT/NGdcTwFeLlX2+eEh chdxpPvlH7G3FxNhR+tIbqSD72QtYlg9YRGRi5/tFDuqufb95onzp4/A9TQyUZ0SmT4+f0D5Hhv cR841Z0T1bxheq23AGGqVmjJvXOP0v4XtTMSPHVhj/Zggbb+tuQLsp1hjQckB39vmjfNkRASUON MX9P+8b96otdVXXhVVz38loXFnzBRSwagLJGe/AWsqldxdASOh5pO5IqfVfFhc/ZBYoP6IivcXy 6f6Uw3cOkABHWEWWieK+v9w/HRb/T1+ihRrcYt1qwFQKGVaezqrUKaJN6Ew2tlRnaGnUyqjaSKJ CwRSfQG+NO9ffWaBeEWeGRtGiJsR1YRxxDv4+peY3KH9qQSorFwggHTrYidxus7KUTTIDF2kclW 8Fv340YmYdzqgUnvXigrBR6oQDVy08I7e0PnJq9v4ng/PQBwSDw0SJQyr8u7AzryjTqqViLuqoU yiJORhiX4oaQQAXla4GnLhgR5+FDdorNxZb/blwjwEOw4+GzgwQCqz8FVEtOaLY1Y84JhHpYr4C l3P+EqbNFXOvaoft/tFir7Iz7o1QU3dtJdHojmiYGP/tBFlsF+aUhcHJU+KNBiWaxjQ5AhNQMiF ZNrP434aYfc6qhg== X-Developer-Key: i=jai.luthra@ideasonboard.com; a=openpgp; fpr=4DE0D818E5D575E8D45AAFC543DE91F9249A7145 From: Umang Jain In commit 81495a59baeb ("media: imx335: Fix active area height discrepency") the height for the mode struct was rectified to '1944'. However, the name of mode struct is still reflecting to '1940'. Update it. Signed-off-by: Umang Jain Reviewed-by: Tommaso Merciai Reviewed-by: Kieran Bingham Signed-off-by: Jai Luthra --- drivers/media/i2c/imx335.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index 9b4db4cd4929caf83596e93d2ac3de2f54e892b0..33f92a3062c14251498cc65f14c= c34cff6179f78 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -252,7 +252,7 @@ static const int imx335_tpg_val[] =3D { }; =20 /* Sensor mode registers */ -static const struct cci_reg_sequence mode_2592x1940_regs[] =3D { +static const struct cci_reg_sequence mode_2592x1944_regs[] =3D { { IMX335_REG_MODE_SELECT, IMX335_MODE_STANDBY }, { IMX335_REG_MASTER_MODE, 0x00 }, { IMX335_REG_WINMODE, 0x04 }, @@ -416,8 +416,8 @@ static const struct imx335_mode supported_mode =3D { .vblank_max =3D 133060, .pclk =3D 396000000, .reg_list =3D { - .num_of_regs =3D ARRAY_SIZE(mode_2592x1940_regs), - .regs =3D mode_2592x1940_regs, + .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_regs), + .regs =3D mode_2592x1944_regs, }, }; =20 --=20 2.50.1 From nobody Tue Dec 16 03:23:38 2025 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 88FA62D46B4; Wed, 13 Aug 2025 07:21:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069680; cv=none; b=r5kW76WEa2q3oQ04ak8MehEEif27T0UyFIl6MMQdf7kNOk5sLwJ1mfWRRdgSfGSsnABDWZz+l0BGhcGZlWlhUup/oN1hokab4JPfWKdUKi7gZZ+ZbueTVNx69MnGyVbM6Qi3tQHnEuMF5FFIKD+11Sp5zObilFjB8xrMVKKPMjY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069680; c=relaxed/simple; bh=zgWVoLf44W7zpwzzoRCJmrq/d1DfwbqjVRtQYev9G7E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HLY7XrAJGCEIogkyNmBU76H1O+ICy+b5O35nKx22SvWmmTlpR+WiGD7QQINy3oXW6pFQWyRCU7TfYCcqzVoubZLaUhPHqWlkLfDBsRP3g5p9yXcZdgn/UAwDLMYTpiHKchIjCElIwJHcxFYl2byE8FHL47ARJ/TUDgLG/XdAD1Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=TRaS9ZUI; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="TRaS9ZUI" Received: from mail.ideasonboard.com (unknown [IPv6:2401:4900:1c66:bd1a:669e:3dcb:5a6b:a905]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6E598351; Wed, 13 Aug 2025 09:20:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1755069622; bh=zgWVoLf44W7zpwzzoRCJmrq/d1DfwbqjVRtQYev9G7E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TRaS9ZUI1aaEJoRA9JjPsqC+2QcAdA/Vd7TKMj6++43KlQGcQjw1mJk6GCpFCU1kx mFcrLXIOQuM11IBRj1ApefggAo6fbdZfl9bbrMv18UYRUMDhu++c5i1SATc86+lHAY m/Reb4knTiJdiPcmKj907Da77dSDfxT5qaLrOTIw= From: Jai Luthra Date: Wed, 13 Aug 2025 12:50:33 +0530 Subject: [PATCH 2/6] media: imx335: Support vertical flip Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250813-imx335_binning-v1-2-a42b687d8541@ideasonboard.com> References: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> In-Reply-To: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> To: Kieran Bingham , Sakari Ailus , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Jai Luthra , Umang Jain , Tommaso Merciai X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5962; i=jai.luthra@ideasonboard.com; h=from:subject:message-id; bh=gnvxXU7y11ZFL8BNfuQYX0YjbopnxjR4gzoKloQMIn8=; b=owEBbQKS/ZANAwAKAUPekfkkmnFFAcsmYgBonDzWBNCJxH7JAoOQy5gPtS4p1wtcJ4fkwTgWa uqc0pZX75KJAjMEAAEKAB0WIQRN4NgY5dV16NRar8VD3pH5JJpxRQUCaJw81gAKCRBD3pH5JJpx RVKKEACEPqXX9eicrI5mlcYlvhrSgL5YsRwuD3SOtO/xyfbU9TM8F/KwoPO3ZIYEPEw8Ya5fREk zHQTEBIR9NQ2evSgcH4OE7L4i3jcZ/G/6wSFBeTc4gajxBpQYhkqqAIPqNDM3WdqSvMHI+u5bGT 1N1DLt6Otv5+6P8tRMc2eQjWrS4kEiPgp/0IniqNoGY3pvxJe0p5XDTQssWIWxXXAvAg7b4Nlng VbVU6hRhrFmgKZ2GUrYihU+5ghN4WHI8zTbjpjqsMidFLfdKwntounES7+lWqjeeFsKIAM22IVs yVlpqh5u7t5G/rGicY2a6OlarBa8Hyse34d6Iyv5UE48gYVz8zAJG5CgU3I9UzzWD3+TUgvFTNh 5FoZUT3hUDWweE89VGaQ8MjkVozPYErUov6PyJqrA/eVCf+AwFAe3WDmrVgWKO5TOf7RFc3V8Pn +tgl78pu5FTHGPHWDiNwgvkwejDLfmHAPEl/NPqlGCuslVwrWx2bF5cd1/dJs2/TrNrLBqvXVSZ fxe18vLWaHZmWgj0jB+wfKhqiLAxk99oAFgPtXPvLhNyuFQ932KxI+7KKpigKU54lnoJdY+Wvyt ChPn4QStEme6LEL7Y1ANwVpM2iUnmRc1C0qqGD1rgn88InkVD4cSg/7c/9Ac09JRwNp1wEtOcZB dGPZbI2zQo7299Q== X-Developer-Key: i=jai.luthra@ideasonboard.com; a=openpgp; fpr=4DE0D818E5D575E8D45AAFC543DE91F9249A7145 From: Umang Jain Support vertical flip by setting REG_VREVERSE. Additional registers also needs to be set per mode, according to the readout direction (normal/inverted) as mentioned in the data sheet. Since the register IMX335_REG_AREA3_ST_ADR_1 is based on the flip (and is set via vflip related registers), it has been moved out of the 2592x1944 mode regs. Signed-off-by: Umang Jain Reviewed-by: Tommaso Merciai Reviewed-by: Kieran Bingham Signed-off-by: Jai Luthra --- drivers/media/i2c/imx335.c | 71 ++++++++++++++++++++++++++++++++++++++++++= ++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index 33f92a3062c14251498cc65f14cc34cff6179f78..6369bdbd2b09ba1f89c143cdf6b= e061820f2d051 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -56,6 +56,9 @@ #define IMX335_AGAIN_STEP 1 #define IMX335_AGAIN_DEFAULT 0 =20 +/* Vertical flip */ +#define IMX335_REG_VREVERSE CCI_REG8(0x304f) + #define IMX335_REG_TPG_TESTCLKEN CCI_REG8(0x3148) =20 #define IMX335_REG_INCLKSEL1 CCI_REG16_LE(0x314c) @@ -155,6 +158,8 @@ static const char * const imx335_supply_name[] =3D { * @vblank_max: Maximum vertical blanking in lines * @pclk: Sensor pixel clock * @reg_list: Register list for sensor mode + * @vflip_normal: Register list vflip (normal readout) + * @vflip_inverted: Register list vflip (inverted readout) */ struct imx335_mode { u32 width; @@ -166,6 +171,8 @@ struct imx335_mode { u32 vblank_max; u64 pclk; struct imx335_reg_list reg_list; + struct imx335_reg_list vflip_normal; + struct imx335_reg_list vflip_inverted; }; =20 /** @@ -183,6 +190,7 @@ struct imx335_mode { * @pclk_ctrl: Pointer to pixel clock control * @hblank_ctrl: Pointer to horizontal blanking control * @vblank_ctrl: Pointer to vertical blanking control + * @vflip: Pointer to vertical flip control * @exp_ctrl: Pointer to exposure control * @again_ctrl: Pointer to analog gain control * @vblank: Vertical blanking in lines @@ -207,6 +215,7 @@ struct imx335 { struct v4l2_ctrl *pclk_ctrl; struct v4l2_ctrl *hblank_ctrl; struct v4l2_ctrl *vblank_ctrl; + struct v4l2_ctrl *vflip; struct { struct v4l2_ctrl *exp_ctrl; struct v4l2_ctrl *again_ctrl; @@ -259,7 +268,6 @@ static const struct cci_reg_sequence mode_2592x1944_reg= s[] =3D { { IMX335_REG_HTRIMMING_START, 48 }, { IMX335_REG_HNUM, 2592 }, { IMX335_REG_Y_OUT_SIZE, 1944 }, - { IMX335_REG_AREA3_ST_ADR_1, 176 }, { IMX335_REG_AREA3_WIDTH_1, 3928 }, { IMX335_REG_OPB_SIZE_V, 0 }, { IMX335_REG_XVS_XHS_DRV, 0x00 }, @@ -333,6 +341,26 @@ static const struct cci_reg_sequence mode_2592x1944_re= gs[] =3D { { CCI_REG8(0x3a00), 0x00 }, }; =20 +static const struct cci_reg_sequence mode_2592x1944_vflip_normal[] =3D { + { IMX335_REG_AREA3_ST_ADR_1, 176 }, + + /* Undocumented V-Flip related registers on Page 55 of datasheet. */ + { CCI_REG8(0x3081), 0x02, }, + { CCI_REG8(0x3083), 0x02, }, + { CCI_REG16_LE(0x30b6), 0x00 }, + { CCI_REG16_LE(0x3116), 0x08 }, +}; + +static const struct cci_reg_sequence mode_2592x1944_vflip_inverted[] =3D { + { IMX335_REG_AREA3_ST_ADR_1, 4112 }, + + /* Undocumented V-Flip related registers on Page 55 of datasheet. */ + { CCI_REG8(0x3081), 0xfe, }, + { CCI_REG8(0x3083), 0xfe, }, + { CCI_REG16_LE(0x30b6), 0x1fa }, + { CCI_REG16_LE(0x3116), 0x002 }, +}; + static const struct cci_reg_sequence raw10_framefmt_regs[] =3D { { IMX335_REG_ADBIT, 0x00 }, { IMX335_REG_MDBIT, 0x00 }, @@ -419,6 +447,14 @@ static const struct imx335_mode supported_mode =3D { .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_regs), .regs =3D mode_2592x1944_regs, }, + .vflip_normal =3D { + .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_vflip_normal), + .regs =3D mode_2592x1944_vflip_normal, + }, + .vflip_inverted =3D { + .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_vflip_inverted), + .regs =3D mode_2592x1944_vflip_inverted, + }, }; =20 /** @@ -492,6 +528,26 @@ static int imx335_update_exp_gain(struct imx335 *imx33= 5, u32 exposure, u32 gain) return ret; } =20 +static int imx335_update_vertical_flip(struct imx335 *imx335, u32 vflip) +{ + int ret =3D 0; + + if (vflip) + cci_multi_reg_write(imx335->cci, + imx335->cur_mode->vflip_inverted.regs, + imx335->cur_mode->vflip_inverted.num_of_regs, + &ret); + else + cci_multi_reg_write(imx335->cci, + imx335->cur_mode->vflip_normal.regs, + imx335->cur_mode->vflip_normal.num_of_regs, + &ret); + if (ret) + return ret; + + return cci_write(imx335->cci, IMX335_REG_VREVERSE, vflip, NULL); +} + static int imx335_update_test_pattern(struct imx335 *imx335, u32 pattern_i= ndex) { int ret =3D 0; @@ -593,6 +649,10 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) =20 ret =3D imx335_update_exp_gain(imx335, exposure, analog_gain); =20 + break; + case V4L2_CID_VFLIP: + ret =3D imx335_update_vertical_flip(imx335, ctrl->val); + break; case V4L2_CID_TEST_PATTERN: ret =3D imx335_update_test_pattern(imx335, ctrl->val); @@ -1176,7 +1236,7 @@ static int imx335_init_controls(struct imx335 *imx335) return ret; =20 /* v4l2_fwnode_device_properties can add two more controls */ - ret =3D v4l2_ctrl_handler_init(ctrl_hdlr, 9); + ret =3D v4l2_ctrl_handler_init(ctrl_hdlr, 10); if (ret) return ret; =20 @@ -1211,6 +1271,13 @@ static int imx335_init_controls(struct imx335 *imx33= 5) =20 v4l2_ctrl_cluster(2, &imx335->exp_ctrl); =20 + imx335->vflip =3D v4l2_ctrl_new_std(ctrl_hdlr, + &imx335_ctrl_ops, + V4L2_CID_VFLIP, + 0, 1, 1, 0); + if (imx335->vflip) + imx335->vflip->flags |=3D V4L2_CTRL_FLAG_MODIFY_LAYOUT; + imx335->vblank_ctrl =3D v4l2_ctrl_new_std(ctrl_hdlr, &imx335_ctrl_ops, V4L2_CID_VBLANK, --=20 2.50.1 From nobody Tue Dec 16 03:23:38 2025 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B00F22E6137; Wed, 13 Aug 2025 07:21:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069683; cv=none; b=LZ5V3rQqwDbA836mdTfbZ7eG/0iNhMczLeLWJZq4cmiE3jM2/y4OEi5+vJgYAbCAOGU6Ro1FCxrxzWKgbo4js1RHSrWmevMZSLqwTKBnscxWd8psfSJBjz1P/XwFN8XBu1mgfROgtbSVVhi6+Je55NZ0FqIIC4halVIbWG1W0I8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069683; c=relaxed/simple; bh=S1Favj4HSSU0z5pC5G1EzkLDtwSs+X4mZUXj/zOdENw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BpFxyH5D3yveDWvyFutdaS7lvzIRvJk4P6aGbrXhIHAbfGbmSrhgJvTP5WADNpI1xg0hGKmdnZmqyRZ2vbkelpMLTtr+b0iqKLP7AP5zpAJGg3fs4VruIp0VHM61oW6sh4ABbf6QhW0L8rl+1rw69Ipx2JObFgZBbLX+6YF0jLI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=ZQkpz3Kh; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ZQkpz3Kh" Received: from mail.ideasonboard.com (unknown [IPv6:2401:4900:1c66:bd1a:669e:3dcb:5a6b:a905]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C9EE23A4; Wed, 13 Aug 2025 09:20:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1755069627; bh=S1Favj4HSSU0z5pC5G1EzkLDtwSs+X4mZUXj/zOdENw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ZQkpz3KhGd4bzfIRR0WWuIFYBGtNh53vLRKp4hvyWTtNrhwwwGfLfrLGUVBRP5M8y 0ILRAch/0BUs7fT3x4QI+7GrXiF7LAiycE3JB8ZolMONQw8k/G5SEobZxF1Nf+5rv4 J2ewrj8iLADzNotNlXRcNQyBYY68mqYHCiUvWpV8= From: Jai Luthra Date: Wed, 13 Aug 2025 12:50:34 +0530 Subject: [PATCH 3/6] media: imx335: Update the native pixel array width Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250813-imx335_binning-v1-3-a42b687d8541@ideasonboard.com> References: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> In-Reply-To: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> To: Kieran Bingham , Sakari Ailus , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Jai Luthra X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1110; i=jai.luthra@ideasonboard.com; h=from:subject:message-id; bh=S1Favj4HSSU0z5pC5G1EzkLDtwSs+X4mZUXj/zOdENw=; b=owEBbQKS/ZANAwAKAUPekfkkmnFFAcsmYgBonDzXBWrfJaMFYIw+5gn0hEi3vuA1eGJaswAP5 hqx+fOuEE6JAjMEAAEKAB0WIQRN4NgY5dV16NRar8VD3pH5JJpxRQUCaJw81wAKCRBD3pH5JJpx RV17EADIb86aWGJK6NZ9IQV0y5hHAA71CGukJmCdi0UPtRRJgurwXr1SD11rSiP5xsYdAis9roo ALM80MfS9km6IHfxA6/YZIkw0+oO9naGwcv4q0ndavryXNuaUMtsi+dmeIskleU21F/6nbMJO43 XENdgbn6onzLsDZq5vZV4AKrTR3aBL6O4eZReWuGwuwsUq7BVSctDHDey4x3geAAx7ZVQnKZF34 WsDhyjpDQNqGVUDuNpdfuUlj9O9V8HW49W4qiixL+p17ge1IxzDIPB10Sw1LTmYG8mmIRVXbX9D F1xKFxvmaNwv/BBckaCoVgfwx6fHPsd0TItZuhhfzFJCtbB7hmHrY/ZGryY3NvXGdhL6gaos7gQ dVxK5mYwjrLHtLnAoWE+vs4X1krTx0ZJcWLzwC8TOSglFONciR1U3Cs49ALrSUEnPlvpd9bkc1N CfSC4+eX+yn/UxuU92YxfzsLh9sVwDzTYjzRNHHLx7QB12cePbOIadswLiB6coeHeEweJyIylVS LO40DsH9LCq38cLMgROj2zNikmCbfBrefkvXHzMTvR6FXDOQgWhldffplvJWy8FiutXpo/welgE VAck1tV5oSd5KjINHLJmJupNoo4XXgIGUo1YCc3LxwAlws6gjm+liInFNCD4ILajuabve0UVju6 gqRwDmg/N30enwA== X-Developer-Key: i=jai.luthra@ideasonboard.com; a=openpgp; fpr=4DE0D818E5D575E8D45AAFC543DE91F9249A7145 The sensor datasheet reports actual total number of pixels as 2696x2044. This becomes important for supporting 2x2 binning modes that can go beyond the current maximum pixel array width set here. Signed-off-by: Jai Luthra Reviewed-by: Kieran Bingham --- drivers/media/i2c/imx335.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index 6369bdbd2b09ba1f89c143cdf6be061820f2d051..dbf2db4bf9cbfd792ff5865264c= 6f465eb79a43b 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -124,10 +124,10 @@ #define IMX335_NUM_DATA_LANES 4 =20 /* IMX335 native and active pixel array size. */ -#define IMX335_NATIVE_WIDTH 2616U -#define IMX335_NATIVE_HEIGHT 1964U -#define IMX335_PIXEL_ARRAY_LEFT 12U -#define IMX335_PIXEL_ARRAY_TOP 12U +#define IMX335_NATIVE_WIDTH 2696U +#define IMX335_NATIVE_HEIGHT 2044U +#define IMX335_PIXEL_ARRAY_LEFT 52U +#define IMX335_PIXEL_ARRAY_TOP 50U #define IMX335_PIXEL_ARRAY_WIDTH 2592U #define IMX335_PIXEL_ARRAY_HEIGHT 1944U =20 --=20 2.50.1 From nobody Tue Dec 16 03:23:38 2025 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E89D92EA149; Wed, 13 Aug 2025 07:21:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069688; cv=none; b=DGlzNR3bcK+3L39BCRZoXzXHmspOmHiDgjk4tyiX4w1BIC3mK3HCPMNFL0R8c4FXxIsaMUBlpiwJQVcvnKZB/I+K9xbUtOGrThl6xtJS5lDgZE5Y2h6Mkw+bjQuUfepOss/XG34JNWtqUiaWR+TOUPEJV9UEWyLRBh2H9Htk5Vs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069688; c=relaxed/simple; bh=z2tpeqsxhyoVQjGXPJFWvDTUNx8Ap3EwlbioBfoZZpc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cRzuZpSOPR/MR4LbhnrDSnqwiwGHORefwk9NGQ2svtUhfn5U//KPXeVzT+jJclZwwhNDQ1yWdcIFTOJ+8pNWzspqiZeFAsrvba65Q6ETsTF8AFL4gh4IwwjNUzzhS2N9RD8JZHKtwl1j0frlf0CeRQE54aUlabhm2EEFF8EDY/E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=WFuj2sPg; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WFuj2sPg" Received: from mail.ideasonboard.com (unknown [IPv6:2401:4900:1c66:bd1a:669e:3dcb:5a6b:a905]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 07946351; Wed, 13 Aug 2025 09:20:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1755069632; bh=z2tpeqsxhyoVQjGXPJFWvDTUNx8Ap3EwlbioBfoZZpc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=WFuj2sPgXjVoq9j7Tkgkdam4TS4LdJt/iHB5xf8dtm7nIqHpTvzL+5EGBW3OjGiN+ ixfnBy0jYYyW3Q6jva1Ette0/olgxNbVTlNBKFA6uhvaQqxdcoy8FqBtfD+g4OJWnx oHfVXAd09tS4uHVFKqk0CSAFkKyvYbpyFzfl8Be4= From: Jai Luthra Date: Wed, 13 Aug 2025 12:50:35 +0530 Subject: [PATCH 4/6] media: imx335: Update HBLANK range on mode change Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250813-imx335_binning-v1-4-a42b687d8541@ideasonboard.com> References: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> In-Reply-To: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> To: Kieran Bingham , Sakari Ailus , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Jai Luthra X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1103; i=jai.luthra@ideasonboard.com; h=from:subject:message-id; bh=z2tpeqsxhyoVQjGXPJFWvDTUNx8Ap3EwlbioBfoZZpc=; b=owEBbQKS/ZANAwAKAUPekfkkmnFFAcsmYgBonDzY91XLhzok2sxV8VpmN7XgPUmmvW9mpwKC+ mUll7FZlLmJAjMEAAEKAB0WIQRN4NgY5dV16NRar8VD3pH5JJpxRQUCaJw82AAKCRBD3pH5JJpx RXilEADCQUtgSyomtpkUPeCB1vTrbfEKgLJPjSwd5U4coNSseWyKX33w93lL4XAVX06/huifBj/ +gtbh8f8S27ORxItm/0Q0z+Wj3WPcdXV3zs9OiotOqeb5UrdGLW0pKAp8WMPMqGOHl42DcSIXt5 qwiGpq7xgS5zCVgW+XyHtlCe0FWBqW26vjKfQ3r0di071ElvWS7mWBdhXj9DKYAZmCUWlZLO3FN FgJSzdwg1SCWSfM6H2T+ZdDcn349FcT96U4jtlVvJ01uTp7MCVqBG+K6MX5d2UFco5JmSpAXHJv sQnt/CPPruec+Ps8ByiD/Bl0vnreWCSPDEBXdLnZRpcEKg3qh0cZVbSHy2Tr9Wmw8yJxX6wBtJ+ 58yFEuJ6QSaa2zoUls/ZelgaoWHBEYNIsWgYQOZz+OlpaDcT3b5wiUJqWJe7gSkzxZh9shtA+mX Yl9SGAHYLk385iLETsFSwTCROFR/aXvcQ5oiD8oLqX2e1QOCa7R7vdfYAkJBdqeEOyhZSfeivi6 7aY5Z10LK1ScuwTx391pau6tP32xJwax8UMKrwyi3F7r6sjkF6VaHU+1gleRfnmy7QCOqTJrtwX 951BQUZoB5SQH1uzSp+dEHLibJ09zQdYA7TpOvHVDnKxkM0wpNHrt3ydSRumKxxLI8fO4hbsEGD znnzwtX9xi6bMLA== X-Developer-Key: i=jai.luthra@ideasonboard.com; a=openpgp; fpr=4DE0D818E5D575E8D45AAFC543DE91F9249A7145 While switching modes, updating to a different value of HBLANK isn't sufficient, as this is a read-only control with a single allowed value, and thus hblank_min =3D=3D hblank_max =3D=3D hblank of the default mode. So to correctly update the user-facing value of the HBLANK parameter, which is necessary for correct framerate calculation, update the whole range when switching modes. Signed-off-by: Jai Luthra Reviewed-by: Kieran Bingham --- drivers/media/i2c/imx335.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index dbf2db4bf9cbfd792ff5865264c6f465eb79a43b..c61a6952f828fd8b945746ae2f5= 3f5517e98c410 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -485,7 +485,8 @@ static int imx335_update_controls(struct imx335 *imx335, if (ret) return ret; =20 - ret =3D __v4l2_ctrl_s_ctrl(imx335->hblank_ctrl, mode->hblank); + ret =3D __v4l2_ctrl_modify_range(imx335->hblank_ctrl, mode->hblank, + mode->hblank, 1, mode->hblank); if (ret) return ret; =20 --=20 2.50.1 From nobody Tue Dec 16 03:23:38 2025 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A7672D9EE8; Wed, 13 Aug 2025 07:21:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069693; cv=none; b=dbWCDSVICaMR8Ha8Lt9x87N/ogoTLJOeirOlhbM7as+qdCLxNTcCmywhWBMgnzV9iXFTj4ouQt7DsRZpYtMOU8Eno98FwRLtWiE241GsmuTkMuqXaOjQnbkG8GAIA0mJDFHczHsM4uwYTl3FnTiG19nW+bHy4YyeTKh1B9iw8qE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069693; c=relaxed/simple; bh=25p3Sz1t9kJMVh9fauiqODHhWdxO3rNOkRXGbOODn0c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=p0NZBGeGU5FlLoJcpcZ0CU135HWvt/kL78fyxsTvAZqEZ7Tm4Gwnco8NqCSqdob5zMGUg24TvwUGGrd2wWVkUyb5VU4M4bQzB9FC7or3s3sTyI0FtfrDx7qWJy/WGbDoF3qmwhVwvzKK7CywZ5O+K+cAbDeTAfv5vWBPKD+3myI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=vuxcFNhw; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="vuxcFNhw" Received: from mail.ideasonboard.com (unknown [IPv6:2401:4900:1c66:bd1a:669e:3dcb:5a6b:a905]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4CD01351; Wed, 13 Aug 2025 09:20:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1755069637; bh=25p3Sz1t9kJMVh9fauiqODHhWdxO3rNOkRXGbOODn0c=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=vuxcFNhws+NVSJTL6o83fcogO6wO2iPIQqN75YpnsxUzOwQvf89iDspPm8iS7bcGd 4eStqINb1jKdw/lk5whNsPegeREacRYmc++/FZ4Bs7gBMPl9AcVKl0Jcr4+daBRioZ AgdhGQKDIpS6ghOOBUkwKznLzDHtqHjsPrVxavZs= From: Jai Luthra Date: Wed, 13 Aug 2025 12:50:36 +0530 Subject: [PATCH 5/6] media: imx355: Use subdev active state Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250813-imx335_binning-v1-5-a42b687d8541@ideasonboard.com> References: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> In-Reply-To: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> To: Kieran Bingham , Sakari Ailus , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Jai Luthra X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=9723; i=jai.luthra@ideasonboard.com; h=from:subject:message-id; bh=25p3Sz1t9kJMVh9fauiqODHhWdxO3rNOkRXGbOODn0c=; b=owEBbQKS/ZANAwAKAUPekfkkmnFFAcsmYgBonDzZe20Sqo6U80N8uYqC7P3RJf3DO8/+xoUkR gz91lhw1eOJAjMEAAEKAB0WIQRN4NgY5dV16NRar8VD3pH5JJpxRQUCaJw82QAKCRBD3pH5JJpx RfzdD/92nC/CG3GqE80znfhwQECLhWSBRvulWYFJYN/vZiMY44YW5Ma1J18KtNbJtGwX2wa3kV3 RyN3P/+xGsQt1WuDjWe8fLHwjwMb/OxWxBp0JzuyebXwAReh9ZD6f4/aN55LbMQ0vGUPgp+9kmp r8LUcNtSPIVnowscWXPHR3H/pP1jDij9d2q4xtLhIIInHTWq5URxc7bR+DkefsJgmuRJhP//2vj 5Yj828rKQBK8Fo8Kr1ZgzWOEWe9xLOMNtLR998jCkPuogz61UiELA4Ao5RhQWqjKs8H4mOv/nPe PJMjAhZkeBuwxsWB0i9mL8xN2qECLTTV+0TQFUAQuTYtBughdYTf6vjnEL9wT7ilr9WIn+gIKQC gFhuHSmZG/eHCIjFw87/iqP0KJU/DVknuiKiZvRzZ8mQ+pHDelqksDDYIA8KsDRqhkh7veJlUvQ rBFYfseoGWTlnXr7r1yo+7xX9ZDccChQsUC+Eonw8zvRKM4yohvvPy6J4iIZ9AT00y34KH9rUXG DZ1gjbRICqPpuyWEUMD15nhQESPvvl8vBP1jESjcEX+N5HtOuM3IbxdCDX++kKmd55K7WdjJWQI TSNVoupZclrMmHzUYRcl+Pf1ABbzr/nc53WZKEP/KfspxUdy8ON9SFqSihxYOnMmZ+nyaRkWHU/ Htj7SZWNFnZ+eSw== X-Developer-Key: i=jai.luthra@ideasonboard.com; a=openpgp; fpr=4DE0D818E5D575E8D45AAFC543DE91F9249A7145 Port the driver to use the subdev active state. This simplifies locking, and makes it easier to support different crop sizes for binned modes, by storing the crop rectangle inside the subdev state. Signed-off-by: Jai Luthra --- drivers/media/i2c/imx335.c | 125 +++++++++++++++--------------------------= ---- 1 file changed, 41 insertions(+), 84 deletions(-) diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index c61a6952f828fd8b945746ae2f53f5517e98c410..df1535927f481de3a0d043ac9be= 24b9336ea8f7f 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -196,7 +196,6 @@ struct imx335_mode { * @vblank: Vertical blanking in lines * @lane_mode: Mode for number of connected data lanes * @cur_mode: Pointer to current selected sensor mode - * @mutex: Mutex for serializing sensor controls * @link_freq_bitmap: Menu bitmap for link_freq_ctrl * @cur_mbus_code: Currently selected media bus format code */ @@ -223,7 +222,6 @@ struct imx335 { u32 vblank; u32 lane_mode; const struct imx335_mode *cur_mode; - struct mutex mutex; unsigned long link_freq_bitmap; u32 cur_mbus_code; }; @@ -758,36 +756,6 @@ static void imx335_fill_pad_format(struct imx335 *imx3= 35, fmt->format.xfer_func =3D V4L2_XFER_FUNC_NONE; } =20 -/** - * imx335_get_pad_format() - Get subdevice pad format - * @sd: pointer to imx335 V4L2 sub-device structure - * @sd_state: V4L2 sub-device configuration - * @fmt: V4L2 sub-device format need to be set - * - * Return: 0 if successful, error code otherwise. - */ -static int imx335_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct imx335 *imx335 =3D to_imx335(sd); - - mutex_lock(&imx335->mutex); - - if (fmt->which =3D=3D V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_mbus_framefmt *framefmt; - - framefmt =3D v4l2_subdev_state_get_format(sd_state, fmt->pad); - fmt->format =3D *framefmt; - } else { - imx335_fill_pad_format(imx335, imx335->cur_mode, fmt); - } - - mutex_unlock(&imx335->mutex); - - return 0; -} - /** * imx335_set_pad_format() - Set subdevice pad format * @sd: pointer to imx335 V4L2 sub-device structure @@ -801,12 +769,12 @@ static int imx335_set_pad_format(struct v4l2_subdev *= sd, struct v4l2_subdev_format *fmt) { struct imx335 *imx335 =3D to_imx335(sd); + struct v4l2_mbus_framefmt *format; const struct imx335_mode *mode; int i, ret =3D 0; =20 - mutex_lock(&imx335->mutex); - mode =3D &supported_mode; + for (i =3D 0; i < ARRAY_SIZE(imx335_mbus_codes); i++) { if (imx335_mbus_codes[i] =3D=3D fmt->format.code) imx335->cur_mbus_code =3D imx335_mbus_codes[i]; @@ -814,19 +782,15 @@ static int imx335_set_pad_format(struct v4l2_subdev *= sd, =20 imx335_fill_pad_format(imx335, mode, fmt); =20 - if (fmt->which =3D=3D V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_mbus_framefmt *framefmt; + format =3D v4l2_subdev_state_get_format(sd_state, fmt->pad); + *format =3D fmt->format; =20 - framefmt =3D v4l2_subdev_state_get_format(sd_state, fmt->pad); - *framefmt =3D fmt->format; - } else { + if (fmt->which =3D=3D V4L2_SUBDEV_FORMAT_ACTIVE) { ret =3D imx335_update_controls(imx335, mode); if (!ret) imx335->cur_mode =3D mode; } =20 - mutex_unlock(&imx335->mutex); - return ret; } =20 @@ -846,12 +810,10 @@ static int imx335_init_state(struct v4l2_subdev *sd, fmt.which =3D sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTI= VE; imx335_fill_pad_format(imx335, &supported_mode, &fmt); =20 - mutex_lock(&imx335->mutex); __v4l2_ctrl_modify_range(imx335->link_freq_ctrl, 0, __fls(imx335->link_freq_bitmap), ~(imx335->link_freq_bitmap), __ffs(imx335->link_freq_bitmap)); - mutex_unlock(&imx335->mutex); =20 return imx335_set_pad_format(sd, sd_state, &fmt); } @@ -919,13 +881,17 @@ static int imx335_start_streaming(struct imx335 *imx3= 35) const struct imx335_reg_list *reg_list; int ret; =20 + ret =3D pm_runtime_resume_and_get(imx335->dev); + if (ret < 0) + return ret; + /* Setup PLL */ reg_list =3D &link_freq_reglist[__ffs(imx335->link_freq_bitmap)]; ret =3D cci_multi_reg_write(imx335->cci, reg_list->regs, reg_list->num_of_regs, NULL); if (ret) { dev_err(imx335->dev, "%s failed to set plls\n", __func__); - return ret; + goto err_rpm_put; } =20 /* Write sensor mode registers */ @@ -934,27 +900,27 @@ static int imx335_start_streaming(struct imx335 *imx3= 35) reg_list->num_of_regs, NULL); if (ret) { dev_err(imx335->dev, "fail to write initial registers\n"); - return ret; + goto err_rpm_put; } =20 ret =3D imx335_set_framefmt(imx335); if (ret) { dev_err(imx335->dev, "%s failed to set frame format: %d\n", __func__, ret); - return ret; + goto err_rpm_put; } =20 /* Configure lanes */ ret =3D cci_write(imx335->cci, IMX335_REG_LANEMODE, imx335->lane_mode, NULL); if (ret) - return ret; + goto err_rpm_put; =20 /* Setup handler will write actual exposure and gain */ ret =3D __v4l2_ctrl_handler_setup(imx335->sd.ctrl_handler); if (ret) { dev_err(imx335->dev, "fail to setup handler\n"); - return ret; + goto err_rpm_put; } =20 /* Start streaming */ @@ -962,25 +928,29 @@ static int imx335_start_streaming(struct imx335 *imx3= 35) IMX335_MODE_STREAMING, NULL); if (ret) { dev_err(imx335->dev, "fail to start streaming\n"); - return ret; + goto err_rpm_put; } =20 /* Initial regulator stabilization period */ usleep_range(18000, 20000); =20 return 0; + +err_rpm_put: + pm_runtime_put(imx335->dev); + + return ret; } =20 /** * imx335_stop_streaming() - Stop sensor stream * @imx335: pointer to imx335 device - * - * Return: 0 if successful, error code otherwise. */ -static int imx335_stop_streaming(struct imx335 *imx335) +static void imx335_stop_streaming(struct imx335 *imx335) { - return cci_write(imx335->cci, IMX335_REG_MODE_SELECT, - IMX335_MODE_STANDBY, NULL); + cci_write(imx335->cci, IMX335_REG_MODE_SELECT, + IMX335_MODE_STANDBY, NULL); + pm_runtime_put(imx335->dev); } =20 /** @@ -993,31 +963,18 @@ static int imx335_stop_streaming(struct imx335 *imx33= 5) static int imx335_set_stream(struct v4l2_subdev *sd, int enable) { struct imx335 *imx335 =3D to_imx335(sd); - int ret; + struct v4l2_subdev_state *state; + int ret =3D 0; =20 - mutex_lock(&imx335->mutex); + state =3D v4l2_subdev_lock_and_get_active_state(sd); =20 if (enable) { - ret =3D pm_runtime_resume_and_get(imx335->dev); - if (ret) - goto error_unlock; - ret =3D imx335_start_streaming(imx335); - if (ret) - goto error_power_off; } else { imx335_stop_streaming(imx335); - pm_runtime_put(imx335->dev); } =20 - mutex_unlock(&imx335->mutex); - - return 0; - -error_power_off: - pm_runtime_put(imx335->dev); -error_unlock: - mutex_unlock(&imx335->mutex); + v4l2_subdev_unlock_state(state); =20 return ret; } @@ -1146,7 +1103,7 @@ static const struct v4l2_subdev_pad_ops imx335_pad_op= s =3D { .enum_frame_size =3D imx335_enum_frame_size, .get_selection =3D imx335_get_selection, .set_selection =3D imx335_get_selection, - .get_fmt =3D imx335_get_pad_format, + .get_fmt =3D v4l2_subdev_get_fmt, .set_fmt =3D imx335_set_pad_format, }; =20 @@ -1241,9 +1198,6 @@ static int imx335_init_controls(struct imx335 *imx335) if (ret) return ret; =20 - /* Serialize controls with sensor device */ - ctrl_hdlr->lock =3D &imx335->mutex; - /* Initialize exposure and gain */ lpfr =3D mode->vblank + mode->height; imx335->exp_ctrl =3D v4l2_ctrl_new_std(ctrl_hdlr, @@ -1363,12 +1317,10 @@ static int imx335_probe(struct i2c_client *client) return ret; } =20 - mutex_init(&imx335->mutex); - ret =3D imx335_power_on(imx335->dev); if (ret) { dev_err(imx335->dev, "failed to power-on the sensor\n"); - goto error_mutex_destroy; + return ret; } =20 /* Check module identity */ @@ -1401,11 +1353,18 @@ static int imx335_probe(struct i2c_client *client) goto error_handler_free; } =20 + imx335->sd.state_lock =3D imx335->ctrl_handler.lock; + ret =3D v4l2_subdev_init_finalize(&imx335->sd); + if (ret < 0) { + dev_err(imx335->dev, "subdev init error\n"); + goto error_media_entity; + } + ret =3D v4l2_async_register_subdev_sensor(&imx335->sd); if (ret < 0) { dev_err(imx335->dev, "failed to register async subdev: %d\n", ret); - goto error_media_entity; + goto error_subdev_cleanup; } =20 pm_runtime_set_active(imx335->dev); @@ -1414,14 +1373,14 @@ static int imx335_probe(struct i2c_client *client) =20 return 0; =20 +error_subdev_cleanup: + v4l2_subdev_cleanup(&imx335->sd); error_media_entity: media_entity_cleanup(&imx335->sd.entity); error_handler_free: v4l2_ctrl_handler_free(imx335->sd.ctrl_handler); error_power_off: imx335_power_off(imx335->dev); -error_mutex_destroy: - mutex_destroy(&imx335->mutex); =20 return ret; } @@ -1435,9 +1394,9 @@ static int imx335_probe(struct i2c_client *client) static void imx335_remove(struct i2c_client *client) { struct v4l2_subdev *sd =3D i2c_get_clientdata(client); - struct imx335 *imx335 =3D to_imx335(sd); =20 v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); =20 @@ -1445,8 +1404,6 @@ static void imx335_remove(struct i2c_client *client) if (!pm_runtime_status_suspended(&client->dev)) imx335_power_off(&client->dev); pm_runtime_set_suspended(&client->dev); - - mutex_destroy(&imx335->mutex); } =20 static const struct dev_pm_ops imx335_pm_ops =3D { --=20 2.50.1 From nobody Tue Dec 16 03:23:38 2025 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9CBD42ECD1C; Wed, 13 Aug 2025 07:21:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069698; cv=none; b=g7yFh4wcjUigdk5vqNI6F/wMiYfg2i2jU1lKxwGWKw9AG8H1T3h1opqn2epn75omAj6qzfhT3jvhA7sdWRuwj8wJghYwky+DAJnE3oRq5J06sbL9ESN5Ku7hOKf6onNFpOjl5yzN8fr25dj72CKNuBMDwhlN++pWIN9K/Win42k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755069698; c=relaxed/simple; bh=M8va7BW6+IPfpHvpZxz9KvDHzlVb3pCGLbaCr7MlVGk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=V3QrWoz//wAhqpYbqDRkv8LcgPgzm/s/oS4IL0QHxa4dzuYzGUKGsWx3Ck9coAEreHKc1UmjXLe4GlVntdhrk9O0mIX85otxjXvZkOXGLgBnr+djDi5JsjwiPFCagXk16B+6Srz3p79y7rXzqgZ8AdVqBeyD3b3lbC82yZm7EaA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=qr3nF6sp; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="qr3nF6sp" Received: from mail.ideasonboard.com (unknown [IPv6:2401:4900:1c66:bd1a:669e:3dcb:5a6b:a905]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id EA716351; Wed, 13 Aug 2025 09:20:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1755069642; bh=M8va7BW6+IPfpHvpZxz9KvDHzlVb3pCGLbaCr7MlVGk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qr3nF6spKNv2Y7NRMu9qMYqZmJpLg9q22lkLZj7vnq3rkqjfbP9/LQDoiL/hdOelG RlFWniWlXbU56KS/1hWkU+Isd2GqMbGLU5VnIDQLZWfK3hxuCyRpc5tsoQwJK0bZFR a6Bx5F93SLlZXOqZNL4zyM44a4qYbvr72UCGaxpk= From: Jai Luthra Date: Wed, 13 Aug 2025 12:50:37 +0530 Subject: [PATCH 6/6] media: imx335: Support 2x2 binning Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250813-imx335_binning-v1-6-a42b687d8541@ideasonboard.com> References: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> In-Reply-To: <20250813-imx335_binning-v1-0-a42b687d8541@ideasonboard.com> To: Kieran Bingham , Sakari Ailus , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Jai Luthra X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=15739; i=jai.luthra@ideasonboard.com; h=from:subject:message-id; bh=M8va7BW6+IPfpHvpZxz9KvDHzlVb3pCGLbaCr7MlVGk=; b=owEBbQKS/ZANAwAKAUPekfkkmnFFAcsmYgBonDza+4jyAA84fInaKDxX+ZjHgYrefRkN/HLcU YKfRz7OvRGJAjMEAAEKAB0WIQRN4NgY5dV16NRar8VD3pH5JJpxRQUCaJw82gAKCRBD3pH5JJpx RQsAD/wMq5HNgeoDC3630SyW7JPWjcOjdXjM1BBF8ShBJhjYt3tOYEOHxyiifW0Epf9pWmHO8bO 1RopcKb/JUtTGuk4TypetmmB1sMSdG/3vL4YIVGlVu65VJzav6vvX1CwWVKVNcz6S13rBBOWWzf /Ok/Gm06u7AFTekwkHbls+NqKh8NjSkfXe2EZoGI6/gssA9QtNB0exwZER6M4zrgcCBoHMR5Q3h 2zNOK1b4CV4kWcUtlUblmbF1c6FIalyi9ellctEaYqYZU3gisHBdTTtV6RGe3J43MplqUj5jRzh txsUpoKF7PUlnrj70l4+ME+/MjlmQvQByPGE7OAYDW9/H3VXpMslYpEJJI4ElkPrj40OrbBhwcK ct4bPCsjLgV8lsW06xQdgVOmCve6etZ7UZ9Jrf1q47I2Jt3RLSd2XCr4jEMWm92IX+zv3xdbIWF kGhvQjrZdUHl2JEUkpLXN+ZOQ3nMxNMtdC6rV7xwLGPVwJt25lmFafkdjietIJVMcS7S+6NZVib co4JAwnS0d645aO0t//sIiYkU5Sn/JhQmSh3SL9rRuAsd5ThJaFODmD8UqO/CTZcSqvSd9vmXxD Vnl/g32Wb9g8/rcsTHZ59eMeYXHfE8Kj4XAxhvyFl73t3FlajL4EwOIos7+F9P7d9mxE6EVH6DQ BqDfxTnJcJluydg== X-Developer-Key: i=jai.luthra@ideasonboard.com; a=openpgp; fpr=4DE0D818E5D575E8D45AAFC543DE91F9249A7145 Introduce 2x2 binning mode (1312x972@60fps). Since there are multiple modes now, use v4l2_find_nearest_size() to select the appropriate mode in .set_fmt(). For 2x2 binning the minimum shutter value supported is 17 instead of 9. This effects the maximum allowed exposure time, and if not enforced then the sensor produces very dark frames when the minimum shutter limit is violated. Lastly, update the crop size reported to the userspace. When trying 2x2 binning with the datasheet suggested pixel array size (i.e. 2592 / 2 =3D> 1296), on some platforms (Raspberry Pi 5) artefacts are introduced on the right edge of the output image. Instead, using a higher width of 1312 works fine on all platforms. Signed-off-by: Jai Luthra --- drivers/media/i2c/imx335.c | 274 +++++++++++++++++++++++++++++++++++------= ---- 1 file changed, 217 insertions(+), 57 deletions(-) diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index df1535927f481de3a0d043ac9be24b9336ea8f7f..24d26bc6260bf60ca73df81fe39= 8121ac9371b42 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -35,6 +35,7 @@ =20 /* Lines per frame */ #define IMX335_REG_VMAX CCI_REG24_LE(0x3030) +#define IMX335_REG_HMAX CCI_REG16_LE(0x3034) =20 #define IMX335_REG_OPB_SIZE_V CCI_REG8(0x304c) #define IMX335_REG_ADBIT CCI_REG8(0x3050) @@ -42,10 +43,13 @@ =20 #define IMX335_REG_SHUTTER CCI_REG24_LE(0x3058) #define IMX335_EXPOSURE_MIN 1 -#define IMX335_EXPOSURE_OFFSET 9 +#define IMX335_SHUTTER_MIN 9 +#define IMX335_SHUTTER_MIN_BINNED 17 #define IMX335_EXPOSURE_STEP 1 #define IMX335_EXPOSURE_DEFAULT 0x0648 =20 +#define IMX335_REG_AREA2_WIDTH_1 CCI_REG16_LE(0x3072) + #define IMX335_REG_AREA3_ST_ADR_1 CCI_REG16_LE(0x3074) #define IMX335_REG_AREA3_WIDTH_1 CCI_REG16_LE(0x3076) =20 @@ -126,9 +130,9 @@ /* IMX335 native and active pixel array size. */ #define IMX335_NATIVE_WIDTH 2696U #define IMX335_NATIVE_HEIGHT 2044U -#define IMX335_PIXEL_ARRAY_LEFT 52U +#define IMX335_PIXEL_ARRAY_LEFT 36U #define IMX335_PIXEL_ARRAY_TOP 50U -#define IMX335_PIXEL_ARRAY_WIDTH 2592U +#define IMX335_PIXEL_ARRAY_WIDTH 2624U #define IMX335_PIXEL_ARRAY_HEIGHT 1944U =20 /** @@ -147,8 +151,14 @@ static const char * const imx335_supply_name[] =3D { "dvdd", /* Digital Core (1.2V) supply */ }; =20 +enum imx335_scan_mode { + IMX335_ALL_PIXEL, + IMX335_2_2_BINNING, +}; + /** * struct imx335_mode - imx335 sensor mode structure + * @scan_mode: Configuration scan mode (All pixel / 2x2Binning) * @width: Frame width * @height: Frame height * @code: Format code @@ -162,6 +172,7 @@ static const char * const imx335_supply_name[] =3D { * @vflip_inverted: Register list vflip (inverted readout) */ struct imx335_mode { + enum imx335_scan_mode scan_mode; u32 width; u32 height; u32 code; @@ -263,12 +274,33 @@ static const struct cci_reg_sequence mode_2592x1944_r= egs[] =3D { { IMX335_REG_MODE_SELECT, IMX335_MODE_STANDBY }, { IMX335_REG_MASTER_MODE, 0x00 }, { IMX335_REG_WINMODE, 0x04 }, + { IMX335_REG_HMAX, 550 }, { IMX335_REG_HTRIMMING_START, 48 }, { IMX335_REG_HNUM, 2592 }, { IMX335_REG_Y_OUT_SIZE, 1944 }, + { IMX335_REG_AREA2_WIDTH_1, 40 }, { IMX335_REG_AREA3_WIDTH_1, 3928 }, { IMX335_REG_OPB_SIZE_V, 0 }, { IMX335_REG_XVS_XHS_DRV, 0x00 }, +}; + +static const struct cci_reg_sequence mode_1312x972_regs[] =3D { + { IMX335_REG_MODE_SELECT, IMX335_MODE_STANDBY }, + { IMX335_REG_MASTER_MODE, 0x00 }, + { IMX335_REG_WINMODE, 0x01 }, + { IMX335_REG_HMAX, 275 }, + { IMX335_REG_HTRIMMING_START, 48 }, + { IMX335_REG_HNUM, 2600 }, + { IMX335_REG_Y_OUT_SIZE, 972 }, + { IMX335_REG_AREA2_WIDTH_1, 48 }, + { IMX335_REG_AREA3_WIDTH_1, 3936 }, + { IMX335_REG_OPB_SIZE_V, 0 }, + { IMX335_REG_XVS_XHS_DRV, 0x00 }, + { CCI_REG8(0x3300), 1 }, /* TCYCLE */ + { CCI_REG8(0x3199), 0x30 }, /* HADD/VADD */ +}; + +static const struct cci_reg_sequence imx335_common_regs[] =3D { { CCI_REG8(0x3288), 0x21 }, { CCI_REG8(0x328a), 0x02 }, { CCI_REG8(0x3414), 0x05 }, @@ -359,16 +391,72 @@ static const struct cci_reg_sequence mode_2592x1944_v= flip_inverted[] =3D { { CCI_REG16_LE(0x3116), 0x002 }, }; =20 -static const struct cci_reg_sequence raw10_framefmt_regs[] =3D { - { IMX335_REG_ADBIT, 0x00 }, - { IMX335_REG_MDBIT, 0x00 }, - { IMX335_REG_ADBIT1, 0x1ff }, +static const struct cci_reg_sequence mode_1312x972_vflip_normal[] =3D { + { IMX335_REG_AREA3_ST_ADR_1, 176 }, + + /* Undocumented */ + { CCI_REG8(0x3078), 0x04 }, + { CCI_REG8(0x3079), 0xfd }, + { CCI_REG8(0x307a), 0x04 }, + { CCI_REG8(0x307b), 0xfe }, + { CCI_REG8(0x307c), 0x04 }, + { CCI_REG8(0x307d), 0xfb }, + { CCI_REG8(0x307e), 0x04 }, + { CCI_REG8(0x307f), 0x02 }, + { CCI_REG8(0x3080), 0x04, }, + { CCI_REG8(0x3081), 0xfd, }, + { CCI_REG8(0x3082), 0x04, }, + { CCI_REG8(0x3083), 0xfe, }, + { CCI_REG8(0x3084), 0x04, }, + { CCI_REG8(0x3085), 0xfb, }, + { CCI_REG8(0x3086), 0x04, }, + { CCI_REG8(0x3087), 0x02, }, + { CCI_REG8(0x30a4), 0x77, }, + { CCI_REG8(0x30a8), 0x20, }, + { CCI_REG8(0x30a9), 0x00, }, + { CCI_REG8(0x30ac), 0x08, }, + { CCI_REG8(0x30ad), 0x08, }, + { CCI_REG8(0x30b0), 0x20, }, + { CCI_REG8(0x30b1), 0x00, }, + { CCI_REG8(0x30b4), 0x10, }, + { CCI_REG8(0x30b5), 0x10, }, + { CCI_REG16_LE(0x30b6), 0x00 }, + { CCI_REG16_LE(0x3112), 0x10 }, + { CCI_REG16_LE(0x3116), 0x10 }, }; =20 -static const struct cci_reg_sequence raw12_framefmt_regs[] =3D { - { IMX335_REG_ADBIT, 0x01 }, - { IMX335_REG_MDBIT, 0x01 }, - { IMX335_REG_ADBIT1, 0x47 }, +static const struct cci_reg_sequence mode_1312x972_vflip_inverted[] =3D { + { IMX335_REG_AREA3_ST_ADR_1, 4112 }, + + /* Undocumented */ + { CCI_REG8(0x3078), 0x04 }, + { CCI_REG8(0x3079), 0xfd }, + { CCI_REG8(0x307a), 0x04 }, + { CCI_REG8(0x307b), 0xfe }, + { CCI_REG8(0x307c), 0x04 }, + { CCI_REG8(0x307d), 0xfb }, + { CCI_REG8(0x307e), 0x04 }, + { CCI_REG8(0x307f), 0x02 }, + { CCI_REG8(0x3080), 0xfc, }, + { CCI_REG8(0x3081), 0x05, }, + { CCI_REG8(0x3082), 0xfc, }, + { CCI_REG8(0x3083), 0x02, }, + { CCI_REG8(0x3084), 0xfc, }, + { CCI_REG8(0x3085), 0x03, }, + { CCI_REG8(0x3086), 0xfc, }, + { CCI_REG8(0x3087), 0xfe, }, + { CCI_REG8(0x30a4), 0x77, }, + { CCI_REG8(0x30a8), 0x20, }, + { CCI_REG8(0x30a9), 0x00, }, + { CCI_REG8(0x30ac), 0x08, }, + { CCI_REG8(0x30ad), 0x78, }, + { CCI_REG8(0x30b0), 0x20, }, + { CCI_REG8(0x30b1), 0x00, }, + { CCI_REG8(0x30b4), 0x10, }, + { CCI_REG8(0x30b5), 0x70, }, + { CCI_REG16_LE(0x30b6), 0x01f2 }, + { CCI_REG16_LE(0x3112), 0x10 }, + { CCI_REG16_LE(0x3116), 0x02 }, }; =20 static const struct cci_reg_sequence mipi_data_rate_1188Mbps[] =3D { @@ -433,25 +521,49 @@ static const u32 imx335_mbus_codes[] =3D { }; =20 /* Supported sensor mode configurations */ -static const struct imx335_mode supported_mode =3D { - .width =3D 2592, - .height =3D 1944, - .hblank =3D 342, - .vblank =3D 2556, - .vblank_min =3D 2556, - .vblank_max =3D 133060, - .pclk =3D 396000000, - .reg_list =3D { - .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_regs), - .regs =3D mode_2592x1944_regs, - }, - .vflip_normal =3D { - .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_vflip_normal), - .regs =3D mode_2592x1944_vflip_normal, - }, - .vflip_inverted =3D { - .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_vflip_inverted), - .regs =3D mode_2592x1944_vflip_inverted, +static const struct imx335_mode supported_modes[] =3D { + { + .scan_mode =3D IMX335_ALL_PIXEL, + .width =3D 2592, + .height =3D 1944, + .hblank =3D 342, + .vblank =3D 2556, + .vblank_min =3D 2556, + .vblank_max =3D 133060, + .pclk =3D 396000000, + .reg_list =3D { + .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_regs), + .regs =3D mode_2592x1944_regs, + }, + .vflip_normal =3D { + .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_vflip_normal), + .regs =3D mode_2592x1944_vflip_normal, + }, + .vflip_inverted =3D { + .num_of_regs =3D ARRAY_SIZE(mode_2592x1944_vflip_inverted), + .regs =3D mode_2592x1944_vflip_inverted, + } + }, { + .scan_mode =3D IMX335_2_2_BINNING, + .width =3D 1312, + .height =3D 972, + .hblank =3D 155, + .vblank =3D 3528, + .vblank_min =3D 3528, + .vblank_max =3D 133060, + .pclk =3D 396000000, + .reg_list =3D { + .num_of_regs =3D ARRAY_SIZE(mode_1312x972_regs), + .regs =3D mode_1312x972_regs, + }, + .vflip_normal =3D { + .num_of_regs =3D ARRAY_SIZE(mode_1312x972_vflip_normal), + .regs =3D mode_1312x972_vflip_normal, + }, + .vflip_inverted =3D { + .num_of_regs =3D ARRAY_SIZE(mode_1312x972_vflip_inverted), + .regs =3D mode_1312x972_vflip_inverted, + }, }, }; =20 @@ -608,18 +720,22 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) =20 /* Propagate change of current control to all related controls */ if (ctrl->id =3D=3D V4L2_CID_VBLANK) { + u32 shutter_min =3D IMX335_SHUTTER_MIN; + u32 lpfr; + imx335->vblank =3D imx335->vblank_ctrl->val; + lpfr =3D imx335->vblank + imx335->cur_mode->height; =20 dev_dbg(imx335->dev, "Received vblank %u, new lpfr %u\n", - imx335->vblank, - imx335->vblank + imx335->cur_mode->height); + imx335->vblank, lpfr); + + if (imx335->cur_mode->scan_mode =3D=3D IMX335_2_2_BINNING) + shutter_min =3D IMX335_SHUTTER_MIN_BINNED; =20 ret =3D __v4l2_ctrl_modify_range(imx335->exp_ctrl, IMX335_EXPOSURE_MIN, - imx335->vblank + - imx335->cur_mode->height - - IMX335_EXPOSURE_OFFSET, - 1, IMX335_EXPOSURE_DEFAULT); + lpfr - shutter_min, 1, + IMX335_EXPOSURE_DEFAULT); if (ret) return ret; } @@ -719,17 +835,16 @@ static int imx335_enum_frame_size(struct v4l2_subdev = *sd, struct imx335 *imx335 =3D to_imx335(sd); u32 code; =20 - /* Only a single supported_mode available. */ - if (fsize->index > 0) + if (fsize->index >=3D ARRAY_SIZE(supported_modes)) return -EINVAL; =20 code =3D imx335_get_format_code(imx335, fsize->code); if (fsize->code !=3D code) return -EINVAL; =20 - fsize->min_width =3D supported_mode.width; + fsize->min_width =3D supported_modes[fsize->index].width; fsize->max_width =3D fsize->min_width; - fsize->min_height =3D supported_mode.height; + fsize->min_height =3D supported_modes[fsize->index].height; fsize->max_height =3D fsize->min_height; =20 return 0; @@ -771,9 +886,13 @@ static int imx335_set_pad_format(struct v4l2_subdev *s= d, struct imx335 *imx335 =3D to_imx335(sd); struct v4l2_mbus_framefmt *format; const struct imx335_mode *mode; + struct v4l2_rect *crop; int i, ret =3D 0; =20 - mode =3D &supported_mode; + mode =3D v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), + width, height, + fmt->format.width, fmt->format.height); =20 for (i =3D 0; i < ARRAY_SIZE(imx335_mbus_codes); i++) { if (imx335_mbus_codes[i] =3D=3D fmt->format.code) @@ -785,6 +904,16 @@ static int imx335_set_pad_format(struct v4l2_subdev *s= d, format =3D v4l2_subdev_state_get_format(sd_state, fmt->pad); *format =3D fmt->format; =20 + crop =3D v4l2_subdev_state_get_crop(sd_state, fmt->pad); + crop->width =3D fmt->format.width; + crop->height =3D fmt->format.height; + if (mode->scan_mode =3D=3D IMX335_2_2_BINNING) { + crop->width *=3D 2; + crop->height *=3D 2; + } + crop->left =3D (IMX335_NATIVE_WIDTH - crop->width) / 2; + crop->top =3D (IMX335_NATIVE_HEIGHT - crop->height) / 2; + if (fmt->which =3D=3D V4L2_SUBDEV_FORMAT_ACTIVE) { ret =3D imx335_update_controls(imx335, mode); if (!ret) @@ -808,7 +937,7 @@ static int imx335_init_state(struct v4l2_subdev *sd, struct v4l2_subdev_format fmt =3D { 0 }; =20 fmt.which =3D sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTI= VE; - imx335_fill_pad_format(imx335, &supported_mode, &fmt); + imx335_fill_pad_format(imx335, &supported_modes[0], &fmt); =20 __v4l2_ctrl_modify_range(imx335->link_freq_ctrl, 0, __fls(imx335->link_freq_bitmap), @@ -831,6 +960,11 @@ static int imx335_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_selection *sel) { switch (sel->target) { + case V4L2_SEL_TGT_CROP: + sel->r =3D *v4l2_subdev_state_get_crop(sd_state, 0); + + return 0; + case V4L2_SEL_TGT_NATIVE_SIZE: sel->r.top =3D 0; sel->r.left =3D 0; @@ -839,7 +973,6 @@ static int imx335_get_selection(struct v4l2_subdev *sd, =20 return 0; =20 - case V4L2_SEL_TGT_CROP: case V4L2_SEL_TGT_CROP_DEFAULT: case V4L2_SEL_TGT_CROP_BOUNDS: sel->r.top =3D IMX335_PIXEL_ARRAY_TOP; @@ -855,19 +988,35 @@ static int imx335_get_selection(struct v4l2_subdev *s= d, =20 static int imx335_set_framefmt(struct imx335 *imx335) { - switch (imx335->cur_mbus_code) { - case MEDIA_BUS_FMT_SRGGB10_1X10: - return cci_multi_reg_write(imx335->cci, raw10_framefmt_regs, - ARRAY_SIZE(raw10_framefmt_regs), - NULL); - - case MEDIA_BUS_FMT_SRGGB12_1X12: - return cci_multi_reg_write(imx335->cci, raw12_framefmt_regs, - ARRAY_SIZE(raw12_framefmt_regs), - NULL); + /* + * In the all-pixel scan mode the AD conversion shall match the output + * bit width requested. + * + * However, when 2/2 binning is enabled, the AD conversion is always + * 10-bit, so we ensure ADBIT is clear and ADBIT1 is assigned 0x1ff. + * That's as much as the documentation gives us... + */ + int ret =3D 0; + u8 bpp =3D imx335->cur_mbus_code =3D=3D MEDIA_BUS_FMT_SRGGB10_1X10 ? 10 := 12; + u8 ad_conv =3D bpp; + + /* Start with the output mode */ + cci_write(imx335->cci, IMX335_REG_MDBIT, bpp =3D=3D 12, &ret); + + /* Enforce 10 bit AD on binning modes */ + if (imx335->cur_mode->scan_mode =3D=3D IMX335_2_2_BINNING) + ad_conv =3D 10; + + /* AD Conversion configuration */ + if (ad_conv =3D=3D 10) { + cci_write(imx335->cci, IMX335_REG_ADBIT, 0x00, &ret); + cci_write(imx335->cci, IMX335_REG_ADBIT1, 0x1ff, &ret); + } else { /* 12 bit AD Conversion */ + cci_write(imx335->cci, IMX335_REG_ADBIT, 0x01, &ret); + cci_write(imx335->cci, IMX335_REG_ADBIT1, 0x47, &ret); } =20 - return -EINVAL; + return ret; } =20 /** @@ -903,6 +1052,14 @@ static int imx335_start_streaming(struct imx335 *imx3= 35) goto err_rpm_put; } =20 + /* Write sensor common registers */ + ret =3D cci_multi_reg_write(imx335->cci, imx335_common_regs, + ARRAY_SIZE(imx335_common_regs), NULL); + if (ret) { + dev_err(imx335->dev, "fail to write initial registers\n"); + goto err_rpm_put; + } + ret =3D imx335_set_framefmt(imx335); if (ret) { dev_err(imx335->dev, "%s failed to set frame format: %d\n", @@ -1186,7 +1343,7 @@ static int imx335_init_controls(struct imx335 *imx335) struct v4l2_ctrl_handler *ctrl_hdlr =3D &imx335->ctrl_handler; const struct imx335_mode *mode =3D imx335->cur_mode; struct v4l2_fwnode_device_properties props; - u32 lpfr; + u32 lpfr, shutter_min; int ret; =20 ret =3D v4l2_fwnode_device_parse(imx335->dev, &props); @@ -1200,11 +1357,14 @@ static int imx335_init_controls(struct imx335 *imx3= 35) =20 /* Initialize exposure and gain */ lpfr =3D mode->vblank + mode->height; + shutter_min =3D IMX335_SHUTTER_MIN; + if (mode->scan_mode =3D=3D IMX335_2_2_BINNING) + shutter_min =3D IMX335_SHUTTER_MIN_BINNED; imx335->exp_ctrl =3D v4l2_ctrl_new_std(ctrl_hdlr, &imx335_ctrl_ops, V4L2_CID_EXPOSURE, IMX335_EXPOSURE_MIN, - lpfr - IMX335_EXPOSURE_OFFSET, + lpfr - shutter_min, IMX335_EXPOSURE_STEP, IMX335_EXPOSURE_DEFAULT); =20 @@ -1331,7 +1491,7 @@ static int imx335_probe(struct i2c_client *client) } =20 /* Set default mode to max resolution */ - imx335->cur_mode =3D &supported_mode; + imx335->cur_mode =3D &supported_modes[0]; imx335->cur_mbus_code =3D imx335_mbus_codes[0]; imx335->vblank =3D imx335->cur_mode->vblank; =20 --=20 2.50.1