Add Anbernic RG Vita-Pro
Subsystems (6)
v7 cover Add Anbernic RG Vita-Pro
From: Chris Morgan <[email protected]>
Add support for the Anbernic RG Vita-Pro, based on the Rockchip RK3576 SoC.
Changes Since V1:
- Updated documentation filename to matche compatible string.
- Corrected order of allocating IRQ in charger driver and switched to using devm managed function to allocate work queue.
Changes Since V2:
- Corrected issue with naming of panel binding document and added fallback compatible string.
- Switched to devm helpers in panel driver. Note that devm_drm_panel_add() is currently only in the drm-next branch.
- Optimized setting GPIOs for panel driver.
Changes Since V3:
- Fixed numerous issues identifed by Sashiko bot, mainly relating to unclamped or improperly clamped values from within the charger driver.
- Corrected hard-coded values in the panel driver unprepare routine as well as correcting an improperly checked return condition.
Changes Since V4:
- Fixed errors identified by Sashiko bot on charger driver that could result in an improper value being written to the registers.
- Corrected some error handling in the panel driver.
Changes Since V5:
- Corrected minor errors in documentation and added default values.
- Further corrected clamping behavior in charger driver.
Changes Since V6:
- Additional corrections as suggested by Sashiko bot to fix potential edge cases during probe for sgm41542.
- Corrected an improperly shifted value being written to register for sgm41542.
- Changed a MV value to UV in sgm41542 driver to simplify function.
Chris Morgan (6):
dt-bindings: power: supply: sgm41542: document sgm41542
power: supply: sgm41542: Add SG Micro sgm41542 charger
dt-bindings: display: panel: Add Anbernic TD4310 panel drm/panel: anbernic-td4310: Add RG Vita Pro panel
dt-bindings: arm: rockchip: Add Anbernic RG Vita-Pro
arm64: dts: rockchip: Add Anbernic RG Vita-Pro
.../devicetree/bindings/arm/rockchip.yaml | 6 + .../display/panel/anbernic,td4310.yaml | 66 + .../power/supply/sgmicro,sgm41542.yaml | 96 ++ arch/arm64/boot/dts/rockchip/Makefile | 1 + .../rockchip/rk3576-anbernic-rg-vita-pro.dts | 1327 +++++++++++++++++ drivers/gpu/drm/panel/Kconfig | 10 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-anbernic-td4310.c | 257 ++++ drivers/power/supply/Kconfig | 8 + drivers/power/supply/Makefile | 1 + drivers/power/supply/sgm41542_charger.c | 1067 +++++++++++++ 11 files changed, 2840 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/anbernic,td4310.yaml create mode 100644 Documentation/devicetree/bindings/power/supply/sgmicro,sgm41542.yaml create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-anbernic-rg-vita-pro.dts create mode 100644 drivers/gpu/drm/panel/panel-anbernic-td4310.c create mode 100644 drivers/power/supply/sgm41542_charger.c
Signature · 1 line
2.43.0
PATCH v7 1/6 dt-bindings: power: supply: sgm41542: document sgm41542
From: Chris Morgan <[email protected]>
Document the SG Micro sgm41542 battery charger/boost converter. The parameters of input-current-limit-microamp and input-voltage-limit-microvolt are defined as such since they are in common use among multiple bindings currently.
--- .../power/supply/sgmicro,sgm41542.yaml | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/sgmicro,sgm41542.yaml
Documentation/devicetree/bindings/power/supply/sgmicro,sgm41542.yaml new file +96 -0
@@ -0,0 +1,96 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/sgmicro,sgm41542.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SGM41542 Battery Charger + +description: + The SGMicro SGM41542 is a single cell battery charger/boost controller. + +maintainers: + - Chris Morgan <[email protected]> + - Xu Shengfei <[email protected]> + +allOf: + - $ref: power-supply.yaml# + +properties: + compatible: + const: sgmicro,sgm41542 + + input-current-limit-microamp: + default: 2400000 + minimum: 100000 + maximum: 3800000 + + input-voltage-limit-microvolt: + default: 4500000 + minimum: 3900000 + maximum: 12000000 + + interrupts: + maxItems: 1 + + monitored-battery: + description: | + The charger uses the following battery properties + constant-charge-current-max-microamp (default 2040000) + constant-charge-voltage-max-microvolt (default 4208000) + charge-term-current-microamp (default 180000) + precharge-current-microamp (default 180000) + + reg: + maxItems: 1 + + regulators: + type: object + properties: + otg-vbus: + type: object + description: OTG boost regulator + $ref: /schemas/regulator/regulator.yaml + unevaluatedProperties: false + additionalProperties: false + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + + battery: battery { + compatible = "simple-battery"; + constant-charge-current-max-microamp = <10000000>; + constant-charge-voltage-max-microvolt = <4350000>; + precharge-current-microamp = <180000>; + charge-term-current-microamp = <300000>; + }; + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + charger@3b { + compatible = "sgmicro,sgm41542"; + reg = <0x3b>; + input-current-limit-microamp = <3000000>; + input-voltage-limit-microvolt = <4500000>; + interrupt-parent = <&gpio0>; + interrupts = <26 IRQ_TYPE_EDGE_FALLING>; + monitored-battery = <&battery>; + + regulators { + otg-vbus { + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + }; + }; + }; + };
Signature · 1 line
2.43.0
Rob Herring
maintainerRe: [PATCH V7 1/6] dt-bindings: power: supply: sgm41542: document sgm41542
Quoted 8 lines · Chris Morgan
From: Chris Morgan <[email protected]>
Document the SG Micro sgm41542 battery charger/boost converter. The parameters of input-current-limit-microamp and input-voltage-limit-microvolt are defined as such since they are in common use among multiple bindings currently.
Signed-off-by Chris Morgan <[email protected]>
Missing Conor's reviewed-by.
Quoted 4 lines
--- .../power/supply/sgmicro,sgm41542.yaml | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/sgmicro,sgm41542.yaml
Re: [PATCH V7 1/6] dt-bindings: power: supply: sgm41542: document sgm41542
Quoted 15 lines · Rob Herring
Quoted 8 lines · Chris Morgan
From: Chris Morgan <[email protected]>
Document the SG Micro sgm41542 battery charger/boost converter. The parameters of input-current-limit-microamp and input-voltage-limit-microvolt are defined as such since they are in common use among multiple bindings currently.
Signed-off-by Chris Morgan <[email protected]>Missing Conor's reviewed-by.
Quoted 4 lines
--- .../power/supply/sgmicro,sgm41542.yaml | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/sgmicro,sgm41542.yaml
I'm sorry, somehow I accidentally dropped it. If I need a V8 I'll be sure to include it, unless you want me to submit a V8 to add it?
Thank you,
Chris
PATCH v7 2/6 power: supply: sgm41542: Add SG Micro sgm41542 charger
In reply to Chris MorganFrom: Chris Morgan <[email protected]>
Add support for the SG Micro SGM41542 charger/boost converter. Driver was adapted from Rockchip BSP driver [1] and confirmed with vendor datasheet [2].
[1] https://github.com/rockchip-linux/kernel/blob/develop-6.6/drivers/power/supply/sgm41542_charger.c
[2] https://www.sg-micro.de/rect/assets/1e8de70b-657e-4156-be68-a64fdbe8e418/SGM41541_SGM41542.pdf
--- drivers/power/supply/Kconfig | 8 + drivers/power/supply/Makefile | 1 + drivers/power/supply/sgm41542_charger.c | 1067 +++++++++++++++++++++++ 3 files changed, 1076 insertions(+) create mode 100644 drivers/power/supply/sgm41542_charger.c
drivers/power/supply/Kconfig +8 -0
@@ -856,6 +856,14 @@ config CHARGER_RK817 help Say Y to include support for Rockchip RK817 Battery Charger. +config CHARGER_SGM41542 + tristate "SGM41542 charger driver" + depends on I2C + depends on GPIOLIB || COMPILE_TEST + select REGMAP_I2C + help + Say Y to enable support for the SGM41542 battery charger. + config CHARGER_SMB347 tristate "Summit Microelectronics SMB3XX Battery Charger" depends on I2C
drivers/power/supply/Makefile +1 -0
@@ -107,6 +107,7 @@ obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o obj-$(CONFIG_CHARGER_BQ25980) += bq25980_charger.o obj-$(CONFIG_CHARGER_BQ256XX) += bq256xx_charger.o obj-$(CONFIG_CHARGER_RK817) += rk817_charger.o +obj-$(CONFIG_CHARGER_SGM41542) += sgm41542_charger.o obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
drivers/power/supply/sgm41542_charger.c new file +1067 -0
1,067 lines not on this page · raw message
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH V7 2/6] power: supply: sgm41542: Add SG Micro sgm41542 charger
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: - [High] Hardware watchdog resets charger configuration during system suspend due to missing PM…
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Hardware watchdog resets charger configuration during system suspend due to missing PM suspend/resume handlers.
- [High] The IRQ handler unconditionally overwrites the input current limit whenever VBUS is present, silently destroying userspace-configured limits.
- [Medium] Missing cleanup for device_init_wakeup() on driver unbind and probe error paths.
- [Medium] Lack of synchronization in the sysfs property setter for ONLINE state allows hardware/software state desynchronization.
- [Medium] The IRQ handler returns early on an I2C failure, skipping the critical power_supply_changed() uevent notification. --
commit 518a06e67b4771b8e50e9e0705ace20eca6acede
Author: Chris Morgan <[email protected]>
power: supply: sgm41542: Add SG Micro sgm41542 charger
Add support for the SG Micro SGM41542 charger/boost converter. Driver was adapted from Rockchip BSP driver [1] and confirmed with vendor datasheet [2].
Quoted 4 lines
drivers/power/supply/sgm41542_charger.c new file +0
-0
[ ... ]
Quoted 7 lines
drivers/power/supply/sgm41542_charger.c new file +7
-0+static int sgm4154x_charger_set_property (struct power_supply *psy, +enum power_supply_property prop, +const union power_supply_propval *val) +{ +struct sgm4154x_device *sgm =power_supply_get_drvdata (psy); +int ret = -EINVAL ; +
drivers/power/supply/sgm41542_charger.c line 604
Quoted 10 lines
drivers/power/supply/sgm41542_charger.c new file +10
-0+switch (prop) { +case POWER_SUPPLY_PROP_ONLINE : +if (val->intval) { + ret =sgm4154x_enable_charger (sgm); +sgm4154x_set_watchdog_timer (sgm,SGM4154X_WDT_TIMER_40S ); + }else { +sgm4154x_set_watchdog_timer (sgm,SGM4154X_WDT_TIMER_DISABLE ); + ret =sgm4154x_disable_charger (sgm); + } +break ;
[Severity: Medium]
Is there a need for a mutex in this sysfs property setter?
When modifying POWER_SUPPLY_PROP_ONLINE, the code performs multiple operations without holding any locks.
Could concurrent sysfs writes interleave these operations? This might lead to the hardware charger being disabled while the watchdog timer remains enabled, causing the software sgm->watchdog_enable flag to become desynchronized with the actual hardware state.
[ ... ]
Quoted 5 lines
drivers/power/supply/sgm41542_charger.c new file +5
-0+static irqreturn_t sgm4154x_irq_handler_thread (int irq,void *private) +{ +struct sgm4154x_device *sgm4154x = private; +struct sgm4154x_state state; +int ret;
drivers/power/supply/sgm41542_charger.c line 720
Quoted 10 lines
drivers/power/supply/sgm41542_charger.c new file +10
-0+ + ret =sgm4154x_get_state (sgm4154x, &state); +if (ret) { +dev_err (sgm4154x->dev,"get state error!\n" ); +return IRQ_NONE ; + } + sgm4154x->state = state; +if (state.vbus_gd) { +if (sgm4154x->init_data.ilim >=SGM4154X_DEFAULT_INPUT_CUR ) { + ret =sgm4154x_set_input_curr_lim (sgm4154x, sgm4154x->init_data.ilim);
[Severity: High]
Will this unconditionally overwrite the input current limit configured by userspace?
This checks if VBUS is good, but doesn't check if VBUS just transitioned to being good.
Since it unconditionally applies init_data.ilim, won't any subsequent interrupt while VBUS is present (such as a battery thermal event) silently overwrite custom limits previously set via sysfs?
drivers/power/supply/sgm41542_charger.c line 731
Quoted 11 lines
drivers/power/supply/sgm41542_charger.c new file +11
-0+if (ret) { +dev_err (sgm4154x->dev,"set input current error!\n" ); +/* Reading IRQ clears interrupt, so return handled */ +return IRQ_HANDLED ; + } + } + } +power_supply_changed (sgm4154x->charger); + +return IRQ_HANDLED ; +}
[Severity: Medium]
Should this early return be avoided so that power_supply_changed() is still called?
If the I2C write for the input current limit fails, the code immediately returns.
Will this cause userspace to silently miss important hardware state changes, like cable insertion or fault conditions, that triggered the interrupt?
[ ... ]
Quoted 14 lines
drivers/power/supply/sgm41542_charger.c new file +14
-0+static int sgm4154x_probe (struct i2c_client *client) +{ +struct device *dev = &client->dev; +struct sgm4154x_device *sgm; +int ret; + + sgm =devm_kzalloc (dev,sizeof (*sgm),GFP_KERNEL ); +if (!sgm) +return -ENOMEM ; + + sgm->dev = dev; + + sgm->regmap =devm_regmap_init_i2c (client, &sgm4154x_regmap_config); +if (IS_ERR (sgm->regmap))
drivers/power/supply/sgm41542_charger.c line 996
Quoted 10 lines
drivers/power/supply/sgm41542_charger.c new file +10
-0+return dev_err_probe (dev,PTR_ERR (sgm->regmap), +"Failed to allocate register map\n" ); + +i2c_set_clientdata (client, sgm); + + ret =sgm4154x_hw_chipid_detect (sgm); +if (ret) +return dev_err_probe (dev, ret,"Unable to read HW ID\n" ); + +device_init_wakeup (dev,1 );
[Severity: Medium]
Is there a missing cleanup step for device_init_wakeup()?
The device is marked as wakeup-capable here, but there doesn't seem to be a corresponding device_init_wakeup(dev, 0) during probe error paths or in a driver remove callback.
Could this leave the system PM subsystem in an inconsistent state if the driver unbinds or the probe fails later?
drivers/power/supply/sgm41542_charger.c line 999
Quoted 3 lines
drivers/power/supply/sgm41542_charger.c new file +3
-0+ + sgm->sgm_monitor_wq =devm_alloc_ordered_workqueue (dev,"sgm-monitor-wq" , +WQ_MEM_RECLAIM |WQ_FREEZABLE );
[Severity: High]
How is the hardware watchdog handled during system suspend?
The workqueue feeding the hardware watchdog is allocated with WQ_FREEZABLE, meaning it stops feeding the watchdog during suspend.
[ ... ]
drivers/power/supply/sgm41542_charger.c line 1061
Quoted 8 lines
drivers/power/supply/sgm41542_charger.c new file +8
-0+static struct i2c_driver sgm4154x_driver = { + .driver = { + .name ="sgm4154x-charger" , + .of_match_table = sgm4154x_of_match, + }, + .probe = sgm4154x_probe, + .id_table = sgm4154x_i2c_ids, +};
Because there are no PM suspend/resume handlers defined in the driver, the hardware watchdog is never disabled before sleep.
If the system sleeps longer than the 40-second watchdog timeout, will the charger IC expire the watchdog and reset all registers (such as charge current and voltage limits) to their hardware defaults?
Upon resume, the frozen workqueue thaws and continues resetting the watchdog, but the custom charging parameters are never re-applied.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
PATCH v7 3/6 dt-bindings: display: panel: Add Anbernic TD4310 panel
In reply to Chris MorganFrom: Chris Morgan <[email protected]>
The panel used by Anbernic in the RG Vita-Pro is a DSI panel based on the TD4310 controller IC. It measures approximately 5.5 inches diagonally and is 1080x1920 in resolution.
--- .../display/panel/anbernic,td4310.yaml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/anbernic,td4310.yaml
Documentation/devicetree/bindings/display/panel/anbernic,td4310.yaml new file +66 -0
@@ -0,0 +1,66 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/anbernic,td4310.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Anbernic TD4310 Based Panels + +maintainers: + - Chris Morgan <[email protected]> + +description: + Anbernic TD4310 Based Panels, such as the RG-Vita-Pro panel + (a 1080x1920 5.5 inch panel). + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + items: + - enum: + - anbernic,panel-vita-pro + - const: anbernic,td4310 + + reg: + maxItems: 1 + + vdd-supply: + description: Panel power supply + +required: + - compatible + - port + - reg + - reset-gpios + - vdd-supply + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "anbernic,panel-vita-pro", "anbernic,td4310"; + reg = <0>; + backlight = <&backlight>; + enable-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + rotation = <270>; + vdd-supply = <&vdd_lcd>; + + port { + endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; + }; + +...
Signature · 1 line
2.43.0
PATCH v7 4/6 drm/panel: anbernic-td4310: Add RG Vita Pro panel
In reply to Chris MorganFrom: Chris Morgan <[email protected]>
The panel used by Anbernic in the RG Vita-Pro is a DSI panel based on the TD4310 controller IC. It measures approximately 5.5 inches diagonally and is 1080x1920 in resolution.
--- drivers/gpu/drm/panel/Kconfig | 10 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-anbernic-td4310.c | 257 ++++++++++++++++++ 3 files changed, 268 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-anbernic-td4310.c
drivers/gpu/drm/panel/Kconfig +10 -0
@@ -17,6 +17,16 @@ config DRM_PANEL_ABT_Y030XX067A Y030XX067A 320x480 3.0" panel as found in the YLM RG-280M, RG-300 and RG-99 handheld gaming consoles. +config DRM_PANEL_ANBERNIC_TD4310 + tristate "Anbernic TD4310 LCD panel" + depends on GPIOLIB && OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here to enable support for Anbernic designed panels with the + TD4310 panel controller such as the ones used on the Anbernic RG + Vita Pro. + config DRM_PANEL_ARM_VERSATILE tristate "ARM Versatile panel driver" depends on OF
drivers/gpu/drm/panel/Makefile +1 -0
@@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DRM_PANEL_ABT_Y030XX067A) += panel-abt-y030xx067a.o +obj-$(CONFIG_DRM_PANEL_ANBERNIC_TD4310) += panel-anbernic-td4310.o obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o obj-$(CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596) += panel-asus-z00t-tm5p5-n35596.o obj-$(CONFIG_DRM_PANEL_AUO_A030JTN01) += panel-auo-a030jtn01.o
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +257 -0
257 lines not on this page · raw message
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH V7 4/6] drm/panel: anbernic-td4310: Add RG Vita Pro panel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Medium] Incorrect power-down sequencing in the error path and unprepare function risks backpowering the…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Incorrect power-down sequencing in the error path and unprepare function risks backpowering the panel.
- [Low] The driver calls devm_drm_panel_add(), which does not exist in the kernel API, causing a build failure. --
commit ab0aaf4898e0640c3a73b98bb981eeb9023b2012
Author: Chris Morgan <[email protected]>
drm/panel: anbernic-td4310: Add RG Vita Pro panel
The panel used by Anbernic in the RG Vita-Pro is a DSI panel based on the TD4310 controller IC. It measures approximately 5.5 inches diagonally and is 1080x1920 in resolution.
Quoted 5 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +0
-0
[ ... ]
Quoted 2 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +2
-0+static int panel_anbernic_td4310_prepare (struct drm_panel *panel) +{
[ ... ]
Quoted 12 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +12
-0+ ret =regulator_enable (ctx->vdd); +if (ret) +return ret; + + ret =gpiod_set_value_cansleep (ctx->enable_gpio,1 ); +if (ret) + goto err_enable; + +if (ctx->panel_info->enable_delay) +mipi_dsi_msleep (&dsi_ctx, ctx->panel_info->enable_delay); + + ret =gpiod_set_value_cansleep (ctx->reset_gpio,1 );
[ ... ]
drivers/gpu/drm/panel/panel-anbernic-td4310.c line 100
Quoted 6 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +6
-0+err_reset: +gpiod_set_value_cansleep (ctx->enable_gpio,0 ); +err_enable: +regulator_disable (ctx->vdd); +return ret; +}
[Severity: Medium]
Does this error path miss asserting the reset gpio before disabling the enable gpio and the vdd regulator?
The power-up sequence enables vdd, asserts the enable gpio, and then cycles the reset gpio. To prevent backpowering or latch-up, shouldn't the shutdown sequence strictly reverse this order by asserting the reset gpio first?
Quoted 5 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +5
-0+ +static int panel_anbernic_td4310_unprepare (struct drm_panel *panel) +{ +struct anbernic_panel_td4310 *ctx =panel_to_anbernic_panel_td4310 (panel); +struct mipi_dsi_device *dsi = ctx->dsi;
drivers/gpu/drm/panel/panel-anbernic-td4310.c line 115
Quoted 10 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +10
-0+struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + +mipi_dsi_dcs_set_display_off_multi (&dsi_ctx); +mipi_dsi_msleep (&dsi_ctx, ctx->panel_info->unprepare_delay); +mipi_dsi_dcs_enter_sleep_mode_multi (&dsi_ctx); +mipi_dsi_msleep (&dsi_ctx, ctx->panel_info->disable_delay); + +gpiod_set_value_cansleep (ctx->enable_gpio,0 ); + +gpiod_set_value_cansleep (ctx->reset_gpio,1 );
[Severity: Medium]
Will this sequence risk backpowering the panel?
By disabling the enable gpio before asserting the reset gpio, it violates the reverse power-up sequence mentioned above. Should the reset gpio be asserted first before turning off the enable gpio?
Quoted 5 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +5
-0+ +regulator_disable (ctx->vdd); + +return 0 ; +}
[ ... ]
Quoted 2 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +2
-0+static int panel_anbernic_td4310_probe (struct mipi_dsi_device *dsi) +{
[ ... ]
drivers/gpu/drm/panel/panel-anbernic-td4310.c line 198
Quoted 9 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +9
-0+ dsi->lanes = ctx->panel_info->lanes; + dsi->format = ctx->panel_info->format; + dsi->mode_flags = ctx->panel_info->mode_flags; + + ret =drm_panel_of_backlight (&ctx->panel); +if (ret) +return ret; + +devm_drm_panel_add (dev, &ctx->panel);
[Severity: Low]
Is this call to devm_drm_panel_add() correct?
The function devm_drm_panel_add() doesn't appear to exist in the DRM panel API (only drm_panel_add() does). Will this result in a build failure?
Quoted 7 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +7
-0+ + ret =devm_mipi_dsi_attach (dev, dsi); +if (ret <0 ) +return dev_err_probe (dev, ret,"Failed to attach to DSI host\n" ); + +return 0 ; +}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
Re: [PATCH V7 4/6] drm/panel: anbernic-td4310: Add RG Vita Pro panel
In reply to Chris MorganQuoted 299 lines · Chris Morgan
From: Chris Morgan <[email protected]>
The panel used by Anbernic in the RG Vita-Pro is a DSI panel based on the TD4310 controller IC. It measures approximately 5.5 inches diagonally and is 1080x1920 in resolution.
Signed-off-by Chris Morgan <[email protected]>--- drivers/gpu/drm/panel/Kconfig | 10 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-anbernic-td4310.c | 257 ++++++++++++++++++ 3 files changed, 268 insertions(+)create mode 100644
drivers/gpu/drm/panel/panel-anbernic-td4310.cdrivers/gpu/drm/panel/Kconfig +10
-0@@ -17,6 +17,16 @@ config DRM_PANEL_ABT_Y030XX067A Y030XX067A 320x480 3.0" panel as found in the YLM RG-280M, RG-300 and RG-99 handheld gaming consoles. +config DRM_PANEL_ANBERNIC_TD4310 + tristate "Anbernic TD4310 LCD panel" + depends on GPIOLIB && OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here to enable support for Anbernic designed panels with the + TD4310 panel controller such as the ones used on the Anbernic RG + Vita Pro. + config DRM_PANEL_ARM_VERSATILE tristate "ARM Versatile panel driver" depends on OFdrivers/gpu/drm/panel/Makefile +1
-0@@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DRM_PANEL_ABT_Y030XX067A) += panel-abt-y030xx067a.o +obj-$(CONFIG_DRM_PANEL_ANBERNIC_TD4310) += panel-anbernic-td4310.o obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o obj-$(CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596) += panel-asus-z00t-tm5p5-n35596.o obj-$(CONFIG_DRM_PANEL_AUO_A030JTN01) += panel-auo-a030jtn01.odrivers/gpu/drm/panel/panel-anbernic-td4310.c new file +247
-0@@ -0,0 +1,257 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Driver for Anbernic panels with TD4310 panel controller. +* +* Copyright (C) 2026 Chris Morgan <[email protected]> +* +*/ + +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h> + +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> + +#include <video/mipi_display.h> + +struct anbernic_panel_td4310_info { +const struct drm_display_mode *display_mode; +u16 width_mm; +u16 height_mm; +u32 bus_flags; +unsigned long mode_flags; +u32 format; +u32 lanes; +u16 prepare_delay; +u16 reset_delay; +u16 init_delay; +u16 enable_delay; +u16 disable_delay; +u16 unprepare_delay; +}; + +struct anbernic_panel_td4310 { +struct device *dev; +struct mipi_dsi_device *dsi; +struct drm_panel panel; +const struct anbernic_panel_td4310_info *panel_info; +struct gpio_desc *reset_gpio; +struct gpio_desc *enable_gpio; +struct regulator *vdd; +enum drm_panel_orientation orientation; +}; + +static inline struct anbernic_panel_td4310 *panel_to_anbernic_panel_td4310 (struct drm_panel *panel) +{ + return container_of(panel, struct anbernic_panel_td4310, panel); +} + +static int panel_anbernic_td4310_prepare (struct drm_panel *panel) +{ +struct anbernic_panel_td4310 *ctx =panel_to_anbernic_panel_td4310 (panel); +struct mipi_dsi_device *dsi = ctx->dsi; +struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; +int ret; + + ret =regulator_enable (ctx->vdd); +if (ret) +return ret; + + ret =gpiod_set_value_cansleep (ctx->enable_gpio,1 ); +if (ret) + goto err_enable; + +if (ctx->panel_info->enable_delay) +mipi_dsi_msleep (&dsi_ctx, ctx->panel_info->enable_delay); + + ret =gpiod_set_value_cansleep (ctx->reset_gpio,1 ); +if (ret) + goto err_reset; + +mipi_dsi_msleep (&dsi_ctx,10 ); + + ret =gpiod_set_value_cansleep (ctx->reset_gpio,0 ); +if (ret) + goto err_reset; + +if (ctx->panel_info->reset_delay) +mipi_dsi_msleep (&dsi_ctx, ctx->panel_info->reset_delay); + +mipi_dsi_dcs_exit_sleep_mode_multi (&dsi_ctx); +mipi_dsi_msleep (&dsi_ctx, ctx->panel_info->prepare_delay); +mipi_dsi_dcs_set_display_on_multi (&dsi_ctx); +mipi_dsi_msleep (&dsi_ctx, ctx->panel_info->prepare_delay); + +if (dsi_ctx.accum_err) { + ret = dsi_ctx.accum_err; + goto err_reset; + } + +return 0 ; + +err_reset: +gpiod_set_value_cansleep (ctx->enable_gpio,0 ); +err_enable: +regulator_disable (ctx->vdd); +return ret; +} + +static int panel_anbernic_td4310_unprepare (struct drm_panel *panel) +{ +struct anbernic_panel_td4310 *ctx =panel_to_anbernic_panel_td4310 (panel); +struct mipi_dsi_device *dsi = ctx->dsi; +struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; + +mipi_dsi_dcs_set_display_off_multi (&dsi_ctx); +mipi_dsi_msleep (&dsi_ctx, ctx->panel_info->unprepare_delay); +mipi_dsi_dcs_enter_sleep_mode_multi (&dsi_ctx); +mipi_dsi_msleep (&dsi_ctx, ctx->panel_info->disable_delay); + +gpiod_set_value_cansleep (ctx->enable_gpio,0 ); + +gpiod_set_value_cansleep (ctx->reset_gpio,1 ); + +regulator_disable (ctx->vdd); + +return 0 ; +} + +static int panel_anbernic_td4310_get_mode (struct drm_panel *panel, +struct drm_connector *connector) +{ +struct anbernic_panel_td4310 *ctx =panel_to_anbernic_panel_td4310 (panel); +const struct anbernic_panel_td4310_info *panel_info = ctx->panel_info; + + connector->display_info.bpc =8 ; + connector->display_info.width_mm = panel_info->width_mm; + connector->display_info.height_mm = panel_info->height_mm; + connector->display_info.bus_flags = panel_info->bus_flags; + +return drm_connector_helper_get_modes_fixed (connector, panel_info->display_mode); +} + +static enum drm_panel_orientation panel_anbernic_td4310_get_orientation (struct drm_panel *panel) +{ +struct anbernic_panel_td4310 *ctx =panel_to_anbernic_panel_td4310 (panel); + +return ctx->orientation; +} + +static const struct drm_panel_funcs panel_anbernic_td4310_funcs = { + .prepare = panel_anbernic_td4310_prepare, + .unprepare = panel_anbernic_td4310_unprepare, + .get_modes = panel_anbernic_td4310_get_mode, + .get_orientation = panel_anbernic_td4310_get_orientation, +}; + +static int panel_anbernic_td4310_probe (struct mipi_dsi_device *dsi) +{ +struct device *dev = &dsi->dev; +struct anbernic_panel_td4310 *ctx; +int ret; + + ctx = devm_drm_panel_alloc(dev, struct anbernic_panel_td4310, panel, + &panel_anbernic_td4310_funcs, +DRM_MODE_CONNECTOR_DSI ); +if (IS_ERR (ctx)) +return PTR_ERR (ctx); + + ctx->dev = dev; + + ctx->panel_info =of_device_get_match_data (dev); +if (!ctx->panel_info) +return -EINVAL ; + + ret =of_drm_get_panel_orientation (dev->of_node, &ctx->orientation); +if (ret <0 ) +return dev_err_probe (dev, ret,"Failed to get panel orientation\n" ); + + ctx->reset_gpio =devm_gpiod_get (dev,"reset" ,GPIOD_OUT_LOW ); +if (IS_ERR (ctx->reset_gpio)) +return dev_err_probe (dev,PTR_ERR (ctx->reset_gpio), +"Cannot get reset gpio\n" ); + + ctx->enable_gpio =devm_gpiod_get_optional (dev,"enable" ,GPIOD_OUT_LOW ); +if (IS_ERR (ctx->enable_gpio)) +return dev_err_probe (dev,PTR_ERR (ctx->enable_gpio), +"Cannot get enable gpio\n" ); + + ctx->vdd =devm_regulator_get (dev,"vdd" ); +if (IS_ERR (ctx->vdd)) +return dev_err_probe (dev,PTR_ERR (ctx->vdd), +"Failed to request vdd regulator\n" ); + + ctx->dsi = dsi; +mipi_dsi_set_drvdata (dsi, ctx); + + dsi->lanes = ctx->panel_info->lanes; + dsi->format = ctx->panel_info->format; + dsi->mode_flags = ctx->panel_info->mode_flags; + + ret =drm_panel_of_backlight (&ctx->panel); +if (ret) +return ret; + +devm_drm_panel_add (dev, &ctx->panel); + + ret =devm_mipi_dsi_attach (dev, dsi); +if (ret <0 ) +return dev_err_probe (dev, ret,"Failed to attach to DSI host\n" ); + +return 0 ; +} + +static const struct drm_display_mode anbernic_vitapro_mode = { + .clock =140020 , + .hdisplay =1080 , + .hsync_start =1080 +50 , + .hsync_end =1080 +50 +4 , + .htotal =1080 +50 +4 +50 , + .vdisplay =1920 , + .vsync_start =1920 +15 , + .vsync_end =1920 +15 +4 , + .vtotal =1920 +15 +4 +32 , + .flags =DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_NVSYNC , +}; + +static const struct anbernic_panel_td4310_info anbernic_vitapro_info = { + .display_mode = &anbernic_vitapro_mode, + .width_mm =69 , + .height_mm =121 , + .bus_flags =DRM_BUS_FLAG_DE_LOW |DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE , + .mode_flags =MIPI_DSI_MODE_VIDEO |MIPI_DSI_MODE_VIDEO_BURST | +MIPI_DSI_MODE_LPM |MIPI_DSI_MODE_NO_EOT_PACKET | +MIPI_DSI_CLOCK_NON_CONTINUOUS , + .format =MIPI_DSI_FMT_RGB888 , + .lanes =4 , + .prepare_delay =50 , + .reset_delay =220 , + .enable_delay =120 , + .disable_delay =50 , + .unprepare_delay =20 , +}; + +static const struct of_device_id panel_anbernic_td4310_of_match[] = { + { + .compatible ="anbernic,panel-vita-pro" , + .data = &anbernic_vitapro_info, + }, + { } +}; +MODULE_DEVICE_TABLE (of, panel_anbernic_td4310_of_match); + +static struct mipi_dsi_driver anbernic_panel_td4310_driver = { + .driver = {
drivers/gpu/drm/panel/panel-anbernic-td4310.c line 257
Quoted 10 lines
drivers/gpu/drm/panel/panel-anbernic-td4310.c new file +10
-0+ .name = "panel-anbernic-td4310", + .of_match_table = panel_anbernic_td4310_of_match, + }, + .probe = panel_anbernic_td4310_probe, +}; +module_mipi_dsi_driver (anbernic_panel_td4310_driver); + +MODULE_AUTHOR ("Chris Morgan <[email protected]>" ); +MODULE_DESCRIPTION ("DRM driver for Anbernic TD4310 MIPI DSI panels" ); +MODULE_LICENSE ("GPL" );
Thanks,
Neil
PATCH v7 5/6 dt-bindings: arm: rockchip: Add Anbernic RG Vita-Pro
In reply to Chris MorganFrom: Chris Morgan <[email protected]>
Add compatible string for the Anbernic RG Vita-Pro.
--- Documentation/devicetree/bindings/arm/rockchip.yaml | 6 ++++++ 1 file changed, 6 insertions(+)
Documentation/devicetree/bindings/arm/rockchip.yaml +6 -0
@@ -66,6 +66,12 @@ properties: - anbernic,rg-ds - const: rockchip,rk3568 + - description: Anbernic RK3576 Handheld Gaming Console + items: + - enum: + - anbernic,rg-vita-pro + - const: rockchip,rk3576 + - description: Ariaboard Photonicat items: - const: ariaboard,photonicat
Signature · 1 line
2.43.0
PATCH v7 6/6 arm64: dts: rockchip: Add Anbernic RG Vita-Pro
In reply to Chris MorganFrom: Chris Morgan <[email protected]>
Add device tree for the Anbernic RG Vita-Pro, based on the Rockchip RK3576. All hardware is currently working except for the accelerometer, the touchscreen, the battery monitor, and DisplayPort over USB-C. PWM is also missing currently, and as a result the LEDs and panel backlight are currently controlled via GPIO but will be changed to PWM once supported.
The Anbernic RG Vita-Pro includes the following hardware:
- A 1080x1920 DSI display with touch.
- 21 buttons.
- 3 LEDs.
- 64GB eMMC, 2 SDMMC slots.
- RTL8852BE WiFi (with Bluetooth via UART)
- 1 USB 3.0 USB-C port in OTG mode.
- 3.5mm headphone jack with play button support.
- 5000mAH battery
The following hardware has incomplete driver support and is not yet working:
- An Invensense icm42607p accelerometer.
- A Cellwise cw221x battery monitor.
- A Synaptics i2c touchscreen.
- DisplayPort over USB-C alt-mode.
- PWM controller.
- 2 Analog joysticks with LED controllers.
--- arch/arm64/boot/dts/rockchip/Makefile | 1 + .../rockchip/rk3576-anbernic-rg-vita-pro.dts | 1327 +++++++++++++++++ 2 files changed, 1328 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3576-anbernic-rg-vita-pro.dts
arch/arm64/boot/dts/rockchip/Makefile +1 -0
@@ -165,6 +165,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5-display-vz.dtbo dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5-io-expander.dtbo dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-100ask-dshanpi-a1.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-anbernic-rg-vita-pro.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-armsom-sige5.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-armsom-sige5-v1.2-wifibt.dtbo dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-evb1-v10.dtb
arch/arm64/boot/dts/rockchip/rk3576-anbernic-rg-vita-pro.dts new file +1327 -0
1,327 lines not on this page · raw message
Signature · 1 line
2.43.0
Re: (subset) [PATCH V7 0/6] Add Anbernic RG Vita-Pro
In reply to Chris MorganHi,
Quoted 34 lines · Chris Morgan
From: Chris Morgan <[email protected]>
Add support for the Anbernic RG Vita-Pro, based on the Rockchip RK3576 SoC.
Changes Since V1:
- Updated documentation filename to matche compatible string.
- Corrected order of allocating IRQ in charger driver and switched to using devm managed function to allocate work queue.
Changes Since V2:
- Corrected issue with naming of panel binding document and added fallback compatible string.
- Switched to devm helpers in panel driver. Note thatdevm_drm_panel_add()is currently only in the drm-next branch.
- Optimized setting GPIOs for panel driver.
Changes Since V3:
- Fixed numerous issues identifed by Sashiko bot, mainly relating to unclamped or improperly clamped values from within the charger driver.
- Corrected hard-coded values in the panel driver unprepare routine as well as correcting an improperly checked return condition.
Changes Since V4:
- Fixed errors identified by Sashiko bot on charger driver that could result in an improper value being written to the registers.
- Corrected some error handling in the panel driver.
Changes Since V5:
- Corrected minor errors in documentation and added default values.
- Further corrected clamping behavior in charger driver.
Changes Since V6:
- Additional corrections as suggested by Sashiko bot to fix potential edge cases during probe for sgm41542.
- Corrected an improperly shifted value being written to register for sgm41542.
- Changed a MV value to UV in sgm41542 driver to simplify function.
Quoted 1 line
[...]
Thanks, Applied to https://gitlab.freedesktop.org/drm/misc/kernel.git (drm-misc-next)
[3/6] dt-bindings: display: panel: Add Anbernic TD4310 panel
https://gitlab.freedesktop.org/drm/misc/kernel/-/commit/0fd6ead8270270d859a28d0196a4b47e7d6845b8 [4/6] drm/panel: anbernic-td4310: Add RG Vita Pro panel https://gitlab.freedesktop.org/drm/misc/kernel/-/commit/a81b4fe69e7bd2667524182e76c635f04c1ead7e
Signature · 1 line
Neil