diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index cec19f1cf56c..64553058b67e 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -112,8 +112,8 @@ static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm, return NULL; } -int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type, - u32 interface_pix_fmt) +int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type, + u32 interface_pix_fmt, int hsync_pin, int vsync_pin) { struct imx_drm_device *imxdrm = crtc->dev->dev_private; struct imx_drm_crtc *imx_crtc; @@ -134,9 +134,18 @@ found: helper = &imx_crtc->imx_drm_helper_funcs; if (helper->set_interface_pix_fmt) return helper->set_interface_pix_fmt(crtc, - encoder_type, interface_pix_fmt); + encoder_type, interface_pix_fmt, + hsync_pin, vsync_pin); return 0; } +EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format_pins); + +int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type, + u32 interface_pix_fmt) +{ + return imx_drm_crtc_panel_format_pins(crtc, encoder_type, + interface_pix_fmt, 0, 0); +} EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format); int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h index a24508f05845..f2aac91ddf5d 100644 --- a/drivers/staging/imx-drm/imx-drm.h +++ b/drivers/staging/imx-drm/imx-drm.h @@ -18,7 +18,7 @@ struct imx_drm_crtc_helper_funcs { int (*enable_vblank)(struct drm_crtc *crtc); void (*disable_vblank)(struct drm_crtc *crtc); int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type, - u32 pix_fmt); + u32 pix_fmt, int hsync_pin, int vsync_pin); const struct drm_crtc_helper_funcs *crtc_helper_funcs; const struct drm_crtc_funcs *crtc_funcs; }; @@ -54,6 +54,8 @@ struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); struct drm_device *imx_drm_device_get(void); void imx_drm_device_put(void); +int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type, + u32 interface_pix_fmt, int hsync_pin, int vsync_pin); int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type, u32 interface_pix_fmt); void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper); diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h index 66572d585add..74c022e2a532 100644 --- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h +++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h @@ -54,6 +54,9 @@ struct ipu_di_signal_cfg { #define IPU_DI_CLKMODE_SYNC (1 << 0) #define IPU_DI_CLKMODE_EXT (1 << 1) unsigned long clkflags; + + u8 hsync_pin; + u8 vsync_pin; }; enum ipu_color_space { diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-di.c b/drivers/staging/imx-drm/ipu-v3/ipu-di.c index 26534b770f5e..19d777e39d0b 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-di.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-di.c @@ -440,7 +440,7 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di, .repeat_count = sig->height, .cnt_clr_src = DI_SYNC_VSYNC, } , { - /* 5: DE, referenced by DC */ + /* 5: Pixel Active, referenced by DC */ .run_src = DI_SYNC_CLK, .offset_count = sig->h_sync_width + sig->h_start_width, .offset_src = DI_SYNC_CLK, @@ -454,13 +454,78 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di, /* unused */ } , { /* unused */ + }, + }; + /* can't use #7 and #8 for line active and pixel active counters */ + struct di_sync_config cfg_vga[] = { + { + /* 1: INT_HSYNC */ + .run_count = h_total - 1, + .run_src = DI_SYNC_CLK, + } , { + /* 2: VSYNC */ + .run_count = v_total - 1, + .run_src = DI_SYNC_INT_HSYNC, + } , { + /* 3: Line Active */ + .run_src = DI_SYNC_INT_HSYNC, + .offset_count = sig->v_sync_width + sig->v_start_width, + .offset_src = DI_SYNC_INT_HSYNC, + .repeat_count = sig->height, + .cnt_clr_src = 3 /* VSYNC */, + } , { + /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */ + .run_count = h_total - 1, + .run_src = DI_SYNC_CLK, + .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */ + .offset_src = DI_SYNC_CLK, + .cnt_polarity_gen_en = 1, + .cnt_polarity_trigger_src = DI_SYNC_CLK, + .cnt_down = sig->h_sync_width * 2, + } , { + /* 5: Pixel Active signal to DC */ + .run_src = DI_SYNC_CLK, + .offset_count = sig->h_sync_width + sig->h_start_width, + .offset_src = DI_SYNC_CLK, + .repeat_count = sig->width, + .cnt_clr_src = 4, /* Line Active */ + } , { + /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */ + .run_count = v_total - 1, + .run_src = DI_SYNC_INT_HSYNC, + .offset_count = 1, /* magic value from Freescale TVE driver */ + .offset_src = DI_SYNC_INT_HSYNC, + .cnt_polarity_gen_en = 1, + .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, + .cnt_down = sig->v_sync_width * 2, + } , { + /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */ + .run_count = h_total - 1, + .run_src = DI_SYNC_CLK, + .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */ + .offset_src = DI_SYNC_CLK, + .cnt_polarity_gen_en = 1, + .cnt_polarity_trigger_src = DI_SYNC_CLK, + .cnt_down = sig->h_sync_width * 2, + } , { + /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */ + .run_count = v_total - 1, + .run_src = DI_SYNC_INT_HSYNC, + .offset_count = 1, /* magic value from Freescale TVE driver */ + .offset_src = DI_SYNC_INT_HSYNC, + .cnt_polarity_gen_en = 1, + .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, + .cnt_down = sig->v_sync_width * 2, } , { /* unused */ }, }; ipu_di_write(di, v_total - 1, DI_SCR_CONF); - ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg)); + if (sig->hsync_pin == 2 && sig->vsync_pin == 3) + ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg)); + else + ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga)); } int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) @@ -537,11 +602,25 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) ipu_di_sync_config_noninterlaced(di, sig, div); vsync_cnt = 3; + if (di->id == 1) + vsync_cnt = 6; - if (sig->Hsync_pol) - di_gen |= DI_GEN_POLARITY_2; - if (sig->Vsync_pol) - di_gen |= DI_GEN_POLARITY_3; + if (sig->Hsync_pol) { + if (sig->hsync_pin == 2) + di_gen |= DI_GEN_POLARITY_2; + else if (sig->hsync_pin == 4) + di_gen |= DI_GEN_POLARITY_4; + else if (sig->hsync_pin == 7) + di_gen |= DI_GEN_POLARITY_7; + } + if (sig->Vsync_pol) { + if (sig->hsync_pin == 3) + di_gen |= DI_GEN_POLARITY_3; + else if (sig->hsync_pin == 6) + di_gen |= DI_GEN_POLARITY_6; + else if (sig->hsync_pin == 8) + di_gen |= DI_GEN_POLARITY_8; + } } if (!sig->clk_pol) diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c index 620e571cb551..ea61c869110f 100644 --- a/drivers/staging/imx-drm/ipuv3-crtc.c +++ b/drivers/staging/imx-drm/ipuv3-crtc.c @@ -60,6 +60,8 @@ struct ipu_crtc { int irq; u32 interface_pix_fmt; unsigned long di_clkflags; + int di_hsync_pin; + int di_vsync_pin; }; #define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base) @@ -255,6 +257,9 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, sig_cfg.v_to_h_sync = 0; + sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin; + sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin; + if (ipu_crtc->dp) { ret = ipu_dp_setup_channel(ipu_crtc->dp, IPUV3_COLORSPACE_RGB, IPUV3_COLORSPACE_RGB); @@ -406,11 +411,13 @@ static void ipu_disable_vblank(struct drm_crtc *crtc) } static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type, - u32 pixfmt) + u32 pixfmt, int hsync_pin, int vsync_pin) { struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); ipu_crtc->interface_pix_fmt = pixfmt; + ipu_crtc->di_hsync_pin = hsync_pin; + ipu_crtc->di_vsync_pin = vsync_pin; switch (encoder_type) { case DRM_MODE_ENCODER_DAC: