18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * OMAP2plus display device setup / initialization.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com/
58c2ecf20Sopenharmony_ci *	Senthilvadivu Guruswamy
68c2ecf20Sopenharmony_ci *	Sumit Semwal
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify
98c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as
108c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * This program is distributed "as is" WITHOUT ANY WARRANTY of any
138c2ecf20Sopenharmony_ci * kind, whether express or implied; without even the implied warranty
148c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
158c2ecf20Sopenharmony_ci * GNU General Public License for more details.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/string.h>
198c2ecf20Sopenharmony_ci#include <linux/kernel.h>
208c2ecf20Sopenharmony_ci#include <linux/init.h>
218c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
228c2ecf20Sopenharmony_ci#include <linux/io.h>
238c2ecf20Sopenharmony_ci#include <linux/clk.h>
248c2ecf20Sopenharmony_ci#include <linux/err.h>
258c2ecf20Sopenharmony_ci#include <linux/delay.h>
268c2ecf20Sopenharmony_ci#include <linux/of.h>
278c2ecf20Sopenharmony_ci#include <linux/of_platform.h>
288c2ecf20Sopenharmony_ci#include <linux/slab.h>
298c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h>
308c2ecf20Sopenharmony_ci#include <linux/regmap.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#include <linux/platform_data/omapdss.h>
338c2ecf20Sopenharmony_ci#include "omap_hwmod.h"
348c2ecf20Sopenharmony_ci#include "omap_device.h"
358c2ecf20Sopenharmony_ci#include "common.h"
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include "soc.h"
388c2ecf20Sopenharmony_ci#include "iomap.h"
398c2ecf20Sopenharmony_ci#include "control.h"
408c2ecf20Sopenharmony_ci#include "display.h"
418c2ecf20Sopenharmony_ci#include "prm.h"
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define DISPC_CONTROL		0x0040
448c2ecf20Sopenharmony_ci#define DISPC_CONTROL2		0x0238
458c2ecf20Sopenharmony_ci#define DISPC_CONTROL3		0x0848
468c2ecf20Sopenharmony_ci#define DISPC_IRQSTATUS		0x0018
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define DSS_CONTROL		0x40
498c2ecf20Sopenharmony_ci#define DSS_SDI_CONTROL		0x44
508c2ecf20Sopenharmony_ci#define DSS_PLL_CONTROL		0x48
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#define LCD_EN_MASK		(0x1 << 0)
538c2ecf20Sopenharmony_ci#define DIGIT_EN_MASK		(0x1 << 1)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define FRAMEDONE_IRQ_SHIFT	0
568c2ecf20Sopenharmony_ci#define EVSYNC_EVEN_IRQ_SHIFT	2
578c2ecf20Sopenharmony_ci#define EVSYNC_ODD_IRQ_SHIFT	3
588c2ecf20Sopenharmony_ci#define FRAMEDONE2_IRQ_SHIFT	22
598c2ecf20Sopenharmony_ci#define FRAMEDONE3_IRQ_SHIFT	30
608c2ecf20Sopenharmony_ci#define FRAMEDONETV_IRQ_SHIFT	24
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/*
638c2ecf20Sopenharmony_ci * FRAMEDONE_IRQ_TIMEOUT: how long (in milliseconds) to wait during DISPC
648c2ecf20Sopenharmony_ci *     reset before deciding that something has gone wrong
658c2ecf20Sopenharmony_ci */
668c2ecf20Sopenharmony_ci#define FRAMEDONE_IRQ_TIMEOUT		100
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci#if defined(CONFIG_FB_OMAP2)
698c2ecf20Sopenharmony_cistatic struct platform_device omap_display_device = {
708c2ecf20Sopenharmony_ci	.name          = "omapdss",
718c2ecf20Sopenharmony_ci	.id            = -1,
728c2ecf20Sopenharmony_ci	.dev            = {
738c2ecf20Sopenharmony_ci		.platform_data = NULL,
748c2ecf20Sopenharmony_ci	},
758c2ecf20Sopenharmony_ci};
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#define OMAP4_DSIPHY_SYSCON_OFFSET		0x78
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic struct regmap *omap4_dsi_mux_syscon;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	u32 enable_mask, enable_shift;
848c2ecf20Sopenharmony_ci	u32 pipd_mask, pipd_shift;
858c2ecf20Sopenharmony_ci	u32 reg;
868c2ecf20Sopenharmony_ci	int ret;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	if (dsi_id == 0) {
898c2ecf20Sopenharmony_ci		enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
908c2ecf20Sopenharmony_ci		enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
918c2ecf20Sopenharmony_ci		pipd_mask = OMAP4_DSI1_PIPD_MASK;
928c2ecf20Sopenharmony_ci		pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
938c2ecf20Sopenharmony_ci	} else if (dsi_id == 1) {
948c2ecf20Sopenharmony_ci		enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
958c2ecf20Sopenharmony_ci		enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
968c2ecf20Sopenharmony_ci		pipd_mask = OMAP4_DSI2_PIPD_MASK;
978c2ecf20Sopenharmony_ci		pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
988c2ecf20Sopenharmony_ci	} else {
998c2ecf20Sopenharmony_ci		return -ENODEV;
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	ret = regmap_read(omap4_dsi_mux_syscon,
1038c2ecf20Sopenharmony_ci					  OMAP4_DSIPHY_SYSCON_OFFSET,
1048c2ecf20Sopenharmony_ci					  &reg);
1058c2ecf20Sopenharmony_ci	if (ret)
1068c2ecf20Sopenharmony_ci		return ret;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	reg &= ~enable_mask;
1098c2ecf20Sopenharmony_ci	reg &= ~pipd_mask;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	reg |= (lanes << enable_shift) & enable_mask;
1128c2ecf20Sopenharmony_ci	reg |= (lanes << pipd_shift) & pipd_mask;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	regmap_write(omap4_dsi_mux_syscon, OMAP4_DSIPHY_SYSCON_OFFSET, reg);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	return 0;
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistatic int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	if (cpu_is_omap44xx())
1228c2ecf20Sopenharmony_ci		return omap4_dsi_mux_pads(dsi_id, lane_mask);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	return 0;
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	if (cpu_is_omap44xx())
1308c2ecf20Sopenharmony_ci		omap4_dsi_mux_pads(dsi_id, 0);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic enum omapdss_version __init omap_display_get_version(void)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	if (cpu_is_omap24xx())
1368c2ecf20Sopenharmony_ci		return OMAPDSS_VER_OMAP24xx;
1378c2ecf20Sopenharmony_ci	else if (cpu_is_omap3630())
1388c2ecf20Sopenharmony_ci		return OMAPDSS_VER_OMAP3630;
1398c2ecf20Sopenharmony_ci	else if (cpu_is_omap34xx()) {
1408c2ecf20Sopenharmony_ci		if (soc_is_am35xx()) {
1418c2ecf20Sopenharmony_ci			return OMAPDSS_VER_AM35xx;
1428c2ecf20Sopenharmony_ci		} else {
1438c2ecf20Sopenharmony_ci			if (omap_rev() < OMAP3430_REV_ES3_0)
1448c2ecf20Sopenharmony_ci				return OMAPDSS_VER_OMAP34xx_ES1;
1458c2ecf20Sopenharmony_ci			else
1468c2ecf20Sopenharmony_ci				return OMAPDSS_VER_OMAP34xx_ES3;
1478c2ecf20Sopenharmony_ci		}
1488c2ecf20Sopenharmony_ci	} else if (omap_rev() == OMAP4430_REV_ES1_0)
1498c2ecf20Sopenharmony_ci		return OMAPDSS_VER_OMAP4430_ES1;
1508c2ecf20Sopenharmony_ci	else if (omap_rev() == OMAP4430_REV_ES2_0 ||
1518c2ecf20Sopenharmony_ci			omap_rev() == OMAP4430_REV_ES2_1 ||
1528c2ecf20Sopenharmony_ci			omap_rev() == OMAP4430_REV_ES2_2)
1538c2ecf20Sopenharmony_ci		return OMAPDSS_VER_OMAP4430_ES2;
1548c2ecf20Sopenharmony_ci	else if (cpu_is_omap44xx())
1558c2ecf20Sopenharmony_ci		return OMAPDSS_VER_OMAP4;
1568c2ecf20Sopenharmony_ci	else if (soc_is_omap54xx())
1578c2ecf20Sopenharmony_ci		return OMAPDSS_VER_OMAP5;
1588c2ecf20Sopenharmony_ci	else if (soc_is_am43xx())
1598c2ecf20Sopenharmony_ci		return OMAPDSS_VER_AM43xx;
1608c2ecf20Sopenharmony_ci	else if (soc_is_dra7xx())
1618c2ecf20Sopenharmony_ci		return OMAPDSS_VER_DRA7xx;
1628c2ecf20Sopenharmony_ci	else
1638c2ecf20Sopenharmony_ci		return OMAPDSS_VER_UNKNOWN;
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic int __init omapdss_init_fbdev(void)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	static struct omap_dss_board_info board_data = {
1698c2ecf20Sopenharmony_ci		.dsi_enable_pads = omap_dsi_enable_pads,
1708c2ecf20Sopenharmony_ci		.dsi_disable_pads = omap_dsi_disable_pads,
1718c2ecf20Sopenharmony_ci	};
1728c2ecf20Sopenharmony_ci	struct device_node *node;
1738c2ecf20Sopenharmony_ci	int r;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	board_data.version = omap_display_get_version();
1768c2ecf20Sopenharmony_ci	if (board_data.version == OMAPDSS_VER_UNKNOWN) {
1778c2ecf20Sopenharmony_ci		pr_err("DSS not supported on this SoC\n");
1788c2ecf20Sopenharmony_ci		return -ENODEV;
1798c2ecf20Sopenharmony_ci	}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	omap_display_device.dev.platform_data = &board_data;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	r = platform_device_register(&omap_display_device);
1848c2ecf20Sopenharmony_ci	if (r < 0) {
1858c2ecf20Sopenharmony_ci		pr_err("Unable to register omapdss device\n");
1868c2ecf20Sopenharmony_ci		return r;
1878c2ecf20Sopenharmony_ci	}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	/* create vrfb device */
1908c2ecf20Sopenharmony_ci	r = omap_init_vrfb();
1918c2ecf20Sopenharmony_ci	if (r < 0) {
1928c2ecf20Sopenharmony_ci		pr_err("Unable to register omapvrfb device\n");
1938c2ecf20Sopenharmony_ci		return r;
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	/* create FB device */
1978c2ecf20Sopenharmony_ci	r = omap_init_fb();
1988c2ecf20Sopenharmony_ci	if (r < 0) {
1998c2ecf20Sopenharmony_ci		pr_err("Unable to register omapfb device\n");
2008c2ecf20Sopenharmony_ci		return r;
2018c2ecf20Sopenharmony_ci	}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	/* create V4L2 display device */
2048c2ecf20Sopenharmony_ci	r = omap_init_vout();
2058c2ecf20Sopenharmony_ci	if (r < 0) {
2068c2ecf20Sopenharmony_ci		pr_err("Unable to register omap_vout device\n");
2078c2ecf20Sopenharmony_ci		return r;
2088c2ecf20Sopenharmony_ci	}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	/* add DSI info for omap4 */
2118c2ecf20Sopenharmony_ci	node = of_find_node_by_name(NULL, "omap4_padconf_global");
2128c2ecf20Sopenharmony_ci	if (node)
2138c2ecf20Sopenharmony_ci		omap4_dsi_mux_syscon = syscon_node_to_regmap(node);
2148c2ecf20Sopenharmony_ci	of_node_put(node);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	return 0;
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cistatic const char * const omapdss_compat_names[] __initconst = {
2208c2ecf20Sopenharmony_ci	"ti,omap2-dss",
2218c2ecf20Sopenharmony_ci	"ti,omap3-dss",
2228c2ecf20Sopenharmony_ci	"ti,omap4-dss",
2238c2ecf20Sopenharmony_ci	"ti,omap5-dss",
2248c2ecf20Sopenharmony_ci	"ti,dra7-dss",
2258c2ecf20Sopenharmony_ci};
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic struct device_node * __init omapdss_find_dss_of_node(void)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	struct device_node *node;
2308c2ecf20Sopenharmony_ci	int i;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(omapdss_compat_names); ++i) {
2338c2ecf20Sopenharmony_ci		node = of_find_compatible_node(NULL, NULL,
2348c2ecf20Sopenharmony_ci			omapdss_compat_names[i]);
2358c2ecf20Sopenharmony_ci		if (node)
2368c2ecf20Sopenharmony_ci			return node;
2378c2ecf20Sopenharmony_ci	}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	return NULL;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic int __init omapdss_init_of(void)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	int r;
2458c2ecf20Sopenharmony_ci	struct device_node *node;
2468c2ecf20Sopenharmony_ci	struct platform_device *pdev;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	/* only create dss helper devices if dss is enabled in the .dts */
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	node = omapdss_find_dss_of_node();
2518c2ecf20Sopenharmony_ci	if (!node)
2528c2ecf20Sopenharmony_ci		return 0;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (!of_device_is_available(node)) {
2558c2ecf20Sopenharmony_ci		of_node_put(node);
2568c2ecf20Sopenharmony_ci		return 0;
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	pdev = of_find_device_by_node(node);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	if (!pdev) {
2628c2ecf20Sopenharmony_ci		pr_err("Unable to find DSS platform device\n");
2638c2ecf20Sopenharmony_ci		of_node_put(node);
2648c2ecf20Sopenharmony_ci		return -ENODEV;
2658c2ecf20Sopenharmony_ci	}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	r = of_platform_populate(node, NULL, NULL, &pdev->dev);
2688c2ecf20Sopenharmony_ci	put_device(&pdev->dev);
2698c2ecf20Sopenharmony_ci	of_node_put(node);
2708c2ecf20Sopenharmony_ci	if (r) {
2718c2ecf20Sopenharmony_ci		pr_err("Unable to populate DSS submodule devices\n");
2728c2ecf20Sopenharmony_ci		return r;
2738c2ecf20Sopenharmony_ci	}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	return omapdss_init_fbdev();
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ciomap_device_initcall(omapdss_init_of);
2788c2ecf20Sopenharmony_ci#endif /* CONFIG_FB_OMAP2 */
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic void dispc_disable_outputs(void)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	u32 v, irq_mask = 0;
2838c2ecf20Sopenharmony_ci	bool lcd_en, digit_en, lcd2_en = false, lcd3_en = false;
2848c2ecf20Sopenharmony_ci	int i;
2858c2ecf20Sopenharmony_ci	struct omap_dss_dispc_dev_attr *da;
2868c2ecf20Sopenharmony_ci	struct omap_hwmod *oh;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	oh = omap_hwmod_lookup("dss_dispc");
2898c2ecf20Sopenharmony_ci	if (!oh) {
2908c2ecf20Sopenharmony_ci		WARN(1, "display: could not disable outputs during reset - could not find dss_dispc hwmod\n");
2918c2ecf20Sopenharmony_ci		return;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (!oh->dev_attr) {
2958c2ecf20Sopenharmony_ci		pr_err("display: could not disable outputs during reset due to missing dev_attr\n");
2968c2ecf20Sopenharmony_ci		return;
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	da = (struct omap_dss_dispc_dev_attr *)oh->dev_attr;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	/* store value of LCDENABLE and DIGITENABLE bits */
3028c2ecf20Sopenharmony_ci	v = omap_hwmod_read(oh, DISPC_CONTROL);
3038c2ecf20Sopenharmony_ci	lcd_en = v & LCD_EN_MASK;
3048c2ecf20Sopenharmony_ci	digit_en = v & DIGIT_EN_MASK;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	/* store value of LCDENABLE for LCD2 */
3078c2ecf20Sopenharmony_ci	if (da->manager_count > 2) {
3088c2ecf20Sopenharmony_ci		v = omap_hwmod_read(oh, DISPC_CONTROL2);
3098c2ecf20Sopenharmony_ci		lcd2_en = v & LCD_EN_MASK;
3108c2ecf20Sopenharmony_ci	}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	/* store value of LCDENABLE for LCD3 */
3138c2ecf20Sopenharmony_ci	if (da->manager_count > 3) {
3148c2ecf20Sopenharmony_ci		v = omap_hwmod_read(oh, DISPC_CONTROL3);
3158c2ecf20Sopenharmony_ci		lcd3_en = v & LCD_EN_MASK;
3168c2ecf20Sopenharmony_ci	}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	if (!(lcd_en | digit_en | lcd2_en | lcd3_en))
3198c2ecf20Sopenharmony_ci		return; /* no managers currently enabled */
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	/*
3228c2ecf20Sopenharmony_ci	 * If any manager was enabled, we need to disable it before
3238c2ecf20Sopenharmony_ci	 * DSS clocks are disabled or DISPC module is reset
3248c2ecf20Sopenharmony_ci	 */
3258c2ecf20Sopenharmony_ci	if (lcd_en)
3268c2ecf20Sopenharmony_ci		irq_mask |= 1 << FRAMEDONE_IRQ_SHIFT;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	if (digit_en) {
3298c2ecf20Sopenharmony_ci		if (da->has_framedonetv_irq) {
3308c2ecf20Sopenharmony_ci			irq_mask |= 1 << FRAMEDONETV_IRQ_SHIFT;
3318c2ecf20Sopenharmony_ci		} else {
3328c2ecf20Sopenharmony_ci			irq_mask |= 1 << EVSYNC_EVEN_IRQ_SHIFT |
3338c2ecf20Sopenharmony_ci				1 << EVSYNC_ODD_IRQ_SHIFT;
3348c2ecf20Sopenharmony_ci		}
3358c2ecf20Sopenharmony_ci	}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	if (lcd2_en)
3388c2ecf20Sopenharmony_ci		irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT;
3398c2ecf20Sopenharmony_ci	if (lcd3_en)
3408c2ecf20Sopenharmony_ci		irq_mask |= 1 << FRAMEDONE3_IRQ_SHIFT;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	/*
3438c2ecf20Sopenharmony_ci	 * clear any previous FRAMEDONE, FRAMEDONETV,
3448c2ecf20Sopenharmony_ci	 * EVSYNC_EVEN/ODD, FRAMEDONE2 or FRAMEDONE3 interrupts
3458c2ecf20Sopenharmony_ci	 */
3468c2ecf20Sopenharmony_ci	omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	/* disable LCD and TV managers */
3498c2ecf20Sopenharmony_ci	v = omap_hwmod_read(oh, DISPC_CONTROL);
3508c2ecf20Sopenharmony_ci	v &= ~(LCD_EN_MASK | DIGIT_EN_MASK);
3518c2ecf20Sopenharmony_ci	omap_hwmod_write(v, oh, DISPC_CONTROL);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	/* disable LCD2 manager */
3548c2ecf20Sopenharmony_ci	if (da->manager_count > 2) {
3558c2ecf20Sopenharmony_ci		v = omap_hwmod_read(oh, DISPC_CONTROL2);
3568c2ecf20Sopenharmony_ci		v &= ~LCD_EN_MASK;
3578c2ecf20Sopenharmony_ci		omap_hwmod_write(v, oh, DISPC_CONTROL2);
3588c2ecf20Sopenharmony_ci	}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	/* disable LCD3 manager */
3618c2ecf20Sopenharmony_ci	if (da->manager_count > 3) {
3628c2ecf20Sopenharmony_ci		v = omap_hwmod_read(oh, DISPC_CONTROL3);
3638c2ecf20Sopenharmony_ci		v &= ~LCD_EN_MASK;
3648c2ecf20Sopenharmony_ci		omap_hwmod_write(v, oh, DISPC_CONTROL3);
3658c2ecf20Sopenharmony_ci	}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	i = 0;
3688c2ecf20Sopenharmony_ci	while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) !=
3698c2ecf20Sopenharmony_ci	       irq_mask) {
3708c2ecf20Sopenharmony_ci		i++;
3718c2ecf20Sopenharmony_ci		if (i > FRAMEDONE_IRQ_TIMEOUT) {
3728c2ecf20Sopenharmony_ci			pr_err("didn't get FRAMEDONE1/2/3 or TV interrupt\n");
3738c2ecf20Sopenharmony_ci			break;
3748c2ecf20Sopenharmony_ci		}
3758c2ecf20Sopenharmony_ci		mdelay(1);
3768c2ecf20Sopenharmony_ci	}
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ciint omap_dss_reset(struct omap_hwmod *oh)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	struct omap_hwmod_opt_clk *oc;
3828c2ecf20Sopenharmony_ci	int c = 0;
3838c2ecf20Sopenharmony_ci	int i, r;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	if (!(oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)) {
3868c2ecf20Sopenharmony_ci		pr_err("dss_core: hwmod data doesn't contain reset data\n");
3878c2ecf20Sopenharmony_ci		return -EINVAL;
3888c2ecf20Sopenharmony_ci	}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
3918c2ecf20Sopenharmony_ci		if (oc->_clk)
3928c2ecf20Sopenharmony_ci			clk_prepare_enable(oc->_clk);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	dispc_disable_outputs();
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	/* clear SDI registers */
3978c2ecf20Sopenharmony_ci	if (cpu_is_omap3430()) {
3988c2ecf20Sopenharmony_ci		omap_hwmod_write(0x0, oh, DSS_SDI_CONTROL);
3998c2ecf20Sopenharmony_ci		omap_hwmod_write(0x0, oh, DSS_PLL_CONTROL);
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	/*
4038c2ecf20Sopenharmony_ci	 * clear DSS_CONTROL register to switch DSS clock sources to
4048c2ecf20Sopenharmony_ci	 * PRCM clock, if any
4058c2ecf20Sopenharmony_ci	 */
4068c2ecf20Sopenharmony_ci	omap_hwmod_write(0x0, oh, DSS_CONTROL);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
4098c2ecf20Sopenharmony_ci				& SYSS_RESETDONE_MASK),
4108c2ecf20Sopenharmony_ci			MAX_MODULE_SOFTRESET_WAIT, c);
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	if (c == MAX_MODULE_SOFTRESET_WAIT)
4138c2ecf20Sopenharmony_ci		pr_warn("dss_core: waiting for reset to finish failed\n");
4148c2ecf20Sopenharmony_ci	else
4158c2ecf20Sopenharmony_ci		pr_debug("dss_core: softreset done\n");
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
4188c2ecf20Sopenharmony_ci		if (oc->_clk)
4198c2ecf20Sopenharmony_ci			clk_disable_unprepare(oc->_clk);
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	return r;
4248c2ecf20Sopenharmony_ci}
425