Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * OMAP2plus display device setup / initialization.
0004  *
0005  * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com/
0006  *  Senthilvadivu Guruswamy
0007  *  Sumit Semwal
0008  */
0009 
0010 #include <linux/string.h>
0011 #include <linux/kernel.h>
0012 #include <linux/init.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/io.h>
0015 #include <linux/clk.h>
0016 #include <linux/err.h>
0017 #include <linux/delay.h>
0018 #include <linux/of.h>
0019 #include <linux/of_platform.h>
0020 #include <linux/slab.h>
0021 #include <linux/mfd/syscon.h>
0022 #include <linux/regmap.h>
0023 
0024 #include <linux/platform_data/omapdss.h>
0025 #include "omap_hwmod.h"
0026 #include "omap_device.h"
0027 #include "common.h"
0028 
0029 #include "soc.h"
0030 #include "iomap.h"
0031 #include "control.h"
0032 #include "display.h"
0033 #include "prm.h"
0034 
0035 #define DISPC_CONTROL       0x0040
0036 #define DISPC_CONTROL2      0x0238
0037 #define DISPC_CONTROL3      0x0848
0038 #define DISPC_IRQSTATUS     0x0018
0039 
0040 #define DSS_CONTROL     0x40
0041 #define DSS_SDI_CONTROL     0x44
0042 #define DSS_PLL_CONTROL     0x48
0043 
0044 #define LCD_EN_MASK     (0x1 << 0)
0045 #define DIGIT_EN_MASK       (0x1 << 1)
0046 
0047 #define FRAMEDONE_IRQ_SHIFT 0
0048 #define EVSYNC_EVEN_IRQ_SHIFT   2
0049 #define EVSYNC_ODD_IRQ_SHIFT    3
0050 #define FRAMEDONE2_IRQ_SHIFT    22
0051 #define FRAMEDONE3_IRQ_SHIFT    30
0052 #define FRAMEDONETV_IRQ_SHIFT   24
0053 
0054 /*
0055  * FRAMEDONE_IRQ_TIMEOUT: how long (in milliseconds) to wait during DISPC
0056  *     reset before deciding that something has gone wrong
0057  */
0058 #define FRAMEDONE_IRQ_TIMEOUT       100
0059 
0060 #if defined(CONFIG_FB_OMAP2)
0061 static struct platform_device omap_display_device = {
0062     .name          = "omapdss",
0063     .id            = -1,
0064     .dev            = {
0065         .platform_data = NULL,
0066     },
0067 };
0068 
0069 #define OMAP4_DSIPHY_SYSCON_OFFSET      0x78
0070 
0071 static struct regmap *omap4_dsi_mux_syscon;
0072 
0073 static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
0074 {
0075     u32 enable_mask, enable_shift;
0076     u32 pipd_mask, pipd_shift;
0077     u32 reg;
0078     int ret;
0079 
0080     if (dsi_id == 0) {
0081         enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
0082         enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
0083         pipd_mask = OMAP4_DSI1_PIPD_MASK;
0084         pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
0085     } else if (dsi_id == 1) {
0086         enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
0087         enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
0088         pipd_mask = OMAP4_DSI2_PIPD_MASK;
0089         pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
0090     } else {
0091         return -ENODEV;
0092     }
0093 
0094     ret = regmap_read(omap4_dsi_mux_syscon,
0095                       OMAP4_DSIPHY_SYSCON_OFFSET,
0096                       &reg);
0097     if (ret)
0098         return ret;
0099 
0100     reg &= ~enable_mask;
0101     reg &= ~pipd_mask;
0102 
0103     reg |= (lanes << enable_shift) & enable_mask;
0104     reg |= (lanes << pipd_shift) & pipd_mask;
0105 
0106     regmap_write(omap4_dsi_mux_syscon, OMAP4_DSIPHY_SYSCON_OFFSET, reg);
0107 
0108     return 0;
0109 }
0110 
0111 static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
0112 {
0113     if (cpu_is_omap44xx())
0114         return omap4_dsi_mux_pads(dsi_id, lane_mask);
0115 
0116     return 0;
0117 }
0118 
0119 static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
0120 {
0121     if (cpu_is_omap44xx())
0122         omap4_dsi_mux_pads(dsi_id, 0);
0123 }
0124 
0125 static enum omapdss_version __init omap_display_get_version(void)
0126 {
0127     if (cpu_is_omap24xx())
0128         return OMAPDSS_VER_OMAP24xx;
0129     else if (cpu_is_omap3630())
0130         return OMAPDSS_VER_OMAP3630;
0131     else if (cpu_is_omap34xx()) {
0132         if (soc_is_am35xx()) {
0133             return OMAPDSS_VER_AM35xx;
0134         } else {
0135             if (omap_rev() < OMAP3430_REV_ES3_0)
0136                 return OMAPDSS_VER_OMAP34xx_ES1;
0137             else
0138                 return OMAPDSS_VER_OMAP34xx_ES3;
0139         }
0140     } else if (omap_rev() == OMAP4430_REV_ES1_0)
0141         return OMAPDSS_VER_OMAP4430_ES1;
0142     else if (omap_rev() == OMAP4430_REV_ES2_0 ||
0143             omap_rev() == OMAP4430_REV_ES2_1 ||
0144             omap_rev() == OMAP4430_REV_ES2_2)
0145         return OMAPDSS_VER_OMAP4430_ES2;
0146     else if (cpu_is_omap44xx())
0147         return OMAPDSS_VER_OMAP4;
0148     else if (soc_is_omap54xx())
0149         return OMAPDSS_VER_OMAP5;
0150     else if (soc_is_am43xx())
0151         return OMAPDSS_VER_AM43xx;
0152     else if (soc_is_dra7xx())
0153         return OMAPDSS_VER_DRA7xx;
0154     else
0155         return OMAPDSS_VER_UNKNOWN;
0156 }
0157 
0158 static int __init omapdss_init_fbdev(void)
0159 {
0160     static struct omap_dss_board_info board_data = {
0161         .dsi_enable_pads = omap_dsi_enable_pads,
0162         .dsi_disable_pads = omap_dsi_disable_pads,
0163     };
0164     struct device_node *node;
0165     int r;
0166 
0167     board_data.version = omap_display_get_version();
0168     if (board_data.version == OMAPDSS_VER_UNKNOWN) {
0169         pr_err("DSS not supported on this SoC\n");
0170         return -ENODEV;
0171     }
0172 
0173     omap_display_device.dev.platform_data = &board_data;
0174 
0175     r = platform_device_register(&omap_display_device);
0176     if (r < 0) {
0177         pr_err("Unable to register omapdss device\n");
0178         return r;
0179     }
0180 
0181     /* create vrfb device */
0182     r = omap_init_vrfb();
0183     if (r < 0) {
0184         pr_err("Unable to register omapvrfb device\n");
0185         return r;
0186     }
0187 
0188     /* create FB device */
0189     r = omap_init_fb();
0190     if (r < 0) {
0191         pr_err("Unable to register omapfb device\n");
0192         return r;
0193     }
0194 
0195     /* create V4L2 display device */
0196     r = omap_init_vout();
0197     if (r < 0) {
0198         pr_err("Unable to register omap_vout device\n");
0199         return r;
0200     }
0201 
0202     /* add DSI info for omap4 */
0203     node = of_find_node_by_name(NULL, "omap4_padconf_global");
0204     if (node)
0205         omap4_dsi_mux_syscon = syscon_node_to_regmap(node);
0206     of_node_put(node);
0207 
0208     return 0;
0209 }
0210 
0211 static const char * const omapdss_compat_names[] __initconst = {
0212     "ti,omap2-dss",
0213     "ti,omap3-dss",
0214     "ti,omap4-dss",
0215     "ti,omap5-dss",
0216     "ti,dra7-dss",
0217 };
0218 
0219 static struct device_node * __init omapdss_find_dss_of_node(void)
0220 {
0221     struct device_node *node;
0222     int i;
0223 
0224     for (i = 0; i < ARRAY_SIZE(omapdss_compat_names); ++i) {
0225         node = of_find_compatible_node(NULL, NULL,
0226             omapdss_compat_names[i]);
0227         if (node)
0228             return node;
0229     }
0230 
0231     return NULL;
0232 }
0233 
0234 static int __init omapdss_init_of(void)
0235 {
0236     int r;
0237     struct device_node *node;
0238     struct platform_device *pdev;
0239 
0240     /* only create dss helper devices if dss is enabled in the .dts */
0241 
0242     node = omapdss_find_dss_of_node();
0243     if (!node)
0244         return 0;
0245 
0246     if (!of_device_is_available(node)) {
0247         of_node_put(node);
0248         return 0;
0249     }
0250 
0251     pdev = of_find_device_by_node(node);
0252 
0253     if (!pdev) {
0254         pr_err("Unable to find DSS platform device\n");
0255         of_node_put(node);
0256         return -ENODEV;
0257     }
0258 
0259     r = of_platform_populate(node, NULL, NULL, &pdev->dev);
0260     put_device(&pdev->dev);
0261     of_node_put(node);
0262     if (r) {
0263         pr_err("Unable to populate DSS submodule devices\n");
0264         return r;
0265     }
0266 
0267     return omapdss_init_fbdev();
0268 }
0269 omap_device_initcall(omapdss_init_of);
0270 #endif /* CONFIG_FB_OMAP2 */
0271 
0272 static void dispc_disable_outputs(void)
0273 {
0274     u32 v, irq_mask = 0;
0275     bool lcd_en, digit_en, lcd2_en = false, lcd3_en = false;
0276     int i;
0277     struct omap_dss_dispc_dev_attr *da;
0278     struct omap_hwmod *oh;
0279 
0280     oh = omap_hwmod_lookup("dss_dispc");
0281     if (!oh) {
0282         WARN(1, "display: could not disable outputs during reset - could not find dss_dispc hwmod\n");
0283         return;
0284     }
0285 
0286     if (!oh->dev_attr) {
0287         pr_err("display: could not disable outputs during reset due to missing dev_attr\n");
0288         return;
0289     }
0290 
0291     da = (struct omap_dss_dispc_dev_attr *)oh->dev_attr;
0292 
0293     /* store value of LCDENABLE and DIGITENABLE bits */
0294     v = omap_hwmod_read(oh, DISPC_CONTROL);
0295     lcd_en = v & LCD_EN_MASK;
0296     digit_en = v & DIGIT_EN_MASK;
0297 
0298     /* store value of LCDENABLE for LCD2 */
0299     if (da->manager_count > 2) {
0300         v = omap_hwmod_read(oh, DISPC_CONTROL2);
0301         lcd2_en = v & LCD_EN_MASK;
0302     }
0303 
0304     /* store value of LCDENABLE for LCD3 */
0305     if (da->manager_count > 3) {
0306         v = omap_hwmod_read(oh, DISPC_CONTROL3);
0307         lcd3_en = v & LCD_EN_MASK;
0308     }
0309 
0310     if (!(lcd_en | digit_en | lcd2_en | lcd3_en))
0311         return; /* no managers currently enabled */
0312 
0313     /*
0314      * If any manager was enabled, we need to disable it before
0315      * DSS clocks are disabled or DISPC module is reset
0316      */
0317     if (lcd_en)
0318         irq_mask |= 1 << FRAMEDONE_IRQ_SHIFT;
0319 
0320     if (digit_en) {
0321         if (da->has_framedonetv_irq) {
0322             irq_mask |= 1 << FRAMEDONETV_IRQ_SHIFT;
0323         } else {
0324             irq_mask |= 1 << EVSYNC_EVEN_IRQ_SHIFT |
0325                 1 << EVSYNC_ODD_IRQ_SHIFT;
0326         }
0327     }
0328 
0329     if (lcd2_en)
0330         irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT;
0331     if (lcd3_en)
0332         irq_mask |= 1 << FRAMEDONE3_IRQ_SHIFT;
0333 
0334     /*
0335      * clear any previous FRAMEDONE, FRAMEDONETV,
0336      * EVSYNC_EVEN/ODD, FRAMEDONE2 or FRAMEDONE3 interrupts
0337      */
0338     omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS);
0339 
0340     /* disable LCD and TV managers */
0341     v = omap_hwmod_read(oh, DISPC_CONTROL);
0342     v &= ~(LCD_EN_MASK | DIGIT_EN_MASK);
0343     omap_hwmod_write(v, oh, DISPC_CONTROL);
0344 
0345     /* disable LCD2 manager */
0346     if (da->manager_count > 2) {
0347         v = omap_hwmod_read(oh, DISPC_CONTROL2);
0348         v &= ~LCD_EN_MASK;
0349         omap_hwmod_write(v, oh, DISPC_CONTROL2);
0350     }
0351 
0352     /* disable LCD3 manager */
0353     if (da->manager_count > 3) {
0354         v = omap_hwmod_read(oh, DISPC_CONTROL3);
0355         v &= ~LCD_EN_MASK;
0356         omap_hwmod_write(v, oh, DISPC_CONTROL3);
0357     }
0358 
0359     i = 0;
0360     while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) !=
0361            irq_mask) {
0362         i++;
0363         if (i > FRAMEDONE_IRQ_TIMEOUT) {
0364             pr_err("didn't get FRAMEDONE1/2/3 or TV interrupt\n");
0365             break;
0366         }
0367         mdelay(1);
0368     }
0369 }
0370 
0371 int omap_dss_reset(struct omap_hwmod *oh)
0372 {
0373     struct omap_hwmod_opt_clk *oc;
0374     int c = 0;
0375     int i, r;
0376 
0377     if (!(oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)) {
0378         pr_err("dss_core: hwmod data doesn't contain reset data\n");
0379         return -EINVAL;
0380     }
0381 
0382     for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
0383         clk_prepare_enable(oc->_clk);
0384 
0385     dispc_disable_outputs();
0386 
0387     /* clear SDI registers */
0388     if (cpu_is_omap3430()) {
0389         omap_hwmod_write(0x0, oh, DSS_SDI_CONTROL);
0390         omap_hwmod_write(0x0, oh, DSS_PLL_CONTROL);
0391     }
0392 
0393     /*
0394      * clear DSS_CONTROL register to switch DSS clock sources to
0395      * PRCM clock, if any
0396      */
0397     omap_hwmod_write(0x0, oh, DSS_CONTROL);
0398 
0399     omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
0400                 & SYSS_RESETDONE_MASK),
0401             MAX_MODULE_SOFTRESET_WAIT, c);
0402 
0403     if (c == MAX_MODULE_SOFTRESET_WAIT)
0404         pr_warn("dss_core: waiting for reset to finish failed\n");
0405     else
0406         pr_debug("dss_core: softreset done\n");
0407 
0408     for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
0409         clk_disable_unprepare(oc->_clk);
0410 
0411     r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
0412 
0413     return r;
0414 }