All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes
@ 2014-04-14  8:58 Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 01/21] smiapp: Remove unused quirk register functionality Sakari Ailus
                   ` (20 more replies)
  0 siblings, 21 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

Hi folks,                                                                       

This is the second version of the smiapp and smiapp-pll quirk improvement
patchset. The first version can be found here:

<URL:http://www.spinics.net/lists/linux-media/msg75538.html>

Changes since v1:

- Fix a compiler warning in smiapp-pll.c added by the patch changing limits
  to 64 bits.

- Add a patch that contains macros to access register address, width and
  flags (smiapp: Define macros for obtaining properties of register
  definitions).

- Add a patch to remove the old register quirks (smiapp: Remove unused quirk
  register functionality).

- Make register diversion quirk more generic. Access can be now avoided
  altogether; up to the quirk implementation. Quirk functions can perform
  further register accesses. Additional functions are provided for quirk
  functions to avoid checking for further quirks (no quirks for quirks).

- Add a patch to rename smia prefix still used somehwere as smiapp for
  consistency.

This patchset contains PLL quirk improvements to take quirks in some            
implementations into account, as well as make the quirk mechanisms more         
flexible. The driver core is mostly unaffected by these changes.                
                                                                                
The PLL tree calculation itself is concerned less with the factual              
frequencies but focuses on producing multipliers and dividers that are valid    
for the hardware. Quirk flags are primarily used to convert input and output    
parameters.                                                                     
                                                                                
The limit values are also made 64 bits; 64-bit values are needed in more        
generic case when floating point numbers are converted to fixed point.          
                                                                                
There are some miscellaneous fixes as well.                                     


-- 
Kind regards,
Sakari


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v2 01/21] smiapp: Remove unused quirk register functionality
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 02/21] smiapp: Rename SMIA_REG to SMIAPP_REG for consistency Sakari Ailus
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

The quirk registers mechanism which allows register to have a static read
access value from the sensor specific quirks, is not used. Remove it. It is
to be replaced by a more generic register diversion quirk soon.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp/smiapp-quirk.c | 46 ---------------------------------
 drivers/media/i2c/smiapp/smiapp-quirk.h | 10 -------
 drivers/media/i2c/smiapp/smiapp-regs.c  |  4 ---
 drivers/media/i2c/smiapp/smiapp-regs.h  |  5 ----
 4 files changed, 65 deletions(-)

diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index bb8c506..4955289 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -61,52 +61,6 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor,
 	sensor->limits[limit] = val;
 }
 
-bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
-		      u32 reg, u32 *val)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-	const struct smia_reg *sreg;
-
-	if (!sensor->minfo.quirk)
-		return false;
-
-	sreg = sensor->minfo.quirk->regs;
-
-	if (!sreg)
-		return false;
-
-	while (sreg->type) {
-		u16 type = reg >> 16;
-		u16 reg16 = reg;
-
-		if (sreg->type != type || sreg->reg != reg16) {
-			sreg++;
-			continue;
-		}
-
-		switch ((u8)type) {
-		case SMIA_REG_8BIT:
-			dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%2.2x\n",
-				reg, sreg->val);
-			break;
-		case SMIA_REG_16BIT:
-			dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%4.4x\n",
-				reg, sreg->val);
-			break;
-		case SMIA_REG_32BIT:
-			dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%8.8x\n",
-				reg, sreg->val);
-			break;
-		}
-
-		*val = sreg->val;
-
-		return true;
-	}
-
-	return false;
-}
-
 static int jt8ew9_limits(struct smiapp_sensor *sensor)
 {
 	if (sensor->minfo.revision_number_major < 0x03)
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index 504a6d8..4f65c4e 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -41,7 +41,6 @@ struct smiapp_quirk {
 	int (*post_poweron)(struct smiapp_sensor *sensor);
 	int (*pre_streamon)(struct smiapp_sensor *sensor);
 	int (*post_streamoff)(struct smiapp_sensor *sensor);
-	const struct smia_reg *regs;
 	unsigned long flags;
 };
 
@@ -56,15 +55,6 @@ struct smiapp_reg_8 {
 
 void smiapp_replace_limit(struct smiapp_sensor *sensor,
 			  u32 limit, u32 val);
-bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
-		      u32 reg, u32 *val);
-
-#define SMIAPP_MK_QUIRK_REG(_reg, _val) \
-	{				\
-		.type = (_reg >> 16),	\
-		.reg = (u16)_reg,	\
-		.val = _val,		\
-	}
 
 #define smiapp_call_quirk(_sensor, _quirk, ...)				\
 	(_sensor->minfo.quirk &&					\
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index 4fac32c..e01644c 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -172,9 +172,6 @@ static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
 	    && len != SMIA_REG_32BIT)
 		return -EINVAL;
 
-	if (smiapp_quirk_reg(sensor, reg, val))
-		goto found_quirk;
-
 	if (len == SMIA_REG_8BIT && !only8)
 		rval = ____smiapp_read(sensor, (u16)reg, len, val);
 	else
@@ -182,7 +179,6 @@ static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
 	if (rval < 0)
 		return rval;
 
-found_quirk:
 	if (reg & SMIA_REG_FLAG_FLOAT)
 		*val = float_to_u32_mul_1000000(client, *val);
 
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h
index eefc6c8..e07b30c 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.h
+++ b/drivers/media/i2c/smiapp/smiapp-regs.h
@@ -34,11 +34,6 @@
 #define SMIA_REG_8BIT			1
 #define SMIA_REG_16BIT			2
 #define SMIA_REG_32BIT			4
-struct smia_reg {
-	u16 type;
-	u16 reg;			/* 16-bit offset */
-	u32 val;			/* 8/16/32-bit value */
-};
 
 struct smiapp_sensor;
 
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 02/21] smiapp: Rename SMIA_REG to SMIAPP_REG for consistency
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 01/21] smiapp: Remove unused quirk register functionality Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 03/21] smiapp: Fix determining the need for 8-bit read access Sakari Ailus
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

SMIAPP_REG_ is the common prefix used in the driver for register related
definitions. Use it consistently.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp/smiapp-quirk.c    |  2 +-
 drivers/media/i2c/smiapp/smiapp-reg-defs.h |  8 ++++----
 drivers/media/i2c/smiapp/smiapp-regs.c     | 24 ++++++++++++------------
 drivers/media/i2c/smiapp/smiapp-regs.h     |  8 ++++----
 4 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index 4955289..06a0c21 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -28,7 +28,7 @@
 
 static int smiapp_write_8(struct smiapp_sensor *sensor, u16 reg, u8 val)
 {
-	return smiapp_write(sensor, (SMIA_REG_8BIT << 16) | reg, val);
+	return smiapp_write(sensor, SMIAPP_REG_MK_U8(reg), val);
 }
 
 static int smiapp_write_8s(struct smiapp_sensor *sensor,
diff --git a/drivers/media/i2c/smiapp/smiapp-reg-defs.h b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
index 3aa0ca9..c488ef0 100644
--- a/drivers/media/i2c/smiapp/smiapp-reg-defs.h
+++ b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
@@ -21,11 +21,11 @@
  * 02110-1301 USA
  *
  */
-#define SMIAPP_REG_MK_U8(r) ((SMIA_REG_8BIT << 16) | (r))
-#define SMIAPP_REG_MK_U16(r) ((SMIA_REG_16BIT << 16) | (r))
-#define SMIAPP_REG_MK_U32(r) ((SMIA_REG_32BIT << 16) | (r))
+#define SMIAPP_REG_MK_U8(r) ((SMIAPP_REG_8BIT << 16) | (r))
+#define SMIAPP_REG_MK_U16(r) ((SMIAPP_REG_16BIT << 16) | (r))
+#define SMIAPP_REG_MK_U32(r) ((SMIAPP_REG_32BIT << 16) | (r))
 
-#define SMIAPP_REG_MK_F32(r) (SMIA_REG_FLAG_FLOAT | (SMIA_REG_32BIT << 16) | (r))
+#define SMIAPP_REG_MK_F32(r) (SMIAPP_REG_FLAG_FLOAT | (SMIAPP_REG_32BIT << 16) | (r))
 
 #define SMIAPP_REG_U16_MODEL_ID					SMIAPP_REG_MK_U16(0x0000)
 #define SMIAPP_REG_U8_REVISION_NUMBER_MAJOR			SMIAPP_REG_MK_U8(0x0002)
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index e01644c..5d0151a 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -114,14 +114,14 @@ static int ____smiapp_read(struct smiapp_sensor *sensor, u16 reg,
 	*val = 0;
 	/* high byte comes first */
 	switch (len) {
-	case SMIA_REG_32BIT:
+	case SMIAPP_REG_32BIT:
 		*val = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) +
 			data[3];
 		break;
-	case SMIA_REG_16BIT:
+	case SMIAPP_REG_16BIT:
 		*val = (data[0] << 8) + data[1];
 		break;
-	case SMIA_REG_8BIT:
+	case SMIAPP_REG_8BIT:
 		*val = data[0];
 		break;
 	default:
@@ -168,18 +168,18 @@ static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
 	unsigned int len = (u8)(reg >> 16);
 	int rval;
 
-	if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
-	    && len != SMIA_REG_32BIT)
+	if (len != SMIAPP_REG_8BIT && len != SMIAPP_REG_16BIT
+	    && len != SMIAPP_REG_32BIT)
 		return -EINVAL;
 
-	if (len == SMIA_REG_8BIT && !only8)
+	if (len == SMIAPP_REG_8BIT && !only8)
 		rval = ____smiapp_read(sensor, (u16)reg, len, val);
 	else
 		rval = ____smiapp_read_8only(sensor, (u16)reg, len, val);
 	if (rval < 0)
 		return rval;
 
-	if (reg & SMIA_REG_FLAG_FLOAT)
+	if (reg & SMIAPP_REG_FLAG_FLOAT)
 		*val = float_to_u32_mul_1000000(client, *val);
 
 	return 0;
@@ -213,8 +213,8 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
 	u16 offset = reg;
 	int r;
 
-	if ((len != SMIA_REG_8BIT && len != SMIA_REG_16BIT &&
-	     len != SMIA_REG_32BIT) || flags)
+	if ((len != SMIAPP_REG_8BIT && len != SMIAPP_REG_16BIT &&
+	     len != SMIAPP_REG_32BIT) || flags)
 		return -EINVAL;
 
 	msg.addr = client->addr;
@@ -227,14 +227,14 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
 	data[1] = (u8) (reg & 0xff);
 
 	switch (len) {
-	case SMIA_REG_8BIT:
+	case SMIAPP_REG_8BIT:
 		data[2] = val;
 		break;
-	case SMIA_REG_16BIT:
+	case SMIAPP_REG_16BIT:
 		data[2] = val >> 8;
 		data[3] = val;
 		break;
-	case SMIA_REG_32BIT:
+	case SMIAPP_REG_32BIT:
 		data[2] = val >> 24;
 		data[3] = val >> 16;
 		data[4] = val >> 8;
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h
index e07b30c..934130b 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.h
+++ b/drivers/media/i2c/smiapp/smiapp-regs.h
@@ -29,11 +29,11 @@
 #include <linux/types.h>
 
 /* Use upper 8 bits of the type field for flags */
-#define SMIA_REG_FLAG_FLOAT		(1 << 24)
+#define SMIAPP_REG_FLAG_FLOAT		(1 << 24)
 
-#define SMIA_REG_8BIT			1
-#define SMIA_REG_16BIT			2
-#define SMIA_REG_32BIT			4
+#define SMIAPP_REG_8BIT			1
+#define SMIAPP_REG_16BIT		2
+#define SMIAPP_REG_32BIT		4
 
 struct smiapp_sensor;
 
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 03/21] smiapp: Fix determining the need for 8-bit read access
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 01/21] smiapp: Remove unused quirk register functionality Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 02/21] smiapp: Rename SMIA_REG to SMIAPP_REG for consistency Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 04/21] smiapp: Add a macro for constructing 8-bit quirk registers Sakari Ailus
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

8-bit reads are needed in some cases; however the condition used was wrong.
Regular access (register width) was used if:

	len == SMIAPP_REG_8BIT && !only8

This causes 8-bit read access to be used always. The operator should be ||
instead: regular access can be used for 8-bit reads OR if allowed otherwise.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp/smiapp-regs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index 5d0151a..c2db205 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -172,7 +172,7 @@ static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
 	    && len != SMIAPP_REG_32BIT)
 		return -EINVAL;
 
-	if (len == SMIAPP_REG_8BIT && !only8)
+	if (len == SMIAPP_REG_8BIT || !only8)
 		rval = ____smiapp_read(sensor, (u16)reg, len, val);
 	else
 		rval = ____smiapp_read_8only(sensor, (u16)reg, len, val);
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 04/21] smiapp: Add a macro for constructing 8-bit quirk registers
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (2 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 03/21] smiapp: Fix determining the need for 8-bit read access Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 05/21] smiapp: Use I2C adapter ID and address in the sub-device name Sakari Ailus
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp/smiapp-quirk.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index 4f65c4e..96a253e 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -56,6 +56,12 @@ struct smiapp_reg_8 {
 void smiapp_replace_limit(struct smiapp_sensor *sensor,
 			  u32 limit, u32 val);
 
+#define SMIAPP_MK_QUIRK_REG_8(_reg, _val) \
+	{				\
+		.reg = (u16)_reg,	\
+		.val = _val,		\
+	}
+
 #define smiapp_call_quirk(_sensor, _quirk, ...)				\
 	(_sensor->minfo.quirk &&					\
 	 _sensor->minfo.quirk->_quirk ?					\
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 05/21] smiapp: Use I2C adapter ID and address in the sub-device name
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (3 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 04/21] smiapp: Add a macro for constructing 8-bit quirk registers Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 06/21] smiapp: Make PLL flags separate from regular quirk flags Sakari Ailus
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

The sub-device names should be unique. Should two identical sensors be
present in the same media device they would be indistinguishable. The names
will change e.g. from "vs6555 pixel array" to "vs6555 1-0010 pixel array".

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

diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 8741cae..69c11ec 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -2543,8 +2543,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 		}
 
 		snprintf(this->sd.name,
-			 sizeof(this->sd.name), "%s %s",
-			 sensor->minfo.name, _this->name);
+			 sizeof(this->sd.name), "%s %d-%4.4x %s",
+			 sensor->minfo.name, i2c_adapter_id(client->adapter),
+			 client->addr, _this->name);
 
 		this->sink_fmt.width =
 			sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 06/21] smiapp: Make PLL flags separate from regular quirk flags
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (4 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 05/21] smiapp: Use I2C adapter ID and address in the sub-device name Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 07/21] smiapp: Make PLL flags unsigned long Sakari Ailus
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

It doesn't make sense to just copy the information to the PLL flags. Add a
new fields for the quirks to contain the PLL flags.

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

diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 69c11ec..23f2c4d 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -2617,12 +2617,11 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 	pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
 	pll->csi2.lanes = sensor->platform_data->lanes;
 	pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
+	if (sensor->minfo.quirk)
+		pll->flags = sensor->minfo.quirk->pll_flags;
 	/* Profile 0 sensors have no separate OP clock branch. */
 	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
 		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
-	if (smiapp_needs_quirk(sensor,
-			       SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
-		pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
 	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
 
 	rval = smiapp_update_mode(sensor);
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index 06a0c21..bd2f8a7 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -225,7 +225,7 @@ const struct smiapp_quirk smiapp_jt8ev1_quirk = {
 	.post_poweron = jt8ev1_post_poweron,
 	.pre_streamon = jt8ev1_pre_streamon,
 	.post_streamoff = jt8ev1_post_streamoff,
-	.flags = SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE,
+	.pll_flags = SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE,
 };
 
 static int tcm8500md_limits(struct smiapp_sensor *sensor)
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index 96a253e..ea8231c6 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -42,11 +42,10 @@ struct smiapp_quirk {
 	int (*pre_streamon)(struct smiapp_sensor *sensor);
 	int (*post_streamoff)(struct smiapp_sensor *sensor);
 	unsigned long flags;
+	unsigned long pll_flags;
 };
 
-/* op pix clock is for all lanes in total normally */
-#define SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE			(1 << 0)
-#define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY			(1 << 1)
+#define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY			(1 << 0)
 
 struct smiapp_reg_8 {
 	u16 reg;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 07/21] smiapp: Make PLL flags unsigned long
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (5 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 06/21] smiapp: Make PLL flags separate from regular quirk flags Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 08/21] smiapp: Make PLL (quirk) flags a function Sakari Ailus
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

No reason to keep this u8, really.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp-pll.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index a4a6498..5ce2b61 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -46,7 +46,7 @@ struct smiapp_pll {
 			uint8_t bus_width;
 		} parallel;
 	};
-	uint8_t flags;
+	unsigned long flags;
 	uint8_t binning_horizontal;
 	uint8_t binning_vertical;
 	uint8_t scale_m;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 08/21] smiapp: Make PLL (quirk) flags a function
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (6 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 07/21] smiapp: Make PLL flags unsigned long Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 09/21] smiapp: Use %u for printing u32 value Sakari Ailus
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

This is more flexible. Quirk flags may be affected by configuration.

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

diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 23f2c4d..02041cc 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -2617,8 +2617,8 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 	pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
 	pll->csi2.lanes = sensor->platform_data->lanes;
 	pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
-	if (sensor->minfo.quirk)
-		pll->flags = sensor->minfo.quirk->pll_flags;
+	pll->flags = smiapp_call_quirk(sensor, pll_flags);
+
 	/* Profile 0 sensors have no separate OP clock branch. */
 	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
 		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index bd2f8a7..e0bee87 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -220,12 +220,17 @@ static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor)
 	return smiapp_write_8(sensor, 0x3328, 0x80);
 }
 
+static unsigned long jt8ev1_pll_flags(struct smiapp_sensor *sensor)
+{
+	return SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
+}
+
 const struct smiapp_quirk smiapp_jt8ev1_quirk = {
 	.limits = jt8ev1_limits,
 	.post_poweron = jt8ev1_post_poweron,
 	.pre_streamon = jt8ev1_pre_streamon,
 	.post_streamoff = jt8ev1_post_streamoff,
-	.pll_flags = SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE,
+	.pll_flags = jt8ev1_pll_flags,
 };
 
 static int tcm8500md_limits(struct smiapp_sensor *sensor)
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index ea8231c6..dddb62b 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -41,8 +41,8 @@ struct smiapp_quirk {
 	int (*post_poweron)(struct smiapp_sensor *sensor);
 	int (*pre_streamon)(struct smiapp_sensor *sensor);
 	int (*post_streamoff)(struct smiapp_sensor *sensor);
+	unsigned long (*pll_flags)(struct smiapp_sensor *sensor);
 	unsigned long flags;
-	unsigned long pll_flags;
 };
 
 #define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY			(1 << 0)
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 09/21] smiapp: Use %u for printing u32 value
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (7 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 08/21] smiapp: Make PLL (quirk) flags a function Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 10/21] smiapp-pll: Correct clock debug prints Sakari Ailus
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp/smiapp-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 02041cc..3af8df8 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -606,7 +606,7 @@ static int smiapp_get_limits(struct smiapp_sensor *sensor, int const *limit,
 		if (rval)
 			return rval;
 		sensor->limits[limit[i]] = val;
-		dev_dbg(&client->dev, "0x%8.8x \"%s\" = %d, 0x%x\n",
+		dev_dbg(&client->dev, "0x%8.8x \"%s\" = %u, 0x%x\n",
 			smiapp_reg_limits[limit[i]].addr,
 			smiapp_reg_limits[limit[i]].what, val, val);
 	}
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 10/21] smiapp-pll: Correct clock debug prints
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (8 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 09/21] smiapp: Use %u for printing u32 value Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 11/21] smiapp-pll: The clock tree values are unsigned --- fix " Sakari Ailus
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

The PLL flags were not used correctly.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp-pll.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index 2335529..ab5d9a3 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -67,7 +67,7 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll)
 {
 	dev_dbg(dev, "pre_pll_clk_div\t%d\n",  pll->pre_pll_clk_div);
 	dev_dbg(dev, "pll_multiplier \t%d\n",  pll->pll_multiplier);
-	if (pll->flags != SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+	if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
 		dev_dbg(dev, "op_sys_clk_div \t%d\n", pll->op_sys_clk_div);
 		dev_dbg(dev, "op_pix_clk_div \t%d\n", pll->op_pix_clk_div);
 	}
@@ -77,7 +77,7 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll)
 	dev_dbg(dev, "ext_clk_freq_hz \t%d\n", pll->ext_clk_freq_hz);
 	dev_dbg(dev, "pll_ip_clk_freq_hz \t%d\n", pll->pll_ip_clk_freq_hz);
 	dev_dbg(dev, "pll_op_clk_freq_hz \t%d\n", pll->pll_op_clk_freq_hz);
-	if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+	if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
 		dev_dbg(dev, "op_sys_clk_freq_hz \t%d\n",
 			pll->op_sys_clk_freq_hz);
 		dev_dbg(dev, "op_pix_clk_freq_hz \t%d\n",
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 11/21] smiapp-pll: The clock tree values are unsigned --- fix debug prints
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (9 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 10/21] smiapp-pll: Correct clock debug prints Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 12/21] smiapp: Limits can be 64 bits Sakari Ailus
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

These values are unsigned, so use %u instead of %d.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp-pll.c | 94 +++++++++++++++++++++---------------------
 1 file changed, 47 insertions(+), 47 deletions(-)

diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index ab5d9a3..d14af5c 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -65,26 +65,26 @@ static int bounds_check(struct device *dev, uint32_t val,
 
 static void print_pll(struct device *dev, struct smiapp_pll *pll)
 {
-	dev_dbg(dev, "pre_pll_clk_div\t%d\n",  pll->pre_pll_clk_div);
-	dev_dbg(dev, "pll_multiplier \t%d\n",  pll->pll_multiplier);
+	dev_dbg(dev, "pre_pll_clk_div\t%u\n",  pll->pre_pll_clk_div);
+	dev_dbg(dev, "pll_multiplier \t%u\n",  pll->pll_multiplier);
 	if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
-		dev_dbg(dev, "op_sys_clk_div \t%d\n", pll->op_sys_clk_div);
-		dev_dbg(dev, "op_pix_clk_div \t%d\n", pll->op_pix_clk_div);
+		dev_dbg(dev, "op_sys_clk_div \t%u\n", pll->op_sys_clk_div);
+		dev_dbg(dev, "op_pix_clk_div \t%u\n", pll->op_pix_clk_div);
 	}
-	dev_dbg(dev, "vt_sys_clk_div \t%d\n",  pll->vt_sys_clk_div);
-	dev_dbg(dev, "vt_pix_clk_div \t%d\n",  pll->vt_pix_clk_div);
+	dev_dbg(dev, "vt_sys_clk_div \t%u\n",  pll->vt_sys_clk_div);
+	dev_dbg(dev, "vt_pix_clk_div \t%u\n",  pll->vt_pix_clk_div);
 
-	dev_dbg(dev, "ext_clk_freq_hz \t%d\n", pll->ext_clk_freq_hz);
-	dev_dbg(dev, "pll_ip_clk_freq_hz \t%d\n", pll->pll_ip_clk_freq_hz);
-	dev_dbg(dev, "pll_op_clk_freq_hz \t%d\n", pll->pll_op_clk_freq_hz);
+	dev_dbg(dev, "ext_clk_freq_hz \t%u\n", pll->ext_clk_freq_hz);
+	dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->pll_ip_clk_freq_hz);
+	dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->pll_op_clk_freq_hz);
 	if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
-		dev_dbg(dev, "op_sys_clk_freq_hz \t%d\n",
+		dev_dbg(dev, "op_sys_clk_freq_hz \t%u\n",
 			pll->op_sys_clk_freq_hz);
-		dev_dbg(dev, "op_pix_clk_freq_hz \t%d\n",
+		dev_dbg(dev, "op_pix_clk_freq_hz \t%u\n",
 			pll->op_pix_clk_freq_hz);
 	}
-	dev_dbg(dev, "vt_sys_clk_freq_hz \t%d\n", pll->vt_sys_clk_freq_hz);
-	dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz);
+	dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt_sys_clk_freq_hz);
+	dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt_pix_clk_freq_hz);
 }
 
 /*
@@ -123,11 +123,11 @@ static int __smiapp_pll_calculate(struct device *dev,
 	 * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
 	 * too high.
 	 */
-	dev_dbg(dev, "pre_pll_clk_div %d\n", pll->pre_pll_clk_div);
+	dev_dbg(dev, "pre_pll_clk_div %u\n", pll->pre_pll_clk_div);
 
 	/* Don't go above max pll multiplier. */
 	more_mul_max = limits->max_pll_multiplier / mul;
-	dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %d\n",
+	dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %u\n",
 		more_mul_max);
 	/* Don't go above max pll op frequency. */
 	more_mul_max =
@@ -135,30 +135,30 @@ static int __smiapp_pll_calculate(struct device *dev,
 		      more_mul_max,
 		      limits->max_pll_op_freq_hz
 		      / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
-	dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %d\n",
+	dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %u\n",
 		more_mul_max);
 	/* Don't go above the division capability of op sys clock divider. */
 	more_mul_max = min(more_mul_max,
 			   limits->op.max_sys_clk_div * pll->pre_pll_clk_div
 			   / div);
-	dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %d\n",
+	dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n",
 		more_mul_max);
 	/* Ensure we won't go above min_pll_multiplier. */
 	more_mul_max = min(more_mul_max,
 			   DIV_ROUND_UP(limits->max_pll_multiplier, mul));
-	dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %d\n",
+	dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n",
 		more_mul_max);
 
 	/* Ensure we won't go below min_pll_op_freq_hz. */
 	more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz,
 				    pll->ext_clk_freq_hz / pll->pre_pll_clk_div
 				    * mul);
-	dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %d\n",
+	dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %u\n",
 		more_mul_min);
 	/* Ensure we won't go below min_pll_multiplier. */
 	more_mul_min = max(more_mul_min,
 			   DIV_ROUND_UP(limits->min_pll_multiplier, mul));
-	dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %d\n",
+	dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %u\n",
 		more_mul_min);
 
 	if (more_mul_min > more_mul_max) {
@@ -168,23 +168,23 @@ static int __smiapp_pll_calculate(struct device *dev,
 	}
 
 	more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
-	dev_dbg(dev, "more_mul_factor: %d\n", more_mul_factor);
+	dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor);
 	more_mul_factor = lcm(more_mul_factor, limits->op.min_sys_clk_div);
-	dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
+	dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %u\n",
 		more_mul_factor);
 	i = roundup(more_mul_min, more_mul_factor);
 	if (!is_one_or_even(i))
 		i <<= 1;
 
-	dev_dbg(dev, "final more_mul: %d\n", i);
+	dev_dbg(dev, "final more_mul: %u\n", i);
 	if (i > more_mul_max) {
-		dev_dbg(dev, "final more_mul is bad, max %d\n", more_mul_max);
+		dev_dbg(dev, "final more_mul is bad, max %u\n", more_mul_max);
 		return -EINVAL;
 	}
 
 	pll->pll_multiplier = mul * i;
 	pll->op_sys_clk_div = div * i / pll->pre_pll_clk_div;
-	dev_dbg(dev, "op_sys_clk_div: %d\n", pll->op_sys_clk_div);
+	dev_dbg(dev, "op_sys_clk_div: %u\n", pll->op_sys_clk_div);
 
 	pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz
 		/ pll->pre_pll_clk_div;
@@ -197,7 +197,7 @@ static int __smiapp_pll_calculate(struct device *dev,
 		pll->pll_op_clk_freq_hz / pll->op_sys_clk_div;
 
 	pll->op_pix_clk_div = pll->bits_per_pixel;
-	dev_dbg(dev, "op_pix_clk_div: %d\n", pll->op_pix_clk_div);
+	dev_dbg(dev, "op_pix_clk_div: %u\n", pll->op_pix_clk_div);
 
 	pll->op_pix_clk_freq_hz =
 		pll->op_sys_clk_freq_hz / pll->op_pix_clk_div;
@@ -214,7 +214,7 @@ static int __smiapp_pll_calculate(struct device *dev,
 		vt_op_binning_div = pll->binning_horizontal;
 	else
 		vt_op_binning_div = 1;
-	dev_dbg(dev, "vt_op_binning_div: %d\n", vt_op_binning_div);
+	dev_dbg(dev, "vt_op_binning_div: %u\n", vt_op_binning_div);
 
 	/*
 	 * Profile 2 supports vt_pix_clk_div E [4, 10]
@@ -227,30 +227,30 @@ static int __smiapp_pll_calculate(struct device *dev,
 	 *
 	 * Find absolute limits for the factor of vt divider.
 	 */
-	dev_dbg(dev, "scale_m: %d\n", pll->scale_m);
+	dev_dbg(dev, "scale_m: %u\n", pll->scale_m);
 	min_vt_div = DIV_ROUND_UP(pll->op_pix_clk_div * pll->op_sys_clk_div
 				  * pll->scale_n,
 				  lane_op_clock_ratio * vt_op_binning_div
 				  * pll->scale_m);
 
 	/* Find smallest and biggest allowed vt divisor. */
-	dev_dbg(dev, "min_vt_div: %d\n", min_vt_div);
+	dev_dbg(dev, "min_vt_div: %u\n", min_vt_div);
 	min_vt_div = max(min_vt_div,
 			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
 				      limits->vt.max_pix_clk_freq_hz));
-	dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %d\n",
+	dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n",
 		min_vt_div);
 	min_vt_div = max_t(uint32_t, min_vt_div,
 			   limits->vt.min_pix_clk_div
 			   * limits->vt.min_sys_clk_div);
-	dev_dbg(dev, "min_vt_div: min_vt_clk_div: %d\n", min_vt_div);
+	dev_dbg(dev, "min_vt_div: min_vt_clk_div: %u\n", min_vt_div);
 
 	max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
-	dev_dbg(dev, "max_vt_div: %d\n", max_vt_div);
+	dev_dbg(dev, "max_vt_div: %u\n", max_vt_div);
 	max_vt_div = min(max_vt_div,
 			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
 				      limits->vt.min_pix_clk_freq_hz));
-	dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %d\n",
+	dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n",
 		max_vt_div);
 
 	/*
@@ -258,28 +258,28 @@ static int __smiapp_pll_calculate(struct device *dev,
 	 * with all values of pix_clk_div.
 	 */
 	min_sys_div = limits->vt.min_sys_clk_div;
-	dev_dbg(dev, "min_sys_div: %d\n", min_sys_div);
+	dev_dbg(dev, "min_sys_div: %u\n", min_sys_div);
 	min_sys_div = max(min_sys_div,
 			  DIV_ROUND_UP(min_vt_div,
 				       limits->vt.max_pix_clk_div));
-	dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div);
+	dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div);
 	min_sys_div = max(min_sys_div,
 			  pll->pll_op_clk_freq_hz
 			  / limits->vt.max_sys_clk_freq_hz);
-	dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div);
+	dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div);
 	min_sys_div = clk_div_even_up(min_sys_div);
-	dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div);
+	dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div);
 
 	max_sys_div = limits->vt.max_sys_clk_div;
-	dev_dbg(dev, "max_sys_div: %d\n", max_sys_div);
+	dev_dbg(dev, "max_sys_div: %u\n", max_sys_div);
 	max_sys_div = min(max_sys_div,
 			  DIV_ROUND_UP(max_vt_div,
 				       limits->vt.min_pix_clk_div));
-	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %d\n", max_sys_div);
+	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div);
 	max_sys_div = min(max_sys_div,
 			  DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
 				       limits->vt.min_pix_clk_freq_hz));
-	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %d\n", max_sys_div);
+	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div);
 
 	/*
 	 * Find pix_div such that a legal pix_div * sys_div results
@@ -296,7 +296,7 @@ static int __smiapp_pll_calculate(struct device *dev,
 			if (pix_div < limits->vt.min_pix_clk_div
 			    || pix_div > limits->vt.max_pix_clk_div) {
 				dev_dbg(dev,
-					"pix_div %d too small or too big (%d--%d)\n",
+					"pix_div %u too small or too big (%u--%u)\n",
 					pix_div,
 					limits->vt.min_pix_clk_div,
 					limits->vt.max_pix_clk_div);
@@ -390,9 +390,9 @@ int smiapp_pll_calculate(struct device *dev,
 		lane_op_clock_ratio = pll->csi2.lanes;
 	else
 		lane_op_clock_ratio = 1;
-	dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
+	dev_dbg(dev, "lane_op_clock_ratio: %u\n", lane_op_clock_ratio);
 
-	dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
+	dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal,
 		pll->binning_vertical);
 
 	switch (pll->bus_type) {
@@ -411,7 +411,7 @@ int smiapp_pll_calculate(struct device *dev,
 	}
 
 	/* Figure out limits for pre-pll divider based on extclk */
-	dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
+	dev_dbg(dev, "min / max pre_pll_clk_div: %u / %u\n",
 		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
 	max_pre_pll_clk_div =
 		min_t(uint16_t, limits->max_pre_pll_clk_div,
@@ -422,20 +422,20 @@ int smiapp_pll_calculate(struct device *dev,
 		      clk_div_even_up(
 			      DIV_ROUND_UP(pll->ext_clk_freq_hz,
 					   limits->max_pll_ip_freq_hz)));
-	dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
+	dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %u / %u\n",
 		min_pre_pll_clk_div, max_pre_pll_clk_div);
 
 	i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
 	mul = div_u64(pll->pll_op_clk_freq_hz, i);
 	div = pll->ext_clk_freq_hz / i;
-	dev_dbg(dev, "mul %d / div %d\n", mul, div);
+	dev_dbg(dev, "mul %u / div %u\n", mul, div);
 
 	min_pre_pll_clk_div =
 		max_t(uint16_t, min_pre_pll_clk_div,
 		      clk_div_even_up(
 			      DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
 					   limits->max_pll_op_freq_hz)));
-	dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
+	dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %u / %u\n",
 		min_pre_pll_clk_div, max_pre_pll_clk_div);
 
 	for (pll->pre_pll_clk_div = min_pre_pll_clk_div;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 12/21] smiapp: Limits can be 64 bits
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (10 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 11/21] smiapp-pll: The clock tree values are unsigned --- fix " Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 13/21] smiapp-pll: Use 64-bit types limits Sakari Ailus
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

Limits may exceed the value range of 32 bit unsigned integers. Thus use 64
bits instead.

Use typed min/max/clamp macros. Debug printing changes as well.

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

diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 3af8df8..6d940f0 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -502,7 +502,8 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
 		V4L2_CID_ANALOGUE_GAIN,
 		sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN],
 		sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MAX],
-		max(sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_STEP], 1U),
+		max_t(uint32_t,
+		      sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_STEP], 1U),
 		sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN]);
 
 	/* Exposure limits will be updated soon, use just something here. */
@@ -679,7 +680,7 @@ static int smiapp_get_limits_binning(struct smiapp_sensor *sensor)
 
 	for (i = 0; i < ARRAY_SIZE(limits); i++) {
 		dev_dbg(&client->dev,
-			"replace limit 0x%8.8x \"%s\" = %d, 0x%x\n",
+			"replace limit 0x%8.8x \"%s\" = %llu, 0x%llx\n",
 			smiapp_reg_limits[limits[i]].addr,
 			smiapp_reg_limits[limits[i]].what,
 			sensor->limits[limits_replace[i]],
@@ -1689,13 +1690,13 @@ static int smiapp_set_format(struct v4l2_subdev *subdev,
 	fmt->format.height &= ~1;
 
 	fmt->format.width =
-		clamp(fmt->format.width,
-		      sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE],
-		      sensor->limits[SMIAPP_LIMIT_MAX_X_OUTPUT_SIZE]);
+		clamp_t(uint32_t, fmt->format.width,
+			sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE],
+			sensor->limits[SMIAPP_LIMIT_MAX_X_OUTPUT_SIZE]);
 	fmt->format.height =
-		clamp(fmt->format.height,
-		      sensor->limits[SMIAPP_LIMIT_MIN_Y_OUTPUT_SIZE],
-		      sensor->limits[SMIAPP_LIMIT_MAX_Y_OUTPUT_SIZE]);
+		clamp_t(uint32_t, fmt->format.height,
+			sensor->limits[SMIAPP_LIMIT_MIN_Y_OUTPUT_SIZE],
+			sensor->limits[SMIAPP_LIMIT_MAX_Y_OUTPUT_SIZE]);
 
 	smiapp_get_crop_compose(subdev, fh, crops, NULL, fmt->which);
 
@@ -1834,12 +1835,13 @@ static void smiapp_set_compose_scaler(struct v4l2_subdev *subdev,
 		* sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]
 		/ sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE];
 
-	a = clamp(a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN],
-		  sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]);
-	b = clamp(b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN],
-		  sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]);
-	max_m = clamp(max_m, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN],
-		      sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]);
+	a = clamp_t(uint32_t, a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN],
+		    sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]);
+	b = clamp_t(uint32_t, b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN],
+		    sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]);
+	max_m = clamp_t(uint32_t, max_m,
+			sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN],
+			sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]);
 
 	dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m);
 
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index e0bee87..108ea23 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -51,11 +51,11 @@ static int smiapp_write_8s(struct smiapp_sensor *sensor,
 }
 
 void smiapp_replace_limit(struct smiapp_sensor *sensor,
-			  u32 limit, u32 val)
+			  u32 limit, u64 val)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 
-	dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" = %d, 0x%x\n",
+	dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" = %llu, 0x%llx\n",
 		smiapp_reg_limits[limit].addr,
 		smiapp_reg_limits[limit].what, val, val);
 	sensor->limits[limit] = val;
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index dddb62b..b8b4087 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -53,7 +53,7 @@ struct smiapp_reg_8 {
 };
 
 void smiapp_replace_limit(struct smiapp_sensor *sensor,
-			  u32 limit, u32 val);
+			  u32 limit, u64 val);
 
 #define SMIAPP_MK_QUIRK_REG_8(_reg, _val) \
 	{				\
diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h
index 7cc5aae..0a26487 100644
--- a/drivers/media/i2c/smiapp/smiapp.h
+++ b/drivers/media/i2c/smiapp/smiapp.h
@@ -199,7 +199,7 @@ struct smiapp_sensor {
 	struct smiapp_platform_data *platform_data;
 	struct regulator *vana;
 	struct clk *ext_clk;
-	u32 limits[SMIAPP_LIMIT_LAST];
+	u64 limits[SMIAPP_LIMIT_LAST];
 	u8 nbinning_subtypes;
 	struct smiapp_binning_subtype binning_subtypes[SMIAPP_BINNING_SUBTYPES];
 	u32 mbus_frame_fmts;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 13/21] smiapp-pll: Use 64-bit types limits
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (11 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 12/21] smiapp: Limits can be 64 bits Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 14/21] smiapp-pll: Add support for odd pre-pll divisors Sakari Ailus
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

Limits may exceed the value range of 32-bit unsigned integers. Thus use 64
bits for all of them.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp-pll.c | 72 +++++++++++++++++++++++-------------------
 drivers/media/i2c/smiapp-pll.h | 20 ++++++------
 2 files changed, 50 insertions(+), 42 deletions(-)

diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index d14af5c..ec9f8bb 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -28,6 +28,11 @@
 
 #include "smiapp-pll.h"
 
+static inline uint64_t div_u64_round_up(uint64_t dividend, uint32_t divisor)
+{
+	return div_u64(dividend + divisor - 1, divisor);
+}
+
 /* Return an even number or one. */
 static inline uint32_t clk_div_even(uint32_t a)
 {
@@ -52,13 +57,14 @@ static inline uint32_t is_one_or_even(uint32_t a)
 	return 1;
 }
 
-static int bounds_check(struct device *dev, uint32_t val,
-			uint32_t min, uint32_t max, char *str)
+static int bounds_check(struct device *dev, uint64_t val,
+			uint64_t min, uint64_t max, char *str)
 {
 	if (val >= min && val <= max)
 		return 0;
 
-	dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
+	dev_dbg(dev, "%s out of bounds: %llu (%llu--%llu)\n", str, val, min,
+		max);
 
 	return -EINVAL;
 }
@@ -75,15 +81,15 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll)
 	dev_dbg(dev, "vt_pix_clk_div \t%u\n",  pll->vt_pix_clk_div);
 
 	dev_dbg(dev, "ext_clk_freq_hz \t%u\n", pll->ext_clk_freq_hz);
-	dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->pll_ip_clk_freq_hz);
-	dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->pll_op_clk_freq_hz);
+	dev_dbg(dev, "pll_ip_clk_freq_hz \t%llu\n", pll->pll_ip_clk_freq_hz);
+	dev_dbg(dev, "pll_op_clk_freq_hz \t%llu\n", pll->pll_op_clk_freq_hz);
 	if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
-		dev_dbg(dev, "op_sys_clk_freq_hz \t%u\n",
+		dev_dbg(dev, "op_sys_clk_freq_hz \t%llu\n",
 			pll->op_sys_clk_freq_hz);
 		dev_dbg(dev, "op_pix_clk_freq_hz \t%u\n",
 			pll->op_pix_clk_freq_hz);
 	}
-	dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt_sys_clk_freq_hz);
+	dev_dbg(dev, "vt_sys_clk_freq_hz \t%llu\n", pll->vt_sys_clk_freq_hz);
 	dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt_pix_clk_freq_hz);
 }
 
@@ -131,10 +137,11 @@ static int __smiapp_pll_calculate(struct device *dev,
 		more_mul_max);
 	/* Don't go above max pll op frequency. */
 	more_mul_max =
-		min_t(uint32_t,
+		min_t(uint64_t,
 		      more_mul_max,
-		      limits->max_pll_op_freq_hz
-		      / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
+		      div_u64(limits->max_pll_op_freq_hz,
+			      (pll->ext_clk_freq_hz /
+			       pll->pre_pll_clk_div * mul)));
 	dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %u\n",
 		more_mul_max);
 	/* Don't go above the division capability of op sys clock divider. */
@@ -150,9 +157,9 @@ static int __smiapp_pll_calculate(struct device *dev,
 		more_mul_max);
 
 	/* Ensure we won't go below min_pll_op_freq_hz. */
-	more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz,
-				    pll->ext_clk_freq_hz / pll->pre_pll_clk_div
-				    * mul);
+	more_mul_min = div_u64_round_up(
+		limits->min_pll_op_freq_hz,
+		pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul);
 	dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %u\n",
 		more_mul_min);
 	/* Ensure we won't go below min_pll_multiplier. */
@@ -194,13 +201,13 @@ static int __smiapp_pll_calculate(struct device *dev,
 
 	/* Derive pll_op_clk_freq_hz. */
 	pll->op_sys_clk_freq_hz =
-		pll->pll_op_clk_freq_hz / pll->op_sys_clk_div;
+		div_u64(pll->pll_op_clk_freq_hz, pll->op_sys_clk_div);
 
 	pll->op_pix_clk_div = pll->bits_per_pixel;
 	dev_dbg(dev, "op_pix_clk_div: %u\n", pll->op_pix_clk_div);
 
 	pll->op_pix_clk_freq_hz =
-		pll->op_sys_clk_freq_hz / pll->op_pix_clk_div;
+		div_u64(pll->op_sys_clk_freq_hz, pll->op_pix_clk_div);
 
 	/*
 	 * Some sensors perform analogue binning and some do this
@@ -235,9 +242,9 @@ static int __smiapp_pll_calculate(struct device *dev,
 
 	/* Find smallest and biggest allowed vt divisor. */
 	dev_dbg(dev, "min_vt_div: %u\n", min_vt_div);
-	min_vt_div = max(min_vt_div,
-			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-				      limits->vt.max_pix_clk_freq_hz));
+	min_vt_div = max_t(uint32_t, min_vt_div,
+			   div_u64_round_up(pll->pll_op_clk_freq_hz,
+					    limits->vt.max_pix_clk_freq_hz));
 	dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n",
 		min_vt_div);
 	min_vt_div = max_t(uint32_t, min_vt_div,
@@ -247,9 +254,9 @@ static int __smiapp_pll_calculate(struct device *dev,
 
 	max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
 	dev_dbg(dev, "max_vt_div: %u\n", max_vt_div);
-	max_vt_div = min(max_vt_div,
-			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-				      limits->vt.min_pix_clk_freq_hz));
+	max_vt_div = min_t(uint32_t, max_vt_div,
+			   div_u64_round_up(pll->pll_op_clk_freq_hz,
+					    limits->vt.min_pix_clk_freq_hz));
 	dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n",
 		max_vt_div);
 
@@ -263,9 +270,9 @@ static int __smiapp_pll_calculate(struct device *dev,
 			  DIV_ROUND_UP(min_vt_div,
 				       limits->vt.max_pix_clk_div));
 	dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div);
-	min_sys_div = max(min_sys_div,
-			  pll->pll_op_clk_freq_hz
-			  / limits->vt.max_sys_clk_freq_hz);
+	min_sys_div = max_t(uint32_t, min_sys_div,
+			    pll->pll_op_clk_freq_hz
+			    / limits->vt.max_sys_clk_freq_hz);
 	dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div);
 	min_sys_div = clk_div_even_up(min_sys_div);
 	dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div);
@@ -276,9 +283,9 @@ static int __smiapp_pll_calculate(struct device *dev,
 			  DIV_ROUND_UP(max_vt_div,
 				       limits->vt.min_pix_clk_div));
 	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div);
-	max_sys_div = min(max_sys_div,
-			  DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-				       limits->vt.min_pix_clk_freq_hz));
+	max_sys_div = min_t(uint32_t, max_sys_div,
+			    div_u64_round_up(pll->pll_op_clk_freq_hz,
+					     limits->vt.min_pix_clk_freq_hz));
 	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div);
 
 	/*
@@ -316,9 +323,9 @@ static int __smiapp_pll_calculate(struct device *dev,
 	pll->vt_pix_clk_div = best_pix_div;
 
 	pll->vt_sys_clk_freq_hz =
-		pll->pll_op_clk_freq_hz / pll->vt_sys_clk_div;
+		div_u64(pll->pll_op_clk_freq_hz, pll->vt_sys_clk_div);
 	pll->vt_pix_clk_freq_hz =
-		pll->vt_sys_clk_freq_hz / pll->vt_pix_clk_div;
+		div_u64(pll->vt_sys_clk_freq_hz, pll->vt_pix_clk_div);
 
 	pll->pixel_rate_csi =
 		pll->op_pix_clk_freq_hz * lane_op_clock_ratio;
@@ -402,9 +409,10 @@ int smiapp_pll_calculate(struct device *dev,
 			* (pll->csi2.lanes / lane_op_clock_ratio);
 		break;
 	case SMIAPP_PLL_BUS_TYPE_PARALLEL:
-		pll->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel
-			/ DIV_ROUND_UP(pll->bits_per_pixel,
-				       pll->parallel.bus_width);
+		pll->pll_op_clk_freq_hz = div_u64(
+			pll->link_freq * pll->bits_per_pixel,
+			DIV_ROUND_UP(pll->bits_per_pixel,
+				     pll->parallel.bus_width));
 		break;
 	default:
 		return -EINVAL;
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index 5ce2b61..bb5ae28 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -63,11 +63,11 @@ struct smiapp_pll {
 	uint16_t vt_pix_clk_div;
 
 	uint32_t ext_clk_freq_hz;
-	uint32_t pll_ip_clk_freq_hz;
-	uint32_t pll_op_clk_freq_hz;
-	uint32_t op_sys_clk_freq_hz;
+	uint64_t pll_ip_clk_freq_hz;
+	uint64_t pll_op_clk_freq_hz;
+	uint64_t op_sys_clk_freq_hz;
 	uint32_t op_pix_clk_freq_hz;
-	uint32_t vt_sys_clk_freq_hz;
+	uint64_t vt_sys_clk_freq_hz;
 	uint32_t vt_pix_clk_freq_hz;
 
 	uint32_t pixel_rate_csi;
@@ -76,12 +76,12 @@ struct smiapp_pll {
 struct smiapp_pll_branch_limits {
 	uint16_t min_sys_clk_div;
 	uint16_t max_sys_clk_div;
-	uint32_t min_sys_clk_freq_hz;
-	uint32_t max_sys_clk_freq_hz;
+	uint64_t min_sys_clk_freq_hz;
+	uint64_t max_sys_clk_freq_hz;
 	uint16_t min_pix_clk_div;
 	uint16_t max_pix_clk_div;
-	uint32_t min_pix_clk_freq_hz;
-	uint32_t max_pix_clk_freq_hz;
+	uint64_t min_pix_clk_freq_hz;
+	uint64_t max_pix_clk_freq_hz;
 };
 
 struct smiapp_pll_limits {
@@ -94,8 +94,8 @@ struct smiapp_pll_limits {
 	uint32_t max_pll_ip_freq_hz;
 	uint16_t min_pll_multiplier;
 	uint16_t max_pll_multiplier;
-	uint32_t min_pll_op_freq_hz;
-	uint32_t max_pll_op_freq_hz;
+	uint64_t min_pll_op_freq_hz;
+	uint64_t max_pll_op_freq_hz;
 
 	struct smiapp_pll_branch_limits vt;
 	struct smiapp_pll_branch_limits op;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 14/21] smiapp-pll: Add support for odd pre-pll divisors
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (12 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 13/21] smiapp-pll: Use 64-bit types limits Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 15/21] smiapp: Remove validation of op_pix_clk_div Sakari Ailus
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

Some sensors support odd pre-pll divisor.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp-pll.c | 39 ++++++++++++++++++++++++++-------------
 drivers/media/i2c/smiapp-pll.h |  2 ++
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index ec9f8bb..bed44c0 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -34,14 +34,18 @@ static inline uint64_t div_u64_round_up(uint64_t dividend, uint32_t divisor)
 }
 
 /* Return an even number or one. */
-static inline uint32_t clk_div_even(uint32_t a)
+static inline uint32_t clk_div_even(uint32_t a, bool allow_odd)
 {
+	if (allow_odd)
+		return a;
 	return max_t(uint32_t, 1, a & ~1);
 }
 
 /* Return an even number or one. */
-static inline uint32_t clk_div_even_up(uint32_t a)
+static inline uint32_t clk_div_even_up(uint32_t a, bool allow_odd)
 {
+	if (allow_odd)
+		return a;
 	if (a == 1)
 		return 1;
 	return (a + 1) & ~1;
@@ -269,13 +273,13 @@ static int __smiapp_pll_calculate(struct device *dev,
 	min_sys_div = max(min_sys_div,
 			  DIV_ROUND_UP(min_vt_div,
 				       limits->vt.max_pix_clk_div));
-	dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div);
+	dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div);
 	min_sys_div = max_t(uint32_t, min_sys_div,
 			    pll->pll_op_clk_freq_hz
 			    / limits->vt.max_sys_clk_freq_hz);
-	dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div);
-	min_sys_div = clk_div_even_up(min_sys_div);
-	dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div);
+	dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div);
+	min_sys_div = clk_div_even_up(min_sys_div, 0);
+	dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div);
 
 	max_sys_div = limits->vt.max_sys_clk_div;
 	dev_dbg(dev, "max_sys_div: %u\n", max_sys_div);
@@ -423,14 +427,19 @@ int smiapp_pll_calculate(struct device *dev,
 		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
 	max_pre_pll_clk_div =
 		min_t(uint16_t, limits->max_pre_pll_clk_div,
-		      clk_div_even(pll->ext_clk_freq_hz /
-				   limits->min_pll_ip_freq_hz));
+		      clk_div_even(
+			      pll->ext_clk_freq_hz /
+			      limits->min_pll_ip_freq_hz,
+			      pll->flags
+			      & SMIAPP_PLL_FLAG_ALLOW_ODD_PRE_PLL_CLK_DIV));
 	min_pre_pll_clk_div =
 		max_t(uint16_t, limits->min_pre_pll_clk_div,
 		      clk_div_even_up(
 			      DIV_ROUND_UP(pll->ext_clk_freq_hz,
-					   limits->max_pll_ip_freq_hz)));
-	dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %u / %u\n",
+					   limits->max_pll_ip_freq_hz),
+			      pll->flags
+			      & SMIAPP_PLL_FLAG_ALLOW_ODD_PRE_PLL_CLK_DIV));
+	dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
 		min_pre_pll_clk_div, max_pre_pll_clk_div);
 
 	i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
@@ -442,13 +451,17 @@ int smiapp_pll_calculate(struct device *dev,
 		max_t(uint16_t, min_pre_pll_clk_div,
 		      clk_div_even_up(
 			      DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
-					   limits->max_pll_op_freq_hz)));
-	dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %u / %u\n",
+					   limits->max_pll_op_freq_hz),
+			      pll->flags
+			      & SMIAPP_PLL_FLAG_ALLOW_ODD_PRE_PLL_CLK_DIV));
+	dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
 		min_pre_pll_clk_div, max_pre_pll_clk_div);
 
 	for (pll->pre_pll_clk_div = min_pre_pll_clk_div;
 	     pll->pre_pll_clk_div <= max_pre_pll_clk_div;
-	     pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) {
+	     pll->pre_pll_clk_div +=
+		     pll->flags & SMIAPP_PLL_FLAG_ALLOW_ODD_PRE_PLL_CLK_DIV
+		     ? 1 : (2 - (pll->pre_pll_clk_div & 1))) {
 		rval = __smiapp_pll_calculate(dev, limits, pll, mul, div,
 					      lane_op_clock_ratio);
 		if (rval)
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index bb5ae28..a25f550 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -34,6 +34,8 @@
 /* op pix clock is for all lanes in total normally */
 #define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE			(1 << 0)
 #define SMIAPP_PLL_FLAG_NO_OP_CLOCKS				(1 << 1)
+/* the pre-pll div may be odd */
+#define SMIAPP_PLL_FLAG_ALLOW_ODD_PRE_PLL_CLK_DIV		(1 << 2)
 
 struct smiapp_pll {
 	/* input values */
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 15/21] smiapp: Remove validation of op_pix_clk_div
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (13 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 14/21] smiapp-pll: Add support for odd pre-pll divisors Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 16/21] smiapp-pll: Add quirk for op clk divisor == bits per pixel / 2 Sakari Ailus
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

op_pix_clk_div is directly assigned and not calculated. There's no need to
verify it.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp-pll.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index bed44c0..6bde587 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -355,11 +355,6 @@ static int __smiapp_pll_calculate(struct device *dev,
 			"op_sys_clk_div");
 	if (!rval)
 		rval = bounds_check(
-			dev, pll->op_pix_clk_div,
-			limits->op.min_pix_clk_div, limits->op.max_pix_clk_div,
-			"op_pix_clk_div");
-	if (!rval)
-		rval = bounds_check(
 			dev, pll->op_sys_clk_freq_hz,
 			limits->op.min_sys_clk_freq_hz,
 			limits->op.max_sys_clk_freq_hz,
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 16/21] smiapp-pll: Add quirk for op clk divisor == bits per pixel / 2
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (14 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 15/21] smiapp: Remove validation of op_pix_clk_div Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 17/21] smiapp-pll: Add pixel rate in pixel array as output parameters Sakari Ailus
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

For some sensors in some configurations the effective value of op clk div is
bits per pixel divided by two. The output clock is correctly calculated
whereas some of the rest of the clock tree uses higher clocks than
calculated. This also limits the bpp to even values if the number of lanes
is four.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp-pll.c | 10 ++++++++++
 drivers/media/i2c/smiapp-pll.h |  2 ++
 2 files changed, 12 insertions(+)

diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index 6bde587..aca0ed7 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -208,6 +208,8 @@ static int __smiapp_pll_calculate(struct device *dev,
 		div_u64(pll->pll_op_clk_freq_hz, pll->op_sys_clk_div);
 
 	pll->op_pix_clk_div = pll->bits_per_pixel;
+	if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_DIV_HALF)
+		pll->op_pix_clk_div /= 2;
 	dev_dbg(dev, "op_pix_clk_div: %u\n", pll->op_pix_clk_div);
 
 	pll->op_pix_clk_freq_hz =
@@ -417,6 +419,14 @@ int smiapp_pll_calculate(struct device *dev,
 		return -EINVAL;
 	}
 
+	/*
+	 * Half op pix divisor will give us double the rate compared
+	 * to the regular case. Thus divide the desired pll op clock
+	 * frequency by two.
+	 */
+	if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_DIV_HALF)
+		pll->pll_op_clk_freq_hz /= 2;
+
 	/* Figure out limits for pre-pll divider based on extclk */
 	dev_dbg(dev, "min / max pre_pll_clk_div: %u / %u\n",
 		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index a25f550..02d11db 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -36,6 +36,8 @@
 #define SMIAPP_PLL_FLAG_NO_OP_CLOCKS				(1 << 1)
 /* the pre-pll div may be odd */
 #define SMIAPP_PLL_FLAG_ALLOW_ODD_PRE_PLL_CLK_DIV		(1 << 2)
+/* op pix div value is half of the bits-per-pixel value */
+#define SMIAPP_PLL_FLAG_OP_PIX_DIV_HALF				(1 << 3)
 
 struct smiapp_pll {
 	/* input values */
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 17/21] smiapp-pll: Add pixel rate in pixel array as output parameters
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (15 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 16/21] smiapp-pll: Add quirk for op clk divisor == bits per pixel / 2 Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 18/21] smiapp: Use actual pixel rate calculated by the PLL calculator Sakari Ailus
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

The actual pixel array pixel rate may be something else than vt_pix_clk_freq
on some implementations. Add a new field which contains the corrected value.

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

diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index aca0ed7..25abf01 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -335,6 +335,7 @@ static int __smiapp_pll_calculate(struct device *dev,
 
 	pll->pixel_rate_csi =
 		pll->op_pix_clk_freq_hz * lane_op_clock_ratio;
+	pll->pixel_rate_pixel_array = pll->vt_pix_clk_freq_hz;
 
 	rval = bounds_check(dev, pll->pll_ip_clk_freq_hz,
 			    limits->min_pll_ip_freq_hz,
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index 02d11db..c6ad809 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -75,6 +75,7 @@ struct smiapp_pll {
 	uint32_t vt_pix_clk_freq_hz;
 
 	uint32_t pixel_rate_csi;
+	uint32_t pixel_rate_pixel_array;
 };
 
 struct smiapp_pll_branch_limits {
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 18/21] smiapp: Use actual pixel rate calculated by the PLL calculator
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (16 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 17/21] smiapp-pll: Add pixel rate in pixel array as output parameters Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 19/21] smiapp-pll: Add quirk flag for sensors that effectively use double pix clks Sakari Ailus
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

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

diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 6d940f0..284df17 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -297,7 +297,7 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
 	if (rval < 0)
 		return rval;
 
-	sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
+	sensor->pixel_rate_parray->cur.val64 = pll->pixel_rate_pixel_array;
 	sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
 
 	return 0;
@@ -865,7 +865,7 @@ static int smiapp_update_mode(struct smiapp_sensor *sensor)
 	dev_dbg(&client->dev, "hblank\t\t%d\n", sensor->hblank->val);
 
 	dev_dbg(&client->dev, "real timeperframe\t100/%d\n",
-		sensor->pll.vt_pix_clk_freq_hz /
+		sensor->pll.pixel_rate_pixel_array /
 		((sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width
 		  + sensor->hblank->val) *
 		 (sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 19/21] smiapp-pll: Add quirk flag for sensors that effectively use double pix clks
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (17 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 18/21] smiapp: Use actual pixel rate calculated by the PLL calculator Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 20/21] smiapp: Define macros for obtaining properties of register definitions Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 21/21] smiapp: Add register diversion quirk Sakari Ailus
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

Some sensors have effectively the double pixel (and other clocks) compared
to calculations.

The frequency of the bus is also affected similarly so take this into
account when calculating pll_op_clock frequency.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp-pll.c | 10 ++++++++++
 drivers/media/i2c/smiapp-pll.h |  6 ++++++
 2 files changed, 16 insertions(+)

diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index 25abf01..7d45815 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -336,6 +336,10 @@ static int __smiapp_pll_calculate(struct device *dev,
 	pll->pixel_rate_csi =
 		pll->op_pix_clk_freq_hz * lane_op_clock_ratio;
 	pll->pixel_rate_pixel_array = pll->vt_pix_clk_freq_hz;
+	if (pll->flags & SMIAPP_PLL_FLAG_PIX_CLOCK_DOUBLE) {
+		pll->pixel_rate_csi *= 2;
+		pll->pixel_rate_pixel_array *= 2;
+	}
 
 	rval = bounds_check(dev, pll->pll_ip_clk_freq_hz,
 			    limits->min_pll_ip_freq_hz,
@@ -427,6 +431,12 @@ int smiapp_pll_calculate(struct device *dev,
 	 */
 	if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_DIV_HALF)
 		pll->pll_op_clk_freq_hz /= 2;
+	/*
+	 * If it'll be multiplied by two in the end divide it now to
+	 * avoid achieving double the desired clock.
+	 */
+	if (pll->flags & SMIAPP_PLL_FLAG_PIX_CLOCK_DOUBLE)
+		pll->pll_op_clk_freq_hz /= 2;
 
 	/* Figure out limits for pre-pll divider based on extclk */
 	dev_dbg(dev, "min / max pre_pll_clk_div: %u / %u\n",
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index c6ad809..9eaac54 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -38,6 +38,12 @@
 #define SMIAPP_PLL_FLAG_ALLOW_ODD_PRE_PLL_CLK_DIV		(1 << 2)
 /* op pix div value is half of the bits-per-pixel value */
 #define SMIAPP_PLL_FLAG_OP_PIX_DIV_HALF				(1 << 3)
+/*
+ * The effective vt and op pix clocks are twice as high as the
+ * calculated value. The limits are still against the regular limit
+ * values.
+ */
+#define SMIAPP_PLL_FLAG_PIX_CLOCK_DOUBLE			(1 << 4)
 
 struct smiapp_pll {
 	/* input values */
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 20/21] smiapp: Define macros for obtaining properties of register definitions
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (18 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 19/21] smiapp-pll: Add quirk flag for sensors that effectively use double pix clks Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  2014-04-14  8:58 ` [PATCH v2 21/21] smiapp: Add register diversion quirk Sakari Ailus
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

