All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thierry Reding <thierry.reding@gmail.com>
To: abhinavk@codeaurora.org
Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org,
	hoegsberg@google.com, chandanu@codeaurora.org
Subject: Re: [PATCH v4 1/2] drm/panel: Add support for Truly NT35597 panel
Date: Tue, 10 Jul 2018 11:44:44 +0200	[thread overview]
Message-ID: <20180710094444.GB1504@ulmo> (raw)
In-Reply-To: <0beaa3a7765dbf9bfffdee59235f180d@codeaurora.org>


[-- Attachment #1.1: Type: text/plain, Size: 21411 bytes --]

On Wed, May 30, 2018 at 03:37:26PM -0700, abhinavk@codeaurora.org wrote:
> Hi Sean
> 
> Thanks for your review.
> 
> Some responses below. Please help to check.
> 
> Thanks
> 
> Abhinav

Looks like this got stuck in review. Some comments below, which I hope
will match Sean's opinion.

> On 2018-05-30 12:12, Sean Paul wrote:
> > On Fri, May 25, 2018 at 05:27:51PM -0700, Abhinav Kumar wrote:
> > > Add support for Truly NT35597 panel used
> > > in MSM reference platforms.
> > > 
> > > This panel supports both single DSI and dual DSI
> > > modes.
> > > 
> > > However, this patch series adds support only for
> > > dual DSI mode.
> > > 
> > > Changes in v4:
> > > - Fix the license identifier
> > > - Fix formatting issues for the regulator loads
> > > - Fix error messages and return code
> > > 
> > > Signed-off-by: Archit Taneja <architt@codeaurora.org>
> > > Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
> > > ---
> > >  drivers/gpu/drm/panel/Kconfig               |   8 +
> > >  drivers/gpu/drm/panel/Makefile              |   1 +
> > >  drivers/gpu/drm/panel/panel-truly-nt35597.c | 576
> > > ++++++++++++++++++++++++++++
> > >  3 files changed, 585 insertions(+)
> > >  create mode 100644 drivers/gpu/drm/panel/panel-truly-nt35597.c
> > > 
> > > diff --git a/drivers/gpu/drm/panel/Kconfig
> > > b/drivers/gpu/drm/panel/Kconfig
> > > index 25682ff..2fcd9b1 100644
> > > --- a/drivers/gpu/drm/panel/Kconfig
> > > +++ b/drivers/gpu/drm/panel/Kconfig
> > > @@ -177,4 +177,12 @@ config DRM_PANEL_SITRONIX_ST7789V
> > >  	  Say Y here if you want to enable support for the Sitronix
> > >  	  ST7789V controller for 240x320 LCD panels
> > > 
> > > +config DRM_PANEL_TRULY_NT35597_WQXGA
> > > +	tristate "Truly WQXGA"
> > > +	depends on OF
> > > +	depends on DRM_MIPI_DSI
> > > +	select VIDEOMODE_HELPERS
> > > +	help
> > > +	  Say Y here if you want to enable support for Truly NT35597 WQXGA
> > > Dual DSI
> > > +	  Video Mode panel
> > >  endmenu
> > > diff --git a/drivers/gpu/drm/panel/Makefile
> > > b/drivers/gpu/drm/panel/Makefile
> > > index f26efc1..056ea93 100644
> > > --- a/drivers/gpu/drm/panel/Makefile
> > > +++ b/drivers/gpu/drm/panel/Makefile
> > > @@ -18,3 +18,4 @@ obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) +=
> > > panel-seiko-43wvf1g.o
> > >  obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) +=
> > > panel-sharp-lq101r1sx01.o
> > >  obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) +=
> > > panel-sharp-ls043t1le01.o
> > >  obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
> > > +obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
> > > diff --git a/drivers/gpu/drm/panel/panel-truly-nt35597.c
> > > b/drivers/gpu/drm/panel/panel-truly-nt35597.c
> > > new file mode 100644
> > > index 0000000..a57cbf0
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/panel/panel-truly-nt35597.c
> > > @@ -0,0 +1,576 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Copyright (c) 2018, The Linux Foundation. All rights reserved.
> > > + */
> > > +
> > > +#include <linux/gpio/consumer.h>
> > > +#include <linux/of_graph.h>
> > > +#include <linux/regulator/consumer.h>
> > > +#include <linux/pinctrl/consumer.h>
> > > +
> > > +#include <video/mipi_display.h>
> > > +#include <video/of_videomode.h>
> > > +#include <video/videomode.h>
> > > +
> > > +#include <drm/drmP.h>
> > > +#include <drm/drm_panel.h>
> > > +#include <drm/drm_mipi_dsi.h>
> > > +
> > > +static const char * const regulator_names[] = {
> > > +	"vdda",
> > > +	"vdispp",
> > > +	"vdispn"
> > > +};
> [Abhinav] Will add a ',' here as per jordan's comment
> > > +
> > > +static unsigned long const regulator_enable_loads[] = {
> > > +	62000,
> > > +	100000,
> > > +	100000,
> > > +};
> > > +
> > > +static unsigned long const regulator_disable_loads[] = {
> > > +	80,
> > > +	100,
> > > +	100,
> > > +};
> > > +
> > > +struct truly_wqxga {
> > > +	struct device *dev;
> > > +	struct drm_panel panel;
> > > +
> > > +	struct regulator_bulk_data supplies[ARRAY_SIZE(regulator_names)];
> > > +
> > > +	struct gpio_desc *reset_gpio;
> > > +	struct gpio_desc *mode_gpio;
> > > +
> > > +	struct backlight_device *backlight;
> > > +	struct videomode vm;
> > > +
> > > +	struct mipi_dsi_device *dsi[2];
> > > +
> > > +	bool prepared;
> > > +	bool enabled;
> > > +};
> > > +
> > > +static inline struct truly_wqxga *panel_to_truly_wqxga(struct
> > > drm_panel *panel)
> > > +{
> > > +	return container_of(panel, struct truly_wqxga, panel);
> > > +}
> > > +
> > > +static int truly_wqxga_power_on(struct truly_wqxga *ctx)
> > > +{
> > > +	int ret, i;
> > > +
> > > +	for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
> > > +		ret = regulator_set_load(ctx->supplies[i].consumer,
> > > +					regulator_enable_loads[i]);
> > > +		if (ret)
> > > +			return ret;
> > > +	}
> > > +
> > > +	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies),
> > > ctx->supplies);
> > > +	if (ret < 0)
> > > +		return ret;
> > > +
> > > +	msleep(20);
> > > +	gpiod_set_value(ctx->reset_gpio, 1);
> > > +	msleep(20);
> > > +	gpiod_set_value(ctx->reset_gpio, 0);
> > > +	msleep(20);
> > > +	gpiod_set_value(ctx->reset_gpio, 1);
> > > +	msleep(50);
> > 
> > Why is this needed? Could you please comment?
> > 
> > Also, it seems like this is active low? You should specify that in the
> > dt, and
> > let gpiod translate the value.
> 
> [Abhinav] This is the panel's reset sequence which demands this delay. I can
> comment the same.
> Its active HIGH. I can leave a comment in the bindings mentioning the same.
> Let me know if this is sufficient.

