linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes
@ 2014-04-09 19:24 Sakari Ailus
  2014-04-09 19:24 ` [PATCH 01/17] smiapp: Use I2C adapter ID and address in the sub-device name Sakari Ailus
                   ` (16 more replies)
  0 siblings, 17 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:24 UTC (permalink / raw)
  To: linux-media

Hi folks,

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] 18+ messages in thread

* [PATCH 01/17] smiapp: Use I2C adapter ID and address in the sub-device name
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
@ 2014-04-09 19:24 ` Sakari Ailus
  2014-04-09 19:24 ` [PATCH 02/17] smiapp: Make PLL flags separate from regular quirk flags Sakari Ailus
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:24 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] 18+ messages in thread

* [PATCH 02/17] smiapp: Make PLL flags separate from regular quirk flags
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
  2014-04-09 19:24 ` [PATCH 01/17] smiapp: Use I2C adapter ID and address in the sub-device name Sakari Ailus
@ 2014-04-09 19:24 ` Sakari Ailus
  2014-04-09 19:24 ` [PATCH 03/17] smiapp: Make PLL flags unsigned long Sakari Ailus
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:24 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 bb8c506..c7f5194 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -271,7 +271,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 504a6d8..bc9d28c 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -43,11 +43,10 @@ struct smiapp_quirk {
 	int (*post_streamoff)(struct smiapp_sensor *sensor);
 	const struct smia_reg *regs;
 	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] 18+ messages in thread

* [PATCH 03/17] smiapp: Make PLL flags unsigned long
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
  2014-04-09 19:24 ` [PATCH 01/17] smiapp: Use I2C adapter ID and address in the sub-device name Sakari Ailus
  2014-04-09 19:24 ` [PATCH 02/17] smiapp: Make PLL flags separate from regular quirk flags Sakari Ailus
@ 2014-04-09 19:24 ` Sakari Ailus
  2014-04-09 19:24 ` [PATCH 04/17] smiapp: Make PLL (quirk) flags a function Sakari Ailus
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:24 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] 18+ messages in thread

* [PATCH 04/17] smiapp: Make PLL (quirk) flags a function
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (2 preceding siblings ...)
  2014-04-09 19:24 ` [PATCH 03/17] smiapp: Make PLL flags unsigned long Sakari Ailus
@ 2014-04-09 19:24 ` Sakari Ailus
  2014-04-09 19:24 ` [PATCH 05/17] smiapp: Use %u for printing u32 value Sakari Ailus
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:24 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 c7f5194..20e62c1 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -266,12 +266,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 bc9d28c..a6b3183 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -41,9 +41,9 @@ 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);
 	const struct smia_reg *regs;
 	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] 18+ messages in thread

* [PATCH 05/17] smiapp: Use %u for printing u32 value
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (3 preceding siblings ...)
  2014-04-09 19:24 ` [PATCH 04/17] smiapp: Make PLL (quirk) flags a function Sakari Ailus
@ 2014-04-09 19:24 ` Sakari Ailus
  2014-04-09 19:24 ` [PATCH 06/17] smiapp-pll: Correct clock debug prints Sakari Ailus
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:24 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] 18+ messages in thread

* [PATCH 06/17] smiapp-pll: Correct clock debug prints
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (4 preceding siblings ...)
  2014-04-09 19:24 ` [PATCH 05/17] smiapp: Use %u for printing u32 value Sakari Ailus
@ 2014-04-09 19:24 ` Sakari Ailus
  2014-04-09 19:24 ` [PATCH 07/17] smiapp-pll: The clock tree values are unsigned --- fix " Sakari Ailus
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:24 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] 18+ messages in thread

