1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Magnachip d53e6ea8966 MIPI-DSI panel driver
4  * Copyright (C) 2023 Chris Morgan
5  */
6 
7 #include <drm/drm_mipi_dbi.h>
8 #include <drm/drm_mipi_dsi.h>
9 #include <drm/drm_modes.h>
10 #include <drm/drm_of.h>
11 #include <drm/drm_panel.h>
12 
13 #include <linux/backlight.h>
14 #include <linux/delay.h>
15 #include <linux/gpio/consumer.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/media-bus-format.h>
19 #include <linux/module.h>
20 #include <linux/of.h>
21 #include <linux/of_device.h>
22 #include <linux/regulator/consumer.h>
23 #include <linux/spi/spi.h>
24 
25 #include <video/mipi_display.h>
26 
27 /* Forward declaration for use in backlight function */
28 struct d53e6ea8966;
29 
30 /* Panel info, unique to each panel */
31 struct d53e6ea8966_panel_info {
32 	/** @display_modes: the supported display modes */
33 	const struct drm_display_mode *display_modes;
34 	/** @num_modes: the number of supported display modes */
35 	unsigned int num_modes;
36 	/** @width_mm: panel width in mm */
37 	u16 width_mm;
38 	/** @height_mm: panel height in mm */
39 	u16 height_mm;
40 	/** @bus_flags: drm bus flags for panel */
41 	u32 bus_flags;
42 	/** @panel_init_seq: panel specific init sequence */
43 	void (*panel_init_seq)(struct d53e6ea8966 *db);
44 	/** @backlight_register: panel backlight registration or NULL */
45 	int (*backlight_register)(struct d53e6ea8966 *db);
46 };
47 
48 struct d53e6ea8966 {
49 	/** @dev: the container device */
50 	struct device *dev;
51 	/** @dbi: the DBI bus abstraction handle */
52 	struct mipi_dbi dbi;
53 	/** @panel: the DRM panel instance for this device */
54 	struct drm_panel panel;
55 	/** @reset: reset GPIO line */
56 	struct gpio_desc *reset;
57 	/** @enable: enable GPIO line */
58 	struct gpio_desc *enable;
59 	/** @reg_vdd: VDD supply regulator for panel logic */
60 	struct regulator *reg_vdd;
61 	/** @reg_elvdd: ELVDD supply regulator for panel display */
62 	struct regulator *reg_elvdd;
63 	/** @dsi_dev: DSI child device (panel) */
64 	struct mipi_dsi_device *dsi_dev;
65 	/** @bl_dev: pseudo-backlight device for oled panel */
66 	struct backlight_device *bl_dev;
67 	/** @panel_info: struct containing panel timing and info */
68 	const struct d53e6ea8966_panel_info *panel_info;
69 };
70 
71 #define NUM_GAMMA_LEVELS	16
72 #define GAMMA_TABLE_COUNT	23
73 #define MAX_BRIGHTNESS		(NUM_GAMMA_LEVELS - 1)
74 
75 #define MCS_ELVSS_ON			0xb1
76 #define MCS_TEMP_SWIRE			0xb2
77 #define MCS_PASSWORD_0			0xf0
78 #define MCS_PASSWORD_1			0xf1
79 #define MCS_ANALOG_PWR_CTL_0		0xf4
80 #define MCS_ANALOG_PWR_CTL_1		0xf5
81 #define MCS_GTCON_SET			0xf7
82 #define MCS_GATELESS_SIGNAL_SET		0xf8
83 #define MCS_SET_GAMMA			0xf9
84 
85 static inline struct d53e6ea8966 *to_d53e6ea8966(struct drm_panel *panel)
86 {
87 	return container_of(panel, struct d53e6ea8966, panel);
88 }
89 
90 /* Table of gamma values provided in datasheet */
91 static u8 ams495qa01_gamma[NUM_GAMMA_LEVELS][GAMMA_TABLE_COUNT] = {
92 	{0x01, 0x79, 0x78, 0x8d, 0xd9, 0xdf, 0xd5, 0xcb, 0xcf, 0xc5,
93 	 0xe5, 0xe0, 0xe4, 0xdc, 0xb8, 0xd4, 0xfa, 0xed, 0xe6, 0x2f,
94 	 0x00, 0x2f},
95 	{0x01, 0x7d, 0x7c, 0x92, 0xd7, 0xdd, 0xd2, 0xcb, 0xd0, 0xc6,
96 	 0xe5, 0xe1, 0xe3, 0xda, 0xbd, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
97 	 0x00, 0x2f},
98 	{0x01, 0x7f, 0x7e, 0x95, 0xd7, 0xde, 0xd2, 0xcb, 0xcf, 0xc5,
99 	 0xe5, 0xe3, 0xe3, 0xda, 0xbf, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
100 	 0x00, 0x2f},
101 	{0x01, 0x82, 0x81, 0x99, 0xd6, 0xdd, 0xd1, 0xca, 0xcf, 0xc3,
102 	 0xe4, 0xe3, 0xe3, 0xda, 0xc2, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
103 	 0x00, 0x2f},
104 	{0x01, 0x84, 0x83, 0x9b, 0xd7, 0xde, 0xd2, 0xc8, 0xce, 0xc2,
105 	 0xe4, 0xe3, 0xe2, 0xd9, 0xc3, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
106 	 0x00, 0x2f},
107 	{0x01, 0x87, 0x86, 0x9f, 0xd6, 0xdd, 0xd1, 0xc7, 0xce, 0xc1,
108 	 0xe4, 0xe3, 0xe2, 0xd9, 0xc6, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
109 	 0x00, 0x2f},
110 	{0x01, 0x89, 0x89, 0xa2, 0xd5, 0xdb, 0xcf, 0xc8, 0xcf, 0xc2,
111 	 0xe3, 0xe3, 0xe1, 0xd9, 0xc7, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
112 	 0x00, 0x2f},
113 	{0x01, 0x8b, 0x8b, 0xa5, 0xd5, 0xdb, 0xcf, 0xc7, 0xce, 0xc0,
114 	 0xe3, 0xe3, 0xe1, 0xd8, 0xc7, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
115 	 0x00, 0x2f},
116 	{0x01, 0x8d, 0x8d, 0xa7, 0xd5, 0xdb, 0xcf, 0xc6, 0xce, 0xc0,
117 	 0xe4, 0xe4, 0xe1, 0xd7, 0xc8, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
118 	 0x00, 0x2f},
119 	{0x01, 0x8f, 0x8f, 0xaa, 0xd4, 0xdb, 0xce, 0xc6, 0xcd, 0xbf,
120 	 0xe3, 0xe3, 0xe1, 0xd7, 0xca, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
121 	 0x00, 0x2f},
122 	{0x01, 0x91, 0x91, 0xac, 0xd3, 0xda, 0xce, 0xc5, 0xcd, 0xbe,
123 	 0xe3, 0xe3, 0xe0, 0xd7, 0xca, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
124 	 0x00, 0x2f},
125 	{0x01, 0x93, 0x93, 0xaf, 0xd3, 0xda, 0xcd, 0xc5, 0xcd, 0xbe,
126 	 0xe2, 0xe3, 0xdf, 0xd6, 0xca, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
127 	 0x00, 0x2f},
128 	{0x01, 0x95, 0x95, 0xb1, 0xd2, 0xd9, 0xcc, 0xc4, 0xcd, 0xbe,
129 	 0xe2, 0xe3, 0xdf, 0xd7, 0xcc, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
130 	 0x00, 0x2f},
131 	{0x01, 0x99, 0x99, 0xb6, 0xd1, 0xd9, 0xcc, 0xc3, 0xcb, 0xbc,
132 	 0xe2, 0xe4, 0xdf, 0xd6, 0xcc, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
133 	 0x00, 0x2f},
134 	{0x01, 0x9c, 0x9c, 0xba, 0xd0, 0xd8, 0xcb, 0xc3, 0xcb, 0xbb,
135 	 0xe2, 0xe4, 0xdf, 0xd6, 0xce, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
136 	 0x00, 0x2f},
137 	{0x01, 0x9f, 0x9f, 0xbe, 0xcf, 0xd7, 0xc9, 0xc2, 0xcb, 0xbb,
138 	 0xe1, 0xe3, 0xde, 0xd6, 0xd0, 0xd3, 0xfa, 0xed, 0xe6, 0x2f,
139 	 0x00, 0x2f},
140 };
141 
142 /*
143  * Table of elvss values provided in datasheet and corresponds to
144  * gamma values.
145  */
146 static u8 ams495qa01_elvss[NUM_GAMMA_LEVELS] = {
147 	0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
148 	0x15, 0x15, 0x14, 0x14, 0x13, 0x12,
149 };
150 
151 static int ams495qa01_update_gamma(struct mipi_dbi *dbi, int brightness)
152 {
153 	int tmp = brightness;
154 
155 	mipi_dbi_command_buf(dbi, MCS_SET_GAMMA, ams495qa01_gamma[tmp],
156 			     ARRAY_SIZE(ams495qa01_gamma[tmp]));
157 	mipi_dbi_command(dbi, MCS_SET_GAMMA, 0x00);
158 
159 	/* Undocumented command */
160 	mipi_dbi_command(dbi, 0x26, 0x00);
161 
162 	mipi_dbi_command(dbi, MCS_TEMP_SWIRE, ams495qa01_elvss[tmp]);
163 
164 	return 0;
165 }
166 
167 static void ams495qa01_panel_init(struct d53e6ea8966 *db)
168 {
169 	struct mipi_dbi *dbi = &db->dbi;
170 
171 	mipi_dbi_command(dbi, MCS_PASSWORD_0, 0x5a, 0x5a);
172 	mipi_dbi_command(dbi, MCS_PASSWORD_1, 0x5a, 0x5a);
173 
174 	/* Undocumented commands */
175 	mipi_dbi_command(dbi, 0xb0, 0x02);
176 	mipi_dbi_command(dbi, 0xf3, 0x3b);
177 
178 	mipi_dbi_command(dbi, MCS_ANALOG_PWR_CTL_0, 0x33, 0x42, 0x00, 0x08);
179 	mipi_dbi_command(dbi, MCS_ANALOG_PWR_CTL_1, 0x00, 0x06, 0x26, 0x35, 0x03);
180 
181 	/* Undocumented commands */
182 	mipi_dbi_command(dbi, 0xf6, 0x02);
183 	mipi_dbi_command(dbi, 0xc6, 0x0b, 0x00, 0x00, 0x3c, 0x00, 0x22,
184 			 0x00, 0x00, 0x00, 0x00);
185 
186 	mipi_dbi_command(dbi, MCS_GTCON_SET, 0x20);
187 	mipi_dbi_command(dbi, MCS_TEMP_SWIRE, 0x06, 0x06, 0x06, 0x06);
188 	mipi_dbi_command(dbi, MCS_ELVSS_ON, 0x07, 0x00, 0x10);
189 	mipi_dbi_command(dbi, MCS_GATELESS_SIGNAL_SET, 0x7f, 0x7a,
190 			 0x89, 0x67, 0x26, 0x38, 0x00, 0x00, 0x09,
191 			 0x67, 0x70, 0x88, 0x7a, 0x76, 0x05, 0x09,
192 			 0x23, 0x23, 0x23);
193 
194 	/* Undocumented commands */
195 	mipi_dbi_command(dbi, 0xb5, 0xff, 0xef, 0x35, 0x42, 0x0d, 0xd7,
196 			 0xff, 0x07, 0xff, 0xff, 0xfd, 0x00, 0x01,
197 			 0xff, 0x05, 0x12, 0x0f, 0xff, 0xff, 0xff,
198 			 0xff);
199 	mipi_dbi_command(dbi, 0xb4, 0x15);
200 	mipi_dbi_command(dbi, 0xb3, 0x00);
201 
202 	ams495qa01_update_gamma(dbi, MAX_BRIGHTNESS);
203 }
204 
205 static int d53e6ea8966_prepare(struct drm_panel *panel)
206 {
207 	struct d53e6ea8966 *db = to_d53e6ea8966(panel);
208 	int ret;
209 
210 	/* Power up */
211 	ret = regulator_enable(db->reg_vdd);
212 	if (ret) {
213 		dev_err(db->dev, "failed to enable vdd regulator: %d\n", ret);
214 		return ret;
215 	}
216 
217 	if (db->reg_elvdd) {
218 		ret = regulator_enable(db->reg_elvdd);
219 		if (ret) {
220 			dev_err(db->dev,
221 				"failed to enable elvdd regulator: %d\n", ret);
222 			regulator_disable(db->reg_vdd);
223 			return ret;
224 		}
225 	}
226 
227 	/* Enable */
228 	if (db->enable)
229 		gpiod_set_value_cansleep(db->enable, 1);
230 
231 	msleep(50);
232 
233 	/* Reset */
234 	gpiod_set_value_cansleep(db->reset, 1);
235 	usleep_range(1000, 5000);
236 	gpiod_set_value_cansleep(db->reset, 0);
237 	msleep(20);
238 
239 	db->panel_info->panel_init_seq(db);
240 
241 	return 0;
242 }
243 
244 static int d53e6ea8966_enable(struct drm_panel *panel)
245 {
246 	struct d53e6ea8966 *db = to_d53e6ea8966(panel);
247 	struct mipi_dbi *dbi = &db->dbi;
248 
249 	mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
250 	msleep(200);
251 	mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
252 	usleep_range(10000, 15000);
253 
254 	return 0;
255 }
256 
257 static int d53e6ea8966_disable(struct drm_panel *panel)
258 {
259 	struct d53e6ea8966 *db = to_d53e6ea8966(panel);
260 	struct mipi_dbi *dbi = &db->dbi;
261 
262 	mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
263 	msleep(20);
264 	mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE);
265 	msleep(100);
266 
267 	return 0;
268 }
269 
270 static int d53e6ea8966_unprepare(struct drm_panel *panel)
271 {
272 	struct d53e6ea8966 *db = to_d53e6ea8966(panel);
273 
274 	if (db->enable)
275 		gpiod_set_value_cansleep(db->enable, 0);
276 
277 	gpiod_set_value_cansleep(db->reset, 1);
278 
279 	if (db->reg_elvdd)
280 		regulator_disable(db->reg_elvdd);
281 
282 	regulator_disable(db->reg_vdd);
283 	msleep(100);
284 
285 	return 0;
286 }
287 
288 static int d53e6ea8966_get_modes(struct drm_panel *panel,
289 				 struct drm_connector *connector)
290 {
291 	struct d53e6ea8966 *db = to_d53e6ea8966(panel);
292 	const struct d53e6ea8966_panel_info *panel_info = db->panel_info;
293 	struct drm_display_mode *mode;
294 	static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
295 	unsigned int i;
296 
297 	for (i = 0; i < panel_info->num_modes; i++) {
298 		mode = drm_mode_duplicate(connector->dev,
299 					  &panel_info->display_modes[i]);
300 		if (!mode)
301 			return -ENOMEM;
302 
303 		drm_mode_set_name(mode);
304 		drm_mode_probed_add(connector, mode);
305 	}
306 
307 	connector->display_info.bpc = 8;
308 	connector->display_info.width_mm = panel_info->width_mm;
309 	connector->display_info.height_mm = panel_info->height_mm;
310 	connector->display_info.bus_flags = panel_info->bus_flags;
311 
312 	drm_display_info_set_bus_formats(&connector->display_info,
313 					 &bus_format, 1);
314 
315 	return 1;
316 }
317 
318 static const struct drm_panel_funcs d53e6ea8966_panel_funcs = {
319 	.disable = d53e6ea8966_disable,
320 	.enable = d53e6ea8966_enable,
321 	.get_modes = d53e6ea8966_get_modes,
322 	.prepare = d53e6ea8966_prepare,
323 	.unprepare = d53e6ea8966_unprepare,
324 };
325 
326 static int ams495qa01_set_brightness(struct backlight_device *bd)
327 {
328 	struct d53e6ea8966 *db = bl_get_data(bd);
329 	struct mipi_dbi *dbi = &db->dbi;
330 	int brightness = backlight_get_brightness(bd);
331 
332 	ams495qa01_update_gamma(dbi, brightness);
333 
334 	return 0;
335 }
336 
337 static const struct backlight_ops ams495qa01_backlight_ops = {
338 	.update_status	= ams495qa01_set_brightness,
339 };
340 
341 static int ams495qa01_backlight_register(struct d53e6ea8966 *db)
342 {
343 	struct backlight_properties props = {
344 		.type		= BACKLIGHT_RAW,
345 		.brightness	= MAX_BRIGHTNESS,
346 		.max_brightness = MAX_BRIGHTNESS,
347 	};
348 	struct device *dev = db->dev;
349 	int ret = 0;
350 
351 	db->bl_dev = devm_backlight_device_register(dev, "panel", dev, db,
352 						    &ams495qa01_backlight_ops,
353 						    &props);
354 	if (IS_ERR(db->bl_dev)) {
355 		ret = PTR_ERR(db->bl_dev);
356 		dev_err(dev, "error registering backlight device (%d)\n", ret);
357 	}
358 
359 	return ret;
360 }
361 
362 static int d53e6ea8966_probe(struct spi_device *spi)
363 {
364 	struct device *dev = &spi->dev;
365 	struct mipi_dsi_host *dsi_host;
366 	struct d53e6ea8966 *db;
367 	int ret;
368 	struct mipi_dsi_device_info info = {
369 		.type = "d53e6ea8966",
370 		.channel = 0,
371 		.node = NULL,
372 	};
373 
374 	db = devm_kzalloc(dev, sizeof(*db), GFP_KERNEL);
375 	if (!db)
376 		return -ENOMEM;
377 
378 	spi_set_drvdata(spi, db);
379 
380 	db->dev = dev;
381 
382 	db->panel_info = of_device_get_match_data(dev);
383 	if (!db->panel_info)
384 		return -EINVAL;
385 
386 	db->reg_vdd = devm_regulator_get(dev, "vdd");
387 	if (IS_ERR(db->reg_vdd))
388 		return dev_err_probe(dev, PTR_ERR(db->reg_vdd),
389 				     "Failed to get vdd supply\n");
390 
391 	db->reg_elvdd = devm_regulator_get_optional(dev, "elvdd");
392 	if (IS_ERR(db->reg_elvdd))
393 		db->reg_elvdd = NULL;
394 
395 	db->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
396 	if (IS_ERR(db->reset)) {
397 		ret = PTR_ERR(db->reset);
398 		return dev_err_probe(dev, ret, "no RESET GPIO\n");
399 	}
400 
401 	db->enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
402 	if (IS_ERR(db->enable)) {
403 		ret = PTR_ERR(db->enable);
404 		return dev_err_probe(dev, ret, "cannot get ENABLE GPIO\n");
405 	}
406 
407 	ret = mipi_dbi_spi_init(spi, &db->dbi, NULL);
408 	if (ret)
409 		return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
410 
411 	dsi_host = drm_of_get_dsi_bus(dev);
412 	if (IS_ERR(dsi_host)) {
413 		ret = PTR_ERR(dsi_host);
414 		return dev_err_probe(dev, ret, "Error attaching DSI bus\n");
415 	}
416 
417 	db->dsi_dev = devm_mipi_dsi_device_register_full(dev, dsi_host, &info);
418 	if (IS_ERR(db->dsi_dev)) {
419 		dev_err(dev, "failed to register dsi device: %ld\n",
420 			PTR_ERR(db->dsi_dev));
421 		return PTR_ERR(db->dsi_dev);
422 	}
423 
424 	db->dsi_dev->lanes = 2;
425 	db->dsi_dev->format = MIPI_DSI_FMT_RGB888;
426 	db->dsi_dev->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
427 			  MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
428 
429 	drm_panel_init(&db->panel, dev, &d53e6ea8966_panel_funcs,
430 		       DRM_MODE_CONNECTOR_DSI);
431 
432 	if (db->panel_info->backlight_register) {
433 		ret = db->panel_info->backlight_register(db);
434 		if (ret < 0)
435 			return ret;
436 		db->panel.backlight = db->bl_dev;
437 	}
438 
439 	drm_panel_add(&db->panel);
440 
441 	ret = devm_mipi_dsi_attach(dev, db->dsi_dev);
442 	if (ret < 0) {
443 		dev_err(dev, "mipi_dsi_attach failed: %d\n", ret);
444 		drm_panel_remove(&db->panel);
445 		return ret;
446 	}
447 
448 	return 0;
449 }
450 
451 static void d53e6ea8966_remove(struct spi_device *spi)
452 {
453 	struct d53e6ea8966 *db = spi_get_drvdata(spi);
454 
455 	drm_panel_remove(&db->panel);
456 }
457 
458 static const struct drm_display_mode ams495qa01_modes[] = {
459 	{ /* 60hz */
460 		.clock = 33500,
461 		.hdisplay = 960,
462 		.hsync_start = 960 + 10,
463 		.hsync_end = 960 + 10 + 2,
464 		.htotal = 960 + 10 + 2 + 10,
465 		.vdisplay = 544,
466 		.vsync_start = 544 + 10,
467 		.vsync_end = 544 + 10 + 2,
468 		.vtotal = 544 + 10 + 2 + 10,
469 		.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
470 		.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
471 		},
472 	{ /* 50hz */
473 		.clock = 27800,
474 		.hdisplay = 960,
475 		.hsync_start = 960 + 10,
476 		.hsync_end = 960 + 10 + 2,
477 		.htotal = 960 + 10 + 2 + 10,
478 		.vdisplay = 544,
479 		.vsync_start = 544 + 10,
480 		.vsync_end = 544 + 10 + 2,
481 		.vtotal = 544 + 10 + 2 + 10,
482 		.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
483 		.type = DRM_MODE_TYPE_DRIVER,
484 	},
485 };
486 
487 static const struct d53e6ea8966_panel_info ams495qa01_info = {
488 	.display_modes = ams495qa01_modes,
489 	.num_modes = ARRAY_SIZE(ams495qa01_modes),
490 	.width_mm = 117,
491 	.height_mm = 74,
492 	.bus_flags = DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
493 	.panel_init_seq = ams495qa01_panel_init,
494 	.backlight_register = ams495qa01_backlight_register,
495 };
496 
497 static const struct of_device_id d53e6ea8966_match[] = {
498 	{ .compatible = "samsung,ams495qa01", .data = &ams495qa01_info },
499 	{ /* sentinel */ },
500 };
501 MODULE_DEVICE_TABLE(of, d53e6ea8966_match);
502 
503 static const struct spi_device_id d53e6ea8966_ids[] = {
504 	{ "ams495qa01", 0 },
505 	{ /* sentinel */ },
506 };
507 MODULE_DEVICE_TABLE(spi, d53e6ea8966_ids);
508 
509 static struct spi_driver d53e6ea8966_driver = {
510 	.driver		= {
511 		.name	= "d53e6ea8966-panel",
512 		.of_match_table = d53e6ea8966_match,
513 	},
514 	.id_table	= d53e6ea8966_ids,
515 	.probe		= d53e6ea8966_probe,
516 	.remove		= d53e6ea8966_remove,
517 };
518 module_spi_driver(d53e6ea8966_driver);
519 
520 MODULE_AUTHOR("Chris Morgan <macromorgan@hotmail.com>");
521 MODULE_DESCRIPTION("Magnachip d53e6ea8966 panel driver");
522 MODULE_LICENSE("GPL");
523