mirror of https://gitee.com/openkylin/linux.git
OMAP2, 3: DSS2: Move clocks from core driver to dss driver
All clock management is moved to dss platform driver. clk_get/put APIs use dss device instead of core platform device. Hwmod adaptation design requires each of the DSS HW IP to be a platform driver. So the device name is changed from omapdss to omapdss_dss in 2420, 2430, 3xxx clock database files. Now the core driver "omapdss" only takes care of panel registration with the custom bus. core driver also uses the clk_enable() / clk_disable() APIs exposed by DSS for clock management. DSS driver would do clock management of clocks needed by DISPC, RFBI, DSI, VENC TODO: The clock content would be adapted to omap_hwmod in a seperate series. Signed-off-by: Senthilvadivu Guruswamy <svadivu@ti.com> Signed-off-by: Sumit Semwal <sumit.semwal@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
This commit is contained in:
parent
96c401bcb8
commit
8b9cb3a8f3
|
@ -1786,10 +1786,10 @@ static struct omap_clk omap2420_clks[] = {
|
|||
CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_242X),
|
||||
CLK(NULL, "gfx_ick", &gfx_ick, CK_242X),
|
||||
/* DSS domain clocks */
|
||||
CLK("omapdss", "ick", &dss_ick, CK_242X),
|
||||
CLK("omapdss", "dss1_fck", &dss1_fck, CK_242X),
|
||||
CLK("omapdss", "dss2_fck", &dss2_fck, CK_242X),
|
||||
CLK("omapdss", "tv_fck", &dss_54m_fck, CK_242X),
|
||||
CLK("omapdss_dss", "ick", &dss_ick, CK_242X),
|
||||
CLK("omapdss_dss", "dss1_fck", &dss1_fck, CK_242X),
|
||||
CLK("omapdss_dss", "dss2_fck", &dss2_fck, CK_242X),
|
||||
CLK("omapdss_dss", "tv_fck", &dss_54m_fck, CK_242X),
|
||||
/* L3 domain clocks */
|
||||
CLK(NULL, "core_l3_ck", &core_l3_ck, CK_242X),
|
||||
CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_242X),
|
||||
|
|
|
@ -1890,10 +1890,10 @@ static struct omap_clk omap2430_clks[] = {
|
|||
CLK(NULL, "mdm_ick", &mdm_ick, CK_243X),
|
||||
CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X),
|
||||
/* DSS domain clocks */
|
||||
CLK("omapdss", "ick", &dss_ick, CK_243X),
|
||||
CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X),
|
||||
CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X),
|
||||
CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X),
|
||||
CLK("omapdss_dss", "ick", &dss_ick, CK_243X),
|
||||
CLK("omapdss_dss", "dss1_fck", &dss1_fck, CK_243X),
|
||||
CLK("omapdss_dss", "dss2_fck", &dss2_fck, CK_243X),
|
||||
CLK("omapdss_dss", "tv_fck", &dss_54m_fck, CK_243X),
|
||||
/* L3 domain clocks */
|
||||
CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X),
|
||||
CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X),
|
||||
|
|
|
@ -3357,13 +3357,13 @@ static struct omap_clk omap3xxx_clks[] = {
|
|||
CLK("omap_rng", "ick", &rng_ick, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "sha11_ick", &sha11_ick, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "des1_ick", &des1_ick, CK_34XX | CK_36XX),
|
||||
CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
|
||||
CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK("omapdss", "tv_fck", &dss_tv_fck, CK_3XXX),
|
||||
CLK("omapdss", "video_fck", &dss_96m_fck, CK_3XXX),
|
||||
CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_3XXX),
|
||||
CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1),
|
||||
CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK("omapdss_dss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
|
||||
CLK("omapdss_dss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK("omapdss_dss", "tv_fck", &dss_tv_fck, CK_3XXX),
|
||||
CLK("omapdss_dss", "video_fck", &dss_96m_fck, CK_3XXX),
|
||||
CLK("omapdss_dss", "dss2_fck", &dss2_alwon_fck, CK_3XXX),
|
||||
CLK("omapdss_dss", "ick", &dss_ick_3430es1, CK_3430ES1),
|
||||
CLK("omapdss_dss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX),
|
||||
|
|
|
@ -34,32 +34,18 @@
|
|||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
#include <plat/clock.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static struct {
|
||||
struct platform_device *pdev;
|
||||
int ctx_id;
|
||||
|
||||
struct clk *dss_ick;
|
||||
struct clk *dss1_fck;
|
||||
struct clk *dss2_fck;
|
||||
struct clk *dss_54m_fck;
|
||||
struct clk *dss_96m_fck;
|
||||
unsigned num_clks_enabled;
|
||||
|
||||
struct regulator *vdds_dsi_reg;
|
||||
struct regulator *vdds_sdi_reg;
|
||||
struct regulator *vdda_dac_reg;
|
||||
} core;
|
||||
|
||||
static void dss_clk_enable_all_no_ctx(void);
|
||||
static void dss_clk_disable_all_no_ctx(void);
|
||||
static void dss_clk_enable_no_ctx(enum dss_clock clks);
|
||||
static void dss_clk_disable_no_ctx(enum dss_clock clks);
|
||||
|
||||
static char *def_disp_name;
|
||||
module_param_named(def_disp, def_disp_name, charp, 0);
|
||||
MODULE_PARM_DESC(def_disp_name, "default display name");
|
||||
|
@ -69,297 +55,6 @@ unsigned int dss_debug;
|
|||
module_param_named(debug, dss_debug, bool, 0644);
|
||||
#endif
|
||||
|
||||
/* CONTEXT */
|
||||
static int dss_get_ctx_id(void)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
|
||||
int r;
|
||||
|
||||
if (!pdata->get_last_off_on_transaction_id)
|
||||
return 0;
|
||||
r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
|
||||
if (r < 0) {
|
||||
dev_err(&core.pdev->dev, "getting transaction ID failed, "
|
||||
"will force context restore\n");
|
||||
r = -1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int dss_need_ctx_restore(void)
|
||||
{
|
||||
int id = dss_get_ctx_id();
|
||||
|
||||
if (id < 0 || id != core.ctx_id) {
|
||||
DSSDBG("ctx id %d -> id %d\n",
|
||||
core.ctx_id, id);
|
||||
core.ctx_id = id;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void save_all_ctx(void)
|
||||
{
|
||||
DSSDBG("save context\n");
|
||||
|
||||
dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
dss_save_context();
|
||||
dispc_save_context();
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_save_context();
|
||||
#endif
|
||||
|
||||
dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
}
|
||||
|
||||
static void restore_all_ctx(void)
|
||||
{
|
||||
DSSDBG("restore context\n");
|
||||
|
||||
dss_clk_enable_all_no_ctx();
|
||||
|
||||
dss_restore_context();
|
||||
dispc_restore_context();
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_restore_context();
|
||||
#endif
|
||||
|
||||
dss_clk_disable_all_no_ctx();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
/* CLOCKS */
|
||||
static void core_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
int i;
|
||||
struct clk *clocks[5] = {
|
||||
core.dss_ick,
|
||||
core.dss1_fck,
|
||||
core.dss2_fck,
|
||||
core.dss_54m_fck,
|
||||
core.dss_96m_fck
|
||||
};
|
||||
|
||||
seq_printf(s, "- CORE -\n");
|
||||
|
||||
seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (!clocks[i])
|
||||
continue;
|
||||
seq_printf(s, "%-15s\t%lu\t%d\n",
|
||||
clocks[i]->name,
|
||||
clk_get_rate(clocks[i]),
|
||||
clocks[i]->usecount);
|
||||
}
|
||||
}
|
||||
#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
|
||||
|
||||
static int dss_get_clock(struct clk **clock, const char *clk_name)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
clk = clk_get(&core.pdev->dev, clk_name);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("can't get clock %s", clk_name);
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
*clock = clk;
|
||||
|
||||
DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_get_clocks(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
core.dss_ick = NULL;
|
||||
core.dss1_fck = NULL;
|
||||
core.dss2_fck = NULL;
|
||||
core.dss_54m_fck = NULL;
|
||||
core.dss_96m_fck = NULL;
|
||||
|
||||
r = dss_get_clock(&core.dss_ick, "ick");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&core.dss1_fck, "dss1_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&core.dss2_fck, "dss2_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&core.dss_96m_fck, "video_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (core.dss_ick)
|
||||
clk_put(core.dss_ick);
|
||||
if (core.dss1_fck)
|
||||
clk_put(core.dss1_fck);
|
||||
if (core.dss2_fck)
|
||||
clk_put(core.dss2_fck);
|
||||
if (core.dss_54m_fck)
|
||||
clk_put(core.dss_54m_fck);
|
||||
if (core.dss_96m_fck)
|
||||
clk_put(core.dss_96m_fck);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void dss_put_clocks(void)
|
||||
{
|
||||
if (core.dss_96m_fck)
|
||||
clk_put(core.dss_96m_fck);
|
||||
clk_put(core.dss_54m_fck);
|
||||
clk_put(core.dss1_fck);
|
||||
clk_put(core.dss2_fck);
|
||||
clk_put(core.dss_ick);
|
||||
}
|
||||
|
||||
unsigned long dss_clk_get_rate(enum dss_clock clk)
|
||||
{
|
||||
switch (clk) {
|
||||
case DSS_CLK_ICK:
|
||||
return clk_get_rate(core.dss_ick);
|
||||
case DSS_CLK_FCK1:
|
||||
return clk_get_rate(core.dss1_fck);
|
||||
case DSS_CLK_FCK2:
|
||||
return clk_get_rate(core.dss2_fck);
|
||||
case DSS_CLK_54M:
|
||||
return clk_get_rate(core.dss_54m_fck);
|
||||
case DSS_CLK_96M:
|
||||
return clk_get_rate(core.dss_96m_fck);
|
||||
}
|
||||
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned count_clk_bits(enum dss_clock clks)
|
||||
{
|
||||
unsigned num_clks = 0;
|
||||
|
||||
if (clks & DSS_CLK_ICK)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_FCK1)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_FCK2)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_54M)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_96M)
|
||||
++num_clks;
|
||||
|
||||
return num_clks;
|
||||
}
|
||||
|
||||
static void dss_clk_enable_no_ctx(enum dss_clock clks)
|
||||
{
|
||||
unsigned num_clks = count_clk_bits(clks);
|
||||
|
||||
if (clks & DSS_CLK_ICK)
|
||||
clk_enable(core.dss_ick);
|
||||
if (clks & DSS_CLK_FCK1)
|
||||
clk_enable(core.dss1_fck);
|
||||
if (clks & DSS_CLK_FCK2)
|
||||
clk_enable(core.dss2_fck);
|
||||
if (clks & DSS_CLK_54M)
|
||||
clk_enable(core.dss_54m_fck);
|
||||
if (clks & DSS_CLK_96M)
|
||||
clk_enable(core.dss_96m_fck);
|
||||
|
||||
core.num_clks_enabled += num_clks;
|
||||
}
|
||||
|
||||
void dss_clk_enable(enum dss_clock clks)
|
||||
{
|
||||
bool check_ctx = core.num_clks_enabled == 0;
|
||||
|
||||
dss_clk_enable_no_ctx(clks);
|
||||
|
||||
if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
|
||||
restore_all_ctx();
|
||||
}
|
||||
|
||||
static void dss_clk_disable_no_ctx(enum dss_clock clks)
|
||||
{
|
||||
unsigned num_clks = count_clk_bits(clks);
|
||||
|
||||
if (clks & DSS_CLK_ICK)
|
||||
clk_disable(core.dss_ick);
|
||||
if (clks & DSS_CLK_FCK1)
|
||||
clk_disable(core.dss1_fck);
|
||||
if (clks & DSS_CLK_FCK2)
|
||||
clk_disable(core.dss2_fck);
|
||||
if (clks & DSS_CLK_54M)
|
||||
clk_disable(core.dss_54m_fck);
|
||||
if (clks & DSS_CLK_96M)
|
||||
clk_disable(core.dss_96m_fck);
|
||||
|
||||
core.num_clks_enabled -= num_clks;
|
||||
}
|
||||
|
||||
void dss_clk_disable(enum dss_clock clks)
|
||||
{
|
||||
if (cpu_is_omap34xx()) {
|
||||
unsigned num_clks = count_clk_bits(clks);
|
||||
|
||||
BUG_ON(core.num_clks_enabled < num_clks);
|
||||
|
||||
if (core.num_clks_enabled == num_clks)
|
||||
save_all_ctx();
|
||||
}
|
||||
|
||||
dss_clk_disable_no_ctx(clks);
|
||||
}
|
||||
|
||||
static void dss_clk_enable_all_no_ctx(void)
|
||||
{
|
||||
enum dss_clock clks;
|
||||
|
||||
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
|
||||
if (cpu_is_omap34xx())
|
||||
clks |= DSS_CLK_96M;
|
||||
dss_clk_enable_no_ctx(clks);
|
||||
}
|
||||
|
||||
static void dss_clk_disable_all_no_ctx(void)
|
||||
{
|
||||
enum dss_clock clks;
|
||||
|
||||
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
|
||||
if (cpu_is_omap34xx())
|
||||
clks |= DSS_CLK_96M;
|
||||
dss_clk_disable_no_ctx(clks);
|
||||
}
|
||||
|
||||
static void dss_clk_disable_all(void)
|
||||
{
|
||||
enum dss_clock clks;
|
||||
|
||||
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
|
||||
if (cpu_is_omap34xx())
|
||||
clks |= DSS_CLK_96M;
|
||||
dss_clk_disable(clks);
|
||||
}
|
||||
|
||||
/* REGULATORS */
|
||||
|
||||
struct regulator *dss_get_vdds_dsi(void)
|
||||
|
@ -404,18 +99,7 @@ struct regulator *dss_get_vdda_dac(void)
|
|||
return reg;
|
||||
}
|
||||
|
||||
/* DEBUGFS */
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
static void dss_debug_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
core_dump_clocks(s);
|
||||
dss_dump_clocks(s);
|
||||
dispc_dump_clocks(s);
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_dump_clocks(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int dss_debug_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
void (*func)(struct seq_file *) = s->private;
|
||||
|
@ -508,21 +192,15 @@ static int omap_dss_probe(struct platform_device *pdev)
|
|||
dss_init_overlay_managers(pdev);
|
||||
dss_init_overlays(pdev);
|
||||
|
||||
r = dss_get_clocks();
|
||||
if (r)
|
||||
goto err_clocks;
|
||||
|
||||
dss_clk_enable_all_no_ctx();
|
||||
|
||||
core.ctx_id = dss_get_ctx_id();
|
||||
DSSDBG("initial ctx id %u\n", core.ctx_id);
|
||||
|
||||
r = dss_init_platform_driver();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize DSS platform driver\n");
|
||||
goto err_dss;
|
||||
}
|
||||
|
||||
/* keep clocks enabled to prevent context saves/restores during init */
|
||||
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
r = rfbi_init();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize rfbi\n");
|
||||
|
@ -588,7 +266,7 @@ static int omap_dss_probe(struct platform_device *pdev)
|
|||
pdata->default_device = dssdev;
|
||||
}
|
||||
|
||||
dss_clk_disable_all();
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -611,9 +289,6 @@ static int omap_dss_probe(struct platform_device *pdev)
|
|||
err_rfbi:
|
||||
dss_uninit_platform_driver();
|
||||
err_dss:
|
||||
dss_clk_disable_all_no_ctx();
|
||||
dss_put_clocks();
|
||||
err_clocks:
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -636,16 +311,6 @@ static int omap_dss_remove(struct platform_device *pdev)
|
|||
|
||||
dss_uninit_platform_driver();
|
||||
|
||||
/*
|
||||
* As part of hwmod changes, DSS is not the only controller of dss
|
||||
* clocks; hwmod framework itself will also enable clocks during hwmod
|
||||
* init for dss, and autoidle is set in h/w for DSS. Hence, there's no
|
||||
* need to disable clocks if their usecounts > 1.
|
||||
*/
|
||||
WARN_ON(core.num_clks_enabled > 0);
|
||||
|
||||
dss_put_clocks();
|
||||
|
||||
dss_uninit_overlays(pdev);
|
||||
dss_uninit_overlay_managers(pdev);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/clk.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
#include <plat/clock.h>
|
||||
#include "dss.h"
|
||||
|
||||
#define DSS_BASE 0x48050000
|
||||
|
@ -61,8 +62,15 @@ struct dss_reg {
|
|||
static struct {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
int ctx_id;
|
||||
|
||||
struct clk *dpll4_m4_ck;
|
||||
struct clk *dss_ick;
|
||||
struct clk *dss1_fck;
|
||||
struct clk *dss2_fck;
|
||||
struct clk *dss_54m_fck;
|
||||
struct clk *dss_96m_fck;
|
||||
unsigned num_clks_enabled;
|
||||
|
||||
unsigned long cache_req_pck;
|
||||
unsigned long cache_prate;
|
||||
|
@ -75,6 +83,11 @@ static struct {
|
|||
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
|
||||
} dss;
|
||||
|
||||
static void dss_clk_enable_all_no_ctx(void);
|
||||
static void dss_clk_disable_all_no_ctx(void);
|
||||
static void dss_clk_enable_no_ctx(enum dss_clock clks);
|
||||
static void dss_clk_disable_no_ctx(enum dss_clock clks);
|
||||
|
||||
static int _omap_dss_wait_reset(void);
|
||||
|
||||
static inline void dss_write_reg(const struct dss_reg idx, u32 val)
|
||||
|
@ -640,6 +653,301 @@ static void dss_exit(void)
|
|||
iounmap(dss.base);
|
||||
}
|
||||
|
||||
/* CONTEXT */
|
||||
static int dss_get_ctx_id(void)
|
||||
{
|
||||
struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
|
||||
int r;
|
||||
|
||||
if (!pdata->board_data->get_last_off_on_transaction_id)
|
||||
return 0;
|
||||
r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
|
||||
if (r < 0) {
|
||||
dev_err(&dss.pdev->dev, "getting transaction ID failed, "
|
||||
"will force context restore\n");
|
||||
r = -1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int dss_need_ctx_restore(void)
|
||||
{
|
||||
int id = dss_get_ctx_id();
|
||||
|
||||
if (id < 0 || id != dss.ctx_id) {
|
||||
DSSDBG("ctx id %d -> id %d\n",
|
||||
dss.ctx_id, id);
|
||||
dss.ctx_id = id;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void save_all_ctx(void)
|
||||
{
|
||||
DSSDBG("save context\n");
|
||||
|
||||
dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
dss_save_context();
|
||||
dispc_save_context();
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_save_context();
|
||||
#endif
|
||||
|
||||
dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
}
|
||||
|
||||
static void restore_all_ctx(void)
|
||||
{
|
||||
DSSDBG("restore context\n");
|
||||
|
||||
dss_clk_enable_all_no_ctx();
|
||||
|
||||
dss_restore_context();
|
||||
dispc_restore_context();
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_restore_context();
|
||||
#endif
|
||||
|
||||
dss_clk_disable_all_no_ctx();
|
||||
}
|
||||
|
||||
static int dss_get_clock(struct clk **clock, const char *clk_name)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
clk = clk_get(&dss.pdev->dev, clk_name);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("can't get clock %s", clk_name);
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
*clock = clk;
|
||||
|
||||
DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_get_clocks(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
dss.dss_ick = NULL;
|
||||
dss.dss1_fck = NULL;
|
||||
dss.dss2_fck = NULL;
|
||||
dss.dss_54m_fck = NULL;
|
||||
dss.dss_96m_fck = NULL;
|
||||
|
||||
r = dss_get_clock(&dss.dss_ick, "ick");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&dss.dss1_fck, "dss1_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&dss.dss2_fck, "dss2_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&dss.dss_54m_fck, "tv_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&dss.dss_96m_fck, "video_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (dss.dss_ick)
|
||||
clk_put(dss.dss_ick);
|
||||
if (dss.dss1_fck)
|
||||
clk_put(dss.dss1_fck);
|
||||
if (dss.dss2_fck)
|
||||
clk_put(dss.dss2_fck);
|
||||
if (dss.dss_54m_fck)
|
||||
clk_put(dss.dss_54m_fck);
|
||||
if (dss.dss_96m_fck)
|
||||
clk_put(dss.dss_96m_fck);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void dss_put_clocks(void)
|
||||
{
|
||||
if (dss.dss_96m_fck)
|
||||
clk_put(dss.dss_96m_fck);
|
||||
clk_put(dss.dss_54m_fck);
|
||||
clk_put(dss.dss1_fck);
|
||||
clk_put(dss.dss2_fck);
|
||||
clk_put(dss.dss_ick);
|
||||
}
|
||||
|
||||
unsigned long dss_clk_get_rate(enum dss_clock clk)
|
||||
{
|
||||
switch (clk) {
|
||||
case DSS_CLK_ICK:
|
||||
return clk_get_rate(dss.dss_ick);
|
||||
case DSS_CLK_FCK1:
|
||||
return clk_get_rate(dss.dss1_fck);
|
||||
case DSS_CLK_FCK2:
|
||||
return clk_get_rate(dss.dss2_fck);
|
||||
case DSS_CLK_54M:
|
||||
return clk_get_rate(dss.dss_54m_fck);
|
||||
case DSS_CLK_96M:
|
||||
return clk_get_rate(dss.dss_96m_fck);
|
||||
}
|
||||
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned count_clk_bits(enum dss_clock clks)
|
||||
{
|
||||
unsigned num_clks = 0;
|
||||
|
||||
if (clks & DSS_CLK_ICK)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_FCK1)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_FCK2)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_54M)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_96M)
|
||||
++num_clks;
|
||||
|
||||
return num_clks;
|
||||
}
|
||||
|
||||
static void dss_clk_enable_no_ctx(enum dss_clock clks)
|
||||
{
|
||||
unsigned num_clks = count_clk_bits(clks);
|
||||
|
||||
if (clks & DSS_CLK_ICK)
|
||||
clk_enable(dss.dss_ick);
|
||||
if (clks & DSS_CLK_FCK1)
|
||||
clk_enable(dss.dss1_fck);
|
||||
if (clks & DSS_CLK_FCK2)
|
||||
clk_enable(dss.dss2_fck);
|
||||
if (clks & DSS_CLK_54M)
|
||||
clk_enable(dss.dss_54m_fck);
|
||||
if (clks & DSS_CLK_96M)
|
||||
clk_enable(dss.dss_96m_fck);
|
||||
|
||||
dss.num_clks_enabled += num_clks;
|
||||
}
|
||||
|
||||
void dss_clk_enable(enum dss_clock clks)
|
||||
{
|
||||
bool check_ctx = dss.num_clks_enabled == 0;
|
||||
|
||||
dss_clk_enable_no_ctx(clks);
|
||||
|
||||
if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
|
||||
restore_all_ctx();
|
||||
}
|
||||
|
||||
static void dss_clk_disable_no_ctx(enum dss_clock clks)
|
||||
{
|
||||
unsigned num_clks = count_clk_bits(clks);
|
||||
|
||||
if (clks & DSS_CLK_ICK)
|
||||
clk_disable(dss.dss_ick);
|
||||
if (clks & DSS_CLK_FCK1)
|
||||
clk_disable(dss.dss1_fck);
|
||||
if (clks & DSS_CLK_FCK2)
|
||||
clk_disable(dss.dss2_fck);
|
||||
if (clks & DSS_CLK_54M)
|
||||
clk_disable(dss.dss_54m_fck);
|
||||
if (clks & DSS_CLK_96M)
|
||||
clk_disable(dss.dss_96m_fck);
|
||||
|
||||
dss.num_clks_enabled -= num_clks;
|
||||
}
|
||||
|
||||
void dss_clk_disable(enum dss_clock clks)
|
||||
{
|
||||
if (cpu_is_omap34xx()) {
|
||||
unsigned num_clks = count_clk_bits(clks);
|
||||
|
||||
BUG_ON(dss.num_clks_enabled < num_clks);
|
||||
|
||||
if (dss.num_clks_enabled == num_clks)
|
||||
save_all_ctx();
|
||||
}
|
||||
|
||||
dss_clk_disable_no_ctx(clks);
|
||||
}
|
||||
|
||||
static void dss_clk_enable_all_no_ctx(void)
|
||||
{
|
||||
enum dss_clock clks;
|
||||
|
||||
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
|
||||
if (cpu_is_omap34xx())
|
||||
clks |= DSS_CLK_96M;
|
||||
dss_clk_enable_no_ctx(clks);
|
||||
}
|
||||
|
||||
static void dss_clk_disable_all_no_ctx(void)
|
||||
{
|
||||
enum dss_clock clks;
|
||||
|
||||
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
|
||||
if (cpu_is_omap34xx())
|
||||
clks |= DSS_CLK_96M;
|
||||
dss_clk_disable_no_ctx(clks);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
/* CLOCKS */
|
||||
static void core_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
int i;
|
||||
struct clk *clocks[5] = {
|
||||
dss.dss_ick,
|
||||
dss.dss1_fck,
|
||||
dss.dss2_fck,
|
||||
dss.dss_54m_fck,
|
||||
dss.dss_96m_fck
|
||||
};
|
||||
|
||||
seq_printf(s, "- CORE -\n");
|
||||
|
||||
seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (!clocks[i])
|
||||
continue;
|
||||
seq_printf(s, "%-15s\t%lu\t%d\n",
|
||||
clocks[i]->name,
|
||||
clk_get_rate(clocks[i]),
|
||||
clocks[i]->usecount);
|
||||
}
|
||||
}
|
||||
#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
|
||||
|
||||
/* DEBUGFS */
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
void dss_debug_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
core_dump_clocks(s);
|
||||
dss_dump_clocks(s);
|
||||
dispc_dump_clocks(s);
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_dump_clocks(s);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* DSS HW IP initialisation */
|
||||
static int omap_dsshw_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -648,6 +956,15 @@ static int omap_dsshw_probe(struct platform_device *pdev)
|
|||
|
||||
dss.pdev = pdev;
|
||||
|
||||
r = dss_get_clocks();
|
||||
if (r)
|
||||
goto err_clocks;
|
||||
|
||||
dss_clk_enable_all_no_ctx();
|
||||
|
||||
dss.ctx_id = dss_get_ctx_id();
|
||||
DSSDBG("initial ctx id %u\n", dss.ctx_id);
|
||||
|
||||
#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
|
||||
/* DISPC_CONTROL */
|
||||
if (omap_readl(0x48050440) & 1) /* LCD enabled? */
|
||||
|
@ -660,15 +977,30 @@ static int omap_dsshw_probe(struct platform_device *pdev)
|
|||
goto err_dss;
|
||||
}
|
||||
|
||||
err_dss:
|
||||
dss_clk_disable_all_no_ctx();
|
||||
return 0;
|
||||
|
||||
err_dss:
|
||||
dss_clk_disable_all_no_ctx();
|
||||
dss_put_clocks();
|
||||
err_clocks:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omap_dsshw_remove(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
dss_exit();
|
||||
|
||||
/*
|
||||
* As part of hwmod changes, DSS is not the only controller of dss
|
||||
* clocks; hwmod framework itself will also enable clocks during hwmod
|
||||
* init for dss, and autoidle is set in h/w for DSS. Hence, there's no
|
||||
* need to disable clocks if their usecounts > 1.
|
||||
*/
|
||||
WARN_ON(dss.num_clks_enabled > 0);
|
||||
|
||||
dss_put_clocks();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,11 +169,6 @@ struct seq_file;
|
|||
struct platform_device;
|
||||
|
||||
/* core */
|
||||
void dss_clk_enable(enum dss_clock clks);
|
||||
void dss_clk_disable(enum dss_clock clks);
|
||||
unsigned long dss_clk_get_rate(enum dss_clock clk);
|
||||
int dss_need_ctx_restore(void);
|
||||
void dss_dump_clocks(struct seq_file *s);
|
||||
struct bus_type *dss_get_bus(void);
|
||||
struct regulator *dss_get_vdds_dsi(void);
|
||||
struct regulator *dss_get_vdds_sdi(void);
|
||||
|
@ -219,8 +214,16 @@ void dss_uninit_platform_driver(void);
|
|||
|
||||
void dss_save_context(void);
|
||||
void dss_restore_context(void);
|
||||
void dss_clk_enable(enum dss_clock clks);
|
||||
void dss_clk_disable(enum dss_clock clks);
|
||||
unsigned long dss_clk_get_rate(enum dss_clock clk);
|
||||
int dss_need_ctx_restore(void);
|
||||
void dss_dump_clocks(struct seq_file *s);
|
||||
|
||||
void dss_dump_regs(struct seq_file *s);
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
void dss_debug_dump_clocks(struct seq_file *s);
|
||||
#endif
|
||||
|
||||
void dss_sdi_init(u8 datapairs);
|
||||
int dss_sdi_enable(void);
|
||||
|
|
Loading…
Reference in New Issue