* [PATCH 07/17] smiapp-pll: The clock tree values are unsigned --- fix debug prints
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (5 preceding siblings ...)
  2014-04-09 19:24 ` [PATCH 06/17] smiapp-pll: Correct clock debug prints Sakari Ailus
@ 2014-04-09 19:24 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 08/17] smiapp: Limits can be 64 bits Sakari Ailus
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:24 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] 18+ messages in thread

* [PATCH 08/17] smiapp: Limits can be 64 bits
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (6 preceding siblings ...)
  2014-04-09 19:24 ` [PATCH 07/17] smiapp-pll: The clock tree values are unsigned --- fix " Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 09/17] smiapp-pll: Use 64-bit types limits Sakari Ailus
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 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 20e62c1..580132d 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 a6b3183..15ef0af6 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -54,7 +54,7 @@ struct smiapp_reg_8 {
 };
 
 void smiapp_replace_limit(struct smiapp_sensor *sensor,
-			  u32 limit, u32 val);
+			  u32 limit, u64 val);
 bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
 		      u32 reg, u32 *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] 18+ messages in thread

* [PATCH 09/17] smiapp-pll: Use 64-bit types limits
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (7 preceding siblings ...)
  2014-04-09 19:25 ` [PATCH 08/17] smiapp: Limits can be 64 bits Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 10/17] smiapp-pll: Add support for odd pre-pll divisors Sakari Ailus
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 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 | 69 +++++++++++++++++++++++-------------------
 drivers/media/i2c/smiapp-pll.h | 20 ++++++------
 2 files changed, 48 insertions(+), 41 deletions(-)

diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index d14af5c..8c196c6 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,8 +57,8 @@ 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;
@@ -75,15 +80,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 +136,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 +156,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 +200,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 +241,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 +253,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 +269,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 +282,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 +322,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 +408,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] 18+ messages in thread

* [PATCH 10/17] smiapp-pll: Add support for odd pre-pll divisors
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (8 preceding siblings ...)
  2014-04-09 19:25 ` [PATCH 09/17] smiapp-pll: Use 64-bit types limits Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 11/17] smiapp: Remove validation of op_pix_clk_div Sakari Ailus
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 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 8c196c6..93a8214 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;
@@ -268,13 +272,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);
@@ -422,14 +426,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);
@@ -441,13 +450,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] 18+ messages in thread

* [PATCH 11/17] smiapp: Remove validation of op_pix_clk_div
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (9 preceding siblings ...)
  2014-04-09 19:25 ` [PATCH 10/17] smiapp-pll: Add support for odd pre-pll divisors Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 12/17] smiapp-pll: Add quirk for op clk divisor == bits per pixel / 2 Sakari Ailus
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 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 93a8214..be94921 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -354,11 +354,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] 18+ messages in thread

* [PATCH 12/17] smiapp-pll: Add quirk for op clk divisor == bits per pixel / 2
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (10 preceding siblings ...)
  2014-04-09 19:25 ` [PATCH 11/17] smiapp: Remove validation of op_pix_clk_div Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 13/17] smiapp-pll: Add pixel rate in pixel array as output parameters Sakari Ailus
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 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 be94921..9d06a33 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -207,6 +207,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 =
@@ -416,6 +418,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] 18+ messages in thread

* [PATCH 13/17] smiapp-pll: Add pixel rate in pixel array as output parameters
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (11 preceding siblings ...)
  2014-04-09 19:25 ` [PATCH 12/17] smiapp-pll: Add quirk for op clk divisor == bits per pixel / 2 Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 14/17] smiapp: Use actual pixel rate calculated by the PLL calculator Sakari Ailus
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 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 9d06a33..a83597e 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -334,6 +334,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] 18+ messages in thread

* [PATCH 14/17] smiapp: Use actual pixel rate calculated by the PLL calculator
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (12 preceding siblings ...)
  2014-04-09 19:25 ` [PATCH 13/17] smiapp-pll: Add pixel rate in pixel array as output parameters Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 15/17] smiapp-pll: Add quirk flag for sensors that effectively use double pix clks Sakari Ailus
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 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] 18+ messages in thread

* [PATCH 15/17] smiapp-pll: Add quirk flag for sensors that effectively use double pix clks
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (13 preceding siblings ...)
  2014-04-09 19:25 ` [PATCH 14/17] smiapp: Use actual pixel rate calculated by the PLL calculator Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 16/17] smiapp: Ignore write accesses to quirk registers Sakari Ailus
  2014-04-09 19:25 ` [PATCH 17/17] smiapp: Add register diversion quirk Sakari Ailus
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 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 a83597e..8c48bdc 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -335,6 +335,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,
@@ -426,6 +430,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] 18+ messages in thread

