All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sam Ravnborg <sam@ravnborg.org>
To: Shawn Guo <shawn.guo@linaro.org>
Cc: Thierry Reding <thierry.reding@gmail.com>,
	Daniel Vetter <daniel@ffwll.ch>, Rob Herring <robh+dt@kernel.org>,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-arm-msm@vger.kernel.org
Subject: Re: [PATCH 2/2] drm/panel: Add Truly NT35521 panel driver
Date: Wed, 4 Aug 2021 18:24:12 +0200	[thread overview]
Message-ID: <YQq/LOWEgTIk9zIT@ravnborg.org> (raw)
In-Reply-To: <20210804081352.30595-3-shawn.guo@linaro.org>

Hi Shawn,

see a few comments in the following.

	Sam

On Wed, Aug 04, 2021 at 04:13:52PM +0800, Shawn Guo wrote:
> It adds a drm driver for Truly NT35521 5.24" 1280x720 DSI panel, which
> can be found on Sony Xperia M4 Aqua phone.  The panel backlight is
> managed through DSI link.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
>  drivers/gpu/drm/panel/Kconfig               |   9 +
>  drivers/gpu/drm/panel/Makefile              |   1 +
>  drivers/gpu/drm/panel/panel-truly-nt35521.c | 491 ++++++++++++++++++++
>  3 files changed, 501 insertions(+)
>  create mode 100644 drivers/gpu/drm/panel/panel-truly-nt35521.c
> 
> diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
> index ef87d92cdf49..cdc4abd5c40c 100644
> --- a/drivers/gpu/drm/panel/Kconfig
> +++ b/drivers/gpu/drm/panel/Kconfig
> @@ -537,6 +537,15 @@ config DRM_PANEL_TPO_TPG110
>  	  400CH LTPS TFT LCD Single Chip Digital Driver for up to
>  	  800x400 LCD panels.
>  
> +config DRM_PANEL_TRULY_NT35521
> +	tristate "Truly NT35521 panel"
> +	depends on OF
> +	depends on DRM_MIPI_DSI
> +	depends on BACKLIGHT_CLASS_DEVICE
> +	help
> +	  Say Y here if you want to enable support for Truly NT35521
> +	  1280x720 DSI panel.
Here you could mention that the first use is the Sone eXperia M4 Aqua to
help the user.

> +
>  config DRM_PANEL_TRULY_NT35597_WQXGA
>  	tristate "Truly WQXGA"
>  	depends on OF
> diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
> index cae4d976c069..3d3c98cb7a7b 100644
> --- a/drivers/gpu/drm/panel/Makefile
> +++ b/drivers/gpu/drm/panel/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_PANEL_TDO_TL070WSH30) += panel-tdo-tl070wsh30.o
>  obj-$(CONFIG_DRM_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o
>  obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
>  obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o
> +obj-$(CONFIG_DRM_PANEL_TRULY_NT35521) += panel-truly-nt35521.o
>  obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
>  obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
>  obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
> diff --git a/drivers/gpu/drm/panel/panel-truly-nt35521.c b/drivers/gpu/drm/panel/panel-truly-nt35521.c
> new file mode 100644
> index 000000000000..ea3cfb46be7e
> --- /dev/null
> +++ b/drivers/gpu/drm/panel/panel-truly-nt35521.c
> @@ -0,0 +1,491 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021, Linaro Limited
> + */
> +
> +#include <linux/backlight.h>
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/module.h>
> +
> +#include <video/mipi_display.h>
> +
> +#include <drm/drm_mipi_dsi.h>
> +#include <drm/drm_modes.h>
> +#include <drm/drm_panel.h>
> +#include <drm/drm_print.h>
drm_print is not used by panel drivers - this also imply that you need
to replace all uses of DRM_ERROR and friends.


> +
> +struct nt35521_panel {
> +	struct drm_panel panel;
> +	struct device *dev;
> +	struct gpio_desc *rst_gpio;
> +	struct gpio_desc *pwrp5_gpio;
> +	struct gpio_desc *pwrn5_gpio;
> +	struct gpio_desc *en_gpio;
> +	bool prepared;
> +	bool enabled;
> +};
> +
> +static inline struct nt35521_panel *panel_to_nt35521(struct drm_panel *panel)
> +{
> +	return container_of(panel, struct nt35521_panel, panel);
> +}
> +
> +#define nt_dcs_write(seq...)						\
> +({									\
> +	const u8 d[] = { seq };						\
> +	if (mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)) < 0)	\
> +		DRM_DEV_ERROR(dev, "dcs write buffer failed\n");	\
> +})
So in case of an error the code just continues with the next write, that
likely also errors out.
Please see what is for example implemented in panel-elida-kd35t133.c
That pattern looks much saner.

