[PATCH 1/8] ARM: sunxi_defconfig: Enable simple panel

372 views
Skip to first unread message

Priit Laes

unread,
Feb 11, 2017, 12:44:17 PM2/11/17
to linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux...@googlegroups.com
From: Jonathan Liu <net...@gmail.com>

Signed-off-by: Jonathan Liu <net...@gmail.com>
---
arch/arm/configs/sunxi_defconfig | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index da92c25..7abe6a4 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -153,3 +153,7 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_FS=y
CONFIG_CRYPTO_DEV_SUN4I_SS=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_DRM_PANEL_SIMPLE=y
--
2.9.3

Priit Laes

unread,
Feb 11, 2017, 12:44:17 PM2/11/17
to linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux...@googlegroups.com, Priit Laes
This series adds initial LVDS functionality for A10 SoC and includes
display blocks (TCON, backend and frontend) for A10 dtsi and implements
of mode property for TCON to allow switching between rgb/lvds output.

This series has been tested on Gemei G9 A10 tablet, but still relies
on u-boot to properly set up LVDS reset controller.

---

Jonathan Liu (1):
ARM: sunxi_defconfig: Enable simple panel

Priit Laes (7):
ARM: sun4i: Add display blocks for the sun4i dtsi.
drm/panel: simple: Add support for LG LP097x02-slq2 panel
drm/sun4i: Add optional 'mode' property to TCON
drm/sun4i: Add encoder type argument to sun4i_tcon0_mode_set
drm/sun4i: Add initial LVDS stub
drm/sun4i: Add various bits and pieces to enable LVDS support on sun4i
ARM: dts: sun4i: gemei-g9: Add LVDS display support

.../bindings/display/sunxi/sun4i-drm.txt | 3 +
arch/arm/boot/dts/sun4i-a10-gemei-g9.dts | 95 ++++++-
arch/arm/boot/dts/sun4i-a10.dtsi | 104 ++++++++
arch/arm/configs/sunxi_defconfig | 4 +
drivers/gpu/drm/panel/panel-simple.c | 25 ++
drivers/gpu/drm/sun4i/Makefile | 1 +
drivers/gpu/drm/sun4i/sun4i_lvds.c | 276 +++++++++++++++++++++
drivers/gpu/drm/sun4i/sun4i_lvds.h | 15 ++
drivers/gpu/drm/sun4i/sun4i_rgb.c | 2 +-
drivers/gpu/drm/sun4i/sun4i_tcon.c | 57 ++++-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 18 +-
11 files changed, 580 insertions(+), 20 deletions(-)
create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h

--
2.9.3

Priit Laes

unread,
Feb 11, 2017, 12:44:25 PM2/11/17
to linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux...@googlegroups.com, Priit Laes
Signed-off-by: Priit Laes <pl...@plaes.org>
---
drivers/gpu/drm/sun4i/Makefile | 1 +
drivers/gpu/drm/sun4i/sun4i_lvds.c | 247 +++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/sun4i/sun4i_lvds.h | 15 +++
3 files changed, 263 insertions(+)
create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index d625a82..5dfbe16 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o
obj-$(CONFIG_DRM_SUN4I) += sun4i_backend.o
obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o
obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
+obj-$(CONFIG_DRM_SUN4I) += sun4i_lvds.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
new file mode 100644
index 0000000..2ba4705
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2016 Priit Laes
+ *
+ * Priit Laes <pl...@plaes.org>
+ *
+ * Based on sun4i_rgb.c by Maxime Ripard <maxime...@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
+
+#include "sun4i_drv.h"
+#include "sun4i_tcon.h"
+
+struct sun4i_lvds {
+ struct drm_connector connector;
+ struct drm_encoder encoder;
+
+ struct sun4i_drv *drv;
+};
+
+static inline struct sun4i_lvds *
+drm_connector_to_sun4i_lvds(struct drm_connector *connector)
+{
+ return container_of(connector, struct sun4i_lvds,
+ connector);
+}
+
+static inline struct sun4i_lvds *
+drm_encoder_to_sun4i_lvds(struct drm_encoder *encoder)
+{
+ return container_of(encoder, struct sun4i_lvds,
+ encoder);
+}
+
+static int sun4i_lvds_get_modes(struct drm_connector *connector)
+{
+ struct sun4i_lvds *lvds =
+ drm_connector_to_sun4i_lvds(connector);
+ struct sun4i_drv *drv = lvds->drv;
+ struct sun4i_tcon *tcon = drv->tcon;
+
+ return drm_panel_get_modes(tcon->panel);
+}
+
+static int sun4i_lvds_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ DRM_DEBUG_DRIVER("LVDS mode valid!\n");
+ return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = {
+ .get_modes = sun4i_lvds_get_modes,
+ .mode_valid = sun4i_lvds_mode_valid,
+};
+
+static enum drm_connector_status
+sun4i_lvds_connector_detect(struct drm_connector *connector, bool force)
+{
+ return connector_status_connected;
+}
+
+static void
+sun4i_lvds_connector_destroy(struct drm_connector *connector)
+{
+ struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector);
+ struct sun4i_drv *drv = lvds->drv;
+ struct sun4i_tcon *tcon = drv->tcon;
+
+ drm_panel_detach(tcon->panel);
+ drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs sun4i_lvds_con_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = sun4i_lvds_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = sun4i_lvds_connector_destroy,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int sun4i_lvds_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ return 0;
+}
+
+static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
+{
+ struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+ struct sun4i_drv *drv = lvds->drv;
+ struct sun4i_tcon *tcon = drv->tcon;
+
+ DRM_DEBUG_DRIVER("Enabling LVDS output\n");
+
+ if (!IS_ERR(tcon->panel)) {
+ drm_panel_prepare(tcon->panel);
+ drm_panel_enable(tcon->panel);
+ }
+
+ /* encoder->bridge can be NULL; drm_bridge_enable checks for it */
+ drm_bridge_enable(encoder->bridge);
+
+ sun4i_tcon_channel_enable(tcon, 0);
+}
+
+static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)
+{
+ struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+ struct sun4i_drv *drv = lvds->drv;
+ struct sun4i_tcon *tcon = drv->tcon;
+
+ DRM_DEBUG_DRIVER("Disabling LVDS output\n");
+
+ sun4i_tcon_channel_disable(tcon, 0);
+
+ /* encoder->bridge can be NULL; drm_bridge_disable checks for it */
+ drm_bridge_disable(encoder->bridge);
+
+ if (!IS_ERR(tcon->panel)) {
+ drm_panel_disable(tcon->panel);
+ drm_panel_unprepare(tcon->panel);
+ }
+}
+
+static void sun4i_lvds_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct sun4i_lvds *lvds = drm_encoder_to_sun4i_lvds(encoder);
+ struct sun4i_drv *drv = lvds->drv;
+ struct sun4i_tcon *tcon = drv->tcon;
+
+ sun4i_tcon0_mode_set(tcon, mode, DRM_MODE_ENCODER_LVDS);
+
+ clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+ /* FIXME: This seems to be board specific */
+ clk_set_phase(tcon->dclk, 60);
+}
+
+static struct drm_encoder_helper_funcs sun4i_lvds_enc_helper_funcs = {
+ .atomic_check = sun4i_lvds_atomic_check,
+ .mode_set = sun4i_lvds_encoder_mode_set,
+ .disable = sun4i_lvds_encoder_disable,
+ .enable = sun4i_lvds_encoder_enable,
+};
+
+static void sun4i_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+static struct drm_encoder_funcs sun4i_lvds_enc_funcs = {
+ .destroy = sun4i_lvds_enc_destroy,
+};
+
+int sun4i_lvds_init(struct drm_device *drm)
+{
+ struct sun4i_drv *drv = drm->dev_private;
+ struct sun4i_tcon *tcon = drv->tcon;
+ struct drm_encoder *encoder;
+ struct sun4i_lvds *lvds;
+ int ret;
+
+ lvds = devm_kzalloc(drm->dev, sizeof(*lvds), GFP_KERNEL);
+ if (!lvds)
+ return -ENOMEM;
+ lvds->drv = drv;
+ encoder = &lvds->encoder;
+
+ tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
+ encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
+ if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
+ dev_info(drm->dev, "No panel or bridge found... LVDS output disabled\n");
+ return 0;
+ }
+
+ drm_encoder_helper_add(&lvds->encoder,
+ &sun4i_lvds_enc_helper_funcs);
+ ret = drm_encoder_init(drm,
+ &lvds->encoder,
+ &sun4i_lvds_enc_funcs,
+ DRM_MODE_ENCODER_NONE,
+ NULL);
+ if (ret) {
+ dev_err(drm->dev, "Couldn't initialise the LVDS encoder\n");
+ goto err_out;
+ }
+
+ /* Hardcode to TCON channel 0 */
+ lvds->encoder.possible_crtcs = BIT(0);
+
+ if (!IS_ERR(tcon->panel)) {
+ drm_connector_helper_add(&lvds->connector,
+ &sun4i_lvds_con_helper_funcs);
+ ret = drm_connector_init(drm, &lvds->connector,
+ &sun4i_lvds_con_funcs,
+ DRM_MODE_CONNECTOR_LVDS);
+ if (ret) {
+ dev_err(drm->dev, "Couldn't initialise the LVDS connector\n");
+ goto err_cleanup_connector;
+ }
+
+ drm_mode_connector_attach_encoder(&lvds->connector,
+ &lvds->encoder);
+
+ ret = drm_panel_attach(tcon->panel, &lvds->connector);
+ if (ret) {
+ dev_err(drm->dev, "Couldn't attach our panel\n");
+ goto err_cleanup_connector;
+ }
+ }
+
+ if (!IS_ERR(encoder->bridge)) {
+ encoder->bridge->encoder = &lvds->encoder;
+
+ ret = drm_bridge_attach(drm, encoder->bridge);
+ if (ret) {
+ dev_err(drm->dev, "Couldn't attach our bridge\n");
+ goto err_cleanup_connector;
+ }
+ } else {
+ encoder->bridge = NULL;
+ }
+
+ return 0;
+
+err_cleanup_connector:
+ drm_encoder_cleanup(&lvds->encoder);
+err_out:
+ return ret;
+}
+EXPORT_SYMBOL(sun4i_lvds_init);
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
new file mode 100644
index 0000000..1fc9646
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2016 Priit Laes <pl...@plaes.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN4I_LVDS_H_
+#define _SUN4I_LVDS_H_
+
+int sun4i_lvds_init(struct drm_device *drm);
+
+#endif /* _SUN4I_LVDS_H_ */
--
2.9.3

