imx-drm: core: handling of DI clock flags to ipu_crtc_mode_set()
authorRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 21 Dec 2014 15:58:19 +0000 (15:58 +0000)
committerPhilipp Zabel <p.zabel@pengutronix.de>
Wed, 7 Jan 2015 20:32:07 +0000 (21:32 +0100)
We do not need to track the state of the IPU DI's clock flags by having
each display bridge calling back into imx-drm-core, and then back out
into ipuv3-crtc.c.

ipuv3-crtc can instead just scan the list of encoders to retrieve their
type, and build up a picture of which types of encoders are attached.
We can then use this information to configure the IPU DI clocking mode
without any uncertainty - if we have multiple bridges connected to the
same DI, if one of them requires a synchronous DI clock, that's what we
must use.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
drivers/gpu/drm/imx/imx-drm-core.c
drivers/gpu/drm/imx/imx-drm.h
drivers/gpu/drm/imx/ipuv3-crtc.c

index 06cd2e516db6a9efbc608394e616a48e42be0d6b..a002f53aab0e3a3654a722f218be7854ffb70cd4 100644 (file)
@@ -116,8 +116,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);
index 7453ae00c412fbc25a90f6ca783603784edbbae4..3c559ccd6af0042a73564041477cb0950674fe7f 100644 (file)
@@ -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;
index c1fc3735913d3029f8e1f972c22d64bd7d8821e2..98551e356e12a4d2c2fdbff21b00a4e22e8b4f3f 100644 (file)
@@ -46,7 +46,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;
 };
@@ -141,22 +140,42 @@ 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);
        dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
                        mode->vdisplay);
 
+       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;
+
        out_pixel_fmt = ipu_crtc->interface_pix_fmt;
 
        sig_cfg.enable_pol = 1;
        sig_cfg.clk_pol = 0;
        sig_cfg.pixel_fmt = out_pixel_fmt;
-       sig_cfg.clkflags = ipu_crtc->di_clkflags;
        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;
@@ -271,7 +290,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);
@@ -280,19 +299,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;
 }