> +
> +#define nt_gen_write(seq...)						\
> +({									\
> +	const u8 d[] = { seq };						\
> +	if (mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)) < 0)		\
> +		DRM_DEV_ERROR(dev, "generic write buffer failed\n");	\
> +})
For the two uses, please consider open coding this.

> +
> +static void nt35521_panel_on(struct nt35521_panel *nt)
> +{
> +	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
> +	struct device *dev = nt->dev;
> +
> +	/* Transmit data in low power mode */
> +	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
> +
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
> +	nt_dcs_write(0xff, 0xaa, 0x55, 0xa5, 0x80);
> +	nt_dcs_write(0x6f, 0x11, 0x00);
> +	nt_dcs_write(0xf7, 0x20, 0x00);
> +	nt_dcs_write(0x6f, 0x01);
> +	nt_dcs_write(0xb1, 0x21);
> +	nt_dcs_write(0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
> +	nt_dcs_write(0xb8, 0x01, 0x02, 0x0c, 0x02);
> +	nt_dcs_write(0xbb, 0x11, 0x11);
> +	nt_dcs_write(0xbc, 0x00, 0x00);
> +	nt_dcs_write(0xb6, 0x02);
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
> +	nt_dcs_write(0xb0, 0x09, 0x09);
> +	nt_dcs_write(0xb1, 0x09, 0x09);
> +	nt_dcs_write(0xbc, 0x8c, 0x00);
> +	nt_dcs_write(0xbd, 0x8c, 0x00);
> +	nt_dcs_write(0xca, 0x00);
> +	nt_dcs_write(0xc0, 0x04);
> +	nt_dcs_write(0xbe, 0xb5);
> +	nt_dcs_write(0xb3, 0x35, 0x35);
> +	nt_dcs_write(0xb4, 0x25, 0x25);
> +	nt_dcs_write(0xb9, 0x43, 0x43);
> +	nt_dcs_write(0xba, 0x24, 0x24);
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
> +	nt_dcs_write(0xee, 0x03);
> +	nt_dcs_write(0xb0, 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00,
> +		     0xc3, 0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01,
> +		     0x11);
> +	nt_dcs_write(0xb1, 0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01,
> +		     0xc3, 0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02,
> +		     0x77);
> +	nt_dcs_write(0xb2, 0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03,
> +		     0x2c, 0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03,
> +		     0x90);
> +	nt_dcs_write(0xb3, 0x03, 0x96, 0x03, 0x98);
> +	nt_dcs_write(0xb4, 0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00,
> +		     0xa9, 0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01,
> +		     0x02);
> +	nt_dcs_write(0xb5, 0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01,
> +		     0xbf, 0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
> +	nt_dcs_write(0xb6, 0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
> +		     0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
> +	nt_dcs_write(0xb7, 0x03, 0xb8, 0x03, 0xba);
> +	nt_dcs_write(0xb8, 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
> +		     0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
> +	nt_dcs_write(0xb9, 0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
> +		     0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
> +	nt_dcs_write(0xba, 0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
> +		     0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
> +	nt_dcs_write(0xbb, 0x03, 0xf6, 0x03, 0xf7);
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
> +	nt_dcs_write(0xb0, 0x22, 0x00);
> +	nt_dcs_write(0xb1, 0x22, 0x00);
> +	nt_dcs_write(0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
> +	nt_dcs_write(0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
> +	nt_dcs_write(0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
> +	nt_dcs_write(0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
> +	nt_dcs_write(0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
> +	nt_dcs_write(0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
> +	nt_dcs_write(0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
> +	nt_dcs_write(0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
> +	nt_dcs_write(0xc0, 0x00, 0x34, 0x00, 0x00);
> +	nt_dcs_write(0xc1, 0x00, 0x00, 0x34, 0x00);
> +	nt_dcs_write(0xc2, 0x00, 0x00, 0x34, 0x00);
> +	nt_dcs_write(0xc3, 0x00, 0x00, 0x34, 0x00);
> +	nt_dcs_write(0xc4, 0x60);
> +	nt_dcs_write(0xc5, 0xc0);
> +	nt_dcs_write(0xc6, 0x00);
> +	nt_dcs_write(0xc7, 0x00);
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
> +	nt_dcs_write(0xb0, 0x17, 0x06);
> +	nt_dcs_write(0xb1, 0x17, 0x06);
> +	nt_dcs_write(0xb2, 0x17, 0x06);
> +	nt_dcs_write(0xb3, 0x17, 0x06);
> +	nt_dcs_write(0xb4, 0x17, 0x06);
> +	nt_dcs_write(0xb5, 0x17, 0x06);
> +	nt_dcs_write(0xb6, 0x17, 0x06);
> +	nt_dcs_write(0xb7, 0x17, 0x06);
> +	nt_dcs_write(0xb8, 0x00);
> +	nt_dcs_write(0xb9, 0x00, 0x03);
> +	nt_dcs_write(0xba, 0x00, 0x00);
> +	nt_dcs_write(0xbb, 0x02, 0x03);
> +	nt_dcs_write(0xbc, 0x02, 0x03);
> +	nt_dcs_write(0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
> +	nt_dcs_write(0xc0, 0x0b);
> +	nt_dcs_write(0xc1, 0x09);
> +	nt_dcs_write(0xc2, 0xa6);
> +	nt_dcs_write(0xc3, 0x05);
> +	nt_dcs_write(0xc4, 0x00);
> +	nt_dcs_write(0xc5, 0x02);
> +	nt_dcs_write(0xc6, 0x22);
> +	nt_dcs_write(0xc7, 0x03);
> +	nt_dcs_write(0xc8, 0x07, 0x20);
> +	nt_dcs_write(0xc9, 0x03, 0x20);
> +	nt_dcs_write(0xca, 0x01, 0x60);
> +	nt_dcs_write(0xcb, 0x01, 0x60);
> +	nt_dcs_write(0xcc, 0x00, 0x00, 0x02);
> +	nt_dcs_write(0xcd, 0x00, 0x00, 0x02);
> +	nt_dcs_write(0xce, 0x00, 0x00, 0x02);
> +	nt_dcs_write(0xcf, 0x00, 0x00, 0x02);
> +	nt_dcs_write(0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
> +	nt_dcs_write(0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
> +	nt_dcs_write(0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
> +	nt_dcs_write(0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
> +	nt_dcs_write(0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
> +	nt_dcs_write(0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		     0x00, 0x00, 0x00, 0x00);
> +	nt_dcs_write(0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		     0x00, 0x00, 0x00, 0x00);
> +	nt_dcs_write(0xd7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		     0x00, 0x00, 0x00, 0x00);
> +	nt_dcs_write(0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
> +	nt_dcs_write(0xe5, 0x06);
> +	nt_dcs_write(0xe6, 0x06);
> +	nt_dcs_write(0xe7, 0x00);
> +	nt_dcs_write(0xe8, 0x06);
> +	nt_dcs_write(0xe9, 0x06);
> +	nt_dcs_write(0xea, 0x06);
> +	nt_dcs_write(0xeb, 0x00);
> +	nt_dcs_write(0xec, 0x00);
> +	nt_dcs_write(0xed, 0x30);
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
> +	nt_dcs_write(0xb0, 0x31, 0x31);
> +	nt_dcs_write(0xb1, 0x31, 0x31);
> +	nt_dcs_write(0xb2, 0x2d, 0x2e);
> +	nt_dcs_write(0xb3, 0x31, 0x34);
> +	nt_dcs_write(0xb4, 0x29, 0x2a);
> +	nt_dcs_write(0xb5, 0x12, 0x10);
> +	nt_dcs_write(0xb6, 0x18, 0x16);
> +	nt_dcs_write(0xb7, 0x00, 0x02);
> +	nt_dcs_write(0xb8, 0x08, 0x31);
> +	nt_dcs_write(0xb9, 0x31, 0x31);
> +	nt_dcs_write(0xba, 0x31, 0x31);
> +	nt_dcs_write(0xbb, 0x31, 0x08);
> +	nt_dcs_write(0xbc, 0x03, 0x01);
> +	nt_dcs_write(0xbd, 0x17, 0x19);
> +	nt_dcs_write(0xbe, 0x11, 0x13);
> +	nt_dcs_write(0xbf, 0x2a, 0x29);
> +	nt_dcs_write(0xc0, 0x34, 0x31);
> +	nt_dcs_write(0xc1, 0x2e, 0x2d);
> +	nt_dcs_write(0xc2, 0x31, 0x31);
> +	nt_dcs_write(0xc3, 0x31, 0x31);
> +	nt_dcs_write(0xc4, 0x31, 0x31);
> +	nt_dcs_write(0xc5, 0x31, 0x31);
> +	nt_dcs_write(0xc6, 0x2e, 0x2d);
> +	nt_dcs_write(0xc7, 0x31, 0x34);
> +	nt_dcs_write(0xc8, 0x29, 0x2a);
> +	nt_dcs_write(0xc9, 0x17, 0x19);
> +	nt_dcs_write(0xca, 0x11, 0x13);
> +	nt_dcs_write(0xcb, 0x03, 0x01);
> +	nt_dcs_write(0xcc, 0x08, 0x31);
> +	nt_dcs_write(0xcd, 0x31, 0x31);
> +	nt_dcs_write(0xce, 0x31, 0x31);
> +	nt_dcs_write(0xcf, 0x31, 0x08);
> +	nt_dcs_write(0xd0, 0x00, 0x02);
> +	nt_dcs_write(0xd1, 0x12, 0x10);
> +	nt_dcs_write(0xd2, 0x18, 0x16);
> +	nt_dcs_write(0xd3, 0x2a, 0x29);
> +	nt_dcs_write(0xd4, 0x34, 0x31);
> +	nt_dcs_write(0xd5, 0x2d, 0x2e);
> +	nt_dcs_write(0xd6, 0x31, 0x31);
> +	nt_dcs_write(0xd7, 0x31, 0x31);
> +	nt_dcs_write(0xe5, 0x31, 0x31);
> +	nt_dcs_write(0xe6, 0x31, 0x31);
> +	nt_dcs_write(0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
> +	nt_dcs_write(0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
> +	nt_dcs_write(0xe7, 0x00);
> +	nt_dcs_write(0x6f, 0x02);
> +	nt_dcs_write(0xf7, 0x47);
> +	nt_dcs_write(0x6f, 0x0a);
> +	nt_dcs_write(0xf7, 0x02);
> +	nt_dcs_write(0x6f, 0x17);
> +	nt_dcs_write(0xf4, 0x60);
> +	nt_dcs_write(0x6f, 0x01);
> +	nt_dcs_write(0xf9, 0x46);
> +	nt_dcs_write(0x6f, 0x11);
> +	nt_dcs_write(0xf3, 0x01);
> +	nt_dcs_write(0x35, 0x00);
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
> +	nt_dcs_write(0xd9, 0x02, 0x03, 0x00);
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
> +	nt_dcs_write(0xb1, 0x6c, 0x21);
> +	nt_dcs_write(0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
> +	nt_dcs_write(0x35, 0x00);
> +	nt_gen_write(0x11, 0x00);
> +	msleep(120);
> +	nt_gen_write(0x29, 0x00);
> +	usleep_range(1000, 1500);
> +	nt_dcs_write(0x53, 0x24);
> +}
> +
> +static void nt35521_panel_off(struct nt35521_panel *nt)
> +{
> +	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
> +	struct device *dev = nt->dev;
> +
> +	/* Transmit data in high speed mode */
> +	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
> +
> +	nt_dcs_write(0x28, 0x00);
This is MIPI_DCS_SET_DISPLAY_OFF
So you can use:
	mipi_dsi_dcs_set_display_off()

> +	msleep(50);
> +	nt_dcs_write(0x10, 0x00);
This is MIPI_DCS_ENTER_SLEEP_MODE
So you can use:
	mipi_dsi_dcs_enter_sleep_mode()

> +	msleep(150);
Please verify if there are other cases where thestandard helpers can be
used.

> +}
> +
> +static int nt35521_prepare(struct drm_panel *panel)
> +{
> +	struct nt35521_panel *nt = panel_to_nt35521(panel);
> +
> +	if (nt->prepared)
> +		return 0;
> +
> +	gpiod_set_value_cansleep(nt->pwrp5_gpio, 1);
> +	usleep_range(1000, 1500);
> +	gpiod_set_value_cansleep(nt->pwrn5_gpio, 1);
> +	usleep_range(10000, 15000);
> +	gpiod_set_value_cansleep(nt->rst_gpio, 0);
> +	msleep(150);
> +
> +	nt35521_panel_on(nt);
> +
> +	nt->prepared = true;
> +
> +	return 0;
> +}
> +
> +static int nt35521_unprepare(struct drm_panel *panel)
> +{
> +	struct nt35521_panel *nt = panel_to_nt35521(panel);
> +
> +	if (!nt->prepared)
> +		return 0;
> +
> +	nt35521_panel_off(nt);
> +
> +	gpiod_set_value_cansleep(nt->rst_gpio, 1);
> +
> +	nt->prepared = false;
> +
> +	return 0;
> +}
> +
> +static int nt35521_enable(struct drm_panel *panel)
> +{
> +	struct nt35521_panel *nt = panel_to_nt35521(panel);
> +
> +	if (nt->enabled)
> +		return 0;
> +
> +	gpiod_set_value_cansleep(nt->en_gpio, 1);
> +
> +	nt->enabled = true;
> +
> +	return 0;
> +}
> +
> +static int nt35521_disable(struct drm_panel *panel)
> +{
> +	struct nt35521_panel *nt = panel_to_nt35521(panel);
> +
> +	if (!nt->enabled)
> +		return 0;
> +
> +	gpiod_set_value_cansleep(nt->en_gpio, 0);
> +
> +	nt->enabled = false;
> +
> +	return 0;
> +}
> +
> +static const struct drm_display_mode nt35521_modes = {
> +	.clock = 133306,
> +	.hdisplay = 720,
> +	.hsync_start = 720 + 632,
> +	.hsync_end = 720 + 632 + 40,
> +	.htotal = 720 + 632 + 40 + 295,
> +	.vdisplay = 1280,
> +	.vsync_start = 1280 + 18,
> +	.vsync_end = 1280 + 18 + 1,
> +	.vtotal = 1280 + 18 + 1 + 18,
> +};
> +
> +static int nt35521_get_modes(struct drm_panel *panel,
> +			      struct drm_connector *connector)
> +{
> +	struct nt35521_panel *nt = panel_to_nt35521(panel);
> +	struct drm_display_mode *mode;
> +
> +	mode = drm_mode_duplicate(connector->dev, &nt35521_modes);
> +	if (!mode) {
> +		DRM_DEV_ERROR(nt->dev, "failed to add display mode\n");
> +		return -ENOMEM;
> +	}
> +
> +	drm_mode_set_name(mode);
> +	drm_mode_probed_add(connector, mode);
> +
> +	connector->display_info.width_mm = 65;
> +	connector->display_info.height_mm = 116;
> +
> +	return 1;
> +}
> +
> +static const struct drm_panel_funcs nt35521_drm_funcs = {
> +	.prepare = nt35521_prepare,
> +	.unprepare = nt35521_unprepare,
> +	.enable = nt35521_enable,
> +	.disable = nt35521_disable,
> +	.get_modes = nt35521_get_modes,
> +};
> +
> +static int nt35521_backlight_update_status(struct backlight_device *bd)
> +{
> +	struct nt35521_panel *nt = bl_get_data(bd);
> +	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
> +	u8 brightness = bd->props.brightness;
Use backlight_get_brightness(bd);


> +	int ret;
> +
> +	ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
> +				 &brightness,
> +				 sizeof(brightness));
Use mipi_dsi_dcs_set_display_brightness()

hich btw uses u16 for brightness.

> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static const struct backlight_ops nt35521_backlight_ops = {
> +	.update_status = nt35521_backlight_update_status,
> +};
> +
> +static int nt35521_probe(struct mipi_dsi_device *dsi)
> +{
> +	struct backlight_properties props;
> +	struct device *dev = &dsi->dev;
> +	struct nt35521_panel *nt;
> +	int ret;
> +
> +	nt = devm_kzalloc(dev, sizeof(*nt), GFP_KERNEL);
> +	if (!nt)
> +		return -ENOMEM;
> +
> +	nt->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> +	if (IS_ERR(nt->rst_gpio)) {
> +		ret = PTR_ERR(nt->rst_gpio);
> +		DRM_DEV_ERROR(dev, "failed to get reset GPIO: %d\n", ret);
> +		return ret;
> +	}
In general - use dev_err_probe() all over the probe function.
See for example panel-samsung-sofef00.c

> +
> +	nt->pwrp5_gpio = devm_gpiod_get(dev, "pwr-positive5", GPIOD_OUT_LOW);
> +	if (IS_ERR(nt->pwrp5_gpio)) {
> +		ret = PTR_ERR(nt->pwrp5_gpio);
> +		DRM_DEV_ERROR(dev, "failed to get positive5 GPIO: %d\n", ret);
> +		return ret;
> +	}
> +
> +	nt->pwrn5_gpio = devm_gpiod_get(dev, "pwr-negative5", GPIOD_OUT_LOW);
> +	if (IS_ERR(nt->pwrn5_gpio)) {
> +		ret = PTR_ERR(nt->pwrn5_gpio);
> +		DRM_DEV_ERROR(dev, "failed to get negative5 GPIO: %d\n", ret);
> +		return ret;
> +	}
> +
> +	nt->en_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
> +	if (IS_ERR(nt->en_gpio)) {
> +		ret = PTR_ERR(nt->en_gpio);
> +		DRM_DEV_ERROR(dev, "failed to get enable GPIO: %d\n", ret);
> +		return ret;
> +	}
> +
> +	nt->dev = dev;
> +
> +	drm_panel_init(&nt->panel, dev, &nt35521_drm_funcs,
> +		       DRM_MODE_CONNECTOR_DSI);
> +
> +	props.max_brightness = 255;
> +	props.brightness = 240;
> +	props.type = BACKLIGHT_RAW;
Use:
       const struct backlight_properties props = {
                .type = BACKLIGHT_RAW,
                .brightness = 240,
                .max_brightness = 255,
        };
in the variable declaration.

> +
> +	nt->panel.backlight = devm_backlight_device_register(dev, dev_name(dev),
> +						dev, nt, &nt35521_backlight_ops,
> +						&props);
> +	if (IS_ERR(nt->panel.backlight)) {
> +		ret = PTR_ERR(nt->panel.backlight);
> +		DRM_DEV_ERROR(dev, "failed to register backlight: %d\n", ret);
> +		return ret;
> +	}
> +
> +	drm_panel_add(&nt->panel);
> +
> +	dsi->lanes = 4;
> +	dsi->format = MIPI_DSI_FMT_RGB888;
> +	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
> +			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
> +
> +	ret = mipi_dsi_attach(dsi);
> +	if (ret < 0) {
> +		DRM_DEV_ERROR(dev, "failed to attach DSI device: %d\n", ret);
> +		drm_panel_remove(&nt->panel);
> +		return ret;
> +	}
> +
> +	mipi_dsi_set_drvdata(dsi, nt);
I think it is wise to set drvdata before mipi_dsi_attach.

> +
> +	return 0;
> +}
> +
> +static int nt35521_remove(struct mipi_dsi_device *dsi)
> +{
> +	struct nt35521_panel *nt = mipi_dsi_get_drvdata(dsi);
> +
> +	mipi_dsi_detach(dsi);
> +	drm_panel_remove(&nt->panel);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id truly_nt35521_of_match[] = {
> +	{ .compatible = "truly,nt35521" },
> +	{ }
Write this as:
	{ /* sentinel */ },

just to be consistent with most panels.

> +};
> +MODULE_DEVICE_TABLE(of, truly_nt35521_of_match);
> +
> +static struct mipi_dsi_driver truly_nt35521_driver = {
> +	.driver = {
> +		.name = "panel-truly-nt35521",
> +		.of_match_table = truly_nt35521_of_match,
> +	},
> +	.probe  = nt35521_probe,
> +	.remove = nt35521_remove,
> +};
> +module_mipi_dsi_driver(truly_nt35521_driver);
> +
MODULE_AUTHOR()??

> +MODULE_DESCRIPTION("Truly NT35521 DSI panel driver");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.17.1

  parent reply	other threads:[~2021-08-04 16:24 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-04  8:13 [PATCH 0/2] Add Truly NT35521 panel driver support Shawn Guo
2021-08-04  8:13 ` [PATCH 1/2] dt-bindings: display: panel: Add Truly NT35521 panel support Shawn Guo
2021-08-04 16:03   ` Sam Ravnborg
2021-08-08 12:04     ` Shawn Guo
2021-08-11 18:51   ` Rob Herring
2021-08-13 13:59     ` Shawn Guo
2021-08-04  8:13 ` [PATCH 2/2] drm/panel: Add Truly NT35521 panel driver Shawn Guo
2021-08-04 12:09   ` Stephan Gerhold
2021-08-08 13:44     ` Shawn Guo
2021-08-08 15:29       ` Stephan Gerhold
2021-08-09  4:20         ` Shawn Guo
2021-08-04 16:24   ` Sam Ravnborg [this message]
2021-08-08 13:49     ` Shawn Guo

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=YQq/LOWEgTIk9zIT@ravnborg.org \
    --to=sam@ravnborg.org \
    --cc=daniel@ffwll.ch \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=shawn.guo@linaro.org \
    --cc=thierry.reding@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.