diff mbox series

[v2,4/9] drm/panel: Add driver for the LG Philips LB035Q02 panel

Message ID 20190810231048.1921-5-laurent.pinchart@ideasonboard.com (mailing list archive)
State New, archived
Headers show
Series DRM panel drivers for omapdrm | expand

Commit Message

Laurent Pinchart Aug. 10, 2019, 11:10 p.m. UTC
This panel is used on the Gumstix Overo Palo35.

The code is based on the omapdrm-specific panel-lgphilips-lb035q02
driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
---
Changes since v1:

- Comments updates
- Store width_mm and height_mm in drm_display_mode
- Use drm_panel_disable() in .remove() handler
---
 drivers/gpu/drm/panel/Kconfig             |   8 +
 drivers/gpu/drm/panel/Makefile            |   1 +
 drivers/gpu/drm/panel/panel-lg-lb035q02.c | 237 ++++++++++++++++++++++
 3 files changed, 246 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-lg-lb035q02.c

Comments

Noralf Trønnes Aug. 11, 2019, 1:19 p.m. UTC | #1
Sam,

Den 11.08.2019 01.10, skrev Laurent Pinchart:
> This panel is used on the Gumstix Overo Palo35.
> 
> The code is based on the omapdrm-specific panel-lgphilips-lb035q02
> driver.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> ---

<snip>

> diff --git a/drivers/gpu/drm/panel/panel-lg-lb035q02.c b/drivers/gpu/drm/panel/panel-lg-lb035q02.c

<snip>

> +static int lb035q02_write(struct lb035q02_device *lcd, u16 reg, u16 val)
> +{
> +	struct spi_message msg;
> +	struct spi_transfer index_xfer = {
> +		.len		= 3,
> +		.cs_change	= 1,
> +	};
> +	struct spi_transfer value_xfer = {
> +		.len		= 3,
> +	};
> +	u8	buffer[16];
> +
> +	spi_message_init(&msg);
> +
> +	/* register index */
> +	buffer[0] = 0x70;
> +	buffer[1] = 0x00;
> +	buffer[2] = reg & 0x7f;
> +	index_xfer.tx_buf = buffer;
> +	spi_message_add_tail(&index_xfer, &msg);
> +
> +	/* register value */
> +	buffer[4] = 0x72;
> +	buffer[5] = val >> 8;
> +	buffer[6] = val;
> +	value_xfer.tx_buf = buffer + 4;
> +	spi_message_add_tail(&value_xfer, &msg);
> +
> +	return spi_sync(lcd->spi, &msg);
> +}

Just a note to Sam:
This is the same spi protocol that the ili9325 controller on the hy28b
panel uses.

I remembered that I have experimented with a regmap implementation:
https://github.com/notro/tinydrm/blob/master/tinydrm-ili9325.c#L191

Noralf.
Laurent Pinchart Aug. 11, 2019, 1:35 p.m. UTC | #2
Hi Noralf,

On Sun, Aug 11, 2019 at 03:19:13PM +0200, Noralf Trønnes wrote:
> Sam,
> 
> Den 11.08.2019 01.10, skrev Laurent Pinchart:
> > This panel is used on the Gumstix Overo Palo35.
> > 
> > The code is based on the omapdrm-specific panel-lgphilips-lb035q02
> > driver.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> > ---
> 
> <snip>
> 
> > diff --git a/drivers/gpu/drm/panel/panel-lg-lb035q02.c b/drivers/gpu/drm/panel/panel-lg-lb035q02.c
> 
> <snip>
> 
> > +static int lb035q02_write(struct lb035q02_device *lcd, u16 reg, u16 val)
> > +{
> > +	struct spi_message msg;
> > +	struct spi_transfer index_xfer = {
> > +		.len		= 3,
> > +		.cs_change	= 1,
> > +	};
> > +	struct spi_transfer value_xfer = {
> > +		.len		= 3,
> > +	};
> > +	u8	buffer[16];
> > +
> > +	spi_message_init(&msg);
> > +
> > +	/* register index */
> > +	buffer[0] = 0x70;
> > +	buffer[1] = 0x00;
> > +	buffer[2] = reg & 0x7f;
> > +	index_xfer.tx_buf = buffer;
> > +	spi_message_add_tail(&index_xfer, &msg);
> > +
> > +	/* register value */
> > +	buffer[4] = 0x72;
> > +	buffer[5] = val >> 8;
> > +	buffer[6] = val;
> > +	value_xfer.tx_buf = buffer + 4;
> > +	spi_message_add_tail(&value_xfer, &msg);
> > +
> > +	return spi_sync(lcd->spi, &msg);
> > +}
> 
> Just a note to Sam:
> This is the same spi protocol that the ili9325 controller on the hy28b
> panel uses.
> 
> I remembered that I have experimented with a regmap implementation:
> https://github.com/notro/tinydrm/blob/master/tinydrm-ili9325.c#L191

That's useful information, thanks. The controller seems different
though, the limited information available in
https://www.beyondinfinite.com/lcd/Library/LG-Philips/LB035Q02.pdf
doesn't match the registers from
https://github.com/notro/tinydrm/blob/master/fb_ili9325.c.
Noralf Trønnes Aug. 11, 2019, 2:13 p.m. UTC | #3
Hi Laurent,

Den 11.08.2019 15.35, skrev Laurent Pinchart:
> Hi Noralf,
> 
> On Sun, Aug 11, 2019 at 03:19:13PM +0200, Noralf Trønnes wrote:
>> Sam,
>>
>> Den 11.08.2019 01.10, skrev Laurent Pinchart:
>>> This panel is used on the Gumstix Overo Palo35.
>>>
>>> The code is based on the omapdrm-specific panel-lgphilips-lb035q02
>>> driver.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
>>> ---
>>
>> <snip>
>>
>>> diff --git a/drivers/gpu/drm/panel/panel-lg-lb035q02.c b/drivers/gpu/drm/panel/panel-lg-lb035q02.c
>>
>> <snip>
>>
>>> +static int lb035q02_write(struct lb035q02_device *lcd, u16 reg, u16 val)
>>> +{
>>> +	struct spi_message msg;
>>> +	struct spi_transfer index_xfer = {
>>> +		.len		= 3,
>>> +		.cs_change	= 1,
>>> +	};
>>> +	struct spi_transfer value_xfer = {
>>> +		.len		= 3,
>>> +	};
>>> +	u8	buffer[16];
>>> +
>>> +	spi_message_init(&msg);
>>> +
>>> +	/* register index */
>>> +	buffer[0] = 0x70;
>>> +	buffer[1] = 0x00;
>>> +	buffer[2] = reg & 0x7f;
>>> +	index_xfer.tx_buf = buffer;
>>> +	spi_message_add_tail(&index_xfer, &msg);
>>> +
>>> +	/* register value */
>>> +	buffer[4] = 0x72;
>>> +	buffer[5] = val >> 8;
>>> +	buffer[6] = val;
>>> +	value_xfer.tx_buf = buffer + 4;
>>> +	spi_message_add_tail(&value_xfer, &msg);
>>> +
>>> +	return spi_sync(lcd->spi, &msg);
>>> +}
>>
>> Just a note to Sam:
>> This is the same spi protocol that the ili9325 controller on the hy28b
>> panel uses.
>>
>> I remembered that I have experimented with a regmap implementation:
>> https://github.com/notro/tinydrm/blob/master/tinydrm-ili9325.c#L191
> 
> That's useful information, thanks. The controller seems different
> though, the limited information available in
> https://www.beyondinfinite.com/lcd/Library/LG-Philips/LB035Q02.pdf
> doesn't match the registers from
> https://github.com/notro/tinydrm/blob/master/fb_ili9325.c.
> 

I've seen several controllers that use this protocol, and one that had a
different start byte configuration. The details unfortunately is lost in
time, it's been a while since I worked on these controllers.

Noralf.
Sam Ravnborg Aug. 11, 2019, 4:49 p.m. UTC | #4
Hi Noralf.

> > +static int lb035q02_write(struct lb035q02_device *lcd, u16 reg, u16 val)
> > +{
> > +	struct spi_message msg;
> > +	struct spi_transfer index_xfer = {
> > +		.len		= 3,
> > +		.cs_change	= 1,
> > +	};
> > +	struct spi_transfer value_xfer = {
> > +		.len		= 3,
> > +	};
> > +	u8	buffer[16];
> > +
> > +	spi_message_init(&msg);
> > +
> > +	/* register index */
> > +	buffer[0] = 0x70;
> > +	buffer[1] = 0x00;
> > +	buffer[2] = reg & 0x7f;
> > +	index_xfer.tx_buf = buffer;
> > +	spi_message_add_tail(&index_xfer, &msg);
> > +
> > +	/* register value */
> > +	buffer[4] = 0x72;
> > +	buffer[5] = val >> 8;
> > +	buffer[6] = val;
> > +	value_xfer.tx_buf = buffer + 4;
> > +	spi_message_add_tail(&value_xfer, &msg);
> > +
> > +	return spi_sync(lcd->spi, &msg);
> > +}
> 
> Just a note to Sam:
> This is the same spi protocol that the ili9325 controller on the hy28b
> panel uses.
> 
> I remembered that I have experimented with a regmap implementation:
> https://github.com/notro/tinydrm/blob/master/tinydrm-ili9325.c#L191

