Skip to contentSkip to conversation

Add support for CH1115 Controller

PATCH Superseded Nicolás Antinori 4 participants 8 messages Aug 29 – Aug 31

Subsystems (3)

v3 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v3 cover Add support for CH1115 Controller

This series add support for the CH1115 Controller [1]. It is a monochrome dot matrix OLED controller that supports several interfaces such as SPI and I2C.

This driver only supports the I2C interface, but all common parts could easily be put into a common file to be used with other interfaces. I only have I2C to test with.

This is the first driver I write. The work is based on the driver located at:
- drivers/gpu/drm/sitronix/st7571-i2c.c
- drivers/gpu/drm/sitronix/st7571.c

Tested with Raspberry Pi 3b+.

Changelog:

v3:
- General:
- Patch series based in kernel v7.2
- In dt-bindings:
- Removed "chipwealth,contrast" property (added backlight_device support in driver's code)
- Renamed "chipwealth,invert" -> "chipwealth,inverted"
- Added default value to "chipwealth,offset"
- Removed 'status = "okay"' from example
- Indented example with 4 spaces as stated in the documentation [4]
- In driver code:
- Added support for backlight_device
- Replaced drm_dev_unregister with drm_dev_unplug to cover the dt overlay unload case
- Executing drm shutdown operations before turning off the display
- Checking that the width (panel-timing.hactive) and height (panel-timing.vactive) parameters are greater than 0

v2: [3]
- General:
- Patch series based in kernel v7.2
- In dt-bindings:
- Fixed linter problems
- Replaced first_page property with offset
- In driver code:
- Fixed dst_pitch calculation
- Renamed file from ch1115.c to ch1115-i2c.c
- Support flip-vertical and flip-horizontal dt properties
- Fixed several things found by sashiko-ai

v1: [2]

[1] https://datasheet4u.com/download/1576606/CH1115.html
[2] https://lore.kernel.org/all/[email protected]/
[3] https://lore.kernel.org/all/[email protected]/
[4] https://docs.kernel.org/devicetree/bindings/writing-schema.html#annotated-example-schema

Nicolás Antinori (3):
dt-bindings: display: add Chipwealth CH1115 OLED Controller drm/ch1115: add support for Chipwealth CH1115 OLED controller
MAINTAINERS: add entry for Chipwealth CH1115 OLED Controller

 .../bindings/display/chipwealth,ch1115.yaml   |  81 ++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 MAINTAINERS                                   |   6 +
 drivers/gpu/drm/Kconfig                       |   1 +
 drivers/gpu/drm/Makefile                      |   1 +
 drivers/gpu/drm/chipwealth/Kconfig            |  16 +
 drivers/gpu/drm/chipwealth/Makefile           |   3 +
 drivers/gpu/drm/chipwealth/ch1115-i2c.c       | 887 ++++++++++++++++++
 8 files changed, 997 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml
 create mode 100644 drivers/gpu/drm/chipwealth/Kconfig
 create mode 100644 drivers/gpu/drm/chipwealth/Makefile
 create mode 100644 drivers/gpu/drm/chipwealth/ch1115-i2c.c

--
2.47.3

#1 lore raw

PATCH v3 1/3 dt-bindings: display: add Chipwealth CH1115 OLED Controller

Chipwealth CH1115 is a controller for monochrome dot matrix OLED panels.

---
NOTE: patch series based in kernel v7.2

 .../bindings/display/chipwealth,ch1115.yaml   | 81 +++++++++++++++++++
 .../devicetree/bindings/vendor-prefixes.yaml  |  2 +
 2 files changed, 83 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml
Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml new file +81 -0
new file mode 100644
index 000000000000..6b037c40242e
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/chipwealth,ch1115.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Chipwealth CH1115 Display Controller
+
+maintainers:
+  - Nicolás Antinori <[email protected]>
+
+description:
+  Chipwealth CH1115 is a controller for monochrome dot matrix OLED
+  panels.
+
+  https://datasheet4u.com/download/1576606/CH1115.html
+
+allOf:
+  - $ref: panel/panel-common.yaml#
+
+properties:
+  compatible:
+    const: chipwealth,ch1115
+
+  reg:
+    maxItems: 1
+
+  chipwealth,inverted:
+    type: boolean
+    description:
+      Display pixels are inverted, i.e. 0 is white and 1 is black.
+
+  chipwealth,offset:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 63
+    default: 0
+    description:
+      Display start line offset. Specifies the vertical alignment and row shift
+      along the Y-coordinate.
+
+  width-mm: true
+  height-mm: true
+  flip-horizontal: true
+  flip-vertical: true
+  panel-timing: true
+
+required:
+  - compatible
+  - reg
+  - width-mm
+  - height-mm
+  - panel-timing
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        display@3c {
+            compatible = "chipwealth,ch1115";
+            reg = <0x3c>;
+            width-mm = <12>;
+            height-mm = <8>;
+            chipwealth,offset = <8>;
+            panel-timing {
+                clock-frequency = <0>;
+                hactive = <88>;
+                vactive = <48>;
+                hfront-porch = <0>;
+                hback-porch = <0>;
+                hsync-len = <0>;
+                vsync-len = <0>;
+                vfront-porch = <0>;
+                vback-porch = <0>;
+            };
+        };
+    };
Documentation/devicetree/bindings/vendor-prefixes.yaml +2 -0
index d2ba67c4c8e0..1d158ac83ce9 100644
@@ -325,6 +325,8 @@ patternProperties:
     description: ChipOne
   "^chipspark,.*":
     description: ChipSPARK