According to the code that reset is active low, otherwise that last
gpiod_set_value() would leave the reset asserted. In either case I think
what Sean meant to say was that the code here should be assuming that
the reset is active high (i.e. the reset deassert should be
gpiod_set_value(..., 0) and the device tree should have GPIO_ACTIVE_LOW
in the specifier for the reset GPIO, which will then cause the gpiod
library to properly do the inversion for you.

> 
> > 
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int truly_wqxga_power_off(struct truly_wqxga *ctx)
> > > +{
> > > +	int ret, i;
> > > +
> > > +	gpiod_set_value(ctx->reset_gpio, 0);
> > > +
> > > +	for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
> > > +		ret = regulator_set_load(ctx->supplies[i].consumer,
> > > +				regulator_disable_loads[i]);
> > > +		if (ret)
> > > +			return ret;
> > > +	}
> > > +
> > > +	return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
> > > ctx->supplies);
> > > +}
> > > +
> > > +static int truly_wqxga_disable(struct drm_panel *panel)
> > > +{
> > > +	struct truly_wqxga *ctx = panel_to_truly_wqxga(panel);
> > > +
> > > +	if (!ctx->enabled)
> > > +		return 0;
> > > +
> > > +	if (ctx->backlight) {
> > > +		ctx->backlight->props.power = FB_BLANK_POWERDOWN;
> > > +		backlight_update_status(ctx->backlight);
> > 
> > You can use the backlight_enable/disable helpers, and please check the
> > return
> > value.
> > 
> [Abhinav] Can you please provide me the reference to the helper you are
> referring to?
> Other panels were using backlight_update_status(), Hence i am not able to
> locate it.
> Yes, I will check the return value in v5.

I think Sean was referring to backlight_enable() and backlight_disable()
in include/linux/backlight.h. You should use those instead of the low-
level backlight_update_status(). If you look at the implementation of
the new helpers, you'll understand why. =)

> 
> > > +	}
> > > +
> > > +	ctx->enabled = false;
> > > +	return 0;
> > > +}
> > > +
> > > +static int truly_wqxga_unprepare(struct drm_panel *panel)
> > > +{
> > > +	struct truly_wqxga *ctx = panel_to_truly_wqxga(panel);
> > > +	struct mipi_dsi_device **dsis = ctx->dsi;
> > 
> > IMO, this obfuscation isn't too useful (and prevents us from using
> > ARRAY_SIZE
> > below).
> [Abhinav] Agreed, will fix this in v5.
> > 
> > > +	int ret = 0, i;
> > > +
> > > +	if (!ctx->prepared)
> > > +		return 0;
> > > +
> > > +	dsis[0]->mode_flags = 0;
> > > +	dsis[1]->mode_flags = 0;
> > > +
> > > +	for (i = 0; i < 2; i++)
> > 
> > s/2/ARRAY_SIZE(ctx->dsi)/
> > 
> > > +		if (mipi_dsi_dcs_set_display_off(dsis[i]) < 0)
> > > +			ret = -ECOMM;
> > 
> > I guess it's alright that we're continuing through errors, however we
> > should
> > probably log the actual error value as well as the channel number in a
> > DEBUG
> > message.
> > 
> [Abhinav] Agreed, will print an error message.
> > > +
> > > +	msleep(120);
> > 
> > Please comment.
> [Abhinav] Agreed, will explain this.
> > 
> > > +
> > > +	for (i = 0; i < 2; i++)
> > 
> > ARRAY_SIZE nit here.
> > 
> [Abhinav] Agreed, will use ARRAY_SIZE here
> > > +		if (mipi_dsi_dcs_enter_sleep_mode(dsis[i]) < 0)
> > > +			ret = -ECOMM;
> > > +
> > > +	truly_wqxga_power_off(ctx);
> > 
> > You don't check the return value.
> [Abhinav] Agreed, will check return value.
> > 
> > > +
> > > +	ctx->prepared = false;
> > > +	return ret;
> > > +}
> > > +
> > > +#define MAX_LEN	5

