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