All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] OMAPDSS: new clock calculation + DSI VM
@ 2013-03-08 11:52 ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Hi,

Here's a series for improving omapdss clock calculation, and also automatically
calculating DSI videomode parameters, instead of requiring them to be
precalculated and passed to omapdss. These are based on the previous misc
patches series.

 Tomi

Tomi Valkeinen (14):
  OMAPDSS: DISPC: store core clk rate
  OMAPDSS: DSI: fix wrong unsigned long long use
  OMAPDSS: DSI: simplify dsi configuration
  OMAPDSS: DSI: get line buffer size at probe
  OMAPDSS: DSI: add enum omap_dss_dsi_trans_mode
  OMAPDSS: DSI remove unneeded clk source setup code
  OMAPDSS: DISPC: add new clock calculation code
  OMAPDSS: DSS: add new clock calculation code
  OMAPDSS: DSI: add new clock calculation code
  OMAPDSS: SDI: use new clock calculation code
  OMAPDSS: DPI: use new clock calculation code
  OMAPDSS: DSI: use new clock calculation code
  OMAPDSS: remove unused old clock calculation code
  OMAPDSS: remove dsi videomode from dssdev

 drivers/video/omap2/displays/panel-taal.c |   19 +-
 drivers/video/omap2/dss/dispc.c           |  124 ++--
 drivers/video/omap2/dss/dpi.c             |  212 +++++--
 drivers/video/omap2/dss/dsi.c             |  959 +++++++++++++++++------------
 drivers/video/omap2/dss/dss.c             |  151 ++---
 drivers/video/omap2/dss/dss.h             |   36 +-
 drivers/video/omap2/dss/sdi.c             |   68 +-
 include/video/omapdss.h                   |   51 +-
 8 files changed, 977 insertions(+), 643 deletions(-)

-- 
1.7.10.4


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

* [PATCH 00/14] OMAPDSS: new clock calculation + DSI VM
@ 2013-03-08 11:52 ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Hi,

Here's a series for improving omapdss clock calculation, and also automatically
calculating DSI videomode parameters, instead of requiring them to be
precalculated and passed to omapdss. These are based on the previous misc
patches series.

 Tomi

Tomi Valkeinen (14):
  OMAPDSS: DISPC: store core clk rate
  OMAPDSS: DSI: fix wrong unsigned long long use
  OMAPDSS: DSI: simplify dsi configuration
  OMAPDSS: DSI: get line buffer size at probe
  OMAPDSS: DSI: add enum omap_dss_dsi_trans_mode
  OMAPDSS: DSI remove unneeded clk source setup code
  OMAPDSS: DISPC: add new clock calculation code
  OMAPDSS: DSS: add new clock calculation code
  OMAPDSS: DSI: add new clock calculation code
  OMAPDSS: SDI: use new clock calculation code
  OMAPDSS: DPI: use new clock calculation code
  OMAPDSS: DSI: use new clock calculation code
  OMAPDSS: remove unused old clock calculation code
  OMAPDSS: remove dsi videomode from dssdev

 drivers/video/omap2/displays/panel-taal.c |   19 +-
 drivers/video/omap2/dss/dispc.c           |  124 ++--
 drivers/video/omap2/dss/dpi.c             |  212 +++++--
 drivers/video/omap2/dss/dsi.c             |  959 +++++++++++++++++------------
 drivers/video/omap2/dss/dss.c             |  151 ++---
 drivers/video/omap2/dss/dss.h             |   36 +-
 drivers/video/omap2/dss/sdi.c             |   68 +-
 include/video/omapdss.h                   |   51 +-
 8 files changed, 977 insertions(+), 643 deletions(-)

-- 
1.7.10.4


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

* [PATCH 01/14] OMAPDSS: DISPC: store core clk rate
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Store dispc core clock rate so that it's available for calculations even
if the HW is disabled.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 05ff2b9..f564955 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -97,6 +97,8 @@ static struct {
 
 	int irq;
 
+	unsigned long core_clk_rate;
+
 	u32 fifo_size[DISPC_MAX_NR_FIFOS];
 	/* maps which plane is using a fifo. fifo-id -> plane-id */
 	int fifo_assignment[DISPC_MAX_NR_FIFOS];
@@ -2951,6 +2953,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
 
 	dispc_write_reg(DISPC_DIVISORo(channel),
 			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+
+	if (dss_has_feature(FEAT_CORE_CLK_DIV) = false &&
+			channel = OMAP_DSS_CHANNEL_LCD)
+		dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
 }
 
 static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -3056,15 +3062,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
 
 unsigned long dispc_core_clk_rate(void)
 {
-	int lcd;
-	unsigned long fclk = dispc_fclk_rate();
-
-	if (dss_has_feature(FEAT_CORE_CLK_DIV))
-		lcd = REG_GET(DISPC_DIVISOR, 23, 16);
-	else
-		lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
-
-	return fclk / lcd;
+	return dispc.core_clk_rate;
 }
 
 static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
@@ -3451,6 +3449,8 @@ static void _omap_dispc_initial_config(void)
 		l = FLD_MOD(l, 1, 0, 0);
 		l = FLD_MOD(l, 1, 23, 16);
 		dispc_write_reg(DISPC_DIVISOR, l);
+
+		dispc.core_clk_rate = dispc_fclk_rate();
 	}
 
 	/* FUNCGATED */
-- 
1.7.10.4


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

* [PATCH 01/14] OMAPDSS: DISPC: store core clk rate
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Store dispc core clock rate so that it's available for calculations even
if the HW is disabled.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 05ff2b9..f564955 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -97,6 +97,8 @@ static struct {
 
 	int irq;
 
+	unsigned long core_clk_rate;
+
 	u32 fifo_size[DISPC_MAX_NR_FIFOS];
 	/* maps which plane is using a fifo. fifo-id -> plane-id */
 	int fifo_assignment[DISPC_MAX_NR_FIFOS];
@@ -2951,6 +2953,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
 
 	dispc_write_reg(DISPC_DIVISORo(channel),
 			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+
+	if (dss_has_feature(FEAT_CORE_CLK_DIV) == false &&
+			channel == OMAP_DSS_CHANNEL_LCD)
+		dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
 }
 
 static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -3056,15 +3062,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
 
 unsigned long dispc_core_clk_rate(void)
 {
-	int lcd;
-	unsigned long fclk = dispc_fclk_rate();
-
-	if (dss_has_feature(FEAT_CORE_CLK_DIV))
-		lcd = REG_GET(DISPC_DIVISOR, 23, 16);
-	else
-		lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
-
-	return fclk / lcd;
+	return dispc.core_clk_rate;
 }
 
 static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
@@ -3451,6 +3449,8 @@ static void _omap_dispc_initial_config(void)
 		l = FLD_MOD(l, 1, 0, 0);
 		l = FLD_MOD(l, 1, 23, 16);
 		dispc_write_reg(DISPC_DIVISOR, l);
+
+		dispc.core_clk_rate = dispc_fclk_rate();
 	}
 
 	/* FUNCGATED */
-- 
1.7.10.4


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

* [PATCH 02/14] OMAPDSS: DSI: fix wrong unsigned long long use
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

dsi_configure_dispc_clocks() stores dsi func clock into unsigned long
long, but it should really be just unsigned long. Fix this.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 2d95ed9..5f5b475 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4611,7 +4611,7 @@ static int dsi_configure_dispc_clocks(struct platform_device *dsidev)
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct dispc_clock_info dispc_cinfo;
 	int r;
-	unsigned long long fck;
+	unsigned long fck;
 
 	fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
 
-- 
1.7.10.4


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

* [PATCH 02/14] OMAPDSS: DSI: fix wrong unsigned long long use
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

dsi_configure_dispc_clocks() stores dsi func clock into unsigned long
long, but it should really be just unsigned long. Fix this.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 2d95ed9..5f5b475 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4611,7 +4611,7 @@ static int dsi_configure_dispc_clocks(struct platform_device *dsidev)
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct dispc_clock_info dispc_cinfo;
 	int r;
-	unsigned long long fck;
+	unsigned long fck;
 
 	fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
 
-- 
1.7.10.4


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

* [PATCH 03/14] OMAPDSS: DSI: simplify dsi configuration
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

We have a bunch of dsi functions that are used to do the basic
configuration for DSI. To simplify things, and to make sure we have all
the necessary information, create a single dsi config function, which
does the basic configuration.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-taal.c |   16 ++++---
 drivers/video/omap2/dss/dsi.c             |   74 ++++-------------------------
 include/video/omapdss.h                   |   23 ++++-----
 3 files changed, 31 insertions(+), 82 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index bc4c95e..eb86cba 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -919,6 +919,13 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
 	u8 id1, id2, id3;
 	int r;
+	struct omap_dss_dsi_config dsi_config = {
+		.mode = OMAP_DSS_DSI_CMD_MODE,
+		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
+		.timings = &dssdev->panel.timings,
+		.hs_clk = 216000000,
+		.lp_clk = 10000000,
+	};
 
 	r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
 	if (r) {
@@ -926,14 +933,9 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 		goto err0;
 	};
 
-	omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
-		dssdev->panel.timings.y_res);
-	omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
-	omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
-
-	r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
+	r = omapdss_dsi_set_config(dssdev, &dsi_config);
 	if (r) {
-		dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
+		dev_err(&dssdev->dev, "failed to configure DSI\n");
 		goto err0;
 	}
 
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 5f5b475..901b721 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4278,7 +4278,7 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_dsi_configure_pins);
 
-int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
+static int dsi_set_clocks(struct omap_dss_device *dssdev,
 		unsigned long ddr_clk, unsigned long lp_clk)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4293,8 +4293,6 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
 
 	DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
 
-	mutex_lock(&dsi->lock);
-
 	/* Calculate PLL output clock */
 	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
 	if (r)
@@ -4336,13 +4334,10 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
 		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
 		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
 
-	mutex_unlock(&dsi->lock);
 	return 0;
 err:
-	mutex_unlock(&dsi->lock);
 	return r;
 }
-EXPORT_SYMBOL(omapdss_dsi_set_clocks);
 
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 {
@@ -4884,75 +4879,26 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 }
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
-void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
+		const struct omap_dss_dsi_config *config)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
 	mutex_lock(&dsi->lock);
 
-	dsi->timings = *timings;
-
-	mutex_unlock(&dsi->lock);
-}
-EXPORT_SYMBOL(omapdss_dsi_set_timings);
-
-void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	mutex_lock(&dsi->lock);
+	dsi->timings = *config->timings;
+	dsi->vm_timings = *config->vm_timings;
+	dsi->pix_fmt = config->pixel_format;
+	dsi->mode = config->mode;
 
-	dsi->timings.x_res = w;
-	dsi->timings.y_res = h;
+	dsi_set_clocks(dssdev, config->hs_clk, config->lp_clk);
 
 	mutex_unlock(&dsi->lock);
-}
-EXPORT_SYMBOL(omapdss_dsi_set_size);
 
-void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_pixel_format fmt)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	mutex_lock(&dsi->lock);
-
-	dsi->pix_fmt = fmt;
-
-	mutex_unlock(&dsi->lock);
-}
-EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
-
-void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_mode mode)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	mutex_lock(&dsi->lock);
-
-	dsi->mode = mode;
-
-	mutex_unlock(&dsi->lock);
-}
-EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
-
-void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
-		struct omap_dss_dsi_videomode_timings *timings)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	mutex_lock(&dsi->lock);
-
-	dsi->vm_timings = *timings;
-
-	mutex_unlock(&dsi->lock);
+	return 0;
 }
-EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
+EXPORT_SYMBOL(omapdss_dsi_set_config);
 
 /*
  * Return a hardcoded channel for the DSI output. This should work for
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 9057e21..4a52197 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -282,6 +282,16 @@ struct omap_dss_dsi_videomode_timings {
 	int window_sync;
 };
 
+struct omap_dss_dsi_config {
+	enum omap_dss_dsi_mode mode;
+	enum omap_dss_dsi_pixel_format pixel_format;
+	const struct omap_video_timings *timings;
+	const struct omap_dss_dsi_videomode_timings *vm_timings;
+
+	unsigned long hs_clk;
+	unsigned long lp_clk;
+};
+
 void dsi_bus_lock(struct omap_dss_device *dssdev);
 void dsi_bus_unlock(struct omap_dss_device *dssdev);
 int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
@@ -805,15 +815,8 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
 		bool enable);
 int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
-void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings);
-void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
-void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_pixel_format fmt);
-void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_mode mode);
-void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
-		struct omap_dss_dsi_videomode_timings *timings);
+int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
+		const struct omap_dss_dsi_config *config);
 
 int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
 		void (*callback)(int, void *), void *data);
@@ -822,8 +825,6 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
 void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
 int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 		const struct omap_dsi_pin_config *pin_cfg);
-int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
-		unsigned long ddr_clk, unsigned long lp_clk);
 
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
-- 
1.7.10.4


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

* [PATCH 03/14] OMAPDSS: DSI: simplify dsi configuration
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

We have a bunch of dsi functions that are used to do the basic
configuration for DSI. To simplify things, and to make sure we have all
the necessary information, create a single dsi config function, which
does the basic configuration.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-taal.c |   16 ++++---
 drivers/video/omap2/dss/dsi.c             |   74 ++++-------------------------
 include/video/omapdss.h                   |   23 ++++-----
 3 files changed, 31 insertions(+), 82 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index bc4c95e..eb86cba 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -919,6 +919,13 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
 	u8 id1, id2, id3;
 	int r;
+	struct omap_dss_dsi_config dsi_config = {
+		.mode = OMAP_DSS_DSI_CMD_MODE,
+		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
+		.timings = &dssdev->panel.timings,
+		.hs_clk = 216000000,
+		.lp_clk = 10000000,
+	};
 
 	r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
 	if (r) {
@@ -926,14 +933,9 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 		goto err0;
 	};
 
-	omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
-		dssdev->panel.timings.y_res);
-	omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
-	omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
-
-	r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
+	r = omapdss_dsi_set_config(dssdev, &dsi_config);
 	if (r) {
-		dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
+		dev_err(&dssdev->dev, "failed to configure DSI\n");
 		goto err0;
 	}
 
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 5f5b475..901b721 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4278,7 +4278,7 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_dsi_configure_pins);
 
-int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
+static int dsi_set_clocks(struct omap_dss_device *dssdev,
 		unsigned long ddr_clk, unsigned long lp_clk)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4293,8 +4293,6 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
 
 	DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
 
-	mutex_lock(&dsi->lock);
-
 	/* Calculate PLL output clock */
 	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
 	if (r)
@@ -4336,13 +4334,10 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
 		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
 		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
 
-	mutex_unlock(&dsi->lock);
 	return 0;
 err:
-	mutex_unlock(&dsi->lock);
 	return r;
 }
-EXPORT_SYMBOL(omapdss_dsi_set_clocks);
 
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 {
@@ -4884,75 +4879,26 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 }
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
-void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
+		const struct omap_dss_dsi_config *config)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
 	mutex_lock(&dsi->lock);
 
-	dsi->timings = *timings;
-
-	mutex_unlock(&dsi->lock);
-}
-EXPORT_SYMBOL(omapdss_dsi_set_timings);
-
-void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	mutex_lock(&dsi->lock);
+	dsi->timings = *config->timings;
+	dsi->vm_timings = *config->vm_timings;
+	dsi->pix_fmt = config->pixel_format;
+	dsi->mode = config->mode;
 
-	dsi->timings.x_res = w;
-	dsi->timings.y_res = h;
+	dsi_set_clocks(dssdev, config->hs_clk, config->lp_clk);
 
 	mutex_unlock(&dsi->lock);
-}
-EXPORT_SYMBOL(omapdss_dsi_set_size);
 
-void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_pixel_format fmt)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	mutex_lock(&dsi->lock);
-
-	dsi->pix_fmt = fmt;
-
-	mutex_unlock(&dsi->lock);
-}
-EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
-
-void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_mode mode)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	mutex_lock(&dsi->lock);
-
-	dsi->mode = mode;
-
-	mutex_unlock(&dsi->lock);
-}
-EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
-
-void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
-		struct omap_dss_dsi_videomode_timings *timings)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	mutex_lock(&dsi->lock);
-
-	dsi->vm_timings = *timings;
-
-	mutex_unlock(&dsi->lock);
+	return 0;
 }
-EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
+EXPORT_SYMBOL(omapdss_dsi_set_config);
 
 /*
  * Return a hardcoded channel for the DSI output. This should work for
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 9057e21..4a52197 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -282,6 +282,16 @@ struct omap_dss_dsi_videomode_timings {
 	int window_sync;
 };
 
+struct omap_dss_dsi_config {
+	enum omap_dss_dsi_mode mode;
+	enum omap_dss_dsi_pixel_format pixel_format;
+	const struct omap_video_timings *timings;
+	const struct omap_dss_dsi_videomode_timings *vm_timings;
+
+	unsigned long hs_clk;
+	unsigned long lp_clk;
+};
+
 void dsi_bus_lock(struct omap_dss_device *dssdev);
 void dsi_bus_unlock(struct omap_dss_device *dssdev);
 int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
@@ -805,15 +815,8 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
 		bool enable);
 int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
-void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings);
-void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
-void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_pixel_format fmt);
-void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
-		enum omap_dss_dsi_mode mode);
-void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
-		struct omap_dss_dsi_videomode_timings *timings);
+int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
+		const struct omap_dss_dsi_config *config);
 
 int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
 		void (*callback)(int, void *), void *data);
@@ -822,8 +825,6 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
 void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
 int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 		const struct omap_dsi_pin_config *pin_cfg);
-int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
-		unsigned long ddr_clk, unsigned long lp_clk);
 
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
-- 
1.7.10.4


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

* [PATCH 04/14] OMAPDSS: DSI: get line buffer size at probe
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

To find out the DSI line buffer size we need to read HW registers. To
make it possible to do DSI configuration calculations without HW powered
up, store the line buffer size at DSI driver's probe.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 901b721..374fd8f 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -336,6 +336,7 @@ struct dsi_data {
 	unsigned long lpdiv_max;
 
 	unsigned num_lanes_supported;
+	unsigned line_buffer_size;
 
 	struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
 	unsigned num_lanes_used;
@@ -3791,13 +3792,12 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
 
 	if (dsi->mode = OMAP_DSS_DSI_VIDEO_MODE) {
 		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
-		unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
 		struct omap_video_timings *timings = &dsi->timings;
 		/*
 		 * Don't use line buffers if width is greater than the video
 		 * port's line buffer size
 		 */
-		if (line_buf_size <= timings->x_res * bpp / 8)
+		if (dsi->line_buffer_size <= timings->x_res * bpp / 8)
 			num_line_buffers = 0;
 		else
 			num_line_buffers = 2;
@@ -4447,7 +4447,7 @@ static void dsi_update_screen_dispc(struct platform_device *dsidev)
 	u32 l;
 	int r;
 	const unsigned channel = dsi->update_channel;
-	const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
+	const unsigned line_buf_size = dsi->line_buffer_size;
 	u16 w = dsi->timings.x_res;
 	u16 h = dsi->timings.y_res;
 
@@ -5290,6 +5290,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
 	else
 		dsi->num_lanes_supported = 3;
 
+	dsi->line_buffer_size = dsi_get_line_buf_size(dsidev);
+
 	dsi_init_output(dsidev);
 
 	dsi_probe_pdata(dsidev);
-- 
1.7.10.4


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

* [PATCH 04/14] OMAPDSS: DSI: get line buffer size at probe
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

To find out the DSI line buffer size we need to read HW registers. To
make it possible to do DSI configuration calculations without HW powered
up, store the line buffer size at DSI driver's probe.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 901b721..374fd8f 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -336,6 +336,7 @@ struct dsi_data {
 	unsigned long lpdiv_max;
 
 	unsigned num_lanes_supported;
+	unsigned line_buffer_size;
 
 	struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
 	unsigned num_lanes_used;
@@ -3791,13 +3792,12 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
 
 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
 		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
-		unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
 		struct omap_video_timings *timings = &dsi->timings;
 		/*
 		 * Don't use line buffers if width is greater than the video
 		 * port's line buffer size
 		 */
-		if (line_buf_size <= timings->x_res * bpp / 8)
+		if (dsi->line_buffer_size <= timings->x_res * bpp / 8)
 			num_line_buffers = 0;
 		else
 			num_line_buffers = 2;
@@ -4447,7 +4447,7 @@ static void dsi_update_screen_dispc(struct platform_device *dsidev)
 	u32 l;
 	int r;
 	const unsigned channel = dsi->update_channel;
-	const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
+	const unsigned line_buf_size = dsi->line_buffer_size;
 	u16 w = dsi->timings.x_res;
 	u16 h = dsi->timings.y_res;
 
@@ -5290,6 +5290,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
 	else
 		dsi->num_lanes_supported = 3;
 
+	dsi->line_buffer_size = dsi_get_line_buf_size(dsidev);
+
 	dsi_init_output(dsidev);
 
 	dsi_probe_pdata(dsidev);
-- 
1.7.10.4


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

* [PATCH 05/14] OMAPDSS: DSI: add enum omap_dss_dsi_trans_mode
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Instead of managing DSI sync ends with booleans, add an enum for the DSI
transfer mode. This is much cleaner way to handle the DSI syncs.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   15 ++++++++++-----
 include/video/omapdss.h       |   13 ++++++++++---
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 374fd8f..7faad58 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3813,18 +3813,22 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
 static void dsi_config_vp_sync_events(struct platform_device *dsidev)
 {
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	bool vsync_end = dsi->vm_timings.vp_vsync_end;
-	bool hsync_end = dsi->vm_timings.vp_hsync_end;
+	bool sync_end;
 	u32 r;
 
+	if (dsi->vm_timings.trans_mode = OMAP_DSS_DSI_PULSE_MODE)
+		sync_end = true;
+	else
+		sync_end = false;
+
 	r = dsi_read_reg(dsidev, DSI_CTRL);
 	r = FLD_MOD(r, 1, 9, 9);		/* VP_DE_POL */
 	r = FLD_MOD(r, 1, 10, 10);		/* VP_HSYNC_POL */
 	r = FLD_MOD(r, 1, 11, 11);		/* VP_VSYNC_POL */
 	r = FLD_MOD(r, 1, 15, 15);		/* VP_VSYNC_START */
-	r = FLD_MOD(r, vsync_end, 16, 16);	/* VP_VSYNC_END */
+	r = FLD_MOD(r, sync_end, 16, 16);	/* VP_VSYNC_END */
 	r = FLD_MOD(r, 1, 17, 17);		/* VP_HSYNC_START */
-	r = FLD_MOD(r, hsync_end, 18, 18);	/* VP_HSYNC_END */
+	r = FLD_MOD(r, sync_end, 18, 18);	/* VP_HSYNC_END */
 	dsi_write_reg(dsidev, DSI_CTRL, r);
 }
 