regmap seems a too limited interface to use when trying to generalize
this.
We should rather go for a ili-lib or something that can be used in all
the present and future ili based drivers.
Obviously it depends on how similar the ili based chips are.

I did a quick look and this driver did not match the ili9325 datasheet
as different bits was are in register 0x1.
So it smeels like another, similar. ili varaint.

So for this driver we would just use the hardcoded varaint already
present. Then we may re-visit ili-lib idea later if we see too much
similar code.
This is as I see it for now...

	Sam
Noralf Trønnes Aug. 11, 2019, 5:20 p.m. UTC | #5
Den 11.08.2019 18.49, skrev Sam Ravnborg:
> Hi Noralf.
> 
>>> +static int lb035q02_write(struct lb035q02_device *lcd, u16 reg, u16 val)
>>> +{
>>> +	struct spi_message msg;
>>> +	struct spi_transfer index_xfer = {
>>> +		.len		= 3,
>>> +		.cs_change	= 1,
>>> +	};
>>> +	struct spi_transfer value_xfer = {
>>> +		.len		= 3,
>>> +	};
>>> +	u8	buffer[16];
>>> +
>>> +	spi_message_init(&msg);
>>> +
>>> +	/* register index */
>>> +	buffer[0] = 0x70;
>>> +	buffer[1] = 0x00;
>>> +	buffer[2] = reg & 0x7f;
>>> +	index_xfer.tx_buf = buffer;
>>> +	spi_message_add_tail(&index_xfer, &msg);
>>> +
>>> +	/* register value */
>>> +	buffer[4] = 0x72;
>>> +	buffer[5] = val >> 8;
>>> +	buffer[6] = val;
>>> +	value_xfer.tx_buf = buffer + 4;
>>> +	spi_message_add_tail(&value_xfer, &msg);
>>> +
>>> +	return spi_sync(lcd->spi, &msg);
>>> +}
>>
>> Just a note to Sam:
>> This is the same spi protocol that the ili9325 controller on the hy28b
>> panel uses.
>>
>> I remembered that I have experimented with a regmap implementation:
>> https://github.com/notro/tinydrm/blob/master/tinydrm-ili9325.c#L191
> 
> regmap seems a too limited interface to use when trying to generalize
> this.
> We should rather go for a ili-lib or something that can be used in all
> the present and future ili based drivers.
> Obviously it depends on how similar the ili based chips are.
> 
> I did a quick look and this driver did not match the ili9325 datasheet
> as different bits was are in register 0x1.
> So it smeels like another, similar. ili varaint.
> 
> So for this driver we would just use the hardcoded varaint already
> present. Then we may re-visit ili-lib idea later if we see too much
> similar code.
> This is as I see it for now...
> 

Yeah, no point in changing this driver until there are more similar
controllers. Just wanted to point out that the hy28b panel you ordered
uses the same protocol.

A web search helped my memory, these 3 supported by staging/fbtft use a
startbyte: ili9320, ili9325 and hx8347d. The ili chips are almost
identical. The search revealed many more including:
st7793, st7781r, S6E63D6, +many ilitek.

Noralf.
Sam Ravnborg Aug. 11, 2019, 5:26 p.m. UTC | #6
Hi Noralf.

> >>> +	/* register value */
> >>> +	buffer[4] = 0x72;
> >>> +	buffer[5] = val >> 8;
> >>> +	buffer[6] = val;
> >>> +	value_xfer.tx_buf = buffer + 4;
> >>> +	spi_message_add_tail(&value_xfer, &msg);
> >>> +
> >>> +	return spi_sync(lcd->spi, &msg);
> >>> +}
> >>
> >> Just a note to Sam:
> >> This is the same spi protocol that the ili9325 controller on the hy28b
> >> panel uses.
> >>
> >> I remembered that I have experimented with a regmap implementation:
> >> https://github.com/notro/tinydrm/blob/master/tinydrm-ili9325.c#L191
> > 
> > regmap seems a too limited interface to use when trying to generalize
> > this.
> > We should rather go for a ili-lib or something that can be used in all
> > the present and future ili based drivers.
> > Obviously it depends on how similar the ili based chips are.
> > 
> > I did a quick look and this driver did not match the ili9325 datasheet
> > as different bits was are in register 0x1.
> > So it smeels like another, similar. ili varaint.
> > 
> > So for this driver we would just use the hardcoded varaint already
> > present. Then we may re-visit ili-lib idea later if we see too much
> > similar code.
> > This is as I see it for now...
> > 
> 
> Yeah, no point in changing this driver until there are more similar
> controllers. Just wanted to point out that the hy28b panel you ordered
> uses the same protocol.
Ohh, that was your point. Thanks!

