1f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen/* 2f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen * LG.Philips LB035Q02 LCD Panel driver 3f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen * 4f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen * Copyright (C) 2013 Texas Instruments 5f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> 6f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen * Based on a driver by: Steve Sakoman <steve@sakoman.com> 7f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen * 8f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen * This program is free software; you can redistribute it and/or modify it 9f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen * under the terms of the GNU General Public License version 2 as published by 10f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen * the Free Software Foundation. 11f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen */ 12f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 13f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen#include <linux/module.h> 14f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen#include <linux/delay.h> 15f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen#include <linux/spi/spi.h> 16f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen#include <linux/mutex.h> 17f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen#include <linux/gpio.h> 18f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 19f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen#include <video/omapdss.h> 20f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen#include <video/omap-panel-data.h> 21f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 22f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic struct omap_video_timings lb035q02_timings = { 23f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .x_res = 320, 24f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .y_res = 240, 25f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 26d8d789416aa71253c6532c9adc7469cb947031f6Tomi Valkeinen .pixelclock = 6500000, 27f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 28f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .hsw = 2, 29f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .hfp = 20, 30f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .hbp = 68, 31f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 32f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .vsw = 2, 33f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .vfp = 4, 34f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .vbp = 18, 35f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 36f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, 37f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, 38f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, 39f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .de_level = OMAPDSS_SIG_ACTIVE_HIGH, 40f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, 41f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen}; 42f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 43f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstruct panel_drv_data { 44f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device dssdev; 45f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *in; 46f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 47f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct spi_device *spi; 48f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 49f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen int data_lines; 50f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 51f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_video_timings videomode; 52f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 53fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen /* used for non-DT boot, to be removed */ 54f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen int backlight_gpio; 55fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen 56fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen struct gpio_desc *enable_gpio; 57f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen}; 58f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 59f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) 60f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 61f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val) 62f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 63f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct spi_message msg; 64f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct spi_transfer index_xfer = { 65f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .len = 3, 66f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .cs_change = 1, 67f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen }; 68f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct spi_transfer value_xfer = { 69f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .len = 3, 70f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen }; 71f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen u8 buffer[16]; 72f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 73f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen spi_message_init(&msg); 74f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 75f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen /* register index */ 76f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen buffer[0] = 0x70; 77f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen buffer[1] = 0x00; 78f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen buffer[2] = reg & 0x7f; 79f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen index_xfer.tx_buf = buffer; 80f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen spi_message_add_tail(&index_xfer, &msg); 81f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 82f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen /* register value */ 83f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen buffer[4] = 0x72; 84f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen buffer[5] = val >> 8; 85f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen buffer[6] = val; 86f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen value_xfer.tx_buf = buffer + 4; 87f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen spi_message_add_tail(&value_xfer, &msg); 88f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 89f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return spi_sync(spi, &msg); 90f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 91f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 92f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic void init_lb035q02_panel(struct spi_device *spi) 93f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 94f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen /* Init sequence from page 28 of the lb035q02 spec */ 95f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x01, 0x6300); 96f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x02, 0x0200); 97f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x03, 0x0177); 98f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x04, 0x04c7); 99f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x05, 0xffc0); 100f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x06, 0xe806); 101f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x0a, 0x4008); 102f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x0b, 0x0000); 103f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x0d, 0x0030); 104f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x0e, 0x2800); 105f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x0f, 0x0000); 106f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x16, 0x9f80); 107f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x17, 0x0a0f); 108f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x1e, 0x00c1); 109f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x30, 0x0300); 110f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x31, 0x0007); 111f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x32, 0x0000); 112f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x33, 0x0000); 113f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x34, 0x0707); 114f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x35, 0x0004); 115f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x36, 0x0302); 116f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x37, 0x0202); 117f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x3a, 0x0a0d); 118f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_write_reg(spi, 0x3b, 0x0806); 119f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 120f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 121f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic int lb035q02_connect(struct omap_dss_device *dssdev) 122f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 123f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata = to_panel_data(dssdev); 124f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *in = ddata->in; 125f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen int r; 126f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 127f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (omapdss_device_is_connected(dssdev)) 128f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return 0; 129f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 130f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen r = in->ops.dpi->connect(in, dssdev); 131f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (r) 132f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return r; 133f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 134f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen init_lb035q02_panel(ddata->spi); 135f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 136f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return 0; 137f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 138f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 139f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic void lb035q02_disconnect(struct omap_dss_device *dssdev) 140f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 141f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata = to_panel_data(dssdev); 142f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *in = ddata->in; 143f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 144f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (!omapdss_device_is_connected(dssdev)) 145f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return; 146f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 147f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen in->ops.dpi->disconnect(in, dssdev); 148f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 149f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 150f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic int lb035q02_enable(struct omap_dss_device *dssdev) 151f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 152f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata = to_panel_data(dssdev); 153f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *in = ddata->in; 154f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen int r; 155f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 156f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (!omapdss_device_is_connected(dssdev)) 157f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return -ENODEV; 158f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 159f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (omapdss_device_is_enabled(dssdev)) 160f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return 0; 161f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 1621b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen if (ddata->data_lines) 1631b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen in->ops.dpi->set_data_lines(in, ddata->data_lines); 164f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen in->ops.dpi->set_timings(in, &ddata->videomode); 165f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 166f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen r = in->ops.dpi->enable(in); 167f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (r) 168f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return r; 169f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 170fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen if (ddata->enable_gpio) 171fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen gpiod_set_value_cansleep(ddata->enable_gpio, 1); 172f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 173f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (gpio_is_valid(ddata->backlight_gpio)) 174f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen gpio_set_value_cansleep(ddata->backlight_gpio, 1); 175f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 176f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 177f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 178f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return 0; 179f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 180f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 181f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic void lb035q02_disable(struct omap_dss_device *dssdev) 182f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 183f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata = to_panel_data(dssdev); 184f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *in = ddata->in; 185f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 186f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (!omapdss_device_is_enabled(dssdev)) 187f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return; 188f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 189fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen if (ddata->enable_gpio) 190fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen gpiod_set_value_cansleep(ddata->enable_gpio, 0); 191f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 192f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (gpio_is_valid(ddata->backlight_gpio)) 193f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen gpio_set_value_cansleep(ddata->backlight_gpio, 0); 194f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 195f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen in->ops.dpi->disable(in); 196f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 197f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 198f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 199f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 200f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic void lb035q02_set_timings(struct omap_dss_device *dssdev, 201f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_video_timings *timings) 202f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 203f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata = to_panel_data(dssdev); 204f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *in = ddata->in; 205f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 206f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen ddata->videomode = *timings; 207f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->panel.timings = *timings; 208f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 209f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen in->ops.dpi->set_timings(in, timings); 210f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 211f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 212f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic void lb035q02_get_timings(struct omap_dss_device *dssdev, 213f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_video_timings *timings) 214f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 215f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata = to_panel_data(dssdev); 216f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 217f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen *timings = ddata->videomode; 218f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 219f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 220f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic int lb035q02_check_timings(struct omap_dss_device *dssdev, 221f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_video_timings *timings) 222f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 223f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata = to_panel_data(dssdev); 224f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *in = ddata->in; 225f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 226f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return in->ops.dpi->check_timings(in, timings); 227f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 228f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 229f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic struct omap_dss_driver lb035q02_ops = { 230f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .connect = lb035q02_connect, 231f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .disconnect = lb035q02_disconnect, 232f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 233f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .enable = lb035q02_enable, 234f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .disable = lb035q02_disable, 235f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 236f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .set_timings = lb035q02_set_timings, 237f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .get_timings = lb035q02_get_timings, 238f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .check_timings = lb035q02_check_timings, 239f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 240f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .get_resolution = omapdss_default_get_resolution, 241f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen}; 242f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 243f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic int lb035q02_probe_pdata(struct spi_device *spi) 244f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 245f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen const struct panel_lb035q02_platform_data *pdata; 246f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); 247f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *dssdev, *in; 248fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen int r; 249f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 250f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen pdata = dev_get_platdata(&spi->dev); 251f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 252f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen in = omap_dss_find_output(pdata->source); 253f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (in == NULL) { 254f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dev_err(&spi->dev, "failed to find video source '%s'\n", 255f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen pdata->source); 256f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return -EPROBE_DEFER; 257f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen } 258f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 259f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen ddata->in = in; 260f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 261f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen ddata->data_lines = pdata->data_lines; 262f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 263f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev = &ddata->dssdev; 264f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->name = pdata->name; 265f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 266fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen r = devm_gpio_request_one(&spi->dev, pdata->enable_gpio, 267fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen GPIOF_OUT_INIT_LOW, "panel enable"); 268fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen if (r) 269fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen goto err_gpio; 270fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen 271fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen ddata->enable_gpio = gpio_to_desc(pdata->enable_gpio); 272fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen 273f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen ddata->backlight_gpio = pdata->backlight_gpio; 274f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 275f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return 0; 276fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinenerr_gpio: 277fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen omap_dss_put_device(ddata->in); 278fbf7309823a15da2b96e8e15781b8ac9074b44c0Tomi Valkeinen return r; 279f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 280f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 2811b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinenstatic int lb035q02_probe_of(struct spi_device *spi) 2821b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen{ 2831b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen struct device_node *node = spi->dev.of_node; 2841b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); 2851b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen struct omap_dss_device *in; 2861b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen struct gpio_desc *gpio; 2871b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen 2881b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen gpio = devm_gpiod_get(&spi->dev, "enable"); 2891b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen if (IS_ERR(gpio)) { 2901b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen dev_err(&spi->dev, "failed to parse enable gpio\n"); 2911b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen return PTR_ERR(gpio); 2921b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen } else { 2931b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen gpiod_direction_output(gpio, 0); 2941b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen ddata->enable_gpio = gpio; 2951b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen } 2961b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen 2971b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen ddata->backlight_gpio = -ENOENT; 2981b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen 2991b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen in = omapdss_of_find_source_for_first_ep(node); 3001b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen if (IS_ERR(in)) { 3011b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen dev_err(&spi->dev, "failed to find video source\n"); 3021b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen return PTR_ERR(in); 3031b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen } 3041b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen 3051b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen ddata->in = in; 3061b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen 3071b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen return 0; 3081b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen} 3091b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen 310f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic int lb035q02_panel_spi_probe(struct spi_device *spi) 311f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 312f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata; 313f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *dssdev; 314f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen int r; 315f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 316f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL); 317f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (ddata == NULL) 318f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return -ENOMEM; 319f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 320f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dev_set_drvdata(&spi->dev, ddata); 321f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 322f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen ddata->spi = spi; 323f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 324f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (dev_get_platdata(&spi->dev)) { 325f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen r = lb035q02_probe_pdata(spi); 326f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (r) 327f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return r; 3281b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen } else if (spi->dev.of_node) { 3291b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen r = lb035q02_probe_of(spi); 3301b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen if (r) 3311b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen return r; 332f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen } else { 333f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return -ENODEV; 334f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen } 335f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 336f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (gpio_is_valid(ddata->backlight_gpio)) { 337f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen r = devm_gpio_request_one(&spi->dev, ddata->backlight_gpio, 338f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen GPIOF_OUT_INIT_LOW, "panel backlight"); 339f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (r) 340f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen goto err_gpio; 341f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen } 342f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 343f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen ddata->videomode = lb035q02_timings; 344f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 345f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev = &ddata->dssdev; 346f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->dev = &spi->dev; 347f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->driver = &lb035q02_ops; 348f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->type = OMAP_DISPLAY_TYPE_DPI; 349f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->owner = THIS_MODULE; 350f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->panel.timings = ddata->videomode; 351f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dssdev->phy.dpi.data_lines = ddata->data_lines; 352f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 353f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen r = omapdss_register_display(dssdev); 354f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen if (r) { 355f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen dev_err(&spi->dev, "Failed to register panel\n"); 356f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen goto err_reg; 357f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen } 358f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 359f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return 0; 360f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 361f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenerr_reg: 362f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenerr_gpio: 363f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen omap_dss_put_device(ddata->in); 364f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return r; 365f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 366f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 367f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic int lb035q02_panel_spi_remove(struct spi_device *spi) 368f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen{ 369f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); 370f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *dssdev = &ddata->dssdev; 371f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen struct omap_dss_device *in = ddata->in; 372f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 373f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen omapdss_unregister_display(dssdev); 374f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 375f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_disable(dssdev); 376f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen lb035q02_disconnect(dssdev); 377f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 378f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen omap_dss_put_device(in); 379f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 380f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen return 0; 381f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen} 382f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 3831b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinenstatic const struct of_device_id lb035q02_of_match[] = { 3841b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen { .compatible = "omapdss,lgphilips,lb035q02", }, 3851b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen {}, 3861b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen}; 3871b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen 3881b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi ValkeinenMODULE_DEVICE_TABLE(of, lb035q02_of_match); 3891b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen 390f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenstatic struct spi_driver lb035q02_spi_driver = { 391f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .probe = lb035q02_panel_spi_probe, 392f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .remove = lb035q02_panel_spi_remove, 393f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .driver = { 394f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .name = "panel_lgphilips_lb035q02", 395f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen .owner = THIS_MODULE, 3961b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi Valkeinen .of_match_table = lb035q02_of_match, 397422ccbd57170d18cfd9d4c0cdbdd4603929fc51bTomi Valkeinen .suppress_bind_attrs = true, 398f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen }, 399f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen}; 400f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 401f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinenmodule_spi_driver(lb035q02_spi_driver); 402f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi Valkeinen 4031b71f1047ee17f4ba48097f134f894d7289fa7a1Tomi ValkeinenMODULE_ALIAS("spi:lgphilips,lb035q02"); 404f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi ValkeinenMODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); 405f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi ValkeinenMODULE_DESCRIPTION("LG.Philips LB035Q02 LCD Panel driver"); 406f92f168f8dc33c8db100fdd0c4ccfb26adedce61Tomi ValkeinenMODULE_LICENSE("GPL"); 407