Created
October 18, 2018 16:24
-
-
Save zavorka/8c8ce200fdbb2e1783e105eecaa01d07 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 = <®_dc1sw>; | |
+ dvdd-supply = <®_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 = <®_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 = <®_dldo2>; | |
+ }; | |
+}; | |
+ | |
&hdmi { | |
hdmi-supply = <®_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 = <®_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 = <®_dldo2>; | |
+ power-supply = <®_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