The display is still in the mail somewhere from China..
Right now I do not have time to hack on it so not a big deal.

For the fun of it I ordred a few other displays. One was ssd1306 based,
and do not recall the rest.

	Sam

> 
> A web search helped my memory, these 3 supported by staging/fbtft use a
> startbyte: ili9320, ili9325 and hx8347d. The ili chips are almost
> identical. The search revealed many more including:
> st7793, st7781r, S6E63D6, +many ilitek.
> 
> Noralf.
diff mbox series

Patch

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index eaecd40cc32e..87cdc330672b 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -103,6 +103,14 @@  config DRM_PANEL_SAMSUNG_LD9040
 	depends on OF && SPI
 	select VIDEOMODE_HELPERS
 
+config DRM_PANEL_LG_LB035Q02
+	tristate "LG LB035Q024573 RGB panel"
+	depends on GPIOLIB && OF && SPI
+	help
+	  Say Y here if you want to enable support for the LB035Q02 RGB panel
+	  (found on the Gumstix Overo Palo35 board). To compile this driver as
+	  a module, choose M here.
+
 config DRM_PANEL_LG_LG4573
 	tristate "LG4573 RGB/SPI panel"
 	depends on OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 62dae45f8f74..9bc6f3c5bf96 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -8,6 +8,7 @@  obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
 obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
 obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o
+obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
 obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
 obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o
