Skip to content

Instantly share code, notes, and snippets.

@zavorka
Created October 18, 2018 16:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zavorka/8c8ce200fdbb2e1783e105eecaa01d07 to your computer and use it in GitHub Desktop.
Save zavorka/8c8ce200fdbb2e1783e105eecaa01d07 to your computer and use it in GitHub Desktop.
From 6d8ddf32722560b47f04a1f1c133a0138d6cb458 Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <anarsoul@gmail.com>
Date: Tue, 24 Jul 2018 10:17:28 -0700
Subject: [PATCH 01/17] Pine64 panel WIP
---
drivers/gpu/drm/panel/Kconfig | 9 +
drivers/gpu/drm/panel/Makefile | 1 +
.../drm/panel/panel-feiyang-fy07024di26a30d.c | 284 ++++++++++++++++++
3 files changed, 294 insertions(+)
create mode 100644 drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 6020c30a33b3..147745ef70e1 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -55,6 +55,15 @@ config DRM_PANEL_ILITEK_ILI9881C
Say Y if you want to enable support for panels based on the
Ilitek ILI9881c controller.
+config DRM_PANEL_FEIYANG_FY07024DI26A30D
+ tristate "Feiyang FY07024DI26A30D Panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y if you want to enable support for Feiyang
+ FY07024DI26A30D panel
+
config DRM_PANEL_INNOLUX_P079ZCA
tristate "Innolux P079ZCA panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 5ccaaa9d13af..24e08cf68e70 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o
obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
+obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o
diff --git a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
new file mode 100644
index 000000000000..9f82b544a789
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Vasily Khoruzhick <anarsoul@gmail.com>
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+struct fy07024di26a30d {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+
+ struct backlight_device *backlight;
+ struct regulator *dvdd;
+ struct regulator *avdd;
+ struct gpio_desc *reset;
+};
+
+struct fy07024di26a30d_cmd {
+ u8 cmd;
+ u8 data;
+};
+
+static struct fy07024di26a30d_cmd fy07024di26a30d_init[] = {
+ { .cmd = 0x80, .data = 0x58 },
+ { .cmd = 0x81, .data = 0x47 },
+ { .cmd = 0x82, .data = 0xD4 },
+ { .cmd = 0x83, .data = 0x88 },
+ { .cmd = 0x84, .data = 0xA9 },
+ { .cmd = 0x85, .data = 0xC3 },
+ { .cmd = 0x86, .data = 0x82 },
+};
+
+static inline struct fy07024di26a30d *panel_to_fy07024di26a30d(struct drm_panel *panel)
+{
+ return container_of(panel, struct fy07024di26a30d, panel);
+}
+
+static int fy07024di26a30d_send_cmd_data(struct fy07024di26a30d *ctx, u8 cmd, u8 data)
+{
+ int ret;
+
+ ret = mipi_dsi_dcs_write(ctx->dsi, cmd,
+ (u8[]){ data }, 1);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int fy07024di26a30d_prepare(struct drm_panel *panel)
+{
+ struct fy07024di26a30d *ctx = panel_to_fy07024di26a30d(panel);
+ unsigned int i;
+ int ret;
+ u8 mode;
+
+ gpiod_set_value(ctx->reset, 1);
+ msleep(50);
+
+ msleep(100);
+
+ gpiod_set_value(ctx->reset, 0);
+ msleep(20);
+
+ gpiod_set_value(ctx->reset, 1);
+ msleep(200);
+
+ for (i = 0; i < ARRAY_SIZE(fy07024di26a30d_init); i++) {
+ struct fy07024di26a30d_cmd *cmd = &fy07024di26a30d_init[i];
+
+ ret = fy07024di26a30d_send_cmd_data(ctx, cmd->cmd,
+ cmd->data);
+
+ if (ret)
+ return ret;
+ }
+
+ //mipi_dsi_dcs_get_power_mode(ctx->dsi, &mode);
+ //pr_info("%s: mode: %.8x\n", __func__, (unsigned)mode);
+
+ //ret = mipi_dsi_dcs_set_tear_on(ctx->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ //if (ret)
+ // return ret;
+
+ //mipi_dsi_dcs_exit_sleep_mode(ctx->dsi);
+ //if (ret)
+ // return ret;
+ //mipi_dsi_dcs_get_power_mode(ctx->dsi, &mode);
+ //pr_info("%s: mode: %.8x\n", __func__, (unsigned)mode);
+
+ return 0;
+}
+
+static int fy07024di26a30d_enable(struct drm_panel *panel)
+{
+ struct fy07024di26a30d *ctx = panel_to_fy07024di26a30d(panel);
+
+ msleep(120);
+
+ backlight_enable(ctx->backlight);
+
+ return 0;
+}
+
+static int fy07024di26a30d_disable(struct drm_panel *panel)
+{
+ struct fy07024di26a30d *ctx = panel_to_fy07024di26a30d(panel);
+
+ backlight_disable(ctx->backlight);
+ gpiod_set_value(ctx->reset, 0);
+
+ return 0;
+}
+
+static int fy07024di26a30d_unprepare(struct drm_panel *panel)
+{
+ struct fy07024di26a30d *ctx = panel_to_fy07024di26a30d(panel);
+
+ //mipi_dsi_dcs_enter_sleep_mode(ctx->dsi);
+ //gpiod_set_value(ctx->reset, 0);
+
+ return 0;
+}
+
+static const struct drm_display_mode default_mode = {
+ .clock = 55000,
+ .hdisplay = 1024,
+ .hsync_start = 1024 + 396,
+ .hsync_end = 1024 + 396 + 20,
+ .htotal = 1024 + 396 + 20 + 100,
+ .vdisplay = 600,
+ .vsync_start = 600 + 12,
+ .vsync_end = 600 + 12 + 2,
+ .vtotal = 600 + 12 + 2 + 21,
+ .vrefresh = 60,
+};
+
+static int fy07024di26a30d_get_modes(struct drm_panel *panel)
+{
+ struct drm_connector *connector = panel->connector;
+ struct fy07024di26a30d *ctx = panel_to_fy07024di26a30d(panel);
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(panel->drm, &default_mode);
+ if (!mode) {
+ dev_err(&ctx->dsi->dev, "failed to add mode %ux%ux@%u\n",
+ default_mode.hdisplay, default_mode.vdisplay,
+ default_mode.vrefresh);
+ return -ENOMEM;
+ }
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_probed_add(connector, mode);
+
+ panel->connector->display_info.width_mm = 62;
+ panel->connector->display_info.height_mm = 110;
+
+ return 1;
+}
+
+static const struct drm_panel_funcs fy07024di26a30d_funcs = {
+ .prepare = fy07024di26a30d_prepare,
+ .unprepare = fy07024di26a30d_unprepare,
+ .enable = fy07024di26a30d_enable,
+ .disable = fy07024di26a30d_disable,
+ .get_modes = fy07024di26a30d_get_modes,
+};
+
+static int fy07024di26a30d_dsi_probe(struct mipi_dsi_device *dsi)
+{
+ struct device_node *np;
+ struct fy07024di26a30d *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->dvdd = devm_regulator_get(&dsi->dev, "dvdd");
+ if (IS_ERR(ctx->dvdd))
+ return PTR_ERR(ctx->dvdd);
+
+ ctx->avdd = devm_regulator_get(&dsi->dev, "avdd");
+ if (IS_ERR(ctx->avdd))
+ return PTR_ERR(ctx->avdd);
+
+ ret = regulator_enable(ctx->dvdd);
+ if (ret < 0) {
+ dev_err(&dsi->dev, "failed to enable dvdd: %d\n", ret);
+ return ret;
+ }
+
+ msleep(100);
+
+ ret = regulator_enable(ctx->avdd);
+ if (ret < 0) {
+ dev_err(&dsi->dev, "failed to enable avdd: %d\n", ret);
+ regulator_disable(ctx->dvdd);
+ return ret;
+ }
+
+ mipi_dsi_set_drvdata(dsi, ctx);
+ ctx->dsi = dsi;
+
+ drm_panel_init(&ctx->panel);
+ ctx->panel.dev = &dsi->dev;
+ ctx->panel.funcs = &fy07024di26a30d_funcs;
+
+ ctx->reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->reset)) {
+ dev_err(&dsi->dev, "Couldn't get our reset GPIO\n");
+ return PTR_ERR(ctx->reset);
+ }
+
+ np = of_parse_phandle(dsi->dev.of_node, "backlight", 0);
+ if (np) {
+ ctx->backlight = of_find_backlight_by_node(np);
+ of_node_put(np);
+
+ if (!ctx->backlight)
+ return -EPROBE_DEFER;
+ }
+
+ ret = drm_panel_add(&ctx->panel);
+ if (ret < 0)
+ return ret;
+
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->lanes = 4;
+
+ return mipi_dsi_attach(dsi);
+}
+
+static int fy07024di26a30d_dsi_remove(struct mipi_dsi_device *dsi)
+{
+ struct fy07024di26a30d *ctx = mipi_dsi_get_drvdata(dsi);
+
+ mipi_dsi_detach(dsi);
+ drm_panel_remove(&ctx->panel);
+
+ if (ctx->backlight)
+ put_device(&ctx->backlight->dev);
+
+ return 0;
+}
+
+static const struct of_device_id fy07024di26a30d_of_match[] = {
+ { .compatible = "feiyang,fy07024di26a30d" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, fy07024di26a30d_of_match);
+
+static struct mipi_dsi_driver fy07024di26a30d_dsi_driver = {
+ .probe = fy07024di26a30d_dsi_probe,
+ .remove = fy07024di26a30d_dsi_remove,
+ .driver = {
+ .name = "fy07024di26a30d-dsi",
+ .of_match_table = fy07024di26a30d_of_match,
+ },
+};
+module_mipi_dsi_driver(fy07024di26a30d_dsi_driver);
+
+MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>");
+MODULE_DESCRIPTION("Feiyang FY07024DI26A30D Panel Driver");
+MODULE_LICENSE("GPL v2");
--
2.19.1
From 2c927dc91912e615ff8b8720ef92e6ec6dfdda68 Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <anarsoul@gmail.com>
Date: Tue, 24 Jul 2018 10:17:55 -0700
Subject: [PATCH 02/17] A64 DSI CCU WIP
---
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 10 ++++++----
drivers/clk/sunxi-ng/ccu_nkm.c | 7 +++++++
drivers/clk/sunxi-ng/ccu_nkm.h | 2 ++
3 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index d0e30192f0cf..5680ed5fd875 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -160,11 +160,13 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
#define SUN50I_A64_PLL_MIPI_REG 0x040
static struct ccu_nkm pll_mipi_clk = {
- .enable = BIT(31),
+ .enable = BIT(31) | BIT(23) | BIT(22),
.lock = BIT(28),
.n = _SUNXI_CCU_MULT(8, 4),
.k = _SUNXI_CCU_MULT_MIN(4, 2, 2),
.m = _SUNXI_CCU_DIV(0, 4),
+ //.min_rate = 550000000,
+ //.max_rate = 1400000000,
.common = {
.reg = 0x040,
.hw.init = CLK_HW_INIT("pll-mipi", "pll-video0",
@@ -515,8 +517,8 @@ static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
0x104, 0, 4, 24, 3, BIT(31), 0);
-static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
-static const u8 tcon0_table[] = { 0, 2, };
+static const char * const tcon0_parents[] = { "pll-mipi", };
+static const u8 tcon0_table[] = { 0, };
static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
tcon0_table, 0x118, 24, 3, BIT(31),
CLK_SET_RATE_PARENT);
@@ -579,7 +581,7 @@ static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" };
static const u8 dsi_dphy_table[] = { 0, 2, };
static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy",
dsi_dphy_parents, dsi_dphy_table,
- 0x168, 0, 4, 8, 2, BIT(31), CLK_SET_RATE_PARENT);
+ 0x168, 0, 4, 8, 2, BIT(15), CLK_SET_RATE_PARENT);
static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT);
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 841840e35e61..884d6f54ab6d 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -122,6 +122,13 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
_nkm.min_m = 1;
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
+#if 0
+ if (rate < nkm->min_rate)
+ rate = nkm->min_rate;
+ if (rate > nkm->max_rate)
+ rate = nkm->max_rate;
+#endif
+
if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate *= nkm->fixed_post_div;
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
index cc6efb70a102..c82590481188 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.h
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -35,6 +35,8 @@ struct ccu_nkm {
struct ccu_mux_internal mux;
unsigned int fixed_post_div;
+ unsigned int min_rate;
+ unsigned int max_rate;
struct ccu_common common;
};
--
2.19.1
From b4d6b59401e4af84bdf4210493ac6a6219bb7227 Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <anarsoul@gmail.com>
Date: Tue, 24 Jul 2018 10:18:55 -0700
Subject: [PATCH 03/17] pinebook bl WIP
---
arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
index 897e60cbe38d..e2e426334cfe 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
@@ -22,12 +22,22 @@
ethernet0 = &rtl8723cs;
};
+ vdd_bl: regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "bl-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */
+ enable-active-high;
+ };
+
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm 0 50000 0>;
brightness-levels = <0 5 10 15 20 30 40 55 70 85 100>;
default-brightness-level = <2>;
enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD23 */
+ power-supply = <&vdd_bl>;
};
chosen {
--
2.19.1
From 69f64b9fb15d9fb0093fc3a26aac04477b2587ac Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <anarsoul@gmail.com>
Date: Tue, 24 Jul 2018 10:19:09 -0700
Subject: [PATCH 04/17] A64 DSI DTS wip
---
.../dts/allwinner/sun50i-a64-pine64-plus.dts | 45 ++++++++++++++++
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 54 +++++++++++++++++++
2 files changed, 99 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
index 24f1aac366d6..bd3a965591bd 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
@@ -41,14 +41,53 @@
*/
#include "sun50i-a64-pine64.dts"
+#include <dt-bindings/pwm/pwm.h>
/ {
model = "Pine64+";
compatible = "pine64,pine64-plus", "allwinner,sun50i-a64";
+ pwm_bl: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&r_pwm 0 50000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <1 2 4 8 16 32 64 128 255>;
+ default-brightness-level = <8>;
+ enable-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */
+ };
+
+
/* TODO: Camera, touchscreen, etc. */
};
+&de {
+ status = "okay";
+};
+
+&mixer0 {
+ status = "okay";
+};
+
+&tcon0 {
+ status = "okay";
+};
+
+&dphy {
+ status = "okay";
+};
+
+&dsi {
+ status = "okay";
+
+ panel@0 {
+ compatible = "feiyang,fy07024di26a30d", "simple-panel";
+ reg = <0>;
+ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
+ backlight = <&pwm_bl>;
+ avdd-supply = <&reg_dc1sw>;
+ dvdd-supply = <&reg_dldo2>;
+ };
+};
+
&emac {
pinctrl-names = "default";
pinctrl-0 = <&rgmii_pins>;
@@ -63,3 +102,9 @@
reg = <1>;
};
};
+
+&r_pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_pwm_pin>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 522b9d9a8188..40b77c4a20e7 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -349,6 +349,11 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
+
+ tcon0_out_dsi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dsi_in_tcon0>;
+ };
};
};
};
@@ -707,6 +712,55 @@
status = "disabled";
};
+ ths: thermal-sensor@1c25000 {
+ compatible = "allwinner,sun50i-a64-ths";
+ reg = <0x01c25000 0x100>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_THS>;
+ #io-channel-cells = <0>;
+ #thermal-sensor-cells = <1>;
+ };
+
+ dsi: dsi@1ca0000 {
+ compatible = "allwinner,sun50i-a64-mipi-dsi";
+ reg = <0x01ca0000 0x1000>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&ccu CLK_DSI_DPHY>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ phys = <&dphy>;
+ phy-names = "dphy";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ dsi_in_tcon0: endpoint {
+ remote-endpoint = <&tcon0_out_dsi>;
+ };
+ };
+ };
+ };
+
+ dphy: d-phy@1ca1000 {
+ compatible = "allwinner,sun50i-a64-mipi-dphy";
+ reg = <0x01ca1000 0x1000>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>;
+ clock-names = "bus";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ status = "disabled";
+ #phy-cells = <0>;
+ };
+
uart0: serial@1c28000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28000 0x400>;
--
2.19.1
From 3e6b7e8a18aefddf802eaf331475631b651363dc Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <anarsoul@gmail.com>
Date: Tue, 24 Jul 2018 17:40:28 -0700
Subject: [PATCH 05/17] ccu wip
---
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 6 +++---
drivers/clk/sunxi-ng/ccu_nkm.c | 4 +---
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 5680ed5fd875..e710a098d324 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -165,8 +165,8 @@ static struct ccu_nkm pll_mipi_clk = {
.n = _SUNXI_CCU_MULT(8, 4),
.k = _SUNXI_CCU_MULT_MIN(4, 2, 2),
.m = _SUNXI_CCU_DIV(0, 4),
- //.min_rate = 550000000,
- //.max_rate = 1400000000,
+ .min_rate = 300000000,
+ .max_rate = 1400000000,
.common = {
.reg = 0x040,
.hw.init = CLK_HW_INIT("pll-mipi", "pll-video0",
@@ -517,7 +517,7 @@ static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
0x104, 0, 4, 24, 3, BIT(31), 0);
-static const char * const tcon0_parents[] = { "pll-mipi", };
+static const char * const tcon0_parents[] = { "pll-mipi", "pll-video-2x" };
static const u8 tcon0_table[] = { 0, };
static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
tcon0_table, 0x118, 24, 3, BIT(31),
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 884d6f54ab6d..01e6df4c1232 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -122,12 +122,10 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
_nkm.min_m = 1;
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
-#if 0
if (rate < nkm->min_rate)
rate = nkm->min_rate;
- if (rate > nkm->max_rate)
+ if (nkm->max_rate && (rate > nkm->max_rate))
rate = nkm->max_rate;
-#endif
if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate *= nkm->fixed_post_div;
--
2.19.1
From 79bdbd811779351add3472c01751fc84f47c091e Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <anarsoul@gmail.com>
Date: Tue, 24 Jul 2018 17:40:42 -0700
Subject: [PATCH 06/17] mipi dsi irq wip
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 ++++++---
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 65 ++++++++++++++++++++++++++
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 3 +-
4 files changed, 82 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 67f34799074b..8869fa6a69a1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -669,12 +669,23 @@ static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
spin_unlock_irqrestore(&dev->event_lock, flags);
}
-static irqreturn_t sun4i_tcon_handler(int irq, void *private)
+void sun4i_tcon_handle_vblank(struct sun4i_tcon *tcon)
{
- struct sun4i_tcon *tcon = private;
struct drm_device *drm = tcon->drm;
struct sun4i_crtc *scrtc = tcon->crtc;
struct sunxi_engine *engine = scrtc->engine;
+
+ drm_crtc_handle_vblank(&scrtc->crtc);
+ sun4i_tcon_finish_page_flip(drm, scrtc);
+
+ if (engine->ops->vblank_quirk)
+ engine->ops->vblank_quirk(engine);
+}
+EXPORT_SYMBOL(sun4i_tcon_handle_vblank);
+
+static irqreturn_t sun4i_tcon_handler(int irq, void *private)
+{
+ struct sun4i_tcon *tcon = private;
unsigned int status;
regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status);
@@ -684,9 +695,6 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private)
SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT)))
return IRQ_NONE;
- drm_crtc_handle_vblank(&scrtc->crtc);
- sun4i_tcon_finish_page_flip(drm, scrtc);
-
/* Acknowledge the interrupt */
regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG,
SUN4I_TCON_GINT0_VBLANK_INT(0) |
@@ -694,8 +702,7 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private)
SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT,
0);
- if (engine->ops->vblank_quirk)
- engine->ops->vblank_quirk(engine);
+ sun4i_tcon_handle_vblank(tcon);
return IRQ_HANDLED;
}
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 7428e967d61c..11605c54fd9b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -279,6 +279,7 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
const struct drm_display_mode *mode);
void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
const struct drm_encoder *encoder, bool enable);
+void sun4i_tcon_handle_vblank(struct sun4i_tcon *crtc);
extern const struct of_device_id sun4i_tcon_of_table[];
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index d8d4e9723854..4892b76b0cd8 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -25,6 +25,7 @@
#include <drm/drm_panel.h>
#include "sun4i_drv.h"
+#include "sun4i_tcon.h"
#include "sun6i_mipi_dsi.h"
#include <video/mipi_display.h>
@@ -32,6 +33,10 @@
#define SUN6I_DSI_CTL_REG 0x000
#define SUN6I_DSI_CTL_EN BIT(0)
+#define SUN6I_DSI_GINT_REG 0x004
+#define SUN6I_DSI_GINT_VIDEO_VBLK_ENABLE BIT(2)
+#define SUN6I_DSI_GINT_VIDEO_VBLK_INT BIT(18)
+
#define SUN6I_DSI_BASIC_CTL_REG 0x00c
#define SUN6I_DSI_BASIC_CTL_TRAIL_INV(n) (((n) & 0xf) << 4)
#define SUN6I_DSI_BASIC_CTL_TRAIL_FILL BIT(3)
@@ -738,6 +743,9 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
udelay(1000);
sun6i_dsi_start(dsi, DSI_START_HSD);
+
+ regmap_write(dsi->regs, SUN6I_DSI_GINT_REG,
+ SUN6I_DSI_GINT_VIDEO_VBLK_ENABLE);
}
static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder)
@@ -746,6 +754,8 @@ static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder)
DRM_DEBUG_DRIVER("Disabling DSI output\n");
+ regmap_write(dsi->regs, SUN6I_DSI_GINT_REG, 0);
+
if (!IS_ERR(dsi->panel)) {
drm_panel_disable(dsi->panel);
drm_panel_unprepare(dsi->panel);
@@ -968,6 +978,46 @@ static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host,
return ret;
}
+static irqreturn_t sun6i_dsi_handler(int irq, void *private)
+{
+ struct sun6i_dsi *dsi = private;
+ struct sun4i_tcon *tcon = dsi->tcon;
+ unsigned int status;
+
+ regmap_read(dsi->regs, SUN6I_DSI_GINT_REG, &status);
+
+ if (!(status & SUN6I_DSI_GINT_VIDEO_VBLK_INT))
+ return IRQ_NONE;
+
+ regmap_update_bits(dsi->regs, SUN6I_DSI_GINT_REG,
+ SUN6I_DSI_GINT_VIDEO_VBLK_INT,
+ SUN6I_DSI_GINT_VIDEO_VBLK_INT);
+
+ sun4i_tcon_handle_vblank(tcon);
+
+ return IRQ_HANDLED;
+}
+static int sun6i_dsi_init_irq(struct device *dev, struct sun6i_dsi *dsi)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ int irq, ret;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "Couldn't retrieve the DSI interrupt\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, sun6i_dsi_handler, 0,
+ dev_name(dev), dsi);
+ if (ret) {
+ dev_err(dev, "Couldn't request the IRQ\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct mipi_dsi_host_ops sun6i_dsi_host_ops = {
.attach = sun6i_dsi_attach,
.detach = sun6i_dsi_detach,
@@ -988,6 +1038,7 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,
struct drm_device *drm = data;
struct sun4i_drv *drv = drm->dev_private;
struct sun6i_dsi *dsi = dev_get_drvdata(dev);
+ struct sun4i_tcon *tcon;
int ret;
if (!dsi->panel)
@@ -995,6 +1046,19 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,
dsi->drv = drv;
+ list_for_each_entry(tcon, &drv->tcon_list, list)
+ if (tcon->id == 0)
+ dsi->tcon = tcon;
+
+ if (!dsi->tcon)
+ return -EPROBE_DEFER;
+
+ if (dsi->quirks->use_dsi_irq) {
+ ret = sun6i_dsi_init_irq(dev, dsi);
+ if (ret)
+ return ret;
+ }
+
drm_encoder_helper_add(&dsi->encoder,
&sun6i_dsi_enc_helper_funcs);
ret = drm_encoder_init(drm,
@@ -1195,6 +1259,7 @@ static const struct sun6i_dsi_quirks sun6i_a31_quirks = {
static const struct sun6i_dsi_quirks sun50i_a64_quirks = {
.mod_clk_freq = 148500000,
+ .use_dsi_irq = true,
};
static const struct of_device_id sun6i_dsi_of_table[] = {
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index d08a930867b2..cfbbedb99905 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -38,15 +38,16 @@ struct sun6i_dsi {
struct device *dev;
struct sun4i_drv *drv;
+ struct sun4i_tcon *tcon;
struct mipi_dsi_device *device;
struct drm_panel *panel;
const struct sun6i_dsi_quirks *quirks;
-
};
struct sun6i_dsi_quirks {
long mod_clk_freq;
+ bool use_dsi_irq;
};
static inline struct sun6i_dsi *host_to_sun6i_dsi(struct mipi_dsi_host *host)
--
2.19.1
From fd544868a846aa902f1ae9774c42bdbde781d079 Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <anarsoul@gmail.com>
Date: Tue, 24 Jul 2018 17:49:42 -0700
Subject: [PATCH 07/17] mipi dsi: don't hardcode tcoon_div
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 4892b76b0cd8..79b8f1d70cc8 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -379,8 +379,12 @@ static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
unsigned int bpp = mipi_dsi_pixel_format_to_bpp(device->format);
u32 line_num, edge0, edge1, sync_point = 40;
- /* FIXME: we need actual tcon_div here */
- u32 tcon_div = 6;
+ unsigned long dclk_rate, dclk_parent_rate;
+ u32 tcon_div;
+
+ dclk_rate = clk_get_rate(dsi->tcon->dclk);
+ dclk_parent_rate = clk_get_rate(clk_get_parent(dsi->tcon->dclk));
+ tcon_div = dclk_parent_rate / dclk_rate;
line_num = mode->htotal * bpp / (8 * device->lanes);
edge1 = sync_point + (mode->hdisplay + mode->htotal - mode->hsync_start + 20) * bpp / (8 * device->lanes);
--
2.19.1
From 94ff092406a837bb28d426161c98cea7e25ad0b3 Mon Sep 17 00:00:00 2001
From: Vasily Khoruzhick <anarsoul@gmail.com>
Date: Tue, 24 Jul 2018 23:40:31 -0700
Subject: [PATCH 08/17] working DSI
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +-
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 18 ++++++++++++++----
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 8869fa6a69a1..64ed55ee4dbe 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1218,7 +1218,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
SUN4I_TCON1_CTL_SRC_SEL_MASK,
tcon->id);
}
-#if 1
+#if 0
/* Test pattern - white */
regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
SUN4I_TCON0_CTL_SRC_SEL_MASK,
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 79b8f1d70cc8..3d277396b1ac 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -366,8 +366,14 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
+ u32 vfp = mode->vtotal - mode->vdisplay - (mode->vtotal - mode->vsync_start);
+ u32 start_delay = mode->vtotal - vfp + 1;
+ if (start_delay > mode->vtotal)
+ start_delay -= mode->vtotal;
+ if (!start_delay)
+ start_delay = 1;
//return mode->vtotal - (mode->vsync_end - mode->vdisplay) + 1;
- return mode->vtotal - mode->vdisplay - 10;
+ return start_delay;
}
static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
@@ -578,8 +584,8 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE0_REG,
SUN6I_DSI_BASIC_SIZE0_VSA(mode->vsync_end -
mode->vsync_start) |
- SUN6I_DSI_BASIC_SIZE0_VBP(mode->vsync_start -
- mode->vdisplay));
+ SUN6I_DSI_BASIC_SIZE0_VBP(mode->vtotal -
+ mode->vsync_end));
regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE1_REG,
SUN6I_DSI_BASIC_SIZE1_VACT(mode->vdisplay) |
@@ -987,9 +993,13 @@ static irqreturn_t sun6i_dsi_handler(int irq, void *private)
struct sun6i_dsi *dsi = private;
struct sun4i_tcon *tcon = dsi->tcon;
unsigned int status;
+ static int cnt;
regmap_read(dsi->regs, SUN6I_DSI_GINT_REG, &status);
+ cnt++;
+ if (!(cnt % 60))
+ pr_info("%s %.8x\n", __func__, status);
if (!(status & SUN6I_DSI_GINT_VIDEO_VBLK_INT))
return IRQ_NONE;
@@ -1263,7 +1273,7 @@ static const struct sun6i_dsi_quirks sun6i_a31_quirks = {
static const struct sun6i_dsi_quirks sun50i_a64_quirks = {
.mod_clk_freq = 148500000,
- .use_dsi_irq = true,
+ //.use_dsi_irq = true,
};
static const struct of_device_id sun6i_dsi_of_table[] = {
--
2.19.1
From d10a541628554f0ac3be3ba31bd1e74546b6061d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Ber=C3=A1nek?= <roman.beranek@prusa3d.com>
Date: Wed, 15 Aug 2018 09:59:19 +0200
Subject: [PATCH 09/17] drm: added panel driver for a FullHD 5" LCD SHARP
LS050T1SX01
---
.../display/panel/sharp,ls050t1sx01.txt | 22 +
drivers/gpu/drm/panel/Kconfig | 8 +
drivers/gpu/drm/panel/Makefile | 1 +
.../gpu/drm/panel/panel-sharp-ls050t1sx01.c | 375 ++++++++++++++++++
4 files changed, 406 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/panel/sharp,ls050t1sx01.txt
create mode 100644 drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
diff --git a/Documentation/devicetree/bindings/display/panel/sharp,ls050t1sx01.txt b/Documentation/devicetree/bindings/display/panel/sharp,ls050t1sx01.txt
new file mode 100644
index 000000000000..bb0ba34c3813
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/sharp,ls050t1sx01.txt
@@ -0,0 +1,22 @@
+Sharp Microelectronics 5.0" qHD TFT LCD panel
+
+Required properties:
+- compatible: should be "sharp,ls050t1sx01-qhd"
+- reg: DSI virtual channel of the peripheral
+- power-supply: phandle of the regulator that provides the supply voltage
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+- reset-gpios: a GPIO spec for the reset pin
+
+Example:
+
+ mdss_dsi@fd922800 {
+ panel@0 {
+ compatible = "sharp,ls050t1sx01";
+ reg = <0>;
+ avdd-supply = <&pm8941_l22>;
+ backlight = <&pm8941_wled>;
+ reset-gpios = <&pm8941_gpios 19 GPIO_ACTIVE_HIGH>;
+ };
+ };
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 147745ef70e1..248aa99c6e5c 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -187,6 +187,14 @@ config DRM_PANEL_SHARP_LS043T1LE01
Say Y here if you want to enable support for Sharp LS043T1LE01 qHD
(540x960) DSI panel as found on the Qualcomm APQ8074 Dragonboard
+config DRM_PANEL_SHARP_LS050T1SX01
+ tristate "Sharp LS050T1SX01 FullHD video mode panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for Sharp LS050T1SX01
+
config DRM_PANEL_SITRONIX_ST7789V
tristate "Sitronix ST7789V panel"
depends on OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 24e08cf68e70..1e13757c0905 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o
obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
+obj-$(CONFIG_DRM_PANEL_SHARP_LS050T1SX01) += panel-sharp-ls050t1sx01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c b/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
new file mode 100644
index 000000000000..17b481acb28c
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
@@ -0,0 +1,375 @@
+#include <linux/backlight.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+struct sharp_panel {
+ struct drm_panel base;
+ struct mipi_dsi_device *dsi;
+
+ struct backlight_device *backlight;
+ struct regulator *supply;
+ struct gpio_desc *reset_gpio;
+
+ bool prepared;
+ bool enabled;
+
+ const struct drm_display_mode *mode;
+};
+
+static inline struct sharp_panel *to_sharp_panel(struct drm_panel *panel)
+{
+ return container_of(panel, struct sharp_panel, base);
+}
+
+
+static int sharp_panel_off(struct sharp_panel *sharp)
+{
+ struct mipi_dsi_device *dsi = sharp->dsi;
+ int ret;
+
+ printk("sharp_panel_off()\n");
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret < 0)
+ return ret;
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int sharp_panel_on(struct sharp_panel *sharp)
+{
+ struct mipi_dsi_device *dsi = sharp->dsi;
+ int ret;
+
+ printk("sharp_panel_on()\n");
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int sharp_panel_init(struct sharp_panel *sharp)
+{
+ struct mipi_dsi_device *dsi = sharp->dsi;
+ int ret;
+
+ printk("sharp_panel_init()\n");
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0)
+ return ret;
+
+ msleep(120);
+
+ return 0;
+}
+
+static int sharp_panel_disable(struct drm_panel *panel)
+{
+ struct sharp_panel *sharp = to_sharp_panel(panel);
+
+ printk("sharp_panel_disable()\n");
+ if (!sharp->enabled)
+ return 0;
+
+ if (sharp->backlight) {
+ backlight_disable(sharp->backlight);
+ }
+
+ sharp->enabled = false;
+
+ return 0;
+}
+
+static int sharp_panel_unprepare(struct drm_panel *panel)
+{
+ struct sharp_panel *sharp = to_sharp_panel(panel);
+ int ret;
+
+ printk("sharp_panel_unprepare()\n");
+
+ if (!sharp->prepared)
+ return 0;
+
+ ret = sharp_panel_off(sharp);
+ if (ret < 0) {
+ dev_err(panel->dev, "failed to set panel off: %d\n", ret);
+ return ret;
+ }
+
+ msleep(120);
+
+ if (sharp->supply) {
+ regulator_disable(sharp->supply);
+ }
+ if (sharp->reset_gpio)
+ gpiod_set_value(sharp->reset_gpio, 0);
+
+ sharp->prepared = false;
+
+ return 0;
+}
+
+static int sharp_panel_prepare(struct drm_panel *panel)
+{
+ struct sharp_panel *sharp = to_sharp_panel(panel);
+ int ret;
+
+ printk("sharp_panel_prepare()\n");
+
+ if (sharp->prepared)
+ return 0;
+
+ if (sharp->supply) {
+ ret = regulator_enable(sharp->supply);
+ if (ret < 0)
+ return ret;
+ msleep(20);
+ }
+
+ printk("sharp->reset_gpio\n");
+ if (sharp->reset_gpio) {
+ gpiod_set_value(sharp->reset_gpio, 1);
+ msleep(1);
+ gpiod_set_value(sharp->reset_gpio, 0);
+ msleep(1);
+ gpiod_set_value(sharp->reset_gpio, 1);
+ msleep(10);
+ }
+
+ ret = sharp_panel_init(sharp);
+ if (ret < 0) {
+ dev_err(panel->dev, "failed to init panel: %d\n", ret);
+ goto poweroff;
+ }
+
+ ret = sharp_panel_on(sharp);
+ if (ret < 0) {
+ dev_err(panel->dev, "failed to set panel on: %d\n", ret);
+ goto poweroff;
+ }
+
+ sharp->prepared = true;
+
+ /* wait for 6 frames before continuing */
+ msleep(120);
+ return 0;
+
+poweroff:
+ if (sharp->supply) {
+ regulator_disable(sharp->supply);
+ }
+ if (sharp->reset_gpio)
+ gpiod_set_value(sharp->reset_gpio, 0);
+ return ret;
+}
+
+
+
+static int sharp_panel_enable(struct drm_panel *panel)
+{
+ struct sharp_panel *sharp = to_sharp_panel(panel);
+
+ printk("sharp_panel_enable()\n");
+
+ if (sharp->enabled)
+ return 0;
+
+ if (sharp->backlight) {
+ backlight_enable(sharp->backlight);
+ }
+
+ sharp->enabled = true;
+
+ return 0;
+}
+
+static const struct drm_display_mode default_mode = {
+ .clock = 144000,
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 50,
+ .hsync_end = 1080 + 50 + 8,
+ .htotal = 1080 + 50 + 8 + 62,
+ .vdisplay = 1920,
+ .vsync_start = 1920 + 73,
+ .vsync_end = 1920 + 73 + 2,
+ .vtotal = 1920 + 73 + 2 + 5,
+ .vrefresh = 60,
+};
+
+static int sharp_panel_get_modes(struct drm_panel *panel)
+{
+ struct drm_display_mode *mode;
+ struct drm_connector *connector = panel->connector;
+ struct sharp_panel *sharp = to_sharp_panel(panel);
+
+ printk("sharp_panel_get_modes()\n");
+ printk("drm_mode_duplcate()\n");
+ mode = drm_mode_duplicate(panel->drm, &default_mode);
+ if (!mode) {
+ dev_err(&sharp->dsi->dev, "failed to add mode %ux%ux@%u\n",
+ default_mode.hdisplay, default_mode.vdisplay,
+ default_mode.vrefresh);
+ return -ENOMEM;
+ }
+
+ printk("drm_mode_set_name()\n");
+ drm_mode_set_name(mode);
+
+ printk("mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED\n");
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_p robed_add(connector, mode);
+
+ panel->connector->display_info.width_mm = 54;
+ panel->connector->display_info.height_mm = 95;
+
+ printk("return 1\n");
+ return 1;
+}
+
+static const struct of_device_id sharp_of_match[] = {
+ { .compatible = "sharp,ls050t1sx01", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sharp_of_match);
+
+static const struct drm_panel_funcs sharp_panel_funcs = {
+ .disable = sharp_panel_disable,
+ .unprepare = sharp_panel_unprepare,
+ .prepare = sharp_panel_prepare,
+ .enable = sharp_panel_enable,
+ .get_modes = sharp_panel_get_modes,
+};
+
+static int sharp_panel_add(struct sharp_panel *sharp)
+{
+ struct device *dev = &sharp->dsi->dev;
+
+ printk("sharp_panel_add()\n");
+ sharp->mode = &default_mode;
+
+ sharp->supply = devm_regulator_get(dev, "avdd");
+ if (IS_ERR(sharp->supply)) {
+ dev_err(dev, "cannot get avdd supply %ld\n", PTR_ERR(sharp->supply));
+ sharp->supply = NULL;
+ }
+
+ sharp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(sharp->reset_gpio)) {
+ dev_err(dev, "cannot get reset-gpios %ld\n",
+ PTR_ERR(sharp->reset_gpio));
+ sharp->reset_gpio = NULL;
+ } else {
+ gpiod_set_value(sharp->reset_gpio, 0);
+ }
+
+ sharp->backlight = devm_of_find_backlight(dev);
+
+ if (IS_ERR(sharp->backlight)) {
+ dev_err(dev, "cannot get backlight %ld\n", PTR_ERR(sharp->backlight));
+ sharp->backlight = NULL;
+ }
+ drm_panel_init(&sharp->base);
+ sharp->base.funcs = &sharp_panel_funcs;
+ sharp->base.dev = &sharp->dsi->dev;
+
+ return drm_panel_add(&sharp->base);
+}
+
+static void sharp_panel_del(struct sharp_panel *sharp)
+{
+ printk("sharp_panel_del()\n");
+ if (sharp->base.dev)
+ drm_panel_remove(&sharp->base);
+}
+
+static int sharp_panel_probe(struct mipi_dsi_device *dsi)
+{
+ struct sharp_panel *sharp;
+ int ret;
+ printk("sharp_panel_probe()\n");
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_HSE |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS |
+ MIPI_DSI_MODE_EOT_PACKET;
+
+ sharp = devm_kzalloc(&dsi->dev, sizeof(*sharp), GFP_KERNEL);
+ if (!sharp)
+ return -ENOMEM;
+
+ mipi_dsi_set_drvdata(dsi, sharp);
+
+ sharp->dsi = dsi;
+
+ ret = sharp_panel_add(sharp);
+ if (ret < 0)
+ return ret;
+
+ return mipi_dsi_attach(dsi);
+}
+
+static int sharp_panel_remove(struct mipi_dsi_device *dsi)
+{
+ struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ printk("sharp_panel_remove()\n");
+ ret = sharp_panel_disable(&sharp->base);
+ if (ret < 0)
+ dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_detach(&sharp->base);
+ sharp_panel_del(sharp);
+
+ return 0;
+}
+
+static void sharp_panel_shutdown(struct mipi_dsi_device *dsi)
+{
+ struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
+ printk("sharp_panel_shutdown()\n");
+
+ sharp_panel_disable(&sharp->base);
+}
+
+static struct mipi_dsi_driver sharp_panel_driver = {
+ .driver = {
+ .name = "panel-sharp-ls050t1sx01",
+ .of_match_table = sharp_of_match,
+ },
+ .probe = sharp_panel_probe,
+ .remove = sharp_panel_remove,
+ .shutdown = sharp_panel_shutdown,
+};
+module_mipi_dsi_driver(sharp_panel_driver);
+
+MODULE_AUTHOR("Roman Beranek <roman.beranek@prusa3d.com>");
+MODULE_DESCRIPTION("Sharp LS050T1SX01 R63311-based FullHD video mode panel driver");
+MODULE_LICENSE("GPL v2");
--
2.19.1
From 77124564533c41578b6e8436653b7ec09adea032 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Ber=C3=A1nek?= <roman.beranek@prusa3d.com>
Date: Wed, 15 Aug 2018 14:03:43 +0200
Subject: [PATCH 10/17] ls050t1sx01 on olinuxino
---
.../dts/allwinner/sun50i-a64-olinuxino.dts | 28 +++++++++++
.../gpu/drm/panel/panel-sharp-ls050t1sx01.c | 46 +++++++++----------
2 files changed, 51 insertions(+), 23 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
index eec2a538b585..f471cd6962cf 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
@@ -289,3 +289,31 @@
pinctrl-0 = <&uart3_pins>;
status = "okay";
};
+
+&de {
+ status = "okay";
+};
+
+&mixer0 {
+ status = "okay";
+};
+
+&tcon0 {
+ status = "okay";
+};
+
+&dphy {
+ status = "okay";
+};
+
+&dsi {
+ status = "okay";
+
+ panel@0 {
+ compatible = "sharp,ls050t1sx01", "simple-panel";
+ reg = <0>;
+ enable-gpios = <&pio 1 7 GPIO_ACTIVE_HIGH>; /* PB7 */
+ reset-gpios = <&pio 1 5 GPIO_ACTIVE_LOW>; /* PB5 */
+ avdd-supply = <&reg_dldo2>;
+ };
+};
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c b/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
index 17b481acb28c..4fe93ec770ed 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
@@ -1,4 +1,3 @@
-#include <linux/backlight.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -15,9 +14,9 @@ struct sharp_panel {
struct drm_panel base;
struct mipi_dsi_device *dsi;
- struct backlight_device *backlight;
struct regulator *supply;
struct gpio_desc *reset_gpio;
+ struct gpio_desc *enable_gpio;
bool prepared;
bool enabled;
@@ -92,10 +91,6 @@ static int sharp_panel_disable(struct drm_panel *panel)
if (!sharp->enabled)
return 0;
- if (sharp->backlight) {
- backlight_disable(sharp->backlight);
- }
-
sharp->enabled = false;
return 0;
@@ -147,13 +142,18 @@ static int sharp_panel_prepare(struct drm_panel *panel)
msleep(20);
}
+ if (sharp->enable_gpio) {
+ gpiod_set_value(sharp->enable_gpio, 1);
+ msleep(100);
+ }
+
printk("sharp->reset_gpio\n");
if (sharp->reset_gpio) {
- gpiod_set_value(sharp->reset_gpio, 1);
- msleep(1);
gpiod_set_value(sharp->reset_gpio, 0);
- msleep(1);
+ msleep(20);
gpiod_set_value(sharp->reset_gpio, 1);
+ msleep(50);
+ gpiod_set_value(sharp->reset_gpio, 0);
msleep(10);
}
@@ -176,11 +176,12 @@ static int sharp_panel_prepare(struct drm_panel *panel)
return 0;
poweroff:
- if (sharp->supply) {
- regulator_disable(sharp->supply);
- }
+ if (sharp->enable_gpio)
+ gpiod_set_value(sharp->enable_gpio, 0);
+ if (sharp->supply)
+ regulator_disable(sharp->supply);
if (sharp->reset_gpio)
- gpiod_set_value(sharp->reset_gpio, 0);
+ gpiod_set_value(sharp->reset_gpio, 0);
return ret;
}
@@ -195,10 +196,6 @@ static int sharp_panel_enable(struct drm_panel *panel)
if (sharp->enabled)
return 0;
- if (sharp->backlight) {
- backlight_enable(sharp->backlight);
- }
-
sharp->enabled = true;
return 0;
@@ -238,7 +235,7 @@ static int sharp_panel_get_modes(struct drm_panel *panel)
printk("mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED\n");
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- drm_mode_p robed_add(connector, mode);
+ drm_mode_probed_add(connector, mode);
panel->connector->display_info.width_mm = 54;
panel->connector->display_info.height_mm = 95;
@@ -283,12 +280,15 @@ static int sharp_panel_add(struct sharp_panel *sharp)
gpiod_set_value(sharp->reset_gpio, 0);
}
- sharp->backlight = devm_of_find_backlight(dev);
-
- if (IS_ERR(sharp->backlight)) {
- dev_err(dev, "cannot get backlight %ld\n", PTR_ERR(sharp->backlight));
- sharp->backlight = NULL;
+ sharp->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(sharp->enable_gpio)) {
+ dev_err(dev, "cannot get enable-gpios %ld\n",
+ PTR_ERR(sharp->enable_gpio));
+ sharp->enable_gpio = NULL;
+ } else {
+ gpiod_set_value(sharp->enable_gpio, 0);
}
+
drm_panel_init(&sharp->base);
sharp->base.funcs = &sharp_panel_funcs;
sharp->base.dev = &sharp->dsi->dev;
--
2.19.1
From 5da271027538410fdaf83a35d77e1f57a13e8e4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Ber=C3=A1nek?= <roman.beranek@prusa3d.com>
Date: Wed, 15 Aug 2018 14:45:31 +0200
Subject: [PATCH 11/17] sun50i-a64-olinuxino.dts: add missing nodes & sort the
list
---
.../dts/allwinner/sun50i-a64-olinuxino.dts | 62 +++++++++----------
1 file changed, 30 insertions(+), 32 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
index f471cd6962cf..c90a682d4d49 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
@@ -52,6 +52,8 @@
aliases {
serial0 = &uart0;
+ serial2 = &uart2;
+ serial3 = &uart3;
};
chosen {
@@ -75,10 +77,6 @@
};
};
-&de {
- status = "okay";
-};
-
&codec {
status = "okay";
};
@@ -91,6 +89,26 @@
status = "okay";
};
+&de {
+ status = "okay";
+};
+
+&dphy {
+ status = "okay";
+};
+
+&dsi {
+ status = "okay";
+
+ panel@0 {
+ compatible = "sharp,ls050t1sx01", "simple-panel";
+ reg = <0>;
+ enable-gpios = <&pio 1 7 GPIO_ACTIVE_HIGH>; /* PB7 */
+ reset-gpios = <&pio 1 5 GPIO_ACTIVE_LOW>; /* PB5 */
+ avdd-supply = <&reg_dldo2>;
+ };
+};
+
&hdmi {
hdmi-supply = <&reg_dldo1>;
status = "okay";
@@ -102,6 +120,10 @@
};
};
+&mixer0 {
+ status = "okay";
+};
+
&mixer1 {
status = "okay";
};
@@ -268,6 +290,10 @@
"Speaker", "LINEOUT";
};
+&tcon0 {
+ status = "okay";
+};
+
&tcon1 {
status = "okay";
};
@@ -289,31 +315,3 @@
pinctrl-0 = <&uart3_pins>;
status = "okay";
};
-
-&de {
- status = "okay";
-};
-
-&mixer0 {
- status = "okay";
-};
-
-&tcon0 {
- status = "okay";
-};
-
-&dphy {
- status = "okay";
-};
-
-&dsi {
- status = "okay";
-
- panel@0 {
- compatible = "sharp,ls050t1sx01", "simple-panel";
- reg = <0>;
- enable-gpios = <&pio 1 7 GPIO_ACTIVE_HIGH>; /* PB7 */
- reset-gpios = <&pio 1 5 GPIO_ACTIVE_LOW>; /* PB5 */
- avdd-supply = <&reg_dldo2>;
- };
-};
--
2.19.1
From 87cf41089c177ba269578b00b0c5d4ecbeffffa5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Ber=C3=A1nek?= <roman.beranek@prusa3d.com>
Date: Wed, 15 Aug 2018 15:25:01 +0200
Subject: [PATCH 12/17] ls050t1sx01: return error from probe when suply/gpios
are unavailable
---
drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c b/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
index 4fe93ec770ed..da91541b8d12 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
@@ -268,14 +268,14 @@ static int sharp_panel_add(struct sharp_panel *sharp)
sharp->supply = devm_regulator_get(dev, "avdd");
if (IS_ERR(sharp->supply)) {
dev_err(dev, "cannot get avdd supply %ld\n", PTR_ERR(sharp->supply));
- sharp->supply = NULL;
+ return PTR_ERR(sharp->supply);
}
sharp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(sharp->reset_gpio)) {
dev_err(dev, "cannot get reset-gpios %ld\n",
PTR_ERR(sharp->reset_gpio));
- sharp->reset_gpio = NULL;
+ return PTR_ERR(sharp->reset_gpio);
} else {
gpiod_set_value(sharp->reset_gpio, 0);
}
@@ -284,7 +284,7 @@ static int sharp_panel_add(struct sharp_panel *sharp)
if (IS_ERR(sharp->enable_gpio)) {
dev_err(dev, "cannot get enable-gpios %ld\n",
PTR_ERR(sharp->enable_gpio));
- sharp->enable_gpio = NULL;
+ return PTR_ERR(sharp->enable_gpio);
} else {
gpiod_set_value(sharp->enable_gpio, 0);
}
--
2.19.1
From 8423e560cae1e32fdb1291f67081e7fd8b52dbe4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Ber=C3=A1nek?= <roman.beranek@prusa3d.com>
Date: Wed, 15 Aug 2018 16:32:28 +0200
Subject: [PATCH 13/17] dts: added mixer0 to sun50i-a64
---
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 40b77c4a20e7..6f3c5febd2af 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -114,7 +114,7 @@
de: display-engine {
compatible = "allwinner,sun50i-a64-display-engine";
- allwinner,pipelines = <&mixer1>;
+ allwinner,pipelines = <&mixer0>, <&mixer1>;
status = "disabled";
};
@@ -226,7 +226,8 @@
ranges = <0 0x1000000 0x400000>;
display_clocks: clock@0 {
- compatible = "allwinner,sun50i-a64-de2-clk";
+ compatible = "allwinner,sun50i-h5-de2-clk",
+ "allwinner,sun50i-a64-de2-clk";
reg = <0x0 0x100000>;
clocks = <&ccu CLK_DE>,
<&ccu CLK_BUS_DE>;
@@ -327,8 +328,9 @@
clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>;
clock-names = "ahb", "tcon-ch0";
clock-output-names = "tcon-pixel-clock";
- resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
- reset-names = "lcd", "lvds";
+ resets = <&ccu RST_BUS_TCON0>;
+ reset-names = "lcd";
+ status = "disabled";
ports {
#address-cells = <1>;
--
2.19.1
From 17e51fdd8a3ef425232e385103fda0d122b5f680 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Ber=C3=A1nek?= <roman.beranek@prusa3d.com>
Date: Wed, 15 Aug 2018 16:52:31 +0200
Subject: [PATCH 14/17] sunxi-ng: select SUN8I_DE2_CCU by default
---
drivers/clk/sunxi-ng/Kconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 826674d090fd..e20182aa9748 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -63,6 +63,8 @@ config SUN8I_V3S_CCU
config SUN8I_DE2_CCU
bool "Support for the Allwinner SoCs DE2 CCU"
+ default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
+ depends on DRM_SUN4I && (MACH_SUN8I || (ARM64 && ARCH_SUNXI))
config SUN8I_R40_CCU
bool "Support for the Allwinner R40 CCU"
--
2.19.1
From 364691f471c276f35f9df4051470dc9146c1491b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Ber=C3=A1nek?= <roman.beranek@prusa3d.com>
Date: Wed, 29 Aug 2018 14:13:43 +0200
Subject: [PATCH 15/17] drm/sun4i: integration of anarsoul's A64 MIPI DSI work
into 4.18
---
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 ++----
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 4 ++--
drivers/gpu/drm/sun4i/Kconfig | 3 ++-
drivers/gpu/drm/sun4i/sun4i_tcon.c | 11 ++++++++---
4 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 6f3c5febd2af..165e8ce73dd0 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -226,8 +226,7 @@
ranges = <0 0x1000000 0x400000>;
display_clocks: clock@0 {
- compatible = "allwinner,sun50i-h5-de2-clk",
- "allwinner,sun50i-a64-de2-clk";
+ compatible = "allwinner,sun50i-a64-de2-clk";
reg = <0x0 0x100000>;
clocks = <&ccu CLK_DE>,
<&ccu CLK_BUS_DE>;
@@ -321,8 +320,7 @@
};
tcon0: lcd-controller@1c0c000 {
- compatible = "allwinner,sun50i-a64-tcon-lcd",
- "allwinner,sun8i-a83t-tcon-lcd";
+ compatible = "allwinner,sun50i-a64-tcon-lcd";
reg = <0x01c0c000 0x1000>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>;
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index e710a098d324..e33716e0233a 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -517,8 +517,8 @@ static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
0x104, 0, 4, 24, 3, BIT(31), 0);
-static const char * const tcon0_parents[] = { "pll-mipi", "pll-video-2x" };
-static const u8 tcon0_table[] = { 0, };
+static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
+static const u8 tcon0_table[] = { 0, 2, };
static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
tcon0_table, 0x118, 24, 3, BIT(31),
CLK_SET_RATE_PARENT);
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index c2c042287c19..cbe64a51463b 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -52,6 +52,7 @@ config DRM_SUN6I_DSI
config DRM_SUN8I_DW_HDMI
tristate "Support for Allwinner version of DesignWare HDMI"
+ default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
depends on DRM_SUN4I
select DRM_DW_HDMI
help
@@ -61,7 +62,7 @@ config DRM_SUN8I_DW_HDMI
config DRM_SUN8I_MIXER
tristate "Support for Allwinner Display Engine 2.0 Mixer"
- default MACH_SUN8I
+ default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
help
Choose this option if you have an Allwinner SoC with the
Allwinner Display Engine 2.0, which has a mixer to do some
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 64ed55ee4dbe..070db858ed78 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -349,9 +349,8 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
* the display clock * 15, but uses an hardcoded 3000...
*/
regmap_write(tcon->regs, SUN4I_TCON_SAFE_PERIOD_REG,
- 0x03390023);
- //SUN4I_TCON_SAFE_PERIOD_NUM(3000) |
- //SUN4I_TCON_SAFE_PERIOD_MODE(3));
+ SUN4I_TCON_SAFE_PERIOD_NUM((mode->crtc_clock * 15) / 1000) |
+ SUN4I_TCON_SAFE_PERIOD_MODE(3));
/* Enable the output on the pins */
regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG,
@@ -1448,6 +1447,11 @@ static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
.needs_edp_reset = true,
};
+static const struct sun4i_tcon_quirks sun50i_a64_lcd_quirks = {
+ .supports_lvds = true,
+ .has_channel_0 = true,
+};
+
/* sun4i_drv uses this list to check if a device node is a TCON */
const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks },
@@ -1462,6 +1466,7 @@ const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks },
+ { .compatible = "allwinner,sun50i-a64-tcon-lcd", .data = &sun50i_a64_lcd_quirks },
{ }
};
MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
--
2.19.1
From ff02f5f0aea46a75768ab277c52c69a65b9cdad0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Ber=C3=A1nek?= <roman.beranek@prusa3d.com>
Date: Wed, 29 Aug 2018 14:14:52 +0200
Subject: [PATCH 16/17] drm/sun4i: MIPI-DSI fixes for non-burst video mode
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 88 ++++++++++----------------
1 file changed, 35 insertions(+), 53 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 3d277396b1ac..74cd4c3ae051 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -417,9 +417,9 @@ static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
val |= SUN6I_DSI_BASIC_CTL_VIDEO_BURST;
regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, val);
} else {
- if ((mode->hsync_end - mode->hdisplay) > 20) {
+ if ((mode->hsync_start - mode->hdisplay) > 20) {
/* Maaaaaagic */
- u16 drq = (mode->hsync_end - mode->hdisplay) - 20;
+ u16 drq = (mode->hsync_start - mode->hdisplay) - 20;
drq *= mipi_dsi_pixel_format_to_bpp(device->format);
drq /= 32;
@@ -520,37 +520,58 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
* minimal size is therefore 10 bytes
*/
#define HSA_PACKET_OVERHEAD 10
- hsa = max((unsigned int)HSA_PACKET_OVERHEAD,
- (mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD);
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ hsa = 0;
+ else
+ hsa = max((unsigned int)HSA_PACKET_OVERHEAD,
+ (mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD);
/*
* The backporch is set using a blanking packet (4 bytes +
* payload + 2 bytes). Its minimal size is therefore 6 bytes
*/
#define HBP_PACKET_OVERHEAD 6
- hbp = max((unsigned int)HBP_PACKET_OVERHEAD,
- (mode->hsync_start - mode->hdisplay) * Bpp - HBP_PACKET_OVERHEAD);
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ hbp = 0;
+ else
+ hbp = max((unsigned int)HBP_PACKET_OVERHEAD,
+ (mode->htotal - mode->hsync_end) * Bpp - HBP_PACKET_OVERHEAD);
+
/*
- * The frontporch is set using a blanking packet (4 bytes +
- * payload + 2 bytes). Its minimal size is therefore 6 bytes
+ * hblk seems to be the line + porches length.
*/
-#define HFP_PACKET_OVERHEAD 6
- hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
- (mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
+#define HBLK_PACKET_OVERHEAD 10
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ hblk = mode->hdisplay * Bpp;
+ else
+ hblk = mode->htotal * Bpp
+ - (hsa + HSA_PACKET_OVERHEAD)
+ - HBLK_PACKET_OVERHEAD;
/*
- * hblk seems to be the line + porches length.
+ * The frontporch is set using a blanking packet (4 bytes +
+ * payload + 2 bytes). Its minimal size is therefore 6 bytes
*/
- hblk = mode->htotal * Bpp - hsa;
+#define HFP_PACKET_OVERHEAD 6
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ hfp = 0;
+ else
+ hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
+ hblk - (4 + mode->hdisplay * Bpp + 2) - (4 + hbp + 2));
+ /* vblk */
/*
* And I'm not entirely sure what vblk is about. The driver in
* Allwinner BSP is using a rather convoluted calculation
* there only for 4 lanes. However, using 0 (the !4 lanes
* case) even with a 4 lanes screen seems to work...
*/
- vblk = 0;
+ if (device->lanes != 4 || device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
+ vblk = 0;
+ } else {
+ vblk = 4 - (mode->htotal * Bpp * mode->vtotal - (4 + hblk + 2)) % 4;
+ }
/* How many bytes do we need to send all payloads? */
bytes = max_t(size_t, max(max(hfp, hblk), max(hsa, hbp)), vblk);
@@ -591,65 +612,26 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
SUN6I_DSI_BASIC_SIZE1_VACT(mode->vdisplay) |
SUN6I_DSI_BASIC_SIZE1_VT(mode->vtotal));
- /*
- * A sync period is composed of a blanking packet (4 bytes +
- * payload + 2 bytes) and a sync event packet (4 bytes). Its
- * minimal size is therefore 10 bytes
- */
-#define HSA_PACKET_OVERHEAD 10
- if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
- hsa = 0;
- else
- hsa = max((unsigned int)HSA_PACKET_OVERHEAD,
- (mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD);
regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA0_REG,
sun6i_dsi_build_blk0_pkt(device->channel, hsa));
regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA1_REG,
sun6i_dsi_build_blk1_pkt(0, buffer, hsa));
- /*
- * The backporch is set using a blanking packet (4 bytes +
- * payload + 2 bytes). Its minimal size is therefore 6 bytes
- */
-#define HBP_PACKET_OVERHEAD 6
- if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
- hbp = 0;
- else
- hbp = max((unsigned int)HBP_PACKET_OVERHEAD,
- (mode->hsync_start - mode->hdisplay) * Bpp - HBP_PACKET_OVERHEAD);
regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP0_REG,
sun6i_dsi_build_blk0_pkt(device->channel, hbp));
regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP1_REG,
sun6i_dsi_build_blk1_pkt(0, buffer, hbp));
- /*
- * The frontporch is set using a blanking packet (4 bytes +
- * payload + 2 bytes). Its minimal size is therefore 6 bytes
- */
-#define HFP_PACKET_OVERHEAD 6
- if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
- hfp = 0;
- else
- hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
- (mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP0_REG,
sun6i_dsi_build_blk0_pkt(device->channel, hfp));
regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP1_REG,
sun6i_dsi_build_blk1_pkt(0, buffer, hfp));
- /*
- * hblk seems to be the line + porches length.
- */
- if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
- hblk = mode->hdisplay * Bpp;
- else
- hblk = mode->htotal * Bpp - hsa;
regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK0_REG,
sun6i_dsi_build_blk0_pkt(device->channel, hblk));
regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK1_REG,
sun6i_dsi_build_blk1_pkt(0, buffer, hblk));
- /* vblk */
regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK0_REG,
sun6i_dsi_build_blk0_pkt(device->channel, vblk));
regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK1_REG,
--
2.19.1
From a03b9811d3f800ab82622e15dd334b2c6bb22389 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Ber=C3=A1nek?= <roman.beranek@prusa3d.com>
Date: Wed, 29 Aug 2018 14:22:35 +0200
Subject: [PATCH 17/17] drm: LS050T1SX01 LCD panel fixes
---
.../display/panel/sharp,ls050t1sx01.txt | 14 ++--
.../dts/allwinner/sun50i-a64-olinuxino.dts | 2 +-
.../gpu/drm/panel/panel-sharp-ls050t1sx01.c | 70 ++++---------------
3 files changed, 20 insertions(+), 66 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/panel/sharp,ls050t1sx01.txt b/Documentation/devicetree/bindings/display/panel/sharp,ls050t1sx01.txt
index bb0ba34c3813..0bf6ddd5b90f 100644
--- a/Documentation/devicetree/bindings/display/panel/sharp,ls050t1sx01.txt
+++ b/Documentation/devicetree/bindings/display/panel/sharp,ls050t1sx01.txt
@@ -1,12 +1,10 @@
-Sharp Microelectronics 5.0" qHD TFT LCD panel
+Sharp Microelectronics 5.0" fullHD TFT LCD panel
Required properties:
-- compatible: should be "sharp,ls050t1sx01-qhd"
+- compatible: should be "sharp,ls050t1sx01"
- reg: DSI virtual channel of the peripheral
- power-supply: phandle of the regulator that provides the supply voltage
-
-Optional properties:
-- backlight: phandle of the backlight device attached to the panel
+- enable-gpios: a GPIO spec for the reset pin
- reset-gpios: a GPIO spec for the reset pin
Example:
@@ -15,8 +13,8 @@ Example:
panel@0 {
compatible = "sharp,ls050t1sx01";
reg = <0>;
- avdd-supply = <&pm8941_l22>;
- backlight = <&pm8941_wled>;
- reset-gpios = <&pm8941_gpios 19 GPIO_ACTIVE_HIGH>;
+ power-supply = <&pm8941_l22>;
+ enable-gpios = <&pm8941_gpios 18 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&pm8941_gpios 19 GPIO_ACTIVE_LOW>;
};
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
index c90a682d4d49..4ca85c94cae5 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
@@ -105,7 +105,7 @@
reg = <0>;
enable-gpios = <&pio 1 7 GPIO_ACTIVE_HIGH>; /* PB7 */
reset-gpios = <&pio 1 5 GPIO_ACTIVE_LOW>; /* PB5 */
- avdd-supply = <&reg_dldo2>;
+ power-supply = <&reg_dldo2>;
};
};
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c b/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
index da91541b8d12..328663ac8a5d 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls050t1sx01.c
@@ -30,55 +30,24 @@ static inline struct sharp_panel *to_sharp_panel(struct drm_panel *panel)
}
-static int sharp_panel_off(struct sharp_panel *sharp)
+static int sharp_panel_init(struct sharp_panel *sharp)
{
struct mipi_dsi_device *dsi = sharp->dsi;
int ret;
- printk("sharp_panel_off()\n");
-
- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
-
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0)
- return ret;
-
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ ret = mipi_dsi_dcs_soft_reset(dsi);
if (ret < 0)
return ret;
-
- return 0;
-}
-
-static int sharp_panel_on(struct sharp_panel *sharp)
-{
- struct mipi_dsi_device *dsi = sharp->dsi;
- int ret;
-
- printk("sharp_panel_on()\n");
- dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+ msleep(10);
ret = mipi_dsi_dcs_set_display_on(dsi);
if (ret < 0)
return ret;
- return 0;
-}
-
-static int sharp_panel_init(struct sharp_panel *sharp)
-{
- struct mipi_dsi_device *dsi = sharp->dsi;
- int ret;
-
- printk("sharp_panel_init()\n");
-
- dsi->mode_flags |= MIPI_DSI_MODE_LPM;
-
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret < 0)
return ret;
-
- msleep(120);
+ msleep(120); // min 6 frames
return 0;
}
@@ -106,13 +75,13 @@ static int sharp_panel_unprepare(struct drm_panel *panel)
if (!sharp->prepared)
return 0;
- ret = sharp_panel_off(sharp);
- if (ret < 0) {
- dev_err(panel->dev, "failed to set panel off: %d\n", ret);
- return ret;
- }
+ ret = mipi_dsi_dcs_set_display_off(sharp->dsi);
+ if (ret < 0) return ret;
+ msleep(20);
- msleep(120);
+ ret = mipi_dsi_dcs_enter_sleep_mode(sharp->dsi);
+ if (ret < 0) return ret;
+ msleep(80);
if (sharp->supply) {
regulator_disable(sharp->supply);
@@ -163,12 +132,6 @@ static int sharp_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
- ret = sharp_panel_on(sharp);
- if (ret < 0) {
- dev_err(panel->dev, "failed to set panel on: %d\n", ret);
- goto poweroff;
- }
-
sharp->prepared = true;
/* wait for 6 frames before continuing */
@@ -220,8 +183,6 @@ static int sharp_panel_get_modes(struct drm_panel *panel)
struct drm_connector *connector = panel->connector;
struct sharp_panel *sharp = to_sharp_panel(panel);
- printk("sharp_panel_get_modes()\n");
- printk("drm_mode_duplcate()\n");
mode = drm_mode_duplicate(panel->drm, &default_mode);
if (!mode) {
dev_err(&sharp->dsi->dev, "failed to add mode %ux%ux@%u\n",
@@ -230,10 +191,8 @@ static int sharp_panel_get_modes(struct drm_panel *panel)
return -ENOMEM;
}
- printk("drm_mode_set_name()\n");
drm_mode_set_name(mode);
- printk("mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED\n");
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
@@ -265,9 +224,9 @@ static int sharp_panel_add(struct sharp_panel *sharp)
printk("sharp_panel_add()\n");
sharp->mode = &default_mode;
- sharp->supply = devm_regulator_get(dev, "avdd");
+ sharp->supply = devm_regulator_get(dev, "power");
if (IS_ERR(sharp->supply)) {
- dev_err(dev, "cannot get avdd supply %ld\n", PTR_ERR(sharp->supply));
+ dev_err(dev, "cannot get power supply %ld\n", PTR_ERR(sharp->supply));
return PTR_ERR(sharp->supply);
}
@@ -311,10 +270,7 @@ static int sharp_panel_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
- dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
- MIPI_DSI_MODE_VIDEO_HSE |
- MIPI_DSI_CLOCK_NON_CONTINUOUS |
- MIPI_DSI_MODE_EOT_PACKET;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO;
sharp = devm_kzalloc(&dsi->dev, sizeof(*sharp), GFP_KERNEL);
if (!sharp)
--
2.19.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment