* [PATCH 0/7] OMAPDSS: func clock handling improvements
From: Tomi Valkeinen @ 2013-11-18 12:38 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
Some of the new TI SoCs using DSS have a dedicated PLL for the DSS functional
clock. This series adds support to omapdss for that kind of clocking scheme.
This series also needs the following commits, which are now in mainline, to
work:
ARM: OMAP3: fix dpll4_m3_ck and dpll4_m4_ck dividers
ARM: OMAP3: use CLK_SET_RATE_PARENT for dss clocks
ARM: OMAP4: use CLK_SET_RATE_PARENT for dss_dss_clk
Tomi
Tomi Valkeinen (7):
OMAPDSS: fix omap2 dss fck handling
OMAPDSS: remove struct dss_clock_info
OMAPDSS: simplify dss clk dump
OMAPDSS: rename parent clk variables
OMAPDSS: cleanup fck parent handling
OMAPDSS: pass pck to dss fck clock calc
OMAPDSS: add dedicated fck PLL support
drivers/video/omap2/dss/dpi.c | 15 ++--
drivers/video/omap2/dss/dss.c | 163 ++++++++++++++----------------------------
drivers/video/omap2/dss/dss.h | 17 ++---
drivers/video/omap2/dss/sdi.c | 21 +++---
4 files changed, 76 insertions(+), 140 deletions(-)
--
1.8.3.2
^ permalink raw reply
* [PATCH 1/7] OMAPDSS: fix omap2 dss fck handling
From: Tomi Valkeinen @ 2013-11-18 12:38 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778344-8226-1-git-send-email-tomi.valkeinen@ti.com>
The driver considers OMAP2 DSS's functional clock as a fixed clock.
However, it can be changed, but the possible dividers are not continuous
which is why it was just handled as a fixed clock.
As a partial fix, this patch changes the code to handle the continous
part of the dividers, from 1 to 6. This let's us handle the OMAP2 fck
the same way as fcks on other OMAPs.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dss.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index bd01608..e59577a 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -484,11 +484,6 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
unsigned m;
if (dss.dpll4_m4_ck = NULL) {
- /*
- * TODO: dss1_fclk can be changed on OMAP2, but the available
- * dividers are not continuous. We just use the pre-set rate for
- * now.
- */
fck = clk_get_rate(dss.dss_clk);
fckd = 1;
return func(fckd, fck, data);
@@ -761,9 +756,13 @@ void dss_debug_dump_clocks(struct seq_file *s)
#endif
static const struct dss_features omap24xx_dss_feats __initconst = {
- .fck_div_max = 16,
+ /*
+ * fck div max is really 16, but the divider range has gaps. The range
+ * from 1 to 6 has no gaps, so let's use that as a max.
+ */
+ .fck_div_max = 6,
.dss_fck_multiplier = 2,
- .clk_name = NULL,
+ .clk_name = "dss1_fck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
};
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/7] OMAPDSS: remove struct dss_clock_info
From: Tomi Valkeinen @ 2013-11-18 12:38 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778344-8226-1-git-send-email-tomi.valkeinen@ti.com>
Remove struct dss_clock_info, as it is not usable in a case where DSS
fclk comes from a dedicated PLL. Instead, just use the fclk rate in
place of dss_clock_info, as that is all that's needed.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dpi.c | 13 +++++-----
drivers/video/omap2/dss/dss.c | 59 ++++++++++---------------------------------
drivers/video/omap2/dss/dss.h | 13 ++--------
drivers/video/omap2/dss/sdi.c | 19 +++++++-------
4 files changed, 30 insertions(+), 74 deletions(-)
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index bd48cde..16acddd 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -117,7 +117,7 @@ struct dpi_clk_calc_ctx {
/* outputs */
struct dsi_clock_info dsi_cinfo;
- struct dss_clock_info dss_cinfo;
+ unsigned long long fck;
struct dispc_clock_info dispc_cinfo;
};
@@ -184,12 +184,11 @@ static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
dpi_calc_hsdiv_cb, ctx);
}
-static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
+static bool dpi_calc_dss_cb(unsigned long fck, void *data)
{
struct dpi_clk_calc_ctx *ctx = data;
- ctx->dss_cinfo.fck = fck;
- ctx->dss_cinfo.fck_div = fckd;
+ ctx->fck = fck;
return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
dpi_calc_dispc_cb, ctx);
@@ -286,13 +285,13 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
if (!ok)
return -EINVAL;
- r = dss_set_clock_div(&ctx.dss_cinfo);
+ r = dss_set_fck_rate(ctx.fck);
if (r)
return r;
dpi.mgr_config.clock_info = ctx.dispc_cinfo;
- *fck = ctx.dss_cinfo.fck;
+ *fck = ctx.fck;
*lck_div = ctx.dispc_cinfo.lck_div;
*pck_div = ctx.dispc_cinfo.pck_div;
@@ -495,7 +494,7 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
if (!ok)
return -EINVAL;
- fck = ctx.dss_cinfo.fck;
+ fck = ctx.fck;
}
lck_div = ctx.dispc_cinfo.lck_div;
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index e59577a..c37d934 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -81,7 +81,6 @@ static struct {
unsigned long cache_req_pck;
unsigned long cache_prate;
- struct dss_clock_info cache_dss_cinfo;
struct dispc_clock_info cache_dispc_cinfo;
enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
@@ -451,29 +450,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
}
}
-/* calculate clock rates using dividers in cinfo */
-int dss_calc_clock_rates(struct dss_clock_info *cinfo)
-{
- if (dss.dpll4_m4_ck) {
- unsigned long prate;
-
- if (cinfo->fck_div > dss.feat->fck_div_max ||
- cinfo->fck_div = 0)
- return -EINVAL;
-
- prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-
- cinfo->fck = prate / cinfo->fck_div *
- dss.feat->dss_fck_multiplier;
- } else {
- if (cinfo->fck_div != 0)
- return -EINVAL;
- cinfo->fck = clk_get_rate(dss.dss_clk);
- }
-
- return 0;
-}
-
bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
{
int fckd, fckd_start, fckd_stop;
@@ -485,8 +461,7 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
if (dss.dpll4_m4_ck = NULL) {
fck = clk_get_rate(dss.dss_clk);
- fckd = 1;
- return func(fckd, fck, data);
+ return func(fck, data);
}
fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
@@ -503,38 +478,35 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
fck = prate / fckd * m;
- if (func(fckd, fck, data))
+ if (func(fck, data))
return true;
}
return false;
}
-int dss_set_clock_div(struct dss_clock_info *cinfo)
+int dss_set_fck_rate(unsigned long rate)
{
+ DSSDBG("set fck to %lu\n", rate);
+
if (dss.dpll4_m4_ck) {
unsigned long prate;
+ unsigned m;
int r;
prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
- DSSDBG("dpll4_m4 = %ld\n", prate);
+ m = dss.feat->dss_fck_multiplier;
- r = clk_set_rate(dss.dpll4_m4_ck,
- DIV_ROUND_UP(prate, cinfo->fck_div));
+ r = clk_set_rate(dss.dpll4_m4_ck, rate * m);
if (r)
return r;
- } else {
- if (cinfo->fck_div != 0)
- return -EINVAL;
}
dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
- WARN_ONCE(dss.dss_clk_rate != cinfo->fck,
+ WARN_ONCE(dss.dss_clk_rate != rate,
"clk rate mismatch: %lu != %lu", dss.dss_clk_rate,
- cinfo->fck);
-
- DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
+ rate);
return 0;
}
@@ -555,8 +527,8 @@ unsigned long dss_get_dispc_clk_rate(void)
static int dss_setup_default_clock(void)
{
unsigned long max_dss_fck, prate;
+ unsigned long fck;
unsigned fck_div;
- struct dss_clock_info dss_cinfo = { 0 };
int r;
if (dss.dpll4_m4_ck = NULL)
@@ -568,14 +540,9 @@ static int dss_setup_default_clock(void)
fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
max_dss_fck);
+ fck = prate / fck_div * dss.feat->dss_fck_multiplier;
- dss_cinfo.fck_div = fck_div;
-
- r = dss_calc_clock_rates(&dss_cinfo);
- if (r)
- return r;
-
- r = dss_set_clock_div(&dss_cinfo);
+ r = dss_set_fck_rate(fck);
if (r)
return r;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index e172531..ead1960 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -100,14 +100,6 @@ enum dss_writeback_channel {
DSS_WB_LCD3_MGR = 7,
};
-struct dss_clock_info {
- /* rates that we get with dividers below */
- unsigned long fck;
-
- /* dividers */
- u16 fck_div;
-};
-
struct dispc_clock_info {
/* rates that we get with dividers below */
unsigned long lck;
@@ -251,10 +243,9 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
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_set_fck_rate(unsigned long rate);
-typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data);
+typedef bool (*dss_div_calc_func)(unsigned long fck, void *data);
bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
/* SDI */
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index ccc569a..221fd34 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -46,7 +46,7 @@ static struct {
struct sdi_clk_calc_ctx {
unsigned long pck_min, pck_max;
- struct dss_clock_info dss_cinfo;
+ unsigned long long fck;
struct dispc_clock_info dispc_cinfo;
};
@@ -63,19 +63,18 @@ static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
return true;
}
-static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
+static bool dpi_calc_dss_cb(unsigned long fck, void *data)
{
struct sdi_clk_calc_ctx *ctx = data;
- ctx->dss_cinfo.fck = fck;
- ctx->dss_cinfo.fck_div = fckd;
+ ctx->fck = fck;
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,
+ unsigned long *fck,
struct dispc_clock_info *dispc_cinfo)
{
int i;
@@ -100,7 +99,7 @@ static int sdi_calc_clock_div(unsigned long pclk,
ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx);
if (ok) {
- *dss_cinfo = ctx.dss_cinfo;
+ *fck = ctx.fck;
*dispc_cinfo = ctx.dispc_cinfo;
return 0;
}
@@ -128,7 +127,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *out = &sdi.output;
struct omap_video_timings *t = &sdi.timings;
- struct dss_clock_info dss_cinfo;
+ unsigned long fck;
struct dispc_clock_info dispc_cinfo;
unsigned long pck;
int r;
@@ -150,13 +149,13 @@ static int 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 = sdi_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
+ r = sdi_calc_clock_div(t->pixel_clock * 1000, &fck, &dispc_cinfo);
if (r)
goto err_calc_clock_div;
sdi.mgr_config.clock_info = dispc_cinfo;
- pck = dss_cinfo.fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div / 1000;
+ pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div / 1000;
if (pck != t->pixel_clock) {
DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
@@ -169,7 +168,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
dss_mgr_set_timings(out->manager, t);
- r = dss_set_clock_div(&dss_cinfo);
+ r = dss_set_fck_rate(fck);
if (r)
goto err_set_dss_clock_div;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/7] OMAPDSS: simplify dss clk dump
From: Tomi Valkeinen @ 2013-11-18 12:39 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778344-8226-1-git-send-email-tomi.valkeinen@ti.com>
Simplify dss_dump_clocks() so that it doesn't make any presumptions
about the DSS fclks nature.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dss.c | 20 +++-----------------
1 file changed, 3 insertions(+), 17 deletions(-)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index c37d934..3dea532 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -264,8 +264,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
void dss_dump_clocks(struct seq_file *s)
{
- unsigned long dpll4_ck_rate;
- unsigned long dpll4_m4_ck_rate;
const char *fclk_name, *fclk_real_name;
unsigned long fclk_rate;
@@ -278,21 +276,9 @@ void dss_dump_clocks(struct seq_file *s)
fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
fclk_rate = clk_get_rate(dss.dss_clk);
- if (dss.dpll4_m4_ck) {
- dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
- dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
-
- seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
-
- seq_printf(s, "%s (%s) = %lu / %lu * %d = %lu\n",
- fclk_name, fclk_real_name, dpll4_ck_rate,
- dpll4_ck_rate / dpll4_m4_ck_rate,
- dss.feat->dss_fck_multiplier, fclk_rate);
- } else {
- seq_printf(s, "%s (%s) = %lu\n",
- fclk_name, fclk_real_name,
- fclk_rate);
- }
+ seq_printf(s, "%s (%s) = %lu\n",
+ fclk_name, fclk_real_name,
+ fclk_rate);
dss_runtime_put();
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 4/7] OMAPDSS: rename parent clk variables
From: Tomi Valkeinen @ 2013-11-18 12:39 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778344-8226-1-git-send-email-tomi.valkeinen@ti.com>
Rename the variables related to DSS fclk's parent: "clk_name" and
"dpll4_m4_ck", to "parent_clk_name" and "parent_clk", which much better
tell what they mean.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dss.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 3dea532..d510ba3 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -67,7 +67,7 @@ static void dss_runtime_put(void);
struct dss_features {
u8 fck_div_max;
u8 dss_fck_multiplier;
- const char *clk_name;
+ const char *parent_clk_name;
int (*dpi_select_source)(enum omap_channel channel);
};
@@ -75,7 +75,7 @@ static struct {
struct platform_device *pdev;
void __iomem *base;
- struct clk *dpll4_m4_ck;
+ struct clk *parent_clk;
struct clk *dss_clk;
unsigned long dss_clk_rate;
@@ -445,7 +445,7 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
unsigned long prate;
unsigned m;
- if (dss.dpll4_m4_ck = NULL) {
+ if (dss.parent_clk = NULL) {
fck = clk_get_rate(dss.dss_clk);
return func(fck, data);
}
@@ -475,15 +475,15 @@ int dss_set_fck_rate(unsigned long rate)
{
DSSDBG("set fck to %lu\n", rate);
- if (dss.dpll4_m4_ck) {
+ if (dss.parent_clk) {
unsigned long prate;
unsigned m;
int r;
- prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
+ prate = clk_get_rate(clk_get_parent(dss.parent_clk));
m = dss.feat->dss_fck_multiplier;
- r = clk_set_rate(dss.dpll4_m4_ck, rate * m);
+ r = clk_set_rate(dss.parent_clk, rate * m);
if (r)
return r;
}
@@ -499,8 +499,8 @@ int dss_set_fck_rate(unsigned long rate)
unsigned long dss_get_dpll4_rate(void)
{
- if (dss.dpll4_m4_ck)
- return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
+ if (dss.parent_clk)
+ return clk_get_rate(clk_get_parent(dss.parent_clk));
else
return 0;
}
@@ -517,7 +517,7 @@ static int dss_setup_default_clock(void)
unsigned fck_div;
int r;
- if (dss.dpll4_m4_ck = NULL)
+ if (dss.parent_clk = NULL)
return 0;
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
@@ -654,25 +654,25 @@ static int dss_get_clocks(void)
dss.dss_clk = clk;
- if (dss.feat->clk_name) {
- clk = clk_get(NULL, dss.feat->clk_name);
+ if (dss.feat->parent_clk_name) {
+ clk = clk_get(NULL, dss.feat->parent_clk_name);
if (IS_ERR(clk)) {
- DSSERR("Failed to get %s\n", dss.feat->clk_name);
+ DSSERR("Failed to get %s\n", dss.feat->parent_clk_name);
return PTR_ERR(clk);
}
} else {
clk = NULL;
}
- dss.dpll4_m4_ck = clk;
+ dss.parent_clk = clk;
return 0;
}
static void dss_put_clocks(void)
{
- if (dss.dpll4_m4_ck)
- clk_put(dss.dpll4_m4_ck);
+ if (dss.parent_clk)
+ clk_put(dss.parent_clk);
}
static int dss_runtime_get(void)
@@ -715,35 +715,35 @@ static const struct dss_features omap24xx_dss_feats __initconst = {
*/
.fck_div_max = 6,
.dss_fck_multiplier = 2,
- .clk_name = "dss1_fck",
+ .parent_clk_name = "dss1_fck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
};
static const struct dss_features omap34xx_dss_feats __initconst = {
.fck_div_max = 16,
.dss_fck_multiplier = 2,
- .clk_name = "dpll4_m4_ck",
+ .parent_clk_name = "dpll4_m4_ck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
};
static const struct dss_features omap3630_dss_feats __initconst = {
.fck_div_max = 32,
.dss_fck_multiplier = 1,
- .clk_name = "dpll4_m4_ck",
+ .parent_clk_name = "dpll4_m4_ck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
};
static const struct dss_features omap44xx_dss_feats __initconst = {
.fck_div_max = 32,
.dss_fck_multiplier = 1,
- .clk_name = "dpll_per_m5x2_ck",
+ .parent_clk_name = "dpll_per_m5x2_ck",
.dpi_select_source = &dss_dpi_select_source_omap4,
};
static const struct dss_features omap54xx_dss_feats __initconst = {
.fck_div_max = 64,
.dss_fck_multiplier = 1,
- .clk_name = "dpll_per_h12x2_ck",
+ .parent_clk_name = "dpll_per_h12x2_ck",
.dpi_select_source = &dss_dpi_select_source_omap5,
};
--
1.8.3.2
^ permalink raw reply related
* [PATCH 5/7] OMAPDSS: cleanup fck parent handling
From: Tomi Valkeinen @ 2013-11-18 12:39 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778344-8226-1-git-send-email-tomi.valkeinen@ti.com>
The dss parent_clk_name currently points to a clock node which we use to
change the fclk rate. Now that we have CLK_SET_RATE_PARENT properly set,
we can set the rate directly to the fclk node.
However, we still need to calculate the possible clock rates. For this,
we need the rate of the parent of the current parent_clk.
To simplify the code, this patch changes the parent_clk_name to point to
the above mentioned parent, so that we can get the rate directly.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dss.c | 39 ++++++++++++---------------------------
drivers/video/omap2/dss/dss.h | 1 -
2 files changed, 12 insertions(+), 28 deletions(-)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index d510ba3..7af9719 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -454,7 +454,7 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
fckd_hw_max = dss.feat->fck_div_max;
m = dss.feat->dss_fck_multiplier;
- prate = dss_get_dpll4_rate();
+ prate = clk_get_rate(dss.parent_clk);
fck_min = fck_min ? fck_min : 1;
@@ -473,20 +473,13 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
int dss_set_fck_rate(unsigned long rate)
{
- DSSDBG("set fck to %lu\n", rate);
-
- if (dss.parent_clk) {
- unsigned long prate;
- unsigned m;
- int r;
+ int r;
- prate = clk_get_rate(clk_get_parent(dss.parent_clk));
- m = dss.feat->dss_fck_multiplier;
+ DSSDBG("set fck to %lu\n", rate);
- r = clk_set_rate(dss.parent_clk, rate * m);
- if (r)
- return r;
- }
+ r = clk_set_rate(dss.dss_clk, rate);
+ if (r)
+ return r;
dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
@@ -497,14 +490,6 @@ int dss_set_fck_rate(unsigned long rate)
return 0;
}
-unsigned long dss_get_dpll4_rate(void)
-{
- if (dss.parent_clk)
- return clk_get_rate(clk_get_parent(dss.parent_clk));
- else
- return 0;
-}
-
unsigned long dss_get_dispc_clk_rate(void)
{
return dss.dss_clk_rate;
@@ -522,7 +507,7 @@ static int dss_setup_default_clock(void)
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
- prate = dss_get_dpll4_rate();
+ prate = clk_get_rate(dss.parent_clk);
fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
max_dss_fck);
@@ -715,35 +700,35 @@ static const struct dss_features omap24xx_dss_feats __initconst = {
*/
.fck_div_max = 6,
.dss_fck_multiplier = 2,
- .parent_clk_name = "dss1_fck",
+ .parent_clk_name = "core_ck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
};
static const struct dss_features omap34xx_dss_feats __initconst = {
.fck_div_max = 16,
.dss_fck_multiplier = 2,
- .parent_clk_name = "dpll4_m4_ck",
+ .parent_clk_name = "dpll4_ck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
};
static const struct dss_features omap3630_dss_feats __initconst = {
.fck_div_max = 32,
.dss_fck_multiplier = 1,
- .parent_clk_name = "dpll4_m4_ck",
+ .parent_clk_name = "dpll4_ck",
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
};
static const struct dss_features omap44xx_dss_feats __initconst = {
.fck_div_max = 32,
.dss_fck_multiplier = 1,
- .parent_clk_name = "dpll_per_m5x2_ck",
+ .parent_clk_name = "dpll_per_x2_ck",
.dpi_select_source = &dss_dpi_select_source_omap4,
};
static const struct dss_features omap54xx_dss_feats __initconst = {
.fck_div_max = 64,
.dss_fck_multiplier = 1,
- .parent_clk_name = "dpll_per_h12x2_ck",
+ .parent_clk_name = "dpll_per_x2_ck",
.dpi_select_source = &dss_dpi_select_source_omap5,
};
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index ead1960..6fc786f 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -242,7 +242,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
void dss_set_venc_output(enum omap_dss_venc_type type);
void dss_set_dac_pwrdn_bgz(bool enable);
-unsigned long dss_get_dpll4_rate(void);
int dss_set_fck_rate(unsigned long rate);
typedef bool (*dss_div_calc_func)(unsigned long fck, void *data);
--
1.8.3.2
^ permalink raw reply related
* [PATCH 6/7] OMAPDSS: pass pck to dss fck clock calc
From: Tomi Valkeinen @ 2013-11-18 12:39 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778344-8226-1-git-send-email-tomi.valkeinen@ti.com>
We need the required pixel clock rate when calculating the dss fclk on
SoCs that have a dedicated DSS PLL.
This patch changes the code to pass the pck to the calc functions. The
pck rate is taken into use in the next patch.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dpi.c | 2 +-
drivers/video/omap2/dss/dss.c | 3 ++-
drivers/video/omap2/dss/dss.h | 3 ++-
drivers/video/omap2/dss/sdi.c | 2 +-
4 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 16acddd..ae1c8b9 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -236,7 +236,7 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
ctx->pck_min = 0;
ctx->pck_max = pck + 1000 * i * i * i;
- ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx);
+ ok = dss_div_calc(pck, ctx->pck_min, dpi_calc_dss_cb, ctx);
if (ok)
return ok;
}
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 7af9719..08c58eb 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -436,7 +436,8 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
}
}
-bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data)
+bool dss_div_calc(unsigned long pck, unsigned long fck_min,
+ dss_div_calc_func func, void *data)
{
int fckd, fckd_start, fckd_stop;
unsigned long fck;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6fc786f..2acc661 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -245,7 +245,8 @@ void dss_set_dac_pwrdn_bgz(bool enable);
int dss_set_fck_rate(unsigned long rate);
typedef bool (*dss_div_calc_func)(unsigned long fck, void *data);
-bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data);
+bool dss_div_calc(unsigned long pck, unsigned long fck_min,
+ dss_div_calc_func func, void *data);
/* SDI */
int sdi_init_platform_driver(void) __init;
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 221fd34..3bf47c9 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -97,7 +97,7 @@ static int sdi_calc_clock_div(unsigned long pclk,
ctx.pck_min = 0;
ctx.pck_max = pclk + 1000 * i * i * i;
- ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx);
+ ok = dss_div_calc(pclk, ctx.pck_min, dpi_calc_dss_cb, &ctx);
if (ok) {
*fck = ctx.fck;
*dispc_cinfo = ctx.dispc_cinfo;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 7/7] OMAPDSS: add dedicated fck PLL support
From: Tomi Valkeinen @ 2013-11-18 12:39 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778344-8226-1-git-send-email-tomi.valkeinen@ti.com>
This patch adds support for SoCs that have a dedicated DSS PLL used for
DSS function clock.
If there is no dss parent clock defined, it is presumed that the
functionl clock rate can be set (almost) freely. The code calculates the
highest allowed fck rate, which when divided with some integer gives the
required pck.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dss.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 08c58eb..9a145da 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -446,12 +446,20 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
unsigned long prate;
unsigned m;
+ fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
if (dss.parent_clk = NULL) {
- fck = clk_get_rate(dss.dss_clk);
+ unsigned pckd;
+
+ pckd = fck_hw_max / pck;
+
+ fck = pck * pckd;
+
+ fck = clk_round_rate(dss.dss_clk, fck);
+
return func(fck, data);
}
- fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
fckd_hw_max = dss.feat->fck_div_max;
m = dss.feat->dss_fck_multiplier;
@@ -503,16 +511,17 @@ static int dss_setup_default_clock(void)
unsigned fck_div;
int r;
- if (dss.parent_clk = NULL)
- return 0;
-
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
- prate = clk_get_rate(dss.parent_clk);
+ if (dss.parent_clk = NULL) {
+ fck = clk_round_rate(dss.dss_clk, max_dss_fck);
+ } else {
+ prate = clk_get_rate(dss.parent_clk);
- fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
- max_dss_fck);
- fck = prate / fck_div * dss.feat->dss_fck_multiplier;
+ fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
+ max_dss_fck);
+ fck = prate / fck_div * dss.feat->dss_fck_multiplier;
+ }
r = dss_set_fck_rate(fck);
if (r)
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/4] OMAPDSS: fix missing EXPORT_SYMBOL()s
From: Tomi Valkeinen @ 2013-11-18 12:44 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
Functions dispc_ovl_set_fifo_threshold and
dispc_ovl_compute_fifo_thresholds need to be exported. Add the
EXPORT_SYMBOLs.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 91c687f..aa95ba5 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1201,6 +1201,7 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
FLD_VAL(high, hi_start, hi_end) |
FLD_VAL(low, lo_start, lo_end));
}
+EXPORT_SYMBOL(dispc_ovl_set_fifo_threshold);
void dispc_enable_fifomerge(bool enable)
{
@@ -1259,6 +1260,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
*fifo_high = total_fifo_size - buf_unit;
}
}
+EXPORT_SYMBOL(dispc_ovl_compute_fifo_thresholds);
static void dispc_ovl_set_fir(enum omap_plane plane,
int hinc, int vinc,
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/4] OMAPDSS: fix debug prints
From: Tomi Valkeinen @ 2013-11-18 12:44 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778649-9396-1-git-send-email-tomi.valkeinen@ti.com>
Fix debug prints all over omapdss:
* add missing linefeeds
* change pr_err/pr_debug to DSSERR/DSSDBG
* add missing DSS_SUBSYS_NAMEs
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/apply.c | 8 ++++----
drivers/video/omap2/dss/hdmi4_core.c | 16 +++++++++-------
drivers/video/omap2/dss/hdmi_common.c | 2 ++
drivers/video/omap2/dss/hdmi_pll.c | 16 +++++++++-------
drivers/video/omap2/dss/hdmi_wp.c | 12 +++++++-----
5 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 60758db..24cd7c2 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -629,7 +629,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
struct mgr_priv_data *mp;
int r;
- DSSDBG("writing ovl %d regs", ovl->id);
+ DSSDBG("writing ovl %d regs\n", ovl->id);
if (!op->enabled || !op->info_dirty)
return;
@@ -664,7 +664,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
struct ovl_priv_data *op = get_ovl_priv(ovl);
struct mgr_priv_data *mp;
- DSSDBG("writing ovl %d regs extra", ovl->id);
+ DSSDBG("writing ovl %d regs extra\n", ovl->id);
if (!op->extra_info_dirty)
return;
@@ -687,7 +687,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
struct mgr_priv_data *mp = get_mgr_priv(mgr);
struct omap_overlay *ovl;
- DSSDBG("writing mgr %d regs", mgr->id);
+ DSSDBG("writing mgr %d regs\n", mgr->id);
if (!mp->enabled)
return;
@@ -713,7 +713,7 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
- DSSDBG("writing mgr %d regs extra", mgr->id);
+ DSSDBG("writing mgr %d regs extra\n", mgr->id);
if (!mp->extra_info_dirty)
return;
diff --git a/drivers/video/omap2/dss/hdmi4_core.c b/drivers/video/omap2/dss/hdmi4_core.c
index 5dd5e54..2386a3d 100644
--- a/drivers/video/omap2/dss/hdmi4_core.c
+++ b/drivers/video/omap2/dss/hdmi4_core.c
@@ -19,6 +19,8 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define DSS_SUBSYS_NAME "HDMICORE"
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
@@ -125,12 +127,12 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core,
/* HDMI_CORE_DDC_STATUS_BUS_LOW */
if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) = 1) {
- pr_err("I2C Bus Low?\n");
+ DSSERR("I2C Bus Low?\n");
return -EIO;
}
/* HDMI_CORE_DDC_STATUS_NO_ACK */
if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) = 1) {
- pr_err("I2C No Ack\n");
+ DSSERR("I2C No Ack\n");
return -EIO;
}
@@ -161,7 +163,7 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core,
checksum += pedid[i];
if (checksum != 0) {
- pr_err("E-EDID checksum failed!!\n");
+ DSSERR("E-EDID checksum failed!!\n");
return -EIO;
}
@@ -199,7 +201,7 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
struct hdmi_core_infoframe_avi *avi_cfg,
struct hdmi_core_packet_enable_repeat *repeat_cfg)
{
- pr_debug("Enter hdmi_core_init\n");
+ DSSDBG("Enter hdmi_core_init\n");
/* video core */
video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
@@ -241,19 +243,19 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
static void hdmi_core_powerdown_disable(struct hdmi_core_data *core)
{
- pr_debug("Enter hdmi_core_powerdown_disable\n");
+ DSSDBG("Enter hdmi_core_powerdown_disable\n");
REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0);
}
static void hdmi_core_swreset_release(struct hdmi_core_data *core)
{
- pr_debug("Enter hdmi_core_swreset_release\n");
+ DSSDBG("Enter hdmi_core_swreset_release\n");
REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x0, 0, 0);
}
static void hdmi_core_swreset_assert(struct hdmi_core_data *core)
{
- pr_debug("Enter hdmi_core_swreset_assert\n");
+ DSSDBG("Enter hdmi_core_swreset_assert\n");
REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x1, 0, 0);
}
diff --git a/drivers/video/omap2/dss/hdmi_common.c b/drivers/video/omap2/dss/hdmi_common.c
index 5586aaa..0614922 100644
--- a/drivers/video/omap2/dss/hdmi_common.c
+++ b/drivers/video/omap2/dss/hdmi_common.c
@@ -13,6 +13,8 @@
* map it to corresponding CEA or VESA index.
*/
+#define DSS_SUBSYS_NAME "HDMI"
+
#include <linux/kernel.h>
#include <linux/err.h>
#include <video/omapdss.h>
diff --git a/drivers/video/omap2/dss/hdmi_pll.c b/drivers/video/omap2/dss/hdmi_pll.c
index d3e6e78..a06f4ee 100644
--- a/drivers/video/omap2/dss/hdmi_pll.c
+++ b/drivers/video/omap2/dss/hdmi_pll.c
@@ -8,6 +8,8 @@
* the Free Software Foundation.
*/
+#define DSS_SUBSYS_NAME "HDMIPLL"
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
@@ -127,24 +129,24 @@ static int hdmi_pll_config(struct hdmi_pll_data *pll)
/* wait for bit change */
if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO,
0, 0, 1) != 1) {
- pr_err("PLL GO bit not set\n");
+ DSSERR("PLL GO bit not set\n");
return -ETIMEDOUT;
}
/* Wait till the lock bit is set in PLL status */
if (hdmi_wait_for_bit_change(pll->base,
PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
- pr_err("cannot lock PLL\n");
- pr_err("CFG1 0x%x\n",
+ DSSERR("cannot lock PLL\n");
+ DSSERR("CFG1 0x%x\n",
hdmi_read_reg(pll->base, PLLCTRL_CFG1));
- pr_err("CFG2 0x%x\n",
+ DSSERR("CFG2 0x%x\n",
hdmi_read_reg(pll->base, PLLCTRL_CFG2));
- pr_err("CFG4 0x%x\n",
+ DSSERR("CFG4 0x%x\n",
hdmi_read_reg(pll->base, PLLCTRL_CFG4));
return -ETIMEDOUT;
}
- pr_debug("PLL locked!\n");
+ DSSDBG("PLL locked!\n");
return 0;
}
@@ -157,7 +159,7 @@ static int hdmi_pll_reset(struct hdmi_pll_data *pll)
/* READ 0x0 reset is in progress */
if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1)
!= 1) {
- pr_err("Failed to sysreset PLL\n");
+ DSSERR("Failed to sysreset PLL\n");
return -ETIMEDOUT;
}
diff --git a/drivers/video/omap2/dss/hdmi_wp.c b/drivers/video/omap2/dss/hdmi_wp.c
index 8151d89..fa8e094 100644
--- a/drivers/video/omap2/dss/hdmi_wp.c
+++ b/drivers/video/omap2/dss/hdmi_wp.c
@@ -8,6 +8,8 @@
* the Free Software Foundation.
*/
+#define DSS_SUBSYS_NAME "HDMIWP"
+
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/io.h>
@@ -76,7 +78,7 @@ int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val)
/* Status of the power control of HDMI PHY */
if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 5, 4, val)
!= val) {
- pr_err("Failed to set PHY power mode to %d\n", val);
+ DSSERR("Failed to set PHY power mode to %d\n", val);
return -ETIMEDOUT;
}
@@ -92,7 +94,7 @@ int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val)
/* wait till PHY_PWR_STATUS is set */
if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val)
!= val) {
- pr_err("Failed to set PLL_PWR_STATUS\n");
+ DSSERR("Failed to set PLL_PWR_STATUS\n");
return -ETIMEDOUT;
}
@@ -129,7 +131,7 @@ void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
{
u32 r;
bool vsync_pol, hsync_pol;
- pr_debug("Enter hdmi_wp_video_config_interface\n");
+ DSSDBG("Enter hdmi_wp_video_config_interface\n");
vsync_pol = timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
hsync_pol = timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
@@ -148,7 +150,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
u32 timing_h = 0;
u32 timing_v = 0;
- pr_debug("Enter hdmi_wp_video_config_timing\n");
+ DSSDBG("Enter hdmi_wp_video_config_timing\n");
timing_h |= FLD_VAL(timings->hbp, 31, 20);
timing_h |= FLD_VAL(timings->hfp, 19, 8);
@@ -164,7 +166,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
struct omap_video_timings *timings, struct hdmi_config *param)
{
- pr_debug("Enter hdmi_wp_video_init_format\n");
+ DSSDBG("Enter hdmi_wp_video_init_format\n");
video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
video_fmt->y_res = param->timings.y_res;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/4] OMAPDSS: apply fixes
From: Tomi Valkeinen @ 2013-11-18 12:44 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778649-9396-1-git-send-email-tomi.valkeinen@ti.com>
When omapfb does ovl->get_overlay_info, ovl->set_overlay_info, the set
function may fail even if the info has not been changed. This is because
omapdss doesn't initialize the info, but expect the caller to set valid
values.
Normally that is the case, but there is at least one corner case: if
omapfb has not allocated memory for the overlay yet, and the user uses
ioctl to disable the overlay to make sure it's disabled. In this case
get_overlay_info returns invalid data, but the user is only interested
in setting the overlay to disabled, not configuring it, and
set_overlay_info fails.
The issue is made possible by the omapfb's setup_plane ioctl, which
groups overlay configuration and overlay enable/disable bit into the
same struct. Thus, when you are disabling an overlay, you are also
configuring it.
This is a bit counter intuitive, so I think it's better to initialize
the info to some valid values.
The fields requiring initialization are color_mode and rotation_type,
and also we need to remove the check for (paddr = 0), as paddr is 0 for
unallocated overlay (but it's still fine to disable the overlay).
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/apply.c | 3 +++
drivers/video/omap2/dss/overlay.c | 5 -----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 24cd7c2..0a0b084 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -149,6 +149,9 @@ static void apply_init_priv(void)
op = &dss_data.ovl_priv_data_array[i];
+ op->info.color_mode = OMAP_DSS_COLOR_RGB16;
+ op->info.rotation_type = OMAP_DSS_ROT_DMA;
+
op->info.global_alpha = 255;
switch (i) {
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index eccde32..2f7cee9 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -113,11 +113,6 @@ void dss_uninit_overlays(struct platform_device *pdev)
int dss_ovl_simple_check(struct omap_overlay *ovl,
const struct omap_overlay_info *info)
{
- if (info->paddr = 0) {
- DSSERR("check_overlay: paddr cannot be 0\n");
- return -EINVAL;
- }
-
if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) = 0) {
if (info->out_width != 0 && info->width != info->out_width) {
DSSERR("check_overlay: overlay %d doesn't support "
--
1.8.3.2
^ permalink raw reply related
* [PATCH 4/4] OMAPDSS: DISPC: Add MFLAG defines
From: Tomi Valkeinen @ 2013-11-18 12:44 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384778649-9396-1-git-send-email-tomi.valkeinen@ti.com>
OMAP5 has MFLAG feature in DISPC. Add the register definition and dump
it. The register is not used yet, though.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 4 ++++
drivers/video/omap2/dss/dispc.h | 20 ++++++++++++++++++++
drivers/video/omap2/dss/dss_features.c | 1 +
drivers/video/omap2/dss/dss_features.h | 1 +
4 files changed, 26 insertions(+)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index aa95ba5..d39a4e3 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -3213,6 +3213,8 @@ static void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_CONTROL3);
DUMPREG(DISPC_CONFIG3);
}
+ if (dss_has_feature(FEAT_MFLAG))
+ DUMPREG(DISPC_GLOBAL_MFLAG_ATTRIBUTE);
#undef DUMPREG
@@ -3287,6 +3289,8 @@ static void dispc_dump_regs(struct seq_file *s)
DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
if (dss_has_feature(FEAT_PRELOAD))
DUMPREG(i, DISPC_OVL_PRELOAD);
+ if (dss_has_feature(FEAT_MFLAG))
+ DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD);
}
#undef DISPC_REG
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index de4863d..78edb44 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -40,6 +40,7 @@
#define DISPC_CONTROL3 0x0848
#define DISPC_CONFIG3 0x084C
#define DISPC_MSTANDBY_CTRL 0x0858
+#define DISPC_GLOBAL_MFLAG_ATTRIBUTE 0x085C
/* DISPC overlay registers */
#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
@@ -100,6 +101,8 @@
DISPC_FIR_COEF_V2_OFFSET(n, i))
#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \
DISPC_PRELOAD_OFFSET(n))
+#define DISPC_OVL_MFLAG_THRESHOLD(n) (DISPC_OVL_BASE(n) + \
+ DISPC_MFLAG_THRESHOLD_OFFSET(n))
/* DISPC up/downsampling FIR filter coefficient structure */
struct dispc_coef {
@@ -894,4 +897,21 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
return 0;
}
}
+
+static inline u16 DISPC_MFLAG_THRESHOLD_OFFSET(enum omap_plane plane)
+{
+ switch (plane) {
+ case OMAP_DSS_GFX:
+ return 0x0860;
+ case OMAP_DSS_VIDEO1:
+ return 0x0864;
+ case OMAP_DSS_VIDEO2:
+ return 0x0868;
+ case OMAP_DSS_VIDEO3:
+ return 0x086c;
+ default:
+ BUG();
+ return 0;
+ }
+}
#endif
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index f8fd6db..7f89691 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -613,6 +613,7 @@ static const enum dss_feat_id omap5_dss_feat_list[] = {
FEAT_DSI_PLL_SELFREQDCO,
FEAT_DSI_PLL_REFSEL,
FEAT_DSI_PHY_DCC,
+ FEAT_MFLAG,
};
/* OMAP2 DSS Features */
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 10b0556..e3ef3b7 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -64,6 +64,7 @@ enum dss_feat_id {
FEAT_DSI_PLL_SELFREQDCO,
FEAT_DSI_PLL_REFSEL,
FEAT_DSI_PHY_DCC,
+ FEAT_MFLAG,
};
/* DSS register field id */
--
1.8.3.2
^ permalink raw reply related
* [PATCH 0/6] OMAPDSS: suspend/resume improvements
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
DISPC's suspend/resume works ok on mainline, but there was recently a bug with
TI's kernel containing support for newer SoCs. The bug was that not all DISPC
registers were restored correctly on resume.
While this bug is not in the mainline, I realized that the current
suspend/resume support in DISPC is rather silly, and can be done much more
efficiently.
This series improves the suspend/resume, making introducing similar bugs as
seen in TI kernel not possible, and cleans up the code quite a bit.
There's also a patch to use runtime PM's autosuspend with DSS devices, which
should reduce the on/off cycles when e.g. starting omapdss.
Tomi
Tomi Valkeinen (6):
OMAPDSS: APPLY: set infos to dirty on enable
OMAPDSS: DISPC: Remove context restore
OMAPDSS: DSS remove ctx stuff
OMAPDSS: remove dss_get_ctx_loss_count
OMAPDSS: add debug print for runtime suspend/resume
OMAPDSS: use runtime PM's autosuspend
arch/arm/mach-omap2/display.c | 1 -
drivers/video/omap2/dss/apply.c | 22 ++++
drivers/video/omap2/dss/dispc.c | 262 ++--------------------------------------
drivers/video/omap2/dss/dsi.c | 9 +-
drivers/video/omap2/dss/dss.c | 103 ++++++----------
drivers/video/omap2/dss/dss.h | 4 +-
drivers/video/omap2/dss/hdmi4.c | 9 +-
drivers/video/omap2/dss/rfbi.c | 9 +-
drivers/video/omap2/dss/venc.c | 9 +-
include/video/omapdss.h | 1 -
10 files changed, 101 insertions(+), 328 deletions(-)
--
1.8.3.2
^ permalink raw reply
* [PATCH 1/6] OMAPDSS: APPLY: set infos to dirty on enable
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
Currently when DISPC is suspended, the driver stores all DISPC registers
to memory, so that they can be restored on resume. This is a bad way to
handle suspend/resume, as it's prone to failures and requires somewhat
large amount of extra space to store the registers.
A better approach is to program the DISPC from scratch when resuming.
This can be easily accomplished in apply layer by setting the manager
and overlay infos to dirty when the manager is to be enabled.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/apply.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 60758db..6ab4cb6 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -1072,6 +1072,7 @@ static void dss_setup_fifos(void)
static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
+ struct omap_overlay *ovl;
unsigned long flags;
int r;
@@ -1091,6 +1092,27 @@ static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
goto err;
}
+ /*
+ * Mark the info & extra_info dirty for the manager and its enabled
+ * overlays to force register writes. This ensures that the relevant
+ * registers are set after DSS has been off and the registers have been
+ * reset.
+ */
+
+ mp->info_dirty = true;
+ mp->extra_info_dirty = true;
+
+ list_for_each_entry(ovl, &mgr->overlays, list) {
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+
+ if (!op->enabled)
+ continue;
+
+ op->info_dirty = true;
+ op->extra_info_dirty = true;
+ dispc_ovl_set_channel_out(ovl->id, mgr->id);
+ }
+
dss_setup_fifos();
dss_write_regs();
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/6] OMAPDSS: DISPC: Remove context restore
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
Now that the apply layer writes the registers after DISPC has been
resumed, we can remove all the context restore code.
Only _omap_dispc_initial_config call is needed on resume, which
configures the non-user-configurable registers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 255 +---------------------------------------
1 file changed, 1 insertion(+), 254 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 91c687f..54716ad 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -43,9 +43,6 @@
#include "dss_features.h"
#include "dispc.h"
-/* DISPC */
-#define DISPC_SZ_REGS SZ_4K
-
enum omap_burst_size {
BURST_SIZE_X2 = 0,
BURST_SIZE_X4 = 1,
@@ -98,8 +95,6 @@ static struct {
struct platform_device *pdev;
void __iomem *base;
- int ctx_loss_cnt;
-
int irq;
unsigned long core_clk_rate;
@@ -109,9 +104,6 @@ static struct {
/* maps which plane is using a fifo. fifo-id -> plane-id */
int fifo_assignment[DISPC_MAX_NR_FIFOS];
- bool ctx_valid;
- u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
-
const struct dispc_features *feat;
} dispc;
@@ -248,249 +240,6 @@ static void mgr_fld_write(enum omap_channel channel,
REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
}
-#define SR(reg) \
- dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
-#define RR(reg) \
- dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
-
-static void dispc_save_context(void)
-{
- int i, j;
-
- DSSDBG("dispc_save_context\n");
-
- SR(IRQENABLE);
- SR(CONTROL);
- SR(CONFIG);
- SR(LINE_NUMBER);
- if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
- dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
- SR(GLOBAL_ALPHA);
- if (dss_has_feature(FEAT_MGR_LCD2)) {
- SR(CONTROL2);
- SR(CONFIG2);
- }
- if (dss_has_feature(FEAT_MGR_LCD3)) {
- SR(CONTROL3);
- SR(CONFIG3);
- }
-
- for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
- SR(DEFAULT_COLOR(i));
- SR(TRANS_COLOR(i));
- SR(SIZE_MGR(i));
- if (i = OMAP_DSS_CHANNEL_DIGIT)
- continue;
- SR(TIMING_H(i));
- SR(TIMING_V(i));
- SR(POL_FREQ(i));
- SR(DIVISORo(i));
-
- SR(DATA_CYCLE1(i));
- SR(DATA_CYCLE2(i));
- SR(DATA_CYCLE3(i));
-
- if (dss_has_feature(FEAT_CPR)) {
- SR(CPR_COEF_R(i));
- SR(CPR_COEF_G(i));
- SR(CPR_COEF_B(i));
- }
- }
-
- for (i = 0; i < dss_feat_get_num_ovls(); i++) {
- SR(OVL_BA0(i));
- SR(OVL_BA1(i));
- SR(OVL_POSITION(i));
- SR(OVL_SIZE(i));
- SR(OVL_ATTRIBUTES(i));
- SR(OVL_FIFO_THRESHOLD(i));
- SR(OVL_ROW_INC(i));
- SR(OVL_PIXEL_INC(i));
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(i));
- if (i = OMAP_DSS_GFX) {
- SR(OVL_WINDOW_SKIP(i));
- SR(OVL_TABLE_BA(i));
- continue;
- }
- SR(OVL_FIR(i));
- SR(OVL_PICTURE_SIZE(i));
- SR(OVL_ACCU0(i));
- SR(OVL_ACCU1(i));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_H(i, j));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_HV(i, j));
-
- for (j = 0; j < 5; j++)
- SR(OVL_CONV_COEF(i, j));
-
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_V(i, j));
- }
-
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- SR(OVL_BA0_UV(i));
- SR(OVL_BA1_UV(i));
- SR(OVL_FIR2(i));
- SR(OVL_ACCU2_0(i));
- SR(OVL_ACCU2_1(i));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_H2(i, j));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_HV2(i, j));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_V2(i, j));
- }
- if (dss_has_feature(FEAT_ATTR2))
- SR(OVL_ATTRIBUTES2(i));
- }
-
- if (dss_has_feature(FEAT_CORE_CLK_DIV))
- SR(DIVISOR);
-
- dispc.ctx_loss_cnt = dss_get_ctx_loss_count();
- dispc.ctx_valid = true;
-
- DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
-}
-
-static void dispc_restore_context(void)
-{
- int i, j, ctx;
-
- DSSDBG("dispc_restore_context\n");
-
- if (!dispc.ctx_valid)
- return;
-
- ctx = dss_get_ctx_loss_count();
-
- if (ctx >= 0 && ctx = dispc.ctx_loss_cnt)
- return;
-
- DSSDBG("ctx_loss_count: saved %d, current %d\n",
- dispc.ctx_loss_cnt, ctx);
-
- /*RR(IRQENABLE);*/
- /*RR(CONTROL);*/
- RR(CONFIG);
- RR(LINE_NUMBER);
- if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
- dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
- RR(GLOBAL_ALPHA);
- if (dss_has_feature(FEAT_MGR_LCD2))
- RR(CONFIG2);
- if (dss_has_feature(FEAT_MGR_LCD3))
- RR(CONFIG3);
-
- for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
- RR(DEFAULT_COLOR(i));
- RR(TRANS_COLOR(i));
- RR(SIZE_MGR(i));
- if (i = OMAP_DSS_CHANNEL_DIGIT)
- continue;
- RR(TIMING_H(i));
- RR(TIMING_V(i));
- RR(POL_FREQ(i));
- RR(DIVISORo(i));
-
- RR(DATA_CYCLE1(i));
- RR(DATA_CYCLE2(i));
- RR(DATA_CYCLE3(i));
-
- if (dss_has_feature(FEAT_CPR)) {
- RR(CPR_COEF_R(i));
- RR(CPR_COEF_G(i));
- RR(CPR_COEF_B(i));
- }
- }
-
- for (i = 0; i < dss_feat_get_num_ovls(); i++) {
- RR(OVL_BA0(i));
- RR(OVL_BA1(i));
- RR(OVL_POSITION(i));
- RR(OVL_SIZE(i));
- RR(OVL_ATTRIBUTES(i));
- RR(OVL_FIFO_THRESHOLD(i));
- RR(OVL_ROW_INC(i));
- RR(OVL_PIXEL_INC(i));
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(i));
- if (i = OMAP_DSS_GFX) {
- RR(OVL_WINDOW_SKIP(i));
- RR(OVL_TABLE_BA(i));
- continue;
- }
- RR(OVL_FIR(i));
- RR(OVL_PICTURE_SIZE(i));
- RR(OVL_ACCU0(i));
- RR(OVL_ACCU1(i));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_H(i, j));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_HV(i, j));
-
- for (j = 0; j < 5; j++)
- RR(OVL_CONV_COEF(i, j));
-
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_V(i, j));
- }
-
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- RR(OVL_BA0_UV(i));
- RR(OVL_BA1_UV(i));
- RR(OVL_FIR2(i));
- RR(OVL_ACCU2_0(i));
- RR(OVL_ACCU2_1(i));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_H2(i, j));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_HV2(i, j));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_V2(i, j));
- }
- if (dss_has_feature(FEAT_ATTR2))
- RR(OVL_ATTRIBUTES2(i));
- }
-
- if (dss_has_feature(FEAT_CORE_CLK_DIV))
- RR(DIVISOR);
-
- /* enable last, because LCD & DIGIT enable are here */
- RR(CONTROL);
- if (dss_has_feature(FEAT_MGR_LCD2))
- RR(CONTROL2);
- if (dss_has_feature(FEAT_MGR_LCD3))
- RR(CONTROL3);
- /* clear spurious SYNC_LOST_DIGIT interrupts */
- dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
-
- /*
- * enable last so IRQs won't trigger before
- * the context is fully restored
- */
- RR(IRQENABLE);
-
- DSSDBG("context restored\n");
-}
-
-#undef SR
-#undef RR
-
int dispc_runtime_get(void)
{
int r;
@@ -3726,14 +3475,12 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
static int dispc_runtime_suspend(struct device *dev)
{
- dispc_save_context();
-
return 0;
}
static int dispc_runtime_resume(struct device *dev)
{
- dispc_restore_context();
+ _omap_dispc_initial_config();
return 0;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/6] OMAPDSS: DSS remove ctx stuff
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
The DSS core driver's suspend/resume can be cleaned up by storing the
required registers to a 'dss_context' struct, instead of having a 512
byte block of memory where the registers are directly stored.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dss.c | 77 ++++++++++++++++---------------------------
1 file changed, 28 insertions(+), 49 deletions(-)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index bd01608..a5f674f 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -39,8 +39,6 @@
#include "dss.h"
#include "dss_features.h"
-#define DSS_SZ_REGS SZ_512
-
struct dss_reg {
u16 idx;
};
@@ -71,6 +69,13 @@ struct dss_features {
int (*dpi_select_source)(enum omap_channel channel);
};
+struct dss_context {
+ bool valid;
+ u32 control;
+ u32 sdi_control;
+ u32 pll_control;
+};
+
static struct {
struct platform_device *pdev;
void __iomem *base;
@@ -88,8 +93,7 @@ static struct {
enum omap_dss_clk_source dispc_clk_source;
enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
- bool ctx_valid;
- u32 ctx[DSS_SZ_REGS / sizeof(u32)];
+ struct dss_context ctx;
const struct dss_features *feat;
} dss;
@@ -112,49 +116,6 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
return __raw_readl(dss.base + idx.idx);
}
-#define SR(reg) \
- dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
-#define RR(reg) \
- dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
-
-static void dss_save_context(void)
-{
- DSSDBG("dss_save_context\n");
-
- SR(CONTROL);
-
- if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
- OMAP_DISPLAY_TYPE_SDI) {
- SR(SDI_CONTROL);
- SR(PLL_CONTROL);
- }
-
- dss.ctx_valid = true;
-
- DSSDBG("context saved\n");
-}
-
-static void dss_restore_context(void)
-{
- DSSDBG("dss_restore_context\n");
-
- if (!dss.ctx_valid)
- return;
-
- RR(CONTROL);
-
- if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
- OMAP_DISPLAY_TYPE_SDI) {
- RR(SDI_CONTROL);
- RR(PLL_CONTROL);
- }
-
- DSSDBG("context restored\n");
-}
-
-#undef SR
-#undef RR
-
int dss_get_ctx_loss_count(void)
{
struct platform_device *core_pdev = dss_get_core_pdev();
@@ -927,7 +888,16 @@ static int __exit omap_dsshw_remove(struct platform_device *pdev)
static int dss_runtime_suspend(struct device *dev)
{
- dss_save_context();
+ dss.ctx.control = dss_read_reg(DSS_CONTROL);
+
+ if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+ OMAP_DISPLAY_TYPE_SDI) {
+ dss.ctx.sdi_control = dss_read_reg(DSS_SDI_CONTROL);
+ dss.ctx.pll_control = dss_read_reg(DSS_PLL_CONTROL);
+ }
+
+ dss.ctx.valid = true;
+
dss_set_min_bus_tput(dev, 0);
return 0;
}
@@ -946,7 +916,16 @@ static int dss_runtime_resume(struct device *dev)
if (r)
return r;
- dss_restore_context();
+ if (dss.ctx.valid) {
+ dss_write_reg(DSS_CONTROL, dss.ctx.control);
+
+ if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+ OMAP_DISPLAY_TYPE_SDI) {
+ dss_write_reg(DSS_SDI_CONTROL, dss.ctx.sdi_control);
+ dss_write_reg(DSS_PLL_CONTROL, dss.ctx.pll_control);
+ }
+ }
+
return 0;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 4/6] OMAPDSS: remove dss_get_ctx_loss_count
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
OMAPDSS driver no longer needs dss_get_ctx_loss_count, so it can be
removed.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
arch/arm/mach-omap2/display.c | 1 -
drivers/video/omap2/dss/dss.c | 16 ----------------
drivers/video/omap2/dss/dss.h | 2 --
include/video/omapdss.h | 1 -
4 files changed, 20 deletions(-)
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 03a0516..e6d219c 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -341,7 +341,6 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
board_data->version = ver;
board_data->dsi_enable_pads = omap_dsi_enable_pads;
board_data->dsi_disable_pads = omap_dsi_disable_pads;
- board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count;
board_data->set_min_bus_tput = omap_dss_set_min_bus_tput;
omap_display_device.dev.platform_data = board_data;
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index a5f674f..0b78c89 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -116,22 +116,6 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
return __raw_readl(dss.base + idx.idx);
}
-int dss_get_ctx_loss_count(void)
-{
- struct platform_device *core_pdev = dss_get_core_pdev();
- struct omap_dss_board_info *board_data = core_pdev->dev.platform_data;
- int cnt;
-
- if (!board_data->get_context_loss_count)
- return -ENOENT;
-
- cnt = board_data->get_context_loss_count(&dss.pdev->dev);
-
- WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
-
- return cnt;
-}
-
void dss_sdi_init(int datapairs)
{
u32 l;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index f538e86..af83c4d 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -233,8 +233,6 @@ void dss_dump_clocks(struct seq_file *s);
void dss_debug_dump_clocks(struct seq_file *s);
#endif
-int dss_get_ctx_loss_count(void);
-
void dss_sdi_init(int datapairs);
int dss_sdi_enable(void);
void dss_sdi_disable(void);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 3d7c51a..1eb9aa6 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -323,7 +323,6 @@ enum omapdss_version {
/* Board specific data */
struct omap_dss_board_info {
- int (*get_context_loss_count)(struct device *dev);
int num_devices;
struct omap_dss_device **devices;
struct omap_dss_device *default_device;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 5/6] OMAPDSS: add debug print for runtime suspend/resume
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
Add consistent debug prints on all suspend & resume callbacks in omapdss
to make it simpler to debug runtime PM.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 4 ++++
drivers/video/omap2/dss/dsi.c | 4 ++++
drivers/video/omap2/dss/dss.c | 5 +++++
drivers/video/omap2/dss/hdmi4.c | 4 ++++
drivers/video/omap2/dss/rfbi.c | 4 ++++
drivers/video/omap2/dss/venc.c | 4 ++++
6 files changed, 25 insertions(+)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 54716ad..58f3626 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -3475,11 +3475,15 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
static int dispc_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
return 0;
}
static int dispc_runtime_resume(struct device *dev)
{
+ DSSDBG("resume\n");
+
_omap_dispc_initial_config();
return 0;
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 6056b27..6b30a58 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -5477,6 +5477,8 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
static int dsi_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
dispc_runtime_put();
return 0;
@@ -5486,6 +5488,8 @@ static int dsi_runtime_resume(struct device *dev)
{
int r;
+ DSSDBG("resume\n");
+
r = dispc_runtime_get();
if (r)
return r;
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 0b78c89..fa7bc00 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -872,6 +872,8 @@ static int __exit omap_dsshw_remove(struct platform_device *pdev)
static int dss_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
dss.ctx.control = dss_read_reg(DSS_CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -889,6 +891,9 @@ static int dss_runtime_suspend(struct device *dev)
static int dss_runtime_resume(struct device *dev)
{
int r;
+
+ DSSDBG("resume\n");
+
/*
* Set an arbitrarily high tput request to ensure OPP100.
* What we should really do is to make a request to stay in OPP100,
diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/omap2/dss/hdmi4.c
index e140096..f1a45fe 100644
--- a/drivers/video/omap2/dss/hdmi4.c
+++ b/drivers/video/omap2/dss/hdmi4.c
@@ -650,6 +650,8 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
static int hdmi_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
clk_disable_unprepare(hdmi.sys_clk);
dispc_runtime_put();
@@ -661,6 +663,8 @@ static int hdmi_runtime_resume(struct device *dev)
{
int r;
+ DSSDBG("resume\n");
+
r = dispc_runtime_get();
if (r < 0)
return r;
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index c8a81a2..74d3ed1 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -1016,6 +1016,8 @@ static int __exit omap_rfbihw_remove(struct platform_device *pdev)
static int rfbi_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
dispc_runtime_put();
return 0;
@@ -1025,6 +1027,8 @@ static int rfbi_runtime_resume(struct device *dev)
{
int r;
+ DSSDBG("resume\n");
+
r = dispc_runtime_get();
if (r < 0)
return r;
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 5f88ac4..e173961 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -867,6 +867,8 @@ static int __exit omap_venchw_remove(struct platform_device *pdev)
static int venc_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
if (venc.tv_dac_clk)
clk_disable_unprepare(venc.tv_dac_clk);
@@ -879,6 +881,8 @@ static int venc_runtime_resume(struct device *dev)
{
int r;
+ DSSDBG("resume\n");
+
r = dispc_runtime_get();
if (r < 0)
return r;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 6/6] OMAPDSS: use runtime PM's autosuspend
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
Use runtime PM's autosuspend support with delay of 100ms.
This will prevent the driver from turning the DSS modules off and on
multiple times e.g. when loading the module.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 5 ++++-
drivers/video/omap2/dss/dsi.c | 5 ++++-
drivers/video/omap2/dss/dss.c | 5 ++++-
drivers/video/omap2/dss/dss.h | 2 ++
drivers/video/omap2/dss/hdmi4.c | 5 ++++-
drivers/video/omap2/dss/rfbi.c | 5 ++++-
drivers/video/omap2/dss/venc.c | 5 ++++-
7 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 58f3626..0643eb0 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -258,7 +258,8 @@ void dispc_runtime_put(void)
DSSDBG("dispc_runtime_put\n");
- r = pm_runtime_put_sync(&dispc.pdev->dev);
+ pm_runtime_mark_last_busy(&dispc.pdev->dev);
+ r = pm_runtime_put_autosuspend(&dispc.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
EXPORT_SYMBOL(dispc_runtime_put);
@@ -3440,6 +3441,8 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
}
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
r = dispc_runtime_get();
if (r)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 6b30a58..19e4cad 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1110,7 +1110,8 @@ void dsi_runtime_put(struct platform_device *dsidev)
DSSDBG("dsi_runtime_put\n");
- r = pm_runtime_put_sync(&dsi->pdev->dev);
+ pm_runtime_mark_last_busy(&dsi->pdev->dev);
+ r = pm_runtime_put_autosuspend(&dsi->pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
@@ -5416,6 +5417,8 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
return r;
pm_runtime_enable(&dsidev->dev);
+ pm_runtime_set_autosuspend_delay(&dsidev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&dsidev->dev);
r = dsi_runtime_get(dsidev);
if (r)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index fa7bc00..d3b0122 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -689,7 +689,8 @@ static void dss_runtime_put(void)
DSSDBG("dss_runtime_put\n");
- r = pm_runtime_put_sync(&dss.pdev->dev);
+ pm_runtime_mark_last_busy(&dss.pdev->dev);
+ r = pm_runtime_put_autosuspend(&dss.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY);
}
@@ -821,6 +822,8 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
goto err_setup_clocks;
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
r = dss_runtime_get();
if (r)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index af83c4d..96505f0 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -73,6 +73,8 @@
#define FLD_MOD(orig, val, start, end) \
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
+#define DSS_AUTOSUSPEND_DELAY 100 /* in ms */
+
enum dss_io_pad_mode {
DSS_IO_PAD_MODE_RESET,
DSS_IO_PAD_MODE_RFBI,
diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/omap2/dss/hdmi4.c
index f1a45fe..f255641 100644
--- a/drivers/video/omap2/dss/hdmi4.c
+++ b/drivers/video/omap2/dss/hdmi4.c
@@ -77,7 +77,8 @@ static void hdmi_runtime_put(void)
DSSDBG("hdmi_runtime_put\n");
- r = pm_runtime_put_sync(&hdmi.pdev->dev);
+ pm_runtime_mark_last_busy(&hdmi.pdev->dev);
+ r = pm_runtime_put_autosuspend(&hdmi.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
@@ -631,6 +632,8 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
}
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
hdmi_init_output(pdev);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 74d3ed1..20dcbfb 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -147,7 +147,8 @@ static void rfbi_runtime_put(void)
DSSDBG("rfbi_runtime_put\n");
- r = pm_runtime_put_sync(&rfbi.pdev->dev);
+ pm_runtime_mark_last_busy(&rfbi.pdev->dev);
+ r = pm_runtime_put_autosuspend(&rfbi.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
@@ -981,6 +982,8 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
clk_put(clk);
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
r = rfbi_runtime_get();
if (r)
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index e173961..bbd35bb 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -410,7 +410,8 @@ static void venc_runtime_put(void)
DSSDBG("venc_runtime_put\n");
- r = pm_runtime_put_sync(&venc.pdev->dev);
+ pm_runtime_mark_last_busy(&venc.pdev->dev);
+ r = pm_runtime_put_autosuspend(&venc.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
@@ -835,6 +836,8 @@ static int omap_venchw_probe(struct platform_device *pdev)
return r;
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
r = venc_runtime_get();
if (r)
--
1.8.3.2
^ permalink raw reply related
* Re: [RFC 03/23] OMAPDSS: raw read and write endian fix
From: Tomi Valkeinen @ 2013-11-18 13:13 UTC (permalink / raw)
To: Taras Kondratiuk, linux-omap
Cc: linaro-networking, Victor Kamensky,
Jean-Christophe Plagniol-Villard, linux-fbdev, linux-kernel
In-Reply-To: <1384560086-11994-4-git-send-email-taras.kondratiuk@linaro.org>
[-- Attachment #1: Type: text/plain, Size: 709 bytes --]
On 2013-11-16 02:01, Taras Kondratiuk wrote:
> From: Victor Kamensky <victor.kamensky@linaro.org>
>
> All OMAP IP blocks expect LE data, but CPU may operate in BE mode.
> Need to use endian neutral functions to read/write h/w registers.
> I.e instead of __raw_read[lw] and __raw_write[lw] functions code
> need to use read[lw]_relaxed and write[lw]_relaxed functions.
> If the first simply reads/writes register, the second will byteswap
> it if host operates in BE mode.
>
> Changes are trivial sed like replacement of __raw_xxx functions
> with xxx_relaxed variant.
>
Looks fine to me. Quick test with o4 panda works fine.
Acked-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Tomi
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
^ permalink raw reply
* Re: [PATCH 0/3] omapdss: venc: Add support for bypass and acbias.
From: Tomi Valkeinen @ 2013-11-18 13:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <F97741D2-FC6F-4DBD-A0DD-E35304501993@goldelico.com>
[-- Attachment #1: Type: text/plain, Size: 1339 bytes --]
On 2013-11-11 16:30, Dr. H. Nikolaus Schaller wrote:
> Maybe it looks as if it is an unsolvable problem. The OPA works only if acbias
> and bypass are enabled, but is not allowed to tell that it is there.
That's why the board file or dts file is there, to have "glue" data to
make different pieces work together.
The perfect (?) solution would be a CDF like data. The idea would be
that in the board file, you would describe configuration options for
VENC and for OPA. In this particular case, you'd tell VENC that it needs
to enable acbias and bypass when OPA is to be connected to VENC. Then
there could be more entries for VENC, saying disable acbias and bypass
when BAR is to be connected to VENC.
However, we don't have such support (yet).
For now, I hope it's enough if we handle VENC in a "single
configuration" manner, i.e. you'll tell VENC to enable acbias and bypass
when VENC is enabled. This means you can't have board setups where you'd
change the VENC->OPA connection to some other analog tv output at
runtime. I hope that's the case (i.e. OPA is always in use on that board).
If so, then I think you can just pass the acbias and bypass
configuration values via omapdss platform data. And VENC driver will use
them to configure those. OPA doesn't know anything about this at all.
Tomi
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
^ permalink raw reply
* Re: [PATCH v2] ARM: OMAPFB: panel-sony-acx565akm: fix bad unlock balance
From: Tomi Valkeinen @ 2013-11-18 13:36 UTC (permalink / raw)
To: Aaro Koskinen, linux-omap, linux-fbdev; +Cc: Eduardo Valentin, stable
In-Reply-To: <1384195298-31542-1-git-send-email-aaro.koskinen@iki.fi>
[-- Attachment #1: Type: text/plain, Size: 2088 bytes --]
On 2013-11-11 20:41, Aaro Koskinen wrote:
> When booting Nokia N900 smartphone with v3.12 + omap2plus_defconfig
> (LOCKDEP enabled) and CONFIG_DISPLAY_PANEL_SONY_ACX565AKM enabled,
> the following BUG is seen during the boot:
>
> [ 7.302154] =====================================
> [ 7.307128] [ BUG: bad unlock balance detected! ]
> [ 7.312103] 3.12.0-los.git-2093492-00120-g5e01dc7 #3 Not tainted
> [ 7.318450] -------------------------------------
> [ 7.323425] kworker/u2:1/12 is trying to release lock (&ddata->mutex) at:
> [ 7.330657] [<c031b760>] acx565akm_enable+0x12c/0x18c
> [ 7.335998] but there are no more locks to release!
>
> Fix by removing double unlock and handling the locking completely inside
> acx565akm_panel_power_on() when doing the power on.
>
> Reported-by: Eduardo Valentin <eduardo.valentin@ti.com>
> Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
> Cc: stable@vger.kernel.org
> ---
> drivers/video/omap2/displays-new/panel-sony-acx565akm.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
> index e6d56f7..d94f35d 100644
> --- a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
> +++ b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
> @@ -526,6 +526,8 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
> struct omap_dss_device *in = ddata->in;
> int r;
>
> + mutex_lock(&ddata->mutex);
> +
> dev_dbg(&ddata->spi->dev, "%s\n", __func__);
>
> in->ops.sdi->set_timings(in, &ddata->videomode);
> @@ -614,10 +616,7 @@ static int acx565akm_enable(struct omap_dss_device *dssdev)
> if (omapdss_device_is_enabled(dssdev))
> return 0;
>
> - mutex_lock(&ddata->mutex);
> r = acx565akm_panel_power_on(dssdev);
> - mutex_unlock(&ddata->mutex);
> -
> if (r)
> return r;
>
>
Thanks, this is better. lock and unlock in different functions makes me
feel very uneasy...
Tomi
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
^ permalink raw reply
* Re: [PATCH 0/3] omapdss: venc: Add support for bypass and acbias.
From: Dr. H. Nikolaus Schaller @ 2013-11-18 14:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <528A1652.4000806@ti.com>
Hi Tomi,
Am 18.11.2013 um 14:29 schrieb Tomi Valkeinen:
> On 2013-11-11 16:30, Dr. H. Nikolaus Schaller wrote:
>
>> Maybe it looks as if it is an unsolvable problem. The OPA works only if acbias
>> and bypass are enabled, but is not allowed to tell that it is there.
>
> That's why the board file or dts file is there, to have "glue" data to
> make different pieces work together.
Our implementation idea was that this makes the board file developer to specify knowlegde that the
drivers already could have and to reduce the risk of misconfiguration.
So we tried to model the invert property of the connector which is also backpropagated
to VENC.
But of course there are different ways of doing it and different priorities of contradicting
requirements.
>
> The perfect (?) solution would be a CDF like data. The idea would be
> that in the board file, you would describe configuration options for
> VENC and for OPA. In this particular case, you'd tell VENC that it needs
> to enable acbias and bypass when OPA is to be connected to VENC. Then
> there could be more entries for VENC, saying disable acbias and bypass
> when BAR is to be connected to VENC.
>
> However, we don't have such support (yet).
>
> For now, I hope it's enough if we handle VENC in a "single
> configuration" manner, i.e. you'll tell VENC to enable acbias and bypass
> when VENC is enabled. This means you can't have board setups where you'd
> change the VENC->OPA connection to some other analog tv output at
> runtime. I hope that's the case (i.e. OPA is always in use on that board).
I also don't think that there is a need for runtime modifications, so your proposal
looks ok.
> If so, then I think you can just pass the acbias and bypass
> configuration values via omapdss platform data. And VENC driver will use
> them to configure those. OPA doesn't know anything about this at all.
We will change it that way.
Do you see a chance to get it into the merge window of 3.13?
BR,
Nikolaus
^ permalink raw reply
* Re: [PATCH] RFC: framebuffer: provide generic get_fb_unmapped_area
From: Uwe Kleine-König @ 2013-11-18 18:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMuHMdWtrSnTHNN-7GtMWAG9gZ0HJ3ZgVZt6Cfc=q=e-5Sr-Qw@mail.gmail.com>
Hello Geert,
On Mon, Nov 18, 2013 at 12:59:40PM +0100, Geert Uytterhoeven wrote:
> On Mon, Nov 18, 2013 at 11:57 AM, Uwe Kleine-König
> <u.kleine-koenig@pengutronix.de> wrote:
> > This patch makes mmapping the simple-framebuffer device work on a no-MMU
> > ARM target. The code is mostly taken from
> > arch/blackfin/kernel/sys_bfin.c.
> >
> > Note this is only tested on this no-MMU machine and I don't know enough
> > about framebuffers and mm to decide if this patch is sane. Also I'm
> > unsure about the size check because it triggers if userspace page aligns
> > the len parameter. (I don't know how usual it is to do, I'd say it's
> > wrong, but my test program (fbtest by Geert Uytterhoeven) does it.)
>
> It's quite common: the granularity of mmap() is PAGE_SIZE, i.e. if you
> try to map a partial page, you'll get access to the full page anyway
> (with MMU; without MMU, you can access everything anyway).
> Fbtest always mmap()s the full (page aligned) smem_len.
>
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > ---
> > drivers/video/fbmem.c | 22 +++++++++++++++++++---
> > 1 file changed, 19 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
> > index dacaf74..70b328c 100644
> > --- a/drivers/video/fbmem.c
> > +++ b/drivers/video/fbmem.c
> > @@ -1483,6 +1483,24 @@ __releases(&info->lock)
> > return 0;
> > }
> >
> > +#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
> > +#define fb_get_unmapped_area get_fb_unmapped_area
> > +#else
> > +unsigned long fb_get_unmapped_area(struct file *filp, unsigned long orig_addr,
> > + unsigned long len, unsigned long pgoff, unsigned long flags)
> > +{
> > + struct fb_info * const info = filp->private_data;
> > + unsigned long screen_size = info->screen_size ?: info->fix.smem_len;
>
> Why restrict this to screen_size? Fbtest will map the whole frame buffer memory.
For me screen_size is zero. The logic to determine the size is copied
from fb_read. In the meantine I'm using
if (len > PAGE_ALIGN(screen_size))
because even if userspace passes an unaligned size it gets aligned
somewhere on the path to fb_get_unmapped_area.
> Typically screen_size is not a multiple of PAGE_SIZE, so this is another
> reason why your size check fails.
>
> > + if (len > screen_size) {
> > + pr_info("%lu > %lu (%lu, %lu)\n", len, screen_size, info->screen_size, info->fix.smem_len);
> > + return -EINVAL;
> > + }
> > +
> > + return (unsigned long)info->screen_base;
>
> Shouldn't you take into account pgoff?
Sounds sensible. Then the same applies to blackfin's
get_fb_unmapped_area.
So is it:
unsigned long screen_size = info->screen_size ?: info->fix.smem_len;
screen_size = PAGE_ALIGN(screen_size);
if (pgoff > screen_size || pgoff + len > screen_size)
return -EINVAL;
return (unsigned long)info->screen_base + pgoff;
? Or should I drop the size check?
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* Re: [PATCH] RFC: framebuffer: provide generic get_fb_unmapped_area
From: Uwe Kleine-König @ 2013-11-18 19:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20131118185959.GE19318@pengutronix.de>
Hello again,
On Mon, Nov 18, 2013 at 07:59:59PM +0100, Uwe Kleine-König wrote:
> if (pgoff > screen_size || pgoff + len > screen_size)
This must be:
if (pgoff > screen_size || len > screen_size - pgoff)
to do what I intended.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox