@@ -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)
@@ -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);
@@ -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 {
@@ -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 (sig->Hsync_pol)
- di_gen |= DI_GEN_POLARITY_2;
- if (sig->Vsync_pol)
- di_gen |= DI_GEN_POLARITY_3;
+ if (di->id == 1)
+ vsync_cnt = 6;
+
+ 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)
@@ -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:
This adds display interface timings for the Television Encoder connected to IPU DI1 on i.MX53 and adds some configuration glue code to select which IPU signal generators / pins are to be used for HSYNC/VSYNC signals. The default configuration is pin2/pin3 for hsync/vsync. The VGA connector on i.MX53-QSB uses pin7/pin8, and the analog part of the DVI-I connector on MBa53 connects to pin4/pin6. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> --- drivers/staging/imx-drm/imx-drm-core.c | 15 ++++- drivers/staging/imx-drm/imx-drm.h | 4 +- drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h | 3 + drivers/staging/imx-drm/ipu-v3/ipu-di.c | 93 ++++++++++++++++++++++++++--- drivers/staging/imx-drm/ipuv3-crtc.c | 9 ++- 5 files changed, 112 insertions(+), 12 deletions(-)