]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
TX53 LVDS support and various fixes
authorLothar Waßmann <LW@KARO-electronics.de>
Fri, 22 Jun 2012 14:22:42 +0000 (16:22 +0200)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 22 Jun 2012 14:22:42 +0000 (16:22 +0200)
15 files changed:
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/tx53.dts
arch/arm/mach-imx/clock-mx51-mx53.c
arch/arm/mach-imx/mach-tx53.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/drm_encon.c
drivers/gpu/drm/imx/imx-drm.c
drivers/gpu/drm/imx/imx-priv.h [deleted file]
drivers/gpu/drm/imx/ipu-v3/ipu-common.c
drivers/gpu/drm/imx/ipu-v3/ipu-dc.c
drivers/gpu/drm/imx/ipu-v3/ipu-di.c
drivers/spi/spi-imx.c
include/drm/imx-ipu-v3.h
include/linux/compiler-gcc2.h [new symlink]
include/linux/gpio-switch.h

index cc51b577b8aca9a5cff82002e1ddf39bb6a493bb..759b5a7ff0408d8d32803b68f63937e119a6f277 100644 (file)
                        };
 
                        nand@63fdb000 {
-                               compatible = "fsl,imx53-nand", "mcd_nand";
+                               compatible = "fsl,imx53-nand", "mxc_nand";
                                reg = <0xf7ff0000 0x10000>, <0x63fdb000 0x4000>;
                                interrupts = <8>;
                                status = "disabled";
index 076d11b12f65115c5e3030b9262292a0b8d8eebc..b3496a197019d60a44e5ca14901fb54cc64f0130 100644 (file)
@@ -78,7 +78,7 @@
                                        spidev0: spi@0 {
                                                compatible = "spidev";
                                                reg = <0>;
-                                               spi-max-frequency = <250000000>;
+                                               spi-max-frequency = <54000000>;
                                        };
                                };
                        };
index c64303c7e6a10241c9fa89f879dfb026691ecae4..70773a7a2e1682b9a840bc049611721d9def982c 100644 (file)
@@ -46,6 +46,8 @@ static struct clk mipi_hsc1_clk;
 static struct clk esdhc1_clk;
 static struct clk esdhc2_clk;
 static struct clk esdhc3_mx53_clk;
+static struct clk ssi1_clk;
+static struct clk ssi2_clk;
 
 #define MAX_DPLL_WAIT_TRIES    1000 /* 1000 * udelay(1) = 1ms */
 
@@ -376,7 +378,7 @@ static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
        if (parent == &pll2_sw_clk)
                reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
        else
-               reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+               return -EINVAL;
 
        __raw_writel(reg, MXC_CCM_CCSR);
        return 0;
