Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  4 */
  5
  6#include <linux/backlight.h>
  7#include <linux/delay.h>
  8#include <linux/gpio/consumer.h>
  9#include <linux/module.h>
 10#include <linux/of_device.h>
 11#include <linux/of_graph.h>
 12#include <linux/pinctrl/consumer.h>
 13#include <linux/regulator/consumer.h>
 14
 15#include <video/mipi_display.h>
 16
 17#include <drm/drm_mipi_dsi.h>
 18#include <drm/drm_modes.h>
 19#include <drm/drm_panel.h>
 20#include <drm/drm_print.h>
 21
 22static const char * const regulator_names[] = {
 23	"vdda",
 24	"vdispp",
 25	"vdispn",
 26};
 27
 28static unsigned long const regulator_enable_loads[] = {
 29	62000,
 30	100000,
 31	100000,
 32};
 33
 34static unsigned long const regulator_disable_loads[] = {
 35	80,
 36	100,
 37	100,
 38};
 39
 40struct cmd_set {
 41	u8 commands[4];
 42	u8 size;
 43};
 44
 45struct nt35597_config {
 46	u32 width_mm;
 47	u32 height_mm;
 48	const char *panel_name;
 49	const struct cmd_set *panel_on_cmds;
 50	u32 num_on_cmds;
 51	const struct drm_display_mode *dm;
 52};
 53
 54struct truly_nt35597 {
 55	struct device *dev;
 56	struct drm_panel panel;
 57
 58	struct regulator_bulk_data supplies[ARRAY_SIZE(regulator_names)];
 59
 60	struct gpio_desc *reset_gpio;
 61	struct gpio_desc *mode_gpio;
 62
 63	struct backlight_device *backlight;
 64
 65	struct mipi_dsi_device *dsi[2];
 66
 67	const struct nt35597_config *config;
 68	bool prepared;
 69	bool enabled;
 70};
 71
 72static inline struct truly_nt35597 *panel_to_ctx(struct drm_panel *panel)
 73{
 74	return container_of(panel, struct truly_nt35597, panel);
 75}
 76
 77static const struct cmd_set qcom_2k_panel_magic_cmds[] = {
 78	/* CMD2_P0 */
 79	{ { 0xff, 0x20 }, 2 },
 80	{ { 0xfb, 0x01 }, 2 },
 81	{ { 0x00, 0x01 }, 2 },
 82	{ { 0x01, 0x55 }, 2 },
 83	{ { 0x02, 0x45 }, 2 },
 84	{ { 0x05, 0x40 }, 2 },
 85	{ { 0x06, 0x19 }, 2 },
 86	{ { 0x07, 0x1e }, 2 },
 87	{ { 0x0b, 0x73 }, 2 },
 88	{ { 0x0c, 0x73 }, 2 },
 89	{ { 0x0e, 0xb0 }, 2 },
 90	{ { 0x0f, 0xae }, 2 },
 91	{ { 0x11, 0xb8 }, 2 },
 92	{ { 0x13, 0x00 }, 2 },
 93	{ { 0x58, 0x80 }, 2 },
 94	{ { 0x59, 0x01 }, 2 },
 95	{ { 0x5a, 0x00 }, 2 },
 96	{ { 0x5b, 0x01 }, 2 },
 97	{ { 0x5c, 0x80 }, 2 },
 98	{ { 0x5d, 0x81 }, 2 },
 99	{ { 0x5e, 0x00 }, 2 },
100	{ { 0x5f, 0x01 }, 2 },
101	{ { 0x72, 0x11 }, 2 },
102	{ { 0x68, 0x03 }, 2 },
103	/* CMD2_P4 */
104	{ { 0xFF, 0x24 }, 2 },
105	{ { 0xFB, 0x01 }, 2 },
106	{ { 0x00, 0x1C }, 2 },
107	{ { 0x01, 0x0B }, 2 },
108	{ { 0x02, 0x0C }, 2 },
109	{ { 0x03, 0x01 }, 2 },
110	{ { 0x04, 0x0F }, 2 },
111	{ { 0x05, 0x10 }, 2 },
112	{ { 0x06, 0x10 }, 2 },
113	{ { 0x07, 0x10 }, 2 },
114	{ { 0x08, 0x89 }, 2 },
115	{ { 0x09, 0x8A }, 2 },
116	{ { 0x0A, 0x13 }, 2 },
117	{ { 0x0B, 0x13 }, 2 },
118	{ { 0x0C, 0x15 }, 2 },
119	{ { 0x0D, 0x15 }, 2 },
120	{ { 0x0E, 0x17 }, 2 },
121	{ { 0x0F, 0x17 }, 2 },
122	{ { 0x10, 0x1C }, 2 },
123	{ { 0x11, 0x0B }, 2 },
124	{ { 0x12, 0x0C }, 2 },
125	{ { 0x13, 0x01 }, 2 },
126	{ { 0x14, 0x0F }, 2 },
127	{ { 0x15, 0x10 }, 2 },
128	{ { 0x16, 0x10 }, 2 },
129	{ { 0x17, 0x10 }, 2 },
130	{ { 0x18, 0x89 }, 2 },
131	{ { 0x19, 0x8A }, 2 },
132	{ { 0x1A, 0x13 }, 2 },
133	{ { 0x1B, 0x13 }, 2 },
134	{ { 0x1C, 0x15 }, 2 },
135	{ { 0x1D, 0x15 }, 2 },
136	{ { 0x1E, 0x17 }, 2 },
137	{ { 0x1F, 0x17 }, 2 },
138	/* STV */
139	{ { 0x20, 0x40 }, 2 },
140	{ { 0x21, 0x01 }, 2 },
141	{ { 0x22, 0x00 }, 2 },
142	{ { 0x23, 0x40 }, 2 },
143	{ { 0x24, 0x40 }, 2 },
144	{ { 0x25, 0x6D }, 2 },
145	{ { 0x26, 0x40 }, 2 },
146	{ { 0x27, 0x40 }, 2 },
147	/* Vend */
148	{ { 0xE0, 0x00 }, 2 },
149	{ { 0xDC, 0x21 }, 2 },
150	{ { 0xDD, 0x22 }, 2 },
151	{ { 0xDE, 0x07 }, 2 },
152	{ { 0xDF, 0x07 }, 2 },
153	{ { 0xE3, 0x6D }, 2 },
154	{ { 0xE1, 0x07 }, 2 },
155	{ { 0xE2, 0x07 }, 2 },
156	/* UD */
157	{ { 0x29, 0xD8 }, 2 },
158	{ { 0x2A, 0x2A }, 2 },
159	/* CLK */
160	{ { 0x4B, 0x03 }, 2 },
161	{ { 0x4C, 0x11 }, 2 },
162	{ { 0x4D, 0x10 }, 2 },
163	{ { 0x4E, 0x01 }, 2 },
164	{ { 0x4F, 0x01 }, 2 },
165	{ { 0x50, 0x10 }, 2 },
166	{ { 0x51, 0x00 }, 2 },
167	{ { 0x52, 0x80 }, 2 },
168	{ { 0x53, 0x00 }, 2 },
169	{ { 0x56, 0x00 }, 2 },
170	{ { 0x54, 0x07 }, 2 },
171	{ { 0x58, 0x07 }, 2 },
172	{ { 0x55, 0x25 }, 2 },
173	/* Reset XDONB */
174	{ { 0x5B, 0x43 }, 2 },
175	{ { 0x5C, 0x00 }, 2 },
176	{ { 0x5F, 0x73 }, 2 },
177	{ { 0x60, 0x73 }, 2 },
178	{ { 0x63, 0x22 }, 2 },
179	{ { 0x64, 0x00 }, 2 },
180	{ { 0x67, 0x08 }, 2 },
181	{ { 0x68, 0x04 }, 2 },
182	/* Resolution:1440x2560 */
183	{ { 0x72, 0x02 }, 2 },
184	/* mux */
185	{ { 0x7A, 0x80 }, 2 },
186	{ { 0x7B, 0x91 }, 2 },
187	{ { 0x7C, 0xD8 }, 2 },
188	{ { 0x7D, 0x60 }, 2 },
189	{ { 0x7F, 0x15 }, 2 },
190	{ { 0x75, 0x15 }, 2 },
191	/* ABOFF */
192	{ { 0xB3, 0xC0 }, 2 },
193	{ { 0xB4, 0x00 }, 2 },
194	{ { 0xB5, 0x00 }, 2 },
195	/* Source EQ */
196	{ { 0x78, 0x00 }, 2 },
197	{ { 0x79, 0x00 }, 2 },
198	{ { 0x80, 0x00 }, 2 },
199	{ { 0x83, 0x00 }, 2 },
200	/* FP BP */
201	{ { 0x93, 0x0A }, 2 },
202	{ { 0x94, 0x0A }, 2 },
203	/* Inversion Type */
204	{ { 0x8A, 0x00 }, 2 },
205	{ { 0x9B, 0xFF }, 2 },
206	/* IMGSWAP =1 @PortSwap=1 */
207	{ { 0x9D, 0xB0 }, 2 },
208	{ { 0x9F, 0x63 }, 2 },
209	{ { 0x98, 0x10 }, 2 },
210	/* FRM */
211	{ { 0xEC, 0x00 }, 2 },
212	/* CMD1 */
213	{ { 0xFF, 0x10 }, 2 },
214	/* VBP+VSA=,VFP = 10H */
215	{ { 0x3B, 0x03, 0x0A, 0x0A }, 4 },
216	/* FTE on */
217	{ { 0x35, 0x00 }, 2 },
218	/* EN_BK =1(auto black) */
219	{ { 0xE5, 0x01 }, 2 },
220	/* CMD mode(10) VDO mode(03) */
221	{ { 0xBB, 0x03 }, 2 },
222	/* Non Reload MTP */
223	{ { 0xFB, 0x01 }, 2 },
224};
225
226static int truly_dcs_write(struct drm_panel *panel, u32 command)
227{
228	struct truly_nt35597 *ctx = panel_to_ctx(panel);
229	int i, ret;
230
231	for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) {
232		ret = mipi_dsi_dcs_write(ctx->dsi[i], command, NULL, 0);
233		if (ret < 0) {
234			DRM_DEV_ERROR(ctx->dev,
235				"cmd 0x%x failed for dsi = %d\n",
236				command, i);
237		}
238	}
239
240	return ret;
241}
242
243static int truly_dcs_write_buf(struct drm_panel *panel,
244	u32 size, const u8 *buf)
245{
246	struct truly_nt35597 *ctx = panel_to_ctx(panel);
247	int ret = 0;
248	int i;
249
250	for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) {
251		ret = mipi_dsi_dcs_write_buffer(ctx->dsi[i], buf, size);
252		if (ret < 0) {
253			DRM_DEV_ERROR(ctx->dev,
254				"failed to tx cmd [%d], err: %d\n", i, ret);
255			return ret;
256		}
257	}
258
259	return ret;
260}
261
262static int truly_35597_power_on(struct truly_nt35597 *ctx)
263{
264	int ret, i;
265
266	for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
267		ret = regulator_set_load(ctx->supplies[i].consumer,
268					regulator_enable_loads[i]);
269		if (ret)
270			return ret;
271	}
272
273	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
274	if (ret < 0)
275		return ret;
276
277	/*
278	 * Reset sequence of truly panel requires the panel to be
279	 * out of reset for 10ms, followed by being held in reset
280	 * for 10ms and then out again
281	 */
282	gpiod_set_value(ctx->reset_gpio, 0);
283	usleep_range(10000, 20000);
284	gpiod_set_value(ctx->reset_gpio, 1);
285	usleep_range(10000, 20000);
286	gpiod_set_value(ctx->reset_gpio, 0);
287	usleep_range(10000, 20000);
288
289	return 0;
290}
291
292static int truly_nt35597_power_off(struct truly_nt35597 *ctx)
293{
294	int ret = 0;
295	int i;
296
297	gpiod_set_value(ctx->reset_gpio, 1);
298
299	for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
300		ret = regulator_set_load(ctx->supplies[i].consumer,
301				regulator_disable_loads[i]);
302		if (ret) {
303			DRM_DEV_ERROR(ctx->dev,
304				"regulator_set_load failed %d\n", ret);
305			return ret;
306		}
307	}
308
309	ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
310	if (ret) {
311		DRM_DEV_ERROR(ctx->dev,
312			"regulator_bulk_disable failed %d\n", ret);
313	}
314	return ret;
315}
316
317static int truly_nt35597_disable(struct drm_panel *panel)
318{
319	struct truly_nt35597 *ctx = panel_to_ctx(panel);
320	int ret;
321
322	if (!ctx->enabled)
323		return 0;
324
325	if (ctx->backlight) {
326		ret = backlight_disable(ctx->backlight);
327		if (ret < 0)
328			DRM_DEV_ERROR(ctx->dev, "backlight disable failed %d\n",
329				ret);
330	}
331
332	ctx->enabled = false;
333	return 0;
334}
335
336static int truly_nt35597_unprepare(struct drm_panel *panel)
337{
338	struct truly_nt35597 *ctx = panel_to_ctx(panel);
339	int ret = 0;
340
341	if (!ctx->prepared)
342		return 0;
343
344	ctx->dsi[0]->mode_flags = 0;
345	ctx->dsi[1]->mode_flags = 0;
346
347	ret = truly_dcs_write(panel, MIPI_DCS_SET_DISPLAY_OFF);
348	if (ret < 0) {
349		DRM_DEV_ERROR(ctx->dev,
350			"set_display_off cmd failed ret = %d\n",
351			ret);
352	}
353
354	/* 120ms delay required here as per DCS spec */
355	msleep(120);
356
357	ret = truly_dcs_write(panel, MIPI_DCS_ENTER_SLEEP_MODE);
358	if (ret < 0) {
359		DRM_DEV_ERROR(ctx->dev,
360			"enter_sleep cmd failed ret = %d\n", ret);
361	}
362
363	ret = truly_nt35597_power_off(ctx);
364	if (ret < 0)
365		DRM_DEV_ERROR(ctx->dev, "power_off failed ret = %d\n", ret);
366
367	ctx->prepared = false;
368	return ret;
369}
370
371static int truly_nt35597_prepare(struct drm_panel *panel)
372{
373	struct truly_nt35597 *ctx = panel_to_ctx(panel);
374	int ret;
375	int i;
376	const struct cmd_set *panel_on_cmds;
377	const struct nt35597_config *config;
378	u32 num_cmds;
379
380	if (ctx->prepared)
381		return 0;
382
383	ret = truly_35597_power_on(ctx);
384	if (ret < 0)
385		return ret;
386
387	ctx->dsi[0]->mode_flags |= MIPI_DSI_MODE_LPM;
388	ctx->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM;
389
390	config = ctx->config;
391	panel_on_cmds = config->panel_on_cmds;
392	num_cmds = config->num_on_cmds;
393
394	for (i = 0; i < num_cmds; i++) {
395		ret = truly_dcs_write_buf(panel,
396				panel_on_cmds[i].size,
397					panel_on_cmds[i].commands);
398		if (ret < 0) {
399			DRM_DEV_ERROR(ctx->dev,
400				"cmd set tx failed i = %d ret = %d\n",
401					i, ret);
402			goto power_off;
403		}
404	}
405
406	ret = truly_dcs_write(panel, MIPI_DCS_EXIT_SLEEP_MODE);
407	if (ret < 0) {
408		DRM_DEV_ERROR(ctx->dev,
409			"exit_sleep_mode cmd failed ret = %d\n",
410			ret);
411		goto power_off;
412	}
413
414	/* Per DSI spec wait 120ms after sending exit sleep DCS command */
415	msleep(120);
416
417	ret = truly_dcs_write(panel, MIPI_DCS_SET_DISPLAY_ON);
418	if (ret < 0) {
419		DRM_DEV_ERROR(ctx->dev,
420			"set_display_on cmd failed ret = %d\n", ret);
421		goto power_off;
422	}
423
424	/* Per DSI spec wait 120ms after sending set_display_on DCS command */
425	msleep(120);
426
427	ctx->prepared = true;
428
429	return 0;
430
431power_off:
432	if (truly_nt35597_power_off(ctx))
433		DRM_DEV_ERROR(ctx->dev, "power_off failed\n");
434	return ret;
435}
436
437static int truly_nt35597_enable(struct drm_panel *panel)
438{
439	struct truly_nt35597 *ctx = panel_to_ctx(panel);
440	int ret;
441
442	if (ctx->enabled)
443		return 0;
444
445	if (ctx->backlight) {
446		ret = backlight_enable(ctx->backlight);
447		if (ret < 0)
448			DRM_DEV_ERROR(ctx->dev, "backlight enable failed %d\n",
449						  ret);
450	}
451
452	ctx->enabled = true;
453
454	return 0;
455}
456
457static int truly_nt35597_get_modes(struct drm_panel *panel,
458				   struct drm_connector *connector)
459{
460	struct truly_nt35597 *ctx = panel_to_ctx(panel);
461	struct drm_display_mode *mode;
462	const struct nt35597_config *config;
463
464	config = ctx->config;
465	mode = drm_mode_create(connector->dev);
466	if (!mode) {
467		DRM_DEV_ERROR(ctx->dev,
468			"failed to create a new display mode\n");
469		return 0;
470	}
471
472	connector->display_info.width_mm = config->width_mm;
473	connector->display_info.height_mm = config->height_mm;
474	drm_mode_copy(mode, config->dm);
475	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
476	drm_mode_probed_add(connector, mode);
477
478	return 1;
479}
480
481static const struct drm_panel_funcs truly_nt35597_drm_funcs = {
482	.disable = truly_nt35597_disable,
483	.unprepare = truly_nt35597_unprepare,
484	.prepare = truly_nt35597_prepare,
485	.enable = truly_nt35597_enable,
486	.get_modes = truly_nt35597_get_modes,
487};
488
489static int truly_nt35597_panel_add(struct truly_nt35597 *ctx)
490{
491	struct device *dev = ctx->dev;
492	int ret, i;
493
494	for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++)
495		ctx->supplies[i].supply = regulator_names[i];
496
497	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
498				      ctx->supplies);
499	if (ret < 0)
500		return ret;
501
502	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
503	if (IS_ERR(ctx->reset_gpio)) {
504		DRM_DEV_ERROR(dev, "cannot get reset gpio %ld\n",
505			PTR_ERR(ctx->reset_gpio));
506		return PTR_ERR(ctx->reset_gpio);
507	}
508
509	ctx->mode_gpio = devm_gpiod_get(dev, "mode", GPIOD_OUT_LOW);
510	if (IS_ERR(ctx->mode_gpio)) {
511		DRM_DEV_ERROR(dev, "cannot get mode gpio %ld\n",
512			PTR_ERR(ctx->mode_gpio));
513		return PTR_ERR(ctx->mode_gpio);
514	}
515
516	/* dual port */
517	gpiod_set_value(ctx->mode_gpio, 0);
518
519	drm_panel_init(&ctx->panel, dev, &truly_nt35597_drm_funcs,
520		       DRM_MODE_CONNECTOR_DSI);
521	drm_panel_add(&ctx->panel);
522
523	return 0;
524}
525
526static const struct drm_display_mode qcom_sdm845_mtp_2k_mode = {
527	.name = "1440x2560",
528	.clock = 268316,
529	.hdisplay = 1440,
530	.hsync_start = 1440 + 200,
531	.hsync_end = 1440 + 200 + 32,
532	.htotal = 1440 + 200 + 32 + 64,
533	.vdisplay = 2560,
534	.vsync_start = 2560 + 8,
535	.vsync_end = 2560 + 8 + 1,
536	.vtotal = 2560 + 8 + 1 + 7,
537	.flags = 0,
538};
539
540static const struct nt35597_config nt35597_dir = {
541	.width_mm = 74,
542	.height_mm = 131,
543	.panel_name = "qcom_sdm845_mtp_2k_panel",
544	.dm = &qcom_sdm845_mtp_2k_mode,
545	.panel_on_cmds = qcom_2k_panel_magic_cmds,
546	.num_on_cmds = ARRAY_SIZE(qcom_2k_panel_magic_cmds),
547};
548
549static int truly_nt35597_probe(struct mipi_dsi_device *dsi)
550{
551	struct device *dev = &dsi->dev;
552	struct truly_nt35597 *ctx;
553	struct mipi_dsi_device *dsi1_device;
554	struct device_node *dsi1;
555	struct mipi_dsi_host *dsi1_host;
556	struct mipi_dsi_device *dsi_dev;
557	int ret = 0;
558	int i;
559
560	const struct mipi_dsi_device_info info = {
561		.type = "trulynt35597",
562		.channel = 0,
563		.node = NULL,
564	};
565
566	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
567
568	if (!ctx)
569		return -ENOMEM;
570
571	/*
572	 * This device represents itself as one with two input ports which are
573	 * fed by the output ports of the two DSI controllers . The DSI0 is
574	 * the master controller and has most of the panel related info in its
575	 * child node.
576	 */
577
578	ctx->config = of_device_get_match_data(dev);
579
580	if (!ctx->config) {
581		dev_err(dev, "missing device configuration\n");
582		return -ENODEV;
583	}
584
585	dsi1 = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
586	if (!dsi1) {
587		DRM_DEV_ERROR(dev,
588			"failed to get remote node for dsi1_device\n");
589		return -ENODEV;
590	}
591
592	dsi1_host = of_find_mipi_dsi_host_by_node(dsi1);
593	of_node_put(dsi1);
594	if (!dsi1_host) {
595		DRM_DEV_ERROR(dev, "failed to find dsi host\n");
596		return -EPROBE_DEFER;
597	}
598
599	/* register the second DSI device */
600	dsi1_device = mipi_dsi_device_register_full(dsi1_host, &info);
601	if (IS_ERR(dsi1_device)) {
602		DRM_DEV_ERROR(dev, "failed to create dsi device\n");
603		return PTR_ERR(dsi1_device);
604	}
605
606	mipi_dsi_set_drvdata(dsi, ctx);
607
608	ctx->dev = dev;
609	ctx->dsi[0] = dsi;
610	ctx->dsi[1] = dsi1_device;
611
612	ret = truly_nt35597_panel_add(ctx);
613	if (ret) {
614		DRM_DEV_ERROR(dev, "failed to add panel\n");
615		goto err_panel_add;
616	}
617
618	for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) {
619		dsi_dev = ctx->dsi[i];
620		dsi_dev->lanes = 4;
621		dsi_dev->format = MIPI_DSI_FMT_RGB888;
622		dsi_dev->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM |
623			MIPI_DSI_CLOCK_NON_CONTINUOUS;
624		ret = mipi_dsi_attach(dsi_dev);
625		if (ret < 0) {
626			DRM_DEV_ERROR(dev,
627				"dsi attach failed i = %d\n", i);
628			goto err_dsi_attach;
629		}
630	}
631
632	return 0;
633
634err_dsi_attach:
635	drm_panel_remove(&ctx->panel);
636err_panel_add:
637	mipi_dsi_device_unregister(dsi1_device);
638	return ret;
639}
640
641static int truly_nt35597_remove(struct mipi_dsi_device *dsi)
642{
643	struct truly_nt35597 *ctx = mipi_dsi_get_drvdata(dsi);
644
645	if (ctx->dsi[0])
646		mipi_dsi_detach(ctx->dsi[0]);
647	if (ctx->dsi[1]) {
648		mipi_dsi_detach(ctx->dsi[1]);
649		mipi_dsi_device_unregister(ctx->dsi[1]);
650	}
651
652	drm_panel_remove(&ctx->panel);
653	return 0;
654}
655
656static const struct of_device_id truly_nt35597_of_match[] = {
657	{
658		.compatible = "truly,nt35597-2K-display",
659		.data = &nt35597_dir,
660	},
661	{ }
662};
663MODULE_DEVICE_TABLE(of, truly_nt35597_of_match);
664
665static struct mipi_dsi_driver truly_nt35597_driver = {
666	.driver = {
667		.name = "panel-truly-nt35597",
668		.of_match_table = truly_nt35597_of_match,
669	},
670	.probe = truly_nt35597_probe,
671	.remove = truly_nt35597_remove,
672};
673module_mipi_dsi_driver(truly_nt35597_driver);
674
675MODULE_DESCRIPTION("Truly NT35597 DSI Panel Driver");
676MODULE_LICENSE("GPL v2");