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 ®); 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