TODO: We still rely on u-boot for clock setup.
Signed-off-by: Priit Laes <[email protected]>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 70 ++++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/sun4i/sun4i_tcon.h | 11 ++++++
 2 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 612c19b..8c7c3d4 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -18,6 +18,7 @@
 #include <drm/drm_panel.h>
 
 #include <linux/component.h>
+#include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/of_address.h>
 #include <linux/of_graph.h>
@@ -75,7 +76,38 @@ void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int 
channel, int type)
                regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
                                   SUN4I_TCON0_CTL_TCON_ENABLE,
                                   SUN4I_TCON0_CTL_TCON_ENABLE);
+
+               if (DRM_MODE_ENCODER_LVDS == type) {
+                       /* Enable the LVDS */
+                       regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+                                          SUN4I_TCON0_LVDS_IF_ENABLE,
+                                          SUN4I_TCON0_LVDS_IF_ENABLE);
+
+                       regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+                                    SUN4I_TCON0_LVDS_ANA0_INIT);
+
+                       regmap_update_bits(tcon->regs, 
SUN4I_TCON0_LVDS_ANA0_REG,
+                                          SUN4I_TCON0_LVDS_ANA0_UPDATE,
+                                          SUN4I_TCON0_LVDS_ANA0_UPDATE);
+
+                       udelay(2000);
+
+                       regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
+                                    SUN4I_TCON0_LVDS_ANA1_INIT);
+
+                       udelay(1000);
+
+                       regmap_update_bits(tcon->regs, 
SUN4I_TCON0_LVDS_ANA1_REG,
+                                    SUN4I_TCON0_LVDS_ANA1_UPDATE,
+                                    SUN4I_TCON0_LVDS_ANA1_UPDATE);
+
+                       regmap_update_bits(tcon->regs, 
SUN4I_TCON0_LVDS_ANA0_REG,
+                                          SUN4I_TCON0_LVDS_ANA0_UPDATE,
+                                          SUN4I_TCON0_LVDS_ANA0_UPDATE);
+               }
+
                clk_prepare_enable(tcon->dclk);
+
        } else if (channel == 1) {
                regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
                                   SUN4I_TCON1_CTL_TCON_ENABLE,
@@ -165,12 +197,29 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
                     SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
 
        /* Set Hsync and Vsync length */
-       hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
-       vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
-       DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
-       regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG,
-                    SUN4I_TCON0_BASIC3_V_SYNC(vsync) |
-                    SUN4I_TCON0_BASIC3_H_SYNC(hsync));
+       if (DRM_MODE_ENCODER_LVDS != type) {
+               // Not needed for LVDS?
+               hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
+               vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
+               DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
+               regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG,
+                            SUN4I_TCON0_BASIC3_V_SYNC(vsync) |
+                            SUN4I_TCON0_BASIC3_H_SYNC(hsync));
+       }
+
+       if (DRM_MODE_ENCODER_LVDS == type) {
+               /* Setup bit depth */
+               /* TODO: Figure out where to get display bit depth
+                * val = (1: 18-bit, 0: 24-bit)
+                * TODO: Should we set more registers:
+                * BIT(28) - LVDS_DIRECTION
+                * BIT(27) - LVDS_MODE
+                * BIT(23) - LVDS_CORRECT_MODE
+                */
+               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+                                  SUN4I_TCON0_LVDS_IF_BITWIDTH,
+                                  SUN4I_TCON0_LVDS_IF_BITWIDTH);
+       }
 
        /* Setup the polarity of the various signals */
        if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
@@ -179,8 +228,15 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
        if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
                val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
 
+
+       /* Set proper DCLK phase value */
+       if (DRM_MODE_ENCODER_LVDS == type)
+               val |= SUN4I_TCON0_IO_POL_DCLK_PHASE(1);
+
        regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
-                          SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | 
SUN4I_TCON0_IO_POL_VSYNC_POSITIVE,
+                          SUN4I_TCON0_IO_POL_HSYNC_POSITIVE |
+                          SUN4I_TCON0_IO_POL_VSYNC_POSITIVE |
+                          SUN4I_TCON0_IO_POL_DCLK_PHASE_MASK,
                           val);
 
        /* Map output pins to channel 0 */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h 
b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 7b0de484..0ab5543 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -69,8 +69,11 @@
 #define SUN4I_TCON0_TTL3_REG                   0x7c
 #define SUN4I_TCON0_TTL4_REG                   0x80
 #define SUN4I_TCON0_LVDS_IF_REG                        0x84
+#define SUN4I_TCON0_LVDS_IF_ENABLE                     BIT(31)
+#define SUN4I_TCON0_LVDS_IF_BITWIDTH                   BIT(26)
 #define SUN4I_TCON0_IO_POL_REG                 0x88
 #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)           ((phase & 3) << 28)
+#define SUN4I_TCON0_IO_POL_DCLK_PHASE_MASK             (3 << 28)
 #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE              BIT(25)
 #define SUN4I_TCON0_IO_POL_VSYNC_POSITIVE              BIT(24)
 
@@ -128,6 +131,14 @@
 #define SUN4I_TCON_CEU_RANGE_G_REG             0x144
 #define SUN4I_TCON_CEU_RANGE_B_REG             0x148
 #define SUN4I_TCON_MUX_CTRL_REG                        0x200
+#define SUN4I_TCON0_LVDS_ANA0_REG              0x220
+/* TODO: use proper register defines instead of "magic" value? */
+#define SUN4I_TCON0_LVDS_ANA0_INIT                     0x3f310000
+/* TODO: rename it to SUN4I_TCON0_LVDS_ANA0_EN_MB like in datasheet ?? */
+#define SUN4I_TCON0_LVDS_ANA0_UPDATE                   BIT(22)
+#define SUN4I_TCON0_LVDS_ANA1_REG              0x224
+#define SUN4I_TCON0_LVDS_ANA1_INIT                     (0x1f << 26 | 0x1f << 
10)
+#define SUN4I_TCON0_LVDS_ANA1_UPDATE                   (0x1f << 16 | 0x1f << 
00)
 #define SUN4I_TCON1_FILL_CTL_REG               0x300
 #define SUN4I_TCON1_FILL_BEG0_REG              0x304
 #define SUN4I_TCON1_FILL_END0_REG              0x308
-- 
2.7.4

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to