Message ID | 20231101122354.270453-2-alexander.stein@ew.tq-group.com (mailing list archive) |
---|---|
State | Superseded |
Headers |
Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from <linux-media-owner@vger.kernel.org>) id 1qyAGZ-00DKKV-Fy; Wed, 01 Nov 2023 12:24:15 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235184AbjKAMYL (ORCPT <rfc822;mkrufky@linuxtv.org> + 1 other); Wed, 1 Nov 2023 08:24:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33356 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235152AbjKAMYJ (ORCPT <rfc822;linux-media@vger.kernel.org>); Wed, 1 Nov 2023 08:24:09 -0400 Received: from mx1.tq-group.com (mx1.tq-group.com [93.104.207.81]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F484118; Wed, 1 Nov 2023 05:24:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tq-group.com; i=@tq-group.com; q=dns/txt; s=key1; t=1698841443; x=1730377443; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=sVoB2nzVS4xYYI7xHmLVJKrUYX9Yfj+tSQTlepogGXM=; b=RRjAWXdOha0cF81aAfqgZup0VTzplZMYKtcBo3+DoxcOYy6EH3IhoTGo 3SxRhrCXAxbBpG34Gxf0kjMu6t3jc+ZA6AJ6A7Wxy3nPhZb9M5mB8Y5q7 wAvnvM1976OezdJCapTi3JcupHOR3ig1R/jquTO8U/jiUVzJ6nObe5ovh XjxOssYCEDSingU8ylLXnPSAQfGOIJnPGufjnDkscw76zUY/Cbgvq0JAW Tziw4E+5QnebvMe1TbOrMuhTYJ0wYuhhMqHL3JSKteMsTwe0G4h1SvJI1 Tp1PXPCHNmMY3m1/vqiWH4ue7zQkUXuZZ1jDHmVTn/hFjeRLpFkJsQl41 Q==; X-IronPort-AV: E=Sophos;i="6.03,268,1694728800"; d="scan'208";a="33759524" Received: from vtuxmail01.tq-net.de ([10.115.0.20]) by mx1.tq-group.com with ESMTP; 01 Nov 2023 13:23:56 +0100 Received: from steina-w.tq-net.de (steina-w.tq-net.de [10.123.53.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by vtuxmail01.tq-net.de (Postfix) with ESMTPSA id A8C51280084; Wed, 1 Nov 2023 13:23:56 +0100 (CET) From: Alexander Stein <alexander.stein@ew.tq-group.com> To: Mauro Carvalho Chehab <mchehab@kernel.org>, Sakari Ailus <sakari.ailus@linux.intel.com>, Manivannan Sadhasivam <mani@kernel.org>, Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Hans de Goede <hdegoede@redhat.com> Cc: Alexander Stein <alexander.stein@ew.tq-group.com>, linux-media@vger.kernel.org, Alain Volmat <alain.volmat@foss.st.com>, stable@vger.kernel.org Subject: [PATCH v2 1/2] media: v4l2-cci: Add support for little-endian encoded registers Date: Wed, 1 Nov 2023 13:23:53 +0100 Message-Id: <20231101122354.270453-2-alexander.stein@ew.tq-group.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231101122354.270453-1-alexander.stein@ew.tq-group.com> References: <20231101122354.270453-1-alexander.stein@ew.tq-group.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-media.vger.kernel.org> X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -4.7 (----) X-LSpam-Report: No, score=-4.7 required=5.0 tests=BAYES_00=-1.9,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1,RCVD_IN_DNSWL_MED=-2.3 autolearn=ham autolearn_force=no |
Series |
v4l2-cci: little-endian registers
|
|
Commit Message
Alexander Stein
Nov. 1, 2023, 12:23 p.m. UTC
Some sensors, e.g. Sony, are using little-endian registers. Add support for
those by encoding the endianess into Bit 20 of the register address.
Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access helpers")
Cc: stable@vger.kernel.org
Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
---
drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------
include/media/v4l2-cci.h | 5 ++++
2 files changed, 41 insertions(+), 8 deletions(-)
Comments
Hi Alexander, Thank you for the patch. On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: > Some sensors, e.g. Sony, are using little-endian registers. Add support for I would write Sony IMX290 here, as there are Sony sensors that use big endian. > those by encoding the endianess into Bit 20 of the register address. > > Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access helpers") > Cc: stable@vger.kernel.org > Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> > --- > drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ > include/media/v4l2-cci.h | 5 ++++ > 2 files changed, 41 insertions(+), 8 deletions(-) > > diff --git a/drivers/media/v4l2-core/v4l2-cci.c b/drivers/media/v4l2-core/v4l2-cci.c > index bc2dbec019b04..673637b67bf67 100644 > --- a/drivers/media/v4l2-core/v4l2-cci.c > +++ b/drivers/media/v4l2-core/v4l2-cci.c > @@ -18,6 +18,7 @@ > > int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > { > + bool little_endian; > unsigned int len; > u8 buf[8]; > int ret; > @@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > if (err && *err) > return *err; > > + little_endian = reg & CCI_REG_LE; You could initialize the variable when declaring it. Same below. > len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); > reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); > > @@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > *val = buf[0]; > break; > case 2: > - *val = get_unaligned_be16(buf); > + if (little_endian) > + *val = get_unaligned_le16(buf); > + else > + *val = get_unaligned_be16(buf); Unrelated to this patch, isn't buf aligned to a 4 bytes boundary ? > break; > case 3: > - *val = get_unaligned_be24(buf); > + if (little_endian) > + *val = get_unaligned_le24(buf); > + else > + *val = get_unaligned_be24(buf); > break; > case 4: > - *val = get_unaligned_be32(buf); > + if (little_endian) > + *val = get_unaligned_le32(buf); > + else > + *val = get_unaligned_be32(buf); > break; > case 8: > - *val = get_unaligned_be64(buf); > + if (little_endian) > + *val = get_unaligned_le64(buf); > + else > + *val = get_unaligned_be64(buf); > break; > default: > dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", > @@ -68,6 +82,7 @@ EXPORT_SYMBOL_GPL(cci_read); > > int cci_write(struct regmap *map, u32 reg, u64 val, int *err) > { > + bool little_endian; > unsigned int len; > u8 buf[8]; > int ret; > @@ -75,6 +90,7 @@ int cci_write(struct regmap *map, u32 reg, u64 val, int *err) > if (err && *err) > return *err; > > + little_endian = reg & CCI_REG_LE; > len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); > reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); > > @@ -83,16 +99,28 @@ int cci_write(struct regmap *map, u32 reg, u64 val, int *err) > buf[0] = val; > break; > case 2: > - put_unaligned_be16(val, buf); > + if (little_endian) > + put_unaligned_le16(val, buf); > + else > + put_unaligned_be16(val, buf); > break; > case 3: > - put_unaligned_be24(val, buf); > + if (little_endian) > + put_unaligned_le24(val, buf); > + else > + put_unaligned_be24(val, buf); > break; > case 4: > - put_unaligned_be32(val, buf); > + if (little_endian) > + put_unaligned_le32(val, buf); > + else > + put_unaligned_be32(val, buf); > break; > case 8: > - put_unaligned_be64(val, buf); > + if (little_endian) > + put_unaligned_le64(val, buf); > + else > + put_unaligned_be64(val, buf); > break; > default: > dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", > diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h > index 0f6803e4b17e9..ef3faf0c9d44d 100644 > --- a/include/media/v4l2-cci.h > +++ b/include/media/v4l2-cci.h > @@ -32,12 +32,17 @@ struct cci_reg_sequence { > #define CCI_REG_ADDR_MASK GENMASK(15, 0) > #define CCI_REG_WIDTH_SHIFT 16 > #define CCI_REG_WIDTH_MASK GENMASK(19, 16) > +#define CCI_REG_LE BIT(20) > > #define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) > #define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) > #define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) > #define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) > #define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) > +#define CCI_REG16_LE(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > +#define CCI_REG24_LE(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > +#define CCI_REG32_LE(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > +#define CCI_REG64_LE(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) I would put CCI_REG_LE first, to match the bits order. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > /** > * cci_read() - Read a value from a single CCI register
Hi Laurent, On Thu, Nov 02, 2023 at 03:22:17AM +0200, Laurent Pinchart wrote: > Hi Alexander, > > Thank you for the patch. > > On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: > > Some sensors, e.g. Sony, are using little-endian registers. Add support for > > I would write Sony IMX290 here, as there are Sony sensors that use big > endian. Almost all of them. There are a few exceptions indeed. This seems to be a bug. > > > those by encoding the endianess into Bit 20 of the register address. > > > > Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access helpers") > > Cc: stable@vger.kernel.org > > Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> > > --- > > drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ > > include/media/v4l2-cci.h | 5 ++++ > > 2 files changed, 41 insertions(+), 8 deletions(-) > > > > diff --git a/drivers/media/v4l2-core/v4l2-cci.c b/drivers/media/v4l2-core/v4l2-cci.c > > index bc2dbec019b04..673637b67bf67 100644 > > --- a/drivers/media/v4l2-core/v4l2-cci.c > > +++ b/drivers/media/v4l2-core/v4l2-cci.c > > @@ -18,6 +18,7 @@ > > > > int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > > { > > + bool little_endian; > > unsigned int len; > > u8 buf[8]; > > int ret; > > @@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > > if (err && *err) > > return *err; > > > > + little_endian = reg & CCI_REG_LE; > > You could initialize the variable when declaring it. Same below. I was thinking of the same, but then it'd be logical to move initialisation of all related variables there. reg is modified here though. I'd keep setting little_endian here. If someone wants to move it, that could be done in a separate patch. > > > len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); > > reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); > > > > @@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > > *val = buf[0]; > > break; > > case 2: > > - *val = get_unaligned_be16(buf); > > + if (little_endian) > > + *val = get_unaligned_le16(buf); > > + else > > + *val = get_unaligned_be16(buf); > > Unrelated to this patch, isn't buf aligned to a 4 bytes boundary ? Very probably, as it's right after len that's an unsigned int. Adding __aligned(8) would ensure we don't need any of the unaligned variants, and most likely would keep the stack layout as-is. Or... how about putting it in an union with a u64? That would mean it's accessible as u64 alignment-wise while the alignment itself is up to the ABI. A comment would be good to have probably. > > > break; > > case 3: > > - *val = get_unaligned_be24(buf); > > + if (little_endian) > > + *val = get_unaligned_le24(buf); > > + else > > + *val = get_unaligned_be24(buf); > > break; > > case 4: > > - *val = get_unaligned_be32(buf); > > + if (little_endian) > > + *val = get_unaligned_le32(buf); > > + else > > + *val = get_unaligned_be32(buf); > > break; > > case 8: > > - *val = get_unaligned_be64(buf); > > + if (little_endian) > > + *val = get_unaligned_le64(buf); > > + else > > + *val = get_unaligned_be64(buf); > > break; > > default: > > dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n",
Hi, thanks for the feedback. Am Donnerstag, 2. November 2023, 07:30:44 CET schrieb Sakari Ailus: > Hi Laurent, > > On Thu, Nov 02, 2023 at 03:22:17AM +0200, Laurent Pinchart wrote: > > Hi Alexander, > > > > Thank you for the patch. > > > > On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: > > > Some sensors, e.g. Sony, are using little-endian registers. Add support > > > for > > > > I would write Sony IMX290 here, as there are Sony sensors that use big > > endian. > > Almost all of them. There are a few exceptions indeed. This seems to be a > bug. Let's name IMX290 here as an actual example. No need to worry about other models here. > > > those by encoding the endianess into Bit 20 of the register address. > > > > > > Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access > > > helpers") Cc: stable@vger.kernel.org > > > Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> > > > --- > > > > > > drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ > > > include/media/v4l2-cci.h | 5 ++++ > > > 2 files changed, 41 insertions(+), 8 deletions(-) > > > > > > diff --git a/drivers/media/v4l2-core/v4l2-cci.c > > > b/drivers/media/v4l2-core/v4l2-cci.c index bc2dbec019b04..673637b67bf67 > > > 100644 > > > --- a/drivers/media/v4l2-core/v4l2-cci.c > > > +++ b/drivers/media/v4l2-core/v4l2-cci.c > > > @@ -18,6 +18,7 @@ > > > > > > int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > > > { > > > > > > + bool little_endian; > > > > > > unsigned int len; > > > u8 buf[8]; > > > int ret; > > > > > > @@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, > > > int *err)> > > > > if (err && *err) > > > > > > return *err; > > > > > > + little_endian = reg & CCI_REG_LE; > > > > You could initialize the variable when declaring it. Same below. > > I was thinking of the same, but then it'd be logical to move initialisation > of all related variables there. reg is modified here though. I'd keep > setting little_endian here. If someone wants to move it, that could be done > in a separate patch. > > > > len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); > > > reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); > > > > > > @@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, > > > int *err)> > > > > *val = buf[0]; > > > break; > > > > > > case 2: > > > - *val = get_unaligned_be16(buf); > > > + if (little_endian) > > > + *val = get_unaligned_le16(buf); > > > + else > > > + *val = get_unaligned_be16(buf); > > > > Unrelated to this patch, isn't buf aligned to a 4 bytes boundary ? > > Very probably, as it's right after len that's an unsigned int. Adding > __aligned(8) would ensure we don't need any of the unaligned variants, and > most likely would keep the stack layout as-is. You mean something like this? u8 __aligned(8) buf[8]; [...] if (little_endian) *val = le64_to_cpup(buf); else *val = be64_to_cpup(buf); But what about 24 Bits? There is no le24_to_cpup. I would rather use the same API for all cases. > Or... how about putting it in an union with a u64? That would mean it's > accessible as u64 alignment-wise while the alignment itself is up to the > ABI. A comment would be good to have probably. An additional union seems a bit too much here. Unless something suitable already exists for general usage. Best regards, Alexander > > > break; > > > > > > case 3: > > > - *val = get_unaligned_be24(buf); > > > + if (little_endian) > > > + *val = get_unaligned_le24(buf); > > > + else > > > + *val = get_unaligned_be24(buf); > > > > > > break; > > > > > > case 4: > > > - *val = get_unaligned_be32(buf); > > > + if (little_endian) > > > + *val = get_unaligned_le32(buf); > > > + else > > > + *val = get_unaligned_be32(buf); > > > > > > break; > > > > > > case 8: > > > - *val = get_unaligned_be64(buf); > > > + if (little_endian) > > > + *val = get_unaligned_le64(buf); > > > + else > > > + *val = get_unaligned_be64(buf); > > > > > > break; > > > > > > default: > > > dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg > > > 0x%04x\n",
Am Donnerstag, 2. November 2023, 02:22:17 CET schrieb Laurent Pinchart: > ******************** > Achtung externe E-Mail: Öffnen Sie Anhänge und Links nur, wenn Sie wissen, > dass diese aus einer sicheren Quelle stammen und sicher sind. Leiten Sie > die E-Mail im Zweifelsfall zur Prüfung an den IT-Helpdesk weiter. > Attention external email: Open attachments and links only if you know that > they are from a secure source and are safe. In doubt forward the email to > the IT-Helpdesk to check it. ******************** > > Hi Alexander, > > Thank you for the patch. > > On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: > > Some sensors, e.g. Sony, are using little-endian registers. Add support > > for > > I would write Sony IMX290 here, as there are Sony sensors that use big > endian. > > > those by encoding the endianess into Bit 20 of the register address. > > > > Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access > > helpers") Cc: stable@vger.kernel.org > > Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> > > --- > > > > drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ > > include/media/v4l2-cci.h | 5 ++++ > > 2 files changed, 41 insertions(+), 8 deletions(-) > > > > diff --git a/drivers/media/v4l2-core/v4l2-cci.c > > b/drivers/media/v4l2-core/v4l2-cci.c index bc2dbec019b04..673637b67bf67 > > 100644 > > --- a/drivers/media/v4l2-core/v4l2-cci.c > > +++ b/drivers/media/v4l2-core/v4l2-cci.c > > @@ -18,6 +18,7 @@ > > > > int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > > { > > > > + bool little_endian; > > > > unsigned int len; > > u8 buf[8]; > > int ret; > > > > @@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int > > *err)> > > if (err && *err) > > > > return *err; > > > > + little_endian = reg & CCI_REG_LE; > > You could initialize the variable when declaring it. Same below. > > > len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); > > reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); > > > > @@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, > > int *err)> > > *val = buf[0]; > > break; > > > > case 2: > > - *val = get_unaligned_be16(buf); > > + if (little_endian) > > + *val = get_unaligned_le16(buf); > > + else > > + *val = get_unaligned_be16(buf); > > Unrelated to this patch, isn't buf aligned to a 4 bytes boundary ? > > > break; > > > > case 3: > > - *val = get_unaligned_be24(buf); > > + if (little_endian) > > + *val = get_unaligned_le24(buf); > > + else > > + *val = get_unaligned_be24(buf); > > > > break; > > > > case 4: > > - *val = get_unaligned_be32(buf); > > + if (little_endian) > > + *val = get_unaligned_le32(buf); > > + else > > + *val = get_unaligned_be32(buf); > > > > break; > > > > case 8: > > - *val = get_unaligned_be64(buf); > > + if (little_endian) > > + *val = get_unaligned_le64(buf); > > + else > > + *val = get_unaligned_be64(buf); > > > > break; > > > > default: > > dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg > > 0x%04x\n",> > > @@ -68,6 +82,7 @@ EXPORT_SYMBOL_GPL(cci_read); > > > > int cci_write(struct regmap *map, u32 reg, u64 val, int *err) > > { > > > > + bool little_endian; > > > > unsigned int len; > > u8 buf[8]; > > int ret; > > > > @@ -75,6 +90,7 @@ int cci_write(struct regmap *map, u32 reg, u64 val, int > > *err)> > > if (err && *err) > > > > return *err; > > > > + little_endian = reg & CCI_REG_LE; > > > > len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); > > reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); > > > > @@ -83,16 +99,28 @@ int cci_write(struct regmap *map, u32 reg, u64 val, > > int *err)> > > buf[0] = val; > > break; > > > > case 2: > > - put_unaligned_be16(val, buf); > > + if (little_endian) > > + put_unaligned_le16(val, buf); > > + else > > + put_unaligned_be16(val, buf); > > > > break; > > > > case 3: > > - put_unaligned_be24(val, buf); > > + if (little_endian) > > + put_unaligned_le24(val, buf); > > + else > > + put_unaligned_be24(val, buf); > > > > break; > > > > case 4: > > - put_unaligned_be32(val, buf); > > + if (little_endian) > > + put_unaligned_le32(val, buf); > > + else > > + put_unaligned_be32(val, buf); > > > > break; > > > > case 8: > > - put_unaligned_be64(val, buf); > > + if (little_endian) > > + put_unaligned_le64(val, buf); > > + else > > + put_unaligned_be64(val, buf); > > > > break; > > > > default: > > dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg > > 0x%04x\n",> > > diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h > > index 0f6803e4b17e9..ef3faf0c9d44d 100644 > > --- a/include/media/v4l2-cci.h > > +++ b/include/media/v4l2-cci.h > > @@ -32,12 +32,17 @@ struct cci_reg_sequence { > > > > #define CCI_REG_ADDR_MASK GENMASK(15, 0) > > #define CCI_REG_WIDTH_SHIFT 16 > > #define CCI_REG_WIDTH_MASK GENMASK(19, 16) > > > > +#define CCI_REG_LE BIT(20) > > > > #define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) > > #define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) > > #define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) > > #define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) > > #define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) > > > > +#define CCI_REG16_LE(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > +#define CCI_REG24_LE(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > +#define CCI_REG32_LE(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > +#define CCI_REG64_LE(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > I would put CCI_REG_LE first, to match the bits order. You mean this order? CCI_REG8(x) CCI_REG16_LE(x) CCI_REG16(x) CCI_REG24_LE(x) CCI_REG24(x) CCI_REG32_LE(x) CCI_REG32(x) CCI_REG64_LE(x) CCI_REG64(x) I would either keep the _LE variants at the bottom or below to their big- endian counterpart. I prefer readability thus I would put the _LE at the bottom, also it aligns nicely with the additional bit set. Best regards, Alexander > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > > /** > > > > * cci_read() - Read a value from a single CCI register
Hi Alexander, On Thu, Nov 02, 2023 at 08:55:01AM +0100, Alexander Stein wrote: > Am Donnerstag, 2. November 2023, 02:22:17 CET schrieb Laurent Pinchart: > > On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: > > > Some sensors, e.g. Sony, are using little-endian registers. Add support > > > for > > > > I would write Sony IMX290 here, as there are Sony sensors that use big > > endian. > > > > > those by encoding the endianess into Bit 20 of the register address. > > > > > > Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access > > > helpers") Cc: stable@vger.kernel.org > > > Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> > > > --- > > > > > > drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ > > > include/media/v4l2-cci.h | 5 ++++ > > > 2 files changed, 41 insertions(+), 8 deletions(-) [snip] > > > diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h > > > index 0f6803e4b17e9..ef3faf0c9d44d 100644 > > > --- a/include/media/v4l2-cci.h > > > +++ b/include/media/v4l2-cci.h > > > @@ -32,12 +32,17 @@ struct cci_reg_sequence { > > > #define CCI_REG_ADDR_MASK GENMASK(15, 0) > > > #define CCI_REG_WIDTH_SHIFT 16 > > > #define CCI_REG_WIDTH_MASK GENMASK(19, 16) > > > +#define CCI_REG_LE BIT(20) > > > > > > #define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) > > > #define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) > > > #define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) > > > #define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) > > > #define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) > > > +#define CCI_REG16_LE(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > > +#define CCI_REG24_LE(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > > +#define CCI_REG32_LE(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > > +#define CCI_REG64_LE(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > > > I would put CCI_REG_LE first, to match the bits order. > > You mean this order? > > CCI_REG8(x) > CCI_REG16_LE(x) > CCI_REG16(x) > CCI_REG24_LE(x) > CCI_REG24(x) > CCI_REG32_LE(x) > CCI_REG32(x) > CCI_REG64_LE(x) > CCI_REG64(x) > > I would either keep the _LE variants at the bottom or below to their big- > endian counterpart. I prefer readability thus I would put the _LE at the > bottom, also it aligns nicely with the additional bit set. No, I meant #define CCI_REG16_LE(x) (CCI_REG_LE | (2 << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG24_LE(x) (CCI_REG_LE | (3 << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG32_LE(x) (CCI_REG_LE | (4 << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG64_LE(x) (CCI_REG_LE | (8 << CCI_REG_WIDTH_SHIFT) | (x)) > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > > > > /** > > > > > > * cci_read() - Read a value from a single CCI register
Hi Alexander, On Thu, Nov 02, 2023 at 08:51:12AM +0100, Alexander Stein wrote: > Hi, > > thanks for the feedback. > > Am Donnerstag, 2. November 2023, 07:30:44 CET schrieb Sakari Ailus: > > Hi Laurent, > > > > On Thu, Nov 02, 2023 at 03:22:17AM +0200, Laurent Pinchart wrote: > > > Hi Alexander, > > > > > > Thank you for the patch. > > > > > > On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: > > > > Some sensors, e.g. Sony, are using little-endian registers. Add support > > > > for > > > > > > I would write Sony IMX290 here, as there are Sony sensors that use big > > > endian. > > > > Almost all of them. There are a few exceptions indeed. This seems to be a > > bug. > > Let's name IMX290 here as an actual example. No need to worry about other > models here. > > > > > those by encoding the endianess into Bit 20 of the register address. > > > > > > > > Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access > > > > helpers") Cc: stable@vger.kernel.org > > > > Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> > > > > --- > > > > > > > > drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ > > > > include/media/v4l2-cci.h | 5 ++++ > > > > 2 files changed, 41 insertions(+), 8 deletions(-) > > > > > > > > diff --git a/drivers/media/v4l2-core/v4l2-cci.c > > > > b/drivers/media/v4l2-core/v4l2-cci.c index bc2dbec019b04..673637b67bf67 > > > > 100644 > > > > --- a/drivers/media/v4l2-core/v4l2-cci.c > > > > +++ b/drivers/media/v4l2-core/v4l2-cci.c > > > > @@ -18,6 +18,7 @@ > > > > > > > > int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > > > > { > > > > > > > > + bool little_endian; > > > > > > > > unsigned int len; > > > > u8 buf[8]; > > > > int ret; > > > > > > > > @@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, > > > > int *err)> > > > > > if (err && *err) > > > > > > > > return *err; > > > > > > > > + little_endian = reg & CCI_REG_LE; > > > > > > You could initialize the variable when declaring it. Same below. > > > > I was thinking of the same, but then it'd be logical to move initialisation > > of all related variables there. reg is modified here though. I'd keep > > setting little_endian here. If someone wants to move it, that could be done > > in a separate patch. > > > > > > len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); > > > > reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); > > > > > > > > @@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, > > > > int *err)> > > > > > *val = buf[0]; > > > > break; > > > > > > > > case 2: > > > > - *val = get_unaligned_be16(buf); > > > > + if (little_endian) > > > > + *val = get_unaligned_le16(buf); > > > > + else > > > > + *val = get_unaligned_be16(buf); > > > > > > Unrelated to this patch, isn't buf aligned to a 4 bytes boundary ? > > > > Very probably, as it's right after len that's an unsigned int. Adding > > __aligned(8) would ensure we don't need any of the unaligned variants, and > > most likely would keep the stack layout as-is. > > You mean something like this? > > u8 __aligned(8) buf[8]; > [...] > if (little_endian) > *val = le64_to_cpup(buf); > else > *val = be64_to_cpup(buf); > > But what about 24 Bits? There is no le24_to_cpup. I would rather use the same > API for all cases. The aligned APIs are much better choice when you can use them. The 24 bit case can remain special IMO. > > > Or... how about putting it in an union with a u64? That would mean it's > > accessible as u64 alignment-wise while the alignment itself is up to the > > ABI. A comment would be good to have probably. > > An additional union seems a bit too much here. Unless something suitable > already exists for general usage. I think it's nicer than using __aligned() as you get ABI alignment that way, not something you force manually --- that's a bit crude. I wonder that others think.
Hi Laurent, Alexander, On Thu, Nov 02, 2023 at 10:24:30AM +0200, Laurent Pinchart wrote: > Hi Alexander, > > On Thu, Nov 02, 2023 at 08:55:01AM +0100, Alexander Stein wrote: > > Am Donnerstag, 2. November 2023, 02:22:17 CET schrieb Laurent Pinchart: > > > On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: > > > > Some sensors, e.g. Sony, are using little-endian registers. Add support > > > > for > > > > > > I would write Sony IMX290 here, as there are Sony sensors that use big > > > endian. > > > > > > > those by encoding the endianess into Bit 20 of the register address. > > > > > > > > Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access > > > > helpers") Cc: stable@vger.kernel.org > > > > Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> > > > > --- > > > > > > > > drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ > > > > include/media/v4l2-cci.h | 5 ++++ > > > > 2 files changed, 41 insertions(+), 8 deletions(-) > > [snip] > > > > > diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h > > > > index 0f6803e4b17e9..ef3faf0c9d44d 100644 > > > > --- a/include/media/v4l2-cci.h > > > > +++ b/include/media/v4l2-cci.h > > > > @@ -32,12 +32,17 @@ struct cci_reg_sequence { > > > > #define CCI_REG_ADDR_MASK GENMASK(15, 0) > > > > #define CCI_REG_WIDTH_SHIFT 16 > > > > #define CCI_REG_WIDTH_MASK GENMASK(19, 16) > > > > +#define CCI_REG_LE BIT(20) > > > > > > > > #define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) > > > > #define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) > > > > #define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) > > > > #define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) > > > > #define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) > > > > +#define CCI_REG16_LE(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > > > +#define CCI_REG24_LE(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > > > +#define CCI_REG32_LE(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > > > +#define CCI_REG64_LE(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) > > > > > > I would put CCI_REG_LE first, to match the bits order. > > > > You mean this order? > > > > CCI_REG8(x) > > CCI_REG16_LE(x) > > CCI_REG16(x) > > CCI_REG24_LE(x) > > CCI_REG24(x) > > CCI_REG32_LE(x) > > CCI_REG32(x) > > CCI_REG64_LE(x) > > CCI_REG64(x) > > > > I would either keep the _LE variants at the bottom or below to their big- > > endian counterpart. I prefer readability thus I would put the _LE at the > > bottom, also it aligns nicely with the additional bit set. > > No, I meant > > #define CCI_REG16_LE(x) (CCI_REG_LE | (2 << CCI_REG_WIDTH_SHIFT) | (x)) > #define CCI_REG24_LE(x) (CCI_REG_LE | (3 << CCI_REG_WIDTH_SHIFT) | (x)) > #define CCI_REG32_LE(x) (CCI_REG_LE | (4 << CCI_REG_WIDTH_SHIFT) | (x)) > #define CCI_REG64_LE(x) (CCI_REG_LE | (8 << CCI_REG_WIDTH_SHIFT) | (x)) Ideally these numbers would be unsigned, i.e. #define CCI_REG16_LE(x) (CCI_REG_LE | (2U << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG24_LE(x) (CCI_REG_LE | (3U << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG32_LE(x) (CCI_REG_LE | (4U << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG64_LE(x) (CCI_REG_LE | (8U << CCI_REG_WIDTH_SHIFT) | (x)) This is a pre-existing problem. Feel free to add a patch to address it. :-)
On Thu, Nov 02, 2023 at 08:31:44AM +0000, Sakari Ailus wrote:
> This is a pre-existing problem. Feel free to add a patch to address it. :-)
I forgot to add that addressing may be part of the same set but come as
last, to avoid unnecessarily backporting patches. There's no bug in the
code related to this --- just a bug-prone pattern.
Hi, On 11/2/23 09:25, Sakari Ailus wrote: > Hi Alexander, > > On Thu, Nov 02, 2023 at 08:51:12AM +0100, Alexander Stein wrote: >> Hi, >> >> thanks for the feedback. >> >> Am Donnerstag, 2. November 2023, 07:30:44 CET schrieb Sakari Ailus: >>> Hi Laurent, >>> >>> On Thu, Nov 02, 2023 at 03:22:17AM +0200, Laurent Pinchart wrote: >>>> Hi Alexander, >>>> >>>> Thank you for the patch. >>>> >>>> On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: >>>>> Some sensors, e.g. Sony, are using little-endian registers. Add support >>>>> for >>>> >>>> I would write Sony IMX290 here, as there are Sony sensors that use big >>>> endian. >>> >>> Almost all of them. There are a few exceptions indeed. This seems to be a >>> bug. >> >> Let's name IMX290 here as an actual example. No need to worry about other >> models here. >> >>>>> those by encoding the endianess into Bit 20 of the register address. >>>>> >>>>> Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access >>>>> helpers") Cc: stable@vger.kernel.org >>>>> Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> >>>>> --- >>>>> >>>>> drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ >>>>> include/media/v4l2-cci.h | 5 ++++ >>>>> 2 files changed, 41 insertions(+), 8 deletions(-) >>>>> >>>>> diff --git a/drivers/media/v4l2-core/v4l2-cci.c >>>>> b/drivers/media/v4l2-core/v4l2-cci.c index bc2dbec019b04..673637b67bf67 >>>>> 100644 >>>>> --- a/drivers/media/v4l2-core/v4l2-cci.c >>>>> +++ b/drivers/media/v4l2-core/v4l2-cci.c >>>>> @@ -18,6 +18,7 @@ >>>>> >>>>> int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) >>>>> { >>>>> >>>>> + bool little_endian; >>>>> >>>>> unsigned int len; >>>>> u8 buf[8]; >>>>> int ret; >>>>> >>>>> @@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, >>>>> int *err)> > >>>>> if (err && *err) >>>>> >>>>> return *err; >>>>> >>>>> + little_endian = reg & CCI_REG_LE; >>>> >>>> You could initialize the variable when declaring it. Same below. >>> >>> I was thinking of the same, but then it'd be logical to move initialisation >>> of all related variables there. reg is modified here though. I'd keep >>> setting little_endian here. If someone wants to move it, that could be done >>> in a separate patch. >>> >>>>> len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); >>>>> reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); >>>>> >>>>> @@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, >>>>> int *err)> > >>>>> *val = buf[0]; >>>>> break; >>>>> >>>>> case 2: >>>>> - *val = get_unaligned_be16(buf); >>>>> + if (little_endian) >>>>> + *val = get_unaligned_le16(buf); >>>>> + else >>>>> + *val = get_unaligned_be16(buf); >>>> >>>> Unrelated to this patch, isn't buf aligned to a 4 bytes boundary ? >>> >>> Very probably, as it's right after len that's an unsigned int. Adding >>> __aligned(8) would ensure we don't need any of the unaligned variants, and >>> most likely would keep the stack layout as-is. >> >> You mean something like this? >> >> u8 __aligned(8) buf[8]; >> [...] >> if (little_endian) >> *val = le64_to_cpup(buf); >> else >> *val = be64_to_cpup(buf); >> >> But what about 24 Bits? There is no le24_to_cpup. I would rather use the same >> API for all cases. > > The aligned APIs are much better choice when you can use them. The 24 bit > case can remain special IMO. > >> >>> Or... how about putting it in an union with a u64? That would mean it's >>> accessible as u64 alignment-wise while the alignment itself is up to the >>> ABI. A comment would be good to have probably. >> >> An additional union seems a bit too much here. Unless something suitable >> already exists for general usage. > > I think it's nicer than using __aligned() as you get ABI alignment that > way, not something you force manually --- that's a bit crude. > > I wonder that others think. I'm fine with adding the __aligned(8) and switching the non 24 bit cases to helpers which assume alignment. The most important note I have is that that is a separate improvement from this series though. So this should be done in a follow-up patch which is not Cc: stable . Regards, Hans
On Thu, Nov 02, 2023 at 10:27:45AM +0100, Hans de Goede wrote: > Hi, > > On 11/2/23 09:25, Sakari Ailus wrote: > > Hi Alexander, > > > > On Thu, Nov 02, 2023 at 08:51:12AM +0100, Alexander Stein wrote: > >> Hi, > >> > >> thanks for the feedback. > >> > >> Am Donnerstag, 2. November 2023, 07:30:44 CET schrieb Sakari Ailus: > >>> Hi Laurent, > >>> > >>> On Thu, Nov 02, 2023 at 03:22:17AM +0200, Laurent Pinchart wrote: > >>>> Hi Alexander, > >>>> > >>>> Thank you for the patch. > >>>> > >>>> On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: > >>>>> Some sensors, e.g. Sony, are using little-endian registers. Add support > >>>>> for > >>>> > >>>> I would write Sony IMX290 here, as there are Sony sensors that use big > >>>> endian. > >>> > >>> Almost all of them. There are a few exceptions indeed. This seems to be a > >>> bug. > >> > >> Let's name IMX290 here as an actual example. No need to worry about other > >> models here. > >> > >>>>> those by encoding the endianess into Bit 20 of the register address. > >>>>> > >>>>> Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access > >>>>> helpers") Cc: stable@vger.kernel.org > >>>>> Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> > >>>>> --- > >>>>> > >>>>> drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ > >>>>> include/media/v4l2-cci.h | 5 ++++ > >>>>> 2 files changed, 41 insertions(+), 8 deletions(-) > >>>>> > >>>>> diff --git a/drivers/media/v4l2-core/v4l2-cci.c > >>>>> b/drivers/media/v4l2-core/v4l2-cci.c index bc2dbec019b04..673637b67bf67 > >>>>> 100644 > >>>>> --- a/drivers/media/v4l2-core/v4l2-cci.c > >>>>> +++ b/drivers/media/v4l2-core/v4l2-cci.c > >>>>> @@ -18,6 +18,7 @@ > >>>>> > >>>>> int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > >>>>> { > >>>>> > >>>>> + bool little_endian; > >>>>> > >>>>> unsigned int len; > >>>>> u8 buf[8]; > >>>>> int ret; > >>>>> > >>>>> @@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, > >>>>> int *err)> > > >>>>> if (err && *err) > >>>>> > >>>>> return *err; > >>>>> > >>>>> + little_endian = reg & CCI_REG_LE; > >>>> > >>>> You could initialize the variable when declaring it. Same below. > >>> > >>> I was thinking of the same, but then it'd be logical to move initialisation > >>> of all related variables there. reg is modified here though. I'd keep > >>> setting little_endian here. If someone wants to move it, that could be done > >>> in a separate patch. > >>> > >>>>> len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); > >>>>> reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); > >>>>> > >>>>> @@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, > >>>>> int *err)> > > >>>>> *val = buf[0]; > >>>>> break; > >>>>> > >>>>> case 2: > >>>>> - *val = get_unaligned_be16(buf); > >>>>> + if (little_endian) > >>>>> + *val = get_unaligned_le16(buf); > >>>>> + else > >>>>> + *val = get_unaligned_be16(buf); > >>>> > >>>> Unrelated to this patch, isn't buf aligned to a 4 bytes boundary ? > >>> > >>> Very probably, as it's right after len that's an unsigned int. Adding > >>> __aligned(8) would ensure we don't need any of the unaligned variants, and > >>> most likely would keep the stack layout as-is. > >> > >> You mean something like this? > >> > >> u8 __aligned(8) buf[8]; > >> [...] > >> if (little_endian) > >> *val = le64_to_cpup(buf); > >> else > >> *val = be64_to_cpup(buf); > >> > >> But what about 24 Bits? There is no le24_to_cpup. I would rather use the same > >> API for all cases. > > > > The aligned APIs are much better choice when you can use them. The 24 bit > > case can remain special IMO. > > > >> > >>> Or... how about putting it in an union with a u64? That would mean it's > >>> accessible as u64 alignment-wise while the alignment itself is up to the > >>> ABI. A comment would be good to have probably. > >> > >> An additional union seems a bit too much here. Unless something suitable > >> already exists for general usage. > > > > I think it's nicer than using __aligned() as you get ABI alignment that > > way, not something you force manually --- that's a bit crude. > > > > I wonder that others think. > > I'm fine with adding the __aligned(8) and switching the non 24 bit > cases to helpers which assume alignment. The most important note > I have is that that is a separate improvement from this series though. > > So this should be done in a follow-up patch which is not Cc: stable . I'm fine with that. So I think these are good as-is then.
On Thu, Nov 02, 2023 at 09:56:24AM +0000, Sakari Ailus wrote: > On Thu, Nov 02, 2023 at 10:27:45AM +0100, Hans de Goede wrote: > > Hi, > > > > On 11/2/23 09:25, Sakari Ailus wrote: > > > Hi Alexander, > > > > > > On Thu, Nov 02, 2023 at 08:51:12AM +0100, Alexander Stein wrote: > > >> Hi, > > >> > > >> thanks for the feedback. > > >> > > >> Am Donnerstag, 2. November 2023, 07:30:44 CET schrieb Sakari Ailus: > > >>> Hi Laurent, > > >>> > > >>> On Thu, Nov 02, 2023 at 03:22:17AM +0200, Laurent Pinchart wrote: > > >>>> Hi Alexander, > > >>>> > > >>>> Thank you for the patch. > > >>>> > > >>>> On Wed, Nov 01, 2023 at 01:23:53PM +0100, Alexander Stein wrote: > > >>>>> Some sensors, e.g. Sony, are using little-endian registers. Add support > > >>>>> for > > >>>> > > >>>> I would write Sony IMX290 here, as there are Sony sensors that use big > > >>>> endian. > > >>> > > >>> Almost all of them. There are a few exceptions indeed. This seems to be a > > >>> bug. > > >> > > >> Let's name IMX290 here as an actual example. No need to worry about other > > >> models here. > > >> > > >>>>> those by encoding the endianess into Bit 20 of the register address. > > >>>>> > > >>>>> Fixes: af73323b97702 ("media: imx290: Convert to new CCI register access > > >>>>> helpers") Cc: stable@vger.kernel.org > > >>>>> Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com> > > >>>>> --- > > >>>>> > > >>>>> drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ > > >>>>> include/media/v4l2-cci.h | 5 ++++ > > >>>>> 2 files changed, 41 insertions(+), 8 deletions(-) > > >>>>> > > >>>>> diff --git a/drivers/media/v4l2-core/v4l2-cci.c > > >>>>> b/drivers/media/v4l2-core/v4l2-cci.c index bc2dbec019b04..673637b67bf67 > > >>>>> 100644 > > >>>>> --- a/drivers/media/v4l2-core/v4l2-cci.c > > >>>>> +++ b/drivers/media/v4l2-core/v4l2-cci.c > > >>>>> @@ -18,6 +18,7 @@ > > >>>>> > > >>>>> int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) > > >>>>> { > > >>>>> > > >>>>> + bool little_endian; > > >>>>> > > >>>>> unsigned int len; > > >>>>> u8 buf[8]; > > >>>>> int ret; > > >>>>> > > >>>>> @@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, > > >>>>> int *err)> > > > >>>>> if (err && *err) > > >>>>> > > >>>>> return *err; > > >>>>> > > >>>>> + little_endian = reg & CCI_REG_LE; > > >>>> > > >>>> You could initialize the variable when declaring it. Same below. > > >>> > > >>> I was thinking of the same, but then it'd be logical to move initialisation > > >>> of all related variables there. reg is modified here though. I'd keep > > >>> setting little_endian here. If someone wants to move it, that could be done > > >>> in a separate patch. > > >>> > > >>>>> len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); > > >>>>> reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); > > >>>>> > > >>>>> @@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, > > >>>>> int *err)> > > > >>>>> *val = buf[0]; > > >>>>> break; > > >>>>> > > >>>>> case 2: > > >>>>> - *val = get_unaligned_be16(buf); > > >>>>> + if (little_endian) > > >>>>> + *val = get_unaligned_le16(buf); > > >>>>> + else > > >>>>> + *val = get_unaligned_be16(buf); > > >>>> > > >>>> Unrelated to this patch, isn't buf aligned to a 4 bytes boundary ? > > >>> > > >>> Very probably, as it's right after len that's an unsigned int. Adding > > >>> __aligned(8) would ensure we don't need any of the unaligned variants, and > > >>> most likely would keep the stack layout as-is. > > >> > > >> You mean something like this? > > >> > > >> u8 __aligned(8) buf[8]; > > >> [...] > > >> if (little_endian) > > >> *val = le64_to_cpup(buf); > > >> else > > >> *val = be64_to_cpup(buf); > > >> > > >> But what about 24 Bits? There is no le24_to_cpup. I would rather use the same > > >> API for all cases. > > > > > > The aligned APIs are much better choice when you can use them. The 24 bit > > > case can remain special IMO. > > > > > >> > > >>> Or... how about putting it in an union with a u64? That would mean it's > > >>> accessible as u64 alignment-wise while the alignment itself is up to the > > >>> ABI. A comment would be good to have probably. > > >> > > >> An additional union seems a bit too much here. Unless something suitable > > >> already exists for general usage. > > > > > > I think it's nicer than using __aligned() as you get ABI alignment that > > > way, not something you force manually --- that's a bit crude. > > > > > > I wonder that others think. > > > > I'm fine with adding the __aligned(8) and switching the non 24 bit > > cases to helpers which assume alignment. The most important note > > I have is that that is a separate improvement from this series though. > > > > So this should be done in a follow-up patch which is not Cc: stable . > > I'm fine with that. > > So I think these are good as-is then. Or rather with the non-functional changes made in v3.
diff --git a/drivers/media/v4l2-core/v4l2-cci.c b/drivers/media/v4l2-core/v4l2-cci.c index bc2dbec019b04..673637b67bf67 100644 --- a/drivers/media/v4l2-core/v4l2-cci.c +++ b/drivers/media/v4l2-core/v4l2-cci.c @@ -18,6 +18,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) { + bool little_endian; unsigned int len; u8 buf[8]; int ret; @@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) if (err && *err) return *err; + little_endian = reg & CCI_REG_LE; len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); @@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) *val = buf[0]; break; case 2: - *val = get_unaligned_be16(buf); + if (little_endian) + *val = get_unaligned_le16(buf); + else + *val = get_unaligned_be16(buf); break; case 3: - *val = get_unaligned_be24(buf); + if (little_endian) + *val = get_unaligned_le24(buf); + else + *val = get_unaligned_be24(buf); break; case 4: - *val = get_unaligned_be32(buf); + if (little_endian) + *val = get_unaligned_le32(buf); + else + *val = get_unaligned_be32(buf); break; case 8: - *val = get_unaligned_be64(buf); + if (little_endian) + *val = get_unaligned_le64(buf); + else + *val = get_unaligned_be64(buf); break; default: dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", @@ -68,6 +82,7 @@ EXPORT_SYMBOL_GPL(cci_read); int cci_write(struct regmap *map, u32 reg, u64 val, int *err) { + bool little_endian; unsigned int len; u8 buf[8]; int ret; @@ -75,6 +90,7 @@ int cci_write(struct regmap *map, u32 reg, u64 val, int *err) if (err && *err) return *err; + little_endian = reg & CCI_REG_LE; len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); @@ -83,16 +99,28 @@ int cci_write(struct regmap *map, u32 reg, u64 val, int *err) buf[0] = val; break; case 2: - put_unaligned_be16(val, buf); + if (little_endian) + put_unaligned_le16(val, buf); + else + put_unaligned_be16(val, buf); break; case 3: - put_unaligned_be24(val, buf); + if (little_endian) + put_unaligned_le24(val, buf); + else + put_unaligned_be24(val, buf); break; case 4: - put_unaligned_be32(val, buf); + if (little_endian) + put_unaligned_le32(val, buf); + else + put_unaligned_be32(val, buf); break; case 8: - put_unaligned_be64(val, buf); + if (little_endian) + put_unaligned_le64(val, buf); + else + put_unaligned_be64(val, buf); break; default: dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h index 0f6803e4b17e9..ef3faf0c9d44d 100644 --- a/include/media/v4l2-cci.h +++ b/include/media/v4l2-cci.h @@ -32,12 +32,17 @@ struct cci_reg_sequence { #define CCI_REG_ADDR_MASK GENMASK(15, 0) #define CCI_REG_WIDTH_SHIFT 16 #define CCI_REG_WIDTH_MASK GENMASK(19, 16) +#define CCI_REG_LE BIT(20) #define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) #define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) +#define CCI_REG16_LE(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) +#define CCI_REG24_LE(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) +#define CCI_REG32_LE(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) +#define CCI_REG64_LE(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x) | CCI_REG_LE) /** * cci_read() - Read a value from a single CCI register