]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/video/ipu_common.c
video: ipu: initialize g_ipu_clk, g_ldb_clk statically
[karo-tx-uboot.git] / drivers / video / ipu_common.c
index 98a8003f81a4eaebd39fb98956057548648da397..355c697ef418e462e85d0d673e42141aad4b2117 100644 (file)
@@ -13,6 +13,7 @@
 
 /* #define DEBUG */
 #include <common.h>
+#include <div64.h>
 #include <ipu.h>
 #include <linux/types.h>
 #include <linux/err.h>
@@ -79,7 +80,7 @@ struct ipu_ch_param {
        temp1;                                                  \
 })
 
-#define IPU_SW_RST_TOUT_USEC   (10000)
+#define IPU_SW_RST_TOUT_USEC   10000
 
 static int clk_ipu_enable(struct clk *clk)
 {
@@ -95,27 +96,37 @@ static void clk_ipu_disable(struct clk *clk)
 static struct clk ipu_clk = {
        .name = "ipu_clk",
        .rate = CONFIG_IPUV3_CLK,
-#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
-       .enable_reg = (u32 *)(CCM_BASE_ADDR +
-               offsetof(struct mxc_ccm_reg, CCGR5)),
-       .enable_shift = MXC_CCM_CCGR5_IPU_OFFSET,
-#else
-       .enable_reg = (u32 *)(CCM_BASE_ADDR +
-               offsetof(struct mxc_ccm_reg, CCGR3)),
-       .enable_shift = MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET,
-#endif
        .enable = clk_ipu_enable,
        .disable = clk_ipu_disable,
 };
 
+static int clk_ldb_enable(struct clk *clk)
+{
+       ldb_clk_enable(0);
+       ldb_clk_enable(1);
+       return 0;
+}
+
+static void clk_ldb_disable(struct clk *clk)
+{
+       ldb_clk_disable(0);
+       ldb_clk_disable(1);
+}
+
+#if !defined CONFIG_SYS_LDB_CLOCK
+#define CONFIG_SYS_LDB_CLOCK 65000000
+#endif
+
 static struct clk ldb_clk = {
        .name = "ldb_clk",
-       .rate = 65000000,
+       .rate = CONFIG_SYS_LDB_CLOCK,
+       .enable = clk_ldb_enable,
+       .disable = clk_ldb_disable,
 };
 
 /* Globals */
-struct clk *g_ipu_clk;
-struct clk *g_ldb_clk;
+struct clk *g_ipu_clk = &ipu_clk;
+struct clk *g_ldb_clk = &ldb_clk;
 struct clk *g_di_clk[2];
 struct clk *g_pixel_clk[2];
 unsigned char g_dc_di_assignment[10];
@@ -169,10 +180,12 @@ static inline void ipu_ch_param_set_buffer(uint32_t ch, int bufNum,
 static void ipu_pixel_clk_recalc(struct clk *clk)
 {
        u32 div = __raw_readl(DI_BS_CLKGEN0(clk->id));
+       u64 parent_rate = (u64)clk->parent->rate * 16;
+
        if (div == 0)
                clk->rate = 0;
        else
-               clk->rate = (clk->parent->rate * 16) / div;
+               clk->rate = lldiv(parent_rate, div);
 }
 
 static unsigned long ipu_pixel_clk_round_rate(struct clk *clk,
@@ -180,38 +193,41 @@ static unsigned long ipu_pixel_clk_round_rate(struct clk *clk,
 {
        u32 div, div1;
        u64 tmp;
+
        /*
         * Calculate divider
         * Fractional part is 4 bits,
         * so simply multiply by 2^4 to get fractional part.
         */
        tmp = (u64)clk->parent->rate * 16;
-       div = tmp / rate;
+       div = lldiv(tmp, rate);
 
        if (div < 0x10)            /* Min DI disp clock divider is 1 */
                div = 0x10;
-       if (div & ~0xFEF)
+       if (div & ~0xFEF) {
                div &= 0xFF8;
-       else {
+       else {
                div1 = div & 0xFE0;
-               if ((tmp/div1 - tmp/div) < rate / 4)
+
+               if ((lldiv(tmp, div1) - lldiv(tmp, div)) < rate / 4)
                        div = div1;
                else
                        div &= 0xFF8;
        }
-       tmp /= div;
+       do_div(tmp, div);
 #if 1
        debug("%s: requested rate: %lu.%03luMHz parent_rate: %lu.%03luMHz actual rate: %llu.%03lluMHz div: %u.%u\n", __func__,
                rate / 1000000, rate / 1000 % 1000,
                clk->parent->rate / 1000000, clk->parent->rate / 1000 % 1000,
-               tmp / 1000000, tmp / 1000 % 1000, div / 16, div % 16);
+               lldiv(tmp, 1000000), lldiv(tmp, 1000) % 1000, div / 16, div % 16);
 #endif
        return tmp;
 }
 
 static int ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate)
 {
-       u32 div = ((u64)clk->parent->rate * 16) / rate;
+       u64 parent_rate = (u64)clk->parent->rate * 16;
+       u32 div = lldiv(parent_rate, rate);
 
        debug("%s: parent_rate: %lu.%03luMHz actual rate: %lu.%03luMHz div: %u.%u\n", __func__,
                clk->parent->rate / 1000000, clk->parent->rate / 1000 % 1000,
@@ -221,8 +237,7 @@ static int ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate)
 
        /* Setup pixel clock timing */
        __raw_writel((div / 16) << 16, DI_BS_CLKGEN1(clk->id));
-
-       clk->rate = ((u64)clk->parent->rate * 16) / div;
+       clk->rate = lldiv(parent_rate, div);
        debug("%s: pix_clk=%lu.%03luMHz\n", __func__,
                clk->rate / 1000000, clk->rate / 1000 % 1000);
        return 0;
@@ -297,21 +312,36 @@ static struct clk pixel_clk[] = {
        },
 };
 
+static int clk_ipu_di_enable(struct clk *clk)
+{
+       ipu_di_clk_enable(clk->id);
+       return 0;
+}
+
+static void clk_ipu_di_disable(struct clk *clk)
+{
+       ipu_di_clk_disable(clk->id);
+}
+
 static struct clk di_clk[] = {
        {
                .name = "ipu_di_clk",
                .id = 0,
+               .enable = clk_ipu_di_enable,
+               .disable = clk_ipu_di_disable,
        },
        {
                .name = "ipu_di_clk",
                .id = 1,
+               .enable = clk_ipu_di_enable,
+               .disable = clk_ipu_di_disable,
        },
 };
 
 /*
  * This function resets IPU
  */
-void ipu_reset(void)
+static void ipu_reset(void)
 {
        u32 *reg;
        u32 value;
@@ -345,7 +375,7 @@ int ipu_probe(int di, ipu_di_clk_parent_t di_clk_parent, int di_clk_val)
        int ret;
        void *ipu_base;
        unsigned long start;
-#if defined CONFIG_MX51
+#if defined CONFIG_SOC_MX51
        u32 temp;
        u32 *reg_hsc_mcd = (u32 *)MIPI_HSC_BASE_ADDR;
        u32 *reg_hsc_mxt_conf = (u32 *)(MIPI_HSC_BASE_ADDR + 0x800);
@@ -379,10 +409,7 @@ int ipu_probe(int di, ipu_di_clk_parent_t di_clk_parent, int di_clk_val)
        g_di_clk[1] = &di_clk[1];
        g_di_clk[di]->rate = di_clk_val;
 
-       g_ipu_clk = &ipu_clk;
        debug("ipu_clk = %u\n", clk_get_rate(g_ipu_clk));
-
-       g_ldb_clk = &ldb_clk;
        debug("ldb_clk = %u\n", clk_get_rate(g_ldb_clk));
 
        ret = clk_enable(g_ipu_clk);
@@ -543,9 +570,11 @@ int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params)
                ipu_conf |= IPU_CONF_DMFC_EN;
        if (ipu_di_use_count[0] == 1) {
                ipu_conf |= IPU_CONF_DI0_EN;
+               clk_enable(g_di_clk[0]);
        }
        if (ipu_di_use_count[1] == 1) {
                ipu_conf |= IPU_CONF_DI1_EN;
+               clk_enable(g_di_clk[1]);
        }
 
        __raw_writel(ipu_conf, IPU_CONF);
@@ -626,11 +655,13 @@ void ipu_uninit_channel(ipu_channel_t channel)
                ipu_conf &= ~IPU_CONF_DP_EN;
        if (ipu_dmfc_use_count == 0)
                ipu_conf &= ~IPU_CONF_DMFC_EN;
-       if (ipu_di_use_count[0] == 0) {
+       if (ipu_di_use_count[0] == 0 && ipu_conf & IPU_CONF_DI0_EN) {
                ipu_conf &= ~IPU_CONF_DI0_EN;
+               clk_disable(g_di_clk[0]);
        }
-       if (ipu_di_use_count[1] == 0) {
+       if (ipu_di_use_count[1] == 0 && ipu_conf & IPU_CONF_DI1_EN) {
                ipu_conf &= ~IPU_CONF_DI1_EN;
+               clk_disable(g_di_clk[1]);
        }
 
        __raw_writel(ipu_conf, IPU_CONF);
@@ -1139,3 +1170,11 @@ ipu_color_space_t format_to_colorspace(uint32_t fmt)
        }
        return RGB;
 }
+
+/* should be removed when clk framework is availiable */
+int ipu_set_ldb_clock(int rate)
+{
+       ldb_clk.rate = rate;
+
+       return 0;
+}