1ebd8cbf1SMarkuss Broks // SPDX-License-Identifier: GPL-2.0
2ebd8cbf1SMarkuss Broks /*
3ebd8cbf1SMarkuss Broks * Panel driver for the Samsung S6D27A1 480x800 DPI RGB panel.
4ebd8cbf1SMarkuss Broks * Found in the Samsung Galaxy Ace 2 GT-I8160 mobile phone.
5ebd8cbf1SMarkuss Broks */
6ebd8cbf1SMarkuss Broks
7ebd8cbf1SMarkuss Broks #include <drm/drm_mipi_dbi.h>
8ebd8cbf1SMarkuss Broks #include <drm/drm_modes.h>
9ebd8cbf1SMarkuss Broks #include <drm/drm_panel.h>
10ebd8cbf1SMarkuss Broks
11ebd8cbf1SMarkuss Broks #include <linux/delay.h>
12ebd8cbf1SMarkuss Broks #include <linux/gpio/consumer.h>
13ebd8cbf1SMarkuss Broks #include <linux/init.h>
14ebd8cbf1SMarkuss Broks #include <linux/kernel.h>
15ebd8cbf1SMarkuss Broks #include <linux/media-bus-format.h>
16ebd8cbf1SMarkuss Broks #include <linux/module.h>
17ebd8cbf1SMarkuss Broks #include <linux/of.h>
18ebd8cbf1SMarkuss Broks #include <linux/regulator/consumer.h>
19ebd8cbf1SMarkuss Broks #include <linux/spi/spi.h>
20ebd8cbf1SMarkuss Broks
21ebd8cbf1SMarkuss Broks #include <video/mipi_display.h>
22ebd8cbf1SMarkuss Broks
23ebd8cbf1SMarkuss Broks #define S6D27A1_PASSWD_L2 0xF0 /* Password Command for Level 2 Control */
24ebd8cbf1SMarkuss Broks #define S6D27A1_RESCTL 0xB3 /* Resolution Select Control */
25ebd8cbf1SMarkuss Broks #define S6D27A1_PANELCTL2 0xB4 /* ASG Signal Control */
26ebd8cbf1SMarkuss Broks #define S6D27A1_READID1 0xDA /* Read panel ID 1 */
27ebd8cbf1SMarkuss Broks #define S6D27A1_READID2 0xDB /* Read panel ID 2 */
28ebd8cbf1SMarkuss Broks #define S6D27A1_READID3 0xDC /* Read panel ID 3 */
29ebd8cbf1SMarkuss Broks #define S6D27A1_DISPCTL 0xF2 /* Display Control */
30ebd8cbf1SMarkuss Broks #define S6D27A1_MANPWR 0xF3 /* Manual Control */
31ebd8cbf1SMarkuss Broks #define S6D27A1_PWRCTL1 0xF4 /* Power Control */
32ebd8cbf1SMarkuss Broks #define S6D27A1_SRCCTL 0xF6 /* Source Control */
33ebd8cbf1SMarkuss Broks #define S6D27A1_PANELCTL 0xF7 /* Panel Control*/
34ebd8cbf1SMarkuss Broks
35ebd8cbf1SMarkuss Broks static const u8 s6d27a1_dbi_read_commands[] = {
36ebd8cbf1SMarkuss Broks S6D27A1_READID1,
37ebd8cbf1SMarkuss Broks S6D27A1_READID2,
38ebd8cbf1SMarkuss Broks S6D27A1_READID3,
39ebd8cbf1SMarkuss Broks 0, /* sentinel */
40ebd8cbf1SMarkuss Broks };
41ebd8cbf1SMarkuss Broks
42ebd8cbf1SMarkuss Broks struct s6d27a1 {
43ebd8cbf1SMarkuss Broks struct device *dev;
44ebd8cbf1SMarkuss Broks struct mipi_dbi dbi;
45ebd8cbf1SMarkuss Broks struct drm_panel panel;
46ebd8cbf1SMarkuss Broks struct gpio_desc *reset;
47ebd8cbf1SMarkuss Broks struct regulator_bulk_data regulators[2];
48ebd8cbf1SMarkuss Broks };
49ebd8cbf1SMarkuss Broks
50ebd8cbf1SMarkuss Broks static const struct drm_display_mode s6d27a1_480_800_mode = {
51ebd8cbf1SMarkuss Broks /*
52ebd8cbf1SMarkuss Broks * The vendor driver states that the S6D27A1 panel
53ebd8cbf1SMarkuss Broks * has a pixel clock frequency of 49920000 Hz / 2 = 24960000 Hz.
54ebd8cbf1SMarkuss Broks */
55ebd8cbf1SMarkuss Broks .clock = 24960,
56ebd8cbf1SMarkuss Broks .hdisplay = 480,
57ebd8cbf1SMarkuss Broks .hsync_start = 480 + 63,
58ebd8cbf1SMarkuss Broks .hsync_end = 480 + 63 + 2,
59ebd8cbf1SMarkuss Broks .htotal = 480 + 63 + 2 + 63,
60ebd8cbf1SMarkuss Broks .vdisplay = 800,
61ebd8cbf1SMarkuss Broks .vsync_start = 800 + 11,
62ebd8cbf1SMarkuss Broks .vsync_end = 800 + 11 + 2,
63ebd8cbf1SMarkuss Broks .vtotal = 800 + 11 + 2 + 10,
64ebd8cbf1SMarkuss Broks .width_mm = 50,
65ebd8cbf1SMarkuss Broks .height_mm = 84,
66ebd8cbf1SMarkuss Broks .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
67ebd8cbf1SMarkuss Broks };
68ebd8cbf1SMarkuss Broks
to_s6d27a1(struct drm_panel * panel)69ebd8cbf1SMarkuss Broks static inline struct s6d27a1 *to_s6d27a1(struct drm_panel *panel)
70ebd8cbf1SMarkuss Broks {
71ebd8cbf1SMarkuss Broks return container_of(panel, struct s6d27a1, panel);
72ebd8cbf1SMarkuss Broks }
73ebd8cbf1SMarkuss Broks
s6d27a1_read_mtp_id(struct s6d27a1 * ctx)74ebd8cbf1SMarkuss Broks static void s6d27a1_read_mtp_id(struct s6d27a1 *ctx)
75ebd8cbf1SMarkuss Broks {
76ebd8cbf1SMarkuss Broks struct mipi_dbi *dbi = &ctx->dbi;
77ebd8cbf1SMarkuss Broks u8 id1, id2, id3;
78ebd8cbf1SMarkuss Broks int ret;
79ebd8cbf1SMarkuss Broks
80ebd8cbf1SMarkuss Broks ret = mipi_dbi_command_read(dbi, S6D27A1_READID1, &id1);
81ebd8cbf1SMarkuss Broks if (ret) {
82ebd8cbf1SMarkuss Broks dev_err(ctx->dev, "unable to read MTP ID 1\n");
83ebd8cbf1SMarkuss Broks return;
84ebd8cbf1SMarkuss Broks }
85ebd8cbf1SMarkuss Broks ret = mipi_dbi_command_read(dbi, S6D27A1_READID2, &id2);
86ebd8cbf1SMarkuss Broks if (ret) {
87ebd8cbf1SMarkuss Broks dev_err(ctx->dev, "unable to read MTP ID 2\n");
88ebd8cbf1SMarkuss Broks return;
89ebd8cbf1SMarkuss Broks }
90ebd8cbf1SMarkuss Broks ret = mipi_dbi_command_read(dbi, S6D27A1_READID3, &id3);
91ebd8cbf1SMarkuss Broks if (ret) {
92ebd8cbf1SMarkuss Broks dev_err(ctx->dev, "unable to read MTP ID 3\n");
93ebd8cbf1SMarkuss Broks return;
94ebd8cbf1SMarkuss Broks }
95ebd8cbf1SMarkuss Broks dev_info(ctx->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3);
96ebd8cbf1SMarkuss Broks }
97ebd8cbf1SMarkuss Broks
s6d27a1_power_on(struct s6d27a1 * ctx)98ebd8cbf1SMarkuss Broks static int s6d27a1_power_on(struct s6d27a1 *ctx)
99ebd8cbf1SMarkuss Broks {
100ebd8cbf1SMarkuss Broks struct mipi_dbi *dbi = &ctx->dbi;
101ebd8cbf1SMarkuss Broks int ret;
102ebd8cbf1SMarkuss Broks
103ebd8cbf1SMarkuss Broks /* Power up */
104ebd8cbf1SMarkuss Broks ret = regulator_bulk_enable(ARRAY_SIZE(ctx->regulators),
105ebd8cbf1SMarkuss Broks ctx->regulators);
106ebd8cbf1SMarkuss Broks if (ret) {
107ebd8cbf1SMarkuss Broks dev_err(ctx->dev, "failed to enable regulators: %d\n", ret);
108ebd8cbf1SMarkuss Broks return ret;
109ebd8cbf1SMarkuss Broks }
110ebd8cbf1SMarkuss Broks
111ebd8cbf1SMarkuss Broks msleep(20);
112ebd8cbf1SMarkuss Broks
113ebd8cbf1SMarkuss Broks /* Assert reset >=1 ms */
114ebd8cbf1SMarkuss Broks gpiod_set_value_cansleep(ctx->reset, 1);
115ebd8cbf1SMarkuss Broks usleep_range(1000, 5000);
116ebd8cbf1SMarkuss Broks /* De-assert reset */
117ebd8cbf1SMarkuss Broks gpiod_set_value_cansleep(ctx->reset, 0);
118ebd8cbf1SMarkuss Broks /* Wait >= 10 ms */
119ebd8cbf1SMarkuss Broks msleep(20);
120ebd8cbf1SMarkuss Broks
121ebd8cbf1SMarkuss Broks /*
122ebd8cbf1SMarkuss Broks * Exit sleep mode and initialize display - some hammering is
123ebd8cbf1SMarkuss Broks * necessary.
124ebd8cbf1SMarkuss Broks */
125ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
126ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
127ebd8cbf1SMarkuss Broks msleep(120);
128ebd8cbf1SMarkuss Broks
129ebd8cbf1SMarkuss Broks /* Magic to unlock level 2 control of the display */
130ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, S6D27A1_PASSWD_L2, 0x5A, 0x5A);
131ebd8cbf1SMarkuss Broks
132ebd8cbf1SMarkuss Broks /* Configure resolution to 480RGBx800 */
133ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, S6D27A1_RESCTL, 0x22);
134ebd8cbf1SMarkuss Broks
135ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, S6D27A1_PANELCTL2, 0x00, 0x02, 0x03, 0x04, 0x05, 0x08, 0x00, 0x0c);
136ebd8cbf1SMarkuss Broks
137ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, S6D27A1_MANPWR, 0x01, 0x00, 0x00, 0x08, 0x08, 0x02, 0x00);
138ebd8cbf1SMarkuss Broks
139ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, S6D27A1_DISPCTL, 0x19, 0x00, 0x08, 0x0D, 0x03, 0x41, 0x3F);
140ebd8cbf1SMarkuss Broks
141ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, S6D27A1_PWRCTL1, 0x00, 0x00, 0x00, 0x00, 0x55,
142ebd8cbf1SMarkuss Broks 0x44, 0x05, 0x88, 0x4B, 0x50);
143ebd8cbf1SMarkuss Broks
144ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, S6D27A1_SRCCTL, 0x03, 0x09, 0x8A, 0x00, 0x01, 0x16);
145ebd8cbf1SMarkuss Broks
146ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, S6D27A1_PANELCTL, 0x00, 0x05, 0x06, 0x07, 0x08,
147ebd8cbf1SMarkuss Broks 0x01, 0x09, 0x0D, 0x0A, 0x0E,
148ebd8cbf1SMarkuss Broks 0x0B, 0x0F, 0x0C, 0x10, 0x01,
149ebd8cbf1SMarkuss Broks 0x11, 0x12, 0x13, 0x14, 0x05,
150ebd8cbf1SMarkuss Broks 0x06, 0x07, 0x08, 0x01, 0x09,
151ebd8cbf1SMarkuss Broks 0x0D, 0x0A, 0x0E, 0x0B, 0x0F,
152ebd8cbf1SMarkuss Broks 0x0C, 0x10, 0x01, 0x11, 0x12,
153ebd8cbf1SMarkuss Broks 0x13, 0x14);
154ebd8cbf1SMarkuss Broks
155ebd8cbf1SMarkuss Broks /* lock the level 2 control */
156ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, S6D27A1_PASSWD_L2, 0xA5, 0xA5);
157ebd8cbf1SMarkuss Broks
158ebd8cbf1SMarkuss Broks s6d27a1_read_mtp_id(ctx);
159ebd8cbf1SMarkuss Broks
160ebd8cbf1SMarkuss Broks return 0;
161ebd8cbf1SMarkuss Broks }
162ebd8cbf1SMarkuss Broks
s6d27a1_power_off(struct s6d27a1 * ctx)163ebd8cbf1SMarkuss Broks static int s6d27a1_power_off(struct s6d27a1 *ctx)
164ebd8cbf1SMarkuss Broks {
165ebd8cbf1SMarkuss Broks /* Go into RESET and disable regulators */
166ebd8cbf1SMarkuss Broks gpiod_set_value_cansleep(ctx->reset, 1);
167ebd8cbf1SMarkuss Broks return regulator_bulk_disable(ARRAY_SIZE(ctx->regulators),
168ebd8cbf1SMarkuss Broks ctx->regulators);
169ebd8cbf1SMarkuss Broks }
170ebd8cbf1SMarkuss Broks
s6d27a1_unprepare(struct drm_panel * panel)171ebd8cbf1SMarkuss Broks static int s6d27a1_unprepare(struct drm_panel *panel)
172ebd8cbf1SMarkuss Broks {
173ebd8cbf1SMarkuss Broks struct s6d27a1 *ctx = to_s6d27a1(panel);
174ebd8cbf1SMarkuss Broks struct mipi_dbi *dbi = &ctx->dbi;
175ebd8cbf1SMarkuss Broks
176ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE);
177ebd8cbf1SMarkuss Broks msleep(120);
178ebd8cbf1SMarkuss Broks return s6d27a1_power_off(to_s6d27a1(panel));
179ebd8cbf1SMarkuss Broks }
180ebd8cbf1SMarkuss Broks
s6d27a1_disable(struct drm_panel * panel)181ebd8cbf1SMarkuss Broks static int s6d27a1_disable(struct drm_panel *panel)
182ebd8cbf1SMarkuss Broks {
183ebd8cbf1SMarkuss Broks struct s6d27a1 *ctx = to_s6d27a1(panel);
184ebd8cbf1SMarkuss Broks struct mipi_dbi *dbi = &ctx->dbi;
185ebd8cbf1SMarkuss Broks
186ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
187ebd8cbf1SMarkuss Broks msleep(25);
188ebd8cbf1SMarkuss Broks
189ebd8cbf1SMarkuss Broks return 0;
190ebd8cbf1SMarkuss Broks }
191ebd8cbf1SMarkuss Broks
s6d27a1_prepare(struct drm_panel * panel)192ebd8cbf1SMarkuss Broks static int s6d27a1_prepare(struct drm_panel *panel)
193ebd8cbf1SMarkuss Broks {
194ebd8cbf1SMarkuss Broks return s6d27a1_power_on(to_s6d27a1(panel));
195ebd8cbf1SMarkuss Broks }
196ebd8cbf1SMarkuss Broks
s6d27a1_enable(struct drm_panel * panel)197ebd8cbf1SMarkuss Broks static int s6d27a1_enable(struct drm_panel *panel)
198ebd8cbf1SMarkuss Broks {
199ebd8cbf1SMarkuss Broks struct s6d27a1 *ctx = to_s6d27a1(panel);
200ebd8cbf1SMarkuss Broks struct mipi_dbi *dbi = &ctx->dbi;
201ebd8cbf1SMarkuss Broks
202ebd8cbf1SMarkuss Broks mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
203ebd8cbf1SMarkuss Broks
204ebd8cbf1SMarkuss Broks return 0;
205ebd8cbf1SMarkuss Broks }
206ebd8cbf1SMarkuss Broks
s6d27a1_get_modes(struct drm_panel * panel,struct drm_connector * connector)207ebd8cbf1SMarkuss Broks static int s6d27a1_get_modes(struct drm_panel *panel,
208ebd8cbf1SMarkuss Broks struct drm_connector *connector)
209ebd8cbf1SMarkuss Broks {
210ebd8cbf1SMarkuss Broks struct s6d27a1 *ctx = to_s6d27a1(panel);
211ebd8cbf1SMarkuss Broks struct drm_display_mode *mode;
212ebd8cbf1SMarkuss Broks static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
213ebd8cbf1SMarkuss Broks
214ebd8cbf1SMarkuss Broks mode = drm_mode_duplicate(connector->dev, &s6d27a1_480_800_mode);
215ebd8cbf1SMarkuss Broks if (!mode) {
216ebd8cbf1SMarkuss Broks dev_err(ctx->dev, "failed to add mode\n");
217ebd8cbf1SMarkuss Broks return -ENOMEM;
218ebd8cbf1SMarkuss Broks }
219ebd8cbf1SMarkuss Broks
220ebd8cbf1SMarkuss Broks connector->display_info.bpc = 8;
221ebd8cbf1SMarkuss Broks connector->display_info.width_mm = mode->width_mm;
222ebd8cbf1SMarkuss Broks connector->display_info.height_mm = mode->height_mm;
223ebd8cbf1SMarkuss Broks connector->display_info.bus_flags =
224ebd8cbf1SMarkuss Broks DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
225ebd8cbf1SMarkuss Broks drm_display_info_set_bus_formats(&connector->display_info,
226ebd8cbf1SMarkuss Broks &bus_format, 1);
227ebd8cbf1SMarkuss Broks
228ebd8cbf1SMarkuss Broks drm_mode_set_name(mode);
229ebd8cbf1SMarkuss Broks mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
230ebd8cbf1SMarkuss Broks
231ebd8cbf1SMarkuss Broks drm_mode_probed_add(connector, mode);
232ebd8cbf1SMarkuss Broks
233ebd8cbf1SMarkuss Broks return 1;
234ebd8cbf1SMarkuss Broks }
235ebd8cbf1SMarkuss Broks
236ebd8cbf1SMarkuss Broks static const struct drm_panel_funcs s6d27a1_drm_funcs = {
237ebd8cbf1SMarkuss Broks .disable = s6d27a1_disable,
238ebd8cbf1SMarkuss Broks .unprepare = s6d27a1_unprepare,
239ebd8cbf1SMarkuss Broks .prepare = s6d27a1_prepare,
240ebd8cbf1SMarkuss Broks .enable = s6d27a1_enable,
241ebd8cbf1SMarkuss Broks .get_modes = s6d27a1_get_modes,
242ebd8cbf1SMarkuss Broks };
243ebd8cbf1SMarkuss Broks
s6d27a1_probe(struct spi_device * spi)244ebd8cbf1SMarkuss Broks static int s6d27a1_probe(struct spi_device *spi)
245ebd8cbf1SMarkuss Broks {
246ebd8cbf1SMarkuss Broks struct device *dev = &spi->dev;
247ebd8cbf1SMarkuss Broks struct s6d27a1 *ctx;
248ebd8cbf1SMarkuss Broks int ret;
249ebd8cbf1SMarkuss Broks
250ebd8cbf1SMarkuss Broks ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
251ebd8cbf1SMarkuss Broks if (!ctx)
252ebd8cbf1SMarkuss Broks return -ENOMEM;
253ebd8cbf1SMarkuss Broks
254ebd8cbf1SMarkuss Broks ctx->dev = dev;
255ebd8cbf1SMarkuss Broks
256ebd8cbf1SMarkuss Broks /*
257ebd8cbf1SMarkuss Broks * VCI is the analog voltage supply
258ebd8cbf1SMarkuss Broks * VCCIO is the digital I/O voltage supply
259ebd8cbf1SMarkuss Broks */
260ebd8cbf1SMarkuss Broks ctx->regulators[0].supply = "vci";
261ebd8cbf1SMarkuss Broks ctx->regulators[1].supply = "vccio";
262ebd8cbf1SMarkuss Broks ret = devm_regulator_bulk_get(dev,
263ebd8cbf1SMarkuss Broks ARRAY_SIZE(ctx->regulators),
264ebd8cbf1SMarkuss Broks ctx->regulators);
265ebd8cbf1SMarkuss Broks if (ret)
266ebd8cbf1SMarkuss Broks return dev_err_probe(dev, ret, "failed to get regulators\n");
267ebd8cbf1SMarkuss Broks
268ebd8cbf1SMarkuss Broks ctx->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
269ebd8cbf1SMarkuss Broks if (IS_ERR(ctx->reset)) {
270ebd8cbf1SMarkuss Broks ret = PTR_ERR(ctx->reset);
271ebd8cbf1SMarkuss Broks return dev_err_probe(dev, ret, "no RESET GPIO\n");
272ebd8cbf1SMarkuss Broks }
273ebd8cbf1SMarkuss Broks
274ebd8cbf1SMarkuss Broks ret = mipi_dbi_spi_init(spi, &ctx->dbi, NULL);
275ebd8cbf1SMarkuss Broks if (ret)
276ebd8cbf1SMarkuss Broks return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
277ebd8cbf1SMarkuss Broks
278ebd8cbf1SMarkuss Broks ctx->dbi.read_commands = s6d27a1_dbi_read_commands;
279ebd8cbf1SMarkuss Broks
280ebd8cbf1SMarkuss Broks drm_panel_init(&ctx->panel, dev, &s6d27a1_drm_funcs,
281ebd8cbf1SMarkuss Broks DRM_MODE_CONNECTOR_DPI);
282ebd8cbf1SMarkuss Broks
283ebd8cbf1SMarkuss Broks ret = drm_panel_of_backlight(&ctx->panel);
284ebd8cbf1SMarkuss Broks if (ret)
285ebd8cbf1SMarkuss Broks return dev_err_probe(dev, ret, "failed to add backlight\n");
286ebd8cbf1SMarkuss Broks
287ebd8cbf1SMarkuss Broks spi_set_drvdata(spi, ctx);
288ebd8cbf1SMarkuss Broks
289ebd8cbf1SMarkuss Broks drm_panel_add(&ctx->panel);
290ebd8cbf1SMarkuss Broks
291ebd8cbf1SMarkuss Broks return 0;
292ebd8cbf1SMarkuss Broks }
293ebd8cbf1SMarkuss Broks
s6d27a1_remove(struct spi_device * spi)294*a0386bbaSUwe Kleine-König static void s6d27a1_remove(struct spi_device *spi)
295ebd8cbf1SMarkuss Broks {
296ebd8cbf1SMarkuss Broks struct s6d27a1 *ctx = spi_get_drvdata(spi);
297ebd8cbf1SMarkuss Broks
298ebd8cbf1SMarkuss Broks drm_panel_remove(&ctx->panel);
299ebd8cbf1SMarkuss Broks }
300ebd8cbf1SMarkuss Broks
301ebd8cbf1SMarkuss Broks static const struct of_device_id s6d27a1_match[] = {
302ebd8cbf1SMarkuss Broks { .compatible = "samsung,s6d27a1", },
303ebd8cbf1SMarkuss Broks { /* sentinel */ },
304ebd8cbf1SMarkuss Broks };
305ebd8cbf1SMarkuss Broks MODULE_DEVICE_TABLE(of, s6d27a1_match);
306ebd8cbf1SMarkuss Broks
307ebd8cbf1SMarkuss Broks static struct spi_driver s6d27a1_driver = {
308ebd8cbf1SMarkuss Broks .probe = s6d27a1_probe,
309ebd8cbf1SMarkuss Broks .remove = s6d27a1_remove,
310ebd8cbf1SMarkuss Broks .driver = {
311ebd8cbf1SMarkuss Broks .name = "s6d27a1-panel",
312ebd8cbf1SMarkuss Broks .of_match_table = s6d27a1_match,
313ebd8cbf1SMarkuss Broks },
314ebd8cbf1SMarkuss Broks };
315ebd8cbf1SMarkuss Broks module_spi_driver(s6d27a1_driver);
316ebd8cbf1SMarkuss Broks
317ebd8cbf1SMarkuss Broks MODULE_AUTHOR("Markuss Broks <markuss.broks@gmail.com>");
318ebd8cbf1SMarkuss Broks MODULE_DESCRIPTION("Samsung S6D27A1 panel driver");
319ebd8cbf1SMarkuss Broks MODULE_LICENSE("GPL v2");
320