Priit Laes

unread,
Feb 11, 2017, 12:44:26 PM2/11/17
to linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux...@googlegroups.com, Priit Laes
Signed-off-by: Priit Laes <pl...@plaes.org>
---
arch/arm/boot/dts/sun4i-a10-gemei-g9.dts | 95 +++++++++++++++++++++++++++++---
1 file changed, 86 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts b/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts
index 9616cde..c19f906 100644
--- a/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts
+++ b/arch/arm/boot/dts/sun4i-a10-gemei-g9.dts
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Priit Laes
+ * Copyright 2015-2017 Priit Laes
*
* Priit Laes <pl...@plaes.org>
*
@@ -48,28 +48,69 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>

/ {
model = "Gemei G9 Tablet";
compatible = "gemei,g9", "allwinner,sun4i-a10";

+ /*
+ * TODO:
+ * 2x cameras via CSI
+ * AXP battery management
+ * NAND
+ * OTG
+ * Touchscreen - gt801_2plus1 @ i2c adapter 2 @ 0x48
+ * HDMI output
+ */
+
aliases {
serial0 = &uart0;
};

+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_backlight_pin>;
+ /* TODO: Figure out proper parameters */
+ pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
+ enable-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
+ default-brightness-level = <8>;
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
+
+ panel: panel {
+ compatible = "lg,lp097x02-slq2";
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_enable_pin &lcd_lvds0_pins>;
+ enable-gpios = <&pio 7 8 GPIO_ACTIVE_HIGH>; /* PH8 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel_input: endpoint {
+ remote-endpoint = <&tcon0_out_panel>;
+ };
+ };
+ };
+
+ display-engine {
+ compatible = "allwinner,sun5i-a13-display-engine";
+ allwinner,pipelines = <&fe0>;
+ };
+};
+
+&be0 {
+ status = "okay";
};

-/*
- * TODO:
- * 2x cameras via CSI
- * AXP battery management
- * NAND
- * OTG
- * Touchscreen - gt801_2plus1 @ i2c adapter 2 @ 0x48
- */
&codec {
/* PH15 controls power to external amplifier (ft2012q) */
pinctrl-names = "default";
@@ -90,6 +131,10 @@
status = "okay";
};

+&fe0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
@@ -159,6 +204,27 @@
pins = "PH15";
function = "gpio_out";
};
+
+ lcd_backlight_pin: lcd_backlight_pin@0 {
+ pins = "PH7";
+ function = "gpio_out";
+ };
+
+ lcd_enable_pin: lcd_enable_pin@0 {
+ pins = "PH8";
+ function = "gpio_out";
+ };
+
+ lcd_lvds0_pins: lcd_lvds0_pins@0 {
+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD9";
+ function = "lvds0";
+ };
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_pins_a>;
+ status = "okay";
};

&reg_dcdc2 {
@@ -194,6 +260,17 @@
status = "okay";
};

+&tcon0 {
+ mode = "lvds";
+ status = "okay";
+};
+
+&tcon0_out {
+ tcon0_out_panel: endpoint@1 {
+ reg = <0>;
+ remote-endpoint = <&panel_input>;
+ };
+};

