All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sakari Ailus <sakari.ailus@linux.intel.com>
To: linux-media@vger.kernel.org
Cc: hverkuil@xs4all.nl, mchehab@kernel.org
Subject: [PATCH v2 09/29] smiapp: Read CCS limit values
Date: Fri, 27 Nov 2020 12:33:05 +0200	[thread overview]
Message-ID: <20201127103325.29814-10-sakari.ailus@linux.intel.com> (raw)
In-Reply-To: <20201127103325.29814-1-sakari.ailus@linux.intel.com>

Read limit and capability values into a driver allocated buffer. This will
later replace (most of) the existing SMIA limits.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp/smiapp-core.c | 177 ++++++++++++++++++++++++-
 drivers/media/i2c/smiapp/smiapp.h      |   4 +
 2 files changed, 176 insertions(+), 5 deletions(-)

diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index bc9c80221d2f..4b33b9a1d52c 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -28,6 +28,7 @@
 #include <media/v4l2-device.h>
 
 #include "ccs-limits.h"
+#include "ccs-regs.h"
 #include "smiapp.h"
 
 #define SMIAPP_ALIGN_DIM(dim, flags)	\
@@ -102,6 +103,164 @@ static int smiapp_read_all_smia_limits(struct smiapp_sensor *sensor)
 	return 0;
 }
 
