1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2015 Red Hat
4  * Copyright (C) 2015 Sony Mobile Communications Inc.
5  * Author: Werner Johansson <werner.johansson@sonymobile.com>
6  *
7  * Based on AUO panel driver by Rob Clark <robdclark@gmail.com>
8  */
9 
10 #include <linux/backlight.h>
11 #include <linux/delay.h>
12 #include <linux/gpio/consumer.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/regulator/consumer.h>
16 
17 #include <video/mipi_display.h>
18 
19 #include <drm/drm_crtc.h>
20 #include <drm/drm_device.h>
21 #include <drm/drm_mipi_dsi.h>
22 #include <drm/drm_panel.h>
23 
24 struct sharp_nt_panel {
25 	struct drm_panel base;
26 	struct mipi_dsi_device *dsi;
27 
28 	struct backlight_device *backlight;
29 	struct regulator *supply;
30 	struct gpio_desc *reset_gpio;
31 
32 	bool prepared;
33 	bool enabled;
34 
35 	const struct drm_display_mode *mode;
36 };
37 
38 static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel)
39 {
40 	return container_of(panel, struct sharp_nt_panel, base);
41 }
42 
43 static int sharp_nt_panel_init(struct sharp_nt_panel *sharp_nt)
44 {
45 	struct mipi_dsi_device *dsi = sharp_nt->dsi;
46 	int ret;
47 
48 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
49 
50 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
51 	if (ret < 0)
52 		return ret;
53 
54 	msleep(120);
55 
56 	/* Novatek two-lane operation */
57 	ret = mipi_dsi_dcs_write(dsi, 0xae, (u8[]){ 0x03 }, 1);
58 	if (ret < 0)
59 		return ret;
60 
61 	/* Set both MCU and RGB I/F to 24bpp */
62 	ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT |
63 					(MIPI_DCS_PIXEL_FMT_24BIT << 4));
64 	if (ret < 0)
65 		return ret;
66 
67 	return 0;
68 }
69 
70 static int sharp_nt_panel_on(struct sharp_nt_panel *sharp_nt)
71 {
72 	struct mipi_dsi_device *dsi = sharp_nt->dsi;
73 	int ret;
74 
75 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
76 
77 	ret = mipi_dsi_dcs_set_display_on(dsi);
78 	if (ret < 0)
79 		return ret;
80 
81 	return 0;
82 }
83 
84 static int sharp_nt_panel_off(struct sharp_nt_panel *sharp_nt)
85 {
86 	struct mipi_dsi_device *dsi = sharp_nt->dsi;
87 	int ret;
88 
89 	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
90 
91 	ret = mipi_dsi_dcs_set_display_off(dsi);
92 	if (ret < 0)
93 		return ret;
94 
95 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
96 	if (ret < 0)
97 		return ret;
98 
99 	return 0;
100 }
101 
102 
103 static int sharp_nt_panel_disable(struct drm_panel *panel)
104 {
105 	struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
106 
107 	if (!sharp_nt->enabled)
108 		return 0;
109 
110 	backlight_disable(sharp_nt->backlight);
111 
112 	sharp_nt->enabled = false;
113 
114 	return 0;
115 }
116 
117 static int sharp_nt_panel_unprepare(struct drm_panel *panel)
118 {
119 	struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
120 	int ret;
121 
122 	if (!sharp_nt->prepared)
123 		return 0;
124 
125 	ret = sharp_nt_panel_off(sharp_nt);
126 	if (ret < 0) {
127 		dev_err(panel->dev, "failed to set panel off: %d\n", ret);
128 		return ret;
129 	}
130 
131 	regulator_disable(sharp_nt->supply);
132 	if (sharp_nt->reset_gpio)
133 		gpiod_set_value(sharp_nt->reset_gpio, 0);
134 
135 	sharp_nt->prepared = false;
136 
137 	return 0;
138 }
139 
140 static int sharp_nt_panel_prepare(struct drm_panel *panel)
141 {
142 	struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
143 	int ret;
144 
145 	if (sharp_nt->prepared)
146 		return 0;
147 
148 	ret = regulator_enable(sharp_nt->supply);
149 	if (ret < 0)
150 		return ret;
151 
152 	msleep(20);
153 
154 	if (sharp_nt->reset_gpio) {
155 		gpiod_set_value(sharp_nt->reset_gpio, 1);
156 		msleep(1);
157 		gpiod_set_value(sharp_nt->reset_gpio, 0);
158 		msleep(1);
159 		gpiod_set_value(sharp_nt->reset_gpio, 1);
160 		msleep(10);
161 	}
162 
163 	ret = sharp_nt_panel_init(sharp_nt);
164 	if (ret < 0) {
165 		dev_err(panel->dev, "failed to init panel: %d\n", ret);
166 		goto poweroff;
167 	}
168 
169 	ret = sharp_nt_panel_on(sharp_nt);
170 	if (ret < 0) {
171 		dev_err(panel->dev, "failed to set panel on: %d\n", ret);
172 		goto poweroff;
173 	}
174 
175 	sharp_nt->prepared = true;
176 
177 	return 0;
178 
179 poweroff:
180 	regulator_disable(sharp_nt->supply);
181 	if (sharp_nt->reset_gpio)
182 		gpiod_set_value(sharp_nt->reset_gpio, 0);
183 	return ret;
184 }
185 
186 static int sharp_nt_panel_enable(struct drm_panel *panel)
187 {
188 	struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
189 
190 	if (sharp_nt->enabled)
191 		return 0;
192 
193 	backlight_enable(sharp_nt->backlight);
194 
195 	sharp_nt->enabled = true;
196 
197 	return 0;
198 }
199 
200 static const struct drm_display_mode default_mode = {
201 	.clock = 41118,
202 	.hdisplay = 540,
203 	.hsync_start = 540 + 48,
204 	.hsync_end = 540 + 48 + 80,
205 	.htotal = 540 + 48 + 80 + 32,
206 	.vdisplay = 960,
207 	.vsync_start = 960 + 3,
208 	.vsync_end = 960 + 3 + 15,
209 	.vtotal = 960 + 3 + 15 + 1,
210 	.vrefresh = 60,
211 };
212 
213 static int sharp_nt_panel_get_modes(struct drm_panel *panel)
214 {
215 	struct drm_display_mode *mode;
216 
217 	mode = drm_mode_duplicate(panel->drm, &default_mode);
218 	if (!mode) {
219 		dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
220 				default_mode.hdisplay, default_mode.vdisplay,
221 				default_mode.vrefresh);
222 		return -ENOMEM;
223 	}
224 
225 	drm_mode_set_name(mode);
226 
227 	drm_mode_probed_add(panel->connector, mode);
228 
229 	panel->connector->display_info.width_mm = 54;
230 	panel->connector->display_info.height_mm = 95;
231 
232 	return 1;
233 }
234 
235 static const struct drm_panel_funcs sharp_nt_panel_funcs = {
236 	.disable = sharp_nt_panel_disable,
237 	.unprepare = sharp_nt_panel_unprepare,
238 	.prepare = sharp_nt_panel_prepare,
239 	.enable = sharp_nt_panel_enable,
240 	.get_modes = sharp_nt_panel_get_modes,
241 };
242 
243 static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
244 {
245 	struct device *dev = &sharp_nt->dsi->dev;
246 
247 	sharp_nt->mode = &default_mode;
248 
249 	sharp_nt->supply = devm_regulator_get(dev, "avdd");
250 	if (IS_ERR(sharp_nt->supply))
251 		return PTR_ERR(sharp_nt->supply);
252 
253 	sharp_nt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
254 	if (IS_ERR(sharp_nt->reset_gpio)) {
255 		dev_err(dev, "cannot get reset-gpios %ld\n",
256 			PTR_ERR(sharp_nt->reset_gpio));
257 		sharp_nt->reset_gpio = NULL;
258 	} else {
259 		gpiod_set_value(sharp_nt->reset_gpio, 0);
260 	}
261 
262 	sharp_nt->backlight = devm_of_find_backlight(dev);
263 
264 	if (IS_ERR(sharp_nt->backlight))
265 		return PTR_ERR(sharp_nt->backlight);
266 
267 	drm_panel_init(&sharp_nt->base);
268 	sharp_nt->base.funcs = &sharp_nt_panel_funcs;
269 	sharp_nt->base.dev = &sharp_nt->dsi->dev;
270 
271 	return drm_panel_add(&sharp_nt->base);
272 }
273 
274 static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt)
275 {
276 	if (sharp_nt->base.dev)
277 		drm_panel_remove(&sharp_nt->base);
278 }
279 
280 static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
281 {
282 	struct sharp_nt_panel *sharp_nt;
283 	int ret;
284 
285 	dsi->lanes = 2;
286 	dsi->format = MIPI_DSI_FMT_RGB888;
287 	dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
288 			MIPI_DSI_MODE_VIDEO_HSE |
289 			MIPI_DSI_CLOCK_NON_CONTINUOUS |
290 			MIPI_DSI_MODE_EOT_PACKET;
291 
292 	sharp_nt = devm_kzalloc(&dsi->dev, sizeof(*sharp_nt), GFP_KERNEL);
293 	if (!sharp_nt)
294 		return -ENOMEM;
295 
296 	mipi_dsi_set_drvdata(dsi, sharp_nt);
297 
298 	sharp_nt->dsi = dsi;
299 
300 	ret = sharp_nt_panel_add(sharp_nt);
301 	if (ret < 0)
302 		return ret;
303 
304 	return mipi_dsi_attach(dsi);
305 }
306 
307 static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
308 {
309 	struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
310 	int ret;
311 
312 	ret = sharp_nt_panel_disable(&sharp_nt->base);
313 	if (ret < 0)
314 		dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
315 
316 	ret = mipi_dsi_detach(dsi);
317 	if (ret < 0)
318 		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
319 
320 	sharp_nt_panel_del(sharp_nt);
321 
322 	return 0;
323 }
324 
325 static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi)
326 {
327 	struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
328 
329 	sharp_nt_panel_disable(&sharp_nt->base);
330 }
331 
332 static const struct of_device_id sharp_nt_of_match[] = {
333 	{ .compatible = "sharp,ls043t1le01-qhd", },
334 	{ }
335 };
336 MODULE_DEVICE_TABLE(of, sharp_nt_of_match);
337 
338 static struct mipi_dsi_driver sharp_nt_panel_driver = {
339 	.driver = {
340 		.name = "panel-sharp-ls043t1le01-qhd",
341 		.of_match_table = sharp_nt_of_match,
342 	},
343 	.probe = sharp_nt_panel_probe,
344 	.remove = sharp_nt_panel_remove,
345 	.shutdown = sharp_nt_panel_shutdown,
346 };
347 module_mipi_dsi_driver(sharp_nt_panel_driver);
348 
349 MODULE_AUTHOR("Werner Johansson <werner.johansson@sonymobile.com>");
350 MODULE_DESCRIPTION("Sharp LS043T1LE01 NT35565-based qHD (540x960) video mode panel driver");
351 MODULE_LICENSE("GPL v2");
352