@@ -4171,11 +4175,12 @@ static void dsi_proto_timings(struct platform_device *dsidev)
 		int vfp = dsi->vm_timings.vfp;
 		int vbp = dsi->vm_timings.vbp;
 		int window_sync = dsi->vm_timings.window_sync;
-		bool hsync_end = dsi->vm_timings.vp_hsync_end;
+		bool hsync_end;
 		struct omap_video_timings *timings = &dsi->timings;
 		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
 		int tl, t_he, width_bytes;
 
+		hsync_end = dsi->vm_timings.trans_mode = OMAP_DSS_DSI_PULSE_MODE;
 		t_he = hsync_end ?
 			((hsa = 0 && ndl = 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
 
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 4a52197..161011e 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -257,6 +257,15 @@ void rfbi_bus_unlock(void);
 
 /* DSI */
 
+enum omap_dss_dsi_trans_mode {
+	/* Sync Pulses: both sync start and end packets sent */
+	OMAP_DSS_DSI_PULSE_MODE,
+	/* Sync Events: only sync start packets sent */
+	OMAP_DSS_DSI_EVENT_MODE,
+	/* Burst: only sync start packets sent, pixels are time compressed */
+	OMAP_DSS_DSI_BURST_MODE,
+};
+
 struct omap_dss_dsi_videomode_timings {
 	/* DSI video mode blanking data */
 	/* Unit: byte clock cycles */
@@ -274,9 +283,7 @@ struct omap_dss_dsi_videomode_timings {
 	int hbp_blanking_mode;
 	int hfp_blanking_mode;
 
-	/* Video port sync events */
-	bool vp_vsync_end;
-	bool vp_hsync_end;
+	enum omap_dss_dsi_trans_mode trans_mode;
 
 	bool ddr_clk_always_on;
 	int window_sync;
-- 
1.7.10.4


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

* [PATCH 05/14] OMAPDSS: DSI: add enum omap_dss_dsi_trans_mode
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Instead of managing DSI sync ends with booleans, add an enum for the DSI
transfer mode. This is much cleaner way to handle the DSI syncs.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   15 ++++++++++-----
 include/video/omapdss.h       |   13 ++++++++++---
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 374fd8f..7faad58 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3813,18 +3813,22 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
 static void dsi_config_vp_sync_events(struct platform_device *dsidev)
 {
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	bool vsync_end = dsi->vm_timings.vp_vsync_end;
-	bool hsync_end = dsi->vm_timings.vp_hsync_end;
+	bool sync_end;
 	u32 r;
 
+	if (dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE)
+		sync_end = true;
+	else
+		sync_end = false;
+
 	r = dsi_read_reg(dsidev, DSI_CTRL);
 	r = FLD_MOD(r, 1, 9, 9);		/* VP_DE_POL */
 	r = FLD_MOD(r, 1, 10, 10);		/* VP_HSYNC_POL */
 	r = FLD_MOD(r, 1, 11, 11);		/* VP_VSYNC_POL */
 	r = FLD_MOD(r, 1, 15, 15);		/* VP_VSYNC_START */
-	r = FLD_MOD(r, vsync_end, 16, 16);	/* VP_VSYNC_END */
+	r = FLD_MOD(r, sync_end, 16, 16);	/* VP_VSYNC_END */
 	r = FLD_MOD(r, 1, 17, 17);		/* VP_HSYNC_START */
-	r = FLD_MOD(r, hsync_end, 18, 18);	/* VP_HSYNC_END */
+	r = FLD_MOD(r, sync_end, 18, 18);	/* VP_HSYNC_END */
 	dsi_write_reg(dsidev, DSI_CTRL, r);
 }
 
@@ -4171,11 +4175,12 @@ static void dsi_proto_timings(struct platform_device *dsidev)
 		int vfp = dsi->vm_timings.vfp;
 		int vbp = dsi->vm_timings.vbp;
 		int window_sync = dsi->vm_timings.window_sync;
-		bool hsync_end = dsi->vm_timings.vp_hsync_end;
+		bool hsync_end;
 		struct omap_video_timings *timings = &dsi->timings;
 		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
 		int tl, t_he, width_bytes;
 
+		hsync_end = dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE;
 		t_he = hsync_end ?
 			((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
 
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 4a52197..161011e 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -257,6 +257,15 @@ void rfbi_bus_unlock(void);
 
 /* DSI */
 
+enum omap_dss_dsi_trans_mode {
+	/* Sync Pulses: both sync start and end packets sent */
+	OMAP_DSS_DSI_PULSE_MODE,
+	/* Sync Events: only sync start packets sent */
+	OMAP_DSS_DSI_EVENT_MODE,
+	/* Burst: only sync start packets sent, pixels are time compressed */
+	OMAP_DSS_DSI_BURST_MODE,
+};
+
 struct omap_dss_dsi_videomode_timings {
 	/* DSI video mode blanking data */
 	/* Unit: byte clock cycles */
@@ -274,9 +283,7 @@ struct omap_dss_dsi_videomode_timings {
 	int hbp_blanking_mode;
 	int hfp_blanking_mode;
 
-	/* Video port sync events */
-	bool vp_vsync_end;
-	bool vp_hsync_end;
+	enum omap_dss_dsi_trans_mode trans_mode;
 
 	bool ddr_clk_always_on;
 	int window_sync;
-- 
1.7.10.4


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

* [PATCH 06/14] OMAPDSS: DSI remove unneeded clk source setup code
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

We always use the same clock sources for DSI, so let's remove the
unnecessary clock source fields from dsi_data.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   24 ++++++------------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 7faad58..aabe472 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -269,10 +269,6 @@ struct dsi_data {
 	struct dispc_clock_info user_dispc_cinfo;
 	struct dsi_clock_info user_dsi_cinfo;
 
-	enum omap_dss_clk_source user_dispc_fclk_src;
-	enum omap_dss_clk_source user_lcd_clk_src;
-	enum omap_dss_clk_source user_dsi_fclk_src;
-
 	struct dsi_clock_info current_cinfo;
 
 	bool vdds_dsi_enabled;
@@ -4327,18 +4323,6 @@ static int dsi_set_clocks(struct omap_dss_device *dssdev,
 	dsi->user_dispc_cinfo.lck_div = dispc_cinfo.lck_div;
 	dsi->user_dispc_cinfo.pck_div = dispc_cinfo.pck_div;
 
-	dsi->user_dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
-
-	dsi->user_lcd_clk_src -		dsi->module_id = 0 ?
-		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
-		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
-
-	dsi->user_dsi_fclk_src -		dsi->module_id = 0 ?
-		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
-		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
-
 	return 0;
 err:
 	return r;
@@ -4635,7 +4619,9 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	int r;
 
-	dss_select_lcd_clk_source(mgr->id, dsi->user_lcd_clk_src);
+	dss_select_lcd_clk_source(mgr->id, dsi->module_id = 0 ?
+			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
+			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
 
 	if (dsi->mode = OMAP_DSS_DSI_CMD_MODE) {
 		dsi->timings.hsw = 1;
@@ -4741,7 +4727,9 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
 	if (r)
 		goto err1;
 
-	dss_select_dsi_clk_source(dsi->module_id, dsi->user_dsi_fclk_src);
+	dss_select_dsi_clk_source(dsi->module_id, dsi->module_id = 0 ?
+			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
+			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI);
 
 	DSSDBG("PLL OK\n");
 
-- 
1.7.10.4


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

* [PATCH 06/14] OMAPDSS: DSI remove unneeded clk source setup code
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

We always use the same clock sources for DSI, so let's remove the
unnecessary clock source fields from dsi_data.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   24 ++++++------------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 7faad58..aabe472 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -269,10 +269,6 @@ struct dsi_data {
 	struct dispc_clock_info user_dispc_cinfo;
 	struct dsi_clock_info user_dsi_cinfo;
 
-	enum omap_dss_clk_source user_dispc_fclk_src;
-	enum omap_dss_clk_source user_lcd_clk_src;
-	enum omap_dss_clk_source user_dsi_fclk_src;
-
 	struct dsi_clock_info current_cinfo;
 
 	bool vdds_dsi_enabled;
@@ -4327,18 +4323,6 @@ static int dsi_set_clocks(struct omap_dss_device *dssdev,
 	dsi->user_dispc_cinfo.lck_div = dispc_cinfo.lck_div;
 	dsi->user_dispc_cinfo.pck_div = dispc_cinfo.pck_div;
 
-	dsi->user_dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
-
-	dsi->user_lcd_clk_src =
-		dsi->module_id == 0 ?
-		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
-		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
-
-	dsi->user_dsi_fclk_src =
-		dsi->module_id == 0 ?
-		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
-		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
-
 	return 0;
 err:
 	return r;
@@ -4635,7 +4619,9 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	int r;
 
-	dss_select_lcd_clk_source(mgr->id, dsi->user_lcd_clk_src);
+	dss_select_lcd_clk_source(mgr->id, dsi->module_id == 0 ?
+			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
+			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
 
 	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
 		dsi->timings.hsw = 1;
@@ -4741,7 +4727,9 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
 	if (r)
 		goto err1;
 
-	dss_select_dsi_clk_source(dsi->module_id, dsi->user_dsi_fclk_src);
+	dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ?
+			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
+			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI);
 
 	DSSDBG("PLL OK\n");
 
-- 
1.7.10.4


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

* [PATCH 07/14] OMAPDSS: DISPC: add new clock calculation code
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Add new way to iterate over DISPC clock divisors. dispc_div_calc()
provides a generic way to go over all the divisors, within given pixel
clock range. dispc_div_calc() will call a callback function for each
divider set, making the function reusable for all use cases.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   60 +++++++++++++++++++++++++++++++++++++++
 drivers/video/omap2/dss/dss.h   |    6 ++++
 2 files changed, 66 insertions(+)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index f564955..cd54e8f 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -3374,6 +3374,66 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 	return 0;
 }
 
+bool dispc_div_calc(unsigned long dispc,
+		unsigned long pck_min, unsigned long pck_max,
+		dispc_div_calc_func func, void *data)
+{
+	int lckd, lckd_start, lckd_stop;
+	int pckd, pckd_start, pckd_stop;
+	unsigned long pck, lck;
+	unsigned long lck_max;
+	unsigned long pckd_hw_min, pckd_hw_max;
+	unsigned min_fck_per_pck;
+	unsigned long fck;
+
+#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK
+	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+#else
+	min_fck_per_pck = 0;
+#endif
+
+	pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
+	pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
+
+	lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	pck_min = pck_min ? pck_min : 1;
+	pck_max = pck_max ? pck_max : ULONG_MAX;
+
+	lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul);
+	lckd_stop = min(dispc / pck_min, 255ul);
+
+	for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
+		lck = dispc / lckd;
+
+		pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
+		pckd_stop = min(lck / pck_min, pckd_hw_max);
+
+		for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) {
+			pck = lck / pckd;
+
+			/*
+			 * For OMAP2/3 the DISPC fclk is the same as LCD's logic
+			 * clock, which means we're configuring DISPC fclk here
+			 * also. Thus we need to use the calculated lck. For
+			 * OMAP4+ the DISPC fclk is a separate clock.
+			 */
+			if (dss_has_feature(FEAT_CORE_CLK_DIV))
+				fck = dispc_core_clk_rate();
+			else
+				fck = lck;
+
+			if (fck < pck * min_fck_per_pck)
+				continue;
+
+			if (func(lckd, pckd, lck, pck, data))
+				return true;
+		}
+	}
+
+	return false;
+}
+
 void dispc_mgr_set_clock_div(enum omap_channel channel,
 		const struct dispc_clock_info *cinfo)
 {
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 610c8e5..0ff41dd 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -376,6 +376,12 @@ void dispc_enable_fifomerge(bool enable);
 void dispc_enable_gamma_table(bool enable);
 void dispc_set_loadmode(enum omap_dss_load_mode mode);
 
+typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data);
+bool dispc_div_calc(unsigned long dispc,
+		unsigned long pck_min, unsigned long pck_max,
+		dispc_div_calc_func func, void *data);
+
 bool dispc_mgr_timings_ok(enum omap_channel channel,
 		const struct omap_video_timings *timings);
 unsigned long dispc_fclk_rate(void);
-- 
1.7.10.4


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

* [PATCH 07/14] OMAPDSS: DISPC: add new clock calculation code
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Add new way to iterate over DISPC clock divisors. dispc_div_calc()
provides a generic way to go over all the divisors, within given pixel
clock range. dispc_div_calc() will call a callback function for each
divider set, making the function reusable for all use cases.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   60 +++++++++++++++++++++++++++++++++++++++
 drivers/video/omap2/dss/dss.h   |    6 ++++
 2 files changed, 66 insertions(+)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index f564955..cd54e8f 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -3374,6 +3374,66 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 	return 0;
 }
 
+bool dispc_div_calc(unsigned long dispc,
+		unsigned long pck_min, unsigned long pck_max,
+		dispc_div_calc_func func, void *data)
+{
+	int lckd, lckd_start, lckd_stop;
+	int pckd, pckd_start, pckd_stop;
+	unsigned long pck, lck;
+	unsigned long lck_max;
+	unsigned long pckd_hw_min, pckd_hw_max;
+	unsigned min_fck_per_pck;
+	unsigned long fck;
+
+#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK
+	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+#else
+	min_fck_per_pck = 0;
+#endif
+
+	pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
+	pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
+
+	lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	pck_min = pck_min ? pck_min : 1;
+	pck_max = pck_max ? pck_max : ULONG_MAX;
+
+	lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul);
+	lckd_stop = min(dispc / pck_min, 255ul);
+
+	for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) {
+		lck = dispc / lckd;
+
+		pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min);
+		pckd_stop = min(lck / pck_min, pckd_hw_max);
+
+		for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) {
+			pck = lck / pckd;
+
+			/*
+			 * For OMAP2/3 the DISPC fclk is the same as LCD's logic
+			 * clock, which means we're configuring DISPC fclk here
+			 * also. Thus we need to use the calculated lck. For
+			 * OMAP4+ the DISPC fclk is a separate clock.
+			 */
+			if (dss_has_feature(FEAT_CORE_CLK_DIV))
+				fck = dispc_core_clk_rate();
+			else
+				fck = lck;
+
+			if (fck < pck * min_fck_per_pck)
+				continue;
+
+			if (func(lckd, pckd, lck, pck, data))
+				return true;
+		}
+	}
+
+	return false;
+}
+
 void dispc_mgr_set_clock_div(enum omap_channel channel,
 		const struct dispc_clock_info *cinfo)
 {
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 610c8e5..0ff41dd 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -376,6 +376,12 @@ void dispc_enable_fifomerge(bool enable);
 void dispc_enable_gamma_table(bool enable);
 void dispc_set_loadmode(enum omap_dss_load_mode mode);
 
+typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data);
+bool dispc_div_calc(unsigned long dispc,
+		unsigned long pck_min, unsigned long pck_max,
+		dispc_div_calc_func func, void *data);
+
 bool dispc_mgr_timings_ok(enum omap_channel channel,
 		const struct omap_video_timings *timings);
 unsigned long dispc_fclk_rate(void);
-- 
1.7.10.4


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

* [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Add new way to iterate over DSS clock divisors. dss_div_calc() provides
a generic way to go over all the divisors, within given clock range.
dss_div_calc() will call a callback function for each divider set,
making the function reusable for all use cases.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   36 ++++++++++++++++++++++++++++++++++++
 drivers/video/omap2/dss/dss.h |    3 +++
 2 files changed, 39 insertions(+)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 054c2a2..21a3dc8 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
 	return 0;
 }
 
+bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
+{
+	int fckd, fckd_start, fckd_stop;
+	unsigned long fck;
+	unsigned long fck_hw_max;
+	unsigned long fckd_hw_max;
+	unsigned long prate;
+
+	if (dss.dpll4_m4_ck = NULL) {
+		/* XXX can we change the clock on omap2? */
+		fck = clk_get_rate(dss.dss_clk);
+		fckd = 1;
+
+		return func(fckd, fck, data);
+	}
+
+	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+	fckd_hw_max = dss.feat->fck_div_max;
+
+	prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier;
+
+	fck_min = fck_min ? fck_min : 1;
+
+	fckd_start = min(prate / fck_min, fckd_hw_max);
+	fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul);
+
+	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
+		fck = prate / fckd;
+
+		if (func(fckd, fck, data))
+			return true;
+	}
+
+	return false;
+}
+
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
 	if (dss.dpll4_m4_ck) {
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 0ff41dd..4180302 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -271,6 +271,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo);
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 		struct dispc_clock_info *dispc_cinfo);
 
+typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
+bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
+
 /* SDI */
 int sdi_init_platform_driver(void) __init;
 void sdi_uninit_platform_driver(void) __exit;
-- 
1.7.10.4


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

* [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Add new way to iterate over DSS clock divisors. dss_div_calc() provides
a generic way to go over all the divisors, within given clock range.
dss_div_calc() will call a callback function for each divider set,
making the function reusable for all use cases.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   36 ++++++++++++++++++++++++++++++++++++
 drivers/video/omap2/dss/dss.h |    3 +++
 2 files changed, 39 insertions(+)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 054c2a2..21a3dc8 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
 	return 0;
 }
 
+bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
+{
+	int fckd, fckd_start, fckd_stop;
+	unsigned long fck;
+	unsigned long fck_hw_max;
+	unsigned long fckd_hw_max;
+	unsigned long prate;
+
+	if (dss.dpll4_m4_ck == NULL) {
+		/* XXX can we change the clock on omap2? */
+		fck = clk_get_rate(dss.dss_clk);
+		fckd = 1;
+
+		return func(fckd, fck, data);
+	}
+
+	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+	fckd_hw_max = dss.feat->fck_div_max;
+
+	prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier;
+
+	fck_min = fck_min ? fck_min : 1;
+
+	fckd_start = min(prate / fck_min, fckd_hw_max);
+	fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul);
+
+	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
+		fck = prate / fckd;
+
+		if (func(fckd, fck, data))
+			return true;
+	}
+
+	return false;
+}
+
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
 	if (dss.dpll4_m4_ck) {
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 0ff41dd..4180302 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -271,6 +271,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo);
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 		struct dispc_clock_info *dispc_cinfo);
 
+typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
+bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
+
 /* SDI */
 int sdi_init_platform_driver(void) __init;
 void sdi_uninit_platform_driver(void) __exit;
-- 
1.7.10.4


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

* [PATCH 09/14] OMAPDSS: DSI: add new clock calculation code
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Add new way to iterate over DSI PLL and HSDIV clock divisors.
dsi_pll_calc() and dss_hsdiv_calc() provide a generic way to go over
all the divisors, within given clock range. The functions will call a
callback function for each divider set, making the function reusable for
all use cases.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   69 +++++++++++++++++++++++++++++++++++++++++
 drivers/video/omap2/dss/dss.h |   12 +++++++
 2 files changed, 81 insertions(+)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index aabe472..c8d5574 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1280,6 +1280,75 @@ static int dsi_pll_power(struct platform_device *dsidev,
 	return 0;
 }
 
+unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	return clk_get_rate(dsi->sys_clk);
+}
+
+bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
+		unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int regm, regm_start, regm_stop;
+	unsigned long out_max;
+	unsigned long out;
+
+	out_min = out_min ? out_min : 1;
+	out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
+	regm_stop = min(pll / out_min, dsi->regm_dispc_max);
+
+	for (regm = regm_start; regm <= regm_stop; ++regm) {
+		out = pll / regm;
+
+		if (func(regm, out, data))
+			return true;
+	}
+
+	return false;
+}
+
+bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
+		unsigned long pll_min, unsigned long pll_max,
+		dsi_pll_calc_func func, void *data)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int regn, regn_start, regn_stop;
+	int regm, regm_start, regm_stop;
+	unsigned long fint, pll;
+	const unsigned long pll_hw_max = 1800000000;
+	unsigned long fint_hw_min, fint_hw_max;
+
+	fint_hw_min = dsi->fint_min;
+	fint_hw_max = dsi->fint_max;
+
+	regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
+	regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
+
+	pll_max = pll_max ? pll_max : ULONG_MAX;
+
+	for (regn = regn_start; regn <= regn_stop; ++regn) {
+		fint = clkin / regn;
+
+		regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
+				1ul);
+		regm_stop = min3(pll_max / fint / 2,
+				pll_hw_max / fint / 2,
+				dsi->regm_max);
+
+		for (regm = regm_start; regm <= regm_stop; ++regm) {
+			pll = 2 * regm * fint;
+
+			if (func(regn, regm, fint, pll, data))
+				return true;
+		}
+	}
+
+	return false;
+}
+
 /* calculate clock rates using dividers in cinfo */
 static int dsi_calc_clock_rates(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 4180302..dde6cc1 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -295,6 +295,18 @@ void dsi_dump_clocks(struct seq_file *s);
 void dsi_irq_handler(void);
 u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
 
+unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
+
+typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data);
+typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
+		void *data);
+bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
+		unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
+bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
+		unsigned long pll_min, unsigned long pll_max,
+		dsi_pll_calc_func func, void *data);
+
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo);
-- 
1.7.10.4


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

* [PATCH 09/14] OMAPDSS: DSI: add new clock calculation code
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Add new way to iterate over DSI PLL and HSDIV clock divisors.
dsi_pll_calc() and dss_hsdiv_calc() provide a generic way to go over
all the divisors, within given clock range. The functions will call a
callback function for each divider set, making the function reusable for
all use cases.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   69 +++++++++++++++++++++++++++++++++++++++++
 drivers/video/omap2/dss/dss.h |   12 +++++++
 2 files changed, 81 insertions(+)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index aabe472..c8d5574 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1280,6 +1280,75 @@ static int dsi_pll_power(struct platform_device *dsidev,
 	return 0;
 }
 
+unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	return clk_get_rate(dsi->sys_clk);
+}
+
+bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
+		unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int regm, regm_start, regm_stop;
+	unsigned long out_max;
+	unsigned long out;
+
+	out_min = out_min ? out_min : 1;
+	out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
+	regm_stop = min(pll / out_min, dsi->regm_dispc_max);
+
+	for (regm = regm_start; regm <= regm_stop; ++regm) {
+		out = pll / regm;
+
+		if (func(regm, out, data))
+			return true;
+	}
+
+	return false;
+}
+
+bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
+		unsigned long pll_min, unsigned long pll_max,
+		dsi_pll_calc_func func, void *data)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int regn, regn_start, regn_stop;
+	int regm, regm_start, regm_stop;
+	unsigned long fint, pll;
+	const unsigned long pll_hw_max = 1800000000;
+	unsigned long fint_hw_min, fint_hw_max;
+
+	fint_hw_min = dsi->fint_min;
+	fint_hw_max = dsi->fint_max;
+
+	regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
+	regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
+
+	pll_max = pll_max ? pll_max : ULONG_MAX;
+
+	for (regn = regn_start; regn <= regn_stop; ++regn) {
+		fint = clkin / regn;
+
+		regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
+				1ul);
+		regm_stop = min3(pll_max / fint / 2,
+				pll_hw_max / fint / 2,
+				dsi->regm_max);
+
+		for (regm = regm_start; regm <= regm_stop; ++regm) {
+			pll = 2 * regm * fint;
+
+			if (func(regn, regm, fint, pll, data))
+				return true;
+		}
+	}
+
+	return false;
+}
+
 /* calculate clock rates using dividers in cinfo */
 static int dsi_calc_clock_rates(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 4180302..dde6cc1 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -295,6 +295,18 @@ void dsi_dump_clocks(struct seq_file *s);
 void dsi_irq_handler(void);
 u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
 
+unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
+
+typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data);
+typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
+		void *data);
+bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
+		unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
+bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
+		unsigned long pll_min, unsigned long pll_max,
+		dsi_pll_calc_func func, void *data);
+
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo);
-- 
1.7.10.4


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

* [PATCH 10/14] OMAPDSS: SDI: use new clock calculation code
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Use the new clock calculation code in the SDI driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/sdi.c |   68 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index eb4ee17..5754245 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -41,6 +41,72 @@ static struct {
 	struct omap_dss_output output;
 } sdi;
 
+struct sdi_clk_calc_ctx {
+	unsigned long pck_min, pck_max;
+
+	struct dss_clock_info dss_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+};
+
+static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct sdi_clk_calc_ctx *ctx = data;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	return true;
+}
+
+static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
+{
+	struct sdi_clk_calc_ctx *ctx = data;
+
+	ctx->dss_cinfo.fck = fck;
+	ctx->dss_cinfo.fck_div = fckd;
+
+	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+static int sdi_calc_clock_div(unsigned long pclk,
+		struct dss_clock_info *dss_cinfo,
+		struct dispc_clock_info *dispc_cinfo)
+{
+	int i;
+	struct sdi_clk_calc_ctx ctx;
+
+	/*
+	 * DSS fclk gives us very few possibilities, so finding a good pixel
+	 * clock may not be possible. We try multiple times to find the clock,
+	 * each time widening the pixel clock range we look for, up to
+	 * +/- 1MHz.
+	 */
+
+	for (i = 0; i < 10; ++i) {
+		bool ok;
+
+		memset(&ctx, 0, sizeof(ctx));
+		if (pclk > 1000 * i * i * i)
+			ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
+		else
+			ctx.pck_min = 0;
+		ctx.pck_max = pclk + 1000 * i * i * i;
+
+		ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx);
+		if (ok) {
+			*dss_cinfo = ctx.dss_cinfo;
+			*dispc_cinfo = ctx.dispc_cinfo;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
 {
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
@@ -88,7 +154,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 	t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 	t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 
-	r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
+	r = sdi_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
 	if (r)
 		goto err_calc_clock_div;
 
-- 
1.7.10.4


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

* [PATCH 10/14] OMAPDSS: SDI: use new clock calculation code
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Use the new clock calculation code in the SDI driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/sdi.c |   68 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index eb4ee17..5754245 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -41,6 +41,72 @@ static struct {
 	struct omap_dss_output output;
 } sdi;
 
+struct sdi_clk_calc_ctx {
+	unsigned long pck_min, pck_max;
+
+	struct dss_clock_info dss_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+};
+
+static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct sdi_clk_calc_ctx *ctx = data;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	return true;
+}
+
+static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
+{
+	struct sdi_clk_calc_ctx *ctx = data;
+
+	ctx->dss_cinfo.fck = fck;
+	ctx->dss_cinfo.fck_div = fckd;
+
+	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+static int sdi_calc_clock_div(unsigned long pclk,
+		struct dss_clock_info *dss_cinfo,
+		struct dispc_clock_info *dispc_cinfo)
+{
+	int i;
+	struct sdi_clk_calc_ctx ctx;
+
+	/*
+	 * DSS fclk gives us very few possibilities, so finding a good pixel
+	 * clock may not be possible. We try multiple times to find the clock,
+	 * each time widening the pixel clock range we look for, up to
+	 * +/- 1MHz.
+	 */
+
+	for (i = 0; i < 10; ++i) {
+		bool ok;
+
+		memset(&ctx, 0, sizeof(ctx));
+		if (pclk > 1000 * i * i * i)
+			ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu);
+		else
+			ctx.pck_min = 0;
+		ctx.pck_max = pclk + 1000 * i * i * i;
+
+		ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx);
+		if (ok) {
+			*dss_cinfo = ctx.dss_cinfo;
+			*dispc_cinfo = ctx.dispc_cinfo;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
 {
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
@@ -88,7 +154,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 	t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 	t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 
-	r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
+	r = sdi_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
 	if (r)
 		goto err_calc_clock_div;
 
-- 
1.7.10.4


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

* [PATCH 11/14] OMAPDSS: DPI: use new clock calculation code
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Use the new clock calculation code in the DPI driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dpi.c |  212 +++++++++++++++++++++++++++++++++--------
 1 file changed, 172 insertions(+), 40 deletions(-)

diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 775214c..c7363b1 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -91,31 +91,170 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
 	}
 }
 
+struct dpi_clk_calc_ctx {
+	struct platform_device *dsidev;
+
+	/* inputs */
+
+	unsigned long pck_min, pck_max;
+
+	/* outputs */
+
+	struct dsi_clock_info dsi_cinfo;
+	struct dss_clock_info dss_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+};
+
+static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	/*
+	 * Odd dividers give us uneven duty cycle, causing problem when level
+	 * shifted. So skip all odd dividers when the pixel clock is on the
+	 * higher side.
+	 */
+	if (ctx->pck_min >= 1000000) {
+		if (lckd > 1 && lckd % 2 != 0)
+			return false;
+
+		if (pckd > 1 && pckd % 2 != 0)
+			return false;
+	}
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	return true;
+}
+
+
+static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	/*
+	 * Odd dividers give us uneven duty cycle, causing problem when level
+	 * shifted. So skip all odd dividers when the pixel clock is on the
+	 * higher side.
+	 */
+	if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 1000000)
+		return false;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+
+static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll,
+		void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
+			dpi_calc_hsdiv_cb, ctx);
+}
+
+static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	ctx->dss_cinfo.fck = fck;
+	ctx->dss_cinfo.fck_div = fckd;
+
+	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+{
+	unsigned long clkin;
+	unsigned long pll_min, pll_max;
+
+	clkin = dsi_get_pll_clkin(dpi.dsidev);
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dpi.dsidev;
+	ctx->pck_min = pck - 1000;
+	ctx->pck_max = pck + 1000;
+	ctx->dsi_cinfo.clkin = clkin;
+
+	pll_min = 0;
+	pll_max = 0;
+
+	return dsi_pll_calc(dpi.dsidev, clkin,
+			pll_min, pll_max,
+			dpi_calc_pll_cb, ctx);
+}
+
+static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+{
+	int i;
+
+	/*
+	 * DSS fck gives us very few possibilities, so finding a good pixel
+	 * clock may not be possible. We try multiple times to find the clock,
+	 * each time widening the pixel clock range we look for, up to
+	 * +/- 1MHz.
+	 */
+
+	for (i = 0; i < 10; ++i) {
+		bool ok;
+
+		memset(ctx, 0, sizeof(*ctx));
+		if (pck > 1000 * i * i * i)
+			ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
+		else
+			ctx->pck_min = 0;
+		ctx->pck_max = pck + 1000 * i * i * i;
+
+		ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx);
+		if (ok)
+			return ok;
+	}
+
+	return false;
+}
+
+
+
 static int dpi_set_dsi_clk(enum omap_channel channel,
 		unsigned long pck_req, unsigned long *fck, int *lck_div,
 		int *pck_div)
 {
-	struct dsi_clock_info dsi_cinfo;
-	struct dispc_clock_info dispc_cinfo;
+	struct dpi_clk_calc_ctx ctx;
 	int r;
+	bool ok;
 
-	r = dsi_pll_calc_clock_div_pck(dpi.dsidev, pck_req, &dsi_cinfo,
-			&dispc_cinfo);
-	if (r)
-		return r;
+	ok = dpi_dsi_clk_calc(pck_req, &ctx);
+	if (!ok)
+		return -EINVAL;
 
-	r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo);
+	r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
 	if (r)
 		return r;
 
 	dss_select_lcd_clk_source(channel,
 			dpi_get_alt_clk_src(channel));
 
-	dpi.mgr_config.clock_info = dispc_cinfo;
+	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
 
-	*fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
-	*lck_div = dispc_cinfo.lck_div;
-	*pck_div = dispc_cinfo.pck_div;
+	*fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+	*lck_div = ctx.dispc_cinfo.lck_div;
+	*pck_div = ctx.dispc_cinfo.pck_div;
 
 	return 0;
 }
@@ -123,23 +262,23 @@ static int dpi_set_dsi_clk(enum omap_channel channel,
 static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
 		int *lck_div, int *pck_div)
 {
-	struct dss_clock_info dss_cinfo;
-	struct dispc_clock_info dispc_cinfo;
+	struct dpi_clk_calc_ctx ctx;
 	int r;
+	bool ok;
 
-	r = dss_calc_clock_div(pck_req, &dss_cinfo, &dispc_cinfo);
-	if (r)
-		return r;
+	ok = dpi_dss_clk_calc(pck_req, &ctx);
+	if (!ok)
+		return -EINVAL;
 
-	r = dss_set_clock_div(&dss_cinfo);
+	r = dss_set_clock_div(&ctx.dss_cinfo);
 	if (r)
 		return r;
 
-	dpi.mgr_config.clock_info = dispc_cinfo;
+	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
 
-	*fck = dss_cinfo.fck;
-	*lck_div = dispc_cinfo.lck_div;
-	*pck_div = dispc_cinfo.pck_div;
+	*fck = ctx.dss_cinfo.fck;
+	*lck_div = ctx.dispc_cinfo.lck_div;
+	*pck_div = ctx.dispc_cinfo.pck_div;
 
 	return 0;
 }
@@ -319,12 +458,12 @@ EXPORT_SYMBOL(omapdss_dpi_set_timings);
 int dpi_check_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
 {
-	int r;
 	struct omap_overlay_manager *mgr = dpi.output.manager;
 	int lck_div, pck_div;
 	unsigned long fck;
 	unsigned long pck;
-	struct dispc_clock_info dispc_cinfo;
+	struct dpi_clk_calc_ctx ctx;
+	bool ok;
 
 	if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
 		return -EINVAL;
@@ -333,28 +472,21 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
 		return -EINVAL;
 
 	if (dpi.dsidev) {
-		struct dsi_clock_info dsi_cinfo;
-		r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
-				timings->pixel_clock * 1000,
-				&dsi_cinfo, &dispc_cinfo);
+		ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx);
+		if (!ok)
+			return -EINVAL;
 
-		if (r)
-			return r;
-
-		fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+		fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
 	} else {
-		struct dss_clock_info dss_cinfo;
-		r = dss_calc_clock_div(timings->pixel_clock * 1000,
-				&dss_cinfo, &dispc_cinfo);
-
-		if (r)
-			return r;
+		ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &ctx);
+		if (!ok)
+			return -EINVAL;
 
-		fck = dss_cinfo.fck;
+		fck = ctx.dss_cinfo.fck;
 	}
 
-	lck_div = dispc_cinfo.lck_div;
-	pck_div = dispc_cinfo.pck_div;
+	lck_div = ctx.dispc_cinfo.lck_div;
+	pck_div = ctx.dispc_cinfo.pck_div;
 
 	pck = fck / lck_div / pck_div / 1000;
 
-- 
1.7.10.4


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

* [PATCH 11/14] OMAPDSS: DPI: use new clock calculation code
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Use the new clock calculation code in the DPI driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dpi.c |  212 +++++++++++++++++++++++++++++++++--------
 1 file changed, 172 insertions(+), 40 deletions(-)

diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 775214c..c7363b1 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -91,31 +91,170 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
 	}
 }
 
+struct dpi_clk_calc_ctx {
+	struct platform_device *dsidev;
+
+	/* inputs */
+
+	unsigned long pck_min, pck_max;
+
+	/* outputs */
+
+	struct dsi_clock_info dsi_cinfo;
+	struct dss_clock_info dss_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+};
+
+static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	/*
+	 * Odd dividers give us uneven duty cycle, causing problem when level
+	 * shifted. So skip all odd dividers when the pixel clock is on the
+	 * higher side.
+	 */
+	if (ctx->pck_min >= 1000000) {
+		if (lckd > 1 && lckd % 2 != 0)
+			return false;
+
+		if (pckd > 1 && pckd % 2 != 0)
+			return false;
+	}
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	return true;
+}
+
+
+static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	/*
+	 * Odd dividers give us uneven duty cycle, causing problem when level
+	 * shifted. So skip all odd dividers when the pixel clock is on the
+	 * higher side.
+	 */
+	if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 1000000)
+		return false;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+
+static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll,
+		void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
+			dpi_calc_hsdiv_cb, ctx);
+}
+
+static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
+{
+	struct dpi_clk_calc_ctx *ctx = data;
+
+	ctx->dss_cinfo.fck = fck;
+	ctx->dss_cinfo.fck_div = fckd;
+
+	return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
+			dpi_calc_dispc_cb, ctx);
+}
+
+static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+{
+	unsigned long clkin;
+	unsigned long pll_min, pll_max;
+
+	clkin = dsi_get_pll_clkin(dpi.dsidev);
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dpi.dsidev;
+	ctx->pck_min = pck - 1000;
+	ctx->pck_max = pck + 1000;
+	ctx->dsi_cinfo.clkin = clkin;
+
+	pll_min = 0;
+	pll_max = 0;
+
+	return dsi_pll_calc(dpi.dsidev, clkin,
+			pll_min, pll_max,
+			dpi_calc_pll_cb, ctx);
+}
+
+static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+{
+	int i;
+
+	/*
+	 * DSS fck gives us very few possibilities, so finding a good pixel
+	 * clock may not be possible. We try multiple times to find the clock,
+	 * each time widening the pixel clock range we look for, up to
+	 * +/- 1MHz.
+	 */
+
+	for (i = 0; i < 10; ++i) {
+		bool ok;
+
+		memset(ctx, 0, sizeof(*ctx));
+		if (pck > 1000 * i * i * i)
+			ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
+		else
+			ctx->pck_min = 0;
+		ctx->pck_max = pck + 1000 * i * i * i;
+
+		ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx);
+		if (ok)
+			return ok;
+	}
+
+	return false;
+}
+
+
+
 static int dpi_set_dsi_clk(enum omap_channel channel,
 		unsigned long pck_req, unsigned long *fck, int *lck_div,
 		int *pck_div)
 {
-	struct dsi_clock_info dsi_cinfo;
-	struct dispc_clock_info dispc_cinfo;
+	struct dpi_clk_calc_ctx ctx;
 	int r;
+	bool ok;
 
-	r = dsi_pll_calc_clock_div_pck(dpi.dsidev, pck_req, &dsi_cinfo,
-			&dispc_cinfo);
-	if (r)
-		return r;
+	ok = dpi_dsi_clk_calc(pck_req, &ctx);
+	if (!ok)
+		return -EINVAL;
 
-	r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo);
+	r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
 	if (r)
 		return r;
 
 	dss_select_lcd_clk_source(channel,
 			dpi_get_alt_clk_src(channel));
 
-	dpi.mgr_config.clock_info = dispc_cinfo;
+	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
 
-	*fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
-	*lck_div = dispc_cinfo.lck_div;
-	*pck_div = dispc_cinfo.pck_div;
+	*fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+	*lck_div = ctx.dispc_cinfo.lck_div;
+	*pck_div = ctx.dispc_cinfo.pck_div;
 
 	return 0;
 }
@@ -123,23 +262,23 @@ static int dpi_set_dsi_clk(enum omap_channel channel,
 static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
 		int *lck_div, int *pck_div)
 {
-	struct dss_clock_info dss_cinfo;
-	struct dispc_clock_info dispc_cinfo;
+	struct dpi_clk_calc_ctx ctx;
 	int r;
+	bool ok;
 
-	r = dss_calc_clock_div(pck_req, &dss_cinfo, &dispc_cinfo);
-	if (r)
-		return r;
+	ok = dpi_dss_clk_calc(pck_req, &ctx);
+	if (!ok)
+		return -EINVAL;
 
-	r = dss_set_clock_div(&dss_cinfo);
+	r = dss_set_clock_div(&ctx.dss_cinfo);
 	if (r)
 		return r;
 
-	dpi.mgr_config.clock_info = dispc_cinfo;
+	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
 
-	*fck = dss_cinfo.fck;
-	*lck_div = dispc_cinfo.lck_div;
-	*pck_div = dispc_cinfo.pck_div;
+	*fck = ctx.dss_cinfo.fck;
+	*lck_div = ctx.dispc_cinfo.lck_div;
+	*pck_div = ctx.dispc_cinfo.pck_div;
 
 	return 0;
 }
@@ -319,12 +458,12 @@ EXPORT_SYMBOL(omapdss_dpi_set_timings);
 int dpi_check_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
 {
-	int r;
 	struct omap_overlay_manager *mgr = dpi.output.manager;
 	int lck_div, pck_div;
 	unsigned long fck;
 	unsigned long pck;
-	struct dispc_clock_info dispc_cinfo;
+	struct dpi_clk_calc_ctx ctx;
+	bool ok;
 
 	if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
 		return -EINVAL;
@@ -333,28 +472,21 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
 		return -EINVAL;
 
 	if (dpi.dsidev) {
-		struct dsi_clock_info dsi_cinfo;
-		r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
-				timings->pixel_clock * 1000,
-				&dsi_cinfo, &dispc_cinfo);
+		ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx);
+		if (!ok)
+			return -EINVAL;
 
-		if (r)
-			return r;
-
-		fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
+		fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
 	} else {
-		struct dss_clock_info dss_cinfo;
-		r = dss_calc_clock_div(timings->pixel_clock * 1000,
-				&dss_cinfo, &dispc_cinfo);
-
-		if (r)
-			return r;
+		ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &ctx);
+		if (!ok)
+			return -EINVAL;
 
-		fck = dss_cinfo.fck;
+		fck = ctx.dss_cinfo.fck;
 	}
 
-	lck_div = dispc_cinfo.lck_div;
-	pck_div = dispc_cinfo.pck_div;
+	lck_div = ctx.dispc_cinfo.lck_div;
+	pck_div = ctx.dispc_cinfo.pck_div;
 
 	pck = fck / lck_div / pck_div / 1000;
 
-- 
1.7.10.4


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

* [PATCH 12/14] OMAPDSS: DSI: use new clock calculation code
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Use the new clock calculation code in the DSI driver.

The new code does not need DSI video mode parameters from the panel
driver, like the old code does. Instead the new code is given the normal
video timings, and a few DSI parameters, which are used to create DSI
video timings.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-taal.c |    7 +-
 drivers/video/omap2/dss/dsi.c             |  504 ++++++++++++++++++++++++++++-
 include/video/omapdss.h                   |   20 +-
 3 files changed, 513 insertions(+), 18 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index eb86cba..2fc923d 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -787,6 +787,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
 
 	dssdev->panel.timings.x_res = 864;
 	dssdev->panel.timings.y_res = 480;
+	dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
 	dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
 	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
 		OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
@@ -923,8 +924,10 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 		.mode = OMAP_DSS_DSI_CMD_MODE,
 		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
 		.timings = &dssdev->panel.timings,
-		.hs_clk = 216000000,
-		.lp_clk = 10000000,
+		.hs_clk_min = 150000000,
+		.hs_clk_max = 300000000,
+		.lp_clk_min = 7000000,
+		.lp_clk_max = 10000000,
 	};
 
 	r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index c8d5574..593022b 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -255,6 +255,24 @@ struct dsi_isr_tables {
 	struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
 };
 
+struct dsi_clk_calc_ctx {
+	struct platform_device *dsidev;
+
+	/* inputs */
+
+	const struct omap_dss_dsi_config *config;
+
+	unsigned long req_pck_min, req_pck_nom, req_pck_max;
+
+	/* outputs */
+
+	struct dsi_clock_info dsi_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+
+	struct omap_video_timings dispc_vm;
+	struct omap_dss_dsi_videomode_timings dsi_vm;
+};
+
 struct dsi_data {
 	struct platform_device *pdev;
 	void __iomem	*base;
@@ -1201,6 +1219,25 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
 	return r;
 }
 
+static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
+		unsigned long lp_clk_min, unsigned long lp_clk_max)
+{
+	unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
+	unsigned lp_clk_div;
+	unsigned long lp_clk;
+
+	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2);
+	lp_clk = dsi_fclk / 2 / lp_clk_div;
+
+	if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
+		return -EINVAL;
+
+	cinfo->lp_clk_div = lp_clk_div;
+	cinfo->lp_clk = lp_clk;
+
+	return 0;
+}
+
 static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
 {
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -1577,8 +1614,7 @@ found:
 	return 0;
 }
 
