sm8250-6.11: add oneplus kebab patches

This commit is contained in:
amazingfate 2024-10-17 17:12:34 +08:00 committed by Igor
parent 14314337da
commit 92bd238f83
6 changed files with 2300 additions and 0 deletions

View File

@ -0,0 +1,106 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Caleb Connolly <caleb@postmarketos.org>
Date: Sun, 30 Jun 2024 20:36:27 +0200
Subject: drm: mipi: add mipi_dsi_generic_write_multi_type()
Some panels like the Samsung AMB655X use long write commands for all
non-standard messages and do not work when trying to use the appropriate
command type.
Support these panels by introducing a new helper to send commands of a
specific type, overriding the normal rules.
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
---
drivers/gpu/drm/drm_mipi_dsi.c | 40 ++++++++++
include/drm/drm_mipi_dsi.h | 16 ++++
2 files changed, 56 insertions(+)
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -820,6 +820,46 @@ void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
}
EXPORT_SYMBOL(mipi_dsi_generic_write_multi);
+/**
+ * mipi_dsi_generic_write_raw_multi() - transmit data using a generic write packet of
+ * a specific type
+ * @ctx: Context for multiple DSI transactions
+ * @type: data type of the packet
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * This function will automatically choose the right data type depending on
+ * the payload length.
+ *
+ * Return: The number of bytes transmitted on success or a negative error code
+ * on failure.
+ */
+ssize_t mipi_dsi_generic_write_raw_multi(struct mipi_dsi_multi_context *ctx,
+ u8 type, const void *payload, size_t size)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct mipi_dsi_msg msg = {
+ .channel = dsi->channel,
+ .tx_buf = payload,
+ .tx_len = size,
+ .type = type,
+ };
+ ssize_t ret;
+
+ if (ctx->accum_err)
+ return 0;
+
+ ret = mipi_dsi_device_transfer(dsi, &msg);
+ if (ret < 0) {
+ ctx->accum_err = ret;
+ dev_err(&dsi->dev, "sending generic data %*ph failed: %zd\n",
+ (int)size, payload, ret);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write_raw_multi);
+
/**
* mipi_dsi_generic_read() - receive data using a generic read packet
* @dsi: DSI peripheral device
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 111111111111..222222222222 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -289,6 +289,8 @@ int mipi_dsi_generic_write_chatty(struct mipi_dsi_device *dsi,
const void *payload, size_t size);
void mipi_dsi_generic_write_multi(struct mipi_dsi_multi_context *ctx,
const void *payload, size_t size);
+ssize_t mipi_dsi_generic_write_raw_multi(struct mipi_dsi_multi_context *ctx, u8 type,
+ const void *payload, size_t size);
ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
size_t num_params, void *data, size_t size);
@@ -440,6 +442,20 @@ void mipi_dsi_dcs_set_tear_on_multi(struct mipi_dsi_multi_context *ctx,
mipi_dsi_dcs_write_buffer_multi(ctx, d, ARRAY_SIZE(d)); \
} while (0)
+/**
+ * mipi_dsi_dcs_write_long_multi - transmit a DCS long command with payload
+ * @ctx: Context for multiple DSI transactions
+ * @cmd: Commands
+ * @seq: buffer containing data to be transmitted
+ */
+#define mipi_dsi_dcs_write_long_multi(ctx, cmd, seq...) \
+ do { \
+ static const u8 d[] = { cmd, seq }; \
+ mipi_dsi_generic_write_raw_multi(ctx, \
+ MIPI_DSI_DCS_LONG_WRITE, \
+ d, ARRAY_SIZE(d)); \
+ } while (0)
+
/**
* struct mipi_dsi_driver - DSI driver
* @driver: device driver model driver
--
Armbian

View File

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Caleb Connolly <caleb@postmarketos.org>
Date: Sun, 30 Jun 2024 20:36:28 +0200
Subject: drm/mipi-dsi: add set column/page multi helpers
Introduce mipi_dsi_dcs_set_column_address_multi() and
mipi_dsi_dcs_set_page_address_multi() helpers.
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
---
include/drm/drm_mipi_dsi.h | 16 ++++++++++
1 file changed, 16 insertions(+)
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 111111111111..222222222222 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -442,6 +442,22 @@ void mipi_dsi_dcs_set_tear_on_multi(struct mipi_dsi_multi_context *ctx,
mipi_dsi_dcs_write_buffer_multi(ctx, d, ARRAY_SIZE(d)); \
} while (0)
+#define mipi_dsi_dcs_set_column_address_multi(ctx, start, end) \
+ do { \
+ static const u8 d[] = { MIPI_DCS_SET_COLUMN_ADDRESS, \
+ (start) >> 8, (start) & 0xff, \
+ (end) >> 8, (end) & 0xff }; \
+ mipi_dsi_dcs_write_buffer_multi(ctx, d, ARRAY_SIZE(d)); \
+ } while (0)
+
+#define mipi_dsi_dcs_set_page_address_multi(ctx, start, end) \
+ do { \
+ static const u8 d[] = { MIPI_DCS_SET_PAGE_ADDRESS, \
+ (start) >> 8, (start) & 0xff, \
+ (end) >> 8, (end) & 0xff }; \
+ mipi_dsi_dcs_write_buffer_multi(ctx, d, ARRAY_SIZE(d)); \
+ } while (0)
+
/**
* mipi_dsi_dcs_write_long_multi - transmit a DCS long command with payload
* @ctx: Context for multiple DSI transactions
--
Armbian

View File

@ -0,0 +1,479 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Caleb Connolly <caleb@postmarketos.org>
Date: Sun, 30 Jun 2024 20:36:29 +0200
Subject: drm/panel: add driver for samsung amb655x
This is a 1080x2400 120hz panel used on the OnePlus 8T. It uses DSC but
with many non-standard DCS commands.
The only user of this panel (the OnePlus 8T) has a bug somewhere in the
DSI stack whereby it isn't possible to properly initialize this panel
after a reset. As a result, the reset GPIO is made optional so it can be
left unused on that device.
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
---
MAINTAINERS | 7 +
drivers/gpu/drm/panel/Kconfig | 9 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-samsung-amb655x.c | 399 ++++++++++
4 files changed, 416 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 111111111111..222222222222 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7231,6 +7231,13 @@ S: Maintained
F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.yaml
F: drivers/gpu/drm/panel/panel-raydium-rm67191.c
+DRM DRIVER FOR SAMSUNG AMB655X PANEL
+M: Caleb Connolly <caleb@postmarketos.org>
+S: Maintained
+T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
+F: Documentation/devicetree/bindings/display/panel/samsung,amb655x.yaml
+F: drivers/gpu/drm/panel/panel-samsung-amb655x.c
+
DRM DRIVER FOR SAMSUNG DB7430 PANELS
M: Linus Walleij <linus.walleij@linaro.org>
S: Maintained
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -611,6 +611,15 @@ config DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01
select DRM_MIPI_DSI
select VIDEOMODE_HELPERS
+config DRM_PANEL_SAMSUNG_AMB655X
+ tristate "Samsung AMB655X DSI panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ DRM panel driver for the Samsung AMB655X panel.
+ This panel has a resolution of 1080x2400 @ 60hz or 120Hz.
+
config DRM_PANEL_SAMSUNG_ATNA33XC20
tristate "Samsung ATNA33XC20 eDP panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM692E5) += panel-raydium-rm692e5.o
obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM69380) += panel-raydium-rm69380.o
obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_AMB655X) += panel-samsung-amb655x.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20) += panel-samsung-atna33xc20.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
diff --git a/drivers/gpu/drm/panel/panel-samsung-amb655x.c b/drivers/gpu/drm/panel/panel-samsung-amb655x.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-amb655x.c
@@ -0,0 +1,399 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+// Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+// Copyright (c) 2024 Caleb Connolly <caleb@postmarketos.org>
+
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/display/drm_dsc.h>
+#include <drm/display/drm_dsc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct samsung_amb655x {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct drm_dsc_config dsc;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[3];
+};
+
+static inline
+struct samsung_amb655x *to_samsung_amb655x(struct drm_panel *panel)
+{
+ return container_of(panel, struct samsung_amb655x, panel);
+}
+
+static void samsung_amb655x_reset(struct samsung_amb655x *amb655x)
+{
+ gpiod_set_value_cansleep(amb655x->reset_gpio, 0);
+ usleep_range(10000, 11000);
+ gpiod_set_value_cansleep(amb655x->reset_gpio, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value_cansleep(amb655x->reset_gpio, 0);
+ usleep_range(10000, 11000);
+}
+
+static int samsung_amb655x_on(struct samsung_amb655x *amb655x)
+{
+ struct drm_dsc_picture_parameter_set pps;
+ struct mipi_dsi_device *dsi = amb655x->dsi;
+ struct mipi_dsi_multi_context ctx = { .dsi = dsi };
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ drm_dsc_pps_payload_pack(&pps, &amb655x->dsc);
+
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_buffer_multi(&ctx, &pps, sizeof(pps));
+ mipi_dsi_dcs_write_long_multi(&ctx, 0x9d, 0x01);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0xa5, 0xa5);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 11);
+
+ /* VLIN CURRENT LIMIT */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb0, 0x04);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xd5, 0x24, 0x9e, 0x9e, 0x00, 0x20);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0xa5, 0xa5);
+
+ /* OSC Select */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xfc, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb0, 0x16);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xd1, 0x22);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xd6, 0x11);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xfc, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0xa5, 0xa5);
+
+ /* TE ON */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_long_multi(&ctx, MIPI_DCS_SET_TEAR_ON, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0xa5, 0xa5);
+
+ /* TSP Setting */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xdf, 0x83, 0x00, 0x10);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xe6, 0x01);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0xa5, 0xa5);
+
+ mipi_dsi_dcs_set_column_address_multi(&ctx, 0x0000, 1080 - 1);
+ mipi_dsi_dcs_set_page_address_multi(&ctx, 0x0000, 2400 - 1);
+
+ /* FD Setting */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xd5, 0x8d);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb0, 0x0a);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xd5, 0x05);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0xa5, 0xa5);
+
+ /* FFC Function */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xfc, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xe4, 0xa6, 0x75, 0xa3);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xe9,
+ 0x11, 0x75, 0xa6, 0x75,
+ 0xa3, 0x4b, 0x17, 0xac,
+ 0x4b, 0x17, 0xac, 0x00,
+ 0x19, 0x19);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xfc, 0xa5, 0xa5);
+ mipi_dsi_msleep(&ctx, 61);
+
+ /* Dimming Setting */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb0, 0x06);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb7, 0x01);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb0, 0x05);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb7, 0x13);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb0, 0x01);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xb7, 0x4c);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0xa5, 0xa5);
+
+ mipi_dsi_dcs_write_long_multi(&ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
+
+ /* refresh rate Transition */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ /* 60 Hz */
+ //mipi_dsi_dcs_write_long_multi(&ctx, 0x60, 0x00);
+ /* 120 Hz */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0x60, 0x10);
+
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0xa5, 0xa5);
+
+ /* ACL Mode */
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_long_multi(&ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0xf0, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq_multi(&ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
+ mipi_dsi_msleep(&ctx, 110);
+
+ mipi_dsi_dcs_write_long_multi(&ctx, 0x9F, 0x5A, 0x5A);
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
+ mipi_dsi_dcs_write_seq_multi(&ctx, MIPI_DCS_ENTER_NORMAL_MODE);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0x9F, 0xA5, 0xA5);
+
+ return ctx.accum_err;
+}
+
+static int samsung_amb655x_off(struct samsung_amb655x *amb655x)
+{
+ struct mipi_dsi_device *dsi = amb655x->dsi;
+ struct mipi_dsi_multi_context ctx = { .dsi = dsi };
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_write_long_multi(&ctx, 0x9f, 0x5a, 0x5a);
+
+ mipi_dsi_dcs_set_display_on_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 20);
+
+ mipi_dsi_dcs_set_display_off_multi(&ctx);
+ mipi_dsi_msleep(&ctx, 20);
+
+ mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
+ mipi_dsi_dcs_write_long_multi(&ctx, 0x9f, 0xa5, 0xa5);
+
+ mipi_dsi_msleep(&ctx, 150);
+
+ return ctx.accum_err;
+}
+
+static int samsung_amb655x_prepare(struct drm_panel *panel)
+{
+ struct samsung_amb655x *ctx = to_samsung_amb655x(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ /*
+ * During the first call to prepare, the regulators are already enabled
+ * since they're boot-on. Avoid enabling them twice so we keep the refcounts
+ * balanced.
+ */
+ if (!regulator_is_enabled(ctx->supplies[0].consumer)) {
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret) {
+ dev_err(dev, "Failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+ }
+
+ samsung_amb655x_reset(ctx);
+
+ ret = samsung_amb655x_on(ctx);
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ return ret;
+ }
+
+ msleep(28);
+
+ return 0;
+}
+
+static int samsung_amb655x_unprepare(struct drm_panel *panel)
+{
+ struct samsung_amb655x *amb655x = to_samsung_amb655x(panel);
+ struct device *dev = &amb655x->dsi->dev;
+ int ret;
+
+ ret = samsung_amb655x_off(amb655x);
+ if (ret < 0)
+ dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+ gpiod_set_value_cansleep(amb655x->reset_gpio, 1);
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(amb655x->supplies), amb655x->supplies);
+ if (ret) {
+ dev_err(dev, "Failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct drm_display_mode samsung_amb655x_120_mode = {
+ .clock = (1080 + 52 + 24 + 24) * (2400 + 4 + 4 + 8) * 120 / 1000,
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 52,
+ .hsync_end = 1080 + 52 + 24,
+ .htotal = 1080 + 52 + 24 + 24,
+ .vdisplay = 2400,
+ .vsync_start = 2400 + 4,
+ .vsync_end = 2400 + 4 + 4,
+ .vtotal = 2400 + 4 + 4 + 8,
+ .width_mm = 70,
+ .height_mm = 151,
+};
+
+static int samsung_amb655x_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, &samsung_amb655x_120_mode);
+ if (!mode)
+ return -ENOMEM;
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs samsung_amb655x_panel_funcs = {
+ .prepare = samsung_amb655x_prepare,
+ .unprepare = samsung_amb655x_unprepare,
+ .get_modes = samsung_amb655x_get_modes,
+};
+
+static int samsung_amb655x_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ u16 brightness = backlight_get_brightness(bl);
+ int ret;
+
+ ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct backlight_ops samsung_amb655x_bl_ops = {
+ .update_status = samsung_amb655x_bl_update_status,
+};
+
+static struct backlight_device *
+samsung_amb655x_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = 2047,
+ .max_brightness = 2047,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &samsung_amb655x_bl_ops, &props);
+}
+
+static int samsung_amb655x_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct samsung_amb655x *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->supplies[0].supply = "vddio";
+ ctx->supplies[1].supply = "vdd";
+ ctx->supplies[2].supply = "avdd";
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get vddio regulator\n");
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret)
+ dev_err(dev, "Failed to enable regulators: %d\n", ret);
+
+ ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ ctx->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+
+ drm_panel_init(&ctx->panel, dev, &samsung_amb655x_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
+
+ ctx->panel.backlight = samsung_amb655x_create_backlight(dsi);
+ if (IS_ERR(ctx->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+ "Failed to create backlight\n");
+
+ drm_panel_add(&ctx->panel);
+
+ /* This panel only supports DSC; unconditionally enable it */
+ dsi->dsc = &ctx->dsc;
+
+ ctx->dsc.dsc_version_major = 1;
+ ctx->dsc.dsc_version_minor = 1;
+
+ /* TODO: Pass slice_per_pkt = 2 */
+ ctx->dsc.slice_height = 30;
+ ctx->dsc.slice_width = 540;
+ /*
+ * TODO: hdisplay should be read from the selected mode once
+ * it is passed back to drm_panel (in prepare?)
+ */
+ WARN_ON(1080 % ctx->dsc.slice_width);
+ ctx->dsc.slice_count = 1080 / ctx->dsc.slice_width;
+ ctx->dsc.bits_per_component = 8;
+ ctx->dsc.bits_per_pixel = 8 << 4; /* 4 fractional bits */
+ ctx->dsc.block_pred_enable = true;
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+ drm_panel_remove(&ctx->panel);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void samsung_amb655x_remove(struct mipi_dsi_device *dsi)
+{
+ struct samsung_amb655x *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id samsung_amb655x_of_match[] = {
+ { .compatible = "samsung,amb655x" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, samsung_amb655x_of_match);
+
+static struct mipi_dsi_driver samsung_amb655x_driver = {
+ .probe = samsung_amb655x_probe,
+ .remove = samsung_amb655x_remove,
+ .driver = {
+ .name = "panel-samsung-amb655x",
+ .of_match_table = samsung_amb655x_of_match,
+ },
+};
+module_mipi_dsi_driver(samsung_amb655x_driver);
+
+MODULE_AUTHOR("Caleb Connolly <caleb@postmarketos.org>");
+MODULE_DESCRIPTION("DRM driver for Samsung AMB655X DSC DSI panel");
+MODULE_LICENSE("GPL");
--
Armbian

View File

@ -0,0 +1,660 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Caleb Connolly <caleb@postmarketos.org>
Date: Sun, 30 Jun 2024 20:36:30 +0200
Subject: Input: touchscreen: add Synaptics TCM oncell S3908
The TCM oncell is the next generation of Synaptics touchscreen ICs.
These run a very featured firmware with a reasonably well defined API.
It is however entirely incompatible with the existing RMI4 interface.
Unfortunately, no public datasheet for the interface seems to be
available, instead this driver was created through a combination of
vendor drivers and trial and error.
The firmware interface implies support for defining the exact bit
encoding of the touch reports, however on the S3908 chip + firmware
found in the OnePlus 8t the TCM_SET_TOUCH_REPORT_CONFIG command appears
to be unsupported.
Co-developed-by: Frieder Hannenheim <frieder.hannenheim@proton.me>
Signed-off-by: Frieder Hannenheim <frieder.hannenheim@proton.me>
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
---
MAINTAINERS | 7 +
drivers/input/touchscreen/Kconfig | 11 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/synaptics_tcm_oncell.c | 571 ++++++++++
4 files changed, 590 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 111111111111..222222222222 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22082,6 +22082,13 @@ S: Maintained
F: Documentation/devicetree/bindings/regulator/silergy,sy8106a.yaml
F: drivers/regulator/sy8106a-regulator.c
+SYNAPTICS TCM ONCELL TOUCHSCREEN DRIVER
+M: Caleb Connolly <caleb@postmarketos.org>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/input/touchscreen/syna,tcm-oncell.yaml
+F: drivers/input/touchscreen/synaptics_tcm_oncell.c
+
SYNC FILE FRAMEWORK
M: Sumit Semwal <sumit.semwal@linaro.org>
R: Gustavo Padovan <gustavo@padovan.org>
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -534,6 +534,17 @@ config TOUCHSCREEN_S6SY761
To compile this driver as module, choose M here: the
module will be called s6sy761.
+config TOUCHSCREEN_SYNAPTICS_TCM_ONCELL
+ tristate "Synaptics TCM Oncell Touchscreen driver"
+ depends on I2C
+ help
+ Say Y if you have the Synaptics S3908 TCM Oncell
+
+ If unsure, say N
+
+ To compile this driver as module, choose M here: the
+ module will be called synaptics_tcm_oncell.
+
config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen"
select SERIO
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 111111111111..222222222222 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -89,6 +89,7 @@ obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
obj-$(CONFIG_TOUCHSCREEN_SURFACE3_SPI) += surface3_spi.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_ONCELL) += synaptics_tcm_oncell.o
obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
diff --git a/drivers/input/touchscreen/synaptics_tcm_oncell.c b/drivers/input/touchscreen/synaptics_tcm_oncell.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics_tcm_oncell.c
@@ -0,0 +1,571 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for Synaptics TCM Oncell Touchscreens
+ *
+ * Copyright (c) 2024 Frieder Hannenheim <frieder.hannenheim@proton.me>
+ * Copyright (c) 2024 Caleb Connolly <caleb@postmarketos.org>
+ */
+
+#include <asm-generic/unaligned.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/touchscreen.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/of_gpio.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+
+/*
+ * The TCM oncell interface uses a command byte, which may be followed by additional
+ * data. The packet format is defined in the tcm_cmd struct.
+ *
+ * The following list only defines commands that are used in this driver (and their
+ * counterparts for context). Vendor reference implementations can be found at
+ * https://github.com/LineageOS/android_kernel_oneplus_sm8250/tree/ee0a7ee1939ffd53000e42051caf8f0800defb27/drivers/input/touchscreen/synaptics_tcm
+ */
+
+/*
+ * Request information about the chip. We don't send this command explicitly as
+ * the controller automatically sends this information when starting up.
+ */
+#define TCM_IDENTIFY 0x02
+
+/* Enable/disable reporting touch inputs */
+#define TCM_ENABLE_REPORT 0x05
+#define TCM_DISABLE_REPORT 0x06
+
+/*
+ * After powering on, we send this to exit the bootloader mode and run the main
+ * firmware.
+ */
+#define TCM_RUN_APPLICATION_FIRMWARE 0x14
+
+/*
+ * Reports information about the vendor provided application firmware. This is
+ * also used to determine when the firmware has finished booting.
+ */
+#define TCM_GET_APPLICATION_INFO 0x20
+
+#define MODE_APPLICATION 0x01
+
+#define APP_STATUS_OK 0x00
+#define APP_STATUS_BOOTING 0x01
+#define APP_STATUS_UPDATING 0x02
+
+/* status codes */
+#define REPORT_IDLE 0x00
+#define REPORT_OK 0x01
+#define REPORT_BUSY 0x02
+#define REPORT_CONTINUED_READ 0x03
+#define REPORT_RECEIVE_BUFFER_OVERFLOW 0x0c
+#define REPORT_PREVIOUS_COMMAND_PENDING 0x0d
+#define REPORT_NOT_IMPLEMENTED 0x0e
+#define REPORT_ERROR 0x0f
+
+/* report types */
+#define REPORT_IDENTIFY 0x10
+#define REPORT_TOUCH 0x11
+#define REPORT_DELTA 0x12
+#define REPORT_RAW 0x13
+#define REPORT_DEBUG 0x14
+#define REPORT_LOG 0x1d
+#define REPORT_TOUCH_HOLD 0x20
+#define REPORT_INVALID 0xff
+
+struct tcm_message_header {
+ u8 marker;
+ u8 code;
+ __le16 length;
+} __packed;
+
+struct tcm_cmd {
+ u8 cmd;
+ __le16 length;
+ u8 data[];
+};
+
+struct tcm_identification {
+ struct tcm_message_header header;
+ u8 version;
+ u8 mode;
+ char part_number[16];
+ u8 build_id[4];
+ u8 max_write_size[2];
+} __packed;
+
+struct tcm_app_info {
+ struct tcm_message_header header;
+ u8 version[2];
+ __le16 status;
+ u8 static_config_size[2];
+ u8 dynamic_config_size[2];
+ u8 app_config_start_write_block[2];
+ u8 app_config_size[2];
+ u8 max_touch_report_config_size[2];
+ u8 max_touch_report_payload_size[2];
+ char customer_config_id[16];
+ __le16 max_x;
+ __le16 max_y;
+ u8 max_objects[2];
+ u8 num_of_buttons[2];
+ u8 num_of_image_rows[2];
+ u8 num_of_image_cols[2];
+ u8 has_hybrid_data[2];
+} __packed;
+
+struct tcm_data {
+ struct i2c_client *client;
+ struct regmap *regmap;
+ struct input_dev *input;
+ struct gpio_desc *reset_gpio;
+ struct completion response;
+ struct touchscreen_properties props;
+ struct regulator_bulk_data supplies[2];
+
+ /* annoying state */
+ u16 buf_size;
+ char buf[256];
+};
+
+static int tcm_send_cmd(struct tcm_data *tcm, struct tcm_cmd *cmd)
+{
+ struct i2c_client *client = tcm->client;
+ struct i2c_msg msg;
+ int ret;
+
+ dev_dbg(&client->dev, "sending command %#x\n", cmd->cmd);
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = 1 + cmd->length;
+ msg.buf = (u8 *)cmd;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret == 1)
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+static int tcm_send_cmd_noargs(struct tcm_data *tcm, u8 cmd)
+{
+ struct tcm_cmd c = {
+ .cmd = cmd,
+ .length = 0,
+ };
+
+ return tcm_send_cmd(tcm, &c);
+}
+
+static int tcm_recv_report(struct tcm_data *tcm,
+ void *buf, size_t length)
+{
+ struct i2c_client *client = tcm->client;
+ struct i2c_msg msg;
+ int ret;
+
+ msg.addr = client->addr;
+ msg.flags = I2C_M_RD;
+ msg.len = length;
+ msg.buf = buf;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret == 1)
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+static int tcm_read_message(struct tcm_data *tcm, u8 cmd, void *buf, size_t length)
+{
+ int ret;
+
+ reinit_completion(&tcm->response);
+ ret = tcm_send_cmd_noargs(tcm, cmd);
+ if (ret)
+ return ret;
+
+ ret = wait_for_completion_timeout(&tcm->response, msecs_to_jiffies(1000));
+ if (ret == 0)
+ return -ETIMEDOUT;
+
+ if (buf) {
+ if (length > tcm->buf_size) {
+ dev_warn(&tcm->client->dev, "expected %zu bytes, got %u\n",
+ length, tcm->buf_size);
+ }
+ length = min(tcm->buf_size, length);
+ memcpy(buf, tcm->buf, length);
+ }
+
+ return 0;
+}
+
+static void tcm_power_off(void *data)
+{
+ struct tcm_data *tcm = data;
+
+ disable_irq(tcm->client->irq);
+ regulator_bulk_disable(ARRAY_SIZE(tcm->supplies), tcm->supplies);
+}
+
+static int tcm_input_open(struct input_dev *dev)
+{
+ struct tcm_data *tcm = input_get_drvdata(dev);
+
+ return i2c_smbus_write_byte(tcm->client, TCM_ENABLE_REPORT);
+}
+
+static void tcm_input_close(struct input_dev *dev)
+{
+ struct tcm_data *tcm = input_get_drvdata(dev);
+ int ret;
+
+ ret = i2c_smbus_write_byte(tcm->client, TCM_DISABLE_REPORT);
+ if (ret)
+ dev_err(&tcm->client->dev, "failed to turn off sensing\n");
+}
+
+/*
+ * The default report config looks like this:
+ *
+ * a5 01 80 00 11 08 1e 08 0f 01 04 01 06 04 07 04
+ * 08 0c 09 0c 0a 08 0b 08 0c 08 0d 10 0e 10 03 00
+ * 00 00
+ *
+ * a5 01 80 00 - HEADER + length
+ *
+ * 11 08 - TOUCH_FRAME_RATE (8 bits)
+ * 30 08 - UNKNOWN (8 bits)
+ * 0f 01 - TOUCH_0D_BUTTONS_STATE (1 bit)
+ * 04 01 - TOUCH_PAD_TO_NEXT_BYTE (7 bits - padding)
+ * 06 04 - TOUCH_OBJECT_N_INDEX (4 bits)
+ * 07 04 - TOUCH_OBJECT_N_CLASSIFICATION (4 bits)
+ * 08 0c - TOUCH_OBJECT_N_X_POSITION (12 bits)
+ * 09 0c - TOUCH_OBJECT_N_Y_POSITION (12 bits)
+ * 0a 08 - TOUCH_OBJECT_N_Z (8 bits)
+ * 0b 08 - TOUCH_OBJECT_N_X_WIDTH (8 bits)
+ * 0c 08 - TOUCH_OBJECT_N_Y_WIDTH (8 bits)
+ * 0d 10 - TOUCH_OBJECT_N_TX_POSITION_TIXELS (16 bits) ??
+ * 0e 10 - TOUCH_OBJECT_N_RX_POSITION_TIXELS (16 bits) ??
+ * 03 00 - TOUCH_FOREACH_END (0 bits)
+ * 00 00 - TOUCH_END (0 bits)
+ *
+ * Since we only support this report config, we just hardcode the format below.
+ * To support additional report configs, we would need to parse the config and
+ * use it to parse the reports dynamically.
+ */
+
+struct tcm_report_point {
+ u8 unknown;
+ u8 buttons;
+ __le32 point; /* idx : 4, class : 4, x : 12, y : 12 */
+ // u8 idx : 4;
+ // u8 classification : 4;
+ // u16 x : 12;
+ // u16 y : 12;
+ u8 z;
+ u8 width_x;
+ u8 width_y;
+ u8 tx;
+ u8 rx;
+} __packed;
+
+static int tcm_handle_touch_report(struct tcm_data *tcm, const char *buf, size_t len)
+{
+ const struct tcm_report_point *point;
+ /* If the input device hasn't registered yet then we can't do anything */
+ if (!tcm->input)
+ return 0;
+
+ buf += sizeof(struct tcm_message_header);
+ len -= sizeof(struct tcm_message_header);
+
+ dev_dbg(&tcm->client->dev, "touch report len %zu\n", len);
+ if ((len - 3) % sizeof(*point))
+ dev_err(&tcm->client->dev, "invalid touch report length\n");
+
+ buf++; /* Skip the FPS report */
+
+ /* We don't need to report releases because we have INPUT_MT_DROP_UNUSED */
+ for (int i = 0; i < (len - 1) / sizeof(*point); i++) {
+ u8 major_width, minor_width;
+ u16 idx, x, y;
+ u32 _point;
+
+ point = (struct tcm_report_point *)buf;
+ _point = le32_to_cpu(point->point);
+
+ minor_width = point->width_x;
+ major_width = point->width_y;
+
+ if (minor_width > major_width)
+ swap(major_width, minor_width);
+
+ idx = _point & 0xf;
+ x = (_point >> 8) & 0xfff;
+ y = (_point >> 20) & 0xfff;
+
+ dev_dbg(&tcm->client->dev, "touch report: idx %u x %u y %u\n",
+ idx, x, y);
+
+ input_mt_slot(tcm->input, idx);
+ input_mt_report_slot_state(tcm->input, MT_TOOL_FINGER, true);
+
+ touchscreen_report_pos(tcm->input, &tcm->props, x, y, true);
+
+ input_report_abs(tcm->input, ABS_MT_TOUCH_MAJOR, major_width);
+ input_report_abs(tcm->input, ABS_MT_TOUCH_MINOR, minor_width);
+ input_report_abs(tcm->input, ABS_MT_PRESSURE, point->z);
+
+ buf += sizeof(*point);
+ }
+
+ input_mt_sync_frame(tcm->input);
+ input_sync(tcm->input);
+
+ return 0;
+}
+
+static irqreturn_t tcm_report_irq(int irq, void *data)
+{
+ struct tcm_data *tcm = data;
+ struct tcm_message_header *header;
+ char buf[256];
+ u16 len;
+ int ret;
+
+ header = (struct tcm_message_header *)buf;
+ ret = tcm_recv_report(tcm, buf, sizeof(buf));
+ if (ret) {
+ dev_err(&tcm->client->dev, "failed to read report: %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ switch (header->code) {
+ case REPORT_OK:
+ case REPORT_IDENTIFY:
+ case REPORT_TOUCH:
+ case REPORT_DELTA:
+ case REPORT_RAW:
+ case REPORT_DEBUG:
+ case REPORT_TOUCH_HOLD:
+ break;
+ default:
+ dev_dbg(&tcm->client->dev, "Ignoring report %#x\n", header->code);
+ return IRQ_HANDLED;
+ }
+
+ len = le32_to_cpu(header->length);
+
+ dev_dbg(&tcm->client->dev, "report %#x len %u\n", header->code, len);
+ print_hex_dump_bytes("report: ", DUMP_PREFIX_OFFSET, buf,
+ min(sizeof(buf), len + sizeof(*header)));
+
+ if (len > sizeof(buf) - sizeof(*header)) {
+ dev_err(&tcm->client->dev, "report too long\n");
+ return IRQ_HANDLED;
+ }
+
+ /* Check if this is a read response or an indication. For indications
+ * (user touched the screen) we just parse the report directly.
+ */
+ if (completion_done(&tcm->response) && header->code == REPORT_TOUCH) {
+ tcm_handle_touch_report(tcm, buf, len + sizeof(*header));
+ return IRQ_HANDLED;
+ }
+
+ tcm->buf_size = len + sizeof(*header);
+ memcpy(tcm->buf, buf, len + sizeof(*header));
+ complete(&tcm->response);
+
+ return IRQ_HANDLED;
+}
+
+static int tcm_hw_init(struct tcm_data *tcm, u16 *max_x, u16 *max_y)
+{
+ int ret;
+ struct tcm_identification id = { 0 };
+ struct tcm_app_info app_info = { 0 };
+ u16 status;
+
+ /*
+ * Tell the firmware to start up. After starting it sends an IDENTIFY report, which
+ * we treat like a response to this message even though it's technically a new report.
+ */
+ ret = tcm_read_message(tcm, TCM_RUN_APPLICATION_FIRMWARE, &id, sizeof(id));
+ if (ret) {
+ dev_err(&tcm->client->dev, "failed to identify device: %d\n", ret);
+ return ret;
+ }
+
+ dev_dbg(&tcm->client->dev, "Synaptics TCM %s v%d mode %d\n",
+ id.part_number, id.version, id.mode);
+ if (id.mode != MODE_APPLICATION) {
+ /* We don't support firmware updates or anything else */
+ dev_err(&tcm->client->dev, "Device is not in application mode\n");
+ return -ENODEV;
+ }
+
+ do {
+ msleep(20);
+ ret = tcm_read_message(tcm, TCM_GET_APPLICATION_INFO, &app_info, sizeof(app_info));
+ if (ret) {
+ dev_err(&tcm->client->dev, "failed to get application info: %d\n", ret);
+ return ret;
+ }
+ status = le16_to_cpu(app_info.status);
+ } while (status == APP_STATUS_BOOTING || status == APP_STATUS_UPDATING);
+
+ dev_dbg(&tcm->client->dev, "Application firmware v%d.%d (customer '%s') status %d\n",
+ app_info.version[0], app_info.version[1], app_info.customer_config_id,
+ status);
+
+ *max_x = le16_to_cpu(app_info.max_x);
+ *max_y = le16_to_cpu(app_info.max_y);
+
+ return 0;
+}
+
+static int tcm_power_on(struct tcm_data *tcm)
+{
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(tcm->supplies),
+ tcm->supplies);
+ if (ret)
+ return ret;
+
+ gpiod_set_value_cansleep(tcm->reset_gpio, 1);
+ usleep_range(10000, 11000);
+ gpiod_set_value_cansleep(tcm->reset_gpio, 0);
+ usleep_range(80000, 81000);
+
+ return 0;
+}
+
+static int tcm_probe(struct i2c_client *client)
+{
+ struct tcm_data *tcm;
+ u16 max_x, max_y;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -ENODEV;
+
+ tcm = devm_kzalloc(&client->dev, sizeof(struct tcm_data), GFP_KERNEL);
+ if (!tcm)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, tcm);
+ tcm->client = client;
+
+ init_completion(&tcm->response);
+
+ tcm->supplies[0].supply = "vdd";
+ tcm->supplies[1].supply = "vcc";
+ ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(tcm->supplies),
+ tcm->supplies);
+ if (ret)
+ return ret;
+
+ tcm->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW);
+
+ ret = devm_add_action_or_reset(&client->dev, tcm_power_off,
+ tcm);
+ if (ret)
+ return ret;
+
+ ret = tcm_power_on(tcm);
+ if (ret)
+ return ret;
+
+ ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ tcm_report_irq,
+ IRQF_ONESHOT,
+ "synaptics_tcm_report", tcm);
+ if (ret < 0)
+ return ret;
+
+ ret = tcm_hw_init(tcm, &max_x, &max_y);
+ if (ret) {
+ dev_err(&client->dev, "failed to initialize hardware\n");
+ return ret;
+ }
+
+ tcm->input = devm_input_allocate_device(&client->dev);
+ if (!tcm->input)
+ return -ENOMEM;
+
+ tcm->input->name = "Synaptics TCM Oncell Touchscreen";
+ tcm->input->id.bustype = BUS_I2C;
+ tcm->input->open = tcm_input_open;
+ tcm->input->close = tcm_input_close;
+
+ input_set_abs_params(tcm->input, ABS_MT_POSITION_X, 0, max_x, 0, 0);
+ input_set_abs_params(tcm->input, ABS_MT_POSITION_Y, 0, max_y, 0, 0);
+ input_set_abs_params(tcm->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(tcm->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
+ input_set_abs_params(tcm->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+ touchscreen_parse_properties(tcm->input, true, &tcm->props);
+
+ ret = input_mt_init_slots(tcm->input, 10, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+ if (ret)
+ return ret;
+
+ input_set_drvdata(tcm->input, tcm);
+
+ ret = input_register_device(tcm->input);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct of_device_id syna_driver_ids[] = {
+ {
+ .compatible = "syna,s3908",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, syna_driver_ids);
+
+static const struct i2c_device_id syna_i2c_ids[] = {
+ { "synaptics-tcm", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, syna_i2c_ids);
+
+static struct i2c_driver syna_i2c_driver = {
+ .probe = tcm_probe,
+ .id_table = syna_i2c_ids,
+ .driver = {
+ .name = "synaptics-tcm",
+ .of_match_table = syna_driver_ids,
+ },
+};
+
+module_i2c_driver(syna_i2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Frieder Hannenheim <frieder.hannenheim@proton.me>");
+MODULE_AUTHOR("Caleb Connolly <caleb@postmarketos.org>");
+MODULE_DESCRIPTION("A driver for Synaptics TCM Oncell Touchpanels");
+
--
Armbian

View File

@ -0,0 +1,988 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Caleb Connolly <caleb@postmarketos.org>
Date: Sun, 30 Jun 2024 20:36:31 +0200
Subject: arm64: dts: qcom: add OnePlus 8T (kebab)
Initial support for USB, UFS, touchscreen, panel, wifi, and bluetooth.
Co-developed-by: Frieder Hannenheim <frieder.hannenheim@proton.me>
Signed-off-by: Frieder Hannenheim <frieder.hannenheim@proton.me>
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
---
arch/arm64/boot/dts/qcom/Makefile | 1 +
arch/arm64/boot/dts/qcom/sm8250-oneplus-common.dtsi | 909 ++++++++++
arch/arm64/boot/dts/qcom/sm8250-oneplus-kebab.dts | 36 +
3 files changed, 946 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -236,6 +236,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8150-sony-xperia-kumano-griffin.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8250-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8250-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8250-oneplus-instantnoodlep.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm8250-oneplus-kebab.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8250-sony-xperia-edo-pdx203.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8250-sony-xperia-edo-pdx206.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8250-xiaomi-elish-boe.dtb
diff --git a/arch/arm64/boot/dts/qcom/sm8250-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-oneplus-common.dtsi
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8250-oneplus-common.dtsi
@@ -0,0 +1,909 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (c) 2024, Frieder Hannenheim <frieder.hannenheim@proton.me>
+ * Copyright (c) 2024, Caleb Connolly <caleb@postmarketos.org>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/usb/pd.h>
+#include "sm8250.dtsi"
+#include "pm8150.dtsi"
+#include "pm8150b.dtsi"
+#include "pm8150l.dtsi"
+
+/* removed_mem @ 0x80b00000 is bigger so we gotta shift everything up... */
+/delete-node/ &removed_mem;
+/delete-node/ &camera_mem;
+/delete-node/ &wlan_mem;
+/delete-node/ &ipa_fw_mem;
+/delete-node/ &ipa_gsi_mem;
+/delete-node/ &gpu_mem;
+/delete-node/ &npu_mem;
+/delete-node/ &video_mem;
+/delete-node/ &cvp_mem;
+/delete-node/ &cdsp_mem;
+/delete-node/ &slpi_mem;
+/delete-node/ &adsp_mem;
+/delete-node/ &spss_mem;
+/delete-node/ &cdsp_secure_heap;
+
+
+/ {
+ aliases {
+ serial0 = &uart12;
+ serial1 = &uart6;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ stdout-path = "serial0:115200n8";
+
+ framebuffer: framebuffer@9c000000 {
+ compatible = "simple-framebuffer";
+ reg = <0 0x9c000000 0 0x2300000>;
+ width = <1080>;
+ height = <2400>;
+ stride = <(1080 * 4)>;
+ format = "a8r8g8b8";
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ autorepeat;
+
+ key-vol-up {
+ label = "Volume up";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&pm8150_gpios 6 GPIO_ACTIVE_LOW>;
+ };
+
+ key-vol-dowm {
+ label = "Volume down";
+ linux,code = <KEY_VOLUMEDOWN>;
+ gpios = <&pm8150_gpios 7 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ reserved-memory {
+ camera_mem: camera@8dc00000 {
+ reg = <0x0 0x8dc00000 0x0 0x500000>;
+ no-map;
+ };
+
+ wlan_mem: wlan@8e100000 {
+ reg = <0x0 0x8e100000 0x0 0x100000>;
+ no-map;
+ };
+
+ ipa_fw_mem: ipa-fw@8e200000 {
+ reg = <0x0 0x8e200000 0x0 0x10000>;
+ no-map;
+ };
+
+ ipa_gsi_mem: ipa-gsi@8e210000 {
+ reg = <0x0 0x8e210000 0x0 0xa000>;
+ no-map;
+ };
+
+ gpu_mem: gpu@8e21a000 {
+ reg = <0x0 0x8e21a000 0x0 0x2000>;
+ no-map;
+ };
+
+ npu_mem: memory@8e300000 {
+ reg = <0x0 0x8e300000 0x0 0x500000>;
+ no-map;
+ };
+
+ video_mem: video@8e800000 {
+ reg = <0x0 0x8e800000 0x0 0x500000>;
+ no-map;
+ };
+
+ cvp_mem: cvp@8ed00000 {
+ reg = <0x0 0x8ed00000 0x0 0x500000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp@8f200000 {
+ reg = <0x0 0x8f200000 0x0 0x1400000>;
+ no-map;
+ };
+
+ slpi_mem: slpi@90600000 {
+ reg = <0x0 0x90600000 0x0 0x1500000>;
+ no-map;
+ };
+
+ adsp_mem: adsp@91b00000 {
+ reg = <0x00 0x91b00000 0x00 0x2500000>;
+ no-map;
+ };
+
+ spss_mem: spss@94000000 {
+ reg = <0x0 0x94000000 0x0 0x100000>;
+ no-map;
+ };
+
+ cdsp_secure_heap: cdsp-secure@94100000 {
+ reg = <0x0 0x94100000 0x0 0x4600000>;
+ no-map;
+ };
+
+ framebuffer@9c000000 {
+ reg = <0 0x9c000000 0 0x2300000>;
+ no-map;
+ };
+ };
+
+ panel_avdd_5p5: regulator-panel-avdd {
+ compatible = "regulator-fixed";
+ regulator-name = "panel_avdd_5p5";
+ regulator-min-microvolt = <5500000>;
+ regulator-max-microvolt = <5500000>;
+ regulator-enable-ramp-delay = <233>;
+ gpio = <&tlmm 61 GPIO_ACTIVE_HIGH>;
+ regulator-boot-on;
+ pinctrl-names = "default";
+ pinctrl-0 = <&panel_avdd_pins>;
+ };
+
+ vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ regulator-always-on;
+ };
+
+ vreg_s4a_1p8: regulator-vreg-s4a-1p8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_s4a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ qca6390-pmu {
+ compatible = "qcom,qca6390-pmu";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_en_state>, <&wlan_en_state>;
+
+ vddaon-supply = <&vreg_s6a_0p95>;
+ vddpmu-supply = <&vreg_s6a_0p95>;
+ vddrfa0p95-supply = <&vreg_s6a_0p95>;
+ vddrfa1p3-supply = <&vreg_s8c_1p3>;
+ vddrfa1p9-supply = <&vreg_s5a_1p9>;
+ vddpcie1p3-supply = <&vreg_s8c_1p3>;
+ vddpcie1p9-supply = <&vreg_s5a_1p9>;
+ vddio-supply = <&vreg_s4a_1p8>;
+
+ wlan-enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>;
+ bt-enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>;
+
+ regulators {
+ vreg_pmu_rfa_cmn: ldo0 {
+ regulator-name = "vreg_pmu_rfa_cmn";
+ };
+
+ vreg_pmu_aon_0p59: ldo1 {
+ regulator-name = "vreg_pmu_aon_0p59";
+ };
+
+ vreg_pmu_wlcx_0p8: ldo2 {
+ regulator-name = "vreg_pmu_wlcx_0p8";
+ };
+
+ vreg_pmu_wlmx_0p85: ldo3 {
+ regulator-name = "vreg_pmu_wlmx_0p85";
+ };
+
+ vreg_pmu_btcmx_0p85: ldo4 {
+ regulator-name = "vreg_pmu_btcmx_0p85";
+ };
+
+ vreg_pmu_rfa_0p8: ldo5 {
+ regulator-name = "vreg_pmu_rfa_0p8";
+ };
+
+ vreg_pmu_rfa_1p2: ldo6 {
+ regulator-name = "vreg_pmu_rfa_1p2";
+ };
+
+ vreg_pmu_rfa_1p7: ldo7 {
+ regulator-name = "vreg_pmu_rfa_1p7";
+ };
+
+ vreg_pmu_pcie_0p9: ldo8 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_pcie_1p8: ldo9 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+ };
+ };
+};
+
+&adsp {
+ firmware-name = "qcom/sm8250/OnePlus/adsp.mbn";
+ status = "okay";
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8150-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+ vdd-s9-supply = <&vph_pwr>;
+ vdd-s10-supply = <&vph_pwr>;
+ vdd-l2-l10-supply = <&vreg_bob>;
+ vdd-l3-l4-l5-l18-supply = <&vreg_s6a_0p95>;
+ vdd-l6-l9-supply = <&vreg_s8c_1p3>;
+ vdd-l7-l12-l14-l15-supply = <&vreg_s5a_1p9>;
+ vdd-l13-l16-l17-supply = <&vreg_bob>;
+
+ vreg_s5a_1p9: smps5 {
+ regulator-name = "vreg_s5a_1p9";
+ regulator-min-microvolt = <1904000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_s6a_0p95: smps6 {
+ regulator-name = "vreg_s6a_0p95";
+ regulator-min-microvolt = <920000>;
+ regulator-max-microvolt = <1128000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2a_3p1: ldo2 {
+ regulator-name = "vreg_l2a_3p1";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3a_0p9: ldo3 {
+ regulator-name = "vreg_l3a_0p9";
+ regulator-min-microvolt = <928000>;
+ regulator-max-microvolt = <932000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ /* l4 = VDD_SSC_MX (lmx.lvl) */
+
+ vreg_l5a_0p88: ldo5 {
+ regulator-name = "vreg_l5a_0p88";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6a_1p2: ldo6 {
+ regulator-name = "vreg_l6a_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7a_1p7: ldo7 {
+ regulator-name = "vreg_l7a_1p7";
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9a_1p2: ldo9 {
+ regulator-name = "vreg_l9a_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10a_1p8: ldo10 {
+ regulator-name = "vreg_l10a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ /* l11 = VDD_SSC_CX (lxc.lvl) */
+
+ vreg_l12a_1p8: ldo12 {
+ regulator-name = "vreg_l12a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13a_ts_3p0: ldo13 {
+ regulator-name = "vreg_l13a_ts_3p0";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14a_1p8: ldo14 {
+ regulator-name = "vreg_l14a_1p8";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <1880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_LPM>;
+ regulator-boot-on;
+ };
+
+ vreg_l15a_1p8: ldo15 {
+ regulator-name = "vreg_l15a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ /* Fingerprint reader power (goodix_fp) */
+ vreg_l16a_2p7: ldo16 {
+ regulator-name = "vreg_l16a_2p7";
+ regulator-min-microvolt = <3024000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17a_3p0: ldo17 {
+ regulator-name = "vreg_l17a_3p0";
+ regulator-min-microvolt = <2504000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l18a_0p92: ldo18 {
+ regulator-name = "vreg_l18a_0p92";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm8150l-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+ vdd-l1-l8-supply = <&vreg_s4a_1p8>;
+ vdd-l2-l3-supply = <&vreg_s8c_1p3>;
+ vdd-l4-l5-l6-supply = <&vreg_bob>;
+ vdd-l7-l11-supply = <&vreg_bob>;
+ vdd-l9-l10-supply = <&vreg_bob>;
+ vdd-bob-supply = <&vph_pwr>;
+
+ vreg_s8c_1p3: smps8 {
+ regulator-name = "vreg_s8c_1p3";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob: bob {
+ regulator-name = "vreg_bob";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <4000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ };
+
+ vreg_l1c_1p8: ldo1 {
+ regulator-name = "vreg_l1c_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2c_1p2: ldo2 {
+ regulator-name = "vreg_l2c_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l3c_0p8: ldo3 {
+ regulator-name = "vreg_l3c_0p8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4c_1p7: ldo4 {
+ regulator-name = "vreg_l4c_1p7";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5c_1p8: ldo5 {
+ regulator-name = "vreg_l5c_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6c_2p96: ldo6 {
+ regulator-name = "vreg_l6c_2p96";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7c_cam_vcm0_2p85: ldo7 {
+ regulator-name = "vreg_l7c_cam_vcm0_2p85";
+ regulator-min-microvolt = <2856000>;
+ regulator-max-microvolt = <3104000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8c_1p8: ldo8 {
+ regulator-name = "vreg_l8c_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9c_2p96: ldo9 {
+ regulator-name = "vreg_l9c_2p96";
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10c_3p0: ldo10 {
+ regulator-name = "vreg_l10c_3p0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11c_3p3: ldo11 {
+ regulator-name = "vreg_l11c_3p3";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-boot-on;
+ /* FIXME: we don't yet support power cycling the panel */
+ //regulator-always-on;
+ };
+ };
+};
+
+&cdsp {
+ firmware-name = "qcom/sm8250/OnePlus/cdsp.mbn";
+ status = "okay";
+};
+
+&crypto {
+ status = "disabled";
+};
+
+&gmu {
+ status = "okay";
+};
+
+&gpu {
+ status = "okay";
+
+ zap-shader {
+ memory-region = <&gpu_mem>;
+ firmware-name = "qcom/sm8250/OnePlus/a650_zap.mbn";
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ /*
+ * Pixelworks Iris 5 @ 26 (i3c) or 22 (i2c)
+ * This is a co-processor for the display which needs to be
+ * initialized along with the panel.
+ */
+};
+
+&i2c15 {
+ status = "okay";
+
+ typec-mux@42 {
+ compatible = "fcs,fsa4480";
+ reg = <0x42>;
+
+ vcc-supply = <&vreg_s4a_1p8>;
+
+ orientation-switch;
+
+ /* Currently unsupported */
+ status = "disabled";
+
+ port {
+ fsa4480_sbu_mux: endpoint {
+ };
+ };
+ };
+};
+
+&i2c16 {
+ status = "okay";
+
+ bq27541_fg: bq27541-battery@55 {
+ compatible = "ti,bq27541";
+ status = "okay";
+ reg = <0x55>;
+ };
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mdss_dsi0 {
+ vdda-supply = <&vreg_l9a_1p2>;
+ status = "okay";
+
+ display_panel: panel@0 {
+ reg = <0>;
+ vddio-supply = <&vreg_l14a_1p8>;
+ vdd-supply = <&vreg_l11c_3p3>;
+ avdd-supply = <&panel_avdd_5p5>;
+ /*
+ * FIXME: There is a bug somewhere in the display stack and it isn't
+ * possible to get the panel to a working state after toggling reset.
+ * At best it just shows one or more vertical red lines. So for now
+ * let's skip the reset GPIO.
+ */
+ // reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>;
+
+ pinctrl-0 = <&panel_reset_pins &panel_vsync_pins &panel_vout_pins>;
+ pinctrl-names = "default";
+
+ status = "disabled";
+
+ port {
+ panel_in_0: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+
+};
+
+&mdss_dsi0_out {
+ data-lanes = <0 1 2 3>;
+ remote-endpoint = <&panel_in_0>;
+};
+
+&mdss_dsi0_phy {
+ vdds-supply = <&vreg_l5a_0p88>;
+ status = "okay";
+};
+
+&pcie0 {
+ status = "okay";
+};
+
+&pcie0_phy {
+ vdda-phy-supply = <&vreg_l5a_0p88>;
+ vdda-pll-supply = <&vreg_l9a_1p2>;
+
+ status = "okay";
+};
+
+&pcieport0 {
+ wifi@0 {
+ compatible = "pci17cb,1101";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
+ vddaon-supply = <&vreg_pmu_aon_0p59>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p7-supply = <&vreg_pmu_rfa_1p7>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ };
+};
+
+&pcie2 {
+ status = "okay";
+};
+
+&pcie2_phy {
+ vdda-phy-supply = <&vreg_l5a_0p88>;
+ vdda-pll-supply = <&vreg_l9a_1p2>;
+ status = "okay";
+};
+
+&pm8150_adc {
+ channel@4c {
+ reg = <ADC5_XO_THERM_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ label = "xo_therm";
+ };
+
+ channel@4d {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ label = "skin_therm";
+ };
+
+ channel@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ label = "wifi_therm";
+ };
+};
+
+&pm8150_adc_tm {
+ status = "okay";
+
+ xo-therm@0 {
+ reg = <0>;
+ io-channels = <&pm8150_adc ADC5_XO_THERM_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ skin-therm@1 {
+ reg = <1>;
+ io-channels = <&pm8150_adc ADC5_XO_THERM_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ wifi-therm@2 {
+ reg = <2>;
+ io-channels = <&pm8150_adc ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+};
+
+&pm8150_gpios {
+ /*
+ * These are marked as reserved in downstream
+ * with no description, without schematics we
+ * don't know what the deal is here.
+ */
+ gpio-reserved-ranges = <2 1>, <4 2>, <8 1>;
+};
+
+&pm8150b_adc {
+ channel@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ label = "conn_therm";
+ };
+};
+
+&pm8150b_adc_tm {
+ status = "okay";
+
+ conn-therm@0 {
+ reg = <0>;
+ io-channels = <&pm8150b_adc ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+};
+
+&pm8150l_adc {
+ channel@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ label = "skin_msm_therm";
+ };
+
+ channel@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ label = "pm8150l_therm";
+ };
+};
+
+&pm8150l_adc_tm {
+ status = "okay";
+
+ skin-msm-therm@0 {
+ reg = <0>;
+ io-channels = <&pm8150l_adc ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ pm8150l-therm@1 {
+ reg = <1>;
+ io-channels = <&pm8150l_adc ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ status = "okay";
+
+ linux,code = <KEY_VOLUMEDOWN>;
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&qupv3_id_2 {
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <28 4>, <40 4>;
+
+ bt_en_state: bt-default-state {
+ pins = "gpio21";
+ function = "gpio";
+ drive-strength = <16>;
+ output-low;
+ bias-pull-up;
+ };
+
+ wlan_en_state: wlan-default-state {
+ pins = "gpio20";
+ function = "gpio";
+
+ drive-strength = <16>;
+ output-low;
+ bias-pull-up;
+ };
+
+ panel_reset_pins: panel-reset-state {
+ pins = "gpio75";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ panel_vsync_pins: panel-vsync-state {
+ pins = "gpio66";
+ function = "mdp_vsync";
+ drive-strength = <16>;
+ bias-pull-down;
+ };
+
+ panel_vout_pins: panel-vout-state {
+ pins = "gpio24";
+ function = "gpio";
+ drive-strength = <16>;
+ output-high;
+ };
+
+ panel_avdd_pins: panel-avdd-state {
+ pins = "gpio65";
+ function = "gpio";
+ drive-strength = <8>;
+ output-high;
+ };
+
+ touch_irq_active: touch-irq-state {
+ pins = "gpio39";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ output-disable;
+ };
+
+ touch_rst_active: touch-rst-state {
+ pins = "gpio38";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+};
+
+&uart6 {
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,qca6390-bt";
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
+ vddaon-supply = <&vreg_pmu_aon_0p59>;
+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p7-supply = <&vreg_pmu_rfa_1p7>;
+ };
+};
+
+&uart12 {
+ status = "okay";
+};
+
+&ufs_mem_hc {
+ status = "okay";
+
+ vcc-supply = <&vreg_l17a_3p0>;
+ vcc-max-microamp = <800000>;
+ vccq-supply = <&vreg_l6a_1p2>;
+ vccq-max-microamp = <800000>;
+ vccq2-supply = <&vreg_s4a_1p8>;
+ vccq2-max-microamp = <800000>;
+};
+
+&ufs_mem_phy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l5a_0p88>;
+ vdda-pll-supply = <&vreg_l9a_1p2>;
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+ status = "okay";
+
+ vdda-pll-supply = <&vreg_l5a_0p88>;
+ vdda33-supply = <&vreg_l2a_3p1>;
+ vdda18-supply = <&vreg_l12a_1p8>;
+};
+
+&usb_1_qmpphy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l9a_1p2>;
+ vdda-pll-supply = <&vreg_l18a_0p92>;
+};
+
+&venus {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8250-oneplus-kebab.dts b/arch/arm64/boot/dts/qcom/sm8250-oneplus-kebab.dts
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8250-oneplus-kebab.dts
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (c) 2024, Caleb Connolly <caleb.connolly@linaro.org>
+ */
+
+#include "sm8250-oneplus-common.dtsi"
+
+/ {
+ model = "OnePlus 8T";
+ compatible = "oneplus,kebab", "qcom,sm8250";
+};
+
+&display_panel {
+ compatible = "samsung,amb655x";
+ status = "okay";
+};
+
+&i2c13 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ touchscreen@4b {
+ compatible = "syna,s3908";
+ reg = <0x4B>;
+
+ pinctrl-0 = <&touch_irq_active &touch_rst_active>;
+ pinctrl-names = "default";
+
+ interrupts-extended = <&tlmm 39 0x2008>;
+
+ reset-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
+
+ vdd-supply = <&vreg_l13a_ts_3p0>;
+ vcc-supply = <&vreg_l1c_1p8>;
+ };
+};
--
Armbian

View File

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: amazingfate <liujianfeng1994@gmail.com>
Date: Thu, 17 Oct 2024 17:10:02 +0800
Subject: arm64: dts: qcom: Add venus firmware for OnePlus 8T
---
arch/arm64/boot/dts/qcom/sm8250-oneplus-kebab.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sm8250-oneplus-kebab.dts b/arch/arm64/boot/dts/qcom/sm8250-oneplus-kebab.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/qcom/sm8250-oneplus-kebab.dts
+++ b/arch/arm64/boot/dts/qcom/sm8250-oneplus-kebab.dts
@@ -34,3 +34,7 @@ touchscreen@4b {
vcc-supply = <&vreg_l1c_1p8>;
};
};
+
+&venus {
+ firmware-name = "qcom/sm8250/OnePlus/kebab/venus.mbn";
+};
--
Armbian