That's odd, you set MAX_LEN to 5, but the longest command in the
sequence below is 4 bytes. That means you're effectively wasting at
least 1 byte per command.

> > > +struct {
> > > +	u8 commands[MAX_LEN];
> > > +	int size;

This can be unsigned.

> > > +} panel_cmds[] = { /* CMD2_P0 */

You probably want to make this static and const?

> > > +		   { { 0xff, 0x20 }, 2 },
> > > +		   { { 0xfb, 0x01 }, 2 },
> > > +		   { { 0x00, 0x01 }, 2 },
> > > +		   { { 0x01, 0x55 }, 2 },
> > > +		   { { 0x02, 0x45 }, 2 },
> > > +		   { { 0x05, 0x40 }, 2 },
> > > +		   { { 0x06, 0x19 }, 2 },
> > > +		   { { 0x07, 0x1e }, 2 },
> > > +		   { { 0x0b, 0x73 }, 2 },
> > > +		   { { 0x0c, 0x73 }, 2 },
> > > +		   { { 0x0e, 0xb0 }, 2 },
> > > +		   { { 0x0f, 0xae }, 2 },
> > > +		   { { 0x11, 0xb8 }, 2 },
> > > +		   { { 0x13, 0x00 }, 2 },
> > > +		   { { 0x58, 0x80 }, 2 },
> > > +		   { { 0x59, 0x01 }, 2 },
> > > +		   { { 0x5a, 0x00 }, 2 },
> > > +		   { { 0x5b, 0x01 }, 2 },
> > > +		   { { 0x5c, 0x80 }, 2 },
> > > +		   { { 0x5d, 0x81 }, 2 },
> > > +		   { { 0x5e, 0x00 }, 2 },
> > > +		   { { 0x5f, 0x01 }, 2 },
> > > +		   { { 0x72, 0x11 }, 2 },
> > > +		   { { 0x68, 0x03 }, 2 },
> > > +		   /* CMD2_P4 */
> > > +		   { { 0xFF, 0x24 }, 2 },
> > > +		   { { 0xFB, 0x01 }, 2 },
> > > +		   { { 0x00, 0x1C }, 2 },
> > > +		   { { 0x01, 0x0B }, 2 },
> > > +		   { { 0x02, 0x0C }, 2 },
> > > +		   { { 0x03, 0x01 }, 2 },
> > > +		   { { 0x04, 0x0F }, 2 },
> > > +		   { { 0x05, 0x10 }, 2 },
> > > +		   { { 0x06, 0x10 }, 2 },
> > > +		   { { 0x07, 0x10 }, 2 },
> > > +		   { { 0x08, 0x89 }, 2 },
> > > +		   { { 0x09, 0x8A }, 2 },
> > > +		   { { 0x0A, 0x13 }, 2 },
> > > +		   { { 0x0B, 0x13 }, 2 },
> > > +		   { { 0x0C, 0x15 }, 2 },
> > > +		   { { 0x0D, 0x15 }, 2 },
> > > +		   { { 0x0E, 0x17 }, 2 },
> > > +		   { { 0x0F, 0x17 }, 2 },
> > > +		   { { 0x10, 0x1C }, 2 },
> > > +		   { { 0x11, 0x0B }, 2 },
> > > +		   { { 0x12, 0x0C }, 2 },
> > > +		   { { 0x13, 0x01 }, 2 },
> > > +		   { { 0x14, 0x0F }, 2 },
> > > +		   { { 0x15, 0x10 }, 2 },
> > > +		   { { 0x16, 0x10 }, 2 },
> > > +		   { { 0x17, 0x10 }, 2 },
> > > +		   { { 0x18, 0x89 }, 2 },
> > > +		   { { 0x19, 0x8A }, 2 },
> > > +		   { { 0x1A, 0x13 }, 2 },
> > > +		   { { 0x1B, 0x13 }, 2 },
> > > +		   { { 0x1C, 0x15 }, 2 },
> > > +		   { { 0x1D, 0x15 }, 2 },
> > > +		   { { 0x1E, 0x17 }, 2 },
> > > +		   { { 0x1F, 0x17 }, 2 },
> > > +		   /* STV */
> > > +		   { { 0x20, 0x40 }, 2 },
> > > +		   { { 0x21, 0x01 }, 2 },
> > > +		   { { 0x22, 0x00 }, 2 },
> > > +		   { { 0x23, 0x40 }, 2 },
> > > +		   { { 0x24, 0x40 }, 2 },
> > > +		   { { 0x25, 0x6D }, 2 },
> > > +		   { { 0x26, 0x40 }, 2 },
> > > +		   { { 0x27, 0x40 }, 2 },
> > > +		   /* Vend */
> > > +		   { { 0xE0, 0x00 }, 2 },
> > > +		   { { 0xDC, 0x21 }, 2 },
> > > +		   { { 0xDD, 0x22 }, 2 },
> > > +		   { { 0xDE, 0x07 }, 2 },
> > > +		   { { 0xDF, 0x07 }, 2 },
> > > +		   { { 0xE3, 0x6D }, 2 },
> > > +		   { { 0xE1, 0x07 }, 2 },
> > > +		   { { 0xE2, 0x07 }, 2 },
> > > +		   /* UD */
> > > +		   { { 0x29, 0xD8 }, 2 },
> > > +		   { { 0x2A, 0x2A }, 2 },
> > > +		   /* CLK */
> > > +		   { { 0x4B, 0x03 }, 2 },
> > > +		   { { 0x4C, 0x11 }, 2 },
> > > +		   { { 0x4D, 0x10 }, 2 },
> > > +		   { { 0x4E, 0x01 }, 2 },
> > > +		   { { 0x4F, 0x01 }, 2 },
> > > +		   { { 0x50, 0x10 }, 2 },
> > > +		   { { 0x51, 0x00 }, 2 },
> > > +		   { { 0x52, 0x80 }, 2 },
> > > +		   { { 0x53, 0x00 }, 2 },
> > > +		   { { 0x56, 0x00 }, 2 },
> > > +		   { { 0x54, 0x07 }, 2 },
> > > +		   { { 0x58, 0x07 }, 2 },
> > > +		   { { 0x55, 0x25 }, 2 },
> > > +		   /* Reset XDONB */
> > > +		   { { 0x5B, 0x43 }, 2 },
> > > +		   { { 0x5C, 0x00 }, 2 },
> > > +		   { { 0x5F, 0x73 }, 2 },
> > > +		   { { 0x60, 0x73 }, 2 },
> > > +		   { { 0x63, 0x22 }, 2 },
> > > +		   { { 0x64, 0x00 }, 2 },
> > > +		   { { 0x67, 0x08 }, 2 },
> > > +		   { { 0x68, 0x04 }, 2 },
> > > +		   /* Resolution:1440x2560 */
> > > +		   { { 0x72, 0x02 }, 2 },
> > > +		   /* mux */
> > > +		   { { 0x7A, 0x80 }, 2 },
> > > +		   { { 0x7B, 0x91 }, 2 },
> > > +		   { { 0x7C, 0xD8 }, 2 },
> > > +		   { { 0x7D, 0x60 }, 2 },
> > > +		   { { 0x7F, 0x15 }, 2 },
> > > +		   { { 0x75, 0x15 }, 2 },
> > > +		   /* ABOFF */
> > > +		   { { 0xB3, 0xC0 }, 2 },
> > > +		   { { 0xB4, 0x00 }, 2 },
> > > +		   { { 0xB5, 0x00 }, 2 },
> > > +		   /* Source EQ */
> > > +		   { { 0x78, 0x00 }, 2 },
> > > +		   { { 0x79, 0x00 }, 2 },
> > > +		   { { 0x80, 0x00 }, 2 },
> > > +		   { { 0x83, 0x00 }, 2 },
> > > +		   /* FP BP */
> > > +		   { { 0x93, 0x0A }, 2 },
> > > +		   { { 0x94, 0x0A }, 2 },
> > > +		   /* Inversion Type */
> > > +		   { { 0x8A, 0x00 }, 2 },
> > > +		   { { 0x9B, 0xFF }, 2 },
> > > +		   /* IMGSWAP =1 @PortSwap=1 */
> > > +		   { { 0x9D, 0xB0 }, 2 },
> > > +		   { { 0x9F, 0x63 }, 2 },
> > > +		   { { 0x98, 0x10 }, 2 },
> > > +		   /* FRM */
> > > +		   { { 0xEC, 0x00 }, 2 },
> > > +		   /* CMD1 */
> > > +		   { { 0xFF, 0x10 }, 2 },
> > > +		    /* VBP+VSA=,VFP = 10H */
> > > +		   { { 0x3B, 0x03, 0x0A, 0x0A, }, 4 },
> > > +		   /* FTE on */
> > > +		   { { 0x35, 0x00 }, 2 },
> > > +		   /* EN_BK =1(auto black) */
> > > +		   { { 0xE5, 0x01 }, 2 },
> > > +		   /* CMD mode(10) VDO mode(03) */
> > > +		   { { 0xBB, 0x03 }, 2 },
> > > +		   /* Non Reload MTP */
> > > +		   { { 0xFB, 0x01 }, 2 },
> > > +};
> > 
> > How many of these commands are specific to MTP? Decoding the cryptic
> > comments,
> > it seems like this probably wouldn't work on any other boards?
> > 
> > I see a couple of duplicate writes as well.
> > 
> > Finally, all but one command is 2 bytes, with the outlier being 4 bytes.
> > Yet,
> > MAX_LEN is 5. If we _must_ keep the huge list of obfuscated register
> > writes,
> > could we eliminate the size member?
> 
> [Abhinav] The name is probably misleading you here. MTP mentioned here is
> something
> specific to the panel. It has no relation to our MTP board.
> Hence none of these commands are specific to our MTP board. They are all
> related to
> the panel.
> 
> There are no duplicates. The sequences of the panel often demand the same
> command to
> be sent again in different places.
> 
> You are right, all the commands except one have 2 bytes of payload.
> However, the 4 byte long command has to be sent in between.
> If we want to get rid of the extra member element, I can break the commands
> into 3
> sets.
> First set of x commands with 2 byte payload, then the 4 byte payload
> command, then the
> remaining 2 byte payload commands.
> Let me know if that works for you.
> 
> I have tried to leave as much comments as possible about the command sets.
> It will be difficult to explain more.

