drm: rcar-du: Remove LVDS and HDMI encoders chaining restriction
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Sat, 25 Oct 2014 22:14:27 +0000 (01:14 +0300)
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tue, 23 Dec 2014 10:01:49 +0000 (12:01 +0200)
The rcar-du driver refuses connecting an LVDS output to an HDMI encoder.
There is not technical reason for that restriction, remove it.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drivers/gpu/drm/rcar-du/rcar_du_encoder.c
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c

index 7c74ecf2ca672b66ad3f99ad3162063d5d085bf9..243aba8d4dd270ad74d3d66f52a5c7bc82e7ed9d 100644 (file)
@@ -190,13 +190,6 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
        }
 
        if (type == RCAR_DU_ENCODER_HDMI) {
-               if (renc->lvds) {
-                       dev_err(rcdu->dev,
-                               "Chaining LVDS and HDMI encoders not supported\n");
-                       ret = -EINVAL;
-                       goto done;
-               }
-
                ret = rcar_du_hdmienc_init(rcdu, renc, enc_node);
                if (ret < 0)
                        goto done;
index 359bc999a9c8444ff41d43ee2c8af3cc36308509..0d774a937e7964407f21d987afbab1866a8fba3e 100644 (file)
@@ -21,6 +21,7 @@
 #include "rcar_du_drv.h"
 #include "rcar_du_encoder.h"
 #include "rcar_du_hdmienc.h"
+#include "rcar_du_lvdsenc.h"
 
 struct rcar_du_hdmienc {
        struct rcar_du_encoder *renc;
@@ -39,9 +40,15 @@ static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode)
        if (hdmienc->dpms == mode)
                return;
 
+       if (mode == DRM_MODE_DPMS_ON && hdmienc->renc->lvds)
+               rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode);
+
        if (sfuncs->dpms)
                sfuncs->dpms(encoder, mode);
 
+       if (mode != DRM_MODE_DPMS_ON && hdmienc->renc->lvds)
+               rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode);
+
        hdmienc->dpms = mode;
 }
 
@@ -49,8 +56,16 @@ static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder,
                                       const struct drm_display_mode *mode,
                                       struct drm_display_mode *adjusted_mode)
 {
+       struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
        struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder);
 
+       /* The internal LVDS encoder has a clock frequency operating range of
+        * 30MHz to 150MHz. Clamp the clock accordingly.
+        */
+       if (hdmienc->renc->lvds)
+               adjusted_mode->clock = clamp(adjusted_mode->clock,
+                                            30000, 150000);
+
        if (sfuncs->mode_fixup == NULL)
                return true;