diff options
Diffstat (limited to 'drivers/video/omap2/dss/dss.c')
| -rw-r--r-- | drivers/video/omap2/dss/dss.c | 118 | 
1 files changed, 82 insertions, 36 deletions
| diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 3f1fee63c678..d9489d5c4f08 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -29,7 +29,7 @@  #include <linux/seq_file.h>  #include <linux/clk.h> -#include <plat/display.h> +#include <video/omapdss.h>  #include <plat/clock.h>  #include "dss.h"  #include "dss_features.h" @@ -45,7 +45,6 @@ struct dss_reg {  #define DSS_REVISION			DSS_REG(0x0000)  #define DSS_SYSCONFIG			DSS_REG(0x0010)  #define DSS_SYSSTATUS			DSS_REG(0x0014) -#define DSS_IRQSTATUS			DSS_REG(0x0018)  #define DSS_CONTROL			DSS_REG(0x0040)  #define DSS_SDI_CONTROL			DSS_REG(0x0044)  #define DSS_PLL_CONTROL			DSS_REG(0x0048) @@ -75,17 +74,17 @@ static struct {  	struct dss_clock_info cache_dss_cinfo;  	struct dispc_clock_info cache_dispc_cinfo; -	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]; +	enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI]; +	enum omap_dss_clk_source dispc_clk_source; +	enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];  	u32		ctx[DSS_SZ_REGS / sizeof(u32)];  } dss;  static const char * const dss_generic_clk_source_names[] = { -	[DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI_PLL_HSDIV_DISPC", -	[DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]		= "DSI_PLL_HSDIV_DSI", -	[DSS_CLK_SRC_FCK]			= "DSS_FCK", +	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI_PLL_HSDIV_DISPC", +	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DSI_PLL_HSDIV_DSI", +	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCK",  };  static void dss_clk_enable_all_no_ctx(void); @@ -230,7 +229,7 @@ void dss_sdi_disable(void)  	REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */  } -const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src) +const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)  {  	return dss_generic_clk_source_names[clk_src];  } @@ -246,8 +245,8 @@ void dss_dump_clocks(struct seq_file *s)  	seq_printf(s, "- DSS -\n"); -	fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK); -	fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK); +	fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); +	fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);  	fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);  	if (dss.dpll4_m4_ck) { @@ -286,7 +285,6 @@ void dss_dump_regs(struct seq_file *s)  	DUMPREG(DSS_REVISION);  	DUMPREG(DSS_SYSCONFIG);  	DUMPREG(DSS_SYSSTATUS); -	DUMPREG(DSS_IRQSTATUS);  	DUMPREG(DSS_CONTROL);  	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & @@ -300,18 +298,25 @@ void dss_dump_regs(struct seq_file *s)  #undef DUMPREG  } -void dss_select_dispc_clk_source(enum dss_clk_source clk_src) +void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)  { +	struct platform_device *dsidev;  	int b;  	u8 start, end;  	switch (clk_src) { -	case DSS_CLK_SRC_FCK: +	case OMAP_DSS_CLK_SRC_FCK:  		b = 0;  		break; -	case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: +	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:  		b = 1; -		dsi_wait_pll_hsdiv_dispc_active(); +		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(); @@ -324,17 +329,27 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src)  	dss.dispc_clk_source = clk_src;  } -void dss_select_dsi_clk_source(enum 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;  	switch (clk_src) { -	case DSS_CLK_SRC_FCK: +	case OMAP_DSS_CLK_SRC_FCK:  		b = 0;  		break; -	case DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: +	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; -		dsi_wait_pll_hsdiv_dsi_active(); +		dsidev = dsi_get_dsidev_from_id(1); +		dsi_wait_pll_hsdiv_dsi_active(dsidev);  		break;  	default:  		BUG(); @@ -342,25 +357,33 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src)  	REG_FLD_MOD(DSS_CONTROL, b, 1, 1);	/* DSI_CLK_SWITCH */ -	dss.dsi_clk_source = clk_src; +	dss.dsi_clk_source[dsi_module] = clk_src;  }  void dss_select_lcd_clk_source(enum omap_channel channel, -		enum dss_clk_source clk_src) +		enum omap_dss_clk_source clk_src)  { +	struct platform_device *dsidev;  	int b, ix, pos;  	if (!dss_has_feature(FEAT_LCD_CLK_SRC))  		return;  	switch (clk_src) { -	case DSS_CLK_SRC_FCK: +	case OMAP_DSS_CLK_SRC_FCK:  		b = 0;  		break; -	case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: +	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:  		BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);  		b = 1; -		dsi_wait_pll_hsdiv_dispc_active(); +		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); +		b = 1; +		dsidev = dsi_get_dsidev_from_id(1); +		dsi_wait_pll_hsdiv_dispc_active(dsidev);  		break;  	default:  		BUG(); @@ -373,20 +396,26 @@ void dss_select_lcd_clk_source(enum omap_channel channel,  	dss.lcd_clk_source[ix] = clk_src;  } -enum dss_clk_source dss_get_dispc_clk_source(void) +enum omap_dss_clk_source dss_get_dispc_clk_source(void)  {  	return dss.dispc_clk_source;  } -enum dss_clk_source dss_get_dsi_clk_source(void) +enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)  { -	return dss.dsi_clk_source; +	return dss.dsi_clk_source[dsi_module];  } -enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) +enum omap_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]; +	if (dss_has_feature(FEAT_LCD_CLK_SRC)) { +		int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; +		return dss.lcd_clk_source[ix]; +	} else { +		/* LCD_CLK source is the same as DISPC_FCLK source for +		 * OMAP2 and OMAP3 */ +		return dss.dispc_clk_source; +	}  }  /* calculate clock rates using dividers in cinfo */ @@ -659,13 +688,18 @@ static int dss_init(void)  	 * the kernel resets it */  	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); +#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET  	/* We need to wait here a bit, otherwise we sometimes start to  	 * get synclost errors, and after that only power cycle will  	 * restore DSS functionality. I have no idea why this happens.  	 * And we have to wait _before_ resetting the DSS, but after  	 * enabling clocks. +	 * +	 * This bug was at least present on OMAP3430. It's unknown +	 * if it happens on OMAP2 or OMAP3630.  	 */  	msleep(50); +#endif  	_omap_dss_reset(); @@ -700,10 +734,11 @@ static int dss_init(void)  	dss.dpll4_m4_ck = dpll4_m4_ck; -	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.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; +	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; +	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; +	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; +	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;  	dss_save_context(); @@ -1015,6 +1050,14 @@ static void core_dump_clocks(struct seq_file *s)  		dss.dss_video_fck  	}; +	const char *names[5] = { +		"ick", +		"fck", +		"sys_clk", +		"tv_fck", +		"video_fck" +	}; +  	seq_printf(s, "- CORE -\n");  	seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); @@ -1022,8 +1065,11 @@ static void core_dump_clocks(struct seq_file *s)  	for (i = 0; i < 5; i++) {  		if (!clocks[i])  			continue; -		seq_printf(s, "%-15s\t%lu\t%d\n", +		seq_printf(s, "%s (%s)%*s\t%lu\t%d\n", +				names[i],  				clocks[i]->name, +				24 - strlen(names[i]) - strlen(clocks[i]->name), +				"",  				clk_get_rate(clocks[i]),  				clocks[i]->usecount);  	} |