&uart0 {
pinctrl-names = "default";
--
2.9.3

Priit Laes

unread,
Feb 11, 2017, 12:44:26 PM2/11/17
to linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux...@googlegroups.com, Priit Laes
TODO: We still rely on u-boot for lvds reset bit setup :(

Signed-off-by: Priit Laes <pl...@plaes.org>
---
drivers/gpu/drm/sun4i/sun4i_lvds.c | 29 ++++++++++++++++++++
drivers/gpu/drm/sun4i/sun4i_tcon.c | 54 ++++++++++++++++++++++++++++++++------
drivers/gpu/drm/sun4i/sun4i_tcon.h | 15 +++++++++++
3 files changed, 90 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
index 2ba4705..de738e5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_lvds.c
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
@@ -114,6 +114,35 @@ static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)
/* encoder->bridge can be NULL; drm_bridge_enable checks for it */
drm_bridge_enable(encoder->bridge);

+ /* Enable the LVDS */
+ regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
+ SUN4I_TCON0_LVDS_IF_ENABLE,
+ SUN4I_TCON0_LVDS_IF_ENABLE);
+
+ /*
+ * TODO: SUN4I_TCON0_LVDS_ANA0_REG_C and SUN4I_TCON0_LVDS_ANA0_PD
+ * registers span 3 bits, but we only set upper 2 for both
+ * of them based on values taken from Allwinner driver.
+ */
+ regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
+ SUN4I_TCON0_LVDS_ANA0_CK_EN |
+ SUN4I_TCON0_LVDS_ANA0_REG_V |
+ SUN4I_TCON0_LVDS_ANA0_REG_C |
+ SUN4I_TCON0_LVDS_ANA0_EN_MB |
+ SUN4I_TCON0_LVDS_ANA0_PD |
+ SUN4I_TCON0_LVDS_ANA0_DCHS);
+
+ 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);
+
sun4i_tcon_channel_enable(tcon, 0);
}

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 71d0087..468a3ce 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_device.h>
@@ -29,6 +30,7 @@
#include "sun4i_crtc.h"
#include "sun4i_dotclock.h"
#include "sun4i_drv.h"
+#include "sun4i_lvds.h"
#include "sun4i_rgb.h"
#include "sun4i_tcon.h"

@@ -169,12 +171,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 (type != DRM_MODE_ENCODER_LVDS) {
+ // 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 (type == DRM_MODE_ENCODER_LVDS) {
+ /* 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))
@@ -183,8 +202,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 (type == DRM_MODE_ENCODER_LVDS)
+ 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 */
@@ -480,6 +506,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
struct drm_device *drm = data;
struct sun4i_drv *drv = drm->dev_private;
struct sun4i_tcon *tcon;
+ const char *mode;
int ret;

tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
@@ -525,7 +552,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
goto err_free_clocks;
}

- ret = sun4i_rgb_init(drm);
+ /* Check which output mode is set, defaulting to RGB */
+ ret = of_property_read_string(dev->of_node, "mode", &mode);
+
+ if (ret || !strcmp(mode, "rgb"))
+ ret = sun4i_rgb_init(drm);
+ else if (!strcmp(mode, "lvds"))
+ ret = sun4i_lvds_init(drm);
+ else {
+ dev_err(dev, "Unknown TCON mode: %s\n", mode);
+ ret = -1;
+ }
+
if (ret < 0)
goto err_free_clocks;

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index b040e10..dc4e350 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,18 @@
#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
+#define SUN4I_TCON0_LVDS_ANA0_CK_EN BIT(29) | BIT(28)
+#define SUN4I_TCON0_LVDS_ANA0_REG_V BIT(27) | BIT(26)
+/* TODO: BIT(23) also belongs to ANA0_REG_C register set */
+#define SUN4I_TCON0_LVDS_ANA0_REG_C BIT(25) | BIT(24)
+#define SUN4I_TCON0_LVDS_ANA0_EN_MB BIT(22)
+/* TODO: BIT(19) also belongs to ANA0_PD register set */
+#define SUN4I_TCON0_LVDS_ANA0_PD BIT(21) | BIT(20)
+#define SUN4I_TCON0_LVDS_ANA0_DCHS BIT(16)
+#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.9.3

Priit Laes

unread,
Feb 11, 2017, 12:44:28 PM2/11/17
to linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux...@googlegroups.com, Priit Laes
Add simple-panel support for the LG LP097x02-slq2, which is 10"
1024x768 LVDS panel.

Signed-off-by: Priit Laes <pl...@plaes.org>
---
drivers/gpu/drm/panel/panel-simple.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 06aaf79..2948fed 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1205,6 +1205,28 @@ static const struct panel_desc lg_lp097qx1_spa1 = {
},
};