+static void ccs_assign_limit(void *ptr, unsigned int width, u32 val)
+{
+	switch (width) {
+	case sizeof(u8):
+		*(u8 *)ptr = val;
+		break;
+	case sizeof(u16):
+		*(u16 *)ptr = val;
+		break;
+	case sizeof(u32):
+		*(u32 *)ptr = val;
+		break;
+	}
+}
+
+static int ccs_limit_ptr(struct smiapp_sensor *sensor, unsigned int limit,
+			 unsigned int offset, void **__ptr)
+{
+	const struct ccs_limit *linfo;
+
+	if (WARN_ON(limit >= CCS_L_LAST))
+		return -EINVAL;
+
+	linfo = &ccs_limits[ccs_limit_offsets[limit].info];
+
+	if (WARN_ON(!sensor->ccs_limits) ||
+	    WARN_ON(offset + ccs_reg_width(linfo->reg) >
+		    ccs_limit_offsets[limit + 1].lim))
+		return -EINVAL;
+
+	*__ptr = sensor->ccs_limits + ccs_limit_offsets[limit].lim + offset;
+
+	return 0;
+}
+
+void ccs_replace_limit(struct smiapp_sensor *sensor,
+		       unsigned int limit, unsigned int offset, u32 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	const struct ccs_limit *linfo;
+	void *ptr;
+	int ret;
+
+	ret = ccs_limit_ptr(sensor, limit, offset, &ptr);
+	if (ret)
+		return;
+
+	linfo = &ccs_limits[ccs_limit_offsets[limit].info];
+
+	dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" %u = %d, 0x%x\n",
+		linfo->reg, linfo->name, offset, val, val);
+
+	ccs_assign_limit(ptr, ccs_reg_width(linfo->reg), val);
+}
+
+static u32 ccs_get_limit(struct smiapp_sensor *sensor,
+			 unsigned int limit, unsigned int offset)
+{
+	void *ptr;
+	int ret;
+
+	ret = ccs_limit_ptr(sensor, limit, offset, &ptr);
+	if (ret)
+		return 0;
+
+	switch (ccs_reg_width(ccs_limits[ccs_limit_offsets[limit].info].reg)) {
+	case sizeof(u8):
+		return *(u8 *)ptr;
+	case sizeof(u16):
+		return *(u16 *)ptr;
+	case sizeof(u32):
+		return *(u32 *)ptr;
+	}
+
+	WARN_ON(1);
+
+	return 0;
+}
+
+#define CCS_LIM(sensor, limit) \
+	ccs_get_limit(sensor, CCS_L_##limit, 0)
+
+#define CCS_LIM_AT(sensor, limit, offset)	\
+	ccs_get_limit(sensor, CCS_L_##limit, CCS_L_##limit##_OFFSET(offset))
+
+static int ccs_read_all_limits(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	void *ptr, *alloc, *end;
+	unsigned int i, l;
+	int ret;
+
+	kfree(sensor->ccs_limits);
+	sensor->ccs_limits = NULL;
+
+	alloc = kzalloc(ccs_limit_offsets[CCS_L_LAST].lim, GFP_KERNEL);
+	if (!alloc)
+		return -ENOMEM;
+
+	end = alloc + ccs_limit_offsets[CCS_L_LAST].lim;
+
+	for (i = 0, l = 0, ptr = alloc; ccs_limits[i].size; i++) {
+		u32 reg = ccs_limits[i].reg;
+		unsigned int width = ccs_reg_width(reg);
+		unsigned int j;
+
+		if (l == CCS_L_LAST) {
+			dev_err(&client->dev,
+				"internal error --- end of limit array\n");
+			ret = -EINVAL;
+			goto out_err;
+		}
+
+		for (j = 0; j < ccs_limits[i].size / width;
+		     j++, reg += width, ptr += width) {
+			u32 val;
+
+			ret = smiapp_read(sensor, reg, &val);
+			if (ret)
+				goto out_err;
+
+			if (ptr + width > end) {
+				dev_err(&client->dev,
+					"internal error --- no room for regs\n");
+				ret = -EINVAL;
+				goto out_err;
+			}
+
+			ccs_assign_limit(ptr, width, val);
+
+			dev_dbg(&client->dev, "0x%8.8x \"%s\" = %u, 0x%x\n",
+				reg, ccs_limits[i].name, val, val);
+		}
+
+		if (ccs_limits[i].flags & CCS_L_FL_SAME_REG)
+			continue;
+
+		l++;
+		ptr = alloc + ccs_limit_offsets[l].lim;
+	}
+
+	if (l != CCS_L_LAST) {
+		dev_err(&client->dev,
+			"internal error --- insufficient limits\n");
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	sensor->ccs_limits = alloc;
+
+	return 0;
+
+out_err:
+	kfree(alloc);
+
+	return ret;
+}
+
 static int smiapp_read_frame_fmt(struct smiapp_sensor *sensor)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
@@ -2970,10 +3129,14 @@ static int smiapp_probe(struct i2c_client *client)
 		goto out_power_off;
 	}
 
+	rval = ccs_read_all_limits(sensor);
+	if (rval)
+		goto out_power_off;
+
 	rval = smiapp_read_frame_fmt(sensor);
 	if (rval) {
 		rval = -ENODEV;
-		goto out_power_off;
+		goto out_free_ccs_limits;
 	}
 
 	/*
@@ -2997,7 +3160,7 @@ static int smiapp_probe(struct i2c_client *client)
 	rval = smiapp_call_quirk(sensor, limits);
 	if (rval) {
 		dev_err(&client->dev, "limits quirks failed\n");
-		goto out_power_off;
+		goto out_free_ccs_limits;
 	}
 
 	if (SMIA_LIM(sensor, BINNING_CAPABILITY)) {
@@ -3007,7 +3170,7 @@ static int smiapp_probe(struct i2c_client *client)
 				   SMIAPP_REG_U8_BINNING_SUBTYPES, &val);
 		if (rval < 0) {
 			rval = -ENODEV;
-			goto out_power_off;
+			goto out_free_ccs_limits;
 		}
 		sensor->nbinning_subtypes = min_t(u8, val,
 						  SMIAPP_BINNING_SUBTYPES);
@@ -3017,7 +3180,7 @@ static int smiapp_probe(struct i2c_client *client)
 				sensor, SMIAPP_REG_U8_BINNING_TYPE_n(i), &val);
 			if (rval < 0) {
 				rval = -ENODEV;
-				goto out_power_off;
+				goto out_free_ccs_limits;
 			}
 			sensor->binning_subtypes[i] =
 				*(struct smiapp_binning_subtype *)&val;
@@ -3033,7 +3196,7 @@ static int smiapp_probe(struct i2c_client *client)
 	if (device_create_file(&client->dev, &dev_attr_ident) != 0) {
 		dev_err(&client->dev, "sysfs ident entry creation failed\n");
 		rval = -ENOENT;
-		goto out_power_off;
+		goto out_free_ccs_limits;
 	}
 
 	if (sensor->minfo.smiapp_version &&
@@ -3150,6 +3313,9 @@ static int smiapp_probe(struct i2c_client *client)
 out_cleanup:
 	smiapp_cleanup(sensor);
 
+out_free_ccs_limits:
+	kfree(sensor->ccs_limits);
+
 out_power_off:
 	smiapp_power_off(&client->dev);
 	mutex_destroy(&sensor->mutex);
@@ -3176,6 +3342,7 @@ static int smiapp_remove(struct i2c_client *client)
 	}
 	smiapp_cleanup(sensor);
 	mutex_destroy(&sensor->mutex);
+	kfree(sensor->ccs_limits);
 
 	return 0;
 }
diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h
index b1d0e3d71630..08ca1b3d1b2f 100644
--- a/drivers/media/i2c/smiapp/smiapp.h
+++ b/drivers/media/i2c/smiapp/smiapp.h
@@ -228,6 +228,7 @@ struct smiapp_sensor {
 	struct clk *ext_clk;
 	struct gpio_desc *xshutdown;
 	u32 limits[SMIAPP_LIMIT_LAST];
+	void *ccs_limits;
 	u8 nbinning_subtypes;
 	struct smiapp_binning_subtype binning_subtypes[SMIAPP_BINNING_SUBTYPES];
 	u32 mbus_frame_fmts;
@@ -281,4 +282,7 @@ struct smiapp_sensor {
 #define to_smiapp_sensor(_sd)	\
 	(to_smiapp_subdev(_sd)->sensor)
 
+void ccs_replace_limit(struct smiapp_sensor *sensor,
+		       unsigned int limit, unsigned int offset, u32 val);
+
 #endif /* __SMIAPP_PRIV_H_ */
-- 
2.27.0


  parent reply	other threads:[~2020-11-27 10:38 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-27 10:32 [PATCH v2 00/29] Linux CCS driver preparation Sakari Ailus
2020-11-27 10:32 ` [PATCH v2 01/29] ccs: Add the generator for CCS register definitions and limits Sakari Ailus
2020-12-02 14:17   ` Mauro Carvalho Chehab
2020-12-02 14:46     ` Sakari Ailus
2020-11-27 10:32 ` [PATCH v2 02/29] Documentation: ccs: Add CCS driver documentation Sakari Ailus
2020-11-27 10:32 ` [PATCH v2 03/29] smiapp: Import CCS definitions Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 04/29] smiapp: Use CCS register flags Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 05/29] smiapp: Calculate CCS limit offsets and limit buffer size Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 06/29] smiapp: Remove macros for defining registers, merge definitions Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 07/29] smiapp: Add macros for accessing CCS registers Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 08/29] smiapp: Use MIPI CCS version and manufacturer ID information Sakari Ailus
2020-11-27 10:33 ` Sakari Ailus [this message]
2020-11-27 10:33 ` [PATCH v2 10/29] smiapp: Switch to CCS limits Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 11/29] smiapp: Obtain frame descriptor from " Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 12/29] smiapp: Use CCS limits in reading data format descriptors Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 13/29] smiapp: Use CCS limits in reading binning capabilities Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 14/29] smiapp: Use CCS registers Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 15/29] smiapp: Remove quirk function for writing a single 8-bit register Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 16/29] smiapp: Rename register access functions Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 17/29] smiapp: Internal rename to CCS Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 18/29] smiapp: Differentiate CCS sensors from SMIA in subdev naming Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 19/29] smiapp: Rename as "ccs" Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 20/29] ccs: Remove profile concept Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 21/29] ccs: Give all subdevs a function Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 22/29] dt-bindings: nokia,smia: Fix link-frequencies documentation Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 23/29] dt-bindings: nokia,smia: Make vana-supply optional Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 24/29] dt-bindings: nokia,smia: Remove nokia,nvm-size property Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 25/29] dt-bindings: nokia,smia: Convert to YAML Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 26/29] dt-bindings: nokia,smia: Use better active polarity for reset Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 27/29] dt-bindings: nokia,smia: Amend SMIA bindings with MIPI CCS support Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 28/29] dt-bindings: mipi-ccs: Add bus-type for C-PHY support Sakari Ailus
2020-11-27 10:33 ` [PATCH v2 29/29] ccs: Request for "reset" GPIO Sakari Ailus

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201127103325.29814-10-sakari.ailus@linux.intel.com \
    --to=sakari.ailus@linux.intel.com \
    --cc=hverkuil@xs4all.nl \
    --cc=linux-media@vger.kernel.org \
    --cc=mchehab@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.