diff options
Diffstat (limited to 'drivers/video/fbdev/omap2/dss/dss.c')
-rw-r--r-- | drivers/video/fbdev/omap2/dss/dss.c | 123 |
1 files changed, 86 insertions, 37 deletions
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c index 14bcd6c43f72..702c495083ed 100644 --- a/drivers/video/fbdev/omap2/dss/dss.c +++ b/drivers/video/fbdev/omap2/dss/dss.c @@ -70,7 +70,9 @@ struct dss_features { u8 fck_div_max; u8 dss_fck_multiplier; const char *parent_clk_name; - int (*dpi_select_source)(enum omap_channel channel); + enum omap_display_type *ports; + int num_ports; + int (*dpi_select_source)(int port, enum omap_channel channel); }; static struct { @@ -294,7 +296,6 @@ static void dss_dump_regs(struct seq_file *s) static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) { - struct platform_device *dsidev; int b; u8 start, end; @@ -304,13 +305,9 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) break; case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: b = 1; - dsidev = dsi_get_dsidev_from_id(0); - dsi_wait_pll_hsdiv_dispc_active(dsidev); break; case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: b = 2; - dsidev = dsi_get_dsidev_from_id(1); - dsi_wait_pll_hsdiv_dispc_active(dsidev); break; default: BUG(); @@ -327,7 +324,6 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) void dss_select_dsi_clk_source(int dsi_module, enum omap_dss_clk_source clk_src) { - struct platform_device *dsidev; int b, pos; switch (clk_src) { @@ -337,14 +333,10 @@ void dss_select_dsi_clk_source(int dsi_module, case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: BUG_ON(dsi_module != 0); b = 1; - dsidev = dsi_get_dsidev_from_id(0); - dsi_wait_pll_hsdiv_dsi_active(dsidev); break; case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI: BUG_ON(dsi_module != 1); b = 1; - dsidev = dsi_get_dsidev_from_id(1); - dsi_wait_pll_hsdiv_dsi_active(dsidev); break; default: BUG(); @@ -360,7 +352,6 @@ void dss_select_dsi_clk_source(int dsi_module, void dss_select_lcd_clk_source(enum omap_channel channel, enum omap_dss_clk_source clk_src) { - struct platform_device *dsidev; int b, ix, pos; if (!dss_has_feature(FEAT_LCD_CLK_SRC)) { @@ -375,15 +366,11 @@ void dss_select_lcd_clk_source(enum omap_channel channel, case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); b = 1; - dsidev = dsi_get_dsidev_from_id(0); - dsi_wait_pll_hsdiv_dispc_active(dsidev); break; case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 && channel != OMAP_DSS_CHANNEL_LCD3); b = 1; - dsidev = dsi_get_dsidev_from_id(1); - dsi_wait_pll_hsdiv_dispc_active(dsidev); break; default: BUG(); @@ -564,7 +551,7 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) return REG_GET(DSS_CONTROL, 15, 15); } -static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel) +static int dss_dpi_select_source_omap2_omap3(int port, enum omap_channel channel) { if (channel != OMAP_DSS_CHANNEL_LCD) return -EINVAL; @@ -572,7 +559,7 @@ static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel) return 0; } -static int dss_dpi_select_source_omap4(enum omap_channel channel) +static int dss_dpi_select_source_omap4(int port, enum omap_channel channel) { int val; @@ -592,7 +579,7 @@ static int dss_dpi_select_source_omap4(enum omap_channel channel) return 0; } -static int dss_dpi_select_source_omap5(enum omap_channel channel) +static int dss_dpi_select_source_omap5(int port, enum omap_channel channel) { int val; @@ -618,9 +605,9 @@ static int dss_dpi_select_source_omap5(enum omap_channel channel) return 0; } -int dss_dpi_select_source(enum omap_channel channel) +int dss_dpi_select_source(int port, enum omap_channel channel) { - return dss.feat->dpi_select_source(channel); + return dss.feat->dpi_select_source(port, channel); } static int dss_get_clocks(void) @@ -689,6 +676,16 @@ void dss_debug_dump_clocks(struct seq_file *s) } #endif + +static enum omap_display_type omap2plus_ports[] = { + OMAP_DISPLAY_TYPE_DPI, +}; + +static enum omap_display_type omap34xx_ports[] = { + OMAP_DISPLAY_TYPE_DPI, + OMAP_DISPLAY_TYPE_SDI, +}; + static const struct dss_features omap24xx_dss_feats __initconst = { /* * fck div max is really 16, but the divider range has gaps. The range @@ -698,6 +695,8 @@ static const struct dss_features omap24xx_dss_feats __initconst = { .dss_fck_multiplier = 2, .parent_clk_name = "core_ck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, + .ports = omap2plus_ports, + .num_ports = ARRAY_SIZE(omap2plus_ports), }; static const struct dss_features omap34xx_dss_feats __initconst = { @@ -705,6 +704,8 @@ static const struct dss_features omap34xx_dss_feats __initconst = { .dss_fck_multiplier = 2, .parent_clk_name = "dpll4_ck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, + .ports = omap34xx_ports, + .num_ports = ARRAY_SIZE(omap34xx_ports), }; static const struct dss_features omap3630_dss_feats __initconst = { @@ -712,6 +713,8 @@ static const struct dss_features omap3630_dss_feats __initconst = { .dss_fck_multiplier = 1, .parent_clk_name = "dpll4_ck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, + .ports = omap2plus_ports, + .num_ports = ARRAY_SIZE(omap2plus_ports), }; static const struct dss_features omap44xx_dss_feats __initconst = { @@ -719,6 +722,8 @@ static const struct dss_features omap44xx_dss_feats __initconst = { .dss_fck_multiplier = 1, .parent_clk_name = "dpll_per_x2_ck", .dpi_select_source = &dss_dpi_select_source_omap4, + .ports = omap2plus_ports, + .num_ports = ARRAY_SIZE(omap2plus_ports), }; static const struct dss_features omap54xx_dss_feats __initconst = { @@ -726,6 +731,8 @@ static const struct dss_features omap54xx_dss_feats __initconst = { .dss_fck_multiplier = 1, .parent_clk_name = "dpll_per_x2_ck", .dpi_select_source = &dss_dpi_select_source_omap5, + .ports = omap2plus_ports, + .num_ports = ARRAY_SIZE(omap2plus_ports), }; static const struct dss_features am43xx_dss_feats __initconst = { @@ -733,6 +740,8 @@ static const struct dss_features am43xx_dss_feats __initconst = { .dss_fck_multiplier = 0, .parent_clk_name = NULL, .dpi_select_source = &dss_dpi_select_source_omap2_omap3, + .ports = omap2plus_ports, + .num_ports = ARRAY_SIZE(omap2plus_ports), }; static int __init dss_init_features(struct platform_device *pdev) @@ -798,37 +807,77 @@ static int __init dss_init_ports(struct platform_device *pdev) if (!port) return 0; + if (dss.feat->num_ports == 0) + return 0; + do { + enum omap_display_type port_type; u32 reg; r = of_property_read_u32(port, "reg", ®); if (r) reg = 0; -#ifdef CONFIG_OMAP2_DSS_DPI - if (reg == 0) - dpi_init_port(pdev, port); -#endif + if (reg >= dss.feat->num_ports) + continue; -#ifdef CONFIG_OMAP2_DSS_SDI - if (reg == 1) - sdi_init_port(pdev, port); -#endif + port_type = dss.feat->ports[reg]; + switch (port_type) { + case OMAP_DISPLAY_TYPE_DPI: + dpi_init_port(pdev, port); + break; + case OMAP_DISPLAY_TYPE_SDI: + sdi_init_port(pdev, port); + break; + default: + break; + } } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); return 0; } -static void __exit dss_uninit_ports(void) +static void __exit dss_uninit_ports(struct platform_device *pdev) { -#ifdef CONFIG_OMAP2_DSS_DPI - dpi_uninit_port(); -#endif + struct device_node *parent = pdev->dev.of_node; + struct device_node *port; -#ifdef CONFIG_OMAP2_DSS_SDI - sdi_uninit_port(); -#endif + if (parent == NULL) + return; + + port = omapdss_of_get_next_port(parent, NULL); + if (!port) + return; + + if (dss.feat->num_ports == 0) + return; + + do { + enum omap_display_type port_type; + u32 reg; + int r; + + r = of_property_read_u32(port, "reg", ®); + if (r) + reg = 0; + + if (reg >= dss.feat->num_ports) + continue; + + port_type = dss.feat->ports[reg]; + + switch (port_type) { + case OMAP_DISPLAY_TYPE_DPI: + dpi_uninit_port(port); + break; + case OMAP_DISPLAY_TYPE_SDI: + sdi_uninit_port(port); + break; + default: + break; + } + } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); } /* DSS HW IP initialisation */ @@ -910,7 +959,7 @@ err_setup_clocks: static int __exit omap_dsshw_remove(struct platform_device *pdev) { - dss_uninit_ports(); + dss_uninit_ports(pdev); pm_runtime_disable(&pdev->dev); |