+static const struct drm_display_mode lg_lp097x02_slq2_mode = {
+ .clock = 100000,
+ .hdisplay = 1024,
+ .hsync_start = 1024 + 260,
+ .hsync_end = 1024 + 260 + 1,
+ .htotal = 1024 + 260 + 1 + 799,
+ .vdisplay = 768,
+ .vsync_start = 768 + 16,
+ .vsync_end = 768 + 16 + 1,
+ .vtotal = 768 + 16 + 1 + 15,
+ .vrefresh = 60,
+};
+
+static const struct panel_desc lg_lp097x02_slq2 = {
+ .modes = &lg_lp097x02_slq2_mode,
+ .num_modes = 1,
+ .size = {
+ .width = 197,
+ .height = 147,
+ },
+};
+
static const struct drm_display_mode lg_lp120up1_mode = {
.clock = 162300,
.hdisplay = 1920,
@@ -1817,6 +1839,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "lg,lp097qx1-spa1",
.data = &lg_lp097qx1_spa1,
}, {
+ .compatible = "lg,lp097x02-slq2",
+ .data = &lg_lp097x02_slq2,
+ }, {
.compatible = "lg,lp120up1",
.data = &lg_lp120up1,
}, {
--
2.9.3

Priit Laes

unread,
Feb 11, 2017, 12:44:48 PM2/11/17
to linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux...@googlegroups.com, Priit Laes
Added basic display pipeline consisting of tcon, display backend and
frontend blocks.

Signed-off-by: Priit Laes <pl...@plaes.org>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 104 +++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)

diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index ba20b48..70991c9 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -779,6 +779,45 @@
#size-cells = <0>;
};

+ tcon0: lcd-controller@1c0c000 {
+ compatible = "allwinner,sun5i-a13-tcon";
+ reg = <0x01c0c000 0x1000>;
+ interrupts = <44>;
+ resets = <&tcon0_ch0_clk 1>;
+ reset-names = "lcd";
+ clocks = <&ahb_gates 36>,
+ <&tcon0_ch0_clk>,
+ <&tcon0_ch1_clk>;
+ clock-names = "ahb",
+ "tcon-ch0",
+ "tcon-ch1";
+ clock-output-names = "tcon-pixel-clock";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon0_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ tcon0_in_be0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&be0_out_tcon0>;
+ };
+ };
+
+ tcon0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
+ };
+
+
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun4i-a10-mmc";
reg = <0x01c0f000 0x1000>;
@@ -1328,5 +1367,70 @@
clocks = <&apb1_gates 7>;
status = "disabled";
};
+
+ fe0: display-frontend@1e00000 {
+ compatible = "allwinner,sun5i-a13-display-frontend";
+ reg = <0x01e00000 0x20000>;
+ interrupts = <47>;
+ clocks = <&ahb_gates 46>, <&de_fe0_clk>,
+ <&dram_gates 25>;
+ clock-names = "ahb", "mod",
+ "ram";
+ resets = <&de_fe0_clk>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fe0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ fe0_out_be0: endpoint {
+ remote-endpoint = <&be0_in_fe0>;
+ };
+ };
+ };
+ };
+
+ be0: display-backend@1e60000 {
+ compatible = "allwinner,sun5i-a13-display-backend";
+ reg = <0x01e60000 0x10000>;
+ clocks = <&ahb_gates 44>, <&de_be0_clk>,
+ <&dram_gates 26>;
+ clock-names = "ahb", "mod",
+ "ram";
+ resets = <&de_be0_clk>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ be0_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ be0_in_fe0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&fe0_out_be0>;
+ };
+ };
+
+ be0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ be0_out_tcon0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_in_be0>;
+ };
+ };
+ };
+ };
};
};
--
2.9.3

Priit Laes

unread,
Feb 11, 2017, 12:44:55 PM2/11/17
to linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux...@googlegroups.com, Priit Laes
Depending on the output type, we have to enable/disable some
bits conditionally.

Signed-off-by: Priit Laes <pl...@plaes.org>
---
drivers/gpu/drm/sun4i/sun4i_rgb.c | 2 +-
drivers/gpu/drm/sun4i/sun4i_tcon.c | 3 ++-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 3 ++-
3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index f5e86fe..3d4eb05 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -179,7 +179,7 @@ static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
struct sun4i_drv *drv = rgb->drv;
struct sun4i_tcon *tcon = drv->tcon;

- sun4i_tcon0_mode_set(tcon, mode);
+ sun4i_tcon0_mode_set(tcon, mode, DRM_MODE_ENCODER_DAC);

clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index ea2906f..71d0087 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -124,7 +124,8 @@ static int sun4i_tcon_get_clk_delay(struct drm_display_mode *mode,
}

void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
- struct drm_display_mode *mode)
+ struct drm_display_mode *mode,
+ int type)
{
unsigned int bp, hsync, vsync;
u8 clk_delay;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 166064b..b040e10 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -188,7 +188,8 @@ void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
void sun4i_tcon_switch_interlace(struct sun4i_tcon *tcon,
bool enable);
void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
- struct drm_display_mode *mode);
+ struct drm_display_mode *mode,
+ int type);
void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
struct drm_display_mode *mode);