diff --git a/drivers/gpu/drm/panel/panel-lg-lb035q02.c b/drivers/gpu/drm/panel/panel-lg-lb035q02.c
new file mode 100644
index 000000000000..694489fb91b2
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-lg-lb035q02.c
@@ -0,0 +1,237 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * LG.Philips LB035Q02 LCD Panel Driver
+ *
+ * Copyright (C) 2019 Texas Instruments Incorporated
+ *
+ * Based on the omapdrm-specific panel-lgphilips-lb035q02 driver
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * Based on a driver by: Steve Sakoman <steve@sakoman.com>
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct lb035q02_device {
+	struct drm_panel panel;
+
+	struct spi_device *spi;
+	struct gpio_desc *enable_gpio;
+};
+
+#define to_lb035q02_device(p) container_of(p, struct lb035q02_device, panel)
+
+static int lb035q02_write(struct lb035q02_device *lcd, u16 reg, u16 val)
+{
+	struct spi_message msg;
+	struct spi_transfer index_xfer = {
+		.len		= 3,
+		.cs_change	= 1,
+	};
+	struct spi_transfer value_xfer = {
+		.len		= 3,
+	};
+	u8	buffer[16];
+
+	spi_message_init(&msg);
+
+	/* register index */
+	buffer[0] = 0x70;
+	buffer[1] = 0x00;
+	buffer[2] = reg & 0x7f;
+	index_xfer.tx_buf = buffer;
+	spi_message_add_tail(&index_xfer, &msg);
+
+	/* register value */
+	buffer[4] = 0x72;
+	buffer[5] = val >> 8;
+	buffer[6] = val;
+	value_xfer.tx_buf = buffer + 4;
+	spi_message_add_tail(&value_xfer, &msg);
+
+	return spi_sync(lcd->spi, &msg);
+}
+
+static int lb035q02_init(struct lb035q02_device *lcd)
+{
+	/* Init sequence from page 28 of the lb035q02 spec. */
+	static const struct {
+		u16 index;
+		u16 value;
+	} init_data[] = {
+		{ 0x01, 0x6300 },
+		{ 0x02, 0x0200 },
+		{ 0x03, 0x0177 },
+		{ 0x04, 0x04c7 },
+		{ 0x05, 0xffc0 },
+		{ 0x06, 0xe806 },
+		{ 0x0a, 0x4008 },
+		{ 0x0b, 0x0000 },
+		{ 0x0d, 0x0030 },
+		{ 0x0e, 0x2800 },
+		{ 0x0f, 0x0000 },
+		{ 0x16, 0x9f80 },
+		{ 0x17, 0x0a0f },
+		{ 0x1e, 0x00c1 },
+		{ 0x30, 0x0300 },
+		{ 0x31, 0x0007 },
+		{ 0x32, 0x0000 },
+		{ 0x33, 0x0000 },
+		{ 0x34, 0x0707 },
+		{ 0x35, 0x0004 },
+		{ 0x36, 0x0302 },
+		{ 0x37, 0x0202 },
+		{ 0x3a, 0x0a0d },
+		{ 0x3b, 0x0806 },
+	};
+
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(init_data); ++i) {
+		ret = lb035q02_write(lcd, init_data[i].index,
+				     init_data[i].value);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int lb035q02_disable(struct drm_panel *panel)
+{
+	struct lb035q02_device *lcd = to_lb035q02_device(panel);
+
+	gpiod_set_value_cansleep(lcd->enable_gpio, 0);
+
+	return 0;
+}
+
+static int lb035q02_enable(struct drm_panel *panel)
+{
+	struct lb035q02_device *lcd = to_lb035q02_device(panel);
+
+	gpiod_set_value_cansleep(lcd->enable_gpio, 1);
+
+	return 0;
+}
+
+static const struct drm_display_mode lb035q02_mode = {
+	.clock = 6500,
+	.hdisplay = 320,
+	.hsync_start = 320 + 20,
+	.hsync_end = 320 + 20 + 2,
+	.htotal = 320 + 20 + 2 + 68,
+	.vdisplay = 240,
+	.vsync_start = 240 + 4,
+	.vsync_end = 240 + 4 + 2,
+	.vtotal = 240 + 4 + 2 + 18,
+	.vrefresh = 60,
+	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+	.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+	.width_mm = 70,
+	.height_mm = 53,
+};
+
+static int lb035q02_get_modes(struct drm_panel *panel)
+{
+	struct drm_connector *connector = panel->connector;
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(panel->drm, &lb035q02_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+	drm_mode_probed_add(connector, mode);
+
+	connector->display_info.width_mm = lb035q02_mode.width_mm;
+	connector->display_info.height_mm = lb035q02_mode.height_mm;
+	/*
+	 * FIXME: According to the datasheet pixel data is sampled on the
+	 * rising edge of the clock, but the code running on the Gumstix Overo
+	 * Palo35 indicates sampling on the negative edge. This should be
+	 * tested on a real device.
+	 */
+	connector->display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH
+					  | DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE
+					  | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
+
+	return 1;
+}
+
+static const struct drm_panel_funcs lb035q02_funcs = {
+	.disable = lb035q02_disable,
+	.enable = lb035q02_enable,
+	.get_modes = lb035q02_get_modes,
+};
+
+static int lb035q02_probe(struct spi_device *spi)
+{
+	struct lb035q02_device *lcd;
+	int ret;
+
+	lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
+	if (lcd == NULL)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, lcd);
+	lcd->spi = spi;
+
+	lcd->enable_gpio = devm_gpiod_get(&spi->dev, "enable", GPIOD_OUT_LOW);
+	if (IS_ERR(lcd->enable_gpio)) {
+		dev_err(&spi->dev, "failed to parse enable gpio\n");
+		return PTR_ERR(lcd->enable_gpio);
+	}
+
+	ret = lb035q02_init(lcd);
+	if (ret < 0)
+		return ret;
+
+	drm_panel_init(&lcd->panel);
+	lcd->panel.dev = &lcd->spi->dev;
+	lcd->panel.funcs = &lb035q02_funcs;
+
+	return drm_panel_add(&lcd->panel);
+}
+
+static int lb035q02_remove(struct spi_device *spi)
+{
+	struct lb035q02_device *lcd = spi_get_drvdata(spi);
+
+	drm_panel_remove(&lcd->panel);
+	drm_panel_disable(&lcd->panel);
+
+	return 0;
+}
+
+static const struct of_device_id lb035q02_of_match[] = {
+	{ .compatible = "lgphilips,lb035q02", },
+	{ /* sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, lb035q02_of_match);
+
+static struct spi_driver lb035q02_driver = {
+	.probe		= lb035q02_probe,
+	.remove		= lb035q02_remove,
+	.driver		= {
+		.name	= "panel-lg-lb035q02",
+		.of_match_table = lb035q02_of_match,
+	},
+};
+
+module_spi_driver(lb035q02_driver);
+
+MODULE_ALIAS("spi:lgphilips,lb035q02");
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("LG.Philips LB035Q02 LCD Panel driver");
+MODULE_LICENSE("GPL");