162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Panel driver for the Samsung LMS397KF04 480x800 DPI RGB panel. 462306a36Sopenharmony_ci * According to the data sheet the display controller is called DB7430. 562306a36Sopenharmony_ci * Found in the Samsung Galaxy Beam GT-I8350 mobile phone. 662306a36Sopenharmony_ci * Linus Walleij <linus.walleij@linaro.org> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include <drm/drm_mipi_dbi.h> 962306a36Sopenharmony_ci#include <drm/drm_modes.h> 1062306a36Sopenharmony_ci#include <drm/drm_panel.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/delay.h> 1362306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1462306a36Sopenharmony_ci#include <linux/init.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/media-bus-format.h> 1762306a36Sopenharmony_ci#include <linux/module.h> 1862306a36Sopenharmony_ci#include <linux/of.h> 1962306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 2062306a36Sopenharmony_ci#include <linux/spi/spi.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <video/mipi_display.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define DB7430_ACCESS_PROT_OFF 0xb0 2562306a36Sopenharmony_ci#define DB7430_UNKNOWN_B4 0xb4 2662306a36Sopenharmony_ci#define DB7430_USER_SELECT 0xb5 2762306a36Sopenharmony_ci#define DB7430_UNKNOWN_B7 0xb7 2862306a36Sopenharmony_ci#define DB7430_UNKNOWN_B8 0xb8 2962306a36Sopenharmony_ci#define DB7430_PANEL_DRIVING 0xc0 3062306a36Sopenharmony_ci#define DB7430_SOURCE_CONTROL 0xc1 3162306a36Sopenharmony_ci#define DB7430_GATE_INTERFACE 0xc4 3262306a36Sopenharmony_ci#define DB7430_DISPLAY_H_TIMING 0xc5 3362306a36Sopenharmony_ci#define DB7430_RGB_SYNC_OPTION 0xc6 3462306a36Sopenharmony_ci#define DB7430_GAMMA_SET_RED 0xc8 3562306a36Sopenharmony_ci#define DB7430_GAMMA_SET_GREEN 0xc9 3662306a36Sopenharmony_ci#define DB7430_GAMMA_SET_BLUE 0xca 3762306a36Sopenharmony_ci#define DB7430_BIAS_CURRENT_CTRL 0xd1 3862306a36Sopenharmony_ci#define DB7430_DDV_CTRL 0xd2 3962306a36Sopenharmony_ci#define DB7430_GAMMA_CTRL_REF 0xd3 4062306a36Sopenharmony_ci#define DB7430_UNKNOWN_D4 0xd4 4162306a36Sopenharmony_ci#define DB7430_DCDC_CTRL 0xd5 4262306a36Sopenharmony_ci#define DB7430_VCL_CTRL 0xd6 4362306a36Sopenharmony_ci#define DB7430_UNKNOWN_F8 0xf8 4462306a36Sopenharmony_ci#define DB7430_UNKNOWN_FC 0xfc 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define DATA_MASK 0x100 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/** 4962306a36Sopenharmony_ci * struct db7430 - state container for a panel controlled by the DB7430 5062306a36Sopenharmony_ci * controller 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_cistruct db7430 { 5362306a36Sopenharmony_ci /** @dev: the container device */ 5462306a36Sopenharmony_ci struct device *dev; 5562306a36Sopenharmony_ci /** @dbi: the DBI bus abstraction handle */ 5662306a36Sopenharmony_ci struct mipi_dbi dbi; 5762306a36Sopenharmony_ci /** @panel: the DRM panel instance for this device */ 5862306a36Sopenharmony_ci struct drm_panel panel; 5962306a36Sopenharmony_ci /** @reset: reset GPIO line */ 6062306a36Sopenharmony_ci struct gpio_desc *reset; 6162306a36Sopenharmony_ci /** @regulators: VCCIO and VIO supply regulators */ 6262306a36Sopenharmony_ci struct regulator_bulk_data regulators[2]; 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic const struct drm_display_mode db7430_480_800_mode = { 6662306a36Sopenharmony_ci /* 6762306a36Sopenharmony_ci * 31 ns period min (htotal*vtotal*vrefresh)/1000 6862306a36Sopenharmony_ci * gives a Vrefresh of ~71 Hz. 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_ci .clock = 32258, 7162306a36Sopenharmony_ci .hdisplay = 480, 7262306a36Sopenharmony_ci .hsync_start = 480 + 10, 7362306a36Sopenharmony_ci .hsync_end = 480 + 10 + 4, 7462306a36Sopenharmony_ci .htotal = 480 + 10 + 4 + 40, 7562306a36Sopenharmony_ci .vdisplay = 800, 7662306a36Sopenharmony_ci .vsync_start = 800 + 6, 7762306a36Sopenharmony_ci .vsync_end = 800 + 6 + 1, 7862306a36Sopenharmony_ci .vtotal = 800 + 6 + 1 + 7, 7962306a36Sopenharmony_ci .width_mm = 53, 8062306a36Sopenharmony_ci .height_mm = 87, 8162306a36Sopenharmony_ci .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic inline struct db7430 *to_db7430(struct drm_panel *panel) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci return container_of(panel, struct db7430, panel); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic int db7430_power_on(struct db7430 *db) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct mipi_dbi *dbi = &db->dbi; 9262306a36Sopenharmony_ci int ret; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /* Power up */ 9562306a36Sopenharmony_ci ret = regulator_bulk_enable(ARRAY_SIZE(db->regulators), 9662306a36Sopenharmony_ci db->regulators); 9762306a36Sopenharmony_ci if (ret) { 9862306a36Sopenharmony_ci dev_err(db->dev, "failed to enable regulators: %d\n", ret); 9962306a36Sopenharmony_ci return ret; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci msleep(50); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* Assert reset >=1 ms */ 10462306a36Sopenharmony_ci gpiod_set_value_cansleep(db->reset, 1); 10562306a36Sopenharmony_ci usleep_range(1000, 5000); 10662306a36Sopenharmony_ci /* De-assert reset */ 10762306a36Sopenharmony_ci gpiod_set_value_cansleep(db->reset, 0); 10862306a36Sopenharmony_ci /* Wait >= 10 ms */ 10962306a36Sopenharmony_ci msleep(10); 11062306a36Sopenharmony_ci dev_dbg(db->dev, "de-asserted RESET\n"); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* 11362306a36Sopenharmony_ci * This is set to 0x0a (RGB/BGR order + horizontal flip) in order 11462306a36Sopenharmony_ci * to make the display behave normally. If this is not set the displays 11562306a36Sopenharmony_ci * normal output behaviour is horizontally flipped and BGR ordered. Do 11662306a36Sopenharmony_ci * it twice because the first message doesn't always "take". 11762306a36Sopenharmony_ci */ 11862306a36Sopenharmony_ci mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, 0x0a); 11962306a36Sopenharmony_ci mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, 0x0a); 12062306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_ACCESS_PROT_OFF, 0x00); 12162306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_PANEL_DRIVING, 0x28, 0x08); 12262306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_SOURCE_CONTROL, 12362306a36Sopenharmony_ci 0x01, 0x30, 0x15, 0x05, 0x22); 12462306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_GATE_INTERFACE, 12562306a36Sopenharmony_ci 0x10, 0x01, 0x00); 12662306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_DISPLAY_H_TIMING, 12762306a36Sopenharmony_ci 0x06, 0x55, 0x03, 0x07, 0x0b, 12862306a36Sopenharmony_ci 0x33, 0x00, 0x01, 0x03); 12962306a36Sopenharmony_ci /* 13062306a36Sopenharmony_ci * 0x00 in datasheet 0x01 in vendor code 0x00, it seems 0x01 means 13162306a36Sopenharmony_ci * DE active high and 0x00 means DE active low. 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_RGB_SYNC_OPTION, 0x01); 13462306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_GAMMA_SET_RED, 13562306a36Sopenharmony_ci /* R positive gamma */ 0x00, 13662306a36Sopenharmony_ci 0x0A, 0x31, 0x3B, 0x4E, 0x58, 0x59, 0x5B, 0x58, 0x5E, 0x62, 13762306a36Sopenharmony_ci 0x60, 0x61, 0x5E, 0x62, 0x55, 0x55, 0x7F, 0x08, 13862306a36Sopenharmony_ci /* R negative gamma */ 0x00, 13962306a36Sopenharmony_ci 0x0A, 0x31, 0x3B, 0x4E, 0x58, 0x59, 0x5B, 0x58, 0x5E, 0x62, 14062306a36Sopenharmony_ci 0x60, 0x61, 0x5E, 0x62, 0x55, 0x55, 0x7F, 0x08); 14162306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_GAMMA_SET_GREEN, 14262306a36Sopenharmony_ci /* G positive gamma */ 0x00, 14362306a36Sopenharmony_ci 0x25, 0x15, 0x28, 0x3D, 0x4A, 0x48, 0x4C, 0x4A, 0x52, 0x59, 14462306a36Sopenharmony_ci 0x59, 0x5B, 0x56, 0x60, 0x5D, 0x55, 0x7F, 0x0A, 14562306a36Sopenharmony_ci /* G negative gamma */ 0x00, 14662306a36Sopenharmony_ci 0x25, 0x15, 0x28, 0x3D, 0x4A, 0x48, 0x4C, 0x4A, 0x52, 0x59, 14762306a36Sopenharmony_ci 0x59, 0x5B, 0x56, 0x60, 0x5D, 0x55, 0x7F, 0x0A); 14862306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_GAMMA_SET_BLUE, 14962306a36Sopenharmony_ci /* B positive gamma */ 0x00, 15062306a36Sopenharmony_ci 0x48, 0x10, 0x1F, 0x2F, 0x35, 0x38, 0x3D, 0x3C, 0x45, 0x4D, 15162306a36Sopenharmony_ci 0x4E, 0x52, 0x51, 0x60, 0x7F, 0x7E, 0x7F, 0x0C, 15262306a36Sopenharmony_ci /* B negative gamma */ 0x00, 15362306a36Sopenharmony_ci 0x48, 0x10, 0x1F, 0x2F, 0x35, 0x38, 0x3D, 0x3C, 0x45, 0x4D, 15462306a36Sopenharmony_ci 0x4E, 0x52, 0x51, 0x60, 0x7F, 0x7E, 0x7F, 0x0C); 15562306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_BIAS_CURRENT_CTRL, 0x33, 0x13); 15662306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_DDV_CTRL, 0x11, 0x00, 0x00); 15762306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_GAMMA_CTRL_REF, 0x50, 0x50); 15862306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_DCDC_CTRL, 0x2f, 0x11, 0x1e, 0x46); 15962306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_VCL_CTRL, 0x11, 0x0a); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci return 0; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic int db7430_power_off(struct db7430 *db) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci /* Go into RESET and disable regulators */ 16762306a36Sopenharmony_ci gpiod_set_value_cansleep(db->reset, 1); 16862306a36Sopenharmony_ci return regulator_bulk_disable(ARRAY_SIZE(db->regulators), 16962306a36Sopenharmony_ci db->regulators); 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic int db7430_unprepare(struct drm_panel *panel) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci return db7430_power_off(to_db7430(panel)); 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic int db7430_disable(struct drm_panel *panel) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci struct db7430 *db = to_db7430(panel); 18062306a36Sopenharmony_ci struct mipi_dbi *dbi = &db->dbi; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF); 18362306a36Sopenharmony_ci msleep(25); 18462306a36Sopenharmony_ci mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE); 18562306a36Sopenharmony_ci msleep(120); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci return 0; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic int db7430_prepare(struct drm_panel *panel) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci return db7430_power_on(to_db7430(panel)); 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic int db7430_enable(struct drm_panel *panel) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci struct db7430 *db = to_db7430(panel); 19862306a36Sopenharmony_ci struct mipi_dbi *dbi = &db->dbi; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci /* Exit sleep mode */ 20162306a36Sopenharmony_ci mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); 20262306a36Sopenharmony_ci msleep(20); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* NVM (non-volatile memory) load sequence */ 20562306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_UNKNOWN_D4, 0x52, 0x5e); 20662306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_UNKNOWN_F8, 0x01, 0xf5, 0xf2, 0x71, 0x44); 20762306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_UNKNOWN_FC, 0x00, 0x08); 20862306a36Sopenharmony_ci msleep(150); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci /* CABC turn on sequence (BC = backlight control) */ 21162306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_UNKNOWN_B4, 0x0f, 0x00, 0x50); 21262306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_USER_SELECT, 0x80); 21362306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_UNKNOWN_B7, 0x24); 21462306a36Sopenharmony_ci mipi_dbi_command(dbi, DB7430_UNKNOWN_B8, 0x01); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* Turn on display */ 21762306a36Sopenharmony_ci mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci return 0; 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/** 22362306a36Sopenharmony_ci * db7430_get_modes() - return the mode 22462306a36Sopenharmony_ci * @panel: the panel to get the mode for 22562306a36Sopenharmony_ci * @connector: reference to the central DRM connector control structure 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_cistatic int db7430_get_modes(struct drm_panel *panel, 22862306a36Sopenharmony_ci struct drm_connector *connector) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci struct db7430 *db = to_db7430(panel); 23162306a36Sopenharmony_ci struct drm_display_mode *mode; 23262306a36Sopenharmony_ci static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci mode = drm_mode_duplicate(connector->dev, &db7430_480_800_mode); 23562306a36Sopenharmony_ci if (!mode) { 23662306a36Sopenharmony_ci dev_err(db->dev, "failed to add mode\n"); 23762306a36Sopenharmony_ci return -ENOMEM; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci connector->display_info.bpc = 8; 24162306a36Sopenharmony_ci connector->display_info.width_mm = mode->width_mm; 24262306a36Sopenharmony_ci connector->display_info.height_mm = mode->height_mm; 24362306a36Sopenharmony_ci connector->display_info.bus_flags = 24462306a36Sopenharmony_ci DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE; 24562306a36Sopenharmony_ci drm_display_info_set_bus_formats(&connector->display_info, 24662306a36Sopenharmony_ci &bus_format, 1); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci drm_mode_set_name(mode); 24962306a36Sopenharmony_ci mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci drm_mode_probed_add(connector, mode); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return 1; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic const struct drm_panel_funcs db7430_drm_funcs = { 25762306a36Sopenharmony_ci .disable = db7430_disable, 25862306a36Sopenharmony_ci .unprepare = db7430_unprepare, 25962306a36Sopenharmony_ci .prepare = db7430_prepare, 26062306a36Sopenharmony_ci .enable = db7430_enable, 26162306a36Sopenharmony_ci .get_modes = db7430_get_modes, 26262306a36Sopenharmony_ci}; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic int db7430_probe(struct spi_device *spi) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci struct device *dev = &spi->dev; 26762306a36Sopenharmony_ci struct db7430 *db; 26862306a36Sopenharmony_ci int ret; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci db = devm_kzalloc(dev, sizeof(*db), GFP_KERNEL); 27162306a36Sopenharmony_ci if (!db) 27262306a36Sopenharmony_ci return -ENOMEM; 27362306a36Sopenharmony_ci db->dev = dev; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* 27662306a36Sopenharmony_ci * VCI is the analog voltage supply 27762306a36Sopenharmony_ci * VCCIO is the digital I/O voltage supply 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ci db->regulators[0].supply = "vci"; 28062306a36Sopenharmony_ci db->regulators[1].supply = "vccio"; 28162306a36Sopenharmony_ci ret = devm_regulator_bulk_get(dev, 28262306a36Sopenharmony_ci ARRAY_SIZE(db->regulators), 28362306a36Sopenharmony_ci db->regulators); 28462306a36Sopenharmony_ci if (ret) 28562306a36Sopenharmony_ci return dev_err_probe(dev, ret, "failed to get regulators\n"); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci db->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 28862306a36Sopenharmony_ci if (IS_ERR(db->reset)) { 28962306a36Sopenharmony_ci ret = PTR_ERR(db->reset); 29062306a36Sopenharmony_ci return dev_err_probe(dev, ret, "no RESET GPIO\n"); 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci ret = mipi_dbi_spi_init(spi, &db->dbi, NULL); 29462306a36Sopenharmony_ci if (ret) 29562306a36Sopenharmony_ci return dev_err_probe(dev, ret, "MIPI DBI init failed\n"); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci drm_panel_init(&db->panel, dev, &db7430_drm_funcs, 29862306a36Sopenharmony_ci DRM_MODE_CONNECTOR_DPI); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* FIXME: if no external backlight, use internal backlight */ 30162306a36Sopenharmony_ci ret = drm_panel_of_backlight(&db->panel); 30262306a36Sopenharmony_ci if (ret) 30362306a36Sopenharmony_ci return dev_err_probe(dev, ret, "failed to add backlight\n"); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci spi_set_drvdata(spi, db); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci drm_panel_add(&db->panel); 30862306a36Sopenharmony_ci dev_dbg(dev, "added panel\n"); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci return 0; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cistatic void db7430_remove(struct spi_device *spi) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci struct db7430 *db = spi_get_drvdata(spi); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci drm_panel_remove(&db->panel); 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci/* 32162306a36Sopenharmony_ci * The DB7430 display controller may be used in several display products, 32262306a36Sopenharmony_ci * so list the different variants here and add per-variant data if needed. 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_cistatic const struct of_device_id db7430_match[] = { 32562306a36Sopenharmony_ci { .compatible = "samsung,lms397kf04", }, 32662306a36Sopenharmony_ci {}, 32762306a36Sopenharmony_ci}; 32862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, db7430_match); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic const struct spi_device_id db7430_ids[] = { 33162306a36Sopenharmony_ci { "lms397kf04" }, 33262306a36Sopenharmony_ci { }, 33362306a36Sopenharmony_ci}; 33462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, db7430_ids); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic struct spi_driver db7430_driver = { 33762306a36Sopenharmony_ci .probe = db7430_probe, 33862306a36Sopenharmony_ci .remove = db7430_remove, 33962306a36Sopenharmony_ci .id_table = db7430_ids, 34062306a36Sopenharmony_ci .driver = { 34162306a36Sopenharmony_ci .name = "db7430-panel", 34262306a36Sopenharmony_ci .of_match_table = db7430_match, 34362306a36Sopenharmony_ci }, 34462306a36Sopenharmony_ci}; 34562306a36Sopenharmony_cimodule_spi_driver(db7430_driver); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ciMODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); 34862306a36Sopenharmony_ciMODULE_DESCRIPTION("Samsung DB7430 panel driver"); 34962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 350