1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2016 InforceComputing
4  * Copyright (C) 2016 Linaro Ltd
5  * Copyright (C) 2023 BayLibre, SAS
6  *
7  * Authors:
8  * - Vinay Simha BN <simhavcs@gmail.com>
9  * - Sumit Semwal <sumit.semwal@linaro.org>
10  * - Guillaume La Roque <glaroque@baylibre.com>
11  *
12  */
13 
14 #include <linux/backlight.h>
15 #include <linux/delay.h>
16 #include <linux/gpio/consumer.h>
17 #include <linux/module.h>
18 #include <linux/of.h>
19 #include <linux/regulator/consumer.h>
20 
21 #include <video/mipi_display.h>
22 
23 #include <drm/drm_mipi_dsi.h>
24 #include <drm/drm_modes.h>
25 #include <drm/drm_panel.h>
26 
27 #define DSI_REG_MCAP	0xB0
28 #define DSI_REG_IS	0xB3 /* Interface Setting */
29 #define DSI_REG_IIS	0xB4 /* Interface ID Setting */
30 #define DSI_REG_CTRL	0xB6
31 
32 enum {
33 	IOVCC = 0,
34 	POWER = 1
35 };
36 
37 struct stk_panel {
38 	bool prepared;
39 	const struct drm_display_mode *mode;
40 	struct backlight_device *backlight;
41 	struct drm_panel base;
42 	struct gpio_desc *enable_gpio; /* Power IC supply enable */
43 	struct gpio_desc *reset_gpio; /* External reset */
44 	struct mipi_dsi_device *dsi;
45 	struct regulator_bulk_data supplies[2];
46 };
47 
to_stk_panel(struct drm_panel * panel)48 static inline struct stk_panel *to_stk_panel(struct drm_panel *panel)
49 {
50 	return container_of(panel, struct stk_panel, base);
51 }
52 
stk_panel_init(struct stk_panel * stk)53 static int stk_panel_init(struct stk_panel *stk)
54 {
55 	struct mipi_dsi_device *dsi = stk->dsi;
56 	struct device *dev = &stk->dsi->dev;
57 	int ret;
58 
59 	ret = mipi_dsi_dcs_soft_reset(dsi);
60 	if (ret < 0) {
61 		dev_err(dev, "failed to mipi_dsi_dcs_soft_reset: %d\n", ret);
62 		return ret;
63 	}
64 	mdelay(5);
65 
66 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
67 	if (ret < 0) {
68 		dev_err(dev, "failed to set exit sleep mode: %d\n", ret);
69 		return ret;
70 	}
71 	msleep(120);
72 
73 	mipi_dsi_generic_write_seq(dsi, DSI_REG_MCAP, 0x04);
74 
75 	/* Interface setting, video mode */
76 	mipi_dsi_generic_write_seq(dsi, DSI_REG_IS, 0x14, 0x08, 0x00, 0x22, 0x00);
77 	mipi_dsi_generic_write_seq(dsi, DSI_REG_IIS, 0x0C, 0x00);
78 	mipi_dsi_generic_write_seq(dsi, DSI_REG_CTRL, 0x3A, 0xD3);
79 
80 	ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x77);
81 	if (ret < 0) {
82 		dev_err(dev, "failed to write display brightness: %d\n", ret);
83 		return ret;
84 	}
85 
86 	mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
87 			       MIPI_DCS_WRITE_MEMORY_START);
88 
89 	ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x77);
90 	if (ret < 0) {
91 		dev_err(dev, "failed to set pixel format: %d\n", ret);
92 		return ret;
93 	}
94 
95 	ret = mipi_dsi_dcs_set_column_address(dsi, 0, stk->mode->hdisplay - 1);
96 	if (ret < 0) {
97 		dev_err(dev, "failed to set column address: %d\n", ret);
98 		return ret;
99 	}
100 
101 	ret = mipi_dsi_dcs_set_page_address(dsi, 0, stk->mode->vdisplay - 1);
102 	if (ret < 0) {
103 		dev_err(dev, "failed to set page address: %d\n", ret);
104 		return ret;
105 	}
106 
107 	return 0;
108 }
109 
stk_panel_on(struct stk_panel * stk)110 static int stk_panel_on(struct stk_panel *stk)
111 {
112 	struct mipi_dsi_device *dsi = stk->dsi;
113 	struct device *dev = &stk->dsi->dev;
114 	int ret;
115 
116 	ret = mipi_dsi_dcs_set_display_on(dsi);
117 	if (ret < 0)
118 		dev_err(dev, "failed to set display on: %d\n", ret);
119 
120 	mdelay(20);
121 
122 	return ret;
123 }
124 
stk_panel_off(struct stk_panel * stk)125 static void stk_panel_off(struct stk_panel *stk)
126 {
127 	struct mipi_dsi_device *dsi = stk->dsi;
128 	struct device *dev = &stk->dsi->dev;
129 	int ret;
130 
131 	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
132 
133 	ret = mipi_dsi_dcs_set_display_off(dsi);
134 	if (ret < 0)
135 		dev_err(dev, "failed to set display off: %d\n", ret);
136 
137 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
138 	if (ret < 0)
139 		dev_err(dev, "failed to enter sleep mode: %d\n", ret);
140 
141 	msleep(100);
142 }
143 
stk_panel_unprepare(struct drm_panel * panel)144 static int stk_panel_unprepare(struct drm_panel *panel)
145 {
146 	struct stk_panel *stk = to_stk_panel(panel);
147 
148 	if (!stk->prepared)
149 		return 0;
150 
151 	stk_panel_off(stk);
152 	regulator_bulk_disable(ARRAY_SIZE(stk->supplies), stk->supplies);
153 	gpiod_set_value(stk->reset_gpio, 0);
154 	gpiod_set_value(stk->enable_gpio, 1);
155 
156 	stk->prepared = false;
157 
158 	return 0;
159 }
160 
stk_panel_prepare(struct drm_panel * panel)161 static int stk_panel_prepare(struct drm_panel *panel)
162 {
163 	struct stk_panel *stk = to_stk_panel(panel);
164 	struct device *dev = &stk->dsi->dev;
165 	int ret;
166 
167 	if (stk->prepared)
168 		return 0;
169 
170 	gpiod_set_value(stk->reset_gpio, 0);
171 	gpiod_set_value(stk->enable_gpio, 0);
172 	ret = regulator_enable(stk->supplies[IOVCC].consumer);
173 	if (ret < 0)
174 		return ret;
175 
176 	mdelay(8);
177 	ret = regulator_enable(stk->supplies[POWER].consumer);
178 	if (ret < 0)
179 		goto iovccoff;
180 
181 	mdelay(20);
182 	gpiod_set_value(stk->enable_gpio, 1);
183 	mdelay(20);
184 	gpiod_set_value(stk->reset_gpio, 1);
185 	mdelay(10);
186 	ret = stk_panel_init(stk);
187 	if (ret < 0) {
188 		dev_err(dev, "failed to init panel: %d\n", ret);
189 		goto poweroff;
190 	}
191 
192 	ret = stk_panel_on(stk);
193 	if (ret < 0) {
194 		dev_err(dev, "failed to set panel on: %d\n", ret);
195 		goto poweroff;
196 	}
197 
198 	stk->prepared = true;
199 
200 	return 0;
201 
202 poweroff:
203 	regulator_disable(stk->supplies[POWER].consumer);
204 iovccoff:
205 	regulator_disable(stk->supplies[IOVCC].consumer);
206 	gpiod_set_value(stk->reset_gpio, 0);
207 	gpiod_set_value(stk->enable_gpio, 0);
208 
209 	return ret;
210 }
211 
212 static const struct drm_display_mode default_mode = {
213 		.clock = 163204,
214 		.hdisplay = 1200,
215 		.hsync_start = 1200 + 144,
216 		.hsync_end = 1200 + 144 + 16,
217 		.htotal = 1200 + 144 + 16 + 45,
218 		.vdisplay = 1920,
219 		.vsync_start = 1920 + 8,
220 		.vsync_end = 1920 + 8 + 4,
221 		.vtotal = 1920 + 8 + 4 + 4,
222 		.width_mm = 95,
223 		.height_mm = 151,
224 };
225 
stk_panel_get_modes(struct drm_panel * panel,struct drm_connector * connector)226 static int stk_panel_get_modes(struct drm_panel *panel,
227 			       struct drm_connector *connector)
228 {
229 	struct drm_display_mode *mode;
230 
231 	mode = drm_mode_duplicate(connector->dev, &default_mode);
232 	if (!mode) {
233 		dev_err(panel->dev, "failed to add mode %ux%ux@%u\n",
234 			default_mode.hdisplay, default_mode.vdisplay,
235 			drm_mode_vrefresh(&default_mode));
236 		return -ENOMEM;
237 	}
238 
239 	drm_mode_set_name(mode);
240 	drm_mode_probed_add(connector, mode);
241 	connector->display_info.width_mm = default_mode.width_mm;
242 	connector->display_info.height_mm = default_mode.height_mm;
243 	return 1;
244 }
245 
dsi_dcs_bl_get_brightness(struct backlight_device * bl)246 static int dsi_dcs_bl_get_brightness(struct backlight_device *bl)
247 {
248 	struct mipi_dsi_device *dsi = bl_get_data(bl);
249 	int ret;
250 	u16 brightness;
251 
252 	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
253 	ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
254 	if (ret < 0)
255 		return ret;
256 
257 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
258 	return brightness & 0xff;
259 }
260 
dsi_dcs_bl_update_status(struct backlight_device * bl)261 static int dsi_dcs_bl_update_status(struct backlight_device *bl)
262 {
263 	struct mipi_dsi_device *dsi = bl_get_data(bl);
264 	struct device *dev = &dsi->dev;
265 	int ret;
266 
267 	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
268 	ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
269 	if (ret < 0) {
270 		dev_err(dev, "failed to set DSI control: %d\n", ret);
271 		return ret;
272 	}
273 
274 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
275 	return 0;
276 }
277 
278 static const struct backlight_ops dsi_bl_ops = {
279 	.update_status = dsi_dcs_bl_update_status,
280 	.get_brightness = dsi_dcs_bl_get_brightness,
281 };
282 
283 static struct backlight_device *
drm_panel_create_dsi_backlight(struct mipi_dsi_device * dsi)284 drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi)
285 {
286 	struct device *dev = &dsi->dev;
287 	struct backlight_properties props = {
288 		.type = BACKLIGHT_RAW,
289 		.brightness = 255,
290 		.max_brightness = 255,
291 	};
292 
293 	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
294 					      &dsi_bl_ops, &props);
295 }
296 
297 static const struct drm_panel_funcs stk_panel_funcs = {
298 	.unprepare = stk_panel_unprepare,
299 	.prepare = stk_panel_prepare,
300 	.get_modes = stk_panel_get_modes,
301 };
302 
303 static const struct of_device_id stk_of_match[] = {
304 	{ .compatible = "startek,kd070fhfid015", },
305 	{ }
306 };
307 MODULE_DEVICE_TABLE(of, stk_of_match);
308 
stk_panel_add(struct stk_panel * stk)309 static int stk_panel_add(struct stk_panel *stk)
310 {
311 	struct device *dev = &stk->dsi->dev;
312 	int ret;
313 
314 	stk->mode = &default_mode;
315 
316 	stk->supplies[IOVCC].supply = "iovcc";
317 	stk->supplies[POWER].supply = "power";
318 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(stk->supplies), stk->supplies);
319 	if (ret) {
320 		dev_err(dev, "regulator_bulk failed\n");
321 		return ret;
322 	}
323 
324 	stk->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
325 	if (IS_ERR(stk->reset_gpio)) {
326 		ret = PTR_ERR(stk->reset_gpio);
327 		dev_err(dev, "cannot get reset-gpios %d\n", ret);
328 		return ret;
329 	}
330 
331 	stk->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
332 	if (IS_ERR(stk->enable_gpio)) {
333 		ret = PTR_ERR(stk->enable_gpio);
334 		dev_err(dev, "cannot get enable-gpio %d\n", ret);
335 		return ret;
336 	}
337 
338 	stk->backlight = drm_panel_create_dsi_backlight(stk->dsi);
339 	if (IS_ERR(stk->backlight)) {
340 		ret = PTR_ERR(stk->backlight);
341 		dev_err(dev, "failed to register backlight %d\n", ret);
342 		return ret;
343 	}
344 
345 	drm_panel_init(&stk->base, &stk->dsi->dev, &stk_panel_funcs,
346 		       DRM_MODE_CONNECTOR_DSI);
347 
348 	drm_panel_add(&stk->base);
349 
350 	return 0;
351 }
352 
stk_panel_probe(struct mipi_dsi_device * dsi)353 static int stk_panel_probe(struct mipi_dsi_device *dsi)
354 {
355 	struct stk_panel *stk;
356 	int ret;
357 
358 	dsi->lanes = 4;
359 	dsi->format = MIPI_DSI_FMT_RGB888;
360 	dsi->mode_flags = (MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM);
361 
362 	stk = devm_kzalloc(&dsi->dev, sizeof(*stk), GFP_KERNEL);
363 	if (!stk)
364 		return -ENOMEM;
365 
366 	mipi_dsi_set_drvdata(dsi, stk);
367 
368 	stk->dsi = dsi;
369 
370 	ret = stk_panel_add(stk);
371 	if (ret < 0)
372 		return ret;
373 
374 	ret = mipi_dsi_attach(dsi);
375 	if (ret < 0)
376 		drm_panel_remove(&stk->base);
377 
378 	return 0;
379 }
380 
stk_panel_remove(struct mipi_dsi_device * dsi)381 static void stk_panel_remove(struct mipi_dsi_device *dsi)
382 {
383 	struct stk_panel *stk = mipi_dsi_get_drvdata(dsi);
384 	int err;
385 
386 	err = mipi_dsi_detach(dsi);
387 	if (err < 0)
388 		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
389 			err);
390 
391 	drm_panel_remove(&stk->base);
392 }
393 
394 static struct mipi_dsi_driver stk_panel_driver = {
395 	.driver = {
396 		.name = "panel-startek-kd070fhfid015",
397 		.of_match_table = stk_of_match,
398 	},
399 	.probe = stk_panel_probe,
400 	.remove = stk_panel_remove,
401 };
402 module_mipi_dsi_driver(stk_panel_driver);
403 
404 MODULE_AUTHOR("Guillaume La Roque <glaroque@baylibre.com>");
405 MODULE_DESCRIPTION("STARTEK KD070FHFID015");
406 MODULE_LICENSE("GPL");
407