-static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
-		struct dsi_clock_info *cinfo)
+static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
 {
 	unsigned long max_dsi_fck;
 
@@ -4369,7 +4405,7 @@ static int dsi_set_clocks(struct omap_dss_device *dssdev,
 		goto err;
 
 	/* Calculate PLL's DSI clock */
-	dsi_pll_calc_dsi_fck(dsidev, &cinfo);
+	dsi_pll_calc_dsi_fck(&cinfo);
 
 	/* Calculate PLL's DISPC clock and pck & lck divs */
 	pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
@@ -4693,13 +4729,6 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
 			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
 
 	if (dsi->mode = OMAP_DSS_DSI_CMD_MODE) {
-		dsi->timings.hsw = 1;
-		dsi->timings.hfp = 1;
-		dsi->timings.hbp = 1;
-		dsi->timings.vsw = 1;
-		dsi->timings.vfp = 0;
-		dsi->timings.vbp = 0;
-
 		r = dss_mgr_register_framedone_handler(mgr,
 				dsi_framedone_irq_callback, dsidev);
 		if (r) {
@@ -4941,24 +4970,473 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 }
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
+#ifdef PRINT_VERBOSE_VM_TIMINGS
+static void print_dsi_vm(const char *str,
+		const struct omap_dss_dsi_videomode_timings *t)
+{
+	unsigned long byteclk = t->hsclk / 4;
+	int bl, wc, pps, tot;
+
+	wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
+	pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
+	bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
+	tot = bl + pps;
+
+#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
+
+	pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, "
+			"%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
+			str,
+			byteclk,
+			t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
+			bl, pps, tot,
+			TO_DSI_T(t->hss),
+			TO_DSI_T(t->hsa),
+			TO_DSI_T(t->hse),
+			TO_DSI_T(t->hbp),
+			TO_DSI_T(pps),
+			TO_DSI_T(t->hfp),
+
+			TO_DSI_T(bl),
+			TO_DSI_T(pps),
+
+			TO_DSI_T(tot));
+#undef TO_DSI_T
+}
+
+static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
+{
+	unsigned long pck = t->pixel_clock * 1000;
+	int hact, bl, tot;
+
+	hact = t->x_res;
+	bl = t->hsw + t->hbp + t->hfp;
+	tot = hact + bl;
+
+#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
+
+	pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, "
+			"%u/%u/%u/%u = %u + %u = %u\n",
+			str,
+			pck,
+			t->hsw, t->hbp, hact, t->hfp,
+			bl, hact, tot,
+			TO_DISPC_T(t->hsw),
+			TO_DISPC_T(t->hbp),
+			TO_DISPC_T(hact),
+			TO_DISPC_T(t->hfp),
+			TO_DISPC_T(bl),
+			TO_DISPC_T(hact),
+			TO_DISPC_T(tot));
+#undef TO_DISPC_T
+}
+
+/* note: this is not quite accurate */
+static void print_dsi_dispc_vm(const char *str,
+		const struct omap_dss_dsi_videomode_timings *t)
+{
+	struct omap_video_timings vm = { 0 };
+	unsigned long byteclk = t->hsclk / 4;
+	unsigned long pck;
+	u64 dsi_tput;
+	int dsi_hact, dsi_htot;
+
+	dsi_tput = (u64)byteclk * t->ndl * 8;
+	pck = (u32)div64_u64(dsi_tput, t->bitspp);
+	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
+	dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
+
+	vm.pixel_clock = pck / 1000;
+	vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
+	vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
+	vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
+	vm.x_res = t->hact;
+
+	print_dispc_vm(str, &vm);
+}
+#endif /* PRINT_VERBOSE_VM_TIMINGS */
+
+static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+	struct omap_video_timings *t = &ctx->dispc_vm;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	*t = *ctx->config->timings;
+	t->pixel_clock = pck / 1000;
+	t->x_res = ctx->config->timings->x_res;
+	t->y_res = ctx->config->timings->y_res;
+	t->hsw = t->hfp = t->hbp = t->vsw = 1;
+	t->vfp = t->vbp = 0;
+
+	return true;
+}
+
+static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
+			dsi_cm_calc_dispc_cb, ctx);
+}
+
+static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+			dsi_cm_calc_hsdiv_cb, ctx);
+}
+
+static bool dsi_cm_calc(struct dsi_data *dsi,
+		const struct omap_dss_dsi_config *cfg,
+		struct dsi_clk_calc_ctx *ctx)
+{
+	unsigned long clkin;
+	int bitspp, ndl;
+	unsigned long pll_min, pll_max;
+	unsigned long pck, txbyteclk;
+
+	clkin = clk_get_rate(dsi->sys_clk);
+	bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	ndl = dsi->num_lanes_used - 1;
+
+	/*
+	 * Here we should calculate minimum txbyteclk to be able to send the
+	 * frame in time, and also to handle TE. That's not very simple, though,
+	 * especially as we go to LP between each pixel packet due to HW
+	 * "feature". So let's just estimate very roughly and multiply by 1.5.
+	 */
+	pck = cfg->timings->pixel_clock * 1000;
+	pck = pck * 3 / 2;
+	txbyteclk = pck * bitspp / 8 / ndl;
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dsi->pdev;
+	ctx->config = cfg;
+	ctx->req_pck_min = pck;
+	ctx->req_pck_nom = pck;
+	ctx->req_pck_max = pck * 3 / 2;
+	ctx->dsi_cinfo.clkin = clkin;
+
+	pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
+	pll_max = cfg->hs_clk_max * 4;
+
+	return dsi_pll_calc(dsi->pdev, clkin,
+			pll_min, pll_max,
+			dsi_cm_calc_pll_cb, ctx);
+}
+
+static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
+	const struct omap_dss_dsi_config *cfg = ctx->config;
+	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	int ndl = dsi->num_lanes_used - 1;
+	unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
+	unsigned long byteclk = hsclk / 4;
+
+	unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
+	int xres;
+	int panel_htot, panel_hbl; /* pixels */
+	int dispc_htot, dispc_hbl; /* pixels */
+	int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
+	const struct omap_video_timings *req_vm;
+	struct omap_video_timings *dispc_vm;
+	struct omap_dss_dsi_videomode_timings *dsi_vm;
+	u64 dsi_tput, dispc_tput;
+
+	dsi_tput = (u64)byteclk * ndl * 8;
+
+	req_vm = cfg->timings;
+	req_pck_min = ctx->req_pck_min;
+	req_pck_max = ctx->req_pck_max;
+	req_pck_nom = ctx->req_pck_nom;
+
+	dispc_pck = ctx->dispc_cinfo.pck;
+	dispc_tput = (u64)dispc_pck * bitspp;
+
+	xres = req_vm->x_res;
+
+	panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
+	panel_htot = xres + panel_hbl;
+
+	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
+
+	/*
+	 * When there are no line buffers, DISPC and DSI must have the
+	 * same tput. Otherwise DISPC tput needs to be higher than DSI's.
+	 */
+	if (dsi->line_buffer_size < xres * bitspp / 8) {
+		if (dispc_tput != dsi_tput)
+			return false;
+	} else {
+		if (dispc_tput < dsi_tput)
+			return false;
+	}
+
+	/* DSI tput must be over the min requirement */
+	if (dsi_tput < (u64)bitspp * req_pck_min)
+		return false;
+
+	/* When non-burst mode, DSI tput must be below max requirement. */
+	if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) {
+		if (dsi_tput > (u64)bitspp * req_pck_max)
+			return false;
+	}
+
+	hss = DIV_ROUND_UP(4, ndl);
+
+	if (cfg->trans_mode = OMAP_DSS_DSI_PULSE_MODE) {
+		if (ndl = 3 && req_vm->hsw = 0)
+			hse = 1;
+		else
+			hse = DIV_ROUND_UP(4, ndl);
+	} else {
+		hse = 0;
+	}
+
+	/* DSI htot to match the panel's nominal pck */
+	dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom);
+
+	/* fail if there would be no time for blanking */
+	if (dsi_htot < hss + hse + dsi_hact)
+		return false;
+
+	/* total DSI blanking needed to achieve panel's TL */
+	dsi_hbl = dsi_htot - dsi_hact;
+
+	/* DISPC htot to match the DSI TL */
+	dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk);
+
+	/* verify that the DSI and DISPC TLs are the same */
+	if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk)
+		return false;
+
+	dispc_hbl = dispc_htot - xres;
+
+	/* setup DSI videomode */
+
+	dsi_vm = &ctx->dsi_vm;
+	memset(dsi_vm, 0, sizeof(*dsi_vm));
+
+	dsi_vm->hsclk = hsclk;
+
+	dsi_vm->ndl = ndl;
+	dsi_vm->bitspp = bitspp;
+	dsi_vm->hact = xres;
+	dsi_vm->vact = req_vm->y_res;
+
+	dsi_vm->hss = hss;
+	if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE)
+		dsi_vm->hsa = 0;
+	else if (ndl = 3 && req_vm->hsw = 0)
+		dsi_vm->hsa = 0;
+	else
+		dsi_vm->hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom)
+			- hse;
+
+	dsi_vm->hse = hse;
+	dsi_vm->hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
+	dsi_vm->hfp = dsi_hbl - (hss + dsi_vm->hsa + hse + dsi_vm->hbp);
+
+	dsi_vm->vsa = req_vm->vsw;
+	dsi_vm->vbp = req_vm->vbp;
+	dsi_vm->vfp = req_vm->vfp;
+
+	dsi_vm->trans_mode = cfg->trans_mode;
+
+	dsi_vm->blanking_mode = 0;
+	dsi_vm->hsa_blanking_mode = 1;
+	dsi_vm->hfp_blanking_mode = 1;
+	dsi_vm->hbp_blanking_mode = 1;
+
+	dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
+	dsi_vm->window_sync = 4;
+
+	/* setup DISPC videomode */
+
+	dispc_vm = &ctx->dispc_vm;
+	*dispc_vm = *req_vm;
+	dispc_vm->pixel_clock = dispc_pck / 1000;
+
+	if (cfg->trans_mode = OMAP_DSS_DSI_PULSE_MODE)
+		dispc_vm->hsw = div64_u64((u64)req_vm->hsw * dispc_pck,
+				req_pck_nom);
+	else
+		dispc_vm->hsw = 1;
+	dispc_vm->hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
+	dispc_vm->hfp = dispc_hbl - dispc_vm->hsw - dispc_vm->hbp;
+
+	return true;
+}
+
+
+static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	if (dsi_vm_calc_blanking(ctx) = false)
+		return false;
+
+#ifdef PRINT_VERBOSE_VM_TIMINGS
+	print_dispc_vm("dispc", &ctx->dispc_vm);
+	print_dsi_vm("dsi  ", &ctx->dsi_vm);
+	print_dispc_vm("req  ", ctx->config->timings);
+	print_dsi_dispc_vm("act  ", &ctx->dsi_vm);
+#endif
+
+	return true;
+}
+
+static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+	unsigned long pck_max;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	/*
+	 * In burst mode we can let the dispc pck be arbitrarily high, but it
+	 * limits our scaling abilities. So for now, don't aim too high.
+	 */
+
+	if (ctx->config->trans_mode = OMAP_DSS_DSI_BURST_MODE)
+		pck_max = ctx->req_pck_max + 10000000;
+	else
+		pck_max = ctx->req_pck_max;
+
+	return dispc_div_calc(dispc, ctx->req_pck_min, pck_max,
+			dsi_vm_calc_dispc_cb, ctx);
+}
+
+static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+			dsi_vm_calc_hsdiv_cb, ctx);
+}
+
+static bool dsi_vm_calc(struct dsi_data *dsi,
+		const struct omap_dss_dsi_config *cfg,
+		struct dsi_clk_calc_ctx *ctx)
+{
+	const struct omap_video_timings *t = cfg->timings;
+	unsigned long clkin;
+	unsigned long pll_min;
+	unsigned long pll_max;
+	int ndl = dsi->num_lanes_used - 1;
+	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	unsigned long byteclk_min;
+
+	clkin = clk_get_rate(dsi->sys_clk);
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dsi->pdev;
+	ctx->config = cfg;
+
+	ctx->dsi_cinfo.clkin = clkin;
+
+	/* these limits should come from the panel driver */
+	ctx->req_pck_min = t->pixel_clock * 1000 - 1000;
+	ctx->req_pck_nom = t->pixel_clock * 1000;
+	ctx->req_pck_max = t->pixel_clock * 1000 + 1000;
+
+	byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
+	pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
+
+	if (cfg->trans_mode = OMAP_DSS_DSI_BURST_MODE) {
+		pll_max = cfg->hs_clk_max * 4;
+	} else {
+		unsigned long byteclk_max;
+		byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp,
+				ndl * 8);
+
+		pll_max = byteclk_max * 4 * 4;
+	}
+
+	return dsi_pll_calc(dsi->pdev, clkin,
+			pll_min, pll_max,
+			dsi_vm_calc_pll_cb, ctx);
+}
+
 int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
 		const struct omap_dss_dsi_config *config)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clk_calc_ctx ctx;
+	bool ok;
+	int r;
 
 	mutex_lock(&dsi->lock);
 
-	dsi->timings = *config->timings;
-	dsi->vm_timings = *config->vm_timings;
 	dsi->pix_fmt = config->pixel_format;
 	dsi->mode = config->mode;
 
-	dsi_set_clocks(dssdev, config->hs_clk, config->lp_clk);
+	if (config->mode = OMAP_DSS_DSI_VIDEO_MODE)
+		ok = dsi_vm_calc(dsi, config, &ctx);
+	else
+		ok = dsi_cm_calc(dsi, config, &ctx);
+
+	if (!ok) {
+		DSSERR("failed to find suitable DSI clock settings\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
+
+	r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min,
+			config->lp_clk_max);
+	if (r) {
+		DSSERR("failed to find suitable DSI LP clock settings\n");
+		goto err;
+	}
+
+	dsi->user_dsi_cinfo = ctx.dsi_cinfo;
+	dsi->user_dispc_cinfo = ctx.dispc_cinfo;
+
+	dsi->timings = ctx.dispc_vm;
+	dsi->vm_timings = ctx.dsi_vm;
 
 	mutex_unlock(&dsi->lock);
 
 	return 0;
+err:
+	mutex_unlock(&dsi->lock);
+
+	return r;
 }
 EXPORT_SYMBOL(omapdss_dsi_set_config);
 
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 161011e..cbaf60f 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -267,9 +267,21 @@ enum omap_dss_dsi_trans_mode {
 };
 
 struct omap_dss_dsi_videomode_timings {
+	unsigned long hsclk;
+
+	unsigned ndl;
+	unsigned bitspp;
+
+	/* pixels */
+	u16 hact;
+	/* lines */
+	u16 vact;
+
 	/* DSI video mode blanking data */
 	/* Unit: byte clock cycles */
+	u16 hss;
 	u16 hsa;
+	u16 hse;
 	u16 hfp;
 	u16 hbp;
 	/* Unit: line clocks */
@@ -293,10 +305,12 @@ struct omap_dss_dsi_config {
 	enum omap_dss_dsi_mode mode;
 	enum omap_dss_dsi_pixel_format pixel_format;
 	const struct omap_video_timings *timings;
-	const struct omap_dss_dsi_videomode_timings *vm_timings;
 
-	unsigned long hs_clk;
-	unsigned long lp_clk;
+	unsigned long hs_clk_min, hs_clk_max;
+	unsigned long lp_clk_min, lp_clk_max;
+
+	bool ddr_clk_always_on;
+	enum omap_dss_dsi_trans_mode trans_mode;
 };
 
 void dsi_bus_lock(struct omap_dss_device *dssdev);
-- 
1.7.10.4


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

* [PATCH 12/14] OMAPDSS: DSI: use new clock calculation code
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Use the new clock calculation code in the DSI driver.

The new code does not need DSI video mode parameters from the panel
driver, like the old code does. Instead the new code is given the normal
video timings, and a few DSI parameters, which are used to create DSI
video timings.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-taal.c |    7 +-
 drivers/video/omap2/dss/dsi.c             |  504 ++++++++++++++++++++++++++++-
 include/video/omapdss.h                   |   20 +-
 3 files changed, 513 insertions(+), 18 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index eb86cba..2fc923d 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -787,6 +787,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
 
 	dssdev->panel.timings.x_res = 864;
 	dssdev->panel.timings.y_res = 480;
+	dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
 	dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
 	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
 		OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
@@ -923,8 +924,10 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 		.mode = OMAP_DSS_DSI_CMD_MODE,
 		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
 		.timings = &dssdev->panel.timings,
-		.hs_clk = 216000000,
-		.lp_clk = 10000000,
+		.hs_clk_min = 150000000,
+		.hs_clk_max = 300000000,
+		.lp_clk_min = 7000000,
+		.lp_clk_max = 10000000,
 	};
 
 	r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index c8d5574..593022b 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -255,6 +255,24 @@ struct dsi_isr_tables {
 	struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
 };
 
+struct dsi_clk_calc_ctx {
+	struct platform_device *dsidev;
+
+	/* inputs */
+
+	const struct omap_dss_dsi_config *config;
+
+	unsigned long req_pck_min, req_pck_nom, req_pck_max;
+
+	/* outputs */
+
+	struct dsi_clock_info dsi_cinfo;
+	struct dispc_clock_info dispc_cinfo;
+
+	struct omap_video_timings dispc_vm;
+	struct omap_dss_dsi_videomode_timings dsi_vm;
+};
+
 struct dsi_data {
 	struct platform_device *pdev;
 	void __iomem	*base;
@@ -1201,6 +1219,25 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
 	return r;
 }
 
+static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
+		unsigned long lp_clk_min, unsigned long lp_clk_max)
+{
+	unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
+	unsigned lp_clk_div;
+	unsigned long lp_clk;
+
+	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2);
+	lp_clk = dsi_fclk / 2 / lp_clk_div;
+
+	if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
+		return -EINVAL;
+
+	cinfo->lp_clk_div = lp_clk_div;
+	cinfo->lp_clk = lp_clk;
+
+	return 0;
+}
+
 static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
 {
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -1577,8 +1614,7 @@ found:
 	return 0;
 }
 