--
2.9.3

Priit Laes

unread,
Feb 11, 2017, 12:44:59 PM2/11/17
to linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux...@googlegroups.com, Priit Laes
Add variable to enable either 'rgb' or 'lvds' output.

Signed-off-by: Priit Laes <pl...@plaes.org>
---
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index b82c004..c367ede 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -43,6 +43,9 @@ Required properties:
- reset-names: the reset names mentioned above
- clock-output-names: Name of the pixel clock created

+- mode: Defines which encoder will be enabled. Values are 'rgb', 'lvds'.
+ Defaults to 'rgb' if not set.
+
- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoint, the second one the output
--
2.9.3

Philippe Fouquet

unread,
Feb 12, 2017, 11:50:27 AM2/12/17
to linux-sunxi, linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, net...@gmail.com, thierry...@gmail.com, li...@armlinux.org.uk, we...@csie.org, mark.r...@arm.com, rob...@kernel.org, air...@linux.ie, maxime...@free-electrons.com, quentin...@free-electrons.com, pl...@plaes.org
First way thank for this work
But I can't use it, I'm explain myself.

My LVDS connexion works fine because I display correctly the console under uboot (I work with CONFIG_VIDEO_LCD_MODE)

I use the wiki : http://linux-sunxi.org/LCD to convert my fex config to CONFIG_VIDEO_LCD_MODE for the uboot all work fine

But for the kernel nothing, I have some crazy line or black screen.
I don't know where I can search If some body have a idea?

Thanks 

Priit Laes

