xref: /linux/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c (revision 03c11eb3b16dc0058589751dfd91f254be2be613)
1*22de25f8SKonrad Dybcio // SPDX-License-Identifier: GPL-2.0-only
2*22de25f8SKonrad Dybcio /*
3*22de25f8SKonrad Dybcio  * Copyright (c) 2022 Konrad Dybcio <konrad.dybcio@somainline.org>
4*22de25f8SKonrad Dybcio  *
5*22de25f8SKonrad Dybcio  * Generated with linux-mdss-dsi-panel-driver-generator with a
6*22de25f8SKonrad Dybcio  * substantial amount of manual adjustments.
7*22de25f8SKonrad Dybcio  *
8*22de25f8SKonrad Dybcio  * SONY Downstream kernel calls this one:
9*22de25f8SKonrad Dybcio  * - "JDI ID3" for Akari  (XZ2)
10*22de25f8SKonrad Dybcio  * - "JDI ID4" for Apollo (XZ2 Compact)
11*22de25f8SKonrad Dybcio  */
12*22de25f8SKonrad Dybcio 
13*22de25f8SKonrad Dybcio #include <linux/delay.h>
14*22de25f8SKonrad Dybcio #include <linux/gpio/consumer.h>
15*22de25f8SKonrad Dybcio #include <linux/module.h>
16*22de25f8SKonrad Dybcio #include <linux/of.h>
17*22de25f8SKonrad Dybcio #include <linux/regulator/consumer.h>
18*22de25f8SKonrad Dybcio 
19*22de25f8SKonrad Dybcio #include <video/mipi_display.h>
20*22de25f8SKonrad Dybcio 
21*22de25f8SKonrad Dybcio #include <drm/drm_mipi_dsi.h>
22*22de25f8SKonrad Dybcio #include <drm/drm_modes.h>
23*22de25f8SKonrad Dybcio #include <drm/drm_panel.h>
24*22de25f8SKonrad Dybcio 
25*22de25f8SKonrad Dybcio enum {
26*22de25f8SKonrad Dybcio 	TYPE_TAMA_60HZ,
27*22de25f8SKonrad Dybcio 	/*
28*22de25f8SKonrad Dybcio 	 * Leaving room for expansion - SONY very often uses
29*22de25f8SKonrad Dybcio 	 * *truly reliably* overclockable panels on their flagships!
30*22de25f8SKonrad Dybcio 	 */
31*22de25f8SKonrad Dybcio };
32*22de25f8SKonrad Dybcio 
33*22de25f8SKonrad Dybcio struct sony_td4353_jdi {
34*22de25f8SKonrad Dybcio 	struct drm_panel panel;
35*22de25f8SKonrad Dybcio 	struct mipi_dsi_device *dsi;
36*22de25f8SKonrad Dybcio 	struct regulator_bulk_data supplies[3];
37*22de25f8SKonrad Dybcio 	struct gpio_desc *panel_reset_gpio;
38*22de25f8SKonrad Dybcio 	struct gpio_desc *touch_reset_gpio;
39*22de25f8SKonrad Dybcio 	int type;
40*22de25f8SKonrad Dybcio };
41*22de25f8SKonrad Dybcio 
to_sony_td4353_jdi(struct drm_panel * panel)42*22de25f8SKonrad Dybcio static inline struct sony_td4353_jdi *to_sony_td4353_jdi(struct drm_panel *panel)
43*22de25f8SKonrad Dybcio {
44*22de25f8SKonrad Dybcio 	return container_of(panel, struct sony_td4353_jdi, panel);
45*22de25f8SKonrad Dybcio }
46*22de25f8SKonrad Dybcio 
sony_td4353_jdi_on(struct sony_td4353_jdi * ctx)47*22de25f8SKonrad Dybcio static int sony_td4353_jdi_on(struct sony_td4353_jdi *ctx)
48*22de25f8SKonrad Dybcio {
49*22de25f8SKonrad Dybcio 	struct mipi_dsi_device *dsi = ctx->dsi;
50*22de25f8SKonrad Dybcio 	struct device *dev = &dsi->dev;
51*22de25f8SKonrad Dybcio 	int ret;
52*22de25f8SKonrad Dybcio 
53*22de25f8SKonrad Dybcio 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
54*22de25f8SKonrad Dybcio 
55*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_set_column_address(dsi, 0x0000, 1080 - 1);
56*22de25f8SKonrad Dybcio 	if (ret < 0) {
57*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to set column address: %d\n", ret);
58*22de25f8SKonrad Dybcio 		return ret;
59*22de25f8SKonrad Dybcio 	}
60*22de25f8SKonrad Dybcio 
61*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_set_page_address(dsi, 0x0000, 2160 - 1);
62*22de25f8SKonrad Dybcio 	if (ret < 0) {
63*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to set page address: %d\n", ret);
64*22de25f8SKonrad Dybcio 		return ret;
65*22de25f8SKonrad Dybcio 	}
66*22de25f8SKonrad Dybcio 
67*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0);
68*22de25f8SKonrad Dybcio 	if (ret < 0) {
69*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to set tear scanline: %d\n", ret);
70*22de25f8SKonrad Dybcio 		return ret;
71*22de25f8SKonrad Dybcio 	}
72*22de25f8SKonrad Dybcio 
73*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
74*22de25f8SKonrad Dybcio 	if (ret < 0) {
75*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to set tear on: %d\n", ret);
76*22de25f8SKonrad Dybcio 		return ret;
77*22de25f8SKonrad Dybcio 	}
78*22de25f8SKonrad Dybcio 
79*22de25f8SKonrad Dybcio 	mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
80*22de25f8SKonrad Dybcio 
81*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x77);
82*22de25f8SKonrad Dybcio 	if (ret < 0) {
83*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to set pixel format: %d\n", ret);
84*22de25f8SKonrad Dybcio 		return ret;
85*22de25f8SKonrad Dybcio 	}
86*22de25f8SKonrad Dybcio 
87*22de25f8SKonrad Dybcio 	mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS,
88*22de25f8SKonrad Dybcio 			  0x00, 0x00, 0x08, 0x6f);
89*22de25f8SKonrad Dybcio 
90*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
91*22de25f8SKonrad Dybcio 	if (ret < 0) {
92*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
93*22de25f8SKonrad Dybcio 		return ret;
94*22de25f8SKonrad Dybcio 	}
95*22de25f8SKonrad Dybcio 	msleep(70);
96*22de25f8SKonrad Dybcio 
97*22de25f8SKonrad Dybcio 	mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START);
98*22de25f8SKonrad Dybcio 
99*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_set_display_on(dsi);
100*22de25f8SKonrad Dybcio 	if (ret < 0) {
101*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to turn display on: %d\n", ret);
102*22de25f8SKonrad Dybcio 		return ret;
103*22de25f8SKonrad Dybcio 	}
104*22de25f8SKonrad Dybcio 
105*22de25f8SKonrad Dybcio 	return 0;
106*22de25f8SKonrad Dybcio }
107*22de25f8SKonrad Dybcio 
sony_td4353_jdi_off(struct sony_td4353_jdi * ctx)108*22de25f8SKonrad Dybcio static int sony_td4353_jdi_off(struct sony_td4353_jdi *ctx)
109*22de25f8SKonrad Dybcio {
110*22de25f8SKonrad Dybcio 	struct mipi_dsi_device *dsi = ctx->dsi;
111*22de25f8SKonrad Dybcio 	struct device *dev = &dsi->dev;
112*22de25f8SKonrad Dybcio 	int ret;
113*22de25f8SKonrad Dybcio 
114*22de25f8SKonrad Dybcio 	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
115*22de25f8SKonrad Dybcio 
116*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_set_display_off(dsi);
117*22de25f8SKonrad Dybcio 	if (ret < 0) {
118*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to set display off: %d\n", ret);
119*22de25f8SKonrad Dybcio 		return ret;
120*22de25f8SKonrad Dybcio 	}
121*22de25f8SKonrad Dybcio 	msleep(22);
122*22de25f8SKonrad Dybcio 
123*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_set_tear_off(dsi);
124*22de25f8SKonrad Dybcio 	if (ret < 0) {
125*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to set tear off: %d\n", ret);
126*22de25f8SKonrad Dybcio 		return ret;
127*22de25f8SKonrad Dybcio 	}
128*22de25f8SKonrad Dybcio 
129*22de25f8SKonrad Dybcio 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
130*22de25f8SKonrad Dybcio 	if (ret < 0) {
131*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
132*22de25f8SKonrad Dybcio 		return ret;
133*22de25f8SKonrad Dybcio 	}
134*22de25f8SKonrad Dybcio 	msleep(80);
135*22de25f8SKonrad Dybcio 
136*22de25f8SKonrad Dybcio 	return 0;
137*22de25f8SKonrad Dybcio }
138*22de25f8SKonrad Dybcio 
sony_td4353_assert_reset_gpios(struct sony_td4353_jdi * ctx,int mode)139*22de25f8SKonrad Dybcio static void sony_td4353_assert_reset_gpios(struct sony_td4353_jdi *ctx, int mode)
140*22de25f8SKonrad Dybcio {
141*22de25f8SKonrad Dybcio 	gpiod_set_value_cansleep(ctx->touch_reset_gpio, mode);
142*22de25f8SKonrad Dybcio 	gpiod_set_value_cansleep(ctx->panel_reset_gpio, mode);
143*22de25f8SKonrad Dybcio 	usleep_range(5000, 5100);
144*22de25f8SKonrad Dybcio }
145*22de25f8SKonrad Dybcio 
sony_td4353_jdi_prepare(struct drm_panel * panel)146*22de25f8SKonrad Dybcio static int sony_td4353_jdi_prepare(struct drm_panel *panel)
147*22de25f8SKonrad Dybcio {
148*22de25f8SKonrad Dybcio 	struct sony_td4353_jdi *ctx = to_sony_td4353_jdi(panel);
149*22de25f8SKonrad Dybcio 	struct device *dev = &ctx->dsi->dev;
150*22de25f8SKonrad Dybcio 	int ret;
151*22de25f8SKonrad Dybcio 
152*22de25f8SKonrad Dybcio 	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
153*22de25f8SKonrad Dybcio 	if (ret < 0) {
154*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to enable regulators: %d\n", ret);
155*22de25f8SKonrad Dybcio 		return ret;
156*22de25f8SKonrad Dybcio 	}
157*22de25f8SKonrad Dybcio 
158*22de25f8SKonrad Dybcio 	msleep(100);
159*22de25f8SKonrad Dybcio 
160*22de25f8SKonrad Dybcio 	sony_td4353_assert_reset_gpios(ctx, 1);
161*22de25f8SKonrad Dybcio 
162*22de25f8SKonrad Dybcio 	ret = sony_td4353_jdi_on(ctx);
163*22de25f8SKonrad Dybcio 	if (ret < 0) {
164*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to power on panel: %d\n", ret);
165*22de25f8SKonrad Dybcio 		sony_td4353_assert_reset_gpios(ctx, 0);
166*22de25f8SKonrad Dybcio 		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
167*22de25f8SKonrad Dybcio 		return ret;
168*22de25f8SKonrad Dybcio 	}
169*22de25f8SKonrad Dybcio 
170*22de25f8SKonrad Dybcio 	return 0;
171*22de25f8SKonrad Dybcio }
172*22de25f8SKonrad Dybcio 
sony_td4353_jdi_unprepare(struct drm_panel * panel)173*22de25f8SKonrad Dybcio static int sony_td4353_jdi_unprepare(struct drm_panel *panel)
174*22de25f8SKonrad Dybcio {
175*22de25f8SKonrad Dybcio 	struct sony_td4353_jdi *ctx = to_sony_td4353_jdi(panel);
176*22de25f8SKonrad Dybcio 	struct device *dev = &ctx->dsi->dev;
177*22de25f8SKonrad Dybcio 	int ret;
178*22de25f8SKonrad Dybcio 
179*22de25f8SKonrad Dybcio 	ret = sony_td4353_jdi_off(ctx);
180*22de25f8SKonrad Dybcio 	if (ret < 0)
181*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to power off panel: %d\n", ret);
182*22de25f8SKonrad Dybcio 
183*22de25f8SKonrad Dybcio 	sony_td4353_assert_reset_gpios(ctx, 0);
184*22de25f8SKonrad Dybcio 	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
185*22de25f8SKonrad Dybcio 
186*22de25f8SKonrad Dybcio 	return 0;
187*22de25f8SKonrad Dybcio }
188*22de25f8SKonrad Dybcio 
189*22de25f8SKonrad Dybcio static const struct drm_display_mode sony_td4353_jdi_mode_tama_60hz = {
190*22de25f8SKonrad Dybcio 	.clock = (1080 + 4 + 8 + 8) * (2160 + 259 + 8 + 8) * 60 / 1000,
191*22de25f8SKonrad Dybcio 	.hdisplay = 1080,
192*22de25f8SKonrad Dybcio 	.hsync_start = 1080 + 4,
193*22de25f8SKonrad Dybcio 	.hsync_end = 1080 + 4 + 8,
194*22de25f8SKonrad Dybcio 	.htotal = 1080 + 4 + 8 + 8,
195*22de25f8SKonrad Dybcio 	.vdisplay = 2160,
196*22de25f8SKonrad Dybcio 	.vsync_start = 2160 + 259,
197*22de25f8SKonrad Dybcio 	.vsync_end = 2160 + 259 + 8,
198*22de25f8SKonrad Dybcio 	.vtotal = 2160 + 259 + 8 + 8,
199*22de25f8SKonrad Dybcio 	.width_mm = 64,
200*22de25f8SKonrad Dybcio 	.height_mm = 128,
201*22de25f8SKonrad Dybcio };
202*22de25f8SKonrad Dybcio 
sony_td4353_jdi_get_modes(struct drm_panel * panel,struct drm_connector * connector)203*22de25f8SKonrad Dybcio static int sony_td4353_jdi_get_modes(struct drm_panel *panel,
204*22de25f8SKonrad Dybcio 				   struct drm_connector *connector)
205*22de25f8SKonrad Dybcio {
206*22de25f8SKonrad Dybcio 	struct sony_td4353_jdi *ctx = to_sony_td4353_jdi(panel);
207*22de25f8SKonrad Dybcio 	struct drm_display_mode *mode = NULL;
208*22de25f8SKonrad Dybcio 
209*22de25f8SKonrad Dybcio 	if (ctx->type == TYPE_TAMA_60HZ)
210*22de25f8SKonrad Dybcio 		mode = drm_mode_duplicate(connector->dev, &sony_td4353_jdi_mode_tama_60hz);
211*22de25f8SKonrad Dybcio 	else
212*22de25f8SKonrad Dybcio 		return -EINVAL;
213*22de25f8SKonrad Dybcio 
214*22de25f8SKonrad Dybcio 	if (!mode)
215*22de25f8SKonrad Dybcio 		return -ENOMEM;
216*22de25f8SKonrad Dybcio 
217*22de25f8SKonrad Dybcio 	drm_mode_set_name(mode);
218*22de25f8SKonrad Dybcio 
219*22de25f8SKonrad Dybcio 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
220*22de25f8SKonrad Dybcio 	connector->display_info.width_mm = mode->width_mm;
221*22de25f8SKonrad Dybcio 	connector->display_info.height_mm = mode->height_mm;
222*22de25f8SKonrad Dybcio 	drm_mode_probed_add(connector, mode);
223*22de25f8SKonrad Dybcio 
224*22de25f8SKonrad Dybcio 	return 1;
225*22de25f8SKonrad Dybcio }
226*22de25f8SKonrad Dybcio 
227*22de25f8SKonrad Dybcio static const struct drm_panel_funcs sony_td4353_jdi_panel_funcs = {
228*22de25f8SKonrad Dybcio 	.prepare = sony_td4353_jdi_prepare,
229*22de25f8SKonrad Dybcio 	.unprepare = sony_td4353_jdi_unprepare,
230*22de25f8SKonrad Dybcio 	.get_modes = sony_td4353_jdi_get_modes,
231*22de25f8SKonrad Dybcio };
232*22de25f8SKonrad Dybcio 
sony_td4353_jdi_probe(struct mipi_dsi_device * dsi)233*22de25f8SKonrad Dybcio static int sony_td4353_jdi_probe(struct mipi_dsi_device *dsi)
234*22de25f8SKonrad Dybcio {
235*22de25f8SKonrad Dybcio 	struct device *dev = &dsi->dev;
236*22de25f8SKonrad Dybcio 	struct sony_td4353_jdi *ctx;
237*22de25f8SKonrad Dybcio 	int ret;
238*22de25f8SKonrad Dybcio 
239*22de25f8SKonrad Dybcio 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
240*22de25f8SKonrad Dybcio 	if (!ctx)
241*22de25f8SKonrad Dybcio 		return -ENOMEM;
242*22de25f8SKonrad Dybcio 
243*22de25f8SKonrad Dybcio 	ctx->type = (uintptr_t)of_device_get_match_data(dev);
244*22de25f8SKonrad Dybcio 
245*22de25f8SKonrad Dybcio 	ctx->supplies[0].supply = "vddio";
246*22de25f8SKonrad Dybcio 	ctx->supplies[1].supply = "vsp";
247*22de25f8SKonrad Dybcio 	ctx->supplies[2].supply = "vsn";
248*22de25f8SKonrad Dybcio 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
249*22de25f8SKonrad Dybcio 				      ctx->supplies);
250*22de25f8SKonrad Dybcio 	if (ret < 0)
251*22de25f8SKonrad Dybcio 		return dev_err_probe(dev, ret, "Failed to get regulators\n");
252*22de25f8SKonrad Dybcio 
253*22de25f8SKonrad Dybcio 	ctx->panel_reset_gpio = devm_gpiod_get(dev, "panel-reset", GPIOD_ASIS);
254*22de25f8SKonrad Dybcio 	if (IS_ERR(ctx->panel_reset_gpio))
255*22de25f8SKonrad Dybcio 		return dev_err_probe(dev, PTR_ERR(ctx->panel_reset_gpio),
256*22de25f8SKonrad Dybcio 				     "Failed to get panel-reset-gpios\n");
257*22de25f8SKonrad Dybcio 
258*22de25f8SKonrad Dybcio 	ctx->touch_reset_gpio = devm_gpiod_get(dev, "touch-reset", GPIOD_ASIS);
259*22de25f8SKonrad Dybcio 	if (IS_ERR(ctx->touch_reset_gpio))
260*22de25f8SKonrad Dybcio 		return dev_err_probe(dev, PTR_ERR(ctx->touch_reset_gpio),
261*22de25f8SKonrad Dybcio 				     "Failed to get touch-reset-gpios\n");
262*22de25f8SKonrad Dybcio 
263*22de25f8SKonrad Dybcio 	ctx->dsi = dsi;
264*22de25f8SKonrad Dybcio 	mipi_dsi_set_drvdata(dsi, ctx);
265*22de25f8SKonrad Dybcio 
266*22de25f8SKonrad Dybcio 	dsi->lanes = 4;
267*22de25f8SKonrad Dybcio 	dsi->format = MIPI_DSI_FMT_RGB888;
268*22de25f8SKonrad Dybcio 	dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS;
269*22de25f8SKonrad Dybcio 
270*22de25f8SKonrad Dybcio 	drm_panel_init(&ctx->panel, dev, &sony_td4353_jdi_panel_funcs,
271*22de25f8SKonrad Dybcio 		       DRM_MODE_CONNECTOR_DSI);
272*22de25f8SKonrad Dybcio 
273*22de25f8SKonrad Dybcio 	ret = drm_panel_of_backlight(&ctx->panel);
274*22de25f8SKonrad Dybcio 	if (ret)
275*22de25f8SKonrad Dybcio 		return dev_err_probe(dev, ret, "Failed to get backlight\n");
276*22de25f8SKonrad Dybcio 
277*22de25f8SKonrad Dybcio 	drm_panel_add(&ctx->panel);
278*22de25f8SKonrad Dybcio 
279*22de25f8SKonrad Dybcio 	ret = mipi_dsi_attach(dsi);
280*22de25f8SKonrad Dybcio 	if (ret < 0) {
281*22de25f8SKonrad Dybcio 		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
282*22de25f8SKonrad Dybcio 		drm_panel_remove(&ctx->panel);
283*22de25f8SKonrad Dybcio 		return ret;
284*22de25f8SKonrad Dybcio 	}
285*22de25f8SKonrad Dybcio 
286*22de25f8SKonrad Dybcio 	return 0;
287*22de25f8SKonrad Dybcio }
288*22de25f8SKonrad Dybcio 
sony_td4353_jdi_remove(struct mipi_dsi_device * dsi)289*22de25f8SKonrad Dybcio static void sony_td4353_jdi_remove(struct mipi_dsi_device *dsi)
290*22de25f8SKonrad Dybcio {
291*22de25f8SKonrad Dybcio 	struct sony_td4353_jdi *ctx = mipi_dsi_get_drvdata(dsi);
292*22de25f8SKonrad Dybcio 	int ret;
293*22de25f8SKonrad Dybcio 
294*22de25f8SKonrad Dybcio 	ret = mipi_dsi_detach(dsi);
295*22de25f8SKonrad Dybcio 	if (ret < 0)
296*22de25f8SKonrad Dybcio 		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
297*22de25f8SKonrad Dybcio 
298*22de25f8SKonrad Dybcio 	drm_panel_remove(&ctx->panel);
299*22de25f8SKonrad Dybcio }
300*22de25f8SKonrad Dybcio 
301*22de25f8SKonrad Dybcio static const struct of_device_id sony_td4353_jdi_of_match[] = {
302*22de25f8SKonrad Dybcio 	{ .compatible = "sony,td4353-jdi-tama", .data = (void *)TYPE_TAMA_60HZ },
303*22de25f8SKonrad Dybcio 	{ /* sentinel */ }
304*22de25f8SKonrad Dybcio };
305*22de25f8SKonrad Dybcio MODULE_DEVICE_TABLE(of, sony_td4353_jdi_of_match);
306*22de25f8SKonrad Dybcio 
307*22de25f8SKonrad Dybcio static struct mipi_dsi_driver sony_td4353_jdi_driver = {
308*22de25f8SKonrad Dybcio 	.probe = sony_td4353_jdi_probe,
309*22de25f8SKonrad Dybcio 	.remove = sony_td4353_jdi_remove,
310*22de25f8SKonrad Dybcio 	.driver = {
311*22de25f8SKonrad Dybcio 		.name = "panel-sony-td4353-jdi",
312*22de25f8SKonrad Dybcio 		.of_match_table = sony_td4353_jdi_of_match,
313*22de25f8SKonrad Dybcio 	},
314*22de25f8SKonrad Dybcio };
315*22de25f8SKonrad Dybcio module_mipi_dsi_driver(sony_td4353_jdi_driver);
316*22de25f8SKonrad Dybcio 
317*22de25f8SKonrad Dybcio MODULE_AUTHOR("Konrad Dybcio <konrad.dybcio@somainline.org>");
318*22de25f8SKonrad Dybcio MODULE_DESCRIPTION("DRM panel driver for SONY Xperia XZ2/XZ2c JDI panel");
319*22de25f8SKonrad Dybcio MODULE_LICENSE("GPL");
320