-static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
-		struct dsi_clock_info *cinfo)
+static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
 {
 	unsigned long max_dsi_fck;
 
@@ -4369,7 +4405,7 @@ static int dsi_set_clocks(struct omap_dss_device *dssdev,
 		goto err;
 
 	/* Calculate PLL's DSI clock */
-	dsi_pll_calc_dsi_fck(dsidev, &cinfo);
+	dsi_pll_calc_dsi_fck(&cinfo);
 
 	/* Calculate PLL's DISPC clock and pck & lck divs */
 	pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
@@ -4693,13 +4729,6 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
 			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
 
 	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
-		dsi->timings.hsw = 1;
-		dsi->timings.hfp = 1;
-		dsi->timings.hbp = 1;
-		dsi->timings.vsw = 1;
-		dsi->timings.vfp = 0;
-		dsi->timings.vbp = 0;
-
 		r = dss_mgr_register_framedone_handler(mgr,
 				dsi_framedone_irq_callback, dsidev);
 		if (r) {
@@ -4941,24 +4970,473 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 }
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
+#ifdef PRINT_VERBOSE_VM_TIMINGS
+static void print_dsi_vm(const char *str,
+		const struct omap_dss_dsi_videomode_timings *t)
+{
+	unsigned long byteclk = t->hsclk / 4;
+	int bl, wc, pps, tot;
+
+	wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
+	pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
+	bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
+	tot = bl + pps;
+
+#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
+
+	pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, "
+			"%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
+			str,
+			byteclk,
+			t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
+			bl, pps, tot,
+			TO_DSI_T(t->hss),
+			TO_DSI_T(t->hsa),
+			TO_DSI_T(t->hse),
+			TO_DSI_T(t->hbp),
+			TO_DSI_T(pps),
+			TO_DSI_T(t->hfp),
+
+			TO_DSI_T(bl),
+			TO_DSI_T(pps),
+
+			TO_DSI_T(tot));
+#undef TO_DSI_T
+}
+
+static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
+{
+	unsigned long pck = t->pixel_clock * 1000;
+	int hact, bl, tot;
+
+	hact = t->x_res;
+	bl = t->hsw + t->hbp + t->hfp;
+	tot = hact + bl;
+
+#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
+
+	pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, "
+			"%u/%u/%u/%u = %u + %u = %u\n",
+			str,
+			pck,
+			t->hsw, t->hbp, hact, t->hfp,
+			bl, hact, tot,
+			TO_DISPC_T(t->hsw),
+			TO_DISPC_T(t->hbp),
+			TO_DISPC_T(hact),
+			TO_DISPC_T(t->hfp),
+			TO_DISPC_T(bl),
+			TO_DISPC_T(hact),
+			TO_DISPC_T(tot));
+#undef TO_DISPC_T
+}
+
+/* note: this is not quite accurate */
+static void print_dsi_dispc_vm(const char *str,
+		const struct omap_dss_dsi_videomode_timings *t)
+{
+	struct omap_video_timings vm = { 0 };
+	unsigned long byteclk = t->hsclk / 4;
+	unsigned long pck;
+	u64 dsi_tput;
+	int dsi_hact, dsi_htot;
+
+	dsi_tput = (u64)byteclk * t->ndl * 8;
+	pck = (u32)div64_u64(dsi_tput, t->bitspp);
+	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
+	dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
+
+	vm.pixel_clock = pck / 1000;
+	vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
+	vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
+	vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
+	vm.x_res = t->hact;
+
+	print_dispc_vm(str, &vm);
+}
+#endif /* PRINT_VERBOSE_VM_TIMINGS */
+
+static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+	struct omap_video_timings *t = &ctx->dispc_vm;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	*t = *ctx->config->timings;
+	t->pixel_clock = pck / 1000;
+	t->x_res = ctx->config->timings->x_res;
+	t->y_res = ctx->config->timings->y_res;
+	t->hsw = t->hfp = t->hbp = t->vsw = 1;
+	t->vfp = t->vbp = 0;
+
+	return true;
+}
+
+static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
+			dsi_cm_calc_dispc_cb, ctx);
+}
+
+static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+			dsi_cm_calc_hsdiv_cb, ctx);
+}
+
+static bool dsi_cm_calc(struct dsi_data *dsi,
+		const struct omap_dss_dsi_config *cfg,
+		struct dsi_clk_calc_ctx *ctx)
+{
+	unsigned long clkin;
+	int bitspp, ndl;
+	unsigned long pll_min, pll_max;
+	unsigned long pck, txbyteclk;
+
+	clkin = clk_get_rate(dsi->sys_clk);
+	bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	ndl = dsi->num_lanes_used - 1;
+
+	/*
+	 * Here we should calculate minimum txbyteclk to be able to send the
+	 * frame in time, and also to handle TE. That's not very simple, though,
+	 * especially as we go to LP between each pixel packet due to HW
+	 * "feature". So let's just estimate very roughly and multiply by 1.5.
+	 */
+	pck = cfg->timings->pixel_clock * 1000;
+	pck = pck * 3 / 2;
+	txbyteclk = pck * bitspp / 8 / ndl;
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dsi->pdev;
+	ctx->config = cfg;
+	ctx->req_pck_min = pck;
+	ctx->req_pck_nom = pck;
+	ctx->req_pck_max = pck * 3 / 2;
+	ctx->dsi_cinfo.clkin = clkin;
+
+	pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
+	pll_max = cfg->hs_clk_max * 4;
+
+	return dsi_pll_calc(dsi->pdev, clkin,
+			pll_min, pll_max,
+			dsi_cm_calc_pll_cb, ctx);
+}
+
+static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
+	const struct omap_dss_dsi_config *cfg = ctx->config;
+	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	int ndl = dsi->num_lanes_used - 1;
+	unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
+	unsigned long byteclk = hsclk / 4;
+
+	unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
+	int xres;
+	int panel_htot, panel_hbl; /* pixels */
+	int dispc_htot, dispc_hbl; /* pixels */
+	int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
+	const struct omap_video_timings *req_vm;
+	struct omap_video_timings *dispc_vm;
+	struct omap_dss_dsi_videomode_timings *dsi_vm;
+	u64 dsi_tput, dispc_tput;
+
+	dsi_tput = (u64)byteclk * ndl * 8;
+
+	req_vm = cfg->timings;
+	req_pck_min = ctx->req_pck_min;
+	req_pck_max = ctx->req_pck_max;
+	req_pck_nom = ctx->req_pck_nom;
+
+	dispc_pck = ctx->dispc_cinfo.pck;
+	dispc_tput = (u64)dispc_pck * bitspp;
+
+	xres = req_vm->x_res;
+
+	panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
+	panel_htot = xres + panel_hbl;
+
+	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
+
+	/*
+	 * When there are no line buffers, DISPC and DSI must have the
+	 * same tput. Otherwise DISPC tput needs to be higher than DSI's.
+	 */
+	if (dsi->line_buffer_size < xres * bitspp / 8) {
+		if (dispc_tput != dsi_tput)
+			return false;
+	} else {
+		if (dispc_tput < dsi_tput)
+			return false;
+	}
+
+	/* DSI tput must be over the min requirement */
+	if (dsi_tput < (u64)bitspp * req_pck_min)
+		return false;
+
+	/* When non-burst mode, DSI tput must be below max requirement. */
+	if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) {
+		if (dsi_tput > (u64)bitspp * req_pck_max)
+			return false;
+	}
+
+	hss = DIV_ROUND_UP(4, ndl);
+
+	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
+		if (ndl == 3 && req_vm->hsw == 0)
+			hse = 1;
+		else
+			hse = DIV_ROUND_UP(4, ndl);
+	} else {
+		hse = 0;
+	}
+
+	/* DSI htot to match the panel's nominal pck */
+	dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom);
+
+	/* fail if there would be no time for blanking */
+	if (dsi_htot < hss + hse + dsi_hact)
+		return false;
+
+	/* total DSI blanking needed to achieve panel's TL */
+	dsi_hbl = dsi_htot - dsi_hact;
+
+	/* DISPC htot to match the DSI TL */
+	dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk);
+
+	/* verify that the DSI and DISPC TLs are the same */
+	if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk)
+		return false;
+
+	dispc_hbl = dispc_htot - xres;
+
+	/* setup DSI videomode */
+
+	dsi_vm = &ctx->dsi_vm;
+	memset(dsi_vm, 0, sizeof(*dsi_vm));
+
+	dsi_vm->hsclk = hsclk;
+
+	dsi_vm->ndl = ndl;
+	dsi_vm->bitspp = bitspp;
+	dsi_vm->hact = xres;
+	dsi_vm->vact = req_vm->y_res;
+
+	dsi_vm->hss = hss;
+	if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE)
+		dsi_vm->hsa = 0;
+	else if (ndl == 3 && req_vm->hsw == 0)
+		dsi_vm->hsa = 0;
+	else
+		dsi_vm->hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom)
+			- hse;
+
+	dsi_vm->hse = hse;
+	dsi_vm->hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
+	dsi_vm->hfp = dsi_hbl - (hss + dsi_vm->hsa + hse + dsi_vm->hbp);
+
+	dsi_vm->vsa = req_vm->vsw;
+	dsi_vm->vbp = req_vm->vbp;
+	dsi_vm->vfp = req_vm->vfp;
+
+	dsi_vm->trans_mode = cfg->trans_mode;
+
+	dsi_vm->blanking_mode = 0;
+	dsi_vm->hsa_blanking_mode = 1;
+	dsi_vm->hfp_blanking_mode = 1;
+	dsi_vm->hbp_blanking_mode = 1;
+
+	dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
+	dsi_vm->window_sync = 4;
+
+	/* setup DISPC videomode */
+
+	dispc_vm = &ctx->dispc_vm;
+	*dispc_vm = *req_vm;
+	dispc_vm->pixel_clock = dispc_pck / 1000;
+
+	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE)
+		dispc_vm->hsw = div64_u64((u64)req_vm->hsw * dispc_pck,
+				req_pck_nom);
+	else
+		dispc_vm->hsw = 1;
+	dispc_vm->hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
+	dispc_vm->hfp = dispc_hbl - dispc_vm->hsw - dispc_vm->hbp;
+
+	return true;
+}
+
+
+static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+		unsigned long pck, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dispc_cinfo.lck_div = lckd;
+	ctx->dispc_cinfo.pck_div = pckd;
+	ctx->dispc_cinfo.lck = lck;
+	ctx->dispc_cinfo.pck = pck;
+
+	if (dsi_vm_calc_blanking(ctx) == false)
+		return false;
+
+#ifdef PRINT_VERBOSE_VM_TIMINGS
+	print_dispc_vm("dispc", &ctx->dispc_vm);
+	print_dsi_vm("dsi  ", &ctx->dsi_vm);
+	print_dispc_vm("req  ", ctx->config->timings);
+	print_dsi_dispc_vm("act  ", &ctx->dsi_vm);
+#endif
+
+	return true;
+}
+
+static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+		void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+	unsigned long pck_max;
+
+	ctx->dsi_cinfo.regm_dispc = regm_dispc;
+	ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+
+	/*
+	 * In burst mode we can let the dispc pck be arbitrarily high, but it
+	 * limits our scaling abilities. So for now, don't aim too high.
+	 */
+
+	if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE)
+		pck_max = ctx->req_pck_max + 10000000;
+	else
+		pck_max = ctx->req_pck_max;
+
+	return dispc_div_calc(dispc, ctx->req_pck_min, pck_max,
+			dsi_vm_calc_dispc_cb, ctx);
+}
+
+static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
+		unsigned long pll, void *data)
+{
+	struct dsi_clk_calc_ctx *ctx = data;
+
+	ctx->dsi_cinfo.regn = regn;
+	ctx->dsi_cinfo.regm = regm;
+	ctx->dsi_cinfo.fint = fint;
+	ctx->dsi_cinfo.clkin4ddr = pll;
+
+	return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+			dsi_vm_calc_hsdiv_cb, ctx);
+}
+
+static bool dsi_vm_calc(struct dsi_data *dsi,
+		const struct omap_dss_dsi_config *cfg,
+		struct dsi_clk_calc_ctx *ctx)
+{
+	const struct omap_video_timings *t = cfg->timings;
+	unsigned long clkin;
+	unsigned long pll_min;
+	unsigned long pll_max;
+	int ndl = dsi->num_lanes_used - 1;
+	int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+	unsigned long byteclk_min;
+
+	clkin = clk_get_rate(dsi->sys_clk);
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->dsidev = dsi->pdev;
+	ctx->config = cfg;
+
+	ctx->dsi_cinfo.clkin = clkin;
+
+	/* these limits should come from the panel driver */
+	ctx->req_pck_min = t->pixel_clock * 1000 - 1000;
+	ctx->req_pck_nom = t->pixel_clock * 1000;
+	ctx->req_pck_max = t->pixel_clock * 1000 + 1000;
+
+	byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
+	pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
+
+	if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) {
+		pll_max = cfg->hs_clk_max * 4;
+	} else {
+		unsigned long byteclk_max;
+		byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp,
+				ndl * 8);
+
+		pll_max = byteclk_max * 4 * 4;
+	}
+
+	return dsi_pll_calc(dsi->pdev, clkin,
+			pll_min, pll_max,
+			dsi_vm_calc_pll_cb, ctx);
+}
+
 int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
 		const struct omap_dss_dsi_config *config)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clk_calc_ctx ctx;
+	bool ok;
+	int r;
 
 	mutex_lock(&dsi->lock);
 
-	dsi->timings = *config->timings;
-	dsi->vm_timings = *config->vm_timings;
 	dsi->pix_fmt = config->pixel_format;
 	dsi->mode = config->mode;
 
-	dsi_set_clocks(dssdev, config->hs_clk, config->lp_clk);
+	if (config->mode == OMAP_DSS_DSI_VIDEO_MODE)
+		ok = dsi_vm_calc(dsi, config, &ctx);
+	else
+		ok = dsi_cm_calc(dsi, config, &ctx);
+
+	if (!ok) {
+		DSSERR("failed to find suitable DSI clock settings\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
+
+	r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min,
+			config->lp_clk_max);
+	if (r) {
+		DSSERR("failed to find suitable DSI LP clock settings\n");
+		goto err;
+	}
+
+	dsi->user_dsi_cinfo = ctx.dsi_cinfo;
+	dsi->user_dispc_cinfo = ctx.dispc_cinfo;
+
+	dsi->timings = ctx.dispc_vm;
+	dsi->vm_timings = ctx.dsi_vm;
 
 	mutex_unlock(&dsi->lock);
 
 	return 0;
+err:
+	mutex_unlock(&dsi->lock);
+
+	return r;
 }
 EXPORT_SYMBOL(omapdss_dsi_set_config);
 
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 161011e..cbaf60f 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -267,9 +267,21 @@ enum omap_dss_dsi_trans_mode {
 };
 
 struct omap_dss_dsi_videomode_timings {
+	unsigned long hsclk;
+
+	unsigned ndl;
+	unsigned bitspp;
+
+	/* pixels */
+	u16 hact;
+	/* lines */
+	u16 vact;
+
 	/* DSI video mode blanking data */
 	/* Unit: byte clock cycles */
+	u16 hss;
 	u16 hsa;
+	u16 hse;
 	u16 hfp;
 	u16 hbp;
 	/* Unit: line clocks */
@@ -293,10 +305,12 @@ struct omap_dss_dsi_config {
 	enum omap_dss_dsi_mode mode;
 	enum omap_dss_dsi_pixel_format pixel_format;
 	const struct omap_video_timings *timings;
-	const struct omap_dss_dsi_videomode_timings *vm_timings;
 
-	unsigned long hs_clk;
-	unsigned long lp_clk;
+	unsigned long hs_clk_min, hs_clk_max;
+	unsigned long lp_clk_min, lp_clk_max;
+
+	bool ddr_clk_always_on;
+	enum omap_dss_dsi_trans_mode trans_mode;
 };
 
 void dsi_bus_lock(struct omap_dss_device *dssdev);
-- 
1.7.10.4


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

* [PATCH 13/14] OMAPDSS: remove unused old clock calculation code
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Now that the old clock calculation code is no longer used, we can remove
it from the driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   48 ------
 drivers/video/omap2/dss/dsi.c   |  317 ---------------------------------------
 drivers/video/omap2/dss/dss.c   |  115 --------------
 drivers/video/omap2/dss/dss.h   |   15 --
 4 files changed, 495 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index cd54e8f..8cfa27b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -3311,54 +3311,6 @@ static void dispc_dump_regs(struct seq_file *s)
 #undef DUMPREG
 }
 
-/* with fck as input clock rate, find dispc dividers that produce req_pck */
-void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
-		struct dispc_clock_info *cinfo)
-{
-	u16 pcd_min, pcd_max;
-	unsigned long best_pck;
-	u16 best_ld, cur_ld;
-	u16 best_pd, cur_pd;
-
-	pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
-	pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
-
-	best_pck = 0;
-	best_ld = 0;
-	best_pd = 0;
-
-	for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
-		unsigned long lck = fck / cur_ld;
-
-		for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) {
-			unsigned long pck = lck / cur_pd;
-			long old_delta = abs(best_pck - req_pck);
-			long new_delta = abs(pck - req_pck);
-
-			if (best_pck = 0 || new_delta < old_delta) {
-				best_pck = pck;
-				best_ld = cur_ld;
-				best_pd = cur_pd;
-
-				if (pck = req_pck)
-					goto found;
-			}
-
-			if (pck < req_pck)
-				break;
-		}
-
-		if (lck / pcd_min < req_pck)
-			break;
-	}
-
-found:
-	cinfo->lck_div = best_ld;
-	cinfo->pck_div = best_pd;
-	cinfo->lck = fck / cinfo->lck_div;
-	cinfo->pck = cinfo->lck / cinfo->pck_div;
-}
-
 /* calculate clock rates using dividers in cinfo */
 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 		struct dispc_clock_info *cinfo)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 593022b..46e3d47 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1430,190 +1430,6 @@ static int dsi_calc_clock_rates(struct platform_device *dsidev,
 	return 0;
 }
 
-int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
-		unsigned long req_pck, struct dsi_clock_info *dsi_cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cur, best;
-	struct dispc_clock_info best_dispc;
-	int min_fck_per_pck;
-	int match = 0;
-	unsigned long dss_sys_clk, max_dss_fck;
-
-	dss_sys_clk = clk_get_rate(dsi->sys_clk);
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	if (req_pck = dsi->cache_req_pck &&
-			dsi->cache_cinfo.clkin = dss_sys_clk) {
-		DSSDBG("DSI clock info found from cache\n");
-		*dsi_cinfo = dsi->cache_cinfo;
-		dispc_find_clk_divs(req_pck, dsi_cinfo->dsi_pll_hsdiv_dispc_clk,
-			dispc_cinfo);
-		return 0;
-	}
-
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-
-	if (min_fck_per_pck &&
-		req_pck * min_fck_per_pck > max_dss_fck) {
-		DSSERR("Requested pixel clock not possible with the current "
-				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
-				"the constraint off.\n");
-		min_fck_per_pck = 0;
-	}
-
-	DSSDBG("dsi_pll_calc\n");
-
-retry:
-	memset(&best, 0, sizeof(best));
-	memset(&best_dispc, 0, sizeof(best_dispc));
-
-	memset(&cur, 0, sizeof(cur));
-	cur.clkin = dss_sys_clk;
-
-	/* 0.75MHz < Fint = clkin / regn < 2.1MHz */
-	/* To reduce PLL lock time, keep Fint high (around 2 MHz) */
-	for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
-		cur.fint = cur.clkin / cur.regn;
-
-		if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
-			continue;
-
-		/* DSIPHY(MHz) = (2 * regm / regn) * clkin */
-		for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
-			unsigned long a, b;
-
-			a = 2 * cur.regm * (cur.clkin/1000);
-			b = cur.regn;
-			cur.clkin4ddr = a / b * 1000;
-
-			if (cur.clkin4ddr > 1800 * 1000 * 1000)
-				break;
-
-			/* dsi_pll_hsdiv_dispc_clk(MHz) -			 * DSIPHY(MHz) / regm_dispc  < 173MHz/186Mhz */
-			for (cur.regm_dispc = 1; cur.regm_dispc <
-					dsi->regm_dispc_max; ++cur.regm_dispc) {
-				struct dispc_clock_info cur_dispc;
-				cur.dsi_pll_hsdiv_dispc_clk -					cur.clkin4ddr / cur.regm_dispc;
-
-				if (cur.regm_dispc > 1 &&
-						cur.regm_dispc % 2 != 0 &&
-						req_pck >= 1000000)
-					continue;
-
-				/* this will narrow down the search a bit,
-				 * but still give pixclocks below what was
-				 * requested */
-				if (cur.dsi_pll_hsdiv_dispc_clk  < req_pck)
-					break;
-
-				if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck)
-					continue;
-
-				if (min_fck_per_pck &&
-					cur.dsi_pll_hsdiv_dispc_clk <
-						req_pck * min_fck_per_pck)
-					continue;
-
-				match = 1;
-
-				dispc_find_clk_divs(req_pck,
-						cur.dsi_pll_hsdiv_dispc_clk,
-						&cur_dispc);
-
-				if (abs(cur_dispc.pck - req_pck) <
-						abs(best_dispc.pck - req_pck)) {
-					best = cur;
-					best_dispc = cur_dispc;
-
-					if (cur_dispc.pck = req_pck)
-						goto found;
-				}
-			}
-		}
-	}
-found:
-	if (!match) {
-		if (min_fck_per_pck) {
-			DSSERR("Could not find suitable clock settings.\n"
-					"Turning FCK/PCK constraint off and"
-					"trying again.\n");
-			min_fck_per_pck = 0;
-			goto retry;
-		}
-
-		DSSERR("Could not find suitable clock settings.\n");
-
-		return -EINVAL;
-	}
-
-	/* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */
-	best.regm_dsi = 0;
-	best.dsi_pll_hsdiv_dsi_clk = 0;
-
-	if (dsi_cinfo)
-		*dsi_cinfo = best;
-	if (dispc_cinfo)
-		*dispc_cinfo = best_dispc;
-
-	dsi->cache_req_pck = req_pck;
-	dsi->cache_clk_freq = 0;
-	dsi->cache_cinfo = best;
-
-	return 0;
-}
-
-static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
-		unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cur, best;
-
-	DSSDBG("dsi_pll_calc_ddrfreq\n");
-
-	memset(&best, 0, sizeof(best));
-	memset(&cur, 0, sizeof(cur));
-
-	cur.clkin = clk_get_rate(dsi->sys_clk);
-
-	for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
-		cur.fint = cur.clkin / cur.regn;
-
-		if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
-			continue;
-
-		/* DSIPHY(MHz) = (2 * regm / regn) * clkin */
-		for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
-			unsigned long a, b;
-
-			a = 2 * cur.regm * (cur.clkin/1000);
-			b = cur.regn;
-			cur.clkin4ddr = a / b * 1000;
-
-			if (cur.clkin4ddr > 1800 * 1000 * 1000)
-				break;
-
-			if (abs(cur.clkin4ddr - req_clkin4ddr) <
-					abs(best.clkin4ddr - req_clkin4ddr)) {
-				best = cur;
-				DSSDBG("best %ld\n", best.clkin4ddr);
-			}
-
-			if (cur.clkin4ddr = req_clkin4ddr)
-				goto found;
-		}
-	}
-found:
-	if (cinfo)
-		*cinfo = best;
-
-	return 0;
-}
-
 static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
 {
 	unsigned long max_dsi_fck;
@@ -1624,90 +1440,6 @@ static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
 	cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
 }
 
-static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
-		unsigned long req_pck, struct dsi_clock_info *cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned regm_dispc, best_regm_dispc;
-	unsigned long dispc_clk, best_dispc_clk;
-	int min_fck_per_pck;
-	unsigned long max_dss_fck;
-	struct dispc_clock_info best_dispc;
-	bool match;
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-
-	if (min_fck_per_pck &&
-			req_pck * min_fck_per_pck > max_dss_fck) {
-		DSSERR("Requested pixel clock not possible with the current "
-				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
-				"the constraint off.\n");
-		min_fck_per_pck = 0;
-	}
-
-retry:
-	best_regm_dispc = 0;
-	best_dispc_clk = 0;
-	memset(&best_dispc, 0, sizeof(best_dispc));
-	match = false;
-
-	for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
-		struct dispc_clock_info cur_dispc;
-
-		dispc_clk = cinfo->clkin4ddr / regm_dispc;
-
-		/* this will narrow down the search a bit,
-		 * but still give pixclocks below what was
-		 * requested */
-		if (dispc_clk  < req_pck)
-			break;
-
-		if (dispc_clk > max_dss_fck)
-			continue;
-
-		if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
-			continue;
-
-		match = true;
-
-		dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
-
-		if (abs(cur_dispc.pck - req_pck) <
-				abs(best_dispc.pck - req_pck)) {
-			best_regm_dispc = regm_dispc;
-			best_dispc_clk = dispc_clk;
-			best_dispc = cur_dispc;
-
-			if (cur_dispc.pck = req_pck)
-				goto found;
-		}
-	}
-
-	if (!match) {
-		if (min_fck_per_pck) {
-			DSSERR("Could not find suitable clock settings.\n"
-					"Turning FCK/PCK constraint off and"
-					"trying again.\n");
-			min_fck_per_pck = 0;
-			goto retry;
-		}
-
-		DSSERR("Could not find suitable clock settings.\n");
-
-		return -EINVAL;
-	}
-found:
-	cinfo->regm_dispc = best_regm_dispc;
-	cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
-
-	*dispc_cinfo = best_dispc;
-
-	return 0;
-}
-
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo)
 {
@@ -4384,55 +4116,6 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_dsi_configure_pins);
 
-static int dsi_set_clocks(struct omap_dss_device *dssdev,
-		unsigned long ddr_clk, unsigned long lp_clk)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cinfo;
-	struct dispc_clock_info dispc_cinfo;
-	unsigned lp_clk_div;
-	unsigned long dsi_fclk;
-	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
-	unsigned long pck;
-	int r;
-
-	DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
-
-	/* Calculate PLL output clock */
-	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
-	if (r)
-		goto err;
-
-	/* Calculate PLL's DSI clock */
-	dsi_pll_calc_dsi_fck(&cinfo);
-
-	/* Calculate PLL's DISPC clock and pck & lck divs */
-	pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
-	DSSDBG("finding dispc dividers for pck %lu\n", pck);
-	r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
-	if (r)
-		goto err;
-
-	/* Calculate LP clock */
-	dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
-	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
-
-	dsi->user_dsi_cinfo.regn = cinfo.regn;
-	dsi->user_dsi_cinfo.regm = cinfo.regm;
-	dsi->user_dsi_cinfo.regm_dispc = cinfo.regm_dispc;
-	dsi->user_dsi_cinfo.regm_dsi = cinfo.regm_dsi;
-
-	dsi->user_dsi_cinfo.lp_clk_div = lp_clk_div;
-
-	dsi->user_dispc_cinfo.lck_div = dispc_cinfo.lck_div;
-	dsi->user_dispc_cinfo.pck_div = dispc_cinfo.pck_div;
-
-	return 0;
-err:
-	return r;
-}
-
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 21a3dc8..ee288f0 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -578,121 +578,6 @@ static int dss_setup_default_clock(void)
 	return 0;
 }
 
