public inbox for drm-ai-reviews@public-inbox.freedesktop.org
 help / color / mirror / Atom feed
From: Claude Code Review Bot <claude-review@example.com>
To: dri-devel-reviews@example.com
Subject: Claude review: drm/panel: add LXD M9189A panel driver
Date: Wed, 11 Feb 2026 16:26:36 +1000	[thread overview]
Message-ID: <review-patch3-20260210-drm-panel-ek79007ad3-v3-3-cd2974d56937@pengutronix.de> (raw)
In-Reply-To: <20260210-drm-panel-ek79007ad3-v3-3-cd2974d56937@pengutronix.de>

Patch Review

**Subject:** `[PATCH v3 3/3] drm/panel: add LXD M9189A panel driver`

**Review of driver implementation:**

#### 1. **File header copyright mismatch** (lines 147-150):

```c
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree.
+ * Copyright (c) 2024 Luca Weiss <luca.weiss@fairphone.com>
+ */
```

**Issue:** The copyright attributes the code to Luca Weiss, but the patch is signed off by Rouven Czerwinski and Michael Tretter. This appears to be boilerplate from a code generator that wasn't updated. Either:
- Update copyright to reflect actual authors, or
- Add a note explaining this was generated from tooling with that copyright

#### 2. **Naming inconsistency** (throughout file):

The driver uses mixed naming:
- File: `panel-lxd-m9189a.c` (line 88, 140)
- Kconfig: `DRM_PANEL_LXD_M9189A` (line 116)
- Functions: `m9189_*` prefix (e.g., `m9189_reset`, `m9189_on`)
- Structure: `m9189_panel`
- Driver name: `panel-lxa-m9189a` (line 381) ← **TYPO!**

```c
+	.driver = {
+		.name = "panel-lxa-m9189a",
+		.of_match_table = lxd_m9189_of_match,
+	},
```

**Critical bug:** The driver name is `"panel-lxa-m9189a"` (lxa) but should be `"panel-lxd-m9189a"` (lxd) to match the vendor prefix and file naming.

#### 3. **Magic numbers in timing** (line 281):

```c
+static const struct drm_display_mode m9189_mode = {
+	.clock = (1024 + 160 + 160 + 10) * (600 + 12 + 23 + 1) * 60 / 1000,
+	.hdisplay = 1024,
+	.hsync_start = 1024 + 160,
+	.hsync_end = 1024 + 160 + 160,
+	.htotal = 1024 + 160 + 160 + 10,
+	.vdisplay = 600,
+	.vsync_start = 600 + 12,
+	.vsync_end = 600 + 12 + 23,
+	.vtotal = 600 + 12 + 23 + 1,
```

**Suggestion:** While the formula for clock calculation is clear, consider using #defines for the porch/sync values to make them more readable:

```c
#define M9189_HFRONT_PORCH	160
#define M9189_HSYNC		160
#define M9189_HBACK_PORCH	10
#define M9189_VFRONT_PORCH	12
#define M9189_VSYNC		23
#define M9189_VBACK_PORCH	1
```

This is a minor style issue but improves maintainability.

#### 4. **Missing mode flags** (line 281-292):

The mode structure doesn't specify any flags (hsync/vsync polarity, etc.):

```c
+static const struct drm_display_mode m9189_mode = {
+	.clock = (1024 + 160 + 160 + 10) * (600 + 12 + 23 + 1) * 60 / 1000,
+	...
+	.width_mm = 154,
+	.height_mm = 86,
+};
```

**Question:** Are the default sync polarities (positive hsync/vsync) correct for this panel? Typically this should be documented or explicitly set.

#### 5. **Error handling in probe** (line 317-320):

```c
+	m9189->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(m9189->supply))
+		return dev_err_probe(dev, PTR_ERR(m9189->supply),
+				     "Failed to get power-supply\n");
```

**Good:** The v3 changelog mentions "Fix error code if regulator is missing" and this looks correct. Using `dev_err_probe()` with `PTR_ERR()` is the right pattern.

#### 6. **Regulator enable/disable asymmetry** (lines 246-250 vs 275):

