|
@@ -75,6 +75,8 @@ struct dss_features {
|
|
|
const enum omap_display_type *ports;
|
|
|
int num_ports;
|
|
|
int (*dpi_select_source)(int port, enum omap_channel channel);
|
|
|
+ int (*select_lcd_source)(enum omap_channel channel,
|
|
|
+ enum dss_clk_source clk_src);
|
|
|
};
|
|
|
|
|
|
static struct {
|
|
@@ -205,68 +207,70 @@ void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable)
|
|
|
1 << shift, val << shift);
|
|
|
}
|
|
|
|
|
|
-void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id,
|
|
|
+static int dss_ctrl_pll_set_control_mux(enum dss_clk_source clk_src,
|
|
|
enum omap_channel channel)
|
|
|
{
|
|
|
unsigned shift, val;
|
|
|
|
|
|
if (!dss.syscon_pll_ctrl)
|
|
|
- return;
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
switch (channel) {
|
|
|
case OMAP_DSS_CHANNEL_LCD:
|
|
|
shift = 3;
|
|
|
|
|
|
- switch (pll_id) {
|
|
|
- case DSS_PLL_VIDEO1:
|
|
|
+ switch (clk_src) {
|
|
|
+ case DSS_CLK_SRC_PLL1_1:
|
|
|
val = 0; break;
|
|
|
- case DSS_PLL_HDMI:
|
|
|
+ case DSS_CLK_SRC_HDMI_PLL:
|
|
|
val = 1; break;
|
|
|
default:
|
|
|
DSSERR("error in PLL mux config for LCD\n");
|
|
|
- return;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case OMAP_DSS_CHANNEL_LCD2:
|
|
|
shift = 5;
|
|
|
|
|
|
- switch (pll_id) {
|
|
|
- case DSS_PLL_VIDEO1:
|
|
|
+ switch (clk_src) {
|
|
|
+ case DSS_CLK_SRC_PLL1_3:
|
|
|
val = 0; break;
|
|
|
- case DSS_PLL_VIDEO2:
|
|
|
+ case DSS_CLK_SRC_PLL2_3:
|
|
|
val = 1; break;
|
|
|
- case DSS_PLL_HDMI:
|
|
|
+ case DSS_CLK_SRC_HDMI_PLL:
|
|
|
val = 2; break;
|
|
|
default:
|
|
|
DSSERR("error in PLL mux config for LCD2\n");
|
|
|
- return;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case OMAP_DSS_CHANNEL_LCD3:
|
|
|
shift = 7;
|
|
|
|
|
|
- switch (pll_id) {
|
|
|
- case DSS_PLL_VIDEO1:
|
|
|
- val = 1; break;
|
|
|
- case DSS_PLL_VIDEO2:
|
|
|
+ switch (clk_src) {
|
|
|
+ case DSS_CLK_SRC_PLL2_1:
|
|
|
val = 0; break;
|
|
|
- case DSS_PLL_HDMI:
|
|
|
+ case DSS_CLK_SRC_PLL1_3:
|
|
|
+ val = 1; break;
|
|
|
+ case DSS_CLK_SRC_HDMI_PLL:
|
|
|
val = 2; break;
|
|
|
default:
|
|
|
DSSERR("error in PLL mux config for LCD3\n");
|
|
|
- return;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
default:
|
|
|
DSSERR("error in PLL mux config\n");
|
|
|
- return;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
|
|
|
0x3 << shift, val << shift);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
void dss_sdi_init(int datapairs)
|
|
@@ -404,11 +408,34 @@ static void dss_dump_regs(struct seq_file *s)
|
|
|
#undef DUMPREG
|
|
|
}
|
|
|
|
|
|
+static int dss_get_channel_index(enum omap_channel channel)
|
|
|
+{
|
|
|
+ switch (channel) {
|
|
|
+ case OMAP_DSS_CHANNEL_LCD:
|
|
|
+ return 0;
|
|
|
+ case OMAP_DSS_CHANNEL_LCD2:
|
|
|
+ return 1;
|
|
|
+ case OMAP_DSS_CHANNEL_LCD3:
|
|
|
+ return 2;
|
|
|
+ default:
|
|
|
+ WARN_ON(1);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
|
|
|
{
|
|
|
int b;
|
|
|
u8 start, end;
|
|
|
|
|
|
+ /*
|
|
|
+ * We always use PRCM clock as the DISPC func clock, except on DSS3,
|
|
|
+ * where we don't have separate DISPC and LCD clock sources.
|
|
|
+ */
|
|
|
+ if (WARN_ON(dss_has_feature(FEAT_LCD_CLK_SRC) &&
|
|
|
+ clk_src != DSS_CLK_SRC_FCK))
|
|
|
+ return;
|
|
|
+
|
|
|
switch (clk_src) {
|
|
|
case DSS_CLK_SRC_FCK:
|
|
|
b = 0;
|
|
@@ -459,41 +486,108 @@ void dss_select_dsi_clk_source(int dsi_module,
|
|
|
dss.dsi_clk_source[dsi_module] = clk_src;
|
|
|
}
|
|
|
|
|
|
+static int dss_lcd_clk_mux_dra7(enum omap_channel channel,
|
|
|
+ enum dss_clk_source clk_src)
|
|
|
+{
|
|
|
+ const u8 ctrl_bits[] = {
|
|
|
+ [OMAP_DSS_CHANNEL_LCD] = 0,
|
|
|
+ [OMAP_DSS_CHANNEL_LCD2] = 12,
|
|
|
+ [OMAP_DSS_CHANNEL_LCD3] = 19,
|
|
|
+ };
|
|
|
+
|
|
|
+ u8 ctrl_bit = ctrl_bits[channel];
|
|
|
+ int r;
|
|
|
+
|
|
|
+ if (clk_src == DSS_CLK_SRC_FCK) {
|
|
|
+ /* LCDx_CLK_SWITCH */
|
|
|
+ REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ r = dss_ctrl_pll_set_control_mux(clk_src, channel);
|
|
|
+ if (r)
|
|
|
+ return r;
|
|
|
+
|
|
|
+ REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int dss_lcd_clk_mux_omap5(enum omap_channel channel,
|
|
|
+ enum dss_clk_source clk_src)
|
|
|
+{
|
|
|
+ const u8 ctrl_bits[] = {
|
|
|
+ [OMAP_DSS_CHANNEL_LCD] = 0,
|
|
|
+ [OMAP_DSS_CHANNEL_LCD2] = 12,
|
|
|
+ [OMAP_DSS_CHANNEL_LCD3] = 19,
|
|
|
+ };
|
|
|
+ const enum dss_clk_source allowed_plls[] = {
|
|
|
+ [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
|
|
|
+ [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_FCK,
|
|
|
+ [OMAP_DSS_CHANNEL_LCD3] = DSS_CLK_SRC_PLL2_1,
|
|
|
+ };
|
|
|
+
|
|
|
+ u8 ctrl_bit = ctrl_bits[channel];
|
|
|
+
|
|
|
+ if (clk_src == DSS_CLK_SRC_FCK) {
|
|
|
+ /* LCDx_CLK_SWITCH */
|
|
|
+ REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (WARN_ON(allowed_plls[channel] != clk_src))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int dss_lcd_clk_mux_omap4(enum omap_channel channel,
|
|
|
+ enum dss_clk_source clk_src)
|
|
|
+{
|
|
|
+ const u8 ctrl_bits[] = {
|
|
|
+ [OMAP_DSS_CHANNEL_LCD] = 0,
|
|
|
+ [OMAP_DSS_CHANNEL_LCD2] = 12,
|
|
|
+ };
|
|
|
+ const enum dss_clk_source allowed_plls[] = {
|
|
|
+ [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
|
|
|
+ [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_PLL2_1,
|
|
|
+ };
|
|
|
+
|
|
|
+ u8 ctrl_bit = ctrl_bits[channel];
|
|
|
+
|
|
|
+ if (clk_src == DSS_CLK_SRC_FCK) {
|
|
|
+ /* LCDx_CLK_SWITCH */
|
|
|
+ REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (WARN_ON(allowed_plls[channel] != clk_src))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
void dss_select_lcd_clk_source(enum omap_channel channel,
|
|
|
enum dss_clk_source clk_src)
|
|
|
{
|
|
|
- int b, ix, pos;
|
|
|
+ int idx = dss_get_channel_index(channel);
|
|
|
+ int r;
|
|
|
|
|
|
if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
|
|
|
dss_select_dispc_clk_source(clk_src);
|
|
|
+ dss.lcd_clk_source[idx] = clk_src;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- switch (clk_src) {
|
|
|
- case DSS_CLK_SRC_FCK:
|
|
|
- b = 0;
|
|
|
- break;
|
|
|
- case DSS_CLK_SRC_PLL1_1:
|
|
|
- BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
|
|
|
- b = 1;
|
|
|
- break;
|
|
|
- case DSS_CLK_SRC_PLL2_1:
|
|
|
- BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
|
|
|
- channel != OMAP_DSS_CHANNEL_LCD3);
|
|
|
- b = 1;
|
|
|
- break;
|
|
|
- default:
|
|
|
- BUG();
|
|
|
+ r = dss.feat->select_lcd_source(channel, clk_src);
|
|
|
+ if (r)
|
|
|
return;
|
|
|
- }
|
|
|
-
|
|
|
- pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
|
|
|
- (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
|
|
|
- REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
|
|
|
|
|
|
- ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
|
|
|
- (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
|
|
|
- dss.lcd_clk_source[ix] = clk_src;
|
|
|
+ dss.lcd_clk_source[idx] = clk_src;
|
|
|
}
|
|
|
|
|
|
enum dss_clk_source dss_get_dispc_clk_source(void)
|
|
@@ -509,9 +603,8 @@ enum dss_clk_source dss_get_dsi_clk_source(int dsi_module)
|
|
|
enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
|
|
|
{
|
|
|
if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
|
|
|
- int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
|
|
|
- (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
|
|
|
- return dss.lcd_clk_source[ix];
|
|
|
+ int idx = dss_get_channel_index(channel);
|
|
|
+ return dss.lcd_clk_source[idx];
|
|
|
} else {
|
|
|
/* LCD_CLK source is the same as DISPC_FCLK source for
|
|
|
* OMAP2 and OMAP3 */
|
|
@@ -860,6 +953,7 @@ static const struct dss_features omap44xx_dss_feats = {
|
|
|
.dpi_select_source = &dss_dpi_select_source_omap4,
|
|
|
.ports = omap2plus_ports,
|
|
|
.num_ports = ARRAY_SIZE(omap2plus_ports),
|
|
|
+ .select_lcd_source = &dss_lcd_clk_mux_omap4,
|
|
|
};
|
|
|
|
|
|
static const struct dss_features omap54xx_dss_feats = {
|
|
@@ -869,6 +963,7 @@ static const struct dss_features omap54xx_dss_feats = {
|
|
|
.dpi_select_source = &dss_dpi_select_source_omap5,
|
|
|
.ports = omap2plus_ports,
|
|
|
.num_ports = ARRAY_SIZE(omap2plus_ports),
|
|
|
+ .select_lcd_source = &dss_lcd_clk_mux_omap5,
|
|
|
};
|
|
|
|
|
|
static const struct dss_features am43xx_dss_feats = {
|
|
@@ -887,6 +982,7 @@ static const struct dss_features dra7xx_dss_feats = {
|
|
|
.dpi_select_source = &dss_dpi_select_source_dra7xx,
|
|
|
.ports = dra7xx_ports,
|
|
|
.num_ports = ARRAY_SIZE(dra7xx_ports),
|
|
|
+ .select_lcd_source = &dss_lcd_clk_mux_dra7,
|
|
|
};
|
|
|
|
|
|
static int dss_init_features(struct platform_device *pdev)
|