-int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	unsigned long prate;
-	struct dss_clock_info best_dss;
-	struct dispc_clock_info best_dispc;
-
-	unsigned long fck, max_dss_fck;
-
-	u16 fck_div;
-
-	int match = 0;
-	int min_fck_per_pck;
-
-	prate = dss_get_dpll4_rate();
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	fck = clk_get_rate(dss.dss_clk);
-	if (req_pck = dss.cache_req_pck && prate = dss.cache_prate &&
-		dss.cache_dss_cinfo.fck = fck) {
-		DSSDBG("dispc clock info found from cache.\n");
-		*dss_cinfo = dss.cache_dss_cinfo;
-		*dispc_cinfo = dss.cache_dispc_cinfo;
-		return 0;
-	}
-
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-
-	if (min_fck_per_pck &&
-		req_pck * min_fck_per_pck > max_dss_fck) {
-		DSSERR("Requested pixel clock not possible with the current "
-				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
-				"the constraint off.\n");
-		min_fck_per_pck = 0;
-	}
-
-retry:
-	memset(&best_dss, 0, sizeof(best_dss));
-	memset(&best_dispc, 0, sizeof(best_dispc));
-
-	if (dss.dpll4_m4_ck = NULL) {
-		struct dispc_clock_info cur_dispc;
-		/* XXX can we change the clock on omap2? */
-		fck = clk_get_rate(dss.dss_clk);
-		fck_div = 1;
-
-		dispc_find_clk_divs(req_pck, fck, &cur_dispc);
-		match = 1;
-
-		best_dss.fck = fck;
-		best_dss.fck_div = fck_div;
-
-		best_dispc = cur_dispc;
-
-		goto found;
-	} else {
-		for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
-			struct dispc_clock_info cur_dispc;
-
-			fck = prate / fck_div * dss.feat->dss_fck_multiplier;
-
-			if (fck > max_dss_fck)
-				continue;
-
-			if (min_fck_per_pck &&
-					fck < req_pck * min_fck_per_pck)
-				continue;
-
-			match = 1;
-
-			dispc_find_clk_divs(req_pck, fck, &cur_dispc);
-
-			if (abs(cur_dispc.pck - req_pck) <
-					abs(best_dispc.pck - req_pck)) {
-
-				best_dss.fck = fck;
-				best_dss.fck_div = fck_div;
-
-				best_dispc = cur_dispc;
-
-				if (cur_dispc.pck = req_pck)
-					goto found;
-			}
-		}
-	}
-
-found:
-	if (!match) {
-		if (min_fck_per_pck) {
-			DSSERR("Could not find suitable clock settings.\n"
-					"Turning FCK/PCK constraint off and"
-					"trying again.\n");
-			min_fck_per_pck = 0;
-			goto retry;
-		}
-
-		DSSERR("Could not find suitable clock settings.\n");
-
-		return -EINVAL;
-	}
-
-	if (dss_cinfo)
-		*dss_cinfo = best_dss;
-	if (dispc_cinfo)
-		*dispc_cinfo = best_dispc;
-
-	dss.cache_req_pck = req_pck;
-	dss.cache_prate = prate;
-	dss.cache_dss_cinfo = best_dss;
-	dss.cache_dispc_cinfo = best_dispc;
-
-	return 0;
-}
-
 void dss_set_venc_output(enum omap_dss_venc_type type)
 {
 	int l = 0;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index dde6cc1..faaf358 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -268,8 +268,6 @@ void dss_set_dac_pwrdn_bgz(bool enable);
 unsigned long dss_get_dpll4_rate(void);
 int dss_calc_clock_rates(struct dss_clock_info *cinfo);
 int dss_set_clock_div(struct dss_clock_info *cinfo);
-int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
-		struct dispc_clock_info *dispc_cinfo);
 
 typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
 bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
@@ -310,9 +308,6 @@ bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo);
-int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
-		unsigned long req_pck, struct dsi_clock_info *cinfo,
-		struct dispc_clock_info *dispc_cinfo);
 int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
 		bool enable_hsdiv);
 void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
@@ -343,14 +338,6 @@ static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
 	WARN("%s: DSI not compiled in\n", __func__);
 	return -ENODEV;
 }
-static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
-		unsigned long req_pck,
-		struct dsi_clock_info *dsi_cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	WARN("%s: DSI not compiled in\n", __func__);
-	return -ENODEV;
-}
 static inline int dsi_pll_init(struct platform_device *dsidev,
 		bool enable_hsclk, bool enable_hsdiv)
 {
@@ -400,8 +387,6 @@ bool dispc_div_calc(unsigned long dispc,
 bool dispc_mgr_timings_ok(enum omap_channel channel,
 		const struct omap_video_timings *timings);
 unsigned long dispc_fclk_rate(void);
-void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
-		struct dispc_clock_info *cinfo);
 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 		struct dispc_clock_info *cinfo);
 
-- 
1.7.10.4


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

* [PATCH 13/14] OMAPDSS: remove unused old clock calculation code
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

Now that the old clock calculation code is no longer used, we can remove
it from the driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   48 ------
 drivers/video/omap2/dss/dsi.c   |  317 ---------------------------------------
 drivers/video/omap2/dss/dss.c   |  115 --------------
 drivers/video/omap2/dss/dss.h   |   15 --
 4 files changed, 495 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index cd54e8f..8cfa27b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -3311,54 +3311,6 @@ static void dispc_dump_regs(struct seq_file *s)
 #undef DUMPREG
 }
 
-/* with fck as input clock rate, find dispc dividers that produce req_pck */
-void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
-		struct dispc_clock_info *cinfo)
-{
-	u16 pcd_min, pcd_max;
-	unsigned long best_pck;
-	u16 best_ld, cur_ld;
-	u16 best_pd, cur_pd;
-
-	pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
-	pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
-
-	best_pck = 0;
-	best_ld = 0;
-	best_pd = 0;
-
-	for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
-		unsigned long lck = fck / cur_ld;
-
-		for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) {
-			unsigned long pck = lck / cur_pd;
-			long old_delta = abs(best_pck - req_pck);
-			long new_delta = abs(pck - req_pck);
-
-			if (best_pck == 0 || new_delta < old_delta) {
-				best_pck = pck;
-				best_ld = cur_ld;
-				best_pd = cur_pd;
-
-				if (pck == req_pck)
-					goto found;
-			}
-
-			if (pck < req_pck)
-				break;
-		}
-
-		if (lck / pcd_min < req_pck)
-			break;
-	}
-
-found:
-	cinfo->lck_div = best_ld;
-	cinfo->pck_div = best_pd;
-	cinfo->lck = fck / cinfo->lck_div;
-	cinfo->pck = cinfo->lck / cinfo->pck_div;
-}
-
 /* calculate clock rates using dividers in cinfo */
 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 		struct dispc_clock_info *cinfo)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 593022b..46e3d47 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1430,190 +1430,6 @@ static int dsi_calc_clock_rates(struct platform_device *dsidev,
 	return 0;
 }
 
-int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
-		unsigned long req_pck, struct dsi_clock_info *dsi_cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cur, best;
-	struct dispc_clock_info best_dispc;
-	int min_fck_per_pck;
-	int match = 0;
-	unsigned long dss_sys_clk, max_dss_fck;
-
-	dss_sys_clk = clk_get_rate(dsi->sys_clk);
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	if (req_pck == dsi->cache_req_pck &&
-			dsi->cache_cinfo.clkin == dss_sys_clk) {
-		DSSDBG("DSI clock info found from cache\n");
-		*dsi_cinfo = dsi->cache_cinfo;
-		dispc_find_clk_divs(req_pck, dsi_cinfo->dsi_pll_hsdiv_dispc_clk,
-			dispc_cinfo);
-		return 0;
-	}
-
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-
-	if (min_fck_per_pck &&
-		req_pck * min_fck_per_pck > max_dss_fck) {
-		DSSERR("Requested pixel clock not possible with the current "
-				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
-				"the constraint off.\n");
-		min_fck_per_pck = 0;
-	}
-
-	DSSDBG("dsi_pll_calc\n");
-
-retry:
-	memset(&best, 0, sizeof(best));
-	memset(&best_dispc, 0, sizeof(best_dispc));
-
-	memset(&cur, 0, sizeof(cur));
-	cur.clkin = dss_sys_clk;
-
-	/* 0.75MHz < Fint = clkin / regn < 2.1MHz */
-	/* To reduce PLL lock time, keep Fint high (around 2 MHz) */
-	for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
-		cur.fint = cur.clkin / cur.regn;
-
-		if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
-			continue;
-
-		/* DSIPHY(MHz) = (2 * regm / regn) * clkin */
-		for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
-			unsigned long a, b;
-
-			a = 2 * cur.regm * (cur.clkin/1000);
-			b = cur.regn;
-			cur.clkin4ddr = a / b * 1000;
-
-			if (cur.clkin4ddr > 1800 * 1000 * 1000)
-				break;
-
-			/* dsi_pll_hsdiv_dispc_clk(MHz) =
-			 * DSIPHY(MHz) / regm_dispc  < 173MHz/186Mhz */
-			for (cur.regm_dispc = 1; cur.regm_dispc <
-					dsi->regm_dispc_max; ++cur.regm_dispc) {
-				struct dispc_clock_info cur_dispc;
-				cur.dsi_pll_hsdiv_dispc_clk =
-					cur.clkin4ddr / cur.regm_dispc;
-
-				if (cur.regm_dispc > 1 &&
-						cur.regm_dispc % 2 != 0 &&
-						req_pck >= 1000000)
-					continue;
-
-				/* this will narrow down the search a bit,
-				 * but still give pixclocks below what was
-				 * requested */
-				if (cur.dsi_pll_hsdiv_dispc_clk  < req_pck)
-					break;
-
-				if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck)
-					continue;
-
-				if (min_fck_per_pck &&
-					cur.dsi_pll_hsdiv_dispc_clk <
-						req_pck * min_fck_per_pck)
-					continue;
-
-				match = 1;
-
-				dispc_find_clk_divs(req_pck,
-						cur.dsi_pll_hsdiv_dispc_clk,
-						&cur_dispc);
-
-				if (abs(cur_dispc.pck - req_pck) <
-						abs(best_dispc.pck - req_pck)) {
-					best = cur;
-					best_dispc = cur_dispc;
-
-					if (cur_dispc.pck == req_pck)
-						goto found;
-				}
-			}
-		}
-	}
-found:
-	if (!match) {
-		if (min_fck_per_pck) {
-			DSSERR("Could not find suitable clock settings.\n"
-					"Turning FCK/PCK constraint off and"
-					"trying again.\n");
-			min_fck_per_pck = 0;
-			goto retry;
-		}
-
-		DSSERR("Could not find suitable clock settings.\n");
-
-		return -EINVAL;
-	}
-
-	/* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */
-	best.regm_dsi = 0;
-	best.dsi_pll_hsdiv_dsi_clk = 0;
-
-	if (dsi_cinfo)
-		*dsi_cinfo = best;
-	if (dispc_cinfo)
-		*dispc_cinfo = best_dispc;
-
-	dsi->cache_req_pck = req_pck;
-	dsi->cache_clk_freq = 0;
-	dsi->cache_cinfo = best;
-
-	return 0;
-}
-
-static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
-		unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cur, best;
-
-	DSSDBG("dsi_pll_calc_ddrfreq\n");
-
-	memset(&best, 0, sizeof(best));
-	memset(&cur, 0, sizeof(cur));
-
-	cur.clkin = clk_get_rate(dsi->sys_clk);
-
-	for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
-		cur.fint = cur.clkin / cur.regn;
-
-		if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
-			continue;
-
-		/* DSIPHY(MHz) = (2 * regm / regn) * clkin */
-		for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
-			unsigned long a, b;
-
-			a = 2 * cur.regm * (cur.clkin/1000);
-			b = cur.regn;
-			cur.clkin4ddr = a / b * 1000;
-
-			if (cur.clkin4ddr > 1800 * 1000 * 1000)
-				break;
-
-			if (abs(cur.clkin4ddr - req_clkin4ddr) <
-					abs(best.clkin4ddr - req_clkin4ddr)) {
-				best = cur;
-				DSSDBG("best %ld\n", best.clkin4ddr);
-			}
-
-			if (cur.clkin4ddr == req_clkin4ddr)
-				goto found;
-		}
-	}
-found:
-	if (cinfo)
-		*cinfo = best;
-
-	return 0;
-}
-
 static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
 {
 	unsigned long max_dsi_fck;
@@ -1624,90 +1440,6 @@ static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
 	cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
 }
 
-static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
-		unsigned long req_pck, struct dsi_clock_info *cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	unsigned regm_dispc, best_regm_dispc;
-	unsigned long dispc_clk, best_dispc_clk;
-	int min_fck_per_pck;
-	unsigned long max_dss_fck;
-	struct dispc_clock_info best_dispc;
-	bool match;
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-
-	if (min_fck_per_pck &&
-			req_pck * min_fck_per_pck > max_dss_fck) {
-		DSSERR("Requested pixel clock not possible with the current "
-				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
-				"the constraint off.\n");
-		min_fck_per_pck = 0;
-	}
-
-retry:
-	best_regm_dispc = 0;
-	best_dispc_clk = 0;
-	memset(&best_dispc, 0, sizeof(best_dispc));
-	match = false;
-
-	for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
-		struct dispc_clock_info cur_dispc;
-
-		dispc_clk = cinfo->clkin4ddr / regm_dispc;
-
-		/* this will narrow down the search a bit,
-		 * but still give pixclocks below what was
-		 * requested */
-		if (dispc_clk  < req_pck)
-			break;
-
-		if (dispc_clk > max_dss_fck)
-			continue;
-
-		if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
-			continue;
-
-		match = true;
-
-		dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
-
-		if (abs(cur_dispc.pck - req_pck) <
-				abs(best_dispc.pck - req_pck)) {
-			best_regm_dispc = regm_dispc;
-			best_dispc_clk = dispc_clk;
-			best_dispc = cur_dispc;
-
-			if (cur_dispc.pck == req_pck)
-				goto found;
-		}
-	}
-
-	if (!match) {
-		if (min_fck_per_pck) {
-			DSSERR("Could not find suitable clock settings.\n"
-					"Turning FCK/PCK constraint off and"
-					"trying again.\n");
-			min_fck_per_pck = 0;
-			goto retry;
-		}
-
-		DSSERR("Could not find suitable clock settings.\n");
-
-		return -EINVAL;
-	}
-found:
-	cinfo->regm_dispc = best_regm_dispc;
-	cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
-
-	*dispc_cinfo = best_dispc;
-
-	return 0;
-}
-
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo)
 {
@@ -4384,55 +4116,6 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_dsi_configure_pins);
 
-static int dsi_set_clocks(struct omap_dss_device *dssdev,
-		unsigned long ddr_clk, unsigned long lp_clk)
-{
-	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	struct dsi_clock_info cinfo;
-	struct dispc_clock_info dispc_cinfo;
-	unsigned lp_clk_div;
-	unsigned long dsi_fclk;
-	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
-	unsigned long pck;
-	int r;
-
-	DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
-
-	/* Calculate PLL output clock */
-	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
-	if (r)
-		goto err;
-
-	/* Calculate PLL's DSI clock */
-	dsi_pll_calc_dsi_fck(&cinfo);
-
-	/* Calculate PLL's DISPC clock and pck & lck divs */
-	pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
-	DSSDBG("finding dispc dividers for pck %lu\n", pck);
-	r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
-	if (r)
-		goto err;
-
-	/* Calculate LP clock */
-	dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
-	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
-
-	dsi->user_dsi_cinfo.regn = cinfo.regn;
-	dsi->user_dsi_cinfo.regm = cinfo.regm;
-	dsi->user_dsi_cinfo.regm_dispc = cinfo.regm_dispc;
-	dsi->user_dsi_cinfo.regm_dsi = cinfo.regm_dsi;
-
-	dsi->user_dsi_cinfo.lp_clk_div = lp_clk_div;
-
-	dsi->user_dispc_cinfo.lck_div = dispc_cinfo.lck_div;
-	dsi->user_dispc_cinfo.pck_div = dispc_cinfo.pck_div;
-
-	return 0;
-err:
-	return r;
-}
-
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 21a3dc8..ee288f0 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -578,121 +578,6 @@ static int dss_setup_default_clock(void)
 	return 0;
 }
 
-int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	unsigned long prate;
-	struct dss_clock_info best_dss;
-	struct dispc_clock_info best_dispc;
-
-	unsigned long fck, max_dss_fck;
-
-	u16 fck_div;
-
-	int match = 0;
-	int min_fck_per_pck;
-
-	prate = dss_get_dpll4_rate();
-
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
-
-	fck = clk_get_rate(dss.dss_clk);
-	if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
-		dss.cache_dss_cinfo.fck == fck) {
-		DSSDBG("dispc clock info found from cache.\n");
-		*dss_cinfo = dss.cache_dss_cinfo;
-		*dispc_cinfo = dss.cache_dispc_cinfo;
-		return 0;
-	}
-
-	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
-
-	if (min_fck_per_pck &&
-		req_pck * min_fck_per_pck > max_dss_fck) {
-		DSSERR("Requested pixel clock not possible with the current "
-				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
-				"the constraint off.\n");
-		min_fck_per_pck = 0;
-	}
-
-retry:
-	memset(&best_dss, 0, sizeof(best_dss));
-	memset(&best_dispc, 0, sizeof(best_dispc));
-
-	if (dss.dpll4_m4_ck == NULL) {
-		struct dispc_clock_info cur_dispc;
-		/* XXX can we change the clock on omap2? */
-		fck = clk_get_rate(dss.dss_clk);
-		fck_div = 1;
-
-		dispc_find_clk_divs(req_pck, fck, &cur_dispc);
-		match = 1;
-
-		best_dss.fck = fck;
-		best_dss.fck_div = fck_div;
-
-		best_dispc = cur_dispc;
-
-		goto found;
-	} else {
-		for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
-			struct dispc_clock_info cur_dispc;
-
-			fck = prate / fck_div * dss.feat->dss_fck_multiplier;
-
-			if (fck > max_dss_fck)
-				continue;
-
-			if (min_fck_per_pck &&
-					fck < req_pck * min_fck_per_pck)
-				continue;
-
-			match = 1;
-
-			dispc_find_clk_divs(req_pck, fck, &cur_dispc);
-
-			if (abs(cur_dispc.pck - req_pck) <
-					abs(best_dispc.pck - req_pck)) {
-
-				best_dss.fck = fck;
-				best_dss.fck_div = fck_div;
-
-				best_dispc = cur_dispc;
-
-				if (cur_dispc.pck == req_pck)
-					goto found;
-			}
-		}
-	}
-
-found:
-	if (!match) {
-		if (min_fck_per_pck) {
-			DSSERR("Could not find suitable clock settings.\n"
-					"Turning FCK/PCK constraint off and"
-					"trying again.\n");
-			min_fck_per_pck = 0;
-			goto retry;
-		}
-
-		DSSERR("Could not find suitable clock settings.\n");
-
-		return -EINVAL;
-	}
-
-	if (dss_cinfo)
-		*dss_cinfo = best_dss;
-	if (dispc_cinfo)
-		*dispc_cinfo = best_dispc;
-
-	dss.cache_req_pck = req_pck;
-	dss.cache_prate = prate;
-	dss.cache_dss_cinfo = best_dss;
-	dss.cache_dispc_cinfo = best_dispc;
-
-	return 0;
-}
-
 void dss_set_venc_output(enum omap_dss_venc_type type)
 {
 	int l = 0;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index dde6cc1..faaf358 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -268,8 +268,6 @@ void dss_set_dac_pwrdn_bgz(bool enable);
 unsigned long dss_get_dpll4_rate(void);
 int dss_calc_clock_rates(struct dss_clock_info *cinfo);
 int dss_set_clock_div(struct dss_clock_info *cinfo);
-int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
-		struct dispc_clock_info *dispc_cinfo);
 
 typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
 bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
@@ -310,9 +308,6 @@ bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo);
-int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
-		unsigned long req_pck, struct dsi_clock_info *cinfo,
-		struct dispc_clock_info *dispc_cinfo);
 int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
 		bool enable_hsdiv);
 void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
@@ -343,14 +338,6 @@ static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
 	WARN("%s: DSI not compiled in\n", __func__);
 	return -ENODEV;
 }
-static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
-		unsigned long req_pck,
-		struct dsi_clock_info *dsi_cinfo,
-		struct dispc_clock_info *dispc_cinfo)
-{
-	WARN("%s: DSI not compiled in\n", __func__);
-	return -ENODEV;
-}
 static inline int dsi_pll_init(struct platform_device *dsidev,
 		bool enable_hsclk, bool enable_hsdiv)
 {
@@ -400,8 +387,6 @@ bool dispc_div_calc(unsigned long dispc,
 bool dispc_mgr_timings_ok(enum omap_channel channel,
 		const struct omap_video_timings *timings);
 unsigned long dispc_fclk_rate(void);
-void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
-		struct dispc_clock_info *cinfo);
 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 		struct dispc_clock_info *cinfo);
 
-- 
1.7.10.4


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

* [PATCH 14/14] OMAPDSS: remove dsi videomode from dssdev
  2013-03-08 11:52 ` Tomi Valkeinen
@ 2013-03-08 11:52   ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

DSI videomode is no longer needed in the omap_dss_device, so remove it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 include/video/omapdss.h |    1 -
 1 file changed, 1 deletion(-)

diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index cbaf60f..8979086 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -631,7 +631,6 @@ struct omap_dss_device {
 
 		enum omap_dss_dsi_pixel_format dsi_pix_fmt;
 		enum omap_dss_dsi_mode dsi_mode;
-		struct omap_dss_dsi_videomode_timings dsi_vm_timings;
 	} panel;
 
 	struct {
-- 
1.7.10.4


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

* [PATCH 14/14] OMAPDSS: remove dsi videomode from dssdev
@ 2013-03-08 11:52   ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-08 11:52 UTC (permalink / raw)
  To: Archit Taneja, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen

DSI videomode is no longer needed in the omap_dss_device, so remove it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 include/video/omapdss.h |    1 -
 1 file changed, 1 deletion(-)

diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index cbaf60f..8979086 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -631,7 +631,6 @@ struct omap_dss_device {
 
 		enum omap_dss_dsi_pixel_format dsi_pix_fmt;
 		enum omap_dss_dsi_mode dsi_mode;
-		struct omap_dss_dsi_videomode_timings dsi_vm_timings;
 	} panel;
 
 	struct {
-- 
1.7.10.4


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

* Re: [PATCH 01/14] OMAPDSS: DISPC: store core clk rate
  2013-03-08 11:52   ` Tomi Valkeinen