* [PATCH 16/17] smiapp: Ignore write accesses to quirk registers
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (14 preceding siblings ...)
  2014-04-09 19:25 ` [PATCH 15/17] smiapp-pll: Add quirk flag for sensors that effectively use double pix clks Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  2014-04-09 19:25 ` [PATCH 17/17] smiapp: Add register diversion quirk Sakari Ailus
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 UTC (permalink / raw)
  To: linux-media

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

diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index 4fac32c..e88a59a 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -221,6 +221,13 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
 	     len != SMIA_REG_32BIT) || flags)
 		return -EINVAL;
 
+	if (smiapp_quirk_reg(sensor, reg, &val)) {
+		dev_dbg(&client->dev,
+			"ignoring write access to quirk reg 0x%4.4x\n",
+			(u16)reg);
+		return 0;
+	}
+
 	msg.addr = client->addr;
 	msg.flags = 0; /* Write */
 	msg.len = 2 + len;
-- 
1.8.3.2


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

* [PATCH 17/17] smiapp: Add register diversion quirk
  2014-04-09 19:24 [PATCH 0/17] smiapp and smiapp-pll quirk improvements, fixes Sakari Ailus
                   ` (15 preceding siblings ...)
  2014-04-09 19:25 ` [PATCH 16/17] smiapp: Ignore write accesses to quirk registers Sakari Ailus
@ 2014-04-09 19:25 ` Sakari Ailus
  16 siblings, 0 replies; 18+ messages in thread
From: Sakari Ailus @ 2014-04-09 19:25 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.

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

diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index 580132d..9d86217 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -107,6 +107,14 @@ bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
 	return false;
 }
 
+u32 smiapp_quirk_reg_divert(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+{
+	if (sensor->minfo.quirk && sensor->minfo.quirk->reg_divert)
+		return sensor->minfo.quirk->reg_divert(sensor, reg, val);
+	else
+		return reg;
+}
+
 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 15ef0af6..295931c 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -35,6 +35,8 @@ 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_divert: reg is diverted to point to the location of the actual
+ *		register. For sensors that loosely conform to SMIA.
  */
 struct smiapp_quirk {
 	int (*limits)(struct smiapp_sensor *sensor);
@@ -42,6 +44,7 @@ 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);
+	u32 (*reg_divert)(struct smiapp_sensor *sensor, u32 reg, u32 *val);
 	const struct smia_reg *regs;
 	unsigned long flags;
 };
@@ -57,6 +60,7 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor,
 			  u32 limit, u64 val);
 bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
 		      u32 reg, u32 *val);
+u32 smiapp_quirk_reg_divert(struct smiapp_sensor *sensor, u32 reg, u32 *val);
 
 #define SMIAPP_MK_QUIRK_REG(_reg, _val) \
 	{				\
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index e88a59a..57ebd51 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 = reg >> 16;
 	int rval;
 
 	if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
@@ -175,6 +175,9 @@ static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
 	if (smiapp_quirk_reg(sensor, reg, val))
 		goto found_quirk;
 
+	reg = smiapp_quirk_reg_divert(sensor, reg, val);
+	len = reg >> 16;
+
 	if (len == SMIA_REG_8BIT && !only8)
 		rval = ____smiapp_read(sensor, (u16)reg, len, val);
 	else
@@ -213,8 +216,8 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
 	unsigned char data[6];
 	unsigned int retries;
 	unsigned int flags = reg >> 24;
-	unsigned int len = (u8)(reg >> 16);
-	u16 offset = reg;
+	u8 len = reg >> 16;
+	u16 offset;
 	int r;
 
 	if ((len != SMIA_REG_8BIT && len != SMIA_REG_16BIT &&
@@ -228,6 +231,11 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
 		return 0;
 	}
 
+	reg = smiapp_quirk_reg_divert(sensor, reg, &val);
+	offset = reg;
+	flags = reg >> 24;
+	len = reg >> 16;
+
 	msg.addr = client->addr;
 	msg.flags = 0; /* Write */
 	msg.len = 2 + len;
-- 
1.8.3.2


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

end of thread, other threads:[~2014-04-09 19:25 UTC | newest]

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).