Linux Audio

Check our new training course

Loading...
  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
 36#include <video/exynos_mipi_dsim.h>
 37
 38#include <plat/fb.h>
 39
 40#include "exynos_mipi_dsi_common.h"
 41#include "exynos_mipi_dsi_lowlevel.h"
 42
 43struct mipi_dsim_ddi {
 44	int				bus_id;
 45	struct list_head		list;
 46	struct mipi_dsim_lcd_device	*dsim_lcd_dev;
 47	struct mipi_dsim_lcd_driver	*dsim_lcd_drv;
 48};
 49
 50static LIST_HEAD(dsim_ddi_list);
 51
 52static DEFINE_MUTEX(mipi_dsim_lock);
 53
 54static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
 55							*pdev)
 56{
 57	return pdev->dev.platform_data;
 58}
 59
 60static struct regulator_bulk_data supplies[] = {
 61	{ .supply = "vdd11", },
 62	{ .supply = "vdd18", },
 63};
 64
 65static int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim)
 66{
 67	int ret;
 68
 69	mutex_lock(&dsim->lock);
 70	ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
 71	mutex_unlock(&dsim->lock);
 72
 73	return ret;
 74}
 75
 76static int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim)
 77{
 78	int ret;
 79
 80	mutex_lock(&dsim->lock);
 81	ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
 82	mutex_unlock(&dsim->lock);
 83
 84	return ret;
 85}
 86
 87/* update all register settings to MIPI DSI controller. */
 88static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
 89{
 90	/*
 91	 * data from Display controller(FIMD) is not transferred in video mode
 92	 * but in case of command mode, all settings is not updated to
 93	 * registers.
 94	 */
 95	exynos_mipi_dsi_stand_by(dsim, 0);
 96
 97	exynos_mipi_dsi_init_dsim(dsim);
 98	exynos_mipi_dsi_init_link(dsim);
 99
100	exynos_mipi_dsi_set_hs_enable(dsim);
101
102	/* set display timing. */
103	exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
104
105	exynos_mipi_dsi_init_interrupt(dsim);
106
107	/*
108	 * data from Display controller(FIMD) is transferred in video mode
109	 * but in case of command mode, all settigs is updated to registers.
110	 */
111	exynos_mipi_dsi_stand_by(dsim, 1);
112}
113
114static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim,
115		int power)
116{
117	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
118	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
119
120	switch (power) {
121	case FB_BLANK_POWERDOWN:
122		if (dsim->suspended)
123			return 0;
124
125		if (client_drv && client_drv->suspend)
126			client_drv->suspend(client_dev);
127
128		clk_disable(dsim->clock);
129
130		exynos_mipi_regulator_disable(dsim);
131
132		dsim->suspended = true;
133
134		break;
135	default:
136		break;
137	}
138
139	return 0;
140}
141
142static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
143{
144	struct platform_device *pdev = to_platform_device(dsim->dev);
145	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
146	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
147
148	switch (power) {
149	case FB_BLANK_UNBLANK:
150		if (!dsim->suspended)
151			return 0;
152
153		/* lcd panel power on. */
154		if (client_drv && client_drv->power_on)
155			client_drv->power_on(client_dev, 1);
156
157		exynos_mipi_regulator_disable(dsim);
158
159		/* enable MIPI-DSI PHY. */
160		if (dsim->pd->phy_enable)
161			dsim->pd->phy_enable(pdev, true);
162
163		clk_enable(dsim->clock);
164
165		exynos_mipi_update_cfg(dsim);
166
167		/* set lcd panel sequence commands. */
168		if (client_drv && client_drv->set_sequence)
169			client_drv->set_sequence(client_dev);
170
171		dsim->suspended = false;
172
173		break;
174	case FB_BLANK_NORMAL:
175		/* TODO. */
176		break;
177	default:
178		break;
179	}
180
181	return 0;
182}
183
184int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
185{
186	struct mipi_dsim_ddi *dsim_ddi;
187
188	if (!lcd_dev->name) {
189		pr_err("dsim_lcd_device name is NULL.\n");
190		return -EFAULT;
191	}
192
193	dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
194	if (!dsim_ddi) {
195		pr_err("failed to allocate dsim_ddi object.\n");
196		return -ENOMEM;
197	}
198
199	dsim_ddi->dsim_lcd_dev = lcd_dev;
200
201	mutex_lock(&mipi_dsim_lock);
202	list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
203	mutex_unlock(&mipi_dsim_lock);
204
205	return 0;
206}
207
208struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(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
238out:
239	mutex_unlock(&mipi_dsim_lock);
240
241	return NULL;
242}
243
244int 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
268struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
269						const char *name)
270{
271	struct mipi_dsim_ddi *dsim_ddi, *next;
272	struct mipi_dsim_lcd_driver *lcd_drv;
273	struct mipi_dsim_lcd_device *lcd_dev;
274	int ret;
275
276	mutex_lock(&dsim->lock);
277
278	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
279		lcd_drv = dsim_ddi->dsim_lcd_drv;
280		lcd_dev = dsim_ddi->dsim_lcd_dev;
281		if (!lcd_drv || !lcd_dev ||
282			(dsim->id != dsim_ddi->bus_id))
283				continue;
284
285		dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
286				lcd_drv->id, lcd_dev->id);
287		dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
288				lcd_dev->bus_id, dsim->id);
289
290		if ((strcmp(lcd_drv->name, name) == 0)) {
291			lcd_dev->master = dsim;
292
293			lcd_dev->dev.parent = dsim->dev;
294			dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
295
296			ret = device_register(&lcd_dev->dev);
297			if (ret < 0) {
298				dev_err(dsim->dev,
299					"can't register %s, status %d\n",
300					dev_name(&lcd_dev->dev), ret);
301				mutex_unlock(&dsim->lock);
302
303				return NULL;
304			}
305
306			dsim->dsim_lcd_dev = lcd_dev;
307			dsim->dsim_lcd_drv = lcd_drv;
308
309			mutex_unlock(&dsim->lock);
310
311			return dsim_ddi;
312		}
313	}
314
315	mutex_unlock(&dsim->lock);
316
317	return NULL;
318}
319
320/* define MIPI-DSI Master operations. */
321static struct mipi_dsim_master_ops master_ops = {
322	.cmd_read			= exynos_mipi_dsi_rd_data,
323	.cmd_write			= exynos_mipi_dsi_wr_data,
324	.get_dsim_frame_done		= exynos_mipi_dsi_get_frame_done_status,
325	.clear_dsim_frame_done		= exynos_mipi_dsi_clear_frame_done,
326	.set_early_blank_mode		= exynos_mipi_dsi_early_blank_mode,
327	.set_blank_mode			= exynos_mipi_dsi_blank_mode,
328};
329
330static int exynos_mipi_dsi_probe(struct platform_device *pdev)
331{
332	struct resource *res;
333	struct mipi_dsim_device *dsim;
334	struct mipi_dsim_config *dsim_config;
335	struct mipi_dsim_platform_data *dsim_pd;
336	struct mipi_dsim_ddi *dsim_ddi;
337	int ret = -EINVAL;
338
339	dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL);
340	if (!dsim) {
341		dev_err(&pdev->dev, "failed to allocate dsim object.\n");
342		return -ENOMEM;
343	}
344
345	dsim->pd = to_dsim_plat(pdev);
346	dsim->dev = &pdev->dev;
347	dsim->id = pdev->id;
348
349	/* get mipi_dsim_platform_data. */
350	dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
351	if (dsim_pd == NULL) {
352		dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
353		goto err_clock_get;
354	}
355	/* get mipi_dsim_config. */
356	dsim_config = dsim_pd->dsim_config;
357	if (dsim_config == NULL) {
358		dev_err(&pdev->dev, "failed to get dsim config data.\n");
359		goto err_clock_get;
360	}
361
362	dsim->dsim_config = dsim_config;
363	dsim->master_ops = &master_ops;
364
365	mutex_init(&dsim->lock);
366
367	ret = regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies), supplies);
368	if (ret) {
369		dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret);
370		goto err_clock_get;
371	}
372
373	dsim->clock = clk_get(&pdev->dev, "dsim0");
374	if (IS_ERR(dsim->clock)) {
375		dev_err(&pdev->dev, "failed to get dsim clock source\n");
376		goto err_clock_get;
377	}
378
379	clk_enable(dsim->clock);
380
381	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
382	if (!res) {
383		dev_err(&pdev->dev, "failed to get io memory region\n");
384		goto err_platform_get;
385	}
386
387	dsim->res = request_mem_region(res->start, resource_size(res),
388					dev_name(&pdev->dev));
389	if (!dsim->res) {
390		dev_err(&pdev->dev, "failed to request io memory region\n");
391		ret = -ENOMEM;
392		goto err_mem_region;
393	}
394
395	dsim->reg_base = ioremap(res->start, resource_size(res));
396	if (!dsim->reg_base) {
397		dev_err(&pdev->dev, "failed to remap io region\n");
398		ret = -ENOMEM;
399		goto err_ioremap;
400	}
401
402	mutex_init(&dsim->lock);
403
404	/* bind lcd ddi matched with panel name. */
405	dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
406	if (!dsim_ddi) {
407		dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
408		goto err_bind;
409	}
410
411	dsim->irq = platform_get_irq(pdev, 0);
412	if (dsim->irq < 0) {
413		dev_err(&pdev->dev, "failed to request dsim irq resource\n");
414		ret = -EINVAL;
415		goto err_platform_get_irq;
416	}
417
418	init_completion(&dsim_wr_comp);
419	init_completion(&dsim_rd_comp);
420	platform_set_drvdata(pdev, dsim);
421
422	ret = request_irq(dsim->irq, exynos_mipi_dsi_interrupt_handler,
423			IRQF_SHARED, dev_name(&pdev->dev), dsim);
424	if (ret != 0) {
425		dev_err(&pdev->dev, "failed to request dsim irq\n");
426		ret = -EINVAL;
427		goto err_bind;
428	}
429
430	/* enable interrupts */
431	exynos_mipi_dsi_init_interrupt(dsim);
432
433	/* initialize mipi-dsi client(lcd panel). */
434	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
435		dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
436
437	/* in case mipi-dsi has been enabled by bootloader */
438	if (dsim_pd->enabled) {
439		exynos_mipi_regulator_enable(dsim);
440		goto done;
441	}
442
443	/* lcd panel power on. */
444	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
445		dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
446
447	exynos_mipi_regulator_enable(dsim);
448
449	/* enable MIPI-DSI PHY. */
450	if (dsim->pd->phy_enable)
451		dsim->pd->phy_enable(pdev, true);
452
453	exynos_mipi_update_cfg(dsim);
454
455	/* set lcd panel sequence commands. */
456	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
457		dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
458
459	dsim->suspended = false;
460
461done:
462	platform_set_drvdata(pdev, dsim);
463
464	dev_dbg(&pdev->dev, "%s() completed sucessfuly (%s mode)\n", __func__,
465		dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB");
466
467	return 0;
468
469err_bind:
470	iounmap(dsim->reg_base);
471
472err_ioremap:
473	release_mem_region(dsim->res->start, resource_size(dsim->res));
474
475err_mem_region:
476	release_resource(dsim->res);
477
478err_platform_get:
479	clk_disable(dsim->clock);
480	clk_put(dsim->clock);
481err_clock_get:
482	kfree(dsim);
483
484err_platform_get_irq:
485	return ret;
486}
487
488static int __devexit exynos_mipi_dsi_remove(struct platform_device *pdev)
489{
490	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
491	struct mipi_dsim_ddi *dsim_ddi, *next;
492	struct mipi_dsim_lcd_driver *dsim_lcd_drv;
493
494	iounmap(dsim->reg_base);
495
496	clk_disable(dsim->clock);
497	clk_put(dsim->clock);
498
499	release_resource(dsim->res);
500	release_mem_region(dsim->res->start, resource_size(dsim->res));
501
502	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
503		if (dsim_ddi) {
504			if (dsim->id != dsim_ddi->bus_id)
505				continue;
506
507			dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
508
509			if (dsim_lcd_drv->remove)
510				dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
511
512			kfree(dsim_ddi);
513		}
514	}
515
516	regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
517	kfree(dsim);
518
519	return 0;
520}
521
522#ifdef CONFIG_PM_SLEEP
523static int exynos_mipi_dsi_suspend(struct device *dev)
524{
525	struct platform_device *pdev = to_platform_device(dev);
526	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
527	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
528	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
529
530	disable_irq(dsim->irq);
531
532	if (dsim->suspended)
533		return 0;
534
535	if (client_drv && client_drv->suspend)
536		client_drv->suspend(client_dev);
537
538	/* enable MIPI-DSI PHY. */
539	if (dsim->pd->phy_enable)
540		dsim->pd->phy_enable(pdev, false);
541
542	clk_disable(dsim->clock);
543
544	exynos_mipi_regulator_disable(dsim);
545
546	dsim->suspended = true;
547
548	return 0;
549}
550
551static int exynos_mipi_dsi_resume(struct device *dev)
552{
553	struct platform_device *pdev = to_platform_device(dev);
554	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
555	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
556	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
557
558	enable_irq(dsim->irq);
559
560	if (!dsim->suspended)
561		return 0;
562
563	/* lcd panel power on. */
564	if (client_drv && client_drv->power_on)
565		client_drv->power_on(client_dev, 1);
566
567	exynos_mipi_regulator_enable(dsim);
568
569	/* enable MIPI-DSI PHY. */
570	if (dsim->pd->phy_enable)
571		dsim->pd->phy_enable(pdev, true);
572
573	clk_enable(dsim->clock);
574
575	exynos_mipi_update_cfg(dsim);
576
577	/* set lcd panel sequence commands. */
578	if (client_drv && client_drv->set_sequence)
579		client_drv->set_sequence(client_dev);
580
581	dsim->suspended = false;
582
583	return 0;
584}
585#endif
586
587static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = {
588	SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume)
589};
590
591static struct platform_driver exynos_mipi_dsi_driver = {
592	.probe = exynos_mipi_dsi_probe,
593	.remove = __devexit_p(exynos_mipi_dsi_remove),
594	.driver = {
595		   .name = "exynos-mipi-dsim",
596		   .owner = THIS_MODULE,
597		   .pm = &exynos_mipi_dsi_pm_ops,
598	},
599};
600
601module_platform_driver(exynos_mipi_dsi_driver);
602
603MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
604MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
605MODULE_LICENSE("GPL");