+  "^chipwealth,.*":
+    description: Chip Wealth Technology, Ltd.
   "^chongzhou,.*":
     description: Shenzhen Chongzhou Electronic Technology Co., Ltd
   "^chrontel,.*":

--
2.47.3

#2 lore raw

Re: [PATCH v3 1/3] dt-bindings: display: add Chipwealth CH1115 OLED Controller

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] Use of `additionalProperties: false` instead of `unevaluatedProperties: false` restricts…

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Use of additionalProperties: false instead of unevaluatedProperties: false restricts inherited properties and forces anti-pattern property re-declaration. --

commit 1beb1f223427bea55378a246f7b9205ba032f851
Author: Nicolás Antinori <[email protected]>

dt-bindings: display: add Chipwealth CH1115 OLED Controller

Chipwealth CH1115 is a controller for monochrome dot matrix OLED panels.

Quoted 5 lines
Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml new file +0 -0
new file mode 100644
index 0000000000000..6b037c40242ec

[ ... ]

Quoted 4 lines
Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml new file +4 -0
+  chipwealth,offset:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 63

Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml line 46

Quoted 10 lines
Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml new file +10 -0
+    default: 0
+    description:
+      Display start line offset. Specifies the vertical alignment and row shift
+      along the Y-coordinate.
+
+  width-mm: true
+  height-mm: true
+  flip-horizontal: true
+  flip-vertical: true
+  panel-timing: true

[Severity: Medium]
Since this schema includes panel-common.yaml in its allOf block, are these explicit property re-declarations necessary? They appear redundant with the inherited schema and can typically be removed when unevaluatedProperties is used.

Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml line 55

Quoted 9 lines
Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml new file +9 -0
+
+required:
+  - compatible
+  - reg
+  - width-mm
+  - height-mm
+  - panel-timing
+
+additionalProperties: false

[Severity: Medium]
Does using additionalProperties: false here improperly restrict the schema from inheriting standard properties like reset-gpios or rotation from panel-common.yaml? Should this be unevaluatedProperties: false instead, so that valid common properties aren't falsely rejected during board configuration validation?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Reviewed-by on v3 1/3
#3 lore raw

Re: [PATCH v3 1/3] dt-bindings: display: add Chipwealth CH1115 OLED Controller

In reply to Nicolás Antinori
Quoted 10 lines · Nicolás Antinori

Chipwealth CH1115 is a controller for monochrome dot matrix OLED panels.

---
NOTE: patch series based in kernel v7.2

 .../bindings/display/chipwealth,ch1115.yaml   | 81 +++++++++++++++++++
 .../devicetree/bindings/vendor-prefixes.yaml  |  2 +
 2 files changed, 83 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml

Best regards,
Krzysztof

#4 lore raw

PATCH v3 2/3 drm/ch1115: add support for Chipwealth CH1115 OLED controller

In reply to Nicolás Antinori

Chipwealth CH1115 is a controller for monochrome dot matrix OLED panels.

Add DRM support for this chip using i2c bus.

---
NOTE: patch series based in kernel v7.2

 drivers/gpu/drm/Kconfig                 |   1 +
 drivers/gpu/drm/Makefile                |   1 +
 drivers/gpu/drm/chipwealth/Kconfig      |  16 +
 drivers/gpu/drm/chipwealth/Makefile     |   3 +
 drivers/gpu/drm/chipwealth/ch1115-i2c.c | 887 ++++++++++++++++++++++++
 5 files changed, 908 insertions(+)
 create mode 100644 drivers/gpu/drm/chipwealth/Kconfig
 create mode 100644 drivers/gpu/drm/chipwealth/Makefile
 create mode 100644 drivers/gpu/drm/chipwealth/ch1115-i2c.c
drivers/gpu/drm/Kconfig +1 -0
index ba242a8318a8..7aa3ca225434 100644
@@ -307,6 +307,7 @@ source "drivers/gpu/drm/aspeed/Kconfig"
 source "drivers/gpu/drm/ast/Kconfig"
 source "drivers/gpu/drm/atmel-hlcdc/Kconfig"
 source "drivers/gpu/drm/bridge/Kconfig"
+source "drivers/gpu/drm/chipwealth/Kconfig"
 source "drivers/gpu/drm/etnaviv/Kconfig"
 source "drivers/gpu/drm/exynos/Kconfig"
 source "drivers/gpu/drm/fsl-dcu/Kconfig"
drivers/gpu/drm/Makefile +1 -0
index 58c8729ab5a9..9ef738f549ec 100644
@@ -238,6 +238,7 @@ obj-$(CONFIG_DRM_SPRD) += sprd/
 obj-$(CONFIG_DRM_LOONGSON) += loongson/
 obj-$(CONFIG_DRM_POWERVR) += imagination/
 obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon/
+obj-y			+= chipwealth/
 
 # Ensure drm headers are self-contained and pass kernel-doc
 hdrtest-files := \
drivers/gpu/drm/chipwealth/Kconfig new file +16 -0
new file mode 100644
index 000000000000..1cc5adc1e28e
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config DRM_CH1115_I2C
+	tristate "DRM support for Ch1115 OLED panels (I2C BUS)"
+	depends on DRM && I2C
+	select DRM_CLIENT_SELECTION
+	select DRM_GEM_SHMEM_HELPER
+	select DRM_KMS_HELPER
+	select REGMAP_I2C
+	select VIDEOMODE_HELPERS
+	help
+	  Chipwealth CH1115 is a controller for monochrome dot matrix OLED
+	  panels.
+
+	  DRM Driver for Ch1115 OLED panels connected via I2C.
+
+	  If M is selected the module will be called ch1115-i2c.
drivers/gpu/drm/chipwealth/Makefile new file +3 -0
new file mode 100644
index 000000000000..dc915b7d5e93
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_DRM_CH1115_I2C)		+= ch1115-i2c.o
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +887 -0

887 lines not on this page · raw message

--
2.47.3

#5 lore raw

Re: [PATCH v3 2/3] drm/ch1115: add support for Chipwealth CH1115 OLED controller

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: - [High] Sleeping functions are called from DRM atomic context callbacks - [High] Heap buffer overflow due…

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Sleeping functions are called from DRM atomic context callbacks
- [High] Heap buffer overflow due to under-allocated unpadded shadow buffer
- [High] Heap buffer overflow in row and hwbuf due to Framebuffer vs. Panel coordinate mismatch
- [Medium] Display corruption due to unaligned damage rect X coordinates
- [Medium] Hardware misconfiguration due to out-of-range display offset calculation --

commit cf38fdd0d34bcb3a6b00f5ba5e5408b34feba7a9
Author: Nicolás Antinori <[email protected]>