The register address, width and flags are encoded as a 32-bit value. Add
macros for obtaining these separately. Use the macros in register access
functions.

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

diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index c2db205..47b9e4c 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -165,7 +165,7 @@ static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
 			 bool only8)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-	unsigned int len = (u8)(reg >> 16);
+	u8 len = SMIAPP_REG_WIDTH(reg);
 	int rval;
 
 	if (len != SMIAPP_REG_8BIT && len != SMIAPP_REG_16BIT
@@ -173,9 +173,10 @@ static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
 		return -EINVAL;
 
 	if (len == SMIAPP_REG_8BIT || !only8)
-		rval = ____smiapp_read(sensor, (u16)reg, len, val);
+		rval = ____smiapp_read(sensor, SMIAPP_REG_ADDR(reg), len, val);
 	else
-		rval = ____smiapp_read_8only(sensor, (u16)reg, len, val);
+		rval = ____smiapp_read_8only(sensor, SMIAPP_REG_ADDR(reg), len,
+					     val);
 	if (rval < 0)
 		return rval;
 
@@ -208,9 +209,9 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
 	struct i2c_msg msg;
 	unsigned char data[6];
 	unsigned int retries;
-	unsigned int flags = reg >> 24;
-	unsigned int len = (u8)(reg >> 16);
-	u16 offset = reg;
+	u8 flags = SMIAPP_REG_FLAGS(reg);
+	u8 len = SMIAPP_REG_WIDTH(reg);
+	u16 offset = SMIAPP_REG_ADDR(reg);
 	int r;
 
 	if ((len != SMIAPP_REG_8BIT && len != SMIAPP_REG_16BIT &&
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h
index 934130b..aeecab8 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.h
+++ b/drivers/media/i2c/smiapp/smiapp-regs.h
@@ -28,6 +28,10 @@
 #include <linux/i2c.h>
 #include <linux/types.h>
 
+#define SMIAPP_REG_ADDR(reg)		((u16)reg)
+#define SMIAPP_REG_WIDTH(reg)		((u8)(reg >> 16))
+#define SMIAPP_REG_FLAGS(reg)		((u8)(reg >> 24))
+
 /* Use upper 8 bits of the type field for flags */
 #define SMIAPP_REG_FLAG_FLOAT		(1 << 24)
 
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 21/21] smiapp: Add register diversion quirk
  2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (19 preceding siblings ...)
  2014-04-14  8:58 ` [PATCH v2 20/21] smiapp: Define macros for obtaining properties of register definitions Sakari Ailus
@ 2014-04-14  8:58 ` Sakari Ailus
  20 siblings, 0 replies; 22+ messages in thread
From: Sakari Ailus @ 2014-04-14  8:58 UTC (permalink / raw)
  To: linux-media

Add a quirk for diverting registers for on some sensors, even the standard
registers are not where they can be expected to be found. Add a quirk to
to help using such sensors.

smiapp_write_no_quirk() and smiapp_read_no_quirk() functions are provided
for the use of quirk implementations.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp/smiapp-quirk.h | 13 +++++++++
 drivers/media/i2c/smiapp/smiapp-regs.c  | 48 ++++++++++++++++++++++++++++-----
 drivers/media/i2c/smiapp/smiapp-regs.h  |  2 ++
 3 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index b8b4087..ddc0548 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -35,6 +35,17 @@ struct smiapp_sensor;
  * @post_poweron: Called always after the sensor has been fully powered on.
  * @pre_streamon: Called just before streaming is enabled.
  * @post_streamon: Called right after stopping streaming.
+ * @reg_access: Register access quirk. The quirk may divert the access
+ *		to another register, or no register at all.
+ *
+ *		@write: Is this read (false) or write (true) access?
+ *		@reg: Pointer to the register to access
+ *		@value: Register value, set by the caller on write, or
+ *			by the quirk on read
+ *
+ *		@return: 0 on success, -ENOIOCTLCMD if no register
+ *			 access may be done by the caller (default read
+ *			 value is zero), else negative error code on error
  */
 struct smiapp_quirk {
 	int (*limits)(struct smiapp_sensor *sensor);
@@ -42,6 +53,8 @@ struct smiapp_quirk {
 	int (*pre_streamon)(struct smiapp_sensor *sensor);
 	int (*post_streamoff)(struct smiapp_sensor *sensor);
 	unsigned long (*pll_flags)(struct smiapp_sensor *sensor);
+	int (*reg_access)(struct smiapp_sensor *sensor, bool write, u32 *reg,
+			  u32 *val);
 	unsigned long flags;
 };
 
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index 47b9e4c..a209800 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -186,7 +186,7 @@ static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
 	return 0;
 }
 
-int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+int smiapp_read_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 *val)
 {
 	return __smiapp_read(
 		sensor, reg, val,
@@ -194,16 +194,35 @@ int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
 				   SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY));
 }
 
