Add Inanbo T28CP45TN89 panel support
Subsystems (4)
v2 cover Add Inanbo T28CP45TN89 panel support
Hi,
This adds panel support for Inanbo T28CP45TN89, which I found inside of a handheld thermal camera. The panel is based on the st7789v controller. All information is based on reverse engineering.
Changes since PATCHv1:
* https://lore.kernel.org/all/[email protected]/
* Apply DT binding changes requested by Krzysztof Kozlowski and his Ack
* I changed the driver patches to avoid code duplication and splitted the code a bit more
-- Sebastian
Sebastian Reichel (13):
dt-bindings: vendor-prefixes: add Inanbo
dt-bindings: display: st7789v: add Inanbo T28CP45TN89 drm/panel: sitronix-st7789v: add SPI ID table drm/panel: sitronix-st7789v: remove unused constants drm/panel: sitronix-st7789v: make reset GPIO optional drm/panel: sitronix-st7789v: simplify st7789v_spi_write drm/panel: sitronix-st7789v: improve error handling drm/panel: sitronix-st7789v: avoid hardcoding mode info drm/panel: sitronix-st7789v: avoid hardcoding panel size drm/panel: sitronix-st7789v: add media bus format drm/panel: sitronix-st7789v: avoid hardcoding invert mode drm/panel: sitronix-st7789v: avoid hardcoding polarity info drm/panel: sitronix-st7789v: add Inanbo T28CP45TN89 support
.../display/panel/sitronix,st7789v.yaml | 5 +- .../devicetree/bindings/vendor-prefixes.yaml | 2 + .../gpu/drm/panel/panel-sitronix-st7789v.c | 148 ++++++++++++++---- 3 files changed, 120 insertions(+), 35 deletions(-)
Signature · 1 line
2.39.2
PATCH v2 1/13 dt-bindings: vendor-prefixes: add Inanbo
Shenzhen INANBO Electronic Technology Co., Ltd. manufacturers TFT/OLED LCD panels.
--- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+)
Documentation/devicetree/bindings/vendor-prefixes.yaml +2 -0
@@ -609,6 +609,8 @@ patternProperties: description: Imagination Technologies Ltd. "^imi,.*": description: Integrated Micro-Electronics Inc. + "^inanbo,.*": + description: Shenzhen INANBO Electronic Technology Co., Ltd. "^incircuit,.*": description: In-Circuit GmbH "^inet-tek,.*":
Signature · 1 line
2.39.2
PATCH v2 2/13 dt-bindings: display: st7789v: add Inanbo T28CP45TN89
In reply to Sebastian ReichelAdd compatible value for Inanbo t28cp45tn89 and make reset GPIO non mandatory, since it might not be connected to the CPU.
--- .../devicetree/bindings/display/panel/sitronix,st7789v.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml +3 -2
@@ -15,7 +15,9 @@ allOf: properties: compatible: - const: sitronix,st7789v + enum: + - inanbo,t28cp45tn89-v17 + - sitronix,st7789v reg: true reset-gpios: true
@@ -29,7 +31,6 @@ properties: required: - compatible - reg - - reset-gpios - power-supply unevaluatedProperties: false
Signature · 1 line
2.39.2
Re: [PATCH v2 02/13] dt-bindings: display: st7789v: add Inanbo T28CP45TN89
Quoted 8 lines · Sebastian Reichel
Add compatible value for Inanbo t28cp45tn89 and make reset GPIO non mandatory, since it might not be connected to the CPU.
Signed-off-by Sebastian Reichel <[email protected]>--- .../devicetree/bindings/display/panel/sitronix,st7789v.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
PATCH v2 3/13 drm/panel: sitronix-st7789v: add SPI ID table
In reply to Sebastian ReichelSPI device drivers should also have a SPI ID table.
--- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +7 -0
@@ -394,6 +394,12 @@ static void st7789v_remove(struct spi_device *spi)drm_panel_remove (&ctx->panel); } +static const struct spi_device_id st7789v_spi_id[] = { + {"st7789v" }, + { } +}; +MODULE_DEVICE_TABLE (spi, st7789v_spi_id); +static const struct of_device_id st7789v_of_match[] = { { .compatible ="sitronix,st7789v" }, { }
@@ -403,6 +409,7 @@ MODULE_DEVICE_TABLE(of, st7789v_of_match);static struct spi_driver st7789v_driver = { .probe = st7789v_probe, .remove = st7789v_remove, + .id_table = st7789v_spi_id, .driver = { .name ="st7789v" , .of_match_table = st7789v_of_match,
Signature · 1 line
2.39.2
PATCH v2 4/13 drm/panel: sitronix-st7789v: remove unused constants
In reply to Sebastian ReichelST7789V_COLMOD_RGB_FMT_18BITS and ST7789V_COLMOD_CTRL_FMT_18BITS are unused in favour of MIPI_DCS_PIXEL_FMT_18BIT, remove them.
--- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 3 --- 1 file changed, 3 deletions(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +0 -3
@@ -15,9 +15,6 @@#include <drm/drm_modes.h> #include <drm/drm_panel.h> -#define ST7789V_COLMOD_RGB_FMT_18BITS (6 << 4) -#define ST7789V_COLMOD_CTRL_FMT_18BITS (6 << 0) -#define ST7789V_RAMCTRL_CMD 0xb0#define ST7789V_RAMCTRL_RM_RGB BIT(4)#define ST7789V_RAMCTRL_DM_RGB BIT(0)
Signature · 1 line
2.39.2
PATCH v2 5/13 drm/panel: sitronix-st7789v: make reset GPIO optional
In reply to Sebastian ReichelThe reset pin might not be software controllable from the SoC, so make it optional.
--- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +1 -1
@@ -369,7 +369,7 @@ static int st7789v_probe(struct spi_device *spi)if (IS_ERR (ctx->power))return PTR_ERR (ctx->power); - ctx->reset =devm_gpiod_get (&spi->dev,"reset" ,GPIOD_OUT_LOW ); + ctx->reset =devm_gpiod_get_optional (&spi->dev,"reset" ,GPIOD_OUT_LOW );if (IS_ERR (ctx->reset)) {dev_err (&spi->dev,"Couldn't get our reset line\n" );return PTR_ERR (ctx->reset);
Signature · 1 line
2.39.2
PATCH v2 6/13 drm/panel: sitronix-st7789v: simplify st7789v_spi_write
In reply to Sebastian Reichelst7789v_spi_write initializes a message with just
a single transfer, spi_sync_transfer can be used
for that.
--- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +1 -5
@@ -129,17 +129,13 @@ static int st7789v_spi_write(struct st7789v *ctx, enum st7789v_prefix prefix, u8 data) {struct spi_transfer xfer = { }; -struct spi_message msg;u16 txbuf = ((prefix &1 ) <<8 ) | data; -spi_message_init (&msg); - xfer.tx_buf = &txbuf; xfer.bits_per_word =9 ; xfer.len =sizeof (txbuf); -spi_message_add_tail (&xfer, &msg); -return spi_sync (ctx->spi, &msg); +return spi_sync_transfer (ctx->spi, &xfer,1 ); }static int st7789v_write_command (struct st7789v *ctx,u8 cmd)
Signature · 1 line
2.39.2
PATCH v2 7/13 drm/panel: sitronix-st7789v: improve error handling
In reply to Sebastian ReichelImprove error handling in the probe routine, so that probe defer errors are captured in /sys/kernel/debug/devices_deferred
--- .../gpu/drm/panel/panel-sitronix-st7789v.c | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +12 -11
@@ -348,32 +348,33 @@ static const struct drm_panel_funcs st7789v_drm_funcs = {static int st7789v_probe (struct spi_device *spi) { +struct device *dev = &spi->dev;struct st7789v *ctx;int ret; - ctx =devm_kzalloc (&spi->dev,sizeof (*ctx),GFP_KERNEL ); + ctx =devm_kzalloc (dev,sizeof (*ctx),GFP_KERNEL );if (!ctx)return -ENOMEM ;spi_set_drvdata (spi, ctx); ctx->spi = spi; -drm_panel_init (&ctx->panel, &spi->dev, &st7789v_drm_funcs, +drm_panel_init (&ctx->panel, dev, &st7789v_drm_funcs,DRM_MODE_CONNECTOR_DPI ); - ctx->power =devm_regulator_get (&spi->dev,"power" ); -if (IS_ERR (ctx->power)) -return PTR_ERR (ctx->power); + ctx->power =devm_regulator_get (dev,"power" ); + ret =PTR_ERR_OR_ZERO (ctx->power); +if (ret) +return dev_err_probe (dev, ret,"Failed to get regulator\n" ); - ctx->reset =devm_gpiod_get_optional (&spi->dev,"reset" ,GPIOD_OUT_LOW ); -if (IS_ERR (ctx->reset)) { -dev_err (&spi->dev,"Couldn't get our reset line\n" ); -return PTR_ERR (ctx->reset); - } + ctx->reset =devm_gpiod_get_optional (dev,"reset" ,GPIOD_OUT_LOW ); + ret =PTR_ERR_OR_ZERO (ctx->reset); +if (ret) +return dev_err_probe (dev, ret,"Failed to get reset line\n" ); ret =drm_panel_of_backlight (&ctx->panel);if (ret) -return ret; +return dev_err_probe (dev, ret,"Failed to get backlight\n" );drm_panel_add (&ctx->panel);
Signature · 1 line
2.39.2
PATCH v2 8/13 drm/panel: sitronix-st7789v: avoid hardcoding mode info
In reply to Sebastian ReichelAvoid hard-coding the default_mode and supply it from match data. One additional layer of abstraction has been introduced, which will be needed for specifying other panel information (e.g. bus flags) in the next steps.
--- .../gpu/drm/panel/panel-sitronix-st7789v.c | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +18 -6
@@ -108,8 +108,13 @@return val; \ }while (0 ) +struct st7789_panel_info { +const struct drm_display_mode *mode; +}; +struct st7789v {struct drm_panel panel; +const struct st7789_panel_info *info;struct spi_device *spi;struct gpio_desc *reset;struct regulator *power;
@@ -160,16 +165,21 @@ static const struct drm_display_mode default_mode = { .vtotal = 320 + 8 + 4 + 4, }; +struct st7789_panel_info default_panel = { + .mode = &default_mode, +}; +static int st7789v_get_modes (struct drm_panel *panel,struct drm_connector *connector) { +struct st7789v *ctx =panel_to_st7789v (panel);struct drm_display_mode *mode; - mode =drm_mode_duplicate (connector->dev, &default_mode); + mode =drm_mode_duplicate (connector->dev, ctx->info->mode);if (!mode) { -dev_err (panel->dev,"failed to add mode %ux%ux@%u\n" , - default_mode.hdisplay, default_mode.vdisplay, -drm_mode_vrefresh (&default_mode)); +dev_err (panel->dev,"failed to add mode %ux%u@%u\n" , + ctx->info->mode->hdisplay, ctx->info->mode->vdisplay, +drm_mode_vrefresh (ctx->info->mode));return -ENOMEM ; }
@@ -359,6 +369,8 @@ static int st7789v_probe(struct spi_device *spi)spi_set_drvdata (spi, ctx); ctx->spi = spi; + ctx->info =device_get_match_data (&spi->dev); +drm_panel_init (&ctx->panel, dev, &st7789v_drm_funcs,DRM_MODE_CONNECTOR_DPI );
@@ -389,13 +401,13 @@ static void st7789v_remove(struct spi_device *spi) }static const struct spi_device_id st7789v_spi_id[] = { - {"st7789v" }, + {"st7789v" , (unsigned long ) &default_panel }, { } };MODULE_DEVICE_TABLE (spi, st7789v_spi_id);static const struct of_device_id st7789v_of_match[] = { - { .compatible ="sitronix,st7789v" }, + { .compatible ="sitronix,st7789v" , .data = &default_panel }, { } };MODULE_DEVICE_TABLE (of, st7789v_of_match);
Signature · 1 line
2.39.2
Re: [PATCH v2 08/13] drm/panel: sitronix-st7789v: avoid hardcoding mode info
Hi Sebastian,
Thanks for the v2 of your series. Looks great!
One nitpick though: you seem to wrap the patch message lines at ~50 characters sometimes, which is awfully short.
Another comment below:
Quoted 29 lines · Sebastian Reichel
Avoid hard-coding the
default_modeand supply it from match data. One additional layer of abstraction has been introduced, which will be needed for specifying other panel information (e.g. bus flags) in the next steps.Signed-off-by Sebastian Reichel <[email protected]>--- .../gpu/drm/panel/panel-sitronix-st7789v.c | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-)drivers/gpu/drm/panel/panel-sitronix-st7789v.c +5
-0@@ -108,8 +108,13 @@return val; \ }while (0 ) +struct st7789_panel_info { +const struct drm_display_mode *mode; +}; +struct st7789v {struct drm_panel panel; +const struct st7789_panel_info *info;struct spi_device *spi;struct gpio_desc *reset;struct regulator *power;
drivers/gpu/drm/panel/panel-sitronix-st7789v.c static const struct drm_display_mode default_mode = { · line 170
Quoted 6 lines
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +3
-0@@ -160,16 +165,21 @@ static const struct drm_display_mode default_mode = { .vtotal = 320 + 8 + 4 + 4, }; +struct st7789_panel_info default_panel = { + .mode = &default_mode, +};
Shouldn't this be "static const struct st7789_panel_info default_panel"?
(Same holds for "struct st7789_panel_info t28cp45tn89_panel" in patch 13/13.)
With the comments above addressed, feel free to add my
to the whole v3 of your series.
Thanks and best regards,
Michael
Quoted 44 lines
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +10
-6+static int st7789v_get_modes (struct drm_panel *panel,struct drm_connector *connector) { +struct st7789v *ctx =panel_to_st7789v (panel);struct drm_display_mode *mode; - mode =drm_mode_duplicate (connector->dev, &default_mode); + mode =drm_mode_duplicate (connector->dev, ctx->info->mode);if (!mode) { -dev_err (panel->dev,"failed to add mode %ux%ux@%u\n" , - default_mode.hdisplay, default_mode.vdisplay, -drm_mode_vrefresh (&default_mode)); +dev_err (panel->dev,"failed to add mode %ux%u@%u\n" , + ctx->info->mode->hdisplay, ctx->info->mode->vdisplay, +drm_mode_vrefresh (ctx->info->mode));return -ENOMEM ; }@@ -359,6 +369,8 @@ static int st7789v_probe(struct spi_device *spi)spi_set_drvdata (spi, ctx); ctx->spi = spi; + ctx->info =device_get_match_data (&spi->dev); +drm_panel_init (&ctx->panel, dev, &st7789v_drm_funcs,DRM_MODE_CONNECTOR_DPI );@@ -389,13 +401,13 @@ static void st7789v_remove(struct spi_device *spi) }static const struct spi_device_id st7789v_spi_id[] = { - {"st7789v" }, + {"st7789v" , (unsigned long ) &default_panel }, { } };MODULE_DEVICE_TABLE (spi, st7789v_spi_id);static const struct of_device_id st7789v_of_match[] = { - { .compatible ="sitronix,st7789v" }, + { .compatible ="sitronix,st7789v" , .data = &default_panel }, { } };MODULE_DEVICE_TABLE (of, st7789v_of_match);
PATCH v2 9/13 drm/panel: sitronix-st7789v: avoid hardcoding panel size
In reply to Sebastian ReichelMove the panel size information to the mode struct, so that different panel sizes can be specified depending on the panel type.
--- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +4 -2
@@ -163,6 +163,8 @@ static const struct drm_display_mode default_mode = { .vsync_start = 320 + 8, .vsync_end = 320 + 8 + 4, .vtotal = 320 + 8 + 4 + 4, + .width_mm = 61, + .height_mm = 103, };struct st7789_panel_info default_panel = {
@@ -188,8 +190,8 @@ static int st7789v_get_modes(struct drm_panel *panel, mode->type =DRM_MODE_TYPE_DRIVER |DRM_MODE_TYPE_PREFERRED ;drm_mode_probed_add (connector, mode); - connector->display_info.width_mm =61 ; - connector->display_info.height_mm =103 ; + connector->display_info.width_mm = ctx->info->mode->width_mm; + connector->display_info.height_mm = ctx->info->mode->height_mm;return 1 ; }
Signature · 1 line
2.39.2
PATCH v2 10/13 drm/panel: sitronix-st7789v: add media bus format
In reply to Sebastian ReichelAdd support for describing the media bus format in the panel configuration and expose that to userspace. Since both supported formats (RGB565 and RGB666) are using 6 bits per color also hardcode that information.
--- .../gpu/drm/panel/panel-sitronix-st7789v.c | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +23 -3
@@ -10,6 +10,7 @@#include <linux/spi/spi.h> #include <video/mipi_display.h> +#include <linux/media-bus-format.h> #include <drm/drm_device.h> #include <drm/drm_modes.h>
@@ -110,6 +111,7 @@struct st7789_panel_info {const struct drm_display_mode *mode; +u32 bus_format; };struct st7789v {
@@ -169,6 +171,7 @@ static const struct drm_display_mode default_mode = {struct st7789_panel_info default_panel = { .mode = &default_mode, + .bus_format =MEDIA_BUS_FMT_RGB666_1X18 , }; static int st7789v_get_modes(struct drm_panel *panel,
@@ -190,8 +193,11 @@ static int st7789v_get_modes(struct drm_panel *panel, mode->type =DRM_MODE_TYPE_DRIVER |DRM_MODE_TYPE_PREFERRED ;drm_mode_probed_add (connector, mode); + connector->display_info.bpc =6 ; connector->display_info.width_mm = ctx->info->mode->width_mm; connector->display_info.height_mm = ctx->info->mode->height_mm; +drm_display_info_set_bus_formats (&connector->display_info, + &ctx->info->bus_format,1 );return 1 ; }
@@ -199,8 +205,24 @@ static int st7789v_get_modes(struct drm_panel *panel,static int st7789v_prepare (struct drm_panel *panel) {struct st7789v *ctx =panel_to_st7789v (panel); +u8 pixel_fmt;int ret; +switch (ctx->info->bus_format) { +case MEDIA_BUS_FMT_RGB666_1X18 : + pixel_fmt =MIPI_DCS_PIXEL_FMT_18BIT ; +break ; +case MEDIA_BUS_FMT_RGB565_1X16 : + pixel_fmt =MIPI_DCS_PIXEL_FMT_16BIT ; +break ; +default : +dev_err (panel->dev,"unsupported bus format: %d\n" , + ctx->info->bus_format); +return -EINVAL ; + } + + pixel_fmt = (pixel_fmt <<4 ) | pixel_fmt; + ret =regulator_enable (ctx->power);if (ret)return ret;
@@ -221,9 +243,7 @@ static int st7789v_prepare(struct drm_panel *panel)ST7789V_TEST (ret,st7789v_write_command (ctx,MIPI_DCS_SET_PIXEL_FORMAT )); -ST7789V_TEST (ret,st7789v_write_data (ctx, - (MIPI_DCS_PIXEL_FMT_18BIT <<4 ) | - (MIPI_DCS_PIXEL_FMT_18BIT ))); +ST7789V_TEST (ret,st7789v_write_data (ctx, pixel_fmt));ST7789V_TEST (ret,st7789v_write_command (ctx,ST7789V_PORCTRL_CMD ));ST7789V_TEST (ret,st7789v_write_data (ctx,0xc ));
Signature · 1 line
2.39.2
PATCH v2 11/13 drm/panel: sitronix-st7789v: avoid hardcoding invert mode
In reply to Sebastian ReichelWhile the default panel uses invert mode, some panels require non-invert mode instead.
--- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +9 -1
@@ -112,6 +112,7 @@struct st7789_panel_info {const struct drm_display_mode *mode;u32 bus_format; +bool invert_mode; };struct st7789v {
@@ -171,6 +172,7 @@ static const struct drm_display_mode default_mode = {struct st7789_panel_info default_panel = { .mode = &default_mode, + .invert_mode = true, .bus_format =MEDIA_BUS_FMT_RGB666_1X18 , };
@@ -321,7 +323,13 @@ static int st7789v_prepare(struct drm_panel *panel)ST7789V_TEST (ret,st7789v_write_data (ctx,ST7789V_NVGAMCTRL_VN61 (0x1b )));ST7789V_TEST (ret,st7789v_write_data (ctx,ST7789V_NVGAMCTRL_VN62 (0x28 ))); -ST7789V_TEST (ret,st7789v_write_command (ctx,MIPI_DCS_ENTER_INVERT_MODE )); +if (ctx->info->invert_mode) { +ST7789V_TEST (ret,st7789v_write_command (ctx, +MIPI_DCS_ENTER_INVERT_MODE )); + }else { +ST7789V_TEST (ret,st7789v_write_command (ctx, +MIPI_DCS_EXIT_INVERT_MODE )); + }ST7789V_TEST (ret,st7789v_write_command (ctx,ST7789V_RAMCTRL_CMD )); ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RAMCTRL_DM_RGB |
Signature · 1 line
2.39.2
PATCH v2 12/13 drm/panel: sitronix-st7789v: avoid hardcoding polarity info
In reply to Sebastian ReichelAdd polarity information via mode and bus flags, so that they are no longer hardcoded and forward the information to the DRM stack. This is required for adding panels with different settings.
--- .../gpu/drm/panel/panel-sitronix-st7789v.c | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +18 -4
@@ -28,6 +28,7 @@#define ST7789V_RGBCTRL_VSYNC_HIGH BIT(3)#define ST7789V_RGBCTRL_HSYNC_HIGH BIT(2)#define ST7789V_RGBCTRL_PCLK_HIGH BIT(1) +#define ST7789V_RGBCTRL_DE_LOW BIT(0)#define ST7789V_RGBCTRL_VBP (n) ((n) & 0x7f)#define ST7789V_RGBCTRL_HBP (n) ((n) & 0x1f)
@@ -112,6 +113,7 @@struct st7789_panel_info {const struct drm_display_mode *mode;u32 bus_format; +u32 bus_flags;bool invert_mode; };
@@ -168,12 +170,15 @@ static const struct drm_display_mode default_mode = { .vtotal = 320 + 8 + 4 + 4, .width_mm = 61, .height_mm = 103, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, };struct st7789_panel_info default_panel = { .mode = &default_mode, .invert_mode = true, .bus_format =MEDIA_BUS_FMT_RGB666_1X18 , + .bus_flags =DRM_BUS_FLAG_DE_HIGH | +DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE , }; static int st7789v_get_modes(struct drm_panel *panel,
@@ -198,6 +203,7 @@ static int st7789v_get_modes(struct drm_panel *panel, connector->display_info.bpc =6 ; connector->display_info.width_mm = ctx->info->mode->width_mm; connector->display_info.height_mm = ctx->info->mode->height_mm; + connector->display_info.bus_flags = ctx->info->bus_flags;drm_display_info_set_bus_formats (&connector->display_info, &ctx->info->bus_format,1 );
@@ -207,7 +213,7 @@ static int st7789v_get_modes(struct drm_panel *panel,static int st7789v_prepare (struct drm_panel *panel) {struct st7789v *ctx =panel_to_st7789v (panel); -u8 pixel_fmt; +u8 pixel_fmt, polarity;int ret;switch (ctx->info->bus_format) {
@@ -225,6 +231,16 @@ static int st7789v_prepare(struct drm_panel *panel) pixel_fmt = (pixel_fmt <<4 ) | pixel_fmt; + polarity =0 ; +if (ctx->info->mode->flags &DRM_MODE_FLAG_PVSYNC ) + polarity |=ST7789V_RGBCTRL_VSYNC_HIGH ; +if (ctx->info->mode->flags &DRM_MODE_FLAG_PHSYNC ) + polarity |=ST7789V_RGBCTRL_HSYNC_HIGH ; +if (ctx->info->bus_flags &DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE ) + polarity |=ST7789V_RGBCTRL_PCLK_HIGH ; +if (ctx->info->bus_flags &DRM_BUS_FLAG_DE_LOW ) + polarity |=ST7789V_RGBCTRL_DE_LOW ; + ret =regulator_enable (ctx->power);if (ret)return ret;
@@ -340,9 +356,7 @@ static int st7789v_prepare(struct drm_panel *panel)ST7789V_TEST (ret,st7789v_write_command (ctx,ST7789V_RGBCTRL_CMD ));ST7789V_TEST (ret,st7789v_write_data (ctx,ST7789V_RGBCTRL_WO |ST7789V_RGBCTRL_RCM (2 ) | -ST7789V_RGBCTRL_VSYNC_HIGH | -ST7789V_RGBCTRL_HSYNC_HIGH | -ST7789V_RGBCTRL_PCLK_HIGH )); + polarity));ST7789V_TEST (ret,st7789v_write_data (ctx,ST7789V_RGBCTRL_VBP (8 )));ST7789V_TEST (ret,st7789v_write_data (ctx,ST7789V_RGBCTRL_HBP (20 )));
Signature · 1 line
2.39.2
PATCH v2 13/13 drm/panel: sitronix-st7789v: add Inanbo T28CP45TN89 support
In reply to Sebastian ReichelUNI-T UTi260b has a Inanbo T28CP45TN89 v17 panel. I could not find proper documentation for the panel apart from a technical drawing, but according to the vendor U-Boot it is based on a Sitronix st7789v chip. I generated the init sequence by modifying the default one until proper graphics output has been seen on the device.
--- .../gpu/drm/panel/panel-sitronix-st7789v.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +25 -0
@@ -173,6 +173,21 @@ static const struct drm_display_mode default_mode = { .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, }; +static const struct drm_display_mode t28cp45tn89_mode = { + .clock =6008 , + .hdisplay =240 , + .hsync_start =240 +38 , + .hsync_end =240 +38 +10 , + .htotal =240 +38 +10 +10 , + .vdisplay =320 , + .vsync_start =320 +8 , + .vsync_end =320 +8 +4 , + .vtotal =320 +8 +4 +4 , + .width_mm =43 , + .height_mm =57 , + .flags =DRM_MODE_FLAG_PVSYNC |DRM_MODE_FLAG_NVSYNC , +}; +struct st7789_panel_info default_panel = { .mode = &default_mode, .invert_mode = true,
@@ -181,6 +196,14 @@ struct st7789_panel_info default_panel = { DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE, }; +struct st7789_panel_info t28cp45tn89_panel = { + .mode = &t28cp45tn89_mode, + .invert_mode = false, + .bus_format =MEDIA_BUS_FMT_RGB565_1X16 , + .bus_flags =DRM_BUS_FLAG_DE_HIGH | +DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE , +}; +static int st7789v_get_modes (struct drm_panel *panel,struct drm_connector *connector) {
@@ -446,12 +469,14 @@ static void st7789v_remove(struct spi_device *spi)static const struct spi_device_id st7789v_spi_id[] = { {"st7789v" , (unsigned long ) &default_panel }, + {"t28cp45tn89-v17" , (unsigned long ) &t28cp45tn89_panel }, { } };MODULE_DEVICE_TABLE (spi, st7789v_spi_id);static const struct of_device_id st7789v_of_match[] = { { .compatible ="sitronix,st7789v" , .data = &default_panel }, + { .compatible ="inanbo,t28cp45tn89-v17" , .data = &t28cp45tn89_panel }, { } };MODULE_DEVICE_TABLE (of, st7789v_of_match);
Signature · 1 line
2.39.2
Hi Sebastian,
+ Thomas
[email protected] wrote on Sat, 22 Apr 2023 22:49:59 +0200:
Quoted 5 lines
Hi,
This adds panel support for Inanbo T28CP45TN89, which I found inside of a handheld thermal camera. The panel is based on the st7789v controller. All information is based on reverse engineering.
I haven't seen another version for this series so I assume it is still the one to look at. As you already know, I also want to add support for a panel based on the st7789 display controller. As discussed, I rebased my changes on top of yours as you actually sent them upstream much earlier than I did.
As a single minor comment was made to this version of the series, I would like to know if you wanted to send a new version soon? Or if it would make sense to send a bigger series with all our common patches in one single shot (mine should apply cleanly without further work on yours). Let me know how we can move forward.
For the record, here are my patches.
Thanks a lot,
Miquèl
Quoted 29 lines
Changes since PATCHv1:
* https://lore.kernel.org/all/[email protected]/
* Apply DT binding changes requested by Krzysztof Kozlowski and his Ack
* I changed the driver patches to avoid code duplication and splitted the code a bit more-- Sebastian
Sebastian Reichel (13):
dt-bindings: vendor-prefixes: add Inanbo
dt-bindings: display: st7789v: add Inanbo T28CP45TN89 drm/panel: sitronix-st7789v: add SPI ID table drm/panel: sitronix-st7789v: remove unused constants drm/panel: sitronix-st7789v: make reset GPIO optional drm/panel: sitronix-st7789v: simplifyst7789v_spi_writedrm/panel: sitronix-st7789v: improve error handling drm/panel: sitronix-st7789v: avoid hardcoding mode info drm/panel: sitronix-st7789v: avoid hardcoding panel size drm/panel: sitronix-st7789v: add media bus format drm/panel: sitronix-st7789v: avoid hardcoding invert mode drm/panel: sitronix-st7789v: avoid hardcoding polarity info drm/panel: sitronix-st7789v: add Inanbo T28CP45TN89 support.../display/panel/sitronix,st7789v.yaml | 5 +- .../devicetree/bindings/vendor-prefixes.yaml | 2 + .../gpu/drm/panel/panel-sitronix-st7789v.c | 148 ++++++++++++++---- 3 files changed, 120 insertions(+), 35 deletions(-)