From: Devarsh Thakkar <devarsht@ti.com>
To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>, Nishanth Menon <nm@ti.com>,
Vignesh Raghavendra <vigneshr@ti.com>,
Tero Kristo <kristo@kernel.org>
Cc: <dri-devel@lists.freedesktop.org>, <devicetree@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, Devarsh Thakkar <devarsht@ti.com>,
"LiangCheng Wang" <zaq14760@gmail.com>
Subject: [PATCH v2 06/14] drm/solomon: ssd16xx: Add support for Solomon SSD1677 controller
Date: Sun, 27 Sep 2026 23:53:21 +0530 [thread overview]
Message-ID: <20260927182329.4193961-7-devarsht@ti.com> (raw)
In-Reply-To: <20260927182329.4193961-1-devarsht@ti.com>
Add infrastructure to support the Solomon SSD1677 e-paper controller
(up to 960x680 pixels, 10-bit pixel-level X/Y RAM addressing).
The SSD1677 shares the same command address space as SSD1683 but
differs in several controller-level characteristics:
- RAM X/Y addressing: SSD1677 uses 10-bit pixel-level addresses
whereas SSD1683 uses 6-bit byte-level X and 9-bit Y. The
existing ram_x_address_bits / ram_y_address_bits fields in
ssd16xx_controller_config already handle the different format;
ssd16xx_fb_dirty is updated to compute the correct end address
from device->width using the addressing model:
byte-addressed: XEnd = panel_width/8 - 1
pixel-addressed: XEnd = panel_width - 1
- Deep sleep: only mode 0x03 is documented in SSD1677 (no level-1
RAM-retain mode 0x01 as in SSD1683). Both level1/level2 point
to SSD1683_DEEP_SLEEP_MODE_2 (0x03).
- ctrl2 full refresh uses 0xF4 (omits DISABLE_ANALOG/DISABLE_CLK
bits) per the reference implementation. 0xFF for partial refresh
is listed as valid in the SSD1677 datasheet; BIT(3) semantics are
undocumented — included pending hardware verification.
- Border waveform byte encoding is identical to SSD1683; the same
ssd1683_border_waveform_table[] is reused.
A new booster_soft_start_data / booster_soft_start_len field is added
to ssd16xx_device_config for panels that require BOOSTER_SOFT_START
(0x0C) initialisation. The command exists in both SSD1683 and SSD1677
but the tuning values are board/panel-specific; panels that do not need
it set the pointer to NULL. hw_init sends the command when non-NULL.
Controller limit validation is added in probe: panel dimensions must
not exceed the controller hardware maximum, and for byte-addressed X
controllers the panel width must be a multiple of 8.
Driver Output Control MUX, tx_buf allocation, and fb_dirty RAM window
end addresses now use the actual panel dimensions rather than the
controller maximum, correctly handling panels smaller than the
controller's rated capacity.
Co-developed-by: LiangCheng Wang <zaq14760@gmail.com>
Signed-off-by: Devarsh Thakkar <devarsht@ti.com>
---
Changes from v1:
- New patch: Extracted SSD1677 controller support into dedicated patch
drivers/gpu/drm/solomon/ssd16xx.c | 78 +++++++++++++++++++++++++++----
1 file changed, 68 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/solomon/ssd16xx.c b/drivers/gpu/drm/solomon/ssd16xx.c
index c478309d08e9..93fa064cf589 100644
--- a/drivers/gpu/drm/solomon/ssd16xx.c
+++ b/drivers/gpu/drm/solomon/ssd16xx.c
@@ -39,6 +39,7 @@
/* SPI command codes (common) */
#define SSD16XX_CMD_DRIVER_OUTPUT_CONTROL 0x01
+#define SSD16XX_CMD_BOOSTER_SOFT_START 0x0C
#define SSD16XX_CMD_DATA_ENTRY_MODE 0x11
#define SSD16XX_CMD_SW_RESET 0x12
#define SSD16XX_CMD_MASTER_ACTIVATION 0x20
@@ -181,6 +182,7 @@
enum ssd16xx_controller {
SSD1683 = 1,
+ SSD1677,
};
enum ssd16xx_model {
@@ -332,6 +334,10 @@ struct ssd16xx_device_config {
*/
enum ssd16xx_color_mode default_color_mode;
+ /* Optional BOOSTER_SOFT_START (0x0C) tuning bytes; NULL if unused. */
+ const u8 *booster_soft_start_data;
+ u8 booster_soft_start_len;
+
/* Panel-specific display mode (resolution and physical dimensions) */
const struct drm_display_mode *mode;
};
@@ -420,6 +426,29 @@ static const struct ssd16xx_controller_config ssd16xx_controller_configs[] = {
},
.ctrl2_load_temp_lut = SSD1683_CTRL2_LOAD_TEMP_LUT,
},
+ [SSD1677] = {
+ /*
+ * 10-bit pixel-level X/Y addressing; only deep sleep mode
+ * 0x03 is supported (no RAM-retain mode). Border waveform
+ * encoding matches SSD1683.
+ */
+ .max_width = 960,
+ .max_height = 680,
+ .ram_x_address_bits = 10,
+ .ram_y_address_bits = 10,
+ .has_temp_sensor_ctrl = true,
+ .deep_sleep_mode_level1 = SSD1683_DEEP_SLEEP_MODE_2, /* 0x03 */
+ .deep_sleep_mode_level2 = SSD1683_DEEP_SLEEP_MODE_2, /* 0x03 */
+ .border_waveform_table = ssd1683_border_waveform_table,
+ .ctrl1_normal = SSD1683_CTRL1_NORMAL,
+ .ctrl1_bypass_red_ram = SSD1683_CTRL1_BYPASS_RED_RAM,
+ .ctrl2_refresh = {
+ [SSD16XX_REFRESH_PARTIAL] = 0xFF,
+ [SSD16XX_REFRESH_FULL] = 0xF4,
+ [SSD16XX_REFRESH_FAST] = SSD1683_CTRL2_FAST_REFRESH,
+ },
+ .ctrl2_load_temp_lut = SSD1683_CTRL2_LOAD_TEMP_LUT,
+ },
};
/* GDEY042T81: 4.2" 400x300 panel, 84.8x63.6mm active area */
@@ -553,28 +582,44 @@ static void ssd16xx_send_data(struct ssd16xx_device *device, u8 data,
static void ssd16xx_send_x_param(struct ssd16xx_device *device, u16 x,
int *err)
{
+ u8 bits = device->controller_cfg->ram_x_address_bits;
+ u16 max_val = (1U << bits) - 1;
+
if (*err)
return;
- if (device->controller_cfg->ram_x_address_bits == 8) {
+ if (x > max_val)
+ x = max_val;
+
+ if (bits <= 8) {
ssd16xx_send_data(device, (u8)x, err);
} else {
+ u8 hi_mask = (1U << (bits - 8)) - 1;
+
ssd16xx_send_data(device, x & 0xFF, err);
- ssd16xx_send_data(device, (x >> 8) & 0xFF, err);
+ ssd16xx_send_data(device, (x >> 8) & hi_mask, err);
}
}
static void ssd16xx_send_y_param(struct ssd16xx_device *device, u16 y,
int *err)
{
+ u8 bits = device->controller_cfg->ram_y_address_bits;
+ u16 max_val = (1U << bits) - 1;
+
if (*err)
return;
- if (device->controller_cfg->ram_y_address_bits == 8) {
+ if (y > max_val)
+ y = max_val;
+
+ if (bits <= 8) {
ssd16xx_send_data(device, (u8)y, err);
} else {
+ u8 hi_mask = (1U << (bits - 8)) - 1;
+
ssd16xx_send_data(device, y & 0xFF, err);
- ssd16xx_send_data(device, (y >> 8) & 0xFF, err);
+ ssd16xx_send_data(device, (y >> 8) & hi_mask, err);
}
}
@@ -691,21 +736,34 @@ static int ssd16xx_hw_init(struct ssd16xx_device *device)
ssd16xx_hw_reset(device);
- /* Software reset */
+ /* Software reset (0x12): resets command/parameter registers to defaults. */
ssd16xx_send_cmd(device, SSD16XX_CMD_SW_RESET, &err);
ssd16xx_wait_for_device(device, &err);
- /* Driver output control (0x01): MUX ratio and scan direction. */
- ssd16xx_send_cmd(device, SSD16XX_CMD_DRIVER_OUTPUT_CONTROL, &err);
- ssd16xx_send_y_param(device, device->height - 1, &err);
- ssd16xx_send_data(device, device->device_cfg->driver_output_ctrl_byte3, &err);
-
/* Internal temperature sensor (SSD1683/SSD1680 only; not present in SSD1673) */
if (device->controller_cfg->has_temp_sensor_ctrl) {
ssd16xx_send_cmd(device, SSD1683_CMD_TEMPERATURE_SENSOR_CONTROL, &err);
ssd16xx_send_data(device, SSD1683_TEMP_SENSOR_INTERNAL, &err);
}
+ /*
+ * Booster soft-start (0x0C): panel-specific charge pump tuning.
+ * Some panels (e.g. PIXPAPER 4.26m on SSD1677) require this step;
+ * others (e.g. GDEY042T81 on SSD1683) omit it.
+ */
+ if (device->device_cfg->booster_soft_start_data) {
+ ssd16xx_send_cmd(device, SSD16XX_CMD_BOOSTER_SOFT_START, &err);
+ ssd16xx_send_data_bulk(device,
+ device->device_cfg->booster_soft_start_data,
+ device->device_cfg->booster_soft_start_len,
+ &err);
+ }
+
+ /* Driver output control (0x01): MUX ratio and scan direction. */
+ ssd16xx_send_cmd(device, SSD16XX_CMD_DRIVER_OUTPUT_CONTROL, &err);
+ ssd16xx_send_y_param(device, device->height - 1, &err);
+ ssd16xx_send_data(device, device->device_cfg->driver_output_ctrl_byte3, &err);
+
/*
* For FAST refresh mode, pre-load the LUT once here during initialization.
* FAST mode ctrl2 (0xC7) omits LOAD_LUT on every update for speed, so the
--
2.39.1
next prev parent reply other threads:[~2026-09-27 18:25 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-27 18:23 [PATCH v2 00/14] Add DRM driver for Solomon SSD16xx e-paper display controllers Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 01/14] dt-bindings: vendor-prefixes: Add Dalian Good Display Co., Ltd Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 02/14] dt-bindings: display: Add Solomon SSD16xx e-paper controller binding Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 03/14] dt-bindings: display: solomon,ssd16xx: Add Solomon SSD1677 controller Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 04/14] drm/solomon: Add DRM driver for Solomon SSD16xx e-paper display controllers Devarsh Thakkar
2026-09-28 7:00 ` Thomas Zimmermann
2026-09-27 18:23 ` [PATCH v2 05/14] drm/solomon: ssd16xx: Add clear_on_init/close/disable session management Devarsh Thakkar
2026-09-27 18:23 ` Devarsh Thakkar [this message]
2026-09-27 18:23 ` [PATCH v2 07/14] drm/solomon: ssd16xx: Add power management support Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 08/14] drm/solomon: ssd16xx: Expose refresh mode as plane property Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 09/14] drm/solomon: ssd16xx: Expose color " Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 10/14] drm/solomon: ssd16xx: Expose session management as plane properties Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 11/14] drm/solomon: ssd16xx: support panels whose RAM X order is reversed Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 12/14] MAINTAINERS: Add entry for Solomon SSD16xx DRM driver Devarsh Thakkar
2026-09-27 18:23 ` [PATCH v2 13/14] arm64: defconfig: Enable DRM_SSD16XX for AM62L3 EVM Devarsh Thakkar
2026-09-27 18:23 ` [DO_NOT_MERGE PATCH v2 14/14] arm64: dts: ti: Add AM62L3 EVM overlay for GDEY042T81 e-paper display Devarsh Thakkar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260927182329.4193961-7-devarsht@ti.com \
--to=devarsht@ti.com \
--cc=airlied@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=kristo@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=nm@ti.com \
--cc=robh@kernel.org \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
--cc=vigneshr@ti.com \
--cc=zaq14760@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®