In `m9189_prepare()`:
```c
+	ret = regulator_enable(m9189->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
```

In error path (lines 259-260):
```c
+		gpiod_set_value_cansleep(m9189->reset_gpio, 1);
+		regulator_disable(m9189->supply);
```

In `m9189_unprepare()` (line 275):
```c
+	regulator_disable(m9189->supply);
```

**Analysis:** The regulator is enabled in `prepare()` and disabled in `unprepare()`, which is correct. Error paths also properly disable it. However, there's a potential issue:

In `m9189_disable()` (lines 235-236):
```c
+	gpiod_set_value_cansleep(m9189->standby_gpio, 1);
+
+	return ctx.accum_err;
```

The `disable()` callback sets standby but doesn't touch the regulator. This is probably correct since `unprepare()` handles power, but the ordering should be verified:
- `prepare()` enables power, then initializes panel
- `disable()` puts panel in sleep mode
- `unprepare()` cuts power

This appears correct per DRM panel API conventions.

#### 7. **GPIO active state confusion** (lines 189-194):

```c
+static void m9189_reset(struct m9189_panel *m9189)
+{
+	gpiod_set_value_cansleep(m9189->reset_gpio, 0);
+	msleep(20);
+	gpiod_set_value_cansleep(m9189->reset_gpio, 1);
+	msleep(30);
+	gpiod_set_value_cansleep(m9189->reset_gpio, 0);
+	msleep(55);
+}
```

The reset sequence is: LOW → HIGH → LOW. Combined with:

```c
+	m9189->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
```

And the binding example:
```yaml
+        reset-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
```

**Analysis:** 
- GPIO is acquired with `GPIOD_OUT_LOW` (logical 0)
- With `GPIO_ACTIVE_LOW` in DT, this means physical HIGH
- Reset sequence: physical HIGH → LOW → HIGH
- Assuming reset is active-low (common), this means: inactive → active → inactive

This seems inverted. Typically reset should start inactive, go active, then inactive:
- Start: logical 0 (inactive, physical HIGH with ACTIVE_LOW) ✓
- Assert reset: logical 1 (active, physical LOW with ACTIVE_LOW) ✓  
- Release: logical 0 (inactive, physical HIGH) ✓

Wait, the sequence is `0 → 1 → 0`, which IS correct! The reset line is asserted (logical 1) in the middle. The code is actually correct.

However, in the error path and unprepare (lines 259, 274):
```c
+		gpiod_set_value_cansleep(m9189->reset_gpio, 1);
```

This sets reset to logical 1 (active/asserted) to keep the panel in reset while powered off, which makes sense.

**No issue here**, but the logic is a bit hard to follow. A comment might help.

#### 8. **Manufacturer command definitions** (lines 164-172):

```c
+/* Manufacturer specific DSI commands */
+#define EK79007AD3_GAMMA1		0x80
+#define EK79007AD3_GAMMA2		0x81
+#define EK79007AD3_GAMMA3		0x82
+#define EK79007AD3_GAMMA4		0x83
+#define EK79007AD3_GAMMA5		0x84
+#define EK79007AD3_GAMMA6		0x85
+#define EK79007AD3_GAMMA7		0x86
+#define EK79007AD3_PANEL_CTRL3		0xB2
```

**Good:** Commands are well-documented with the controller name prefix.

#### 9. **Hardcoded gamma values** (lines 203-211):

```c
+	/* Gamma 2.2 */
+	mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA1, 0x48);
+	mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA2, 0xB8);
+	mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA3, 0x88);
+	mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA4, 0x88);
+	mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA5, 0x58);
+	mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA6, 0xD2);
+	mipi_dsi_dcs_write_seq_multi(&ctx, EK79007AD3_GAMMA7, 0x88);
+	mipi_dsi_msleep(&ctx, 50);
```

**Acceptable:** These are panel-specific gamma calibration values, likely from vendor specification. Hardcoding them is normal for panel drivers.

#### 10. **Generic write for panel control** (line 214):

```c
+	/* 4 Lanes */
+	mipi_dsi_generic_write_multi(&ctx, (u8[]){ EK79007AD3_PANEL_CTRL3, 0x70 }, 2);
```