@@ -683,7 +685,7 @@ static unsigned long clk_nfc_round_rate(struct clk *clk,
        unsigned long parent_rate = clk_get_rate(clk->parent);
 
        if (!rate)
-               return -EINVAL;
+               return 0;
 
        div = parent_rate / rate;
 
@@ -691,7 +693,7 @@ static unsigned long clk_nfc_round_rate(struct clk *clk,
                div++;
 
        if (div > 8)
-               return -EINVAL;
+               return 0;
 
        return parent_rate / div;
 
@@ -1190,10 +1192,14 @@ static int clk_usb_phy_set_parent(struct clk *clk, struct clk *parent)
 {
        u32 reg;
 
-       reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+       reg = __raw_readl(MXC_CCM_CSCMR1);
 
        if (parent == &pll3_sw_clk)
-               reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
+               reg |= MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+       else if (parent == &osc_clk)
+               reg &= ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+       else
+               return -EINVAL;
 
        __raw_writel(reg, MXC_CCM_CSCMR1);
 
@@ -1319,6 +1325,181 @@ static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
        return 0;
 }
 
+static int clk_ssi1_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg = __raw_readl(MXC_CCM_CSCMR1) &
+               ~MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK;
+       u32 mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,
+                       &pll3_sw_clk, &lp_apm_clk);
+
+       reg |= mux << MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+       return 0;
+}
+
+static int clk_ssi2_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg = __raw_readl(MXC_CCM_CSCMR1) &
+               ~MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK;
+       u32 mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,
+                       &pll3_sw_clk, &lp_apm_clk);
+
+       reg |= mux << MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+       return 0;
+}
+
+static int clk_ssi3_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg = __raw_readl(MXC_CCM_CSCMR1);
+
+       if (parent == &ssi1_clk)
+               reg &= ~MXC_CCM_CSCMR1_SSI3_CLK_SEL;
+       else if (parent == &ssi2_clk)
+               reg |= MXC_CCM_CSCMR1_SSI3_CLK_SEL;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static unsigned long clk_ssi_round_rate(struct clk *clk, unsigned long rate)
+{
+       u32 div;
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+
+       if (!rate)
+               return -EINVAL;
+
+       div = parent_rate / rate;
+
+       if (parent_rate % rate)
+               div++;
+
+       if (div > 512)
+               return -EINVAL;
+
+       return parent_rate / div;
+}
+
+static inline unsigned long clk_ssi1_round_rate(struct clk *clk,
+                                       unsigned long rate)
+{
+       return clk_ssi_round_rate(clk, rate);
+}
+
+static inline unsigned long clk_ssi2_round_rate(struct clk *clk,
+                                       unsigned long rate)
+{
+       return clk_ssi_round_rate(clk, rate);
+}
+
+static inline unsigned long clk_ssi3_round_rate(struct clk *clk,
+                                       unsigned long rate)
+{
+       return 0;
+}
+
+static unsigned long clk_ssi1_get_rate(struct clk *clk)
+{
+       u32 reg, pred, podf;
+
+       reg = __raw_readl(MXC_CCM_CS1CDR);
+       pred = (reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK)
+               >> MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET;
+       podf = (reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK)
+               >> MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET;
+
+       return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),
+                       (pred + 1) * (podf + 1));
+}
+
+static unsigned long clk_ssi3_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent);
+}
+
+static unsigned long clk_ssi2_get_rate(struct clk *clk)
+{
+       u32 reg, pred, podf;
+
+       reg = __raw_readl(MXC_CCM_CS2CDR);
+       pred = (reg & MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK)
+               >> MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET;
+       podf = (reg & MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK)
+               >> MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET;
+
+       return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),
+                       (pred + 1) * (podf + 1));
+}
+
+static int clk_ssi1_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, parent_rate;
+       u32 pre = 0, post = 0;
+
+       parent_rate = clk_get_rate(clk->parent);
+       div = parent_rate / rate;
+
+       if ((parent_rate / div) != rate)
+               return -EINVAL;
+
+       __calc_pre_post_dividers(div, &pre, &post,
+               (MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK >>
+               MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1,
+               (MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK >>
+               MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1);
+
+       /* Set ssi1 clock divider */
+       reg = __raw_readl(MXC_CCM_CS1CDR) &
+               ~(MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK
+               | MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK);
+       reg |= (post - 1) <<
+               MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET;
+       reg |= (pre - 1) <<
+               MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET;
+       __raw_writel(reg, MXC_CCM_CS1CDR);
+
+       return 0;
+}
+
+static int clk_ssi2_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, parent_rate;
+       u32 pre = 0, post = 0;
+
+       parent_rate = clk_get_rate(clk->parent);
+       div = parent_rate / rate;
+
+       if ((parent_rate / div) != rate)
+               return -EINVAL;
+
+       __calc_pre_post_dividers(div, &pre, &post,
+               (MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK >>
+               MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET) + 1,
+               (MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK >>
+               MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET) + 1);
+
+       /* Set ssi2 clock divider */
+       reg = __raw_readl(MXC_CCM_CS2CDR) &
+               ~(MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK
+               | MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK);
+       reg |= (post - 1) <<
+               MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET;
+       reg |= (pre - 1) <<
+               MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET;
+       __raw_writel(reg, MXC_CCM_CS2CDR);
+
+       return 0;
+}
+
+static int clk_ssi3_set_rate(struct clk *clk, unsigned long rate)
+{
+       return -EINVAL;
+}
+
 #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)         \
        static struct clk name = {                                      \
                .id             = i,                                    \
@@ -1397,16 +1578,16 @@ DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
 /* SSI */
 DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
        NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
-       NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
+DEFINE_CLOCK_CCGR(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
+       clk_ssi1, &pll3_sw_clk, &ssi1_ipg_clk);
 DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
        NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
-       NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
+DEFINE_CLOCK_CCGR(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
+       clk_ssi2, &pll3_sw_clk, &ssi2_ipg_clk);
 DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
        NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
-       NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
+DEFINE_CLOCK_CCGR(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
+       clk_ssi3, &pll3_sw_clk, &ssi3_ipg_clk);
 
 /* eCSPI */
 DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -1518,7 +1699,7 @@ DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NU
 
 /* IPU */
 static struct clk ipu_clk = {
-       .set_parent = clk_ipu_set_parent,
+       .set_parent     = clk_ipu_set_parent,
        .enable_reg     = MXC_CCM_CCGR5,
        .enable_shift   = MXC_CCM_CCGRx_CG5_OFFSET,
        .enable         = clk_ipu_enable,
@@ -1825,6 +2006,23 @@ static struct clk_lookup mx53_lookups[] = {
        _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
 };
 
+static int __clk_set_parent(struct clk *clk, struct clk *parent,
+                       const char *fn, int ln)
+{
+       int ret;
+
+       ret = clk_set_parent(clk, parent);
+       if (ret == 0)
+               printk("%s@%d: parent of %p set to %p\n",
+                       fn, ln, clk, parent);
+       else
+               printk("%s@%d: Failed to set parent of %p to %p: %d\n",
+                       fn, ln, clk, parent, ret);
+       return ret;
+}
+
+#define clk_set_parent(c, p)   __clk_set_parent(c, p, __func__, __LINE__)
+
 static void clk_tree_init(void)
 {
        u32 reg;
@@ -1875,7 +2073,6 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
        clk_enable(&cpu_clk);
        clk_enable(&main_bus_clk);
        clk_enable(&sdma_clk);
-//     clk_enable(&ipu_clk);
 
        clk_enable(&iim_clk);
        imx_print_silicon_rev("i.MX51", mx51_revision());
@@ -1899,16 +2096,20 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
        mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
                MX51_INT_GPT);
 
+       pr_clk(ckih);
+       pr_clk(ckih2);
+
        pr_clk(pll1_main);
        pr_clk(pll1_sw);
        pr_clk(pll2_sw);
        pr_clk(pll3_sw);
 
        pr_clk(ipg);
-       pr_clk(ckih);
-       pr_clk(ckih2);
+       pr_clk(axi_a);
+       pr_clk(axi_b);
        pr_clk(lp_apm);
        pr_clk(periph_apm);
+       pr_clk(ddr);
        pr_clk(ssi1);
 
        pr_clk(usboh3);
@@ -1946,6 +2147,10 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
        clk_enable(&main_bus_clk);
        clk_enable(&sdma_clk);
 
+       clk_set_parent(&ipu_di0_clk, &ldb_di0_clk);
+#if 1
+//     clk_enable(&ipu_clk);
+#endif
        clk_enable(&iim_clk);
        imx_print_silicon_rev("i.MX53", mx53_revision());
        clk_disable(&iim_clk);
@@ -1955,7 +2160,6 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
 
        /* set the usboh3_clk parent to pll2_sw_clk */
        clk_set_parent(&usboh3_clk, &pll2_sw_clk);
-//     clk_set_rate(&usboh3_clk, 66666666);
 
        /* Set SDHC parents to be PLL2 */
        clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
@@ -1966,17 +2170,19 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
        clk_set_rate(&esdhc3_mx53_clk, 200000000);
 
        /* set flexcan parents to be IPG */
-       clk_set_parent(&flexcan1_clk, &ipg_clk);
-       clk_set_parent(&flexcan2_clk, &ipg_clk);
+       clk_set_parent(&flexcan_root_clk, &ipg_clk);
 
        clk_set_parent(&ssi1_clk, &pll3_sw_clk);
        clk_set_parent(&ssi2_clk, &pll3_sw_clk);
-       clk_set_parent(&ssi3_clk, &pll3_sw_clk);
+       clk_set_parent(&ssi3_clk, &ssi1_clk);
 
        /* System timer */
        mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
                MX53_INT_GPT);
 
+       pr_clk(ckih);
+       pr_clk(ckih2);
+
        pr_clk(pll1_main);
        pr_clk(pll1_sw);
        pr_clk(pll2_sw);
@@ -1984,10 +2190,12 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
        pr_clk(mx53_pll4_sw);
 
        pr_clk(ipg);
-       pr_clk(ckih);
-       pr_clk(ckih2);
+       pr_clk(axi_a);
+       pr_clk(axi_b);
        pr_clk(lp_apm);
        pr_clk(periph_apm);
+       pr_clk(ddr);
+
        pr_clk(ssi1);
        pr_clk(flexcan1);
        pr_clk(flexcan_root);
index 62758397242ec81404cd00501913c916a0a0f3ae..d9c3ae59145aef56d1042449f5f7129e189de4bd 100644 (file)
@@ -160,6 +160,18 @@ static iomux_v3_cfg_t tx53_pads[] __initdata = {
        MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
        MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
 
+       /* LVDS option */
+       MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
+       MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
+       MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
+       MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
+       MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
+       MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
+       MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
+       MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
+       MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
+       MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
+
        /* USB Host */
        NEW_PAD_CTRL(MX53_PAD_EIM_D31__GPIO3_31, MX53_GPIO_PAD_CTRL), /* VBUSEN */
        NEW_PAD_CTRL(MX53_PAD_EIM_D30__GPIO3_30, MX53_GPIO_PAD_CTRL), /* OC */
@@ -340,7 +352,6 @@ static void __init tx53_stk5v5_board_init(void)
        mxc_iomux_v3_setup_pad(MX53_PAD_DISP0_DAT0__GPIO4_21);
        mxc_iomux_v3_setup_multiple_pads(tx53_flexcan1_pads,
                                        ARRAY_SIZE(tx53_flexcan1_pads));
-
 }
 
 static void (*board_initfunc)(void) __initdata;
@@ -383,6 +394,9 @@ late_initcall(tx53_lcd_of_init);
 
 static int __init tx53_consistent_dma_init(void)
 {
+       if (!of_machine_is_compatible("karo,tx53"))
+               return 0;
+
        init_consistent_dma_size(SZ_8M);
        return 0;
 }
@@ -397,6 +411,8 @@ void __init tx53_common_init(void)
 #ifdef CONFIG_DRM_KMS_ENCON
        drm_encon_add_dummy("imx-drm.0", 0);
        drm_encon_add_dummy("imx-drm.0", 1);
+       /* configure LVDS bridge for DI0 enabled with spwg pixel mapping */
+       writel(0x01, MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR + 8));
 #endif
 }
 
