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