};
nand@63fdb000 {
- compatible = "fsl,imx53-nand", "mcd_nand";
+ compatible = "fsl,imx53-nand", "mxc_nand";
reg = <0xf7ff0000 0x10000>, <0x63fdb000 0x4000>;
interrupts = <8>;
status = "disabled";
spidev0: spi@0 {
compatible = "spidev";
reg = <0>;
- spi-max-frequency = <250000000>;
+ spi-max-frequency = <54000000>;
};
};
};
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 */
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;
unsigned long parent_rate = clk_get_rate(clk->parent);
if (!rate)
- return -EINVAL;
+ return 0;
div = parent_rate / rate;
div++;
if (div > 8)
- return -EINVAL;
+ return 0;
return parent_rate / div;
{
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);
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, \
/* 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,
/* 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,
_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;
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());
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);
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);
/* 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);
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);
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);
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 */
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;
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;
}
#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
}
# 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
.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)
{
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);
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);
.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;
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;
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);
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;
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;
}
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);
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]);
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event)
{
- printk("%s\n", __func__);
dump_stack();
return 0;
}
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)
.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);
+++ /dev/null
-struct imx_ipu_encoder {
- struct drm_encoder base;
-};
-
-struct imx_ipu_connector {
- struct drm_connector base;
- struct imx_ipu_encoder *encoder;
-};
-
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) {
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);
u32 pixel_fmt, u32 width)
{
struct ipu_dc_priv *priv = dc->priv;
- u32 reg = 0, map;
+ u32 reg = 0;
+ int map;
dc->di = di;
/* 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);
#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>
#define SYNC_WAVE 0
-#define DC_DISP_ID_SYNC(di) (di)
-
struct ipu_di {
void __iomem *base;
int id;
#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)
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);
}
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) {
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)
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);
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);
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) |
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)
unsigned enable_pol:1;
unsigned Hsync_pol:1; /* true = active high */
unsigned Vsync_pol:1;
+ unsigned serial_di:1;
u16 width;
u16 height;
--- /dev/null
+compiler-gcc3.h
\ No newline at end of file
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);