unread,
Feb 12, 2017, 3:52:14 PM2/12/17
to Philippe Fouquet, linux-sunxi
On Sun, 2017-02-12 at 08:50 -0800, Philippe Fouquet wrote:
> First way thank for this work
> But I can't use it, I'm explain myself.
>
> My LVDS connexion works fine because I display correctly the console
> under uboot (I work with CONFIG_VIDEO_LCD_MODE)
>
> I use the wiki : http://linux-sunxi.org/LCD to convert my fex config
> to CONFIG_VIDEO_LCD_MODE for the uboot all work fine
>
> But for the kernel nothing, I have some crazy line or black screen.
> I add my lcd configuration into simple_panel.c (http://linux-sunxi.org/LCD)
> I can seen the debug ligne came from LVDS driver.
> My LCD screen is a dlc070ddg 7' 800x480 LVDS 18bits.
> I work with a Olimex_A20-OLinuXino-Micro.
> I don't know where I can search If some body have a idea?

Did you try this patchset or my sun4i-lvds-wip branch on github?

And can you share your devicetree changes?

Chen-Yu Tsai

unread,
Feb 12, 2017, 11:07:22 PM2/12/17
to Priit Laes, linux-kernel, linux-arm-kernel, devicetree, dri-devel, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Maxime Ripard, Quentin Schulz, linux-sunxi
On Sun, Feb 12, 2017 at 1:43 AM, Priit Laes <pl...@plaes.org> wrote:
> From: Jonathan Liu <net...@gmail.com>
>

This needs a commit message about why these need to be enabled, like

"Most Allwinner tablets use the same design of a dumb LCD panel coupled
with a PWM controlled backlight."

Also the subject does not mention CONFIG_BACKLIGHT_PWM being enabled.

> Signed-off-by: Jonathan Liu <net...@gmail.com>

Since you are resending the patch, you must also add your SoB.

ChenYu

> ---
> arch/arm/configs/sunxi_defconfig | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
> index da92c25..7abe6a4 100644
> --- a/arch/arm/configs/sunxi_defconfig
> +++ b/arch/arm/configs/sunxi_defconfig
> @@ -153,3 +153,7 @@ CONFIG_NLS_ISO8859_1=y
> CONFIG_PRINTK_TIME=y
> CONFIG_DEBUG_FS=y
> CONFIG_CRYPTO_DEV_SUN4I_SS=y
> +CONFIG_BACKLIGHT_CLASS_DEVICE=y
> +CONFIG_BACKLIGHT_LCD_SUPPORT=y
> +CONFIG_BACKLIGHT_PWM=y
> +CONFIG_DRM_PANEL_SIMPLE=y
> --
> 2.9.3
>
> --
> 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 linux-sunxi...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Philippe Fouquet

unread,
Feb 13, 2017, 2:22:56 AM2/13/17
to linux-sunxi, ph.fo...@gmail.com
No, I try the branches sun4i-lvds-wip sun4i-lvds-v1 all have the same results.

they have some diff?

I seen in the dts you configure 10 IOs for the lads (5 twisted pairs) but I used just 8 (4 twisted pairs) this difference could be the cause why my display not work?

Thank for your help
Philippe

Maxime Ripard

unread,
Feb 13, 2017, 3:08:29 AM2/13/17
to Priit Laes, linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Quentin Schulz, linux...@googlegroups.com
On Sat, Feb 11, 2017 at 07:44:04PM +0200, Priit Laes wrote:
> TODO: We still rely on u-boot for lvds reset bit setup :(

That needs to be figured out before merging :/

You also have a number of checkpatch warnings / errors that needs to
be fixed.
This should be merged in your patch 6.
This is your patch 5 (and it would be better to put the condition on
what we know rather than what we assume, we know that it's working for
RGB, but not for anything else).

> +
> + if (type == DRM_MODE_ENCODER_LVDS) {
> + /* 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);
> + }

And this in your patch 6

>
> /* Setup the polarity of the various signals */
> if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
> @@ -183,8 +202,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 (type == DRM_MODE_ENCODER_LVDS)
> + 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);

This is covered by your clk_set_phase already.
Why don't you set them then?

Maxime

--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
signature.asc

Maxime Ripard

unread,
Feb 13, 2017, 3:14:50 AM2/13/17
to Priit Laes, linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Quentin Schulz, linux...@googlegroups.com
Hi,

On Sat, Feb 11, 2017 at 07:44:01PM +0200, Priit Laes wrote:
> Add variable to enable either 'rgb' or 'lvds' output.
>
> Signed-off-by: Priit Laes <pl...@plaes.org>
> ---
> Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index b82c004..c367ede 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -43,6 +43,9 @@ Required properties:
> - reset-names: the reset names mentioned above
> - clock-output-names: Name of the pixel clock created
>
> +- mode: Defines which encoder will be enabled. Values are 'rgb', 'lvds'.
> + Defaults to 'rgb' if not set.
> +

Unfortunately, this won't really work. You could very well have two
panels and switch from one to another by changing the pin muxing, so
we have to use an enpoint for that.

This is pretty much the same case that we have with the A10s where we
need to have two output endpoints for the TV Encoder and HDMI,
something we cannot support right now in our binding, since we assume
that we have the two channels that only have one user, which turned
out to be wrong.

I guess an easy way would be to have an extra property defining which
channel the endpoint is attached to.

Thanks,
signature.asc

Maxime Ripard

unread,
Feb 13, 2017, 3:32:45 AM2/13/17
to Priit Laes, linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Quentin Schulz, linux...@googlegroups.com
On Sat, Feb 11, 2017 at 07:44:02PM +0200, Priit Laes wrote:
> Depending on the output type, we have to enable/disable some
> bits conditionally.
>
> Signed-off-by: Priit Laes <pl...@plaes.org>
> ---
> drivers/gpu/drm/sun4i/sun4i_rgb.c | 2 +-
> drivers/gpu/drm/sun4i/sun4i_tcon.c | 3 ++-
> drivers/gpu/drm/sun4i/sun4i_tcon.h | 3 ++-
> 3 files changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index f5e86fe..3d4eb05 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -179,7 +179,7 @@ static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
> struct sun4i_drv *drv = rgb->drv;
> struct sun4i_tcon *tcon = drv->tcon;
>
> - sun4i_tcon0_mode_set(tcon, mode);
> + sun4i_tcon0_mode_set(tcon, mode, DRM_MODE_ENCODER_DAC);

This is not the proper encoder type. You can just use encoder_type in
drm_encoder.
signature.asc

Maxime Ripard

unread,
Feb 13, 2017, 4:16:24 AM2/13/17
to Priit Laes, linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Quentin Schulz, linux...@googlegroups.com
Hi,

On Sat, Feb 11, 2017 at 07:43:59PM +0200, Priit Laes wrote:
> Added basic display pipeline consisting of tcon, display backend and
> frontend blocks.
>
> Signed-off-by: Priit Laes <pl...@plaes.org>
> ---
> arch/arm/boot/dts/sun4i-a10.dtsi | 104 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 104 insertions(+)
>
> diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
> index ba20b48..70991c9 100644
> --- a/arch/arm/boot/dts/sun4i-a10.dtsi
> +++ b/arch/arm/boot/dts/sun4i-a10.dtsi
> @@ -779,6 +779,45 @@
> #size-cells = <0>;
> };
>
> + tcon0: lcd-controller@1c0c000 {
> + compatible = "allwinner,sun5i-a13-tcon";

There's a few bits here and there that need to be setup differently in
A10, so you cannot reuse that compatible (same thing for the other).

Also, I'd really like to have all the blocks listed here, and not only
the first pipeline. Ideally, on the A10, the two pipelines should be
enabled too.
signature.asc

Chen-Yu Tsai

unread,
Feb 13, 2017, 4:21:24 AM2/13/17
to Maxime Ripard, Priit Laes, linux-kernel, linux-arm-kernel, devicetree, dri-devel, Jonathan Liu, Thierry Reding, Russell King, Chen-Yu Tsai, Mark Rutland, Rob Herring, David Airlie, Quentin Schulz, linux-sunxi
On Mon, Feb 13, 2017 at 5:16 PM, Maxime Ripard
<maxime...@free-electrons.com> wrote:
> Hi,
>
> On Sat, Feb 11, 2017 at 07:43:59PM +0200, Priit Laes wrote:
>> Added basic display pipeline consisting of tcon, display backend and
>> frontend blocks.
>>
>> Signed-off-by: Priit Laes <pl...@plaes.org>
>> ---
>> arch/arm/boot/dts/sun4i-a10.dtsi | 104 +++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 104 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
>> index ba20b48..70991c9 100644
>> --- a/arch/arm/boot/dts/sun4i-a10.dtsi
>> +++ b/arch/arm/boot/dts/sun4i-a10.dtsi
>> @@ -779,6 +779,45 @@
>> #size-cells = <0>;
>> };
>>
>> + tcon0: lcd-controller@1c0c000 {
>> + compatible = "allwinner,sun5i-a13-tcon";
>
> There's a few bits here and there that need to be setup differently in
> A10, so you cannot reuse that compatible (same thing for the other).
>
> Also, I'd really like to have all the blocks listed here, and not only
> the first pipeline. Ideally, on the A10, the two pipelines should be
> enabled too.

The display pipeline driver has to be fixed before that can happen
though. And I haven't started to work on what I proposed yet. Though
if someone wants to take over I can forward any design plans I have.

ChenYu

Priit Laes

unread,
Feb 13, 2017, 11:23:23 AM2/13/17
to ph.fo...@gmail.com, linux-sunxi
On Sun, 2017-02-12 at 23:22 -0800, Philippe Fouquet wrote:
> No, I try the branches sun4i-lvds-wip sun4i-lvds-v1 all have the same
> results.
>
> they have some diff?

The sun4i-lvds-wip branch I have in the repository is currently broken
- mainly an experiment to add the LVDS reset line handling so you don't
need u-boot to set up LVDS.

But you need you need do enable LVDS in your device-specific
devicetree, in order it to work, and add the mode property to the tcon
node:

&tcon0 {
       mode = "lvds";
       status = "okay";
};

Priit Laes

unread,
Feb 13, 2017, 11:46:48 AM2/13/17
to we...@csie.org, Maxime Ripard, linux-kernel, linux-arm-kernel, devicetree, dri-devel, Jonathan Liu, Thierry Reding, Russell King, Mark Rutland, Rob Herring, David Airlie, Quentin Schulz, linux-sunxi
Well, my plan was to get at least minimum bits mainlined and then build
additional features on top.

Wens, it would be cool though, if you could share your plans.

Unfortunately I have only single A10 device (with LVDS and mini-HDMI)
but I don't actually have other LVDS-displays I could easily use with
A20 devices (I have CubieTruck and A20-Olinuxino Micro).

Päikest,
Priit :)

Maxime Ripard

unread,
Feb 14, 2017, 3:24:32 AM2/14/17
to Priit Laes, we...@csie.org, linux-kernel, linux-arm-kernel, devicetree, dri-devel, Jonathan Liu, Thierry Reding, Russell King, Mark Rutland, Rob Herring, David Airlie, Quentin Schulz, linux-sunxi
Hi,
I understand that, but now that we have the DT stability to maintain,
I want to make sure that everything is correctly represented from day
one, with code that works.

Otherwise, we might or might not be able to fix things properly later
down the road (or at the expense of ugly hacks).
signature.asc

Philippe Fouquet

unread,
Apr 20, 2017, 3:23:41 AM4/20/17
to linux-sunxi, we...@csie.org, maxime...@free-electrons.com, linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, devic...@vger.kernel.org, dri-...@lists.freedesktop.org, net...@gmail.com, thierry...@gmail.com, li...@armlinux.org.uk, mark.r...@arm.com, rob...@kernel.org, air...@linux.ie, quentin...@free-electrons.com
Hi

If you want I work with a Allwinner A20 (my board are derived from OlinuXino-Micro-A20), and I will interest with LVDS function.

I use your patch but I have nothing to display on my screen.
My hardware is good, it word with u-boot and a older kernel 3.4.104

I use a dlc screen (dlc0700DDG-T-11) my fault is probably on simple-panel information but I didn't seen were

If you can tell me some things to check.

Thank for your help
Best regards
Philippe FOUQUET
Reply all
Reply to author
Forward
0 new messages