diff options
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
| -rw-r--r-- | drivers/video/omap2/dss/dsi.c | 406 | 
1 files changed, 271 insertions, 135 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 210a3c4f615..14ce8cc079e 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -256,14 +256,13 @@ struct dsi_data {  	struct platform_device *pdev;  	void __iomem	*base; +	int module_id; +  	int irq;  	struct clk *dss_clk;  	struct clk *sys_clk; -	int (*enable_pads)(int dsi_id, unsigned lane_mask); -	void (*disable_pads)(int dsi_id, unsigned lane_mask); -  	struct dsi_clock_info current_cinfo;  	bool vdds_dsi_enabled; @@ -361,11 +360,6 @@ struct platform_device *dsi_get_dsidev_from_id(int module)  	return dsi_pdev_map[module];  } -static inline int dsi_get_dsidev_id(struct platform_device *dsidev) -{ -	return dsidev->id; -} -  static inline void dsi_write_reg(struct platform_device *dsidev,  		const struct dsi_reg idx, u32 val)  { @@ -452,6 +446,7 @@ u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)  		return 16;  	default:  		BUG(); +		return 0;  	}  } @@ -1080,7 +1075,7 @@ void dsi_runtime_put(struct platform_device *dsidev)  	DSSDBG("dsi_runtime_put\n");  	r = pm_runtime_put_sync(&dsi->pdev->dev); -	WARN_ON(r < 0); +	WARN_ON(r < 0 && r != -ENOSYS);  }  /* source clock for DSI PLL. this could also be PCLKFREE */ @@ -1184,10 +1179,9 @@ static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)  static unsigned long dsi_fclk_rate(struct platform_device *dsidev)  {  	unsigned long r; -	int dsi_module = dsi_get_dsidev_id(dsidev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { +	if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) {  		/* DSI FCLK source is DSS_CLK_FCK */  		r = clk_get_rate(dsi->dss_clk);  	} else { @@ -1279,10 +1273,9 @@ static int dsi_pll_power(struct platform_device *dsidev,  }  /* calculate clock rates using dividers in cinfo */ -static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, +static int dsi_calc_clock_rates(struct platform_device *dsidev,  		struct dsi_clock_info *cinfo)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) @@ -1297,21 +1290,8 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,  	if (cinfo->regm_dsi > dsi->regm_dsi_max)  		return -EINVAL; -	if (cinfo->use_sys_clk) { -		cinfo->clkin = clk_get_rate(dsi->sys_clk); -		/* XXX it is unclear if highfreq should be used -		 * with DSS_SYS_CLK source also */ -		cinfo->highfreq = 0; -	} else { -		cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id); - -		if (cinfo->clkin < 32000000) -			cinfo->highfreq = 0; -		else -			cinfo->highfreq = 1; -	} - -	cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); +	cinfo->clkin = clk_get_rate(dsi->sys_clk); +	cinfo->fint = cinfo->clkin / cinfo->regn;  	if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)  		return -EINVAL; @@ -1378,27 +1358,21 @@ retry:  	memset(&cur, 0, sizeof(cur));  	cur.clkin = dss_sys_clk; -	cur.use_sys_clk = 1; -	cur.highfreq = 0; -	/* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ -	/* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ +	/* 0.75MHz < Fint = clkin / regn < 2.1MHz */  	/* To reduce PLL lock time, keep Fint high (around 2 MHz) */  	for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { -		if (cur.highfreq == 0) -			cur.fint = cur.clkin / cur.regn; -		else -			cur.fint = cur.clkin / (2 * cur.regn); +		cur.fint = cur.clkin / cur.regn;  		if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)  			continue; -		/* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ +		/* DSIPHY(MHz) = (2 * regm / regn) * clkin */  		for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {  			unsigned long a, b;  			a = 2 * cur.regm * (cur.clkin/1000); -			b = cur.regn * (cur.highfreq + 1); +			b = cur.regn;  			cur.clkin4ddr = a / b * 1000;  			if (cur.clkin4ddr > 1800 * 1000 * 1000) @@ -1486,9 +1460,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,  	DSSDBGF(); -	dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk; -	dsi->current_cinfo.highfreq = cinfo->highfreq; - +	dsi->current_cinfo.clkin = cinfo->clkin;  	dsi->current_cinfo.fint = cinfo->fint;  	dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;  	dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = @@ -1503,17 +1475,13 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,  	DSSDBG("DSI Fint %ld\n", cinfo->fint); -	DSSDBG("clkin (%s) rate %ld, highfreq %d\n", -			cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", -			cinfo->clkin, -			cinfo->highfreq); +	DSSDBG("clkin rate %ld\n", cinfo->clkin);  	/* DSIPHY == CLKIN4DDR */ -	DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n", +	DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n",  			cinfo->regm,  			cinfo->regn,  			cinfo->clkin, -			cinfo->highfreq + 1,  			cinfo->clkin4ddr);  	DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", @@ -1568,10 +1536,6 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,  	if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))  		l = FLD_MOD(l, f, 4, 1);	/* DSI_PLL_FREQSEL */ -	l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, -			11, 11);		/* DSI_PLL_CLKSEL */ -	l = FLD_MOD(l, cinfo->highfreq, -			12, 12);		/* DSI_PLL_HIGHFREQ */  	l = FLD_MOD(l, 1, 13, 13);		/* DSI_PLL_REFEN */  	l = FLD_MOD(l, 0, 14, 14);		/* DSIPHY_CLKINEN */  	l = FLD_MOD(l, 1, 20, 20);		/* DSI_HSDIVBYPASS */ @@ -1716,7 +1680,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	struct dsi_clock_info *cinfo = &dsi->current_cinfo;  	enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; -	int dsi_module = dsi_get_dsidev_id(dsidev); +	int dsi_module = dsi->module_id;  	dispc_clk_src = dss_get_dispc_clk_source();  	dsi_clk_src = dss_get_dsi_clk_source(dsi_module); @@ -1726,8 +1690,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,  	seq_printf(s,	"- DSI%d PLL -\n", dsi_module + 1); -	seq_printf(s,	"dsi pll source = %s\n", -			cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree"); +	seq_printf(s,	"dsi pll clkin\t%lu\n", cinfo->clkin);  	seq_printf(s,	"Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); @@ -1789,7 +1752,6 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	unsigned long flags;  	struct dsi_irq_stats stats; -	int dsi_module = dsi_get_dsidev_id(dsidev);  	spin_lock_irqsave(&dsi->irq_stats_lock, flags); @@ -1806,7 +1768,7 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,  #define PIS(x) \  	seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); -	seq_printf(s, "-- DSI%d interrupts --\n", dsi_module + 1); +	seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1);  	PIS(VC0);  	PIS(VC1);  	PIS(VC2); @@ -1886,22 +1848,6 @@ static void dsi2_dump_irqs(struct seq_file *s)  	dsi_dump_dsidev_irqs(dsidev, s);  } - -void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, -		const struct file_operations *debug_fops) -{ -	struct platform_device *dsidev; - -	dsidev = dsi_get_dsidev_from_id(0); -	if (dsidev) -		debugfs_create_file("dsi1_irqs", S_IRUGO, debugfs_dir, -			&dsi1_dump_irqs, debug_fops); - -	dsidev = dsi_get_dsidev_from_id(1); -	if (dsidev) -		debugfs_create_file("dsi2_irqs", S_IRUGO, debugfs_dir, -			&dsi2_dump_irqs, debug_fops); -}  #endif  static void dsi_dump_dsidev_regs(struct platform_device *dsidev, @@ -2002,21 +1948,6 @@ static void dsi2_dump_regs(struct seq_file *s)  	dsi_dump_dsidev_regs(dsidev, s);  } -void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, -		const struct file_operations *debug_fops) -{ -	struct platform_device *dsidev; - -	dsidev = dsi_get_dsidev_from_id(0); -	if (dsidev) -		debugfs_create_file("dsi1_regs", S_IRUGO, debugfs_dir, -			&dsi1_dump_regs, debug_fops); - -	dsidev = dsi_get_dsidev_from_id(1); -	if (dsidev) -		debugfs_create_file("dsi2_regs", S_IRUGO, debugfs_dir, -			&dsi2_dump_regs, debug_fops); -}  enum dsi_cio_power_state {  	DSI_COMPLEXIO_POWER_OFF		= 0x0,  	DSI_COMPLEXIO_POWER_ON		= 0x1, @@ -2073,6 +2004,7 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)  		return 1365 * 3;	/* 1365x24 bits */  	default:  		BUG(); +		return 0;  	}  } @@ -2337,7 +2269,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  	DSSDBGF(); -	r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); +	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));  	if (r)  		return r; @@ -2447,7 +2379,7 @@ err_cio_pwr:  		dsi_cio_disable_lane_override(dsidev);  err_scp_clk_dom:  	dsi_disable_scp_clk(dsidev); -	dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); +	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));  	return r;  } @@ -2461,7 +2393,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev)  	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);  	dsi_disable_scp_clk(dsidev); -	dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); +	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));  }  static void dsi_config_tx_fifo(struct platform_device *dsidev, @@ -2485,6 +2417,7 @@ static void dsi_config_tx_fifo(struct platform_device *dsidev,  		if (add + size > 4) {  			DSSERR("Illegal FIFO configuration\n");  			BUG(); +			return;  		}  		v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); @@ -2517,6 +2450,7 @@ static void dsi_config_rx_fifo(struct platform_device *dsidev,  		if (add + size > 4) {  			DSSERR("Illegal FIFO configuration\n");  			BUG(); +			return;  		}  		v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); @@ -2658,6 +2592,7 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel)  		return dsi_sync_vc_l4(dsidev, channel);  	default:  		BUG(); +		return -EINVAL;  	}  } @@ -3226,6 +3161,7 @@ static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev,  		data = reqdata[0] | (reqdata[1] << 8);  	} else {  		BUG(); +		return -EINVAL;  	}  	r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); @@ -3340,7 +3276,6 @@ static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,  		goto err;  	} -	BUG();  err:  	DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel,  		type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); @@ -3735,6 +3670,186 @@ static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)  	dsi_write_reg(dsidev, DSI_CTRL, r);  } +/* + * According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3 + * results in maximum transition time for data and clock lanes to enter and + * exit HS mode. Hence, this is the scenario where the least amount of command + * mode data can be interleaved. We program the minimum amount of TXBYTECLKHS + * clock cycles that can be used to interleave command mode data in HS so that + * all scenarios are satisfied. + */ +static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs, +		int exit_hs, int exiths_clk, int ddr_pre, int ddr_post) +{ +	int transition; + +	/* +	 * If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition +	 * time of data lanes only, if it isn't set, we need to consider HS +	 * transition time of both data and clock lanes. HS transition time +	 * of Scenario 3 is considered. +	 */ +	if (ddr_alwon) { +		transition = enter_hs + exit_hs + max(enter_hs, 2) + 1; +	} else { +		int trans1, trans2; +		trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1; +		trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre + +				enter_hs + 1; +		transition = max(trans1, trans2); +	} + +	return blank > transition ? blank - transition : 0; +} + +/* + * According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1 + * results in maximum transition time for data lanes to enter and exit LP mode. + * Hence, this is the scenario where the least amount of command mode data can + * be interleaved. We program the minimum amount of bytes that can be + * interleaved in LP so that all scenarios are satisfied. + */ +static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs, +		int lp_clk_div, int tdsi_fclk) +{ +	int trans_lp;	/* time required for a LP transition, in TXBYTECLKHS */ +	int tlp_avail;	/* time left for interleaving commands, in CLKIN4DDR */ +	int ttxclkesc;	/* period of LP transmit escape clock, in CLKIN4DDR */ +	int thsbyte_clk = 16;	/* Period of TXBYTECLKHS clock, in CLKIN4DDR */ +	int lp_inter;	/* cmd mode data that can be interleaved, in bytes */ + +	/* maximum LP transition time according to Scenario 1 */ +	trans_lp = exit_hs + max(enter_hs, 2) + 1; + +	/* CLKIN4DDR = 16 * TXBYTECLKHS */ +	tlp_avail = thsbyte_clk * (blank - trans_lp); + +	ttxclkesc = tdsi_fclk * lp_clk_div; + +	lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc - +			26) / 16; + +	return max(lp_inter, 0); +} + +static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	int blanking_mode; +	int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode; +	int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div; +	int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; +	int tclk_trail, ths_exit, exiths_clk; +	bool ddr_alwon; +	struct omap_video_timings *timings = &dssdev->panel.timings; +	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +	int ndl = dsi->num_lanes_used - 1; +	int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1; +	int hsa_interleave_hs = 0, hsa_interleave_lp = 0; +	int hfp_interleave_hs = 0, hfp_interleave_lp = 0; +	int hbp_interleave_hs = 0, hbp_interleave_lp = 0; +	int bl_interleave_hs = 0, bl_interleave_lp = 0; +	u32 r; + +	r = dsi_read_reg(dsidev, DSI_CTRL); +	blanking_mode = FLD_GET(r, 20, 20); +	hfp_blanking_mode = FLD_GET(r, 21, 21); +	hbp_blanking_mode = FLD_GET(r, 22, 22); +	hsa_blanking_mode = FLD_GET(r, 23, 23); + +	r = dsi_read_reg(dsidev, DSI_VM_TIMING1); +	hbp = FLD_GET(r, 11, 0); +	hfp = FLD_GET(r, 23, 12); +	hsa = FLD_GET(r, 31, 24); + +	r = dsi_read_reg(dsidev, DSI_CLK_TIMING); +	ddr_clk_post = FLD_GET(r, 7, 0); +	ddr_clk_pre = FLD_GET(r, 15, 8); + +	r = dsi_read_reg(dsidev, DSI_VM_TIMING7); +	exit_hs_mode_lat = FLD_GET(r, 15, 0); +	enter_hs_mode_lat = FLD_GET(r, 31, 16); + +	r = dsi_read_reg(dsidev, DSI_CLK_CTRL); +	lp_clk_div = FLD_GET(r, 12, 0); +	ddr_alwon = FLD_GET(r, 13, 13); + +	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); +	ths_exit = FLD_GET(r, 7, 0); + +	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); +	tclk_trail = FLD_GET(r, 15, 8); + +	exiths_clk = ths_exit + tclk_trail; + +	width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); +	bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl); + +	if (!hsa_blanking_mode) { +		hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon, +					enter_hs_mode_lat, exit_hs_mode_lat, +					exiths_clk, ddr_clk_pre, ddr_clk_post); +		hsa_interleave_lp = dsi_compute_interleave_lp(hsa, +					enter_hs_mode_lat, exit_hs_mode_lat, +					lp_clk_div, dsi_fclk_hsdiv); +	} + +	if (!hfp_blanking_mode) { +		hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon, +					enter_hs_mode_lat, exit_hs_mode_lat, +					exiths_clk, ddr_clk_pre, ddr_clk_post); +		hfp_interleave_lp = dsi_compute_interleave_lp(hfp, +					enter_hs_mode_lat, exit_hs_mode_lat, +					lp_clk_div, dsi_fclk_hsdiv); +	} + +	if (!hbp_blanking_mode) { +		hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon, +					enter_hs_mode_lat, exit_hs_mode_lat, +					exiths_clk, ddr_clk_pre, ddr_clk_post); + +		hbp_interleave_lp = dsi_compute_interleave_lp(hbp, +					enter_hs_mode_lat, exit_hs_mode_lat, +					lp_clk_div, dsi_fclk_hsdiv); +	} + +	if (!blanking_mode) { +		bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon, +					enter_hs_mode_lat, exit_hs_mode_lat, +					exiths_clk, ddr_clk_pre, ddr_clk_post); + +		bl_interleave_lp = dsi_compute_interleave_lp(bllp, +					enter_hs_mode_lat, exit_hs_mode_lat, +					lp_clk_div, dsi_fclk_hsdiv); +	} + +	DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n", +		hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs, +		bl_interleave_hs); + +	DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n", +		hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp, +		bl_interleave_lp); + +	r = dsi_read_reg(dsidev, DSI_VM_TIMING4); +	r = FLD_MOD(r, hsa_interleave_hs, 23, 16); +	r = FLD_MOD(r, hfp_interleave_hs, 15, 8); +	r = FLD_MOD(r, hbp_interleave_hs, 7, 0); +	dsi_write_reg(dsidev, DSI_VM_TIMING4, r); + +	r = dsi_read_reg(dsidev, DSI_VM_TIMING5); +	r = FLD_MOD(r, hsa_interleave_lp, 23, 16); +	r = FLD_MOD(r, hfp_interleave_lp, 15, 8); +	r = FLD_MOD(r, hbp_interleave_lp, 7, 0); +	dsi_write_reg(dsidev, DSI_VM_TIMING5, r); + +	r = dsi_read_reg(dsidev, DSI_VM_TIMING6); +	r = FLD_MOD(r, bl_interleave_hs, 31, 15); +	r = FLD_MOD(r, bl_interleave_lp, 16, 0); +	dsi_write_reg(dsidev, DSI_VM_TIMING6, r); +} +  static int dsi_proto_config(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -3769,6 +3884,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  		break;  	default:  		BUG(); +		return -EINVAL;  	}  	r = dsi_read_reg(dsidev, DSI_CTRL); @@ -3793,6 +3909,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {  		dsi_config_vp_sync_events(dssdev);  		dsi_config_blanking_modes(dssdev); +		dsi_config_cmd_mode_interleaving(dssdev);  	}  	dsi_vc_initial_config(dsidev, 0); @@ -4008,6 +4125,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)  			break;  		default:  			BUG(); +			return -EINVAL;  		};  		dsi_if_enable(dsidev, false); @@ -4192,10 +4310,6 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)  	__cancel_delayed_work(&dsi->framedone_timeout_work);  	dsi_handle_framedone(dsidev, 0); - -#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC -	dispc_fake_vsync_irq(); -#endif  }  int omap_dsi_update(struct omap_dss_device *dssdev, int channel, @@ -4259,13 +4373,12 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  		dispc_mgr_enable_stallmode(dssdev->manager->id, true);  		dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); -		dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); +		dss_mgr_set_timings(dssdev->manager, &timings);  	} else {  		dispc_mgr_enable_stallmode(dssdev->manager->id, false);  		dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); -		dispc_mgr_set_lcd_timings(dssdev->manager->id, -			&dssdev->panel.timings); +		dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);  	}  		dispc_mgr_set_lcd_display_type(dssdev->manager->id, @@ -4294,13 +4407,11 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)  	struct dsi_clock_info cinfo;  	int r; -	/* we always use DSS_CLK_SYSCK as input clock */ -	cinfo.use_sys_clk = true;  	cinfo.regn  = dssdev->clocks.dsi.regn;  	cinfo.regm  = dssdev->clocks.dsi.regm;  	cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc;  	cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; -	r = dsi_calc_clock_rates(dssdev, &cinfo); +	r = dsi_calc_clock_rates(dsidev, &cinfo);  	if (r) {  		DSSERR("Failed to calc dsi clocks\n");  		return r; @@ -4345,7 +4456,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)  static int dsi_display_init_dsi(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); -	int dsi_module = dsi_get_dsidev_id(dsidev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int r;  	r = dsi_pll_init(dsidev, true, true); @@ -4357,7 +4468,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)  		goto err1;  	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); -	dss_select_dsi_clk_source(dsi_module, dssdev->clocks.dsi.dsi_fclk_src); +	dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);  	dss_select_lcd_clk_source(dssdev->manager->id,  			dssdev->clocks.dispc.channel.lcd_clk_src); @@ -4396,7 +4507,7 @@ err3:  	dsi_cio_uninit(dssdev);  err2:  	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); -	dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); +	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);  	dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);  err1: @@ -4410,7 +4521,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	int dsi_module = dsi_get_dsidev_id(dsidev);  	if (enter_ulps && !dsi->ulps_enabled)  		dsi_enter_ulps(dsidev); @@ -4423,7 +4533,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,  	dsi_vc_enable(dsidev, 3, 0);  	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); -	dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); +	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);  	dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);  	dsi_cio_uninit(dssdev);  	dsi_pll_uninit(dsidev, disconnect_lanes); @@ -4527,7 +4637,7 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)  }  EXPORT_SYMBOL(omapdss_dsi_enable_te); -int dsi_init_display(struct omap_dss_device *dssdev) +static int __init dsi_init_display(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); @@ -4680,13 +4790,39 @@ static void dsi_put_clocks(struct platform_device *dsidev)  		clk_put(dsi->sys_clk);  } +static void __init dsi_probe_pdata(struct platform_device *dsidev) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_dss_board_info *pdata = dsidev->dev.platform_data; +	int i, r; + +	for (i = 0; i < pdata->num_devices; ++i) { +		struct omap_dss_device *dssdev = pdata->devices[i]; + +		if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) +			continue; + +		if (dssdev->phy.dsi.module != dsi->module_id) +			continue; + +		r = dsi_init_display(dssdev); +		if (r) { +			DSSERR("device %s init failed: %d\n", dssdev->name, r); +			continue; +		} + +		r = omap_dss_register_device(dssdev, &dsidev->dev, i); +		if (r) +			DSSERR("device %s register failed: %d\n", +					dssdev->name, r); +	} +} +  /* DSI1 HW IP initialisation */ -static int omap_dsihw_probe(struct platform_device *dsidev) +static int __init omap_dsihw_probe(struct platform_device *dsidev)  { -	struct omap_display_platform_data *dss_plat_data; -	struct omap_dss_board_info *board_info;  	u32 rev; -	int r, i, dsi_module = dsi_get_dsidev_id(dsidev); +	int r, i;  	struct resource *dsi_mem;  	struct dsi_data *dsi; @@ -4694,15 +4830,11 @@ static int omap_dsihw_probe(struct platform_device *dsidev)  	if (!dsi)  		return -ENOMEM; +	dsi->module_id = dsidev->id;  	dsi->pdev = dsidev; -	dsi_pdev_map[dsi_module] = dsidev; +	dsi_pdev_map[dsi->module_id] = dsidev;  	dev_set_drvdata(&dsidev->dev, dsi); -	dss_plat_data = dsidev->dev.platform_data; -	board_info = dss_plat_data->board_data; -	dsi->enable_pads = board_info->dsi_enable_pads; -	dsi->disable_pads = board_info->dsi_disable_pads; -  	spin_lock_init(&dsi->irq_lock);  	spin_lock_init(&dsi->errors_lock);  	dsi->errors = 0; @@ -4780,8 +4912,21 @@ static int omap_dsihw_probe(struct platform_device *dsidev)  	else  		dsi->num_lanes_supported = 3; +	dsi_probe_pdata(dsidev); +  	dsi_runtime_put(dsidev); +	if (dsi->module_id == 0) +		dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs); +	else if (dsi->module_id == 1) +		dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs); + +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +	if (dsi->module_id == 0) +		dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs); +	else if (dsi->module_id == 1) +		dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs); +#endif  	return 0;  err_runtime_get: @@ -4790,12 +4935,14 @@ err_runtime_get:  	return r;  } -static int omap_dsihw_remove(struct platform_device *dsidev) +static int __exit omap_dsihw_remove(struct platform_device *dsidev)  {  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	WARN_ON(dsi->scp_clk_refcount > 0); +	omap_dss_unregister_child_devices(&dsidev->dev); +  	pm_runtime_disable(&dsidev->dev);  	dsi_put_clocks(dsidev); @@ -4816,7 +4963,6 @@ static int omap_dsihw_remove(struct platform_device *dsidev)  static int dsi_runtime_suspend(struct device *dev)  {  	dispc_runtime_put(); -	dss_runtime_put();  	return 0;  } @@ -4825,20 +4971,11 @@ static int dsi_runtime_resume(struct device *dev)  {  	int r; -	r = dss_runtime_get(); -	if (r) -		goto err_get_dss; -  	r = dispc_runtime_get();  	if (r) -		goto err_get_dispc; +		return r;  	return 0; - -err_get_dispc: -	dss_runtime_put(); -err_get_dss: -	return r;  }  static const struct dev_pm_ops dsi_pm_ops = { @@ -4847,8 +4984,7 @@ static const struct dev_pm_ops dsi_pm_ops = {  };  static struct platform_driver omap_dsihw_driver = { -	.probe          = omap_dsihw_probe, -	.remove         = omap_dsihw_remove, +	.remove         = __exit_p(omap_dsihw_remove),  	.driver         = {  		.name   = "omapdss_dsi",  		.owner  = THIS_MODULE, @@ -4856,12 +4992,12 @@ static struct platform_driver omap_dsihw_driver = {  	},  }; -int dsi_init_platform_driver(void) +int __init dsi_init_platform_driver(void)  { -	return platform_driver_register(&omap_dsihw_driver); +	return platform_driver_probe(&omap_dsihw_driver, omap_dsihw_probe);  } -void dsi_uninit_platform_driver(void) +void __exit dsi_uninit_platform_driver(void)  { -	return platform_driver_unregister(&omap_dsihw_driver); +	platform_driver_unregister(&omap_dsihw_driver);  }  |