17258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee/* linux/drivers/video/exynos/exynos_mipi_dsi.c
27258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee *
37258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee * Samsung SoC MIPI-DSIM driver.
47258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee *
57258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee * Copyright (c) 2012 Samsung Electronics Co., Ltd
67258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee *
77258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee * InKi Dae, <inki.dae@samsung.com>
87258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee * Donghwa Lee, <dh09.lee@samsung.com>
97258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee *
107258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee * This program is free software; you can redistribute it and/or modify
117258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee * it under the terms of the GNU General Public License version 2 as
127258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee * published by the Free Software Foundation.
137258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee*/
147258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
157258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/module.h>
167258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/kernel.h>
177258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/errno.h>
187258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/clk.h>
197258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/mutex.h>
207258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/wait.h>
217258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/fs.h>
227258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/mm.h>
237258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/fb.h>
247258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/ctype.h>
257258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/platform_device.h>
267258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/io.h>
277258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/irq.h>
287258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/memory.h>
297258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/delay.h>
307258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/interrupt.h>
317258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/kthread.h>
327258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/notifier.h>
337e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki#include <linux/phy/phy.h>
347258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/regulator/consumer.h>
357258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <linux/pm_runtime.h>
366637eca322e912bf4e272ab33447bdafea2658e8Sachin Kamat#include <linux/err.h>
377258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
387258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include <video/exynos_mipi_dsim.h>
397258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
407258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include "exynos_mipi_dsi_common.h"
417258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#include "exynos_mipi_dsi_lowlevel.h"
427258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
437258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestruct mipi_dsim_ddi {
447258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	int				bus_id;
457258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct list_head		list;
467258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_device	*dsim_lcd_dev;
477258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_driver	*dsim_lcd_drv;
487258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee};
497258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
507258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic LIST_HEAD(dsim_ddi_list);
517258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
527258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic DEFINE_MUTEX(mipi_dsim_lock);
537258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
547258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
557258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee							*pdev)
567258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
577258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return pdev->dev.platform_data;
587258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
597258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
607258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic struct regulator_bulk_data supplies[] = {
6166685aa00bf9970be8be3783dbc3b59f69968214Donghwa Lee	{ .supply = "vdd11", },
627258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	{ .supply = "vdd18", },
637258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee};
647258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
657258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim)
667258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
677258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	int ret;
687258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
697258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_lock(&dsim->lock);
707258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
717258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_unlock(&dsim->lock);
727258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
737258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return ret;
747258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
757258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
767258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim)
777258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
787258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	int ret;
797258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
807258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_lock(&dsim->lock);
817258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
827258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_unlock(&dsim->lock);
837258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
847258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return ret;
857258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
867258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
877258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee/* update all register settings to MIPI DSI controller. */
887258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
897258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
907258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/*
917258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	 * data from Display controller(FIMD) is not transferred in video mode
927258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	 * but in case of command mode, all settings is not updated to
937258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	 * registers.
947258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	 */
957258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_dsi_stand_by(dsim, 0);
967258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
977258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_dsi_init_dsim(dsim);
987258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_dsi_init_link(dsim);
997258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1007258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_dsi_set_hs_enable(dsim);
1017258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1027258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* set display timing. */
1037258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
1047258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
105113b66844ccd6eb3525c50a506e90b03155fdaf4Donghwa Lee	exynos_mipi_dsi_init_interrupt(dsim);
106113b66844ccd6eb3525c50a506e90b03155fdaf4Donghwa Lee
1077258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/*
1087258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	 * data from Display controller(FIMD) is transferred in video mode
109ff0c26424c1d993d8d1e04f72f1d428e935798daMasanari Iida	 * but in case of command mode, all settings are updated to registers.
1107258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	 */
1117258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_dsi_stand_by(dsim, 1);
1127258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
1137258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1147258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim,
1157258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		int power)
1167258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
1177258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
1187258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
1197258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1207258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	switch (power) {
1217258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	case FB_BLANK_POWERDOWN:
1227258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if (dsim->suspended)
1237258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			return 0;
1247258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1257258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if (client_drv && client_drv->suspend)
1267258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			client_drv->suspend(client_dev);
1277258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1287258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		clk_disable(dsim->clock);
1297258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1307258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		exynos_mipi_regulator_disable(dsim);
1317258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1327258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dsim->suspended = true;
1337258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1347258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		break;
1357258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	default:
1367258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		break;
1377258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
1387258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1397258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return 0;
1407258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
1417258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1427258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
1437258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
1447258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
1457258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
1467258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1477258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	switch (power) {
1487258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	case FB_BLANK_UNBLANK:
1497258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if (!dsim->suspended)
1507258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			return 0;
1517258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1527258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		/* lcd panel power on. */
1537258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if (client_drv && client_drv->power_on)
1547258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			client_drv->power_on(client_dev, 1);
1557258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
15691d1cfa8779e1929167a7cf1e5825462af7d6e4aDonghwa Lee		exynos_mipi_regulator_enable(dsim);
1577258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1587258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		/* enable MIPI-DSI PHY. */
1597e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki		phy_power_on(dsim->phy);
1607258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1617258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		clk_enable(dsim->clock);
1627258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1637258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		exynos_mipi_update_cfg(dsim);
1647258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1657258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		/* set lcd panel sequence commands. */
1667258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if (client_drv && client_drv->set_sequence)
1677258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			client_drv->set_sequence(client_dev);
1687258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1697258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dsim->suspended = false;
1707258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1717258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		break;
1727258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	case FB_BLANK_NORMAL:
1737258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		/* TODO. */
1747258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		break;
1757258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	default:
1767258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		break;
1777258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
1787258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1797258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return 0;
1807258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
1817258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1827258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leeint exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
1837258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
1847258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_ddi *dsim_ddi;
1857258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1867258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (!lcd_dev->name) {
1877258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		pr_err("dsim_lcd_device name is NULL.\n");
1887258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		return -EFAULT;
1897258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
1907258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1917258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
1927258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (!dsim_ddi) {
1937258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		pr_err("failed to allocate dsim_ddi object.\n");
1947258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		return -ENOMEM;
1957258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
1967258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1977258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim_ddi->dsim_lcd_dev = lcd_dev;
1987258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
1997258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_lock(&mipi_dsim_lock);
2007258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
2017258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_unlock(&mipi_dsim_lock);
2027258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2037258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return 0;
2047258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
2057258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2064c4ceee0de69616f98240cbe3f5a4ed6d1973c63Sachin Kamatstatic struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(
2074c4ceee0de69616f98240cbe3f5a4ed6d1973c63Sachin Kamat					struct mipi_dsim_lcd_driver *lcd_drv)
2087258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
2097258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_ddi *dsim_ddi, *next;
2107258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_device *lcd_dev;
2117258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2127258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_lock(&mipi_dsim_lock);
2137258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2147258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
2157258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if (!dsim_ddi)
2167258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			goto out;
2177258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2187258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		lcd_dev = dsim_ddi->dsim_lcd_dev;
2197258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if (!lcd_dev)
2207258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			continue;
2217258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2227258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
2237258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			/**
2247258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			 * bus_id would be used to identify
2257258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			 * connected bus.
2267258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			 */
2277258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			dsim_ddi->bus_id = lcd_dev->bus_id;
2287258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			mutex_unlock(&mipi_dsim_lock);
2297258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2307258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			return dsim_ddi;
2317258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		}
2327258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2337258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		list_del(&dsim_ddi->list);
2347258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		kfree(dsim_ddi);
2357258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
2367258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2377258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leeout:
2387258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_unlock(&mipi_dsim_lock);
2397258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2407258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return NULL;
2417258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
2427258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2437258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leeint exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
2447258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
2457258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_ddi *dsim_ddi;
2467258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2477258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (!lcd_drv->name) {
2487258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		pr_err("dsim_lcd_driver name is NULL.\n");
2497258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		return -EFAULT;
2507258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
2517258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2527258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
2537258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (!dsim_ddi) {
2547258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		pr_err("mipi_dsim_ddi object not found.\n");
2557258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		return -EFAULT;
2567258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
2577258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2587258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim_ddi->dsim_lcd_drv = lcd_drv;
2597258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2607258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	pr_info("registered panel driver(%s) to mipi-dsi driver.\n",
2617258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		lcd_drv->name);
2627258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2637258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return 0;
2647258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2657258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
2667258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2674c4ceee0de69616f98240cbe3f5a4ed6d1973c63Sachin Kamatstatic struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(
2684c4ceee0de69616f98240cbe3f5a4ed6d1973c63Sachin Kamat						struct mipi_dsim_device *dsim,
2697258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee						const char *name)
2707258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
2717258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_ddi *dsim_ddi, *next;
2727258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_driver *lcd_drv;
2737258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_device *lcd_dev;
2747258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	int ret;
2757258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2767258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_lock(&dsim->lock);
2777258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2787258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
2797258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		lcd_drv = dsim_ddi->dsim_lcd_drv;
2807258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		lcd_dev = dsim_ddi->dsim_lcd_dev;
2817258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if (!lcd_drv || !lcd_dev ||
2827258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			(dsim->id != dsim_ddi->bus_id))
2837258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee				continue;
2847258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2857258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
2867258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee				lcd_drv->id, lcd_dev->id);
2877258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
2887258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee				lcd_dev->bus_id, dsim->id);
2897258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2907258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if ((strcmp(lcd_drv->name, name) == 0)) {
2917258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			lcd_dev->master = dsim;
2927258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2937258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			lcd_dev->dev.parent = dsim->dev;
2947258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
2957258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
2967258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			ret = device_register(&lcd_dev->dev);
2977258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			if (ret < 0) {
2987258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee				dev_err(dsim->dev,
2997258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee					"can't register %s, status %d\n",
3007258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee					dev_name(&lcd_dev->dev), ret);
3017258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee				mutex_unlock(&dsim->lock);
3027258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3037258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee				return NULL;
3047258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			}
3057258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3067258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			dsim->dsim_lcd_dev = lcd_dev;
3077258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			dsim->dsim_lcd_drv = lcd_drv;
3087258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3097258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			mutex_unlock(&dsim->lock);
3107258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3117258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			return dsim_ddi;
3127258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		}
3137258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
3147258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3157258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_unlock(&dsim->lock);
3167258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3177258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return NULL;
3187258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
3197258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3207258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee/* define MIPI-DSI Master operations. */
3217258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic struct mipi_dsim_master_ops master_ops = {
3227258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	.cmd_read			= exynos_mipi_dsi_rd_data,
3237258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	.cmd_write			= exynos_mipi_dsi_wr_data,
3247258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	.get_dsim_frame_done		= exynos_mipi_dsi_get_frame_done_status,
3257258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	.clear_dsim_frame_done		= exynos_mipi_dsi_clear_frame_done,
3267258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	.set_early_blank_mode		= exynos_mipi_dsi_early_blank_mode,
3277258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	.set_blank_mode			= exynos_mipi_dsi_blank_mode,
3287258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee};
3297258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3307258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic int exynos_mipi_dsi_probe(struct platform_device *pdev)
3317258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
3327258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct resource *res;
3337258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_device *dsim;
3347258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_config *dsim_config;
3357258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_platform_data *dsim_pd;
3367258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_ddi *dsim_ddi;
3377258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	int ret = -EINVAL;
3387258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
339f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat	dsim = devm_kzalloc(&pdev->dev, sizeof(struct mipi_dsim_device),
340f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat				GFP_KERNEL);
3417258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (!dsim) {
3427258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_err(&pdev->dev, "failed to allocate dsim object.\n");
3437258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		return -ENOMEM;
3447258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
3457258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3467258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim->pd = to_dsim_plat(pdev);
3477258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim->dev = &pdev->dev;
3487258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim->id = pdev->id;
3497258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3507258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* get mipi_dsim_platform_data. */
3517258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
3527258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (dsim_pd == NULL) {
3537258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
354f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat		return -EINVAL;
3557258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
3567258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* get mipi_dsim_config. */
3577258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim_config = dsim_pd->dsim_config;
3587258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (dsim_config == NULL) {
3597258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_err(&pdev->dev, "failed to get dsim config data.\n");
360f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat		return -EINVAL;
3617258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
3627258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3637258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim->dsim_config = dsim_config;
3647258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim->master_ops = &master_ops;
3657258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3667258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_init(&dsim->lock);
3677258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
368f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat	ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies),
369f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat					supplies);
3707258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (ret) {
3717258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret);
372f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat		return ret;
3737258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
3747258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3757e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki	dsim->phy = devm_phy_get(&pdev->dev, "dsim");
3767e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki	if (IS_ERR(dsim->phy))
3777e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki		return PTR_ERR(dsim->phy);
3787e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki
379f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat	dsim->clock = devm_clk_get(&pdev->dev, "dsim0");
3807258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (IS_ERR(dsim->clock)) {
3817258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_err(&pdev->dev, "failed to get dsim clock source\n");
382f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat		return -ENODEV;
3837258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
3847258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3857258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	clk_enable(dsim->clock);
3867258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3877258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3887258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3896637eca322e912bf4e272ab33447bdafea2658e8Sachin Kamat	dsim->reg_base = devm_ioremap_resource(&pdev->dev, res);
3906637eca322e912bf4e272ab33447bdafea2658e8Sachin Kamat	if (IS_ERR(dsim->reg_base)) {
3916637eca322e912bf4e272ab33447bdafea2658e8Sachin Kamat		ret = PTR_ERR(dsim->reg_base);
392f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat		goto error;
3937258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
3947258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3957258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	mutex_init(&dsim->lock);
3967258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
3977258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* bind lcd ddi matched with panel name. */
3987258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
3997258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (!dsim_ddi) {
4007258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
40136141e5692b42da5b010675b6e68e2292367eb9cPeter Senna Tschudin		ret = -EINVAL;
402f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat		goto error;
4037258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
4047258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4057258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim->irq = platform_get_irq(pdev, 0);
4060c980826211611178b6d76b246d00a4c840f21e5Sachin Kamat	if (IS_ERR_VALUE(dsim->irq)) {
4077258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_err(&pdev->dev, "failed to request dsim irq resource\n");
4087258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		ret = -EINVAL;
409f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat		goto error;
4107258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
4117258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
412b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki	init_completion(&dsim_wr_comp);
413b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki	init_completion(&dsim_rd_comp);
414b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki	platform_set_drvdata(pdev, dsim);
415b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki
416f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat	ret = devm_request_irq(&pdev->dev, dsim->irq,
417f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat			exynos_mipi_dsi_interrupt_handler,
418b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki			IRQF_SHARED, dev_name(&pdev->dev), dsim);
4197258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (ret != 0) {
4207258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dev_err(&pdev->dev, "failed to request dsim irq\n");
4217258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		ret = -EINVAL;
422f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamat		goto error;
4237258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
4247258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
425b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki	/* enable interrupts */
4267258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_dsi_init_interrupt(dsim);
4277258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4287258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* initialize mipi-dsi client(lcd panel). */
4297258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
4307258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
4317258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
432b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki	/* in case mipi-dsi has been enabled by bootloader */
433b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki	if (dsim_pd->enabled) {
434b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki		exynos_mipi_regulator_enable(dsim);
435b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki		goto done;
436b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki	}
4377258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4387258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* lcd panel power on. */
4397258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
4407258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
4417258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4427258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_regulator_enable(dsim);
4437258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4447258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* enable MIPI-DSI PHY. */
4457e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki	phy_power_on(dsim->phy);
4467258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4477258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_update_cfg(dsim);
4487258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4497258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* set lcd panel sequence commands. */
4507258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
4517258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
4527258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4537258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim->suspended = false;
4547258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
455b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrockidone:
4567258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	platform_set_drvdata(pdev, dsim);
4577258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4584907cb7b193a4f91c1fd30cf679c035e3644c64dAnatol Pomozov	dev_dbg(&pdev->dev, "%s() completed successfully (%s mode)\n", __func__,
459b89e1399bab8bf72762948d251e69df50a9d6d85Sylwester Nawrocki		dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB");
4607258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4617258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return 0;
4627258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
463f18acdeacbcf038df3c9b03a96193cb01ca45cbbSachin Kamaterror:
4647258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	clk_disable(dsim->clock);
4657258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return ret;
4667258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
4677258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
46848c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartmanstatic int exynos_mipi_dsi_remove(struct platform_device *pdev)
4697258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
4707258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
4717258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_ddi *dsim_ddi, *next;
4727258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_driver *dsim_lcd_drv;
4737258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4747258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	clk_disable(dsim->clock);
4757258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4767258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
4777258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		if (dsim_ddi) {
4787258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			if (dsim->id != dsim_ddi->bus_id)
4797258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee				continue;
4807258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4817258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
4827258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4837258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			if (dsim_lcd_drv->remove)
4847258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee				dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
4857258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4867258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee			kfree(dsim_ddi);
4877258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		}
4887258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	}
4897258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4907258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return 0;
4917258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
4927258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
4933bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrocki#ifdef CONFIG_PM_SLEEP
4943bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrockistatic int exynos_mipi_dsi_suspend(struct device *dev)
4957258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
4963bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrocki	struct platform_device *pdev = to_platform_device(dev);
4977258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
4987258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
4997258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
5007258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5017258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	disable_irq(dsim->irq);
5027258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5037258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (dsim->suspended)
5047258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		return 0;
5057258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5067258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (client_drv && client_drv->suspend)
5077258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		client_drv->suspend(client_dev);
5087258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5097e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki	/* disable MIPI-DSI PHY. */
5107e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki	phy_power_off(dsim->phy);
5117258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5127258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	clk_disable(dsim->clock);
5137258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5147258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_regulator_disable(dsim);
5157258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5167258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim->suspended = true;
5177258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5187258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return 0;
5197258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
5207258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5213bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrockistatic int exynos_mipi_dsi_resume(struct device *dev)
5227258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee{
5233bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrocki	struct platform_device *pdev = to_platform_device(dev);
5247258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
5257258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
5267258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
5277258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5287258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	enable_irq(dsim->irq);
5297258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5307258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (!dsim->suspended)
5317258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		return 0;
5327258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5337258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* lcd panel power on. */
5347258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (client_drv && client_drv->power_on)
5357258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		client_drv->power_on(client_dev, 1);
5367258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5377258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_regulator_enable(dsim);
5387258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5397258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* enable MIPI-DSI PHY. */
5407e0be9f9f7cba3356f75b86737dbe3a005da067eSylwester Nawrocki	phy_power_on(dsim->phy);
5417258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5427258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	clk_enable(dsim->clock);
5437258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5447258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	exynos_mipi_update_cfg(dsim);
5457258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5467258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	/* set lcd panel sequence commands. */
5477258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	if (client_drv && client_drv->set_sequence)
5487258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		client_drv->set_sequence(client_dev);
5497258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5507258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	dsim->suspended = false;
5517258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5527258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	return 0;
5537258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee}
5547258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee#endif
5557258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5563bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrockistatic const struct dev_pm_ops exynos_mipi_dsi_pm_ops = {
5573bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrocki	SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume)
5583bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrocki};
5593bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrocki
5607258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leestatic struct platform_driver exynos_mipi_dsi_driver = {
5617258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	.probe = exynos_mipi_dsi_probe,
56248c68c4f1b542444f175a9e136febcecf3e704d8Greg Kroah-Hartman	.remove = exynos_mipi_dsi_remove,
5637258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	.driver = {
5647258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		   .name = "exynos-mipi-dsim",
5657258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee		   .owner = THIS_MODULE,
5663bfc9b835a8729f8a44de56930c1652293cfbf57Sylwester Nawrocki		   .pm = &exynos_mipi_dsi_pm_ops,
5677258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee	},
5687258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee};
5697258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5707258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Leemodule_platform_driver(exynos_mipi_dsi_driver);
5717258cc14f310b912b6fea5421aedb9beb69d8581Donghwa Lee
5727258cc14f310b912b6fea5421aedb9beb69d8581Donghwa LeeMODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
5737258cc14f310b912b6fea5421aedb9beb69d8581Donghwa LeeMODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
5747258cc14f310b912b6fea5421aedb9beb69d8581Donghwa LeeMODULE_LICENSE("GPL");
575