• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* linux/drivers/video/exynos/exynos_mipi_dsi.c
2  *
3  * Samsung SoC MIPI-DSIM driver.
4  *
5  * Copyright (c) 2012 Samsung Electronics Co., Ltd
6  *
7  * InKi Dae, <inki.dae@samsung.com>
8  * Donghwa Lee, <dh09.lee@samsung.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13 */
14 
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/errno.h>
18 #include <linux/clk.h>
19 #include <linux/mutex.h>
20 #include <linux/wait.h>
21 #include <linux/fs.h>
22 #include <linux/mm.h>
23 #include <linux/fb.h>
24 #include <linux/ctype.h>
25 #include <linux/platform_device.h>
26 #include <linux/io.h>
27 #include <linux/irq.h>
28 #include <linux/memory.h>
29 #include <linux/delay.h>
30 #include <linux/interrupt.h>
31 #include <linux/kthread.h>
32 #include <linux/notifier.h>
33 #include <linux/regulator/consumer.h>
34 #include <linux/pm_runtime.h>
35 #include <linux/err.h>
36 
37 #include <video/exynos_mipi_dsim.h>
38 
39 #include "exynos_mipi_dsi_common.h"
40 #include "exynos_mipi_dsi_lowlevel.h"
41 
42 struct mipi_dsim_ddi {
43 	int				bus_id;
44 	struct list_head		list;
45 	struct mipi_dsim_lcd_device	*dsim_lcd_dev;
46 	struct mipi_dsim_lcd_driver	*dsim_lcd_drv;
47 };
48 
49 static LIST_HEAD(dsim_ddi_list);
50 
51 static DEFINE_MUTEX(mipi_dsim_lock);
52 
to_dsim_plat(struct platform_device * pdev)53 static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
54 							*pdev)
55 {
56 	return pdev->dev.platform_data;
57 }
58 
59 static struct regulator_bulk_data supplies[] = {
60 	{ .supply = "vdd11", },
61 	{ .supply = "vdd18", },
62 };
63 
exynos_mipi_regulator_enable(struct mipi_dsim_device * dsim)64 static int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim)
65 {
66 	int ret;
67 
68 	mutex_lock(&dsim->lock);
69 	ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
70 	mutex_unlock(&dsim->lock);
71 
72 	return ret;
73 }
74 
exynos_mipi_regulator_disable(struct mipi_dsim_device * dsim)75 static int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim)
76 {
77 	int ret;
78 
79 	mutex_lock(&dsim->lock);
80 	ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
81 	mutex_unlock(&dsim->lock);
82 
83 	return ret;
84 }
85 
86 /* update all register settings to MIPI DSI controller. */
exynos_mipi_update_cfg(struct mipi_dsim_device * dsim)87 static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
88 {
89 	/*
90 	 * data from Display controller(FIMD) is not transferred in video mode
91 	 * but in case of command mode, all settings is not updated to
92 	 * registers.
93 	 */
94 	exynos_mipi_dsi_stand_by(dsim, 0);
95 
96 	exynos_mipi_dsi_init_dsim(dsim);
97 	exynos_mipi_dsi_init_link(dsim);
98 
99 	exynos_mipi_dsi_set_hs_enable(dsim);
100 
101 	/* set display timing. */
102 	exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
103 
104 	exynos_mipi_dsi_init_interrupt(dsim);
105 
106 	/*
107 	 * data from Display controller(FIMD) is transferred in video mode
108 	 * but in case of command mode, all settings are updated to registers.
109 	 */
110 	exynos_mipi_dsi_stand_by(dsim, 1);
111 }
112 
exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device * dsim,int power)113 static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim,
114 		int power)
115 {
116 	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
117 	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
118 
119 	switch (power) {
120 	case FB_BLANK_POWERDOWN:
121 		if (dsim->suspended)
122 			return 0;
123 
124 		if (client_drv && client_drv->suspend)
125 			client_drv->suspend(client_dev);
126 
127 		clk_disable(dsim->clock);
128 
129 		exynos_mipi_regulator_disable(dsim);
130 
131 		dsim->suspended = true;
132 
133 		break;
134 	default:
135 		break;
136 	}
137 
138 	return 0;
139 }
140 
exynos_mipi_dsi_blank_mode(struct mipi_dsim_device * dsim,int power)141 static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
142 {
143 	struct platform_device *pdev = to_platform_device(dsim->dev);
144 	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
145 	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
146 
147 	switch (power) {
148 	case FB_BLANK_UNBLANK:
149 		if (!dsim->suspended)
150 			return 0;
151 
152 		/* lcd panel power on. */
153 		if (client_drv && client_drv->power_on)
154 			client_drv->power_on(client_dev, 1);
155 
156 		exynos_mipi_regulator_enable(dsim);
157 
158 		/* enable MIPI-DSI PHY. */
159 		if (dsim->pd->phy_enable)
160 			dsim->pd->phy_enable(pdev, true);
161 
162 		clk_enable(dsim->clock);
163 
164 		exynos_mipi_update_cfg(dsim);
165 
166 		/* set lcd panel sequence commands. */
167 		if (client_drv && client_drv->set_sequence)
168 			client_drv->set_sequence(client_dev);
169 
170 		dsim->suspended = false;
171 
172 		break;
173 	case FB_BLANK_NORMAL:
174 		/* TODO. */
175 		break;
176 	default:
177 		break;
178 	}
179 
180 	return 0;
181 }
182 
exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device * lcd_dev)183 int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
184 {
185 	struct mipi_dsim_ddi *dsim_ddi;
186 
187 	if (!lcd_dev->name) {
188 		pr_err("dsim_lcd_device name is NULL.\n");
189 		return -EFAULT;
190 	}
191 
192 	dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
193 	if (!dsim_ddi) {
194 		pr_err("failed to allocate dsim_ddi object.\n");
195 		return -ENOMEM;
196 	}
197 
198 	dsim_ddi->dsim_lcd_dev = lcd_dev;
199 
200 	mutex_lock(&mipi_dsim_lock);
201 	list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
202 	mutex_unlock(&mipi_dsim_lock);
203 
204 	return 0;
205 }
206 
exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver * lcd_drv)207 static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(
208 					struct mipi_dsim_lcd_driver *lcd_drv)
209 {
210 	struct mipi_dsim_ddi *dsim_ddi, *next;
211 	struct mipi_dsim_lcd_device *lcd_dev;
212 
213 	mutex_lock(&mipi_dsim_lock);
214 
215 	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
216 		if (!dsim_ddi)
217 			goto out;
218 
219 		lcd_dev = dsim_ddi->dsim_lcd_dev;
220 		if (!lcd_dev)
221 			continue;
222 
223 		if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
224 			/**
225 			 * bus_id would be used to identify
226 			 * connected bus.
227 			 */
228 			dsim_ddi->bus_id = lcd_dev->bus_id;
229 			mutex_unlock(&mipi_dsim_lock);
230 
231 			return dsim_ddi;
232 		}
233 
234 		list_del(&dsim_ddi->list);
235 		kfree(dsim_ddi);
236 	}
237 
238 out:
239 	mutex_unlock(&mipi_dsim_lock);
240 
241 	return NULL;
242 }
243 
exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver * lcd_drv)244 int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
245 {
246 	struct mipi_dsim_ddi *dsim_ddi;
247 
248 	if (!lcd_drv->name) {
249 		pr_err("dsim_lcd_driver name is NULL.\n");
250 		return -EFAULT;
251 	}
252 
253 	dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
254 	if (!dsim_ddi) {
255 		pr_err("mipi_dsim_ddi object not found.\n");
256 		return -EFAULT;
257 	}
258 
259 	dsim_ddi->dsim_lcd_drv = lcd_drv;
260 
261 	pr_info("registered panel driver(%s) to mipi-dsi driver.\n",
262 		lcd_drv->name);
263 
264 	return 0;
265 
266 }
267 
exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device * dsim,const char * name)268 static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(
269 						struct mipi_dsim_device *dsim,
270 						const char *name)
271 {
272 	struct mipi_dsim_ddi *dsim_ddi, *next;
273 	struct mipi_dsim_lcd_driver *lcd_drv;
274 	struct mipi_dsim_lcd_device *lcd_dev;
275 	int ret;
276 
277 	mutex_lock(&dsim->lock);
278 
279 	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
280 		lcd_drv = dsim_ddi->dsim_lcd_drv;
281 		lcd_dev = dsim_ddi->dsim_lcd_dev;
282 		if (!lcd_drv || !lcd_dev ||
283 			(dsim->id != dsim_ddi->bus_id))
284 				continue;
285 
286 		dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
287 				lcd_drv->id, lcd_dev->id);
288 		dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
289 				lcd_dev->bus_id, dsim->id);
290 
291 		if ((strcmp(lcd_drv->name, name) == 0)) {
292 			lcd_dev->master = dsim;
293 
294 			lcd_dev->dev.parent = dsim->dev;
295 			dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
296 
297 			ret = device_register(&lcd_dev->dev);
298 			if (ret < 0) {
299 				dev_err(dsim->dev,
300 					"can't register %s, status %d\n",
301 					dev_name(&lcd_dev->dev), ret);
302 				mutex_unlock(&dsim->lock);
303 
304 				return NULL;
305 			}
306 
307 			dsim->dsim_lcd_dev = lcd_dev;
308 			dsim->dsim_lcd_drv = lcd_drv;
309 
310 			mutex_unlock(&dsim->lock);
311 
312 			return dsim_ddi;
313 		}
314 	}
315 
316 	mutex_unlock(&dsim->lock);
317 
318 	return NULL;
319 }
320 
321 /* define MIPI-DSI Master operations. */
322 static struct mipi_dsim_master_ops master_ops = {
323 	.cmd_read			= exynos_mipi_dsi_rd_data,
324 	.cmd_write			= exynos_mipi_dsi_wr_data,
325 	.get_dsim_frame_done		= exynos_mipi_dsi_get_frame_done_status,
326 	.clear_dsim_frame_done		= exynos_mipi_dsi_clear_frame_done,
327 	.set_early_blank_mode		= exynos_mipi_dsi_early_blank_mode,
328 	.set_blank_mode			= exynos_mipi_dsi_blank_mode,
329 };
330 
exynos_mipi_dsi_probe(struct platform_device * pdev)331 static int exynos_mipi_dsi_probe(struct platform_device *pdev)
332 {
333 	struct resource *res;
334 	struct mipi_dsim_device *dsim;
335 	struct mipi_dsim_config *dsim_config;
336 	struct mipi_dsim_platform_data *dsim_pd;
337 	struct mipi_dsim_ddi *dsim_ddi;
338 	int ret = -EINVAL;
339 
340 	dsim = devm_kzalloc(&pdev->dev, sizeof(struct mipi_dsim_device),
341 				GFP_KERNEL);
342 	if (!dsim) {
343 		dev_err(&pdev->dev, "failed to allocate dsim object.\n");
344 		return -ENOMEM;
345 	}
346 
347 	dsim->pd = to_dsim_plat(pdev);
348 	dsim->dev = &pdev->dev;
349 	dsim->id = pdev->id;
350 
351 	/* get mipi_dsim_platform_data. */
352 	dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
353 	if (dsim_pd == NULL) {
354 		dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
355 		return -EINVAL;
356 	}
357 	/* get mipi_dsim_config. */
358 	dsim_config = dsim_pd->dsim_config;
359 	if (dsim_config == NULL) {
360 		dev_err(&pdev->dev, "failed to get dsim config data.\n");
361 		return -EINVAL;
362 	}
363 
364 	dsim->dsim_config = dsim_config;
365 	dsim->master_ops = &master_ops;
366 
367 	mutex_init(&dsim->lock);
368 
369 	ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies),
370 					supplies);
371 	if (ret) {
372 		dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret);
373 		return ret;
374 	}
375 
376 	dsim->clock = devm_clk_get(&pdev->dev, "dsim0");
377 	if (IS_ERR(dsim->clock)) {
378 		dev_err(&pdev->dev, "failed to get dsim clock source\n");
379 		return -ENODEV;
380 	}
381 
382 	clk_enable(dsim->clock);
383 
384 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
385 
386 	dsim->reg_base = devm_ioremap_resource(&pdev->dev, res);
387 	if (IS_ERR(dsim->reg_base)) {
388 		ret = PTR_ERR(dsim->reg_base);
389 		goto error;
390 	}
391 
392 	mutex_init(&dsim->lock);
393 
394 	/* bind lcd ddi matched with panel name. */
395 	dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
396 	if (!dsim_ddi) {
397 		dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
398 		ret = -EINVAL;
399 		goto error;
400 	}
401 
402 	dsim->irq = platform_get_irq(pdev, 0);
403 	if (IS_ERR_VALUE(dsim->irq)) {
404 		dev_err(&pdev->dev, "failed to request dsim irq resource\n");
405 		ret = -EINVAL;
406 		goto error;
407 	}
408 
409 	init_completion(&dsim_wr_comp);
410 	init_completion(&dsim_rd_comp);
411 	platform_set_drvdata(pdev, dsim);
412 
413 	ret = devm_request_irq(&pdev->dev, dsim->irq,
414 			exynos_mipi_dsi_interrupt_handler,
415 			IRQF_SHARED, dev_name(&pdev->dev), dsim);
416 	if (ret != 0) {
417 		dev_err(&pdev->dev, "failed to request dsim irq\n");
418 		ret = -EINVAL;
419 		goto error;
420 	}
421 
422 	/* enable interrupts */
423 	exynos_mipi_dsi_init_interrupt(dsim);
424 
425 	/* initialize mipi-dsi client(lcd panel). */
426 	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
427 		dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
428 
429 	/* in case mipi-dsi has been enabled by bootloader */
430 	if (dsim_pd->enabled) {
431 		exynos_mipi_regulator_enable(dsim);
432 		goto done;
433 	}
434 
435 	/* lcd panel power on. */
436 	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
437 		dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
438 
439 	exynos_mipi_regulator_enable(dsim);
440 
441 	/* enable MIPI-DSI PHY. */
442 	if (dsim->pd->phy_enable)
443 		dsim->pd->phy_enable(pdev, true);
444 
445 	exynos_mipi_update_cfg(dsim);
446 
447 	/* set lcd panel sequence commands. */
448 	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
449 		dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
450 
451 	dsim->suspended = false;
452 
453 done:
454 	platform_set_drvdata(pdev, dsim);
455 
456 	dev_dbg(&pdev->dev, "%s() completed successfully (%s mode)\n", __func__,
457 		dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB");
458 
459 	return 0;
460 
461 error:
462 	clk_disable(dsim->clock);
463 	return ret;
464 }
465 
exynos_mipi_dsi_remove(struct platform_device * pdev)466 static int exynos_mipi_dsi_remove(struct platform_device *pdev)
467 {
468 	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
469 	struct mipi_dsim_ddi *dsim_ddi, *next;
470 	struct mipi_dsim_lcd_driver *dsim_lcd_drv;
471 
472 	clk_disable(dsim->clock);
473 
474 	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
475 		if (dsim_ddi) {
476 			if (dsim->id != dsim_ddi->bus_id)
477 				continue;
478 
479 			dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
480 
481 			if (dsim_lcd_drv->remove)
482 				dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
483 
484 			kfree(dsim_ddi);
485 		}
486 	}
487 
488 	return 0;
489 }
490 
491 #ifdef CONFIG_PM_SLEEP
exynos_mipi_dsi_suspend(struct device * dev)492 static int exynos_mipi_dsi_suspend(struct device *dev)
493 {
494 	struct platform_device *pdev = to_platform_device(dev);
495 	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
496 	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
497 	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
498 
499 	disable_irq(dsim->irq);
500 
501 	if (dsim->suspended)
502 		return 0;
503 
504 	if (client_drv && client_drv->suspend)
505 		client_drv->suspend(client_dev);
506 
507 	/* enable MIPI-DSI PHY. */
508 	if (dsim->pd->phy_enable)
509 		dsim->pd->phy_enable(pdev, false);
510 
511 	clk_disable(dsim->clock);
512 
513 	exynos_mipi_regulator_disable(dsim);
514 
515 	dsim->suspended = true;
516 
517 	return 0;
518 }
519 
exynos_mipi_dsi_resume(struct device * dev)520 static int exynos_mipi_dsi_resume(struct device *dev)
521 {
522 	struct platform_device *pdev = to_platform_device(dev);
523 	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
524 	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
525 	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
526 
527 	enable_irq(dsim->irq);
528 
529 	if (!dsim->suspended)
530 		return 0;
531 
532 	/* lcd panel power on. */
533 	if (client_drv && client_drv->power_on)
534 		client_drv->power_on(client_dev, 1);
535 
536 	exynos_mipi_regulator_enable(dsim);
537 
538 	/* enable MIPI-DSI PHY. */
539 	if (dsim->pd->phy_enable)
540 		dsim->pd->phy_enable(pdev, true);
541 
542 	clk_enable(dsim->clock);
543 
544 	exynos_mipi_update_cfg(dsim);
545 
546 	/* set lcd panel sequence commands. */
547 	if (client_drv && client_drv->set_sequence)
548 		client_drv->set_sequence(client_dev);
549 
550 	dsim->suspended = false;
551 
552 	return 0;
553 }
554 #endif
555 
556 static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = {
557 	SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume)
558 };
559 
560 static struct platform_driver exynos_mipi_dsi_driver = {
561 	.probe = exynos_mipi_dsi_probe,
562 	.remove = exynos_mipi_dsi_remove,
563 	.driver = {
564 		   .name = "exynos-mipi-dsim",
565 		   .owner = THIS_MODULE,
566 		   .pm = &exynos_mipi_dsi_pm_ops,
567 	},
568 };
569 
570 module_platform_driver(exynos_mipi_dsi_driver);
571 
572 MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
573 MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
574 MODULE_LICENSE("GPL");
575