@ 2013-03-20 11:20     ` Archit Taneja
  -1 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-20 11:08 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

Hi,

On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
> Store dispc core clock rate so that it's available for calculations even
> if the HW is disabled.

I think the core_clk_rate variable should change when we change the lcd 
clock source through dss_select_lcd_clk_source() for omap3.

If we have the following sequence:

...
dispc_mgr_set_lcd_divisor();
dss_select_lcd_clk_source();
...

The value of core_clock variable would be based on the previous clock 
source, and not the current one.

This situation doesn't occur currently as the 'apply' framework delays 
all dispc writes to the point when we enable the manager. So the 
sequence above cannot occur. But maybe we should keep this in mind when 
we move more things to omapdrm, where 'apply' isn't in use.

Archit

>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dispc.c |   18 +++++++++---------
>   1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
> index 05ff2b9..f564955 100644
> --- a/drivers/video/omap2/dss/dispc.c
> +++ b/drivers/video/omap2/dss/dispc.c
> @@ -97,6 +97,8 @@ static struct {
>
>   	int irq;
>
> +	unsigned long core_clk_rate;
> +
>   	u32 fifo_size[DISPC_MAX_NR_FIFOS];
>   	/* maps which plane is using a fifo. fifo-id -> plane-id */
>   	int fifo_assignment[DISPC_MAX_NR_FIFOS];
> @@ -2951,6 +2953,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
>
>   	dispc_write_reg(DISPC_DIVISORo(channel),
>   			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
> +
> +	if (dss_has_feature(FEAT_CORE_CLK_DIV) == false &&
> +			channel == OMAP_DSS_CHANNEL_LCD)
> +		dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
>   }
>
>   static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
> @@ -3056,15 +3062,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
>
>   unsigned long dispc_core_clk_rate(void)
>   {
> -	int lcd;
> -	unsigned long fclk = dispc_fclk_rate();
> -
> -	if (dss_has_feature(FEAT_CORE_CLK_DIV))
> -		lcd = REG_GET(DISPC_DIVISOR, 23, 16);
> -	else
> -		lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
> -
> -	return fclk / lcd;
> +	return dispc.core_clk_rate;
>   }
>
>   static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
> @@ -3451,6 +3449,8 @@ static void _omap_dispc_initial_config(void)
>   		l = FLD_MOD(l, 1, 0, 0);
>   		l = FLD_MOD(l, 1, 23, 16);
>   		dispc_write_reg(DISPC_DIVISOR, l);
> +
> +		dispc.core_clk_rate = dispc_fclk_rate();
>   	}
>
>   	/* FUNCGATED */
>


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

* Re: [PATCH 01/14] OMAPDSS: DISPC: store core clk rate
@ 2013-03-20 11:20     ` Archit Taneja
  0 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-20 11:20 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

Hi,

On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
> Store dispc core clock rate so that it's available for calculations even
> if the HW is disabled.

I think the core_clk_rate variable should change when we change the lcd 
clock source through dss_select_lcd_clk_source() for omap3.

If we have the following sequence:

...
dispc_mgr_set_lcd_divisor();
dss_select_lcd_clk_source();
...

The value of core_clock variable would be based on the previous clock 
source, and not the current one.

This situation doesn't occur currently as the 'apply' framework delays 
all dispc writes to the point when we enable the manager. So the 
sequence above cannot occur. But maybe we should keep this in mind when 
we move more things to omapdrm, where 'apply' isn't in use.

Archit

>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dispc.c |   18 +++++++++---------
>   1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
> index 05ff2b9..f564955 100644
> --- a/drivers/video/omap2/dss/dispc.c
> +++ b/drivers/video/omap2/dss/dispc.c
> @@ -97,6 +97,8 @@ static struct {
>
>   	int irq;
>
> +	unsigned long core_clk_rate;
> +
>   	u32 fifo_size[DISPC_MAX_NR_FIFOS];
>   	/* maps which plane is using a fifo. fifo-id -> plane-id */
>   	int fifo_assignment[DISPC_MAX_NR_FIFOS];
> @@ -2951,6 +2953,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
>
>   	dispc_write_reg(DISPC_DIVISORo(channel),
>   			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
> +
> +	if (dss_has_feature(FEAT_CORE_CLK_DIV) = false &&
> +			channel = OMAP_DSS_CHANNEL_LCD)
> +		dispc.core_clk_rate = dispc_fclk_rate() / lck_div;
>   }
>
>   static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
> @@ -3056,15 +3062,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
>
>   unsigned long dispc_core_clk_rate(void)
>   {
> -	int lcd;
> -	unsigned long fclk = dispc_fclk_rate();
> -
> -	if (dss_has_feature(FEAT_CORE_CLK_DIV))
> -		lcd = REG_GET(DISPC_DIVISOR, 23, 16);
> -	else
> -		lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
> -
> -	return fclk / lcd;
> +	return dispc.core_clk_rate;
>   }
>
>   static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
> @@ -3451,6 +3449,8 @@ static void _omap_dispc_initial_config(void)
>   		l = FLD_MOD(l, 1, 0, 0);
>   		l = FLD_MOD(l, 1, 23, 16);
>   		dispc_write_reg(DISPC_DIVISOR, l);
> +
> +		dispc.core_clk_rate = dispc_fclk_rate();
>   	}
>
>   	/* FUNCGATED */
>


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

* Re: [PATCH 03/14] OMAPDSS: DSI: simplify dsi configuration
  2013-03-08 11:52   ` Tomi Valkeinen
@ 2013-03-20 11:36     ` Archit Taneja
  -1 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-20 11:24 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
> We have a bunch of dsi functions that are used to do the basic
> configuration for DSI. To simplify things, and to make sure we have all
> the necessary information, create a single dsi config function, which
> does the basic configuration.

I had split these funcs in the manner so that they could be converted 
into generic output ops or something equivalent to what we anticipated 
CDF to represent encoders. Hence, we may have to split this into smaller 
funcs again later :p

Also, set_size and set_timings were 2 different ops for command and 
video mode panels respectively. omapdss_dsi_set_size() also came in use 
when we supported rotation in Taal. We have an equivalent func for rfbi.

Archit

>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/displays/panel-taal.c |   16 ++++---
>   drivers/video/omap2/dss/dsi.c             |   74 ++++-------------------------
>   include/video/omapdss.h                   |   23 ++++-----
>   3 files changed, 31 insertions(+), 82 deletions(-)
>
> diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
> index bc4c95e..eb86cba 100644
> --- a/drivers/video/omap2/displays/panel-taal.c
> +++ b/drivers/video/omap2/displays/panel-taal.c
> @@ -919,6 +919,13 @@ static int taal_power_on(struct omap_dss_device *dssdev)
>   	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
>   	u8 id1, id2, id3;
>   	int r;
> +	struct omap_dss_dsi_config dsi_config = {
> +		.mode = OMAP_DSS_DSI_CMD_MODE,
> +		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
> +		.timings = &dssdev->panel.timings,
> +		.hs_clk = 216000000,
> +		.lp_clk = 10000000,
> +	};
>
>   	r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
>   	if (r) {
> @@ -926,14 +933,9 @@ static int taal_power_on(struct omap_dss_device *dssdev)
>   		goto err0;
>   	};
>
> -	omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
> -		dssdev->panel.timings.y_res);
> -	omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
> -	omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
> -
> -	r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
> +	r = omapdss_dsi_set_config(dssdev, &dsi_config);
>   	if (r) {
> -		dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
> +		dev_err(&dssdev->dev, "failed to configure DSI\n");
>   		goto err0;
>   	}
>
> diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
> index 5f5b475..901b721 100644
> --- a/drivers/video/omap2/dss/dsi.c
> +++ b/drivers/video/omap2/dss/dsi.c
> @@ -4278,7 +4278,7 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
>   }
>   EXPORT_SYMBOL(omapdss_dsi_configure_pins);
>
> -int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
> +static int dsi_set_clocks(struct omap_dss_device *dssdev,
>   		unsigned long ddr_clk, unsigned long lp_clk)
>   {
>   	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> @@ -4293,8 +4293,6 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
>
>   	DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
>
> -	mutex_lock(&dsi->lock);
> -
>   	/* Calculate PLL output clock */
>   	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
>   	if (r)
> @@ -4336,13 +4334,10 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
>   		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
>   		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
>
> -	mutex_unlock(&dsi->lock);
>   	return 0;
>   err:
> -	mutex_unlock(&dsi->lock);
>   	return r;
>   }
> -EXPORT_SYMBOL(omapdss_dsi_set_clocks);
>
>   int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
>   {
> @@ -4884,75 +4879,26 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
>   }
>   EXPORT_SYMBOL(omapdss_dsi_enable_te);
>
> -void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
> -		struct omap_video_timings *timings)
> +int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
> +		const struct omap_dss_dsi_config *config)
>   {
>   	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
>   	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
>
>   	mutex_lock(&dsi->lock);
>
> -	dsi->timings = *timings;
> -
> -	mutex_unlock(&dsi->lock);
> -}
> -EXPORT_SYMBOL(omapdss_dsi_set_timings);
> -
> -void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
> -{
> -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
> -
> -	mutex_lock(&dsi->lock);
> +	dsi->timings = *config->timings;
> +	dsi->vm_timings = *config->vm_timings;
> +	dsi->pix_fmt = config->pixel_format;
> +	dsi->mode = config->mode;
>
> -	dsi->timings.x_res = w;
> -	dsi->timings.y_res = h;
> +	dsi_set_clocks(dssdev, config->hs_clk, config->lp_clk);
>
>   	mutex_unlock(&dsi->lock);
> -}
> -EXPORT_SYMBOL(omapdss_dsi_set_size);
>
> -void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
> -		enum omap_dss_dsi_pixel_format fmt)
> -{
> -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
> -
> -	mutex_lock(&dsi->lock);
> -
> -	dsi->pix_fmt = fmt;
> -
> -	mutex_unlock(&dsi->lock);
> -}
> -EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
> -
> -void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
> -		enum omap_dss_dsi_mode mode)
> -{
> -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
> -
> -	mutex_lock(&dsi->lock);
> -
> -	dsi->mode = mode;
> -
> -	mutex_unlock(&dsi->lock);
> -}
> -EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
> -
> -void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
> -		struct omap_dss_dsi_videomode_timings *timings)
> -{
> -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
> -
> -	mutex_lock(&dsi->lock);
> -
> -	dsi->vm_timings = *timings;
> -
> -	mutex_unlock(&dsi->lock);
> +	return 0;
>   }
> -EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
> +EXPORT_SYMBOL(omapdss_dsi_set_config);
>
>   /*
>    * Return a hardcoded channel for the DSI output. This should work for
> diff --git a/include/video/omapdss.h b/include/video/omapdss.h
> index 9057e21..4a52197 100644
> --- a/include/video/omapdss.h
> +++ b/include/video/omapdss.h
> @@ -282,6 +282,16 @@ struct omap_dss_dsi_videomode_timings {
>   	int window_sync;
>   };
>
> +struct omap_dss_dsi_config {
> +	enum omap_dss_dsi_mode mode;
> +	enum omap_dss_dsi_pixel_format pixel_format;
> +	const struct omap_video_timings *timings;
> +	const struct omap_dss_dsi_videomode_timings *vm_timings;
> +
> +	unsigned long hs_clk;
> +	unsigned long lp_clk;
> +};
> +
>   void dsi_bus_lock(struct omap_dss_device *dssdev);
>   void dsi_bus_unlock(struct omap_dss_device *dssdev);
>   int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
> @@ -805,15 +815,8 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
>   void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
>   		bool enable);
>   int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
> -void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
> -		struct omap_video_timings *timings);
> -void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
> -void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
> -		enum omap_dss_dsi_pixel_format fmt);
> -void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
> -		enum omap_dss_dsi_mode mode);
> -void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
> -		struct omap_dss_dsi_videomode_timings *timings);
> +int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
> +		const struct omap_dss_dsi_config *config);
>
>   int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
>   		void (*callback)(int, void *), void *data);
> @@ -822,8 +825,6 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
>   void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
>   int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
>   		const struct omap_dsi_pin_config *pin_cfg);
> -int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
> -		unsigned long ddr_clk, unsigned long lp_clk);
>
>   int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
>   void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
>


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

* Re: [PATCH 05/14] OMAPDSS: DSI: add enum omap_dss_dsi_trans_mode
  2013-03-08 11:52   ` Tomi Valkeinen
@ 2013-03-20 11:42     ` Archit Taneja
  -1 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-20 11:30 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
> Instead of managing DSI sync ends with booleans, add an enum for the DSI
> transfer mode. This is much cleaner way to handle the DSI syncs.

This sort of DSI protocol specific enums should definitely get into the 
CDF encoder drivers, maybe even in include/video/mipi_display.h for the 
time CDF is being worked upon.

Archit


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

* Re: [PATCH 01/14] OMAPDSS: DISPC: store core clk rate
  2013-03-20 11:20     ` Archit Taneja
@ 2013-03-20 11:36       ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-20 11:36 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap, linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 1410 bytes --]

On 2013-03-20 13:08, Archit Taneja wrote:
> Hi,
> 
> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>> Store dispc core clock rate so that it's available for calculations even
>> if the HW is disabled.
> 
> I think the core_clk_rate variable should change when we change the lcd
> clock source through dss_select_lcd_clk_source() for omap3.
> 
> If we have the following sequence:
> 
> ...
> dispc_mgr_set_lcd_divisor();
> dss_select_lcd_clk_source();
> ...
> 
> The value of core_clock variable would be based on the previous clock
> source, and not the current one.
> 
> This situation doesn't occur currently as the 'apply' framework delays
> all dispc writes to the point when we enable the manager. So the
> sequence above cannot occur. But maybe we should keep this in mind when
> we move more things to omapdrm, where 'apply' isn't in use.

Hmm. Good point.

I don't think this has to do with apply system. The clock source is set
by the output drivers, and the output drivers also calculate the
divisors, and call the functions to set the divisors. Both DPI and DSI
drivers first set the clock source, and then call the
dss_mgr_set_lcd_config() which sets the divisors (causing the recalc).

Whether using the apply or not, I think it should work correctly. But
it's clearly something that is a bit fragile.
*cough*commonclockframework*cough*.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

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

* Re: [PATCH 01/14] OMAPDSS: DISPC: store core clk rate
@ 2013-03-20 11:36       ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-20 11:36 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap, linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 1410 bytes --]

On 2013-03-20 13:08, Archit Taneja wrote:
> Hi,
> 
> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>> Store dispc core clock rate so that it's available for calculations even
>> if the HW is disabled.
> 
> I think the core_clk_rate variable should change when we change the lcd
> clock source through dss_select_lcd_clk_source() for omap3.
> 
> If we have the following sequence:
> 
> ...
> dispc_mgr_set_lcd_divisor();
> dss_select_lcd_clk_source();
> ...
> 
> The value of core_clock variable would be based on the previous clock
> source, and not the current one.
> 
> This situation doesn't occur currently as the 'apply' framework delays
> all dispc writes to the point when we enable the manager. So the
> sequence above cannot occur. But maybe we should keep this in mind when
> we move more things to omapdrm, where 'apply' isn't in use.

Hmm. Good point.

I don't think this has to do with apply system. The clock source is set
by the output drivers, and the output drivers also calculate the
divisors, and call the functions to set the divisors. Both DPI and DSI
drivers first set the clock source, and then call the
dss_mgr_set_lcd_config() which sets the divisors (causing the recalc).

Whether using the apply or not, I think it should work correctly. But
it's clearly something that is a bit fragile.
*cough*commonclockframework*cough*.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

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

* Re: [PATCH 03/14] OMAPDSS: DSI: simplify dsi configuration
@ 2013-03-20 11:36     ` Archit Taneja
  0 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-20 11:36 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
> We have a bunch of dsi functions that are used to do the basic
> configuration for DSI. To simplify things, and to make sure we have all
> the necessary information, create a single dsi config function, which
> does the basic configuration.

I had split these funcs in the manner so that they could be converted 
into generic output ops or something equivalent to what we anticipated 
CDF to represent encoders. Hence, we may have to split this into smaller 
funcs again later :p

Also, set_size and set_timings were 2 different ops for command and 
video mode panels respectively. omapdss_dsi_set_size() also came in use 
when we supported rotation in Taal. We have an equivalent func for rfbi.

Archit

>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/displays/panel-taal.c |   16 ++++---
>   drivers/video/omap2/dss/dsi.c             |   74 ++++-------------------------
>   include/video/omapdss.h                   |   23 ++++-----
>   3 files changed, 31 insertions(+), 82 deletions(-)
>
> diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
> index bc4c95e..eb86cba 100644
> --- a/drivers/video/omap2/displays/panel-taal.c
> +++ b/drivers/video/omap2/displays/panel-taal.c
> @@ -919,6 +919,13 @@ static int taal_power_on(struct omap_dss_device *dssdev)
>   	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
>   	u8 id1, id2, id3;
>   	int r;
> +	struct omap_dss_dsi_config dsi_config = {
> +		.mode = OMAP_DSS_DSI_CMD_MODE,
> +		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
> +		.timings = &dssdev->panel.timings,
> +		.hs_clk = 216000000,
> +		.lp_clk = 10000000,
> +	};
>
>   	r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
>   	if (r) {
> @@ -926,14 +933,9 @@ static int taal_power_on(struct omap_dss_device *dssdev)
>   		goto err0;
>   	};
>
> -	omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
> -		dssdev->panel.timings.y_res);
> -	omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
> -	omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
> -
> -	r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
> +	r = omapdss_dsi_set_config(dssdev, &dsi_config);
>   	if (r) {
> -		dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
> +		dev_err(&dssdev->dev, "failed to configure DSI\n");
>   		goto err0;
>   	}
>
> diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
> index 5f5b475..901b721 100644
> --- a/drivers/video/omap2/dss/dsi.c
> +++ b/drivers/video/omap2/dss/dsi.c
> @@ -4278,7 +4278,7 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
>   }
>   EXPORT_SYMBOL(omapdss_dsi_configure_pins);
>
> -int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
> +static int dsi_set_clocks(struct omap_dss_device *dssdev,
>   		unsigned long ddr_clk, unsigned long lp_clk)
>   {
>   	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> @@ -4293,8 +4293,6 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
>
>   	DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
>
> -	mutex_lock(&dsi->lock);
> -
>   	/* Calculate PLL output clock */
>   	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
>   	if (r)
> @@ -4336,13 +4334,10 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
>   		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
>   		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
>
> -	mutex_unlock(&dsi->lock);
>   	return 0;
>   err:
> -	mutex_unlock(&dsi->lock);
>   	return r;
>   }
> -EXPORT_SYMBOL(omapdss_dsi_set_clocks);
>
>   int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
>   {
> @@ -4884,75 +4879,26 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
>   }
>   EXPORT_SYMBOL(omapdss_dsi_enable_te);
>
> -void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
> -		struct omap_video_timings *timings)
> +int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
> +		const struct omap_dss_dsi_config *config)
>   {
>   	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
>   	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
>
>   	mutex_lock(&dsi->lock);
>
> -	dsi->timings = *timings;
> -
> -	mutex_unlock(&dsi->lock);
> -}
> -EXPORT_SYMBOL(omapdss_dsi_set_timings);
> -
> -void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
> -{
> -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
> -
> -	mutex_lock(&dsi->lock);
> +	dsi->timings = *config->timings;
> +	dsi->vm_timings = *config->vm_timings;
> +	dsi->pix_fmt = config->pixel_format;
> +	dsi->mode = config->mode;
>
> -	dsi->timings.x_res = w;
> -	dsi->timings.y_res = h;
> +	dsi_set_clocks(dssdev, config->hs_clk, config->lp_clk);
>
>   	mutex_unlock(&dsi->lock);
> -}
> -EXPORT_SYMBOL(omapdss_dsi_set_size);
>
> -void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
> -		enum omap_dss_dsi_pixel_format fmt)
> -{
> -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
> -
> -	mutex_lock(&dsi->lock);
> -
> -	dsi->pix_fmt = fmt;
> -
> -	mutex_unlock(&dsi->lock);
> -}
> -EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
> -
> -void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
> -		enum omap_dss_dsi_mode mode)
> -{
> -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
> -
> -	mutex_lock(&dsi->lock);
> -
> -	dsi->mode = mode;
> -
> -	mutex_unlock(&dsi->lock);
> -}
> -EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
> -
> -void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
> -		struct omap_dss_dsi_videomode_timings *timings)
> -{
> -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
> -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
> -
> -	mutex_lock(&dsi->lock);
> -
> -	dsi->vm_timings = *timings;
> -
> -	mutex_unlock(&dsi->lock);
> +	return 0;
>   }
> -EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
> +EXPORT_SYMBOL(omapdss_dsi_set_config);
>
>   /*
>    * Return a hardcoded channel for the DSI output. This should work for
> diff --git a/include/video/omapdss.h b/include/video/omapdss.h
> index 9057e21..4a52197 100644
> --- a/include/video/omapdss.h
> +++ b/include/video/omapdss.h
> @@ -282,6 +282,16 @@ struct omap_dss_dsi_videomode_timings {
>   	int window_sync;
>   };
>
> +struct omap_dss_dsi_config {
> +	enum omap_dss_dsi_mode mode;
> +	enum omap_dss_dsi_pixel_format pixel_format;
> +	const struct omap_video_timings *timings;
> +	const struct omap_dss_dsi_videomode_timings *vm_timings;
> +
> +	unsigned long hs_clk;
> +	unsigned long lp_clk;
> +};
> +
>   void dsi_bus_lock(struct omap_dss_device *dssdev);
>   void dsi_bus_unlock(struct omap_dss_device *dssdev);
>   int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
> @@ -805,15 +815,8 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
>   void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
>   		bool enable);
>   int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
> -void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
> -		struct omap_video_timings *timings);
> -void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
> -void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
> -		enum omap_dss_dsi_pixel_format fmt);
> -void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
> -		enum omap_dss_dsi_mode mode);
> -void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
> -		struct omap_dss_dsi_videomode_timings *timings);
> +int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
> +		const struct omap_dss_dsi_config *config);
>
>   int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
>   		void (*callback)(int, void *), void *data);
> @@ -822,8 +825,6 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
>   void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
>   int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
>   		const struct omap_dsi_pin_config *pin_cfg);
> -int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
> -		unsigned long ddr_clk, unsigned long lp_clk);
>
>   int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
>   void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
>


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

* Re: [PATCH 05/14] OMAPDSS: DSI: add enum omap_dss_dsi_trans_mode
@ 2013-03-20 11:42     ` Archit Taneja
  0 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-20 11:42 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
> Instead of managing DSI sync ends with booleans, add an enum for the DSI
> transfer mode. This is much cleaner way to handle the DSI syncs.

This sort of DSI protocol specific enums should definitely get into the 
CDF encoder drivers, maybe even in include/video/mipi_display.h for the 
time CDF is being worked upon.

Archit


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

* Re: [PATCH 03/14] OMAPDSS: DSI: simplify dsi configuration
  2013-03-20 11:36     ` Archit Taneja
@ 2013-03-20 11:44       ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-20 11:44 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap, linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 1782 bytes --]

On 2013-03-20 13:24, Archit Taneja wrote:
> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>> We have a bunch of dsi functions that are used to do the basic
>> configuration for DSI. To simplify things, and to make sure we have all
>> the necessary information, create a single dsi config function, which
>> does the basic configuration.
> 
> I had split these funcs in the manner so that they could be converted
> into generic output ops or something equivalent to what we anticipated
> CDF to represent encoders. Hence, we may have to split this into smaller
> funcs again later :p

Well, it was from the CDF discussions that this change arose. Everybody
wanted a simpler way than n+1 functions.

And I think it makes sense. It makes it possible to manage the
configuration as one "whole", instead of small bits that may have
interdependencies. E.g the size of the output affects video mode
calculations, so one had to make the calls in certain order. Now we have
all the needed information in one piece.

We could, perhaps, have common parts between different video busses, but
I'm not sure if configuration is one of those common parts.

> Also, set_size and set_timings were 2 different ops for command and
> video mode panels respectively. omapdss_dsi_set_size() also came in use
> when we supported rotation in Taal. We have an equivalent func for rfbi.

Yep. I felt it's a bit confusing, so I just combined them. Even for
command mode some timing information is good (well, pixel clock), to
calculate proper DSI bus speed.

I think this also works in case of panel rotation. From DSS's point of
view (and that's what we're talking about when setting the timings)
there's no rotation. It's the panel's internal thing.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

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

* Re: [PATCH 03/14] OMAPDSS: DSI: simplify dsi configuration
@ 2013-03-20 11:44       ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-20 11:44 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap, linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 1782 bytes --]

On 2013-03-20 13:24, Archit Taneja wrote:
> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>> We have a bunch of dsi functions that are used to do the basic
>> configuration for DSI. To simplify things, and to make sure we have all
>> the necessary information, create a single dsi config function, which
>> does the basic configuration.
> 
> I had split these funcs in the manner so that they could be converted
> into generic output ops or something equivalent to what we anticipated
> CDF to represent encoders. Hence, we may have to split this into smaller
> funcs again later :p

Well, it was from the CDF discussions that this change arose. Everybody
wanted a simpler way than n+1 functions.

And I think it makes sense. It makes it possible to manage the
configuration as one "whole", instead of small bits that may have
interdependencies. E.g the size of the output affects video mode
calculations, so one had to make the calls in certain order. Now we have
all the needed information in one piece.

We could, perhaps, have common parts between different video busses, but
I'm not sure if configuration is one of those common parts.

> Also, set_size and set_timings were 2 different ops for command and
> video mode panels respectively. omapdss_dsi_set_size() also came in use
> when we supported rotation in Taal. We have an equivalent func for rfbi.

Yep. I felt it's a bit confusing, so I just combined them. Even for
command mode some timing information is good (well, pixel clock), to
calculate proper DSI bus speed.

I think this also works in case of panel rotation. From DSS's point of
view (and that's what we're talking about when setting the timings)
there's no rotation. It's the panel's internal thing.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

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

* Re: [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
  2013-03-08 11:52   ` Tomi Valkeinen
@ 2013-03-20 15:29     ` Archit Taneja
  -1 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-20 15:17 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
> Add new way to iterate over DSS clock divisors. dss_div_calc() provides
> a generic way to go over all the divisors, within given clock range.
> dss_div_calc() will call a callback function for each divider set,
> making the function reusable for all use cases.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dss.c |   36 ++++++++++++++++++++++++++++++++++++
>   drivers/video/omap2/dss/dss.h |    3 +++
>   2 files changed, 39 insertions(+)
>
> diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
> index 054c2a2..21a3dc8 100644
> --- a/drivers/video/omap2/dss/dss.c
> +++ b/drivers/video/omap2/dss/dss.c
> @@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
>   	return 0;
>   }
>
> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
> +{
> +	int fckd, fckd_start, fckd_stop;
> +	unsigned long fck;
> +	unsigned long fck_hw_max;
> +	unsigned long fckd_hw_max;
> +	unsigned long prate;
> +
> +	if (dss.dpll4_m4_ck == NULL) {
> +		/* XXX can we change the clock on omap2? */

