OMAP2, 3: DSS2: Move clocks from core driver to dss driver
authorSenthilvadivu Guruswamy <svadivu@ti.com>
Mon, 24 Jan 2011 06:21:58 +0000 (06:21 +0000)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Fri, 11 Mar 2011 13:46:19 +0000 (15:46 +0200)
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>
arch/arm/mach-omap2/clock2420_data.c
arch/arm/mach-omap2/clock2430_data.c
arch/arm/mach-omap2/clock3xxx_data.c
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/dss.h

index 0a992bc8d0d89a7d792610f03af68e9dbc256a41..9ece62a44a3f6b45a69aa60a6f7939fa48592744 100644 (file)
@@ -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),
index 5c647ce05b042f33dbc9e7ea229e437949ce5700..61006ae7eac42649b580d20f0f27c8153b0f7594 100644 (file)
@@ -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),
index 052ac329282f5aebe5bfb5a1cf12e979f593e601..2e47d16fce77a712c9e1a5812d150614fb5de29d 100644 (file)
@@ -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),
index e399ca22e514c2f8a1df77f4508d6885f5a96233..255935541d0d353efc194d84b6b6c0614936e7d5 100644 (file)
 #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 @@ err_dpi:
 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);
 
index 01406f48f438ee0998c38283622675b60207e764..72b395d69aaeb172d49819efa5b9c99d92374fb4 100644 (file)
@@ -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;
 }
 
index 37c4544e890723fba5f5eaea8cf5b2051d8431eb..c535ee1db3ee4960cfa12643298306e2740f42d2 100644 (file)
@@ -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);