summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev/omap2/dss/dss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbdev/omap2/dss/dss.c')
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.c123
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", &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", &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);