@@ -115,8 +115,7 @@ int imx_drm_panel_format_pins(struct drm_encoder *encoder,
helper = &imx_crtc->imx_drm_helper_funcs;
if (helper->set_interface_pix_fmt)
return helper->set_interface_pix_fmt(encoder->crtc,
- encoder->encoder_type, interface_pix_fmt,
- hsync_pin, vsync_pin);
+ interface_pix_fmt, hsync_pin, vsync_pin);
return 0;
}
EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
@@ -17,7 +17,7 @@ int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
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,
+ int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
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;
@@ -51,7 +51,6 @@ struct ipu_crtc {
struct drm_framebuffer *newfb;
int irq;
u32 interface_pix_fmt;
- unsigned long di_clkflags;
int di_hsync_pin;
int di_vsync_pin;
};
@@ -146,10 +145,13 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
int x, int y,
struct drm_framebuffer *old_fb)
{
+ struct drm_device *dev = crtc->dev;
+ struct drm_encoder *encoder;
struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
- int ret;
struct ipu_di_signal_cfg sig_cfg = {};
+ unsigned long encoder_types = 0;
u32 out_pixel_fmt;
+ int ret;
dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
mode->hdisplay);
@@ -165,6 +167,24 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
sig_cfg.Vsync_pol = 1;
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+ if (encoder->crtc == crtc)
+ encoder_types |= BIT(encoder->encoder_type);
+
+ dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n",
+ __func__, encoder_types);
+
+ /*
+ * If we have DAC, TVDAC or LDB, then we need the IPU DI clock
+ * to be the same as the LDB DI clock.
+ */
+ if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) |
+ BIT(DRM_MODE_ENCODER_TVDAC) |
+ BIT(DRM_MODE_ENCODER_LVDS)))
+ sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT;
+ else
+ sig_cfg.clkflags = 0;
+
sig_cfg.enable_pol = ENABLE_POL_HIGH;
sig_cfg.clk_pol = CLK_POL_NEGEDGE;
sig_cfg.width = mode->hdisplay;
@@ -178,7 +198,6 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
sig_cfg.v_sync_width = mode->vsync_end - mode->vsync_start;
sig_cfg.v_end_width = mode->vsync_start - mode->vdisplay;
sig_cfg.pixelclock = mode->clock * 1000;
- sig_cfg.clkflags = ipu_crtc->di_clkflags;
sig_cfg.v_to_h_sync = 0;
@@ -277,7 +296,7 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
ipu_crtc->newfb = NULL;
}
-static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
+static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,
u32 pixfmt, int hsync_pin, int vsync_pin)
{
struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
@@ -286,19 +305,6 @@ static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
ipu_crtc->di_hsync_pin = hsync_pin;
ipu_crtc->di_vsync_pin = vsync_pin;
- switch (encoder_type) {
- case DRM_MODE_ENCODER_DAC:
- case DRM_MODE_ENCODER_TVDAC:
- case DRM_MODE_ENCODER_LVDS:
- ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC |
- IPU_DI_CLKMODE_EXT;
- break;
- case DRM_MODE_ENCODER_TMDS:
- case DRM_MODE_ENCODER_NONE:
- ipu_crtc->di_clkflags = 0;
- break;
- }
-
return 0;
}