**Question:** Why is this using `mipi_dsi_generic_write_multi()` instead of `mipi_dsi_dcs_write_seq_multi()` like the gamma commands? Is `0xB2` not a DCS command? 

If it's a manufacturer-specific command, `generic_write` is correct, but then the gamma commands above should probably also use generic_write. The comment says the panel supports "only 4 lane operation" (line 65), but the code doesn't validate that `dsi->lanes == 4` anywhere.

Consider adding validation in probe:

```c
if (dsi->lanes != 4) {
	dev_err(dev, "This panel only supports 4-lane operation\n");
	return -EINVAL;
}
```

Or if the panel could theoretically support other lane counts, remove the "only" from the commit message.

#### 11. **MAINTAINERS entry** (lines 99-104):

```
+DRM DRIVER FOR LXD M9189A PANELS
+M:	Michael Tretter <m.tretter@pengutronix.de>
+S:	Maintained
+F:	Documentation/devicetree/bindings/display/panel/lxd,m9189a.yaml
+F:	drivers/gpu/drm/panel/panel-lxd-m9189a.c
```

**Good:** Proper MAINTAINERS entry with status and file patterns. Alphabetical ordering looks correct (between LVDS and MANTIX entries).

#### 12. **Module metadata** (lines 387-388):

```c
+MODULE_DESCRIPTION("DRM driver for LXD M9189A MIPI-DSI panels");
+MODULE_LICENSE("GPL");
```

**Issue:** License mismatch. The SPDX header says `GPL-2.0-only` but `MODULE_LICENSE("GPL")` can mean GPL v2 or later. Should be:

```c
MODULE_LICENSE("GPL v2");
```

to match the SPDX identifier.

---

## SUMMARY OF ISSUES

### Critical:
1. **Driver name typo** (panel-lxa vs panel-lxd) - MUST FIX
2. **MODULE_LICENSE mismatch** - should be "GPL v2" not "GPL"

### Important:
3. **Copyright header** - needs updating or explanation
4. **Backlight requirement** - unclear if optional or required in binding
5. **Lane count validation** - driver doesn't validate 4-lane requirement

### Minor/Suggestions:
6. Magic numbers in display mode could use #defines
7. Missing mode flags documentation
8. Inconsistent use of DCS vs generic write
9. Standby GPIO needs better documentation in binding

### Good practices observed:
- Use of modern multi-context helpers
- Proper error handling with dev_err_probe
- Correct panel lifecycle (prepare/unprepare/disable)
- Devm resource management
- prepare_prev_first flag set appropriately

**Overall verdict:** The series needs at least the critical fixes before merge. The rest are improvements that could be addressed or explained in discussion with maintainers.

---
Generated by Claude Code Patch Reviewer

  reply	other threads:[~2026-02-11  6:26 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-10 11:22 [PATCH v3 0/3] drm/panel: add LXD M9189A Michael Tretter
2026-02-10 11:22 ` [PATCH v3 1/3] dt-bindings: vendor-prefixes: Add lxd Michael Tretter
2026-02-11  6:26   ` Claude review: " Claude Code Review Bot
2026-02-10 11:22 ` [PATCH v3 2/3] dt-bindings: display: panel: add YAML schema for LXD M9189A Michael Tretter
2026-02-11  6:26   ` Claude review: " Claude Code Review Bot
2026-02-11  6:28   ` [PATCH v3 2/3] " Krzysztof Kozlowski
2026-02-11 10:06     ` Michael Tretter
2026-02-11 10:12       ` Krzysztof Kozlowski
2026-02-10 11:22 ` [PATCH v3 3/3] drm/panel: add LXD M9189A panel driver Michael Tretter
2026-02-11  6:26   ` Claude Code Review Bot [this message]
2026-02-11  6:26 ` Claude review: drm/panel: add LXD M9189A Claude Code Review Bot

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=review-patch3-20260210-drm-panel-ek79007ad3-v3-3-cd2974d56937@pengutronix.de \
    --to=claude-review@example.com \
    --cc=dri-devel-reviews@example.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