@@ -2365,25 +2365,33 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
lcd = FLD_GET(l, 23, 16);
- r = dispc_fclk_rate();
+ switch (dss_get_lcd_clk_source(channel)) {
+ case DSS_CLK_SRC_FCK:
+ r = dss_clk_get_rate(DSS_CLK_FCK);
+ break;
+ case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+ r = dsi_get_pll_hsdiv_dispc_rate();
+ break;
+ default:
+ BUG();
+ }
return r / lcd;
}
unsigned long dispc_pclk_rate(enum omap_channel channel)
{
- int lcd, pcd;
+ int pcd;
unsigned long r;
u32 l;
l = dispc_read_reg(DISPC_DIVISORo(channel));
- lcd = FLD_GET(l, 23, 16);
pcd = FLD_GET(l, 7, 0);
- r = dispc_fclk_rate();
+ r = dispc_lclk_rate(channel);
- return r / lcd / pcd;
+ return r / pcd;
}
void dispc_dump_clocks(struct seq_file *s)
@@ -2391,6 +2399,7 @@ void dispc_dump_clocks(struct seq_file *s)
int lcd, pcd;
u32 l;
enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
+ enum dss_clk_source lcd_clk_src;
enable_clocks(1);
@@ -2412,6 +2421,12 @@ void dispc_dump_clocks(struct seq_file *s)
}
seq_printf(s, "- LCD1 -\n");
+ lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD);
+
+ seq_printf(s, "lcd1_clk source = %s (%s)\n",
+ dss_get_generic_clk_source_name(lcd_clk_src),
+ dss_feat_get_clk_source_name(lcd_clk_src));
+
dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
@@ -2421,6 +2436,12 @@ void dispc_dump_clocks(struct seq_file *s)
if (dss_has_feature(FEAT_MGR_LCD2)) {
seq_printf(s, "- LCD2 -\n");
+ lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2);
+
+ seq_printf(s, "lcd2_clk source = %s (%s)\n",
+ dss_get_generic_clk_source_name(lcd_clk_src),
+ dss_feat_get_clk_source_name(lcd_clk_src));
+
dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
@@ -77,6 +77,7 @@ static struct {
enum dss_clk_source dsi_clk_source;
enum dss_clk_source dispc_clk_source;
+ enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
} dss;
@@ -292,6 +293,7 @@ void dss_dump_regs(struct seq_file *s)
void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
{
int b;
+ u8 start, end;
switch (clk_src) {
case DSS_CLK_SRC_FCK:
@@ -305,7 +307,9 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
BUG();
}
- REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */
+ dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
+
+ REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */
dss.dispc_clk_source = clk_src;
}
@@ -331,6 +335,34 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
dss.dsi_clk_source = clk_src;
}
+void dss_select_lcd_clk_source(enum omap_channel channel,
+ enum dss_clk_source clk_src)
+{
+ int b, ix, pos;
+
+ if (!dss_has_feature(FEAT_LCD_CLK_SRC))
+ return;
+
+ switch (clk_src) {
+ case DSS_CLK_SRC_FCK:
+ b = 0;
+ break;
+ case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+ BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
+ b = 1;
+ dsi_wait_pll_hsdiv_dispc_active();
+ break;
+ default:
+ BUG();
+ }
+
+ pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12;
+ REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
+
+ ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
+ dss.lcd_clk_source[ix] = clk_src;
+}
+
enum dss_clk_source dss_get_dispc_clk_source(void)
{
return dss.dispc_clk_source;
@@ -341,6 +373,12 @@ enum dss_clk_source dss_get_dsi_clk_source(void)
return dss.dsi_clk_source;
}
+enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
+{
+ int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
+ return dss.lcd_clk_source[ix];
+}
+
/* calculate clock rates using dividers in cinfo */
int dss_calc_clock_rates(struct dss_clock_info *cinfo)
{
@@ -624,6 +662,8 @@ static int dss_init(void)
dss.dsi_clk_source = DSS_CLK_SRC_FCK;
dss.dispc_clk_source = DSS_CLK_SRC_FCK;
+ dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK;
+ dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK;
dss_save_context();
@@ -118,9 +118,12 @@ enum dss_clock {
};
enum dss_clk_source {
- DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* DSI1_PLL_FCLK */
- DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* DSI2_PLL_FCLK */
- DSS_CLK_SRC_FCK, /* DSS1_ALWON_FCLK */
+ DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK
+ * OMAP4: PLL1_CLK1 */
+ DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK
+ * OMAP4: PLL1_CLK2 */
+ DSS_CLK_SRC_FCK, /* OMAP2/3: DSS1_ALWON_FCLK
+ * OMAP4: DSS_FCLK */
};
/* Correlates clock source name and dss_clk_source member */
@@ -152,17 +155,19 @@ struct dsi_clock_info {
unsigned long fint;
unsigned long clkin4ddr;
unsigned long clkin;
- unsigned long dsi_pll_hsdiv_dispc_clk; /* DSI1_PLL_CLK */
- unsigned long dsi_pll_hsdiv_dsi_clk; /* DSI2_PLL_CLK */
-
+ unsigned long dsi_pll_hsdiv_dispc_clk; /* OMAP3: DSI1_PLL_CLK
+ * OMAP4: PLLx_CLK1 */
+ unsigned long dsi_pll_hsdiv_dsi_clk; /* OMAP3: DSI2_PLL_CLK
+ * OMAP4: PLLx_CLK2 */
unsigned long lp_clk;
/* dividers */
u16 regn;
u16 regm;
- u16 regm_dispc; /* REGM3 */
- u16 regm_dsi; /* REGM4 */
-
+ u16 regm_dispc; /* OMAP3: REGM3
+ * OMAP4: REGM4 */
+ u16 regm_dsi; /* OMAP3: REGM4
+ * OMAP4: REGM5 */
u16 lp_clk_div;
u8 highfreq;
@@ -235,8 +240,11 @@ void dss_sdi_disable(void);
void dss_select_dispc_clk_source(enum dss_clk_source clk_src);
void dss_select_dsi_clk_source(enum dss_clk_source clk_src);
+void dss_select_lcd_clk_source(enum omap_channel channel,
+ enum dss_clk_source clk_src);
enum dss_clk_source dss_get_dispc_clk_source(void);
enum dss_clk_source dss_get_dsi_clk_source(void);
+enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
void dss_set_venc_output(enum omap_dss_venc_type type);
void dss_set_dac_pwrdn_bgz(bool enable);
@@ -59,6 +59,7 @@ static const struct dss_reg_field omap2_dss_reg_fields[] = {
{ FEAT_REG_FIFOSIZE, 8, 0 },
{ FEAT_REG_HORIZONTALACCU, 9, 0 },
{ FEAT_REG_VERTICALACCU, 25, 16 },
+ { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 },
};
static const struct dss_reg_field omap3_dss_reg_fields[] = {
@@ -69,6 +70,7 @@ static const struct dss_reg_field omap3_dss_reg_fields[] = {
{ FEAT_REG_FIFOSIZE, 10, 0 },
{ FEAT_REG_HORIZONTALACCU, 9, 0 },
{ FEAT_REG_VERTICALACCU, 25, 16 },
+ { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 },
};
static const struct dss_reg_field omap4_dss_reg_fields[] = {
@@ -79,6 +81,7 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
{ FEAT_REG_FIFOSIZE, 15, 0 },
{ FEAT_REG_HORIZONTALACCU, 10, 0 },
{ FEAT_REG_VERTICALACCU, 26, 16 },
+ { FEAT_REG_DISPC_CLK_SWITCH, 9, 8 },
};
static const enum omap_display_type omap2_dss_supported_displays[] = {
@@ -171,6 +174,12 @@ static const struct dss_clk_source_name omap3_dss_clk_source_names[] = {
{ DSS_CLK_SRC_FCK, "DSS1_ALWON_FCLK" },
};
+static const struct dss_clk_source_name omap4_dss_clk_source_names[] = {
+ { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "PLL1_CLK1" },
+ { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "PLL1_CLK2" },
+ { DSS_CLK_SRC_FCK, "DSS_FCLK" },
+};
+
/* OMAP2 DSS Features */
static struct omap_dss_features omap2_dss_features = {
.reg_fields = omap2_dss_reg_fields,
@@ -235,14 +244,14 @@ static struct omap_dss_features omap4_dss_features = {
.has_feature =
FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
- FEAT_CORE_CLK_DIV,
+ FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC,
.num_mgrs = 3,
.num_ovls = 3,
.max_dss_fck = 186000000,
.supported_displays = omap4_dss_supported_displays,
.supported_color_modes = omap3_dss_supported_color_modes,
- .clksrc_names = omap3_dss_clk_source_names,
+ .clksrc_names = omap4_dss_clk_source_names,
};
/* Functions returning values related to a DSS feature */
@@ -22,6 +22,7 @@
#define MAX_DSS_MANAGERS 3
#define MAX_DSS_OVERLAYS 3
+#define MAX_DSS_LCD_MANAGERS 2
/* DSS has feature id */
enum dss_feat_id {
@@ -38,6 +39,7 @@ enum dss_feat_id {
FEAT_RESIZECONF = 1 << 10,
/* Independent core clk divider */
FEAT_CORE_CLK_DIV = 1 << 11,
+ FEAT_LCD_CLK_SRC = 1 << 12,
};
/* DSS register field id */
@@ -49,6 +51,7 @@ enum dss_feat_reg_field {
FEAT_REG_FIFOSIZE,
FEAT_REG_HORIZONTALACCU,
FEAT_REG_VERTICALACCU,
+ FEAT_REG_DISPC_CLK_SWITCH,
};
/* DSS Feature Functions */