index 71fbf95ddd9692872c9764a96f0d7eab6007d407..e49eb1cd3b4f99d6c233482789b11cc5e1c5b4e4 100644 (file)
@@ -5,7 +5,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 #
 menuconfig DRM
-       tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
+       bool "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
        depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
        select I2C
        select I2C_ALGOBIT
index 76632061eef96b9735c0af654ca0f14d285cea13..cbae55853747fbb0c3aad48dd33e5266e941020a 100644 (file)
@@ -179,6 +179,25 @@ static struct drm_encoder_helper_funcs encoder_helper_funcs = {
        .disable = encoder_disable,
 };
 
+static void drm_encon_type_setup(struct drm_encoder_connector *encon,
+                               const char *name, int id)
+{
+       char *option;
+       char disp_name[17];
+
+       encon->connector.connector_type = DRM_MODE_CONNECTOR_VGA;
+       encon->encoder.encoder_type = DRM_MODE_ENCODER_TMDS;
+
+       snprintf(disp_name, sizeof(disp_name), "LVDS-%u", id + 1);
+       if (fb_get_options(disp_name, &option) || !option)
+               return;
+
+       if (option) {
+               encon->connector.connector_type = DRM_MODE_CONNECTOR_LVDS;
+               encon->encoder.encoder_type = DRM_MODE_ENCODER_LVDS;
+       }
+}
+
 int drm_encoder_connector_init(struct drm_device *drm,
                struct drm_encoder_connector *c)
 {
@@ -187,9 +206,10 @@ int drm_encoder_connector_init(struct drm_device *drm,
 
        drm_connector_helper_add(connector, &connector_helper_funcs);
        drm_connector_init(drm, &c->connector,
-                          &connector_funcs, DRM_MODE_CONNECTOR_VGA);
+                          &connector_funcs, c->connector.connector_type);
 
-       drm_encoder_init(drm, encoder, &encoder_funcs, DRM_MODE_ENCODER_TMDS);
+       drm_encoder_init(drm, encoder, &encoder_funcs,
+                        c->encoder.encoder_type);
        drm_encoder_helper_add(encoder, &encoder_helper_funcs);
 
        drm_mode_connector_attach_encoder(connector, encoder);
@@ -280,6 +300,8 @@ struct drm_encoder_connector *drm_encon_add_dummy(const char *drm_name, int id)
                return NULL;
 
        encon->funcs = &dummy_funcs;
+       drm_encon_type_setup(encon, drm_name, id);
+
        ret = drm_encon_register(drm_name, id, encon);
        if (ret) {
                kfree(encon);
index 213968d1f3561b74b81ebab47a8b4bf19b1a1302..d62a6074ad80132240d40d088625eaf4accc703a 100644 (file)
@@ -143,6 +143,14 @@ static struct ipu_rgb def_rgb_32 = {
        .bits_per_pixel = 32,
 };
 
+static struct ipu_rgb def_rgb_16 = {
+       .red    = { .offset = 11, .length = 5, },
+       .green  = { .offset =  5, .length = 6, },
+       .blue   = { .offset =  0, .length = 5, },
+       .transp = { .offset =  0, .length = 0, },
+       .bits_per_pixel = 16,
+};
+
 static int calc_vref(struct drm_display_mode *mode)
 {
        unsigned long htotal, vtotal;
@@ -203,13 +211,31 @@ static int ipu_fb_set_par(struct drm_crtc *crtc,
        struct ipu_di_signal_cfg sig_cfg;
        u32 out_pixel_fmt;
        struct ipu_ch_param *cpmem = ipu_get_cpmem(ipu_crtc->ipu_ch);
+       struct drm_mode_config *mode_config = &drm->mode_config;
+       struct drm_connector *tmp, *connector = NULL;
+
+       list_for_each_entry(tmp, &mode_config->connector_list, head) {
+               if (tmp->encoder && tmp->encoder->crtc == crtc) {
+                       connector = tmp;
+                       break;
+               }
+       }
+       if (!connector) {
+               DRM_ERROR("Couldn't find connector when setting mode");
+               return -EINVAL;
+       }
 
        ipu_fb_disable(ipu_crtc);
 
        memset(cpmem, 0, sizeof(*cpmem));
-
        memset(&sig_cfg, 0, sizeof(sig_cfg));
-       out_pixel_fmt = ipu_crtc->ipu_res->interface_pix_fmt;
+
+       if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+               sig_cfg.serial_di = 1;
+               out_pixel_fmt = IPU_PIX_FMT_LVDS666;
+       } else {
+               out_pixel_fmt = ipu_crtc->ipu_res->interface_pix_fmt;
+       }
 
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                sig_cfg.interlaced = 1;
@@ -267,7 +293,20 @@ static int ipu_fb_set_par(struct drm_crtc *crtc,
        ipu_cpmem_set_resolution(cpmem, mode->hdisplay, mode->vdisplay);
        ipu_cpmem_set_stride(cpmem, fb->pitches[0]);
        ipu_cpmem_set_buffer(cpmem, 0, phys);
-       ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
+
+       switch (fb->bits_per_pixel) {
+       case 16:
+               ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16);
+               break;
+       case 24:
+       case 32:
+               ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
        ipu_cpmem_set_high_priority(cpmem);
 
        ret = ipu_dmfc_init_channel(ipu_crtc->dmfc, mode->hdisplay);
@@ -402,8 +441,8 @@ static int ipu_ipufb_create(struct drm_fb_helper *helper,
        ipu_fb->virt = info->screen_base;
        ipu_fb->phys = info->fix.smem_start;
        ipu_fb->len = size;
-       dev_info(drm->dev, "%s: %p allocated fb %p [%08x]\n", __func__,
-               ipu_fb, ipu_fb->virt, ipu_fb->phys);
+       dev_info(drm->dev, "%s: %p allocated fb %p [%08x] pix_fmt: %08x bpp: %u depth: %u\n", __func__,
+               ipu_fb, ipu_fb->virt, ipu_fb->phys, mode_cmd.pixel_format, bpp, depth);
 
        info->fix.smem_len = size;
 
@@ -519,8 +558,8 @@ ipu_user_framebuffer_create(struct drm_device *drm,
                return ERR_PTR(-ENOMEM);
        }
 
-       dev_info(drm->dev, "%s: %p allocated fb %p [%08x]\n", __func__,
-               ipu_fb, ipu_fb->virt, ipu_fb->phys);
+       dev_info(drm->dev, "%s: %p allocated fb %p [%08x] pix_fmt: %08x bpp: %u depth: %u\n", __func__,
+               ipu_fb, ipu_fb->virt, ipu_fb->phys, mode_cmd->pixel_format, bpp, depth);
        return &ipu_fb->base;
 }
 
@@ -553,7 +592,7 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
        ipu_fb = to_ipu_framebuffer(fb);
 
        phys = ipu_fb->phys;
-       phys += x * 4; /* FIXME */
+       phys += x * fb->bits_per_pixel / 8;
        phys += y * fb->pitches[0];
 
        ipu_fb_set_par(crtc, mode, phys);
@@ -572,7 +611,7 @@ static int ipu_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        ipu_fb = to_ipu_framebuffer(fb);
 
        phys = ipu_fb->phys;
-       phys += x * 4; /* FIXME */
+       phys += x * fb->bits_per_pixel / 8;
        phys += y * fb->pitches[0];
 
        ipu_cpmem_set_stride(ipu_get_cpmem(ipu_crtc->ipu_ch), fb->pitches[0]);
@@ -631,7 +670,6 @@ static int ipu_page_flip(struct drm_crtc *crtc,
                        struct drm_framebuffer *fb,
                        struct drm_pending_vblank_event *event)
 {
-       printk("%s\n", __func__);
        dump_stack();
        return 0;
 }
@@ -972,11 +1010,9 @@ static struct drm_driver driver = {
 
 static int __devinit ipu_drm_probe(struct platform_device *pdev)
 {
-       int ret;
-
        pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       ret = drm_platform_init(&driver, pdev);
-       return ret;
+
+       return drm_platform_init(&driver, pdev);
 }
 
 static int __devexit ipu_drm_remove(struct platform_device *pdev)
@@ -994,20 +1030,7 @@ static struct platform_driver ipu_drm_driver = {
        .remove = __devexit_p(ipu_drm_remove),
 };
 
-int __init ipu_drm_init(void)
-{
-       int ret;
-       ret = platform_driver_register(&ipu_drm_driver);
-       return ret;
-}
-
-void __exit ipu_drm_exit(void)
-{
-       platform_driver_unregister(&ipu_drm_driver);
-}
-
-late_initcall(ipu_drm_init);
-module_exit(ipu_drm_exit);
+module_platform_driver(ipu_drm_driver);
 
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/gpu/drm/imx/imx-priv.h b/drivers/gpu/drm/imx/imx-priv.h
deleted file mode 100644 (file)
index 32efc59..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-struct imx_ipu_encoder {
-       struct drm_encoder base;
-};
-
-struct imx_ipu_connector {
-       struct drm_connector base;
-       struct imx_ipu_encoder *encoder;
-};
-
index b64b3b26cb094d3c1c32387fef3f78cbeee1df4b..02878aaaf05e653fd06ab55428e43c8c2d5e85bd 100644 (file)
@@ -135,8 +135,8 @@ void ipu_cpmem_set_format_rgb(struct ipu_ch_param *p, struct ipu_rgb *rgb)
                ipu_ch_param_set_field(p, IPU_FIELD_WID3, rgb->transp.length - 1);
                ipu_ch_param_set_field(p, IPU_FIELD_OFS3, to);
        } else {
-               ipu_ch_param_set_field(p, IPU_FIELD_WID3, 7);
-               ipu_ch_param_set_field(p, IPU_FIELD_OFS3, rgb->bits_per_pixel);
+               ipu_ch_param_set_field(p, IPU_FIELD_WID3, 0);
+               ipu_ch_param_set_field(p, IPU_FIELD_OFS3, 0);
        }
 
        switch (rgb->bits_per_pixel) {
@@ -144,18 +144,17 @@ void ipu_cpmem_set_format_rgb(struct ipu_ch_param *p, struct ipu_rgb *rgb)
                bpp = 0;
                npb = 15;
                break;
-       case 24:
-               bpp = 1;
-               npb = 19;
-               break;
        case 16:
                bpp = 3;
-               npb = 31;
+               npb = 15;
                break;
        case 8:
                bpp = 5;
                npb = 63;
                break;
+
+       default:
+               WARN_ON(1);
        }
        ipu_ch_param_set_field(p, IPU_FIELD_BPP, bpp);
        ipu_ch_param_set_field(p, IPU_FIELD_NPB, npb);
index 7b175a3a3a8f1b8ec510ee32bdf9cd5c2918ddc1..573b63db64c3eab712fa1b2e24eef1c0c7354b2e 100644 (file)
@@ -147,7 +147,8 @@ int ipu_dc_init_sync(struct ipu_dc *dc, int di, bool interlaced,
                u32 pixel_fmt, u32 width)
 {
        struct ipu_dc_priv *priv = dc->priv;
-       u32 reg = 0, map;
+       u32 reg = 0;
+       int map;
 
        dc->di = di;
 
@@ -436,8 +437,8 @@ int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
        /* IPU_PIX_FMT_LVDS666 */
        ipu_dc_map_clear(priv, 4);
        ipu_dc_map_config(priv, 4, 0, 5, 0xfc);
-       ipu_dc_map_config(priv, 4, 1, 13, 0xfc);
-       ipu_dc_map_config(priv, 4, 2, 21, 0xfc);
+       ipu_dc_map_config(priv, 4, 1, 11, 0xfc);
+       ipu_dc_map_config(priv, 4, 2, 17, 0xfc);
 
        /* IPU_PIX_FMT_GBR24 */
        ipu_dc_map_clear(priv, 13);
index 82d95a4e53c0aa39826aea100cc3fb8b99ac536e..aa1f21199b8ae93480869a44dc5d54c4f9039caa 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <drm/imx-ipu-v3.h>
-//#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <mach/clock.h>
 
@@ -27,8 +26,6 @@
 
 #define SYNC_WAVE 0
 
-#define DC_DISP_ID_SYNC(di)    (di)
-
 struct ipu_di {
        void __iomem *base;
        int id;
@@ -118,6 +115,8 @@ enum di_sync_wave {
 #define DI_DW_GEN_ACCESS_SIZE_OFFSET           24
 #define DI_DW_GEN_COMPONENT_SIZE_OFFSET                16
 
+#define DI_GEN_DI_CLK_STOP_MODE_MASK           (0xf << 24)
+#define DI_GEN_DI_CLK_STOP_MODE(n)             (((n) << 24) & DI_GEN_DI_CLK_STOP_MODE_MASK)
 #define DI_GEN_DI_CLK_EXT                      (1 << 20)
 #define DI_GEN_DI_VSYNC_EXT                    (1 << 21)
 #define DI_GEN_POLARITY_1                      (1 << 0)
@@ -196,6 +195,8 @@ static int ipu_di_clk_set_rate(struct clk *clk, unsigned long rate)
        int div;
 
        div = ipu_di_clk_calc_div(inrate, rate);
+       if (div < 0)
+               return div;
 
        ipu_get(di->ipu);
        ipu_di_write(di, div, DI_BS_CLKGEN0);
@@ -418,18 +419,26 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
        }
 
        div = ipu_di_read(di, DI_BS_CLKGEN0);
+       div = div / 16;         /* Now divider is integer portion */
+       di_gen = 0;
 
        /* Setup pixel clock timing */
        /* Down time is half of period */
-       ipu_di_write(di, (div / 16) << 16, DI_BS_CLKGEN1);
+       ipu_di_write(di, div << 16, DI_BS_CLKGEN1);
 
-       ipu_di_data_wave_config(di, SYNC_WAVE, div / 16 - 1, div / 16 - 1);
-       ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div / 16 * 2);
+       if (!sig->serial_di) {
+               ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
+               ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
+       } else {
+               ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
+               ipu_di_write(di, 0x300, DI_DW_GEN(SYNC_WAVE));
+               ipu_di_write(di, (div * 2 << 16) | 0, DI_DW_SET(SYNC_WAVE, 3));
 
-       div = div / 16;         /* Now divider is integer portion */
+               di_gen = (di_gen & ~DI_GEN_DI_CLK_STOP_MODE_MASK) |
+                       DI_GEN_DI_CLK_STOP_MODE(6);
+       }
 
-       di_gen = 0;
-       if (sig->ext_clk)
+       if (sig->ext_clk || sig->serial_di)
                di_gen |= DI_GEN_DI_CLK_EXT | DI_GEN_DI_VSYNC_EXT;
 
        if (sig->interlaced) {
@@ -603,7 +612,7 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
                unsigned long base,
                u32 module, struct clk *ipu_clk)
 {
-       const char *con_id;
+       const char *con_id = id ? "di1" : "di0";
        struct ipu_di *di = &dis[id];
 
        if (id > 1)
@@ -611,7 +620,7 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
 
        ipu_dev = dev;
 
-       di->clk = clk_get(dev, NULL);
+       di->clk = clk_get(dev, con_id);
        if (IS_ERR(di->clk))
                return PTR_ERR(di->clk);
 
@@ -637,7 +646,7 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
        di->ipu_di_clk.get_rate = ipu_di_clk_get_rate;
        di->ipu_di_clk.set_rate = ipu_di_clk_set_rate;
        di->ipu_di_clk.round_rate = ipu_di_clk_round_rate;
-       di->ipu_di_clk.parent = di->clk;
+       di->ipu_di_clk.parent = di->ipu_clk;
 
        di->clk_lookup = clkdev_alloc(&di->ipu_di_clk, con_id, "imx-drm.0");
        clkdev_add(di->clk_lookup);
index 570f22053be89fb56d99b464ecc36a9443e2cc8d..993eacb73ce82b1220a60f375a04afbf3903dff0 100644 (file)
@@ -225,11 +225,12 @@ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
        if (unlikely(post > 0xf)) {
                pr_err("%s: cannot set clock freq: %u (base freq: %u)\n",
                                __func__, fspi, fin);
-               return 0xff;
+               pre = 15;
+               post = 15;
+               fspi = fin / (pre + 1) >> post;
+       } else {
+               pre = DIV_ROUND_UP(fin, fspi << post) - 1;
        }
-
-       pre = DIV_ROUND_UP(fin, fspi << post) - 1;
-
        pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
                        __func__, fin, fspi, post, pre);
        return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) |
@@ -733,7 +734,7 @@ static int spi_imx_setup(struct spi_device *spi)
        struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
        int gpio = spi_imx->chipselect[spi->chip_select];
 
-       dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__,
+       dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d Hz\n", __func__,
                 spi->mode, spi->bits_per_word, spi->max_speed_hz);
 
        if (gpio >= 0)
index 28e63f4ba3271a140e4e3291125ef13298a2afb1..70b1a9830a195feeabf43641af2d14204aed426a 100644 (file)
@@ -78,6 +78,7 @@ struct ipu_di_signal_cfg {
        unsigned enable_pol:1;
        unsigned Hsync_pol:1;   /* true = active high */
        unsigned Vsync_pol:1;
+       unsigned serial_di:1;
 
        u16 width;
        u16 height;
diff --git a/include/linux/compiler-gcc2.h b/include/linux/compiler-gcc2.h
new file mode 120000 (symlink)
index 0000000..095df0b
--- /dev/null
@@ -0,0 +1 @@
+compiler-gcc3.h
\ No newline at end of file
index 6567cb0cc87b5767499d543347edbcdb414871bf..5b408b7cf32d32e36a455295cd39d12845e74107 100644 (file)
@@ -47,9 +47,14 @@ static inline void gpio_switch_set(struct gpio_sw *sw, int on)
        if (!sw)
                return;
 
-       if ((on && (sw->enable_count++ == 0)) ||
-               (!on && (--sw->enable_count == 0)))
+       if (!(sw->flags & GPIO_SW_SHARED))
                __gpio_switch_set(sw, on);
+       else
+               if ((on && (sw->enable_count++ == 0)) ||
+                       (!on && (--sw->enable_count == 0))) {
+                       WARN_ON(sw->enable_count < 0);
+                       __gpio_switch_set(sw, on);
+               }
 }
 
 extern void gpio_switch_set_suspend_state(struct gpio_sw *sw, int suspend_state);