+int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+{
+	int rval;
+
+	*val = 0;
+	rval = smiapp_call_quirk(sensor, reg_access, false, &reg, val);
+	if (rval == -ENOIOCTLCMD)
+		return 0;
+	if (rval < 0)
+		return rval;
+
+	return smiapp_read_no_quirk(sensor, reg, val);
+}
+
 int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val)
 {
+	int rval;
+
+	*val = 0;
+	rval = smiapp_call_quirk(sensor, reg_access, false, &reg, val);
+	if (rval == -ENOIOCTLCMD)
+		return 0;
+	if (rval < 0)
+		return rval;
+
 	return __smiapp_read(sensor, reg, val, true);
 }
 
-/*
- * Write to a 8/16-bit register.
- * Returns zero if successful, or non-zero otherwise.
- */
-int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
+int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 	struct i2c_msg msg;
@@ -268,3 +287,20 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
 
 	return r;
 }
+
+/*
+ * Write to a 8/16-bit register.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
+{
+	int rval;
+
+	rval = smiapp_call_quirk(sensor, reg_access, true, &reg, &val);
+	if (rval == -ENOIOCTLCMD)
+		return 0;
+	if (rval < 0)
+		return rval;
+
+	return smiapp_write_no_quirk(sensor, reg, val);
+}
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h
index aeecab8..3552112 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.h
+++ b/drivers/media/i2c/smiapp/smiapp-regs.h
@@ -41,8 +41,10 @@
 
 struct smiapp_sensor;
 
+int smiapp_read_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 *val);
 int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val);
 int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val);
+int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val);
 int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val);
 
 #endif
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2014-04-14  9:01 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-14  8:58 [PATCH v2 00/12] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 01/21] smiapp: Remove unused quirk register functionality Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 02/21] smiapp: Rename SMIA_REG to SMIAPP_REG for consistency Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 03/21] smiapp: Fix determining the need for 8-bit read access Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 04/21] smiapp: Add a macro for constructing 8-bit quirk registers Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 05/21] smiapp: Use I2C adapter ID and address in the sub-device name Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 06/21] smiapp: Make PLL flags separate from regular quirk flags Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 07/21] smiapp: Make PLL flags unsigned long Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 08/21] smiapp: Make PLL (quirk) flags a function Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 09/21] smiapp: Use %u for printing u32 value Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 10/21] smiapp-pll: Correct clock debug prints Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 11/21] smiapp-pll: The clock tree values are unsigned --- fix " Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 12/21] smiapp: Limits can be 64 bits Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 13/21] smiapp-pll: Use 64-bit types limits Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 14/21] smiapp-pll: Add support for odd pre-pll divisors Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 15/21] smiapp: Remove validation of op_pix_clk_div Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 16/21] smiapp-pll: Add quirk for op clk divisor == bits per pixel / 2 Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 17/21] smiapp-pll: Add pixel rate in pixel array as output parameters Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 18/21] smiapp: Use actual pixel rate calculated by the PLL calculator Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 19/21] smiapp-pll: Add quirk flag for sensors that effectively use double pix clks Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 20/21] smiapp: Define macros for obtaining properties of register definitions Sakari Ailus
2014-04-14  8:58 ` [PATCH v2 21/21] smiapp: Add register diversion quirk Sakari Ailus

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.