Given your explanation, I think the above is fine. Modulo the MAX_LEN,
signedness and static const comments.

> > > +static int truly_wqxga_probe(struct mipi_dsi_device *dsi)
> > > +{
> > > +	struct device *dev = &dsi->dev;
> > > +	struct truly_wqxga *ctx;
> > > +	struct mipi_dsi_device *secondary;
> > > +	struct device_node *dsi1;
> > > +	struct mipi_dsi_host *dsi1_host;
> > > +	int ret = 0;
> > > +	const struct mipi_dsi_device_info info = {.type = "trulynt35597",
> > > +		.channel = 0,
> > > +		.node = NULL,
> > > +	};
> > > +
> > > +	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
> > > +
> > > +	if (!ctx)
> > > +		return -ENOMEM;
> > > +
> > > +	/* This device represents itself as one with
> > > +	 * two input ports which are fed by the output
> > > +	 * ports of the two DSI controllers . The DSI0
> > > +	 * is the master controller and has most of the
> > > +	 * panel related info in its child node.
> > > +	 */
> > > +
> > > +	dsi1 = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
> > > +	if (!dsi1) {
> > > +		dev_err(dev, "failed to get remote node for secondary DSI\n");
> > > +		ret = -ENODEV;
> > > +		goto err_get_remote;
> > > +	}
> > > +
> > > +	dsi1_host = of_find_mipi_dsi_host_by_node(dsi1);
> > > +	if (!dsi1_host) {
> > > +		dev_err(dev, "failed to find dsi host\n");
> > > +		ret = -EPROBE_DEFER;
> > > +		goto err_host;
> > > +	}
> > > +
> > > +	of_node_put(dsi1);
> > > +
> > > +	/* register the second DSI device */
> > > +	secondary = mipi_dsi_device_register_full(dsi1_host, &info);

Since this does dual DSI, are you aware of the dual-channel DSI bindings
that Archit (Cc'ed) has recently proposed?

	https://patchwork.freedesktop.org/patch/237057/

> > > +
> > 
> > nit: extra line
> > 
> > While I'm nitpicking, this name leaves something to be desired.
> > Everything else
> > is dsi1, so perhaps this could be dsi1_device to be consistent.
> > 
> [Abhinav] Agreed, will do.
> 
> > > +	if (IS_ERR(secondary)) {
> > > +		dev_err(dev, "failed to create dsi device\n");
> > > +		ret = PTR_ERR(dsi);
> > > +		goto err_dsi_device;
> > > +	}
> > > +
> > > +	mipi_dsi_set_drvdata(dsi, ctx);
> > > +
> > > +	ctx->dev = dev;
> > > +	ctx->dsi[0] = dsi;
> > > +	ctx->dsi[1] = secondary;
> > > +
> > > +	ret = truly_wqxga_panel_add(ctx);
> > > +	if (ret) {
> > > +		dev_err(dev, "failed to add panel\n");
> > > +		goto err_panel_add;
> > > +	}
> > > +
> > > +	/* configure master DSI device */
> > > +	dsi->lanes = 4;
> > > +	dsi->format = MIPI_DSI_FMT_RGB888;
> > > +	dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
> > > MIPI_DSI_CLOCK_NON_CONTINUOUS |
> > > +						MIPI_DSI_MODE_LPM;
> > > +
> > > +	ret = mipi_dsi_attach(dsi);
> > > +	if (ret < 0) {
> > > +		dev_err(dev, "master dsi attach failed\n");
> > > +		goto err_dsi_attach;
> > > +	}
> > > +
> > > +	/* configure secondary DSI device */
> > > +	secondary->lanes = 4;
> > > +	secondary->format = MIPI_DSI_FMT_RGB888;
> > > +	secondary->mode_flags = MIPI_DSI_MODE_VIDEO |
> > > +		MIPI_DSI_CLOCK_NON_CONTINUOUS |
> > > +		MIPI_DSI_MODE_LPM;
> > > +
> > > +	ret = mipi_dsi_attach(secondary);
> > > +	if (ret < 0) {
> > > +		dev_err(dev, "mipi_dsi_attach on secondary failed\n");
> > > +		goto err_dsi_attach_sec;
> > > +	}
> > 
> > Replace the duplicated attach code with a loop:
> > 
> >         for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) {
> >                 struct mipi_dsi_device *dsi_dev = ctx->dsi[i];
> > 
> >                 dsi_dev->lanes = 4;
> >                 dsi_dev->format = MIPI_DSI_FMT_RGB888;
> >                 dsi_dev->mode_flags = MIPI_DSI_MODE_VIDEO |
> > MIPI_DSI_MODE_LPM |
> >                                       MIPI_DSI_CLOCK_NON_CONTINUOUS;
> > 
> >                 ret = mipi_dsi_attach(dsi_dev);
> >                 if (ret < 0) {
> >                         DRM_DEV_ERROR(dev, "master dsi attach
> > failed\n");
> >                         goto err_dsi_attach;
> >                 }
> >         }
> > 
> [Abhinav] Agreed, will do.
> > > +
> > > +	return 0;
> > > +
> > > +err_dsi_attach_sec:
> > > +	mipi_dsi_detach(ctx->dsi[0]);
> > > +err_dsi_attach:
> > > +	truly_wqxga_panel_del(ctx);
> > > +err_panel_add:
> > > +	mipi_dsi_device_unregister(secondary);
> > > +err_dsi_device:
> > > +err_host:
> > > +	of_node_put(dsi1);
> > > +err_get_remote:
> > > +	return ret;
> > > +}
> > > +
> > > +static int truly_wqxga_remove(struct mipi_dsi_device *dsi)
> > > +{
> > > +	struct truly_wqxga *ctx = mipi_dsi_get_drvdata(dsi);
> > > +
> > > +	if (ctx->dsi[0])
> > > +		mipi_dsi_detach(ctx->dsi[0]);
> > > +	if (ctx->dsi[1]) {
> > > +		mipi_dsi_detach(ctx->dsi[1]);
> > > +		mipi_dsi_device_unregister(ctx->dsi[1]);
> > > +	}
> > > +	truly_wqxga_panel_del(ctx);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct of_device_id truly_wqxga_of_match[] = {
> > > +	{ .compatible = "truly,nt35597", },
> > > +	{ }
> > > +};
> > > +MODULE_DEVICE_TABLE(of, truly_wqxga_of_match);
> > > +
> > > +static struct mipi_dsi_driver truly_wqxga_driver = {
> > > +	.driver = {
> > > +		.name = "panel_truly_nt35597",

I generally prefer dashes to underscores in driver names, in this case:
"panel-truly-nt35597".

Thierry

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

      reply	other threads:[~2018-07-10  9:44 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-26  0:27 [PATCH v4 1/2] drm/panel: Add support for Truly NT35597 panel Abhinav Kumar
2018-05-26  0:27 ` [PATCH v4 2/2] dt-bindings: Add Truly NT35597 panel bindings Abhinav Kumar
2018-05-30 15:47 ` [PATCH v4 1/2] drm/panel: Add support for Truly NT35597 panel Jordan Crouse
2018-05-30 19:14   ` Sean Paul
2018-05-30 19:12 ` Sean Paul
2018-05-30 22:37   ` abhinavk
2018-07-10  9:44     ` Thierry Reding [this message]

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=20180710094444.GB1504@ulmo \
    --to=thierry.reding@gmail.com \
    --cc=abhinavk@codeaurora.org \
    --cc=chandanu@codeaurora.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hoegsberg@google.com \
    --cc=linux-arm-msm@vger.kernel.org \
    /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.