We can change dss_fclk1 on omap2, and the cclock2420_data.c and 
cclock2430_data.c have clksel structs which allow a set of dividers. The 
dividers are not continuous though, 1 to 12 and 16 are allowed. So we 
might need to change the code here a bit, if we want to change the clock 
in the first place.

Archit

> +		fck = clk_get_rate(dss.dss_clk);
> +		fckd = 1;
> +
> +		return func(fckd, fck, data);
> +	}
> +
> +	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
> +	fckd_hw_max = dss.feat->fck_div_max;
> +
> +	prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier;
> +
> +	fck_min = fck_min ? fck_min : 1;
> +
> +	fckd_start = min(prate / fck_min, fckd_hw_max);
> +	fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul);
> +
> +	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
> +		fck = prate / fckd;
> +
> +		if (func(fckd, fck, data))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
>   int dss_set_clock_div(struct dss_clock_info *cinfo)
>   {
>   	if (dss.dpll4_m4_ck) {
> diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
> index 0ff41dd..4180302 100644
> --- a/drivers/video/omap2/dss/dss.h
> +++ b/drivers/video/omap2/dss/dss.h
> @@ -271,6 +271,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo);
>   int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
>   		struct dispc_clock_info *dispc_cinfo);
>
> +typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
> +
>   /* SDI */
>   int sdi_init_platform_driver(void) __init;
>   void sdi_uninit_platform_driver(void) __exit;
>


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

* Re: [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
  2013-03-20 15:29     ` Archit Taneja
@ 2013-03-20 15:28       ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-20 15:28 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap, linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 1947 bytes --]

On 2013-03-20 17:17, Archit Taneja wrote:
> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>> Add new way to iterate over DSS clock divisors. dss_div_calc() provides
>> a generic way to go over all the divisors, within given clock range.
>> dss_div_calc() will call a callback function for each divider set,
>> making the function reusable for all use cases.
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> ---
>>   drivers/video/omap2/dss/dss.c |   36
>> ++++++++++++++++++++++++++++++++++++
>>   drivers/video/omap2/dss/dss.h |    3 +++
>>   2 files changed, 39 insertions(+)
>>
>> diff --git a/drivers/video/omap2/dss/dss.c
>> b/drivers/video/omap2/dss/dss.c
>> index 054c2a2..21a3dc8 100644
>> --- a/drivers/video/omap2/dss/dss.c
>> +++ b/drivers/video/omap2/dss/dss.c
>> @@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info
>> *cinfo)
>>       return 0;
>>   }
>>
>> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void
>> *data)
>> +{
>> +    int fckd, fckd_start, fckd_stop;
>> +    unsigned long fck;
>> +    unsigned long fck_hw_max;
>> +    unsigned long fckd_hw_max;
>> +    unsigned long prate;
>> +
>> +    if (dss.dpll4_m4_ck == NULL) {
>> +        /* XXX can we change the clock on omap2? */
> 
> We can change dss_fclk1 on omap2, and the cclock2420_data.c and
> cclock2430_data.c have clksel structs which allow a set of dividers. The
> dividers are not continuous though, 1 to 12 and 16 are allowed. So we
> might need to change the code here a bit, if we want to change the clock
> in the first place.

Ok, good to know. Note that the comment is copied from the old code. I
think I tried changing the clock on N800 with clk_set_rate long ago, but
I didn't get it to work. Things might have changed, but, well, I don't
think we should spend time on omap2 code. I'm sure we'll get a patch if
somebody needs it =).

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

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

* Re: [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
@ 2013-03-20 15:28       ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-20 15:28 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap, linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 1947 bytes --]

On 2013-03-20 17:17, Archit Taneja wrote:
> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>> Add new way to iterate over DSS clock divisors. dss_div_calc() provides
>> a generic way to go over all the divisors, within given clock range.
>> dss_div_calc() will call a callback function for each divider set,
>> making the function reusable for all use cases.
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> ---
>>   drivers/video/omap2/dss/dss.c |   36
>> ++++++++++++++++++++++++++++++++++++
>>   drivers/video/omap2/dss/dss.h |    3 +++
>>   2 files changed, 39 insertions(+)
>>
>> diff --git a/drivers/video/omap2/dss/dss.c
>> b/drivers/video/omap2/dss/dss.c
>> index 054c2a2..21a3dc8 100644
>> --- a/drivers/video/omap2/dss/dss.c
>> +++ b/drivers/video/omap2/dss/dss.c
>> @@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info
>> *cinfo)
>>       return 0;
>>   }
>>
>> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void
>> *data)
>> +{
>> +    int fckd, fckd_start, fckd_stop;
>> +    unsigned long fck;
>> +    unsigned long fck_hw_max;
>> +    unsigned long fckd_hw_max;
>> +    unsigned long prate;
>> +
>> +    if (dss.dpll4_m4_ck == NULL) {
>> +        /* XXX can we change the clock on omap2? */
> 
> We can change dss_fclk1 on omap2, and the cclock2420_data.c and
> cclock2430_data.c have clksel structs which allow a set of dividers. The
> dividers are not continuous though, 1 to 12 and 16 are allowed. So we
> might need to change the code here a bit, if we want to change the clock
> in the first place.

Ok, good to know. Note that the comment is copied from the old code. I
think I tried changing the clock on N800 with clk_set_rate long ago, but
I didn't get it to work. Things might have changed, but, well, I don't
think we should spend time on omap2 code. I'm sure we'll get a patch if
somebody needs it =).

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

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

* Re: [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
@ 2013-03-20 15:29     ` Archit Taneja
  0 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-20 15:29 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
> Add new way to iterate over DSS clock divisors. dss_div_calc() provides
> a generic way to go over all the divisors, within given clock range.
> dss_div_calc() will call a callback function for each divider set,
> making the function reusable for all use cases.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dss.c |   36 ++++++++++++++++++++++++++++++++++++
>   drivers/video/omap2/dss/dss.h |    3 +++
>   2 files changed, 39 insertions(+)
>
> diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
> index 054c2a2..21a3dc8 100644
> --- a/drivers/video/omap2/dss/dss.c
> +++ b/drivers/video/omap2/dss/dss.c
> @@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
>   	return 0;
>   }
>
> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
> +{
> +	int fckd, fckd_start, fckd_stop;
> +	unsigned long fck;
> +	unsigned long fck_hw_max;
> +	unsigned long fckd_hw_max;
> +	unsigned long prate;
> +
> +	if (dss.dpll4_m4_ck = NULL) {
> +		/* XXX can we change the clock on omap2? */

We can change dss_fclk1 on omap2, and the cclock2420_data.c and 
cclock2430_data.c have clksel structs which allow a set of dividers. The 
dividers are not continuous though, 1 to 12 and 16 are allowed. So we 
might need to change the code here a bit, if we want to change the clock 
in the first place.

Archit

> +		fck = clk_get_rate(dss.dss_clk);
> +		fckd = 1;
> +
> +		return func(fckd, fck, data);
> +	}
> +
> +	fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
> +	fckd_hw_max = dss.feat->fck_div_max;
> +
> +	prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier;
> +
> +	fck_min = fck_min ? fck_min : 1;
> +
> +	fckd_start = min(prate / fck_min, fckd_hw_max);
> +	fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul);
> +
> +	for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
> +		fck = prate / fckd;
> +
> +		if (func(fckd, fck, data))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
>   int dss_set_clock_div(struct dss_clock_info *cinfo)
>   {
>   	if (dss.dpll4_m4_ck) {
> diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
> index 0ff41dd..4180302 100644
> --- a/drivers/video/omap2/dss/dss.h
> +++ b/drivers/video/omap2/dss/dss.h
> @@ -271,6 +271,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo);
>   int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
>   		struct dispc_clock_info *dispc_cinfo);
>
> +typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
> +
>   /* SDI */
>   int sdi_init_platform_driver(void) __init;
>   void sdi_uninit_platform_driver(void) __exit;
>


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

* Re: [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
  2013-03-20 15:28       ` Tomi Valkeinen
@ 2013-03-21  6:26         ` Archit Taneja
  -1 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-21  6:14 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

On Wednesday 20 March 2013 08:58 PM, Tomi Valkeinen wrote:
> On 2013-03-20 17:17, Archit Taneja wrote:
>> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>>> Add new way to iterate over DSS clock divisors. dss_div_calc() provides
>>> a generic way to go over all the divisors, within given clock range.
>>> dss_div_calc() will call a callback function for each divider set,
>>> making the function reusable for all use cases.
>>>
>>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>>> ---
>>>    drivers/video/omap2/dss/dss.c |   36
>>> ++++++++++++++++++++++++++++++++++++
>>>    drivers/video/omap2/dss/dss.h |    3 +++
>>>    2 files changed, 39 insertions(+)
>>>
>>> diff --git a/drivers/video/omap2/dss/dss.c
>>> b/drivers/video/omap2/dss/dss.c
>>> index 054c2a2..21a3dc8 100644
>>> --- a/drivers/video/omap2/dss/dss.c
>>> +++ b/drivers/video/omap2/dss/dss.c
>>> @@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info
>>> *cinfo)
>>>        return 0;
>>>    }
>>>
>>> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void
>>> *data)
>>> +{
>>> +    int fckd, fckd_start, fckd_stop;
>>> +    unsigned long fck;
>>> +    unsigned long fck_hw_max;
>>> +    unsigned long fckd_hw_max;
>>> +    unsigned long prate;
>>> +
>>> +    if (dss.dpll4_m4_ck == NULL) {
>>> +        /* XXX can we change the clock on omap2? */
>>
>> We can change dss_fclk1 on omap2, and the cclock2420_data.c and
>> cclock2430_data.c have clksel structs which allow a set of dividers. The
>> dividers are not continuous though, 1 to 12 and 16 are allowed. So we
>> might need to change the code here a bit, if we want to change the clock
>> in the first place.
>
> Ok, good to know. Note that the comment is copied from the old code. I
> think I tried changing the clock on N800 with clk_set_rate long ago, but
> I didn't get it to work. Things might have changed, but, well, I don't
> think we should spend time on omap2 code. I'm sure we'll get a patch if
> somebody needs it =).

We could change the comment to a TODO for now.

Archit


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

* Re: [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
@ 2013-03-21  6:26         ` Archit Taneja
  0 siblings, 0 replies; 48+ messages in thread
From: Archit Taneja @ 2013-03-21  6:26 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev

On Wednesday 20 March 2013 08:58 PM, Tomi Valkeinen wrote:
> On 2013-03-20 17:17, Archit Taneja wrote:
>> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:
>>> Add new way to iterate over DSS clock divisors. dss_div_calc() provides
>>> a generic way to go over all the divisors, within given clock range.
>>> dss_div_calc() will call a callback function for each divider set,
>>> making the function reusable for all use cases.
>>>
>>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>>> ---
>>>    drivers/video/omap2/dss/dss.c |   36
>>> ++++++++++++++++++++++++++++++++++++
>>>    drivers/video/omap2/dss/dss.h |    3 +++
>>>    2 files changed, 39 insertions(+)
>>>
>>> diff --git a/drivers/video/omap2/dss/dss.c
>>> b/drivers/video/omap2/dss/dss.c
>>> index 054c2a2..21a3dc8 100644
>>> --- a/drivers/video/omap2/dss/dss.c
>>> +++ b/drivers/video/omap2/dss/dss.c
>>> @@ -473,6 +473,42 @@ int dss_calc_clock_rates(struct dss_clock_info
>>> *cinfo)
>>>        return 0;
>>>    }
>>>
>>> +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void
>>> *data)
>>> +{
>>> +    int fckd, fckd_start, fckd_stop;
>>> +    unsigned long fck;
>>> +    unsigned long fck_hw_max;
>>> +    unsigned long fckd_hw_max;
>>> +    unsigned long prate;
>>> +
>>> +    if (dss.dpll4_m4_ck = NULL) {
>>> +        /* XXX can we change the clock on omap2? */
>>
>> We can change dss_fclk1 on omap2, and the cclock2420_data.c and
>> cclock2430_data.c have clksel structs which allow a set of dividers. The
>> dividers are not continuous though, 1 to 12 and 16 are allowed. So we
>> might need to change the code here a bit, if we want to change the clock
>> in the first place.
>
> Ok, good to know. Note that the comment is copied from the old code. I
> think I tried changing the clock on N800 with clk_set_rate long ago, but
> I didn't get it to work. Things might have changed, but, well, I don't
> think we should spend time on omap2 code. I'm sure we'll get a patch if
> somebody needs it =).

We could change the comment to a TODO for now.

Archit


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

* Re: [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
  2013-03-21  6:26         ` Archit Taneja
@ 2013-03-21  8:13           ` Tomi Valkeinen
  -1 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-21  8:13 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap, linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 1093 bytes --]

On 2013-03-21 08:14, Archit Taneja wrote:
> On Wednesday 20 March 2013 08:58 PM, Tomi Valkeinen wrote:
>> On 2013-03-20 17:17, Archit Taneja wrote:
>>> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:

>>>> +    if (dss.dpll4_m4_ck == NULL) {
>>>> +        /* XXX can we change the clock on omap2? */
>>>
>>> We can change dss_fclk1 on omap2, and the cclock2420_data.c and
>>> cclock2430_data.c have clksel structs which allow a set of dividers. The
>>> dividers are not continuous though, 1 to 12 and 16 are allowed. So we
>>> might need to change the code here a bit, if we want to change the clock
>>> in the first place.
>>
>> Ok, good to know. Note that the comment is copied from the old code. I
>> think I tried changing the clock on N800 with clk_set_rate long ago, but
>> I didn't get it to work. Things might have changed, but, well, I don't
>> think we should spend time on omap2 code. I'm sure we'll get a patch if
>> somebody needs it =).
> 
> We could change the comment to a TODO for now.

Yep, not a bad idea. I'll make the change.

 Tomi




[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

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

* Re: [PATCH 08/14] OMAPDSS: DSS: add new clock calculation code
@ 2013-03-21  8:13           ` Tomi Valkeinen
  0 siblings, 0 replies; 48+ messages in thread
From: Tomi Valkeinen @ 2013-03-21  8:13 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap, linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 1093 bytes --]

On 2013-03-21 08:14, Archit Taneja wrote:
> On Wednesday 20 March 2013 08:58 PM, Tomi Valkeinen wrote:
>> On 2013-03-20 17:17, Archit Taneja wrote:
>>> On Friday 08 March 2013 05:22 PM, Tomi Valkeinen wrote:

>>>> +    if (dss.dpll4_m4_ck == NULL) {
>>>> +        /* XXX can we change the clock on omap2? */
>>>
>>> We can change dss_fclk1 on omap2, and the cclock2420_data.c and
>>> cclock2430_data.c have clksel structs which allow a set of dividers. The
>>> dividers are not continuous though, 1 to 12 and 16 are allowed. So we
>>> might need to change the code here a bit, if we want to change the clock
>>> in the first place.
>>
>> Ok, good to know. Note that the comment is copied from the old code. I
>> think I tried changing the clock on N800 with clk_set_rate long ago, but
>> I didn't get it to work. Things might have changed, but, well, I don't
>> think we should spend time on omap2 code. I'm sure we'll get a patch if
>> somebody needs it =).
> 
> We could change the comment to a TODO for now.

Yep, not a bad idea. I'll make the change.

 Tomi




[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

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

end of thread, other threads:[~2013-03-21  8:13 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-08 11:52 [PATCH 00/14] OMAPDSS: new clock calculation + DSI VM Tomi Valkeinen
2013-03-08 11:52 ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 01/14] OMAPDSS: DISPC: store core clk rate Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-20 11:08   ` Archit Taneja
2013-03-20 11:20     ` Archit Taneja
2013-03-20 11:36     ` Tomi Valkeinen
2013-03-20 11:36       ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 02/14] OMAPDSS: DSI: fix wrong unsigned long long use Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 03/14] OMAPDSS: DSI: simplify dsi configuration Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-20 11:24   ` Archit Taneja
2013-03-20 11:36     ` Archit Taneja
2013-03-20 11:44     ` Tomi Valkeinen
2013-03-20 11:44       ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 04/14] OMAPDSS: DSI: get line buffer size at probe Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 05/14] OMAPDSS: DSI: add enum omap_dss_dsi_trans_mode Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-20 11:30   ` Archit Taneja
2013-03-20 11:42     ` Archit Taneja
2013-03-08 11:52 ` [PATCH 06/14] OMAPDSS: DSI remove unneeded clk source setup code Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 07/14] OMAPDSS: DISPC: add new clock calculation code Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 08/14] OMAPDSS: DSS: " Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-20 15:17   ` Archit Taneja
2013-03-20 15:29     ` Archit Taneja
2013-03-20 15:28     ` Tomi Valkeinen
2013-03-20 15:28       ` Tomi Valkeinen
2013-03-21  6:14       ` Archit Taneja
2013-03-21  6:26         ` Archit Taneja
2013-03-21  8:13         ` Tomi Valkeinen
2013-03-21  8:13           ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 09/14] OMAPDSS: DSI: " Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 10/14] OMAPDSS: SDI: use " Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 11/14] OMAPDSS: DPI: " Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 12/14] OMAPDSS: DSI: " Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 13/14] OMAPDSS: remove unused old " Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen
2013-03-08 11:52 ` [PATCH 14/14] OMAPDSS: remove dsi videomode from dssdev Tomi Valkeinen
2013-03-08 11:52   ` Tomi Valkeinen

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.