diff options
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
| -rw-r--r-- | drivers/video/omap2/dss/dsi.c | 675 | 
1 files changed, 519 insertions, 156 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 05ee04667af..d64ac384288 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -41,7 +41,6 @@  #include <video/omapdss.h>  #include <video/mipi_display.h> -#include <plat/clock.h>  #include "dss.h"  #include "dss_features.h" @@ -333,6 +332,12 @@ struct dsi_data {  	unsigned scp_clk_refcount;  	struct dss_lcd_mgr_config mgr_config; +	struct omap_video_timings timings; +	enum omap_dss_dsi_pixel_format pix_fmt; +	enum omap_dss_dsi_mode mode; +	struct omap_dss_dsi_videomode_timings vm_timings; + +	struct omap_dss_output output;  };  struct dsi_packet_sent_handler_data { @@ -340,8 +345,6 @@ struct dsi_packet_sent_handler_data {  	struct completion *completion;  }; -static struct platform_device *dsi_pdev_map[MAX_NUM_DSI]; -  #ifdef DEBUG  static bool dsi_perf;  module_param(dsi_perf, bool, 0644); @@ -354,12 +357,19 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside  static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)  { -	return dsi_pdev_map[dssdev->phy.dsi.module]; +	return dssdev->output->pdev;  }  struct platform_device *dsi_get_dsidev_from_id(int module)  { -	return dsi_pdev_map[module]; +	struct omap_dss_output *out; +	enum omap_dss_output_id	id; + +	id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + +	out = omap_dss_get_output(id); + +	return out->pdev;  }  static inline void dsi_write_reg(struct platform_device *dsidev, @@ -1450,6 +1460,148 @@ found:  	return 0;  } +static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev, +		unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct dsi_clock_info cur, best; + +	DSSDBG("dsi_pll_calc_ddrfreq\n"); + +	memset(&best, 0, sizeof(best)); +	memset(&cur, 0, sizeof(cur)); + +	cur.clkin = clk_get_rate(dsi->sys_clk); + +	for (cur.regn = 1; cur.regn < dsi->regn_max; ++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 */ +		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.clkin4ddr = a / b * 1000; + +			if (cur.clkin4ddr > 1800 * 1000 * 1000) +				break; + +			if (abs(cur.clkin4ddr - req_clkin4ddr) < +					abs(best.clkin4ddr - req_clkin4ddr)) { +				best = cur; +				DSSDBG("best %ld\n", best.clkin4ddr); +			} + +			if (cur.clkin4ddr == req_clkin4ddr) +				goto found; +		} +	} +found: +	if (cinfo) +		*cinfo = best; + +	return 0; +} + +static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev, +		struct dsi_clock_info *cinfo) +{ +	unsigned long max_dsi_fck; + +	max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK); + +	cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck); +	cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi; +} + +static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev, +		unsigned long req_pck, struct dsi_clock_info *cinfo, +		struct dispc_clock_info *dispc_cinfo) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	unsigned regm_dispc, best_regm_dispc; +	unsigned long dispc_clk, best_dispc_clk; +	int min_fck_per_pck; +	unsigned long max_dss_fck; +	struct dispc_clock_info best_dispc; +	bool match; + +	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + +	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; + +	if (min_fck_per_pck && +			req_pck * min_fck_per_pck > max_dss_fck) { +		DSSERR("Requested pixel clock not possible with the current " +				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " +				"the constraint off.\n"); +		min_fck_per_pck = 0; +	} + +retry: +	best_regm_dispc = 0; +	best_dispc_clk = 0; +	memset(&best_dispc, 0, sizeof(best_dispc)); +	match = false; + +	for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) { +		struct dispc_clock_info cur_dispc; + +		dispc_clk = cinfo->clkin4ddr / regm_dispc; + +		/* this will narrow down the search a bit, +		 * but still give pixclocks below what was +		 * requested */ +		if (dispc_clk  < req_pck) +			break; + +		if (dispc_clk > max_dss_fck) +			continue; + +		if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck) +			continue; + +		match = true; + +		dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc); + +		if (abs(cur_dispc.pck - req_pck) < +				abs(best_dispc.pck - req_pck)) { +			best_regm_dispc = regm_dispc; +			best_dispc_clk = dispc_clk; +			best_dispc = cur_dispc; + +			if (cur_dispc.pck == req_pck) +				goto found; +		} +	} + +	if (!match) { +		if (min_fck_per_pck) { +			DSSERR("Could not find suitable clock settings.\n" +					"Turning FCK/PCK constraint off and" +					"trying again.\n"); +			min_fck_per_pck = 0; +			goto retry; +		} + +		DSSERR("Could not find suitable clock settings.\n"); + +		return -EINVAL; +	} +found: +	cinfo->regm_dispc = best_regm_dispc; +	cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk; + +	*dispc_cinfo = best_dispc; + +	return 0; +} +  int dsi_pll_set_clock_div(struct platform_device *dsidev,  		struct dsi_clock_info *cinfo)  { @@ -1526,21 +1678,27 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,  	BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); +	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); +  	if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {  		f = cinfo->fint < 1000000 ? 0x3 :  			cinfo->fint < 1250000 ? 0x4 :  			cinfo->fint < 1500000 ? 0x5 :  			cinfo->fint < 1750000 ? 0x6 :  			0x7; -	} -	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); - -	if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))  		l = FLD_MOD(l, f, 4, 1);	/* DSI_PLL_FREQSEL */ +	} else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) { +		f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4; + +		l = FLD_MOD(l, f, 4, 1);	/* PLL_SELFREQDCO */ +	} +  	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 */ +	if (dss_has_feature(FEAT_DSI_PLL_REFSEL)) +		l = FLD_MOD(l, 3, 22, 21);	/* REF_SYSCLK = sysclk */  	dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);  	REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0);	/* DSI_PLL_GO */ @@ -2004,15 +2162,16 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)  		return 1194 * 3;	/* 1194x24 bits */  	case 6:  		return 1365 * 3;	/* 1365x24 bits */ +	case 7: +		return 1920 * 3;	/* 1920x24 bits */  	default:  		BUG();  		return 0;  	}  } -static int dsi_set_lane_config(struct omap_dss_device *dssdev) +static int dsi_set_lane_config(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	static const u8 offsets[] = { 0, 4, 8, 12, 16 };  	static const enum dsi_lane_function functions[] = { @@ -2136,9 +2295,16 @@ static void dsi_cio_timings(struct platform_device *dsidev)  	dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);  	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); -	r = FLD_MOD(r, tlpx_half, 22, 16); +	r = FLD_MOD(r, tlpx_half, 20, 16);  	r = FLD_MOD(r, tclk_trail, 15, 8);  	r = FLD_MOD(r, tclk_zero, 7, 0); + +	if (dss_has_feature(FEAT_DSI_PHY_DCC)) { +		r = FLD_MOD(r, 0, 21, 21);	/* DCCEN = disable */ +		r = FLD_MOD(r, 1, 22, 22);	/* CLKINP_DIVBY2EN = enable */ +		r = FLD_MOD(r, 1, 23, 23);	/* CLKINP_SEL = enable */ +	} +  	dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);  	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); @@ -2147,10 +2313,9 @@ static void dsi_cio_timings(struct platform_device *dsidev)  }  /* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */ -static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, +static void dsi_cio_enable_lane_override(struct platform_device *dsidev,  		unsigned mask_p, unsigned mask_n)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int i;  	u32 l; @@ -2197,9 +2362,8 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)  	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);  } -static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) +static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int t, i;  	bool in_use[DSI_MAX_NR_LANES]; @@ -2247,9 +2411,8 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)  }  /* return bitmask of enabled lanes, lane0 being the lsb */ -static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) +static unsigned dsi_get_lane_mask(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	unsigned mask = 0;  	int i; @@ -2262,16 +2425,15 @@ static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)  	return mask;  } -static int dsi_cio_init(struct omap_dss_device *dssdev) +static int dsi_cio_init(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int r;  	u32 l;  	DSSDBGF(); -	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); +	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));  	if (r)  		return r; @@ -2288,7 +2450,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  		goto err_scp_clk_dom;  	} -	r = dsi_set_lane_config(dssdev); +	r = dsi_set_lane_config(dsidev);  	if (r)  		goto err_scp_clk_dom; @@ -2323,7 +2485,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  			mask_p |= 1 << i;  		} -		dsi_cio_enable_lane_override(dssdev, mask_p, 0); +		dsi_cio_enable_lane_override(dsidev, mask_p, 0);  	}  	r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); @@ -2340,7 +2502,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  	dsi_if_enable(dsidev, false);  	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ -	r = dsi_cio_wait_tx_clk_esc_reset(dssdev); +	r = dsi_cio_wait_tx_clk_esc_reset(dsidev);  	if (r)  		goto err_tx_clk_esc_rst; @@ -2360,10 +2522,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  	dsi_cio_timings(dsidev); -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {  		/* DDR_CLK_ALWAYS_ON */  		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, -			dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); +			dsi->vm_timings.ddr_clk_always_on, 13, 13);  	}  	dsi->ulps_enabled = false; @@ -2381,13 +2543,12 @@ err_cio_pwr:  		dsi_cio_disable_lane_override(dsidev);  err_scp_clk_dom:  	dsi_disable_scp_clk(dsidev); -	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); +	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));  	return r;  } -static void dsi_cio_uninit(struct omap_dss_device *dssdev) +static void dsi_cio_uninit(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	/* DDR_CLK_ALWAYS_ON */ @@ -2395,7 +2556,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev)  	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);  	dsi_disable_scp_clk(dsidev); -	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); +	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));  }  static void dsi_config_tx_fifo(struct platform_device *dsidev, @@ -2685,6 +2846,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,  		bool enable)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); @@ -2701,7 +2863,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,  	dsi_force_tx_stop_mode_io(dsidev);  	/* start the DDR clock by sending a NULL packet */ -	if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable) +	if (dsi->vm_timings.ddr_clk_always_on && enable)  		dsi_vc_send_null(dssdev, channel);  }  EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); @@ -2987,10 +3149,9 @@ int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)  }  EXPORT_SYMBOL(dsi_vc_send_null); -static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, +static int dsi_vc_write_nosync_common(struct platform_device *dsidev,  		int channel, u8 *data, int len, enum dss_dsi_content_type type)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r;  	if (len == 0) { @@ -3021,7 +3182,9 @@ static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,  int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,  		u8 *data, int len)  { -	return dsi_vc_write_nosync_common(dssdev, channel, data, len, +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + +	return dsi_vc_write_nosync_common(dsidev, channel, data, len,  			DSS_DSI_CONTENT_DCS);  }  EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); @@ -3029,7 +3192,9 @@ EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);  int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,  		u8 *data, int len)  { -	return dsi_vc_write_nosync_common(dssdev, channel, data, len, +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + +	return dsi_vc_write_nosync_common(dsidev, channel, data, len,  			DSS_DSI_CONTENT_GENERIC);  }  EXPORT_SYMBOL(dsi_vc_generic_write_nosync); @@ -3040,7 +3205,7 @@ static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r; -	r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type); +	r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type);  	if (r)  		goto err; @@ -3118,10 +3283,9 @@ int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,  }  EXPORT_SYMBOL(dsi_vc_generic_write_2); -static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, +static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,  		int channel, u8 dcs_cmd)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int r; @@ -3139,10 +3303,9 @@ static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,  	return 0;  } -static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, +static int dsi_vc_generic_send_read_request(struct platform_device *dsidev,  		int channel, u8 *reqdata, int reqlen)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	u16 data;  	u8 data_type; @@ -3291,7 +3454,7 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r; -	r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd); +	r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);  	if (r)  		goto err; @@ -3322,7 +3485,7 @@ static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r; -	r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); +	r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen);  	if (r)  		return r; @@ -3604,15 +3767,15 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,  			(total_ticks * 1000) / (fck / 1000 / 1000));  } -static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) +static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int num_line_buffers; -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { -		int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { +		int bpp = dsi_get_pixel_size(dsi->pix_fmt);  		unsigned line_buf_size = dsi_get_line_buf_size(dsidev); -		struct omap_video_timings *timings = &dssdev->panel.timings; +		struct omap_video_timings *timings = &dsi->timings;  		/*  		 * Don't use line buffers if width is greater than the video  		 * port's line buffer size @@ -3630,11 +3793,11 @@ static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)  	REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);  } -static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) +static void dsi_config_vp_sync_events(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); -	bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; -	bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	bool vsync_end = dsi->vm_timings.vp_vsync_end; +	bool hsync_end = dsi->vm_timings.vp_hsync_end;  	u32 r;  	r = dsi_read_reg(dsidev, DSI_CTRL); @@ -3648,13 +3811,13 @@ static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)  	dsi_write_reg(dsidev, DSI_CTRL, r);  } -static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) +static void dsi_config_blanking_modes(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); -	int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode; -	int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode; -	int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode; -	int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode; +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	int blanking_mode = dsi->vm_timings.blanking_mode; +	int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode; +	int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode; +	int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;  	u32 r;  	/* @@ -3741,8 +3904,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)  	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); +	struct omap_video_timings *timings = &dsi->timings; +	int bpp = dsi_get_pixel_size(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; @@ -3852,6 +4015,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)  static int dsi_proto_config(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	u32 r;  	int buswidth = 0; @@ -3871,7 +4035,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);  	dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); -	switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) { +	switch (dsi_get_pixel_size(dsi->pix_fmt)) {  	case 16:  		buswidth = 0;  		break; @@ -3903,11 +4067,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	dsi_write_reg(dsidev, DSI_CTRL, r); -	dsi_config_vp_num_line_buffers(dssdev); +	dsi_config_vp_num_line_buffers(dsidev); -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { -		dsi_config_vp_sync_events(dssdev); -		dsi_config_blanking_modes(dssdev); +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { +		dsi_config_vp_sync_events(dsidev); +		dsi_config_blanking_modes(dsidev);  		dsi_config_cmd_mode_interleaving(dssdev);  	} @@ -3919,9 +4083,8 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	return 0;  } -static void dsi_proto_timings(struct omap_dss_device *dssdev) +static void dsi_proto_timings(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;  	unsigned tclk_pre, tclk_post; @@ -3941,7 +4104,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)  	ths_exit = FLD_GET(r, 7, 0);  	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); -	tlpx = FLD_GET(r, 22, 16) * 2; +	tlpx = FLD_GET(r, 20, 16) * 2;  	tclk_trail = FLD_GET(r, 15, 8);  	tclk_zero = FLD_GET(r, 7, 0); @@ -3984,18 +4147,18 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)  	DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",  			enter_hs_mode_lat, exit_hs_mode_lat); -	 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +	 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {  		/* TODO: Implement a video mode check_timings function */ -		int hsa = dssdev->panel.dsi_vm_data.hsa; -		int hfp = dssdev->panel.dsi_vm_data.hfp; -		int hbp = dssdev->panel.dsi_vm_data.hbp; -		int vsa = dssdev->panel.dsi_vm_data.vsa; -		int vfp = dssdev->panel.dsi_vm_data.vfp; -		int vbp = dssdev->panel.dsi_vm_data.vbp; -		int window_sync = dssdev->panel.dsi_vm_data.window_sync; -		bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; -		struct omap_video_timings *timings = &dssdev->panel.timings; -		int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +		int hsa = dsi->vm_timings.hsa; +		int hfp = dsi->vm_timings.hfp; +		int hbp = dsi->vm_timings.hbp; +		int vsa = dsi->vm_timings.vsa; +		int vfp = dsi->vm_timings.vfp; +		int vbp = dsi->vm_timings.vbp; +		int window_sync = dsi->vm_timings.window_sync; +		bool hsync_end = dsi->vm_timings.vp_hsync_end; +		struct omap_video_timings *timings = &dsi->timings; +		int bpp = dsi_get_pixel_size(dsi->pix_fmt);  		int tl, t_he, width_bytes;  		t_he = hsync_end ? @@ -4100,16 +4263,84 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,  }  EXPORT_SYMBOL(omapdss_dsi_configure_pins); -int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) +int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, +		unsigned long ddr_clk, unsigned long lp_clk)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct dsi_clock_info cinfo; +	struct dispc_clock_info dispc_cinfo; +	unsigned lp_clk_div; +	unsigned long dsi_fclk;  	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +	unsigned long pck; +	int r; + +	DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk); + +	mutex_lock(&dsi->lock); + +	/* Calculate PLL output clock */ +	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo); +	if (r) +		goto err; + +	/* Calculate PLL's DSI clock */ +	dsi_pll_calc_dsi_fck(dsidev, &cinfo); + +	/* Calculate PLL's DISPC clock and pck & lck divs */ +	pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp; +	DSSDBG("finding dispc dividers for pck %lu\n", pck); +	r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo); +	if (r) +		goto err; + +	/* Calculate LP clock */ +	dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk; +	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2); + +	dssdev->clocks.dsi.regn = cinfo.regn; +	dssdev->clocks.dsi.regm = cinfo.regm; +	dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc; +	dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi; + +	dssdev->clocks.dsi.lp_clk_div = lp_clk_div; + +	dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div; +	dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div; + +	dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK; + +	dssdev->clocks.dispc.channel.lcd_clk_src = +		dsi->module_id == 0 ? +		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : +		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC; + +	dssdev->clocks.dsi.dsi_fclk_src = +		dsi->module_id == 0 ? +		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : +		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI; + +	mutex_unlock(&dsi->lock); +	return 0; +err: +	mutex_unlock(&dsi->lock); +	return r; +} +EXPORT_SYMBOL(omapdss_dsi_set_clocks); + +int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager; +	int bpp = dsi_get_pixel_size(dsi->pix_fmt);  	u8 data_type;  	u16 word_count;  	int r; -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { -		switch (dssdev->panel.dsi_pix_fmt) { +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { +		switch (dsi->pix_fmt) {  		case OMAP_DSS_DSI_FMT_RGB888:  			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;  			break; @@ -4133,7 +4364,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)  		/* MODE, 1 = video mode */  		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); -		word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); +		word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);  		dsi_vc_write_long_header(dsidev, channel, data_type,  				word_count, 0); @@ -4142,9 +4373,9 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)  		dsi_if_enable(dsidev, true);  	} -	r = dss_mgr_enable(dssdev->manager); +	r = dss_mgr_enable(mgr);  	if (r) { -		if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +		if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {  			dsi_if_enable(dsidev, false);  			dsi_vc_enable(dsidev, channel, false);  		} @@ -4159,8 +4390,10 @@ EXPORT_SYMBOL(dsi_enable_video_output);  void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager; -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {  		dsi_if_enable(dsidev, false);  		dsi_vc_enable(dsidev, channel, false); @@ -4171,15 +4404,15 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)  		dsi_if_enable(dsidev, true);  	} -	dss_mgr_disable(dssdev->manager); +	dss_mgr_disable(mgr);  }  EXPORT_SYMBOL(dsi_disable_video_output); -static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, -		u16 w, u16 h) +static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	unsigned bytespp;  	unsigned bytespl;  	unsigned bytespf; @@ -4190,12 +4423,14 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,  	int r;  	const unsigned channel = dsi->update_channel;  	const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); +	u16 w = dsi->timings.x_res; +	u16 h = dsi->timings.y_res;  	DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);  	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); -	bytespp	= dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; +	bytespp	= dsi_get_pixel_size(dsi->pix_fmt) / 8;  	bytespl = w * bytespp;  	bytespf = bytespl * h; @@ -4239,7 +4474,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,  		msecs_to_jiffies(250));  	BUG_ON(r == 0); -	dss_mgr_start_update(dssdev->manager); +	dss_mgr_set_timings(mgr, &dsi->timings); + +	dss_mgr_start_update(mgr);  	if (dsi->te_enabled) {  		/* disable LP_RX_TO, so that we can receive TE.  Time to wait @@ -4297,8 +4534,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)  static void dsi_framedone_irq_callback(void *data, u32 mask)  { -	struct omap_dss_device *dssdev = (struct omap_dss_device *) data; -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct platform_device *dsidev = (struct platform_device *) data;  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	/* Note: We get FRAMEDONE when DISPC has finished sending pixels and @@ -4325,13 +4561,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,  	dsi->framedone_callback = callback;  	dsi->framedone_data = data; -	dssdev->driver->get_resolution(dssdev, &dw, &dh); +	dw = dsi->timings.x_res; +	dh = dsi->timings.y_res;  #ifdef DEBUG  	dsi->update_bytes = dw * dh * -		dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; +		dsi_get_pixel_size(dsi->pix_fmt) / 8;  #endif -	dsi_update_screen_dispc(dssdev, dw, dh); +	dsi_update_screen_dispc(dssdev);  	return 0;  } @@ -4367,28 +4604,22 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	struct omap_video_timings timings; +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	int r;  	u32 irq = 0; -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { -		u16 dw, dh; - -		dssdev->driver->get_resolution(dssdev, &dw, &dh); - -		timings.x_res = dw; -		timings.y_res = dh; -		timings.hsw = 1; -		timings.hfp = 1; -		timings.hbp = 1; -		timings.vsw = 1; -		timings.vfp = 0; -		timings.vbp = 0; +	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { +		dsi->timings.hsw = 1; +		dsi->timings.hfp = 1; +		dsi->timings.hbp = 1; +		dsi->timings.vsw = 1; +		dsi->timings.vfp = 0; +		dsi->timings.vbp = 0; -		irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); +		irq = dispc_mgr_get_framedone_irq(mgr->id);  		r = omap_dispc_register_isr(dsi_framedone_irq_callback, -			(void *) dssdev, irq); +			(void *) dsidev, irq);  		if (r) {  			DSSERR("can't get FRAMEDONE irq\n");  			goto err; @@ -4397,8 +4628,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  		dsi->mgr_config.stallmode = true;  		dsi->mgr_config.fifohandcheck = true;  	} else { -		timings = dssdev->panel.timings; -  		dsi->mgr_config.stallmode = false;  		dsi->mgr_config.fifohandcheck = false;  	} @@ -4407,14 +4636,14 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  	 * override interlace, logic level and edge related parameters in  	 * omap_video_timings with default values  	 */ -	timings.interlace = false; -	timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; -	timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; -	timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; -	timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; -	timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; +	dsi->timings.interlace = false; +	dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; +	dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; +	dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; +	dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; +	dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; -	dss_mgr_set_timings(dssdev->manager, &timings); +	dss_mgr_set_timings(mgr, &dsi->timings);  	r = dsi_configure_dispc_clocks(dssdev);  	if (r) @@ -4422,29 +4651,33 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  	dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;  	dsi->mgr_config.video_port_width = -			dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +			dsi_get_pixel_size(dsi->pix_fmt);  	dsi->mgr_config.lcden_sig_polarity = 0; -	dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config); +	dss_mgr_set_lcd_config(mgr, &dsi->mgr_config);  	return 0;  err1: -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) +	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)  		omap_dispc_unregister_isr(dsi_framedone_irq_callback, -			(void *) dssdev, irq); +			(void *) dsidev, irq);  err:  	return r;  }  static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)  { -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager; + +	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {  		u32 irq; -		irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); +		irq = dispc_mgr_get_framedone_irq(mgr->id);  		omap_dispc_unregister_isr(dsi_framedone_irq_callback, -			(void *) dssdev, irq); +			(void *) dsidev, irq);  	}  } @@ -4477,6 +4710,7 @@ static int dsi_display_init_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); +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	int r;  	r = dsi_pll_init(dsidev, true, true); @@ -4489,18 +4723,18 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)  	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);  	dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); -	dss_select_lcd_clk_source(dssdev->manager->id, +	dss_select_lcd_clk_source(mgr->id,  			dssdev->clocks.dispc.channel.lcd_clk_src);  	DSSDBG("PLL OK\n"); -	r = dsi_cio_init(dssdev); +	r = dsi_cio_init(dsidev);  	if (r)  		goto err2;  	_dsi_print_reset_status(dsidev); -	dsi_proto_timings(dssdev); +	dsi_proto_timings(dsidev);  	dsi_set_lp_clk_divisor(dssdev);  	if (1) @@ -4520,11 +4754,11 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)  	return 0;  err3: -	dsi_cio_uninit(dssdev); +	dsi_cio_uninit(dsidev);  err2:  	dss_select_dispc_clk_source(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); +	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);  err1:  	dsi_pll_uninit(dsidev, true); @@ -4537,6 +4771,7 @@ 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); +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	if (enter_ulps && !dsi->ulps_enabled)  		dsi_enter_ulps(dsidev); @@ -4550,8 +4785,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,  	dss_select_dispc_clk_source(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); +	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); +	dsi_cio_uninit(dsidev);  	dsi_pll_uninit(dsidev, disconnect_lanes);  } @@ -4559,6 +4794,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_dss_output *out = dssdev->output;  	int r = 0;  	DSSDBG("dsi_display_enable\n"); @@ -4567,8 +4803,8 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)  	mutex_lock(&dsi->lock); -	if (dssdev->manager == NULL) { -		DSSERR("failed to enable display: no manager\n"); +	if (out == NULL || out->manager == NULL) { +		DSSERR("failed to enable display: no output/manager\n");  		r = -ENODEV;  		goto err_start_dev;  	} @@ -4653,17 +4889,83 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)  }  EXPORT_SYMBOL(omapdss_dsi_enable_te); -static int __init dsi_init_display(struct omap_dss_device *dssdev) +void omapdss_dsi_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	DSSDBG("DSI init\n"); +	mutex_lock(&dsi->lock); -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { -		dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | -			OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; -	} +	dsi->timings = *timings; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_timings); + +void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	mutex_lock(&dsi->lock); + +	dsi->timings.x_res = w; +	dsi->timings.y_res = h; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_size); + +void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev, +		enum omap_dss_dsi_pixel_format fmt) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	mutex_lock(&dsi->lock); + +	dsi->pix_fmt = fmt; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_pixel_format); + +void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev, +		enum omap_dss_dsi_mode mode) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	mutex_lock(&dsi->lock); + +	dsi->mode = mode; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_operation_mode); + +void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev, +		struct omap_dss_dsi_videomode_timings *timings) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	mutex_lock(&dsi->lock); + +	dsi->vm_timings = *timings; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings); + +static int __init dsi_init_display(struct omap_dss_device *dssdev) +{ +	struct platform_device *dsidev = +			dsi_get_dsidev_from_id(dssdev->phy.dsi.module); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	DSSDBG("DSI init\n");  	if (dsi->vdds_dsi_reg == NULL) {  		struct regulator *vdds_dsi; @@ -4806,11 +5108,15 @@ static void dsi_put_clocks(struct platform_device *dsidev)  		clk_put(dsi->sys_clk);  } -static void __init dsi_probe_pdata(struct platform_device *dsidev) +static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)  { -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	struct omap_dss_board_info *pdata = dsidev->dev.platform_data; -	int i, r; +	struct omap_dss_board_info *pdata = pdev->dev.platform_data; +	struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); +	const char *def_disp_name = dss_get_default_display_name(); +	struct omap_dss_device *def_dssdev; +	int i; + +	def_dssdev = NULL;  	for (i = 0; i < pdata->num_devices; ++i) {  		struct omap_dss_device *dssdev = pdata->devices[i]; @@ -4821,19 +5127,73 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)  		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; +		if (def_dssdev == NULL) +			def_dssdev = dssdev; + +		if (def_disp_name != NULL && +				strcmp(dssdev->name, def_disp_name) == 0) { +			def_dssdev = dssdev; +			break;  		} +	} -		r = omap_dss_register_device(dssdev, &dsidev->dev, i); -		if (r) -			DSSERR("device %s register failed: %d\n", -					dssdev->name, r); +	return def_dssdev; +} + +static void __init dsi_probe_pdata(struct platform_device *dsidev) +{ +	struct omap_dss_device *plat_dssdev; +	struct omap_dss_device *dssdev; +	int r; + +	plat_dssdev = dsi_find_dssdev(dsidev); + +	if (!plat_dssdev) +		return; + +	dssdev = dss_alloc_and_init_device(&dsidev->dev); +	if (!dssdev) +		return; + +	dss_copy_device_pdata(dssdev, plat_dssdev); + +	r = dsi_init_display(dssdev); +	if (r) { +		DSSERR("device %s init failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return; +	} + +	r = dss_add_device(dssdev); +	if (r) { +		DSSERR("device %s register failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return;  	}  } +static void __init dsi_init_output(struct platform_device *dsidev) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_dss_output *out = &dsi->output; + +	out->pdev = dsidev; +	out->id = dsi->module_id == 0 ? +			OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + +	out->type = OMAP_DISPLAY_TYPE_DSI; + +	dss_register_output(out); +} + +static void __exit dsi_uninit_output(struct platform_device *dsidev) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_dss_output *out = &dsi->output; + +	dss_unregister_output(out); +} +  /* DSI1 HW IP initialisation */  static int __init omap_dsihw_probe(struct platform_device *dsidev)  { @@ -4848,7 +5208,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)  	dsi->module_id = dsidev->id;  	dsi->pdev = dsidev; -	dsi_pdev_map[dsi->module_id] = dsidev;  	dev_set_drvdata(&dsidev->dev, dsi);  	spin_lock_init(&dsi->irq_lock); @@ -4928,6 +5287,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)  	else  		dsi->num_lanes_supported = 3; +	dsi_init_output(dsidev); +  	dsi_probe_pdata(dsidev);  	dsi_runtime_put(dsidev); @@ -4957,7 +5318,9 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)  	WARN_ON(dsi->scp_clk_refcount > 0); -	omap_dss_unregister_child_devices(&dsidev->dev); +	dss_unregister_child_devices(&dsidev->dev); + +	dsi_uninit_output(dsidev);  	pm_runtime_disable(&dsidev->dev);  |