drm/ch1115: add support for Chipwealth CH1115 OLED controller

Chipwealth CH1115 is a controller for monochrome dot matrix OLED panels. Add DRM support for this chip using i2c bus.

Quoted 5 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +0 -0
new file mode 100644
index 0000000000000..2ceb5e948e82f

[ ... ]

Quoted 6 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +6 -0
+static int ch1115_oled_init(struct ch1115_device *ch1115)
+{
+	u8 commands[] = {
+		CH1115_CMD_OFF,
+
+		CH1115_CMD_CLOCK_DIVIDE_RATIO,

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 198

Quoted 10 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +10 -0
+		CH1115_VAL_CLOCK_DIVIDE_RATIO(CH1115_VAL_CLOCK_OSC_FREQ,
+					      CH1115_VAL_CLOCK_DIV_RATIO),
+
+		CH1115_CMD_MUX_RATIO,
+		ch1115->height - 1,
+
+		CH1115_CMD_OFFSET,
+		ch1115->flip_vertical
+			? ch1115->y_start_offset
+			: CH1115_MAX_HEIGHT - ch1115->y_start_offset,
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: Medium]
Is this offset calculation correct when y_start_offset is 0?

In ch1115_oled_init(), CH1115_MAX_HEIGHT - ch1115->y_start_offset evaluates to 64 when y_start_offset is 0. However, the CH1115 offset register only accepts values up to 63 (0x3F). Could sending an out-of-bounds value of 64 cause the hardware to misbehave or ignore the command?

[ ... ]

Quoted 4 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +4 -0
+static void ch1115_prepare_buffer(struct ch1115_device *ch1115,
+				  const struct iosys_map *vmap,
+				  struct drm_framebuffer *fb,
+				  struct drm_rect *rect,

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 245

Quoted 10 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +10 -0
+				  struct drm_format_conv_state *fmtcnv_state)
+{
+	unsigned int dst_pitch;
+	struct iosys_map dst;
+
+	dst_pitch = DIV_ROUND_UP(ch1115->width, 8);
+	rect->y1 = round_down(rect->y1, CH1115_PAGE_HEIGHT);
+	rect->y2 = min_t(unsigned int, round_up(rect->y2, CH1115_PAGE_HEIGHT), ch1115->height);
+
+	iosys_map_set_vaddr(&dst, ch1115->hwbuf + rect->y1 * dst_pitch + rect->x1 / 8);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
Can this pointer arithmetic point out of bounds if the framebuffer viewport is panned?

The damage iterator yields coordinates in absolute framebuffer (FB) coordinates. If userspace configures a framebuffer larger than the panel and pans the source viewport (e.g., src.x1 = 64), rect->x1 and rect->y1 will exceed the bounds of the panel-sized hwbuf. Does the driver need to translate FB coordinates to panel-relative coordinates by subtracting src.x1 and src.y1?

[Severity: Medium]
Could an unaligned rect->x1 cause screen corruption?

The damage rectangle Y coordinates are rounded to 8-pixel boundaries above, but X coordinates are not. Passing an unaligned rect->x1 to drm_fb_xrgb8888_to_mono() will shift the damaged pixels horizontally within the target byte, clobbering adjacent unaffected pixels in the process.

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 246

Quoted 1 line
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +1 -0
+	drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
Will this cause a heap buffer overflow for unaligned display dimensions?

The shadow framebuffer hwbuf is allocated in ch1115_probe() as exactly (width * height) / 8 bytes. If width or height isn't a multiple of 8 (e.g., 127x64), integer division truncates the allocation size. However, dst_pitch is padded to DIV_ROUND_UP(width, 8). Calling drm_fb_xrgb8888_to_mono() will write full padded rows, overflowing the unpadded heap allocation.

[Severity: High]
Is it safe to trigger a GFP_KERNEL allocation here?

This is called from ch1115_primary_plane_helper_atomic_update(). According to DRM subsystem guidelines, plane atomic_update callbacks run in atomic context during non-blocking commits, where sleeping is forbidden. However, drm_fb_xrgb8888_to_mono() can trigger memory allocations with GFP_KERNEL inside the format conversion helper.

Quoted 1 line

+}

[ ... ]

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 288

Quoted 12 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +12 -0
+static int ch1115_fb_update_rect(struct drm_framebuffer *fb, struct drm_rect *rect)
+{
+	struct ch1115_device *ch1115 = drm_to_ch1115(fb->dev);
+	char *row = ch1115->row;
+	int ret;
+
+	rect->y1 = round_down(rect->y1, CH1115_PAGE_HEIGHT);
+	rect->y2 = min_t(unsigned int, round_up(rect->y2, CH1115_PAGE_HEIGHT), ch1115->height);
+
+	for (int y = rect->y1; y < rect->y2; y += CH1115_PAGE_HEIGHT) {
+		for (int x = rect->x1; x < rect->x2; x++)
+			row[x] = ch1115_transform_xy(ch1115->hwbuf, x, y, ch1115->bytes_per_row);
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
Does this array access write out of bounds when the CRTC is panned?

Since row is allocated to exactly ch1115->width bytes, an absolute framebuffer coordinate like rect->x1 exceeding the panel width will cause row[x] to corrupt kernel heap memory. Should the loop index be translated to panel-relative coordinates?

Quoted 12 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +12 -0
+
+		ret = ch1115_set_position(ch1115, ch1115->x_start_offset + rect->x1, y);
+		if (ret < 0)
+			return ret;
+
+		ret = ch1115_draw_screen(ch1115, row + rect->x1, rect->x2 - rect->x1);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}

[ ... ]

Quoted 8 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +8 -0
+static void ch1115_primary_plane_helper_atomic_update(struct drm_plane *plane,
+						      struct drm_atomic_commit *state)
+{
+	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
+	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+	struct drm_framebuffer *fb = plane_state->fb;
+	struct drm_atomic_helper_damage_iter iter;

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 400

Quoted 10 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +10 -0
+	struct drm_device *dev = plane->dev;
+	struct drm_rect damage;
+	struct ch1115_device *ch1115 = drm_to_ch1115(plane->dev);
+	int idx;
+
+	if (!fb)
+		return;
+
+	if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
+		return;
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
Does this callback sleep in atomic context?

drm_gem_fb_begin_cpu_access() can block to wait on DMA fences. Since ch1115_primary_plane_helper_atomic_update() runs in atomic context during non-blocking commits, this can cause might_sleep() warnings and system deadlocks.

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 412

Quoted 12 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +12 -0
+
+	if (!drm_dev_enter(dev, &idx))
+		goto out_drm_gem_fb_end_cpu_access;
+
+	drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+	drm_atomic_for_each_plane_damage(&iter, &damage) {
+		ch1115_prepare_buffer(ch1115,
+				      &shadow_plane_state->data[0],
+				      fb, &damage,
+				      &shadow_plane_state->fmtcnv_state);
+
+		ch1115_fb_update_rect(fb, &damage);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
Will this initiate blocking I2C transfers from atomic context?

ch1115_fb_update_rect() calls ch1115_set_position() and ch1115_draw_screen(), which perform regmap writes over I2C. I2C transfers lock the bus mutex and can sleep, which is forbidden in atomic update paths.

Quoted 1 line
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +1 -0
+	}

[ ... ]

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 529

Quoted 13 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +13 -0
+static void ch1115_encoder_atomic_enable(struct drm_encoder *encoder,
+					 struct drm_atomic_commit *state)
+{
+	struct drm_device *drm = encoder->dev;
+	struct ch1115_device *ch1115 = drm_to_ch1115(drm);
+
+	ch1115_oled_init(ch1115);
+
+	u8 command = CH1115_CMD_ON;
+
+	ch1115_send_command_list(ch1115, &command, 1);
+
+	backlight_enable(ch1115->bl_dev);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
Is it safe to acquire the backlight mutex here?

ch1115_encoder_atomic_enable() runs in atomic context. Calling backlight_enable() acquires the backlight update_lock mutex, which will sleep and violate the atomic context constraints.

Quoted 1 line

+}

[ ... ]

Quoted 12 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +12 -0
+static int ch1115_probe(struct i2c_client *client)
+{
+	struct ch1115_device *ch1115;
+	struct device *dev;
+	struct backlight_device *bl;
+	int ret;
+
+	dev = &client->dev;
+	ch1115 = devm_drm_dev_alloc(&client->dev, &ch1115_driver,
+				    struct ch1115_device, dev);
+	if (IS_ERR(ch1115))
+		return PTR_ERR(ch1115);

[ ... ]

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 782

Quoted 9 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +9 -0
+	ch1115->pages = DIV_ROUND_UP(ch1115->height, CH1115_PAGE_HEIGHT);
+	ch1115->bytes_per_row = DIV_ROUND_UP(ch1115->width, 8);
+	ch1115->x_start_offset = ch1115->flip_horizontal
+		? CH1115_MAX_WIDTH - ch1115->width
+		: 0;
+	ch1115->mode = ch1115_mode(ch1115);
+
+	ch1115->hwbuf = devm_kzalloc(dev, (ch1115->width * ch1115->height) / 8,
+				     GFP_KERNEL);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
Could this allocation be undersized for unaligned display dimensions?

When width or height is not a multiple of 8, integer division truncates the size, leaving hwbuf too small to hold the padded rows written by ch1115_prepare_buffer().

Quoted 6 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +6 -0
+	if (!ch1115->hwbuf)
+		return -ENOMEM;
+
+	ch1115->row = devm_kzalloc(dev, ch1115->width, GFP_KERNEL);
+	if (!ch1115->row)
+		return -ENOMEM;
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
#6 lore raw

Re: [PATCH v3 2/3] drm/ch1115: add support for Chipwealth CH1115 OLED controller

In reply to Nicolás Antinori

Le 29/08/2026 à 08:32, Nicolás Antinori a écrit :

Quoted 5 lines

Chipwealth CH1115 is a controller for monochrome dot matrix OLED panels.

Add DRM support for this chip using i2c bus.

Hi,

a few nitpick below, should it help.

...

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 603

Quoted 10 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +10 -0
+static int ch1115_connector_init(struct ch1115_device *ch1115)
+{
+	struct drm_connector *connector = &ch1115->connector;
+	struct drm_encoder *encoder = &ch1115->encoder;
+	struct drm_device *dev = &ch1115->dev;
+	int ret;
+
+	ret = drm_connector_init(dev, connector, &ch1115_connector_funcs,
+				 DRM_MODE_CONNECTOR_Unknown);
+

Unneeded empty ilne.

Quoted 7 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +7 -0
+	if (ret)
+		return ret;
+
+	drm_connector_helper_add(connector, &ch1115_connector_helper_funcs);
+
+	return drm_connector_attach_encoder(connector, encoder);
+}

...

Quoted 12 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +12 -0
+static int ch1115_probe(struct i2c_client *client)
+{
+	struct ch1115_device *ch1115;
+	struct device *dev;
+	struct backlight_device *bl;
+	int ret;
+
+	dev = &client->dev;
+	ch1115 = devm_drm_dev_alloc(&client->dev, &ch1115_driver,
+				    struct ch1115_device, dev);
+	if (IS_ERR(ch1115))
+		return PTR_ERR(ch1115);

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 768

Quoted 10 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +10 -0
+
+	i2c_set_clientdata(client, ch1115);
+
+	ch1115->client = client;
+	ch1115->regmap = devm_regmap_init(dev, &ch1115_regmap_bus,
+					  client, &ch1115_regmap_config);
+	if (IS_ERR(ch1115->regmap)) {
+		return dev_err_probe(dev, PTR_ERR(ch1115->regmap),
+				     "Failed to initialize regmap\n");
+	}

Un-needed { } to be consistent with other paths below.

Quoted 80 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +80 -0
+
+	ret = ch1115_parse_dt(ch1115);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to parse DT\n");
+
+	ch1115->pages = DIV_ROUND_UP(ch1115->height, CH1115_PAGE_HEIGHT);
+	ch1115->bytes_per_row = DIV_ROUND_UP(ch1115->width, 8);
+	ch1115->x_start_offset = ch1115->flip_horizontal
+		? CH1115_MAX_WIDTH - ch1115->width
+		: 0;
+	ch1115->mode = ch1115_mode(ch1115);
+
+	ch1115->hwbuf = devm_kzalloc(dev, (ch1115->width * ch1115->height) / 8,
+				     GFP_KERNEL);
+	if (!ch1115->hwbuf)
+		return -ENOMEM;
+
+	ch1115->row = devm_kzalloc(dev, ch1115->width, GFP_KERNEL);
+	if (!ch1115->row)
+		return -ENOMEM;
+
+	// Backlight
+	bl = devm_backlight_device_register(dev, dev_name(dev), dev, ch1115,
+					    &ch1115_bl_ops, NULL);
+	if (IS_ERR(bl))
+		return dev_err_probe(dev, PTR_ERR(bl),
+				     "Unable to register backlight device\n");
+
+	bl->props.brightness = ch1115->contrast;
+	bl->props.max_brightness = CH1115_MAX_CONTRAST;
+	ch1115->bl_dev = bl;
+
+	// DRM
+	ret = ch1115_mode_config_init(ch1115);
+	if (ret)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to initialize mode config\n");
+
+	ret = ch1115_plane_init(ch1115);
+	if (ret)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to initialize primary plane\n");
+
+	ret = ch1115_crtc_init(ch1115);
+	if (ret < 0)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to initialize CRTC\n");
+
+	ret = ch1115_encoder_init(ch1115);
+	if (ret < 0)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to initialize encoder\n");
+
+	ret = ch1115_connector_init(ch1115);
+	if (ret < 0)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to initialize connector\n");
+
+	drm_mode_config_reset(&ch1115->dev);
+
+	ret = drm_dev_register(&ch1115->dev, 0);
+	if (ret)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to register DRM device\n");
+
+	drm_client_setup(&ch1115->dev, NULL);
+
+	return 0;
+}
+
+static void ch1115_remove(struct i2c_client *client)
+{
+	struct ch1115_device *ch1115 = i2c_get_clientdata(client);
+	int ret;
+
+	u8 cmd_list[] = {
+		CH1115_CMD_OFF,
+
+		CH1115_CMD_ALL_ON,
+

drivers/gpu/drm/chipwealth/ch1115-i2c.c line 858

Quoted 10 lines
drivers/gpu/drm/chipwealth/ch1115-i2c.c new file +10 -0
+		CH1115_CMD_DC_DC,
+		CH1115_VAL_DC_DC_OFF,
+	};
+
+	drm_dev_unplug(&ch1115->dev);
+	drm_atomic_helper_shutdown(&ch1115->dev);
+
+	ret = ch1115_send_command_list(ch1115, cmd_list, ARRAY_SIZE(cmd_list));
+	if (ret < 0)
+		dev_err(&client->dev, "There was an error executing the shutdown commands");

Missing trailing \n to be consistent with other messages.

Quoted 1 line

+}

...

CJ

#7 lore raw

PATCH v3 3/3 MAINTAINERS: add entry for Chipwealth CH1115 OLED Controller

In reply to Nicolás Antinori

Add MAINTAINERS entry for the Chipwealth CH1115 dot matrix OLED controller.

---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)
MAINTAINERS +6 -0
index 59d60df34dfa..dff105e5f01b 100644
@@ -8581,6 +8581,12 @@ T:	git https://gitlab.freedesktop.org/drm/misc/kernel.git
 F:	Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
 F:	drivers/gpu/drm/panel/panel-widechips-ws2401.c
 
+DRM DRIVER FOR CHIPWEALTH CH1115 PANELS
+M:	Nicolás Antinori <[email protected]>
+S:	Maintained
+F:	Documentation/devicetree/bindings/display/chipwealth,ch1115.yaml
+F:	drivers/gpu/drm/chipwealth/ch1115-i2c.c
+
 DRM DRIVERS
 M:	David Airlie <[email protected]>
 M:	Simona Vetter <[email protected]>

--
2.47.3