From a0d269ec0bfab89f7b025bf6e1e596e9a6f9d999 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 27 Nov 2012 17:05:54 +0200 Subject: OMAPDSS: DSI: remove DSI & DISPC clk divisors from dssdev struct omap_dss_device contains DSS clock divisors. The idea is that the board file can pass precalculated divisors to the display driver. However, these divsors are no longer needed, as the omapdss driver can calculate the divisors during runtime. This patch removes the divisors from omap_dss_device, and their uses from the dsi driver. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/dsi.c | 47 ++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 21 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 28d41d16b7be..9eb78455b7df 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -261,6 +261,13 @@ struct dsi_data { struct clk *dss_clk; struct clk *sys_clk; + struct dispc_clock_info user_dispc_cinfo; + struct dsi_clock_info user_dsi_cinfo; + + enum omap_dss_clk_source user_dispc_fclk_src; + enum omap_dss_clk_source user_lcd_clk_src; + enum omap_dss_clk_source user_dsi_fclk_src; + struct dsi_clock_info current_cinfo; bool vdds_dsi_enabled; @@ -1200,7 +1207,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) unsigned lp_clk_div; unsigned long lp_clk; - lp_clk_div = dssdev->clocks.dsi.lp_clk_div; + lp_clk_div = dsi->user_dsi_cinfo.lp_clk_div; if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max) return -EINVAL; @@ -3910,7 +3917,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) 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 dsi_fclk_hsdiv = dsi->user_dsi_cinfo.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; @@ -4302,24 +4309,24 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, 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; + dsi->user_dsi_cinfo.regn = cinfo.regn; + dsi->user_dsi_cinfo.regm = cinfo.regm; + dsi->user_dsi_cinfo.regm_dispc = cinfo.regm_dispc; + dsi->user_dsi_cinfo.regm_dsi = cinfo.regm_dsi; - dssdev->clocks.dsi.lp_clk_div = lp_clk_div; + dsi->user_dsi_cinfo.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; + dsi->user_dispc_cinfo.lck_div = dispc_cinfo.lck_div; + dsi->user_dispc_cinfo.pck_div = dispc_cinfo.pck_div; - dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK; + dsi->user_dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK; - dssdev->clocks.dispc.channel.lcd_clk_src = + dsi->user_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->user_dsi_fclk_src = dsi->module_id == 0 ? OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI; @@ -4589,8 +4596,8 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) fck = dsi_get_pll_hsdiv_dispc_rate(dsidev); - dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div; - dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div; + dispc_cinfo.lck_div = dsi->user_dispc_cinfo.lck_div; + dispc_cinfo.pck_div = dsi->user_dispc_cinfo.pck_div; r = dispc_calc_clock_rates(fck, &dispc_cinfo); if (r) { @@ -4679,13 +4686,12 @@ static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) static int dsi_configure_dsi_clocks(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 dsi_clock_info cinfo; int r; - 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; + cinfo = dsi->user_dsi_cinfo; + r = dsi_calc_clock_rates(dsidev, &cinfo); if (r) { DSSERR("Failed to calc dsi clocks\n"); @@ -4716,9 +4722,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) if (r) goto err1; - dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); - dss_select_lcd_clk_source(mgr->id, - dssdev->clocks.dispc.channel.lcd_clk_src); + dss_select_dsi_clk_source(dsi->module_id, dsi->user_dsi_fclk_src); + dss_select_lcd_clk_source(mgr->id, dsi->user_lcd_clk_src); DSSDBG("PLL OK\n"); -- cgit v1.2.1 From 4fdfdf062d896c0afa18aa2d977a933e38c7c96c Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 12 Feb 2013 15:15:21 +0200 Subject: OMAPDSS: HDMI: remove HDMI clk divisors from dssdev struct omap_dss_device contains HDMI clock divisors. The idea is that the board file can pass precalculated divisors to the display driver. However, these divsors are no longer needed, as the omapdss driver can calculate the divisors during runtime. This patch removes the divisors from omap_dss_device, and their uses from the hdmi driver. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/hdmi.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 72923645dcce..b53de043c03f 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -472,17 +472,12 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, * Input clock is predivided by N + 1 * out put of which is reference clk */ - if (dssdev->clocks.hdmi.regn == 0) - pi->regn = HDMI_DEFAULT_REGN; - else - pi->regn = dssdev->clocks.hdmi.regn; + + pi->regn = HDMI_DEFAULT_REGN; refclk = clkin / pi->regn; - if (dssdev->clocks.hdmi.regm2 == 0) - pi->regm2 = HDMI_DEFAULT_REGM2; - else - pi->regm2 = dssdev->clocks.hdmi.regm2; + pi->regm2 = HDMI_DEFAULT_REGM2; /* * multiplier is pixel_clk/ref_clk -- cgit v1.2.1 From 03a0d1e81bdb519aa5881487cc5f20ffb8906c59 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 27 Nov 2012 16:41:16 +0200 Subject: OMAPDSS: DPI: remove omap_dss_device uses The role of struct omap_dss_device will change in the future. The exact details of that are still a bit unclear. However, the less uses of omap_dss_device we have, the easier the change is in the future. This patch removes uses of omap_dss_device from dpi.c, where it can be done neatly, by, for example, passing some lower level parameter in function parameters. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/dpi.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 4af136a04e53..cb6b280124f1 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -91,11 +91,10 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel) } } -static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, +static int dpi_set_dsi_clk(enum omap_channel channel, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { - struct omap_overlay_manager *mgr = dssdev->output->manager; struct dsi_clock_info dsi_cinfo; struct dispc_clock_info dispc_cinfo; int r; @@ -109,8 +108,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, if (r) return r; - dss_select_lcd_clk_source(mgr->id, - dpi_get_alt_clk_src(mgr->id)); + dss_select_lcd_clk_source(channel, + dpi_get_alt_clk_src(channel)); dpi.mgr_config.clock_info = dispc_cinfo; @@ -121,9 +120,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, return 0; } -static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, - unsigned long pck_req, unsigned long *fck, int *lck_div, - int *pck_div) +static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck, + int *lck_div, int *pck_div) { struct dss_clock_info dss_cinfo; struct dispc_clock_info dispc_cinfo; @@ -146,20 +144,19 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, return 0; } -static int dpi_set_mode(struct omap_dss_device *dssdev) +static int dpi_set_mode(struct omap_overlay_manager *mgr) { struct omap_video_timings *t = &dpi.timings; - struct omap_overlay_manager *mgr = dssdev->output->manager; int lck_div = 0, pck_div = 0; unsigned long fck = 0; unsigned long pck; int r = 0; if (dpi.dsidev) - r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck, + r = dpi_set_dsi_clk(mgr->id, t->pixel_clock * 1000, &fck, &lck_div, &pck_div); else - r = dpi_set_dispc_clk(dssdev, t->pixel_clock * 1000, &fck, + r = dpi_set_dispc_clk(t->pixel_clock * 1000, &fck, &lck_div, &pck_div); if (r) return r; @@ -179,10 +176,8 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) return 0; } -static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) +static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr) { - struct omap_overlay_manager *mgr = dssdev->output->manager; - dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; dpi.mgr_config.stallmode = false; @@ -197,7 +192,7 @@ static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) { - struct omap_dss_output *out = dssdev->output; + struct omap_dss_output *out = &dpi.output; int r; mutex_lock(&dpi.lock); @@ -230,7 +225,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) if (r) goto err_get_dispc; - r = dss_dpi_select_source(dssdev->channel); + r = dss_dpi_select_source(out->manager->id); if (r) goto err_src_sel; @@ -244,11 +239,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) goto err_dsi_pll_init; } - r = dpi_set_mode(dssdev); + r = dpi_set_mode(out->manager); if (r) goto err_set_mode; - dpi_config_lcd_manager(dssdev); + dpi_config_lcd_manager(out->manager); mdelay(2); @@ -285,7 +280,7 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable); void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) { - struct omap_overlay_manager *mgr = dssdev->output->manager; + struct omap_overlay_manager *mgr = dpi.output.manager; mutex_lock(&dpi.lock); @@ -325,7 +320,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { int r; - struct omap_overlay_manager *mgr = dssdev->output->manager; + struct omap_overlay_manager *mgr = dpi.output.manager; int lck_div, pck_div; unsigned long fck; unsigned long pck; -- cgit v1.2.1 From 5761217abf1636b6a0979548286e15200f17c010 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 27 Nov 2012 17:32:36 +0200 Subject: OMAPDSS: DSI: remove omap_dss_device uses The role of struct omap_dss_device will change in the future. The exact details of that are still a bit unclear. However, the less uses of omap_dss_device we have, the easier the change is in the future. This patch removes uses of omap_dss_device from dsi.c, where it can be done easily. Mostly this means passing dsi platform device to functions, instead of the omap_dss_device. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/dsi.c | 68 ++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 39 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 9eb78455b7df..815c93047151 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1199,9 +1199,8 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev) return r; } -static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) +static int dsi_set_lp_clk_divisor(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); unsigned long dsi_fclk; unsigned lp_clk_div; @@ -3904,9 +3903,8 @@ static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs, return max(lp_inter, 0); } -static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) +static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev) { - 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; @@ -4022,9 +4020,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) dsi_write_reg(dsidev, DSI_VM_TIMING6, r); } -static int dsi_proto_config(struct omap_dss_device *dssdev) +static int dsi_proto_config(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); u32 r; int buswidth = 0; @@ -4082,7 +4079,7 @@ static int dsi_proto_config(struct omap_dss_device *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); + dsi_config_cmd_mode_interleaving(dsidev); } dsi_vc_initial_config(dsidev, 0); @@ -4343,7 +4340,7 @@ 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; + struct omap_overlay_manager *mgr = dsi->output.manager; int bpp = dsi_get_pixel_size(dsi->pix_fmt); u8 data_type; u16 word_count; @@ -4401,7 +4398,7 @@ 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; + struct omap_overlay_manager *mgr = dsi->output.manager; if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { dsi_if_enable(dsidev, false); @@ -4418,11 +4415,10 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) } EXPORT_SYMBOL(dsi_disable_video_output); -static void dsi_update_screen_dispc(struct omap_dss_device *dssdev) +static void dsi_update_screen_dispc(struct platform_device *dsidev) { - 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; + struct omap_overlay_manager *mgr = dsi->output.manager; unsigned bytespp; unsigned bytespl; unsigned bytespf; @@ -4578,7 +4574,7 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel, dsi->update_bytes = dw * dh * dsi_get_pixel_size(dsi->pix_fmt) / 8; #endif - dsi_update_screen_dispc(dssdev); + dsi_update_screen_dispc(dsidev); return 0; } @@ -4586,9 +4582,8 @@ EXPORT_SYMBOL(omap_dsi_update); /* Display funcs */ -static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) +static int dsi_configure_dispc_clocks(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct dispc_clock_info dispc_cinfo; int r; @@ -4610,11 +4605,10 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) return 0; } -static int dsi_display_init_dispc(struct omap_dss_device *dssdev) +static int dsi_display_init_dispc(struct platform_device *dsidev) { - 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; + struct omap_overlay_manager *mgr = dsi->output.manager; int r; if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { @@ -4652,7 +4646,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) dss_mgr_set_timings(mgr, &dsi->timings); - r = dsi_configure_dispc_clocks(dssdev); + r = dsi_configure_dispc_clocks(dsidev); if (r) goto err1; @@ -4672,20 +4666,18 @@ err: return r; } -static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) +static void dsi_display_uninit_dispc(struct platform_device *dsidev) { - 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; + struct omap_overlay_manager *mgr = dsi->output.manager; if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) dss_mgr_unregister_framedone_handler(mgr, dsi_framedone_irq_callback, dsidev); } -static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) +static int dsi_configure_dsi_clocks(struct platform_device *dsidev) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct dsi_clock_info cinfo; int r; @@ -4707,18 +4699,17 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) return 0; } -static int dsi_display_init_dsi(struct omap_dss_device *dssdev) +static int dsi_display_init_dsi(struct platform_device *dsidev) { - 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; + struct omap_overlay_manager *mgr = dsi->output.manager; int r; r = dsi_pll_init(dsidev, true, true); if (r) goto err0; - r = dsi_configure_dsi_clocks(dssdev); + r = dsi_configure_dsi_clocks(dsidev); if (r) goto err1; @@ -4734,12 +4725,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) _dsi_print_reset_status(dsidev); dsi_proto_timings(dsidev); - dsi_set_lp_clk_divisor(dssdev); + dsi_set_lp_clk_divisor(dsidev); if (1) _dsi_print_reset_status(dsidev); - r = dsi_proto_config(dssdev); + r = dsi_proto_config(dsidev); if (r) goto err3; @@ -4764,12 +4755,11 @@ err0: return r; } -static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, +static void dsi_display_uninit_dsi(struct platform_device *dsidev, bool disconnect_lanes, bool enter_ulps) { - 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; + struct omap_overlay_manager *mgr = dsi->output.manager; if (enter_ulps && !dsi->ulps_enabled) dsi_enter_ulps(dsidev); @@ -4791,7 +4781,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; + struct omap_dss_output *out = &dsi->output; int r = 0; DSSDBG("dsi_display_enable\n"); @@ -4820,11 +4810,11 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) _dsi_initialize_irq(dsidev); - r = dsi_display_init_dispc(dssdev); + r = dsi_display_init_dispc(dsidev); if (r) goto err_init_dispc; - r = dsi_display_init_dsi(dssdev); + r = dsi_display_init_dsi(dsidev); if (r) goto err_init_dsi; @@ -4833,7 +4823,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) return 0; err_init_dsi: - dsi_display_uninit_dispc(dssdev); + dsi_display_uninit_dispc(dsidev); err_init_dispc: dsi_enable_pll_clock(dsidev, 0); dsi_runtime_put(dsidev); @@ -4863,9 +4853,9 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, dsi_sync_vc(dsidev, 2); dsi_sync_vc(dsidev, 3); - dsi_display_uninit_dispc(dssdev); + dsi_display_uninit_dispc(dsidev); - dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps); + dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps); dsi_runtime_put(dsidev); dsi_enable_pll_clock(dsidev, 0); -- cgit v1.2.1 From e087cc21c6d23d27951d45289a096b825326d3e2 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 16 Nov 2012 14:48:51 +0200 Subject: OMAPDSS: Taal: remove multi-panel support Taal panel driver was originally meant to support multiple different DSI command mode panel models. This never realized, and the multi-panel support code is lying there unused, making the driver more difficult to maintain. This patch removes the multi-panel support from Taal driver. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/displays/panel-taal.c | 109 ++++-------------------------- 1 file changed, 15 insertions(+), 94 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index a32407a5735a..038a815ba6c8 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -54,61 +54,6 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); static int taal_panel_reset(struct omap_dss_device *dssdev); -/** - * struct panel_config - panel configuration - * @name: panel name - * @type: panel type - * @timings: panel resolution - * @sleep: various panel specific delays, passed to msleep() if non-zero - * @reset_sequence: reset sequence timings, passed to udelay() if non-zero - * @regulators: array of panel regulators - * @num_regulators: number of regulators in the array - */ -struct panel_config { - const char *name; - int type; - - struct omap_video_timings timings; - - struct { - unsigned int sleep_in; - unsigned int sleep_out; - unsigned int hw_reset; - unsigned int enable_te; - } sleep; - - struct { - unsigned int high; - unsigned int low; - } reset_sequence; - -}; - -enum { - PANEL_TAAL, -}; - -static struct panel_config panel_configs[] = { - { - .name = "taal", - .type = PANEL_TAAL, - .timings = { - .x_res = 864, - .y_res = 480, - }, - .sleep = { - .sleep_in = 5, - .sleep_out = 5, - .hw_reset = 5, - .enable_te = 100, /* possible panel bug */ - }, - .reset_sequence = { - .high = 10, - .low = 10, - }, - }, -}; - struct taal_data { struct mutex lock; @@ -121,9 +66,6 @@ struct taal_data { struct omap_dss_device *dssdev; - /* panel specific HW info */ - struct panel_config *panel_config; - /* panel HW configuration from DT or platform data */ int reset_gpio; int ext_te_gpio; @@ -221,8 +163,7 @@ static int taal_sleep_in(struct taal_data *td) hw_guard_start(td, 120); - if (td->panel_config->sleep.sleep_in) - msleep(td->panel_config->sleep.sleep_in); + msleep(5); return 0; } @@ -239,8 +180,7 @@ static int taal_sleep_out(struct taal_data *td) hw_guard_start(td, 120); - if (td->panel_config->sleep.sleep_out) - msleep(td->panel_config->sleep.sleep_out); + msleep(5); return 0; } @@ -845,17 +785,14 @@ static void taal_hw_reset(struct omap_dss_device *dssdev) return; gpio_set_value(td->reset_gpio, 1); - if (td->panel_config->reset_sequence.high) - udelay(td->panel_config->reset_sequence.high); + udelay(10); /* reset the panel */ gpio_set_value(td->reset_gpio, 0); /* assert reset */ - if (td->panel_config->reset_sequence.low) - udelay(td->panel_config->reset_sequence.low); + udelay(10); gpio_set_value(td->reset_gpio, 1); /* wait after releasing reset */ - if (td->panel_config->sleep.hw_reset) - msleep(td->panel_config->sleep.hw_reset); + msleep(5); } static void taal_probe_pdata(struct taal_data *td, @@ -881,8 +818,7 @@ static int taal_probe(struct omap_dss_device *dssdev) struct backlight_properties props; struct taal_data *td; struct backlight_device *bldev = NULL; - int r, i; - const char *panel_name; + int r; dev_dbg(&dssdev->dev, "probe\n"); @@ -897,26 +833,12 @@ static int taal_probe(struct omap_dss_device *dssdev) const struct nokia_dsi_panel_data *pdata = dssdev->data; taal_probe_pdata(td, pdata); - - panel_name = pdata->name; } else { return -ENODEV; } - if (panel_name == NULL) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { - if (strcmp(panel_name, panel_configs[i].name) == 0) { - td->panel_config = &panel_configs[i]; - break; - } - } - - if (!td->panel_config) - return -EINVAL; - - dssdev->panel.timings = td->panel_config->timings; + dssdev->panel.timings.x_res = 864; + dssdev->panel.timings.y_res = 480; dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; @@ -1086,8 +1008,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) goto err; /* on early Taal revisions CABC is broken */ - if (td->panel_config->type == PANEL_TAAL && - (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) + if (id2 == 0x00 || id2 == 0xff || id2 == 0x81) td->cabc_broken = true; r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff); @@ -1129,8 +1050,8 @@ static int taal_power_on(struct omap_dss_device *dssdev) td->enabled = 1; if (!td->intro_printed) { - dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n", - td->panel_config->name, id1, id2, id3); + dev_info(&dssdev->dev, "panel revision %02x.%02x.%02x\n", + id1, id2, id3); if (td->cabc_broken) dev_info(&dssdev->dev, "old Taal version, CABC disabled\n"); @@ -1311,8 +1232,8 @@ static int taal_update(struct omap_dss_device *dssdev, /* XXX no need to send this every frame, but dsi break if not done */ r = taal_set_update_window(td, 0, 0, - td->panel_config->timings.x_res, - td->panel_config->timings.y_res); + dssdev->panel.timings.x_res, + dssdev->panel.timings.y_res); if (r) goto err; @@ -1365,8 +1286,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) if (!gpio_is_valid(td->ext_te_gpio)) omapdss_dsi_enable_te(dssdev, enable); - if (td->panel_config->sleep.enable_te) - msleep(td->panel_config->sleep.enable_te); + /* possible panel bug */ + msleep(100); return r; } -- cgit v1.2.1 From 346f1e0772cbd087f176fd3e09ffa5a4569812e6 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 15 Feb 2013 14:24:38 +0200 Subject: OMAPDSS: APPLY: remove dssdev from dss_mgr_wait_for_vsync dss_mgr_wait_for_vsync() uses dssdev->type to find out if the output is going to VENC, HDMI, or something else. This creates a dependency on dssdev, which we want to remove. The task is more logically done by looking at the output to which the overlay manager in question is connected to. This patch changes the code to use output->id to find out which kind of output we use. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/apply.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index d446bdfc4c82..a4b356a9780d 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -435,20 +435,27 @@ static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_man static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) { unsigned long timeout = msecs_to_jiffies(500); - struct omap_dss_device *dssdev = mgr->get_device(mgr); u32 irq; int r; + if (mgr->output == NULL) + return -ENODEV; + r = dispc_runtime_get(); if (r) return r; - if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) + switch (mgr->output->id) { + case OMAP_DSS_OUTPUT_VENC: irq = DISPC_IRQ_EVSYNC_ODD; - else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI) + break; + case OMAP_DSS_OUTPUT_HDMI: irq = DISPC_IRQ_EVSYNC_EVEN; - else + break; + default: irq = dispc_mgr_get_vsync_irq(mgr->id); + break; + } r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); -- cgit v1.2.1 From 27831620a6d1b50d1a09f3a5bb3f1451b937b7ed Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 15 Feb 2013 13:47:42 +0200 Subject: OMAPDSS: add missing export for omap_dss_get_output() omap_dss_get_output() is a public function, but was missing EXPORT_SYMBOL(). Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/output.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c index 79dea1a1a732..5214df63e0a9 100644 --- a/drivers/video/omap2/dss/output.c +++ b/drivers/video/omap2/dss/output.c @@ -113,6 +113,7 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id) return NULL; } +EXPORT_SYMBOL(omap_dss_get_output); static const struct dss_mgr_ops *dss_mgr_ops; -- cgit v1.2.1 From 002d368deeae2e8f2a081b21e4e3c1e2b4e69d9d Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 13 Feb 2013 12:17:43 +0200 Subject: OMAPDSS: HDMI: init output earlier Move hdmi driver's output initialization a bit earlier, so that it happens before hdmi panel init. In the future the hdmi panel will depend on the output being ready. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/hdmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index b53de043c03f..04edf325429b 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -1092,6 +1092,8 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) hdmi.ip_data.pll_offset = HDMI_PLLCTRL; hdmi.ip_data.phy_offset = HDMI_PHY; + hdmi_init_output(pdev); + r = hdmi_panel_init(); if (r) { DSSERR("can't init panel\n"); @@ -1100,8 +1102,6 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) dss_debugfs_create_file("hdmi", hdmi_dump_regs); - hdmi_init_output(pdev); - hdmi_probe_pdata(pdev); return 0; -- cgit v1.2.1 From 7286a08fb5607dbcf1a47639609d53d76b60e957 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 18 Feb 2013 13:06:01 +0200 Subject: OMAPDSS: add output->name Add name field to omapdss's outputs so that in the following patches panels refer to the output by their name. The name also helps debugging. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/dpi.c | 1 + drivers/video/omap2/dss/dsi.c | 1 + drivers/video/omap2/dss/hdmi.c | 1 + drivers/video/omap2/dss/rfbi.c | 1 + drivers/video/omap2/dss/sdi.c | 1 + drivers/video/omap2/dss/venc.c | 1 + 6 files changed, 6 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index cb6b280124f1..e393b6ab60db 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -512,6 +512,7 @@ static void __init dpi_init_output(struct platform_device *pdev) out->pdev = pdev; out->id = OMAP_DSS_OUTPUT_DPI; out->type = OMAP_DISPLAY_TYPE_DPI; + out->name = "dpi.0"; dss_register_output(out); } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 815c93047151..294c83299cea 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -5183,6 +5183,7 @@ static void __init dsi_init_output(struct platform_device *dsidev) OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; out->type = OMAP_DISPLAY_TYPE_DSI; + out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1"; dss_register_output(out); } diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 04edf325429b..9cbca03eff43 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -1046,6 +1046,7 @@ static void __init hdmi_init_output(struct platform_device *pdev) out->pdev = pdev; out->id = OMAP_DSS_OUTPUT_HDMI; out->type = OMAP_DISPLAY_TYPE_HDMI; + out->name = "hdmi.0"; dss_register_output(out); } diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index e903dd3f54d9..d9d7f3511a7b 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -1025,6 +1025,7 @@ static void __init rfbi_init_output(struct platform_device *pdev) out->pdev = pdev; out->id = OMAP_DSS_OUTPUT_DBI; out->type = OMAP_DISPLAY_TYPE_DBI; + out->name = "rfbi.0"; dss_register_output(out); } diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 62b5374ce438..c27b58ad8e4d 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -278,6 +278,7 @@ static void __init sdi_init_output(struct platform_device *pdev) out->pdev = pdev; out->id = OMAP_DSS_OUTPUT_SDI; out->type = OMAP_DISPLAY_TYPE_SDI; + out->name = "sdi.0"; dss_register_output(out); } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 006caf3cb509..4c07a25d3d9b 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -819,6 +819,7 @@ static void __init venc_init_output(struct platform_device *pdev) out->pdev = pdev; out->id = OMAP_DSS_OUTPUT_VENC; out->type = OMAP_DISPLAY_TYPE_VENC; + out->name = "venc.0"; dss_register_output(out); } -- cgit v1.2.1 From 2eea5ae6c102a5088e39733115ff7762a4674887 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 13 Feb 2013 11:23:54 +0200 Subject: OMAPDSS: add output->dispc_channel The DISPC channel used for each output is currently passed in panel platform data from the board files. To simplify this, and to make the panel drivers less dependent on OMAP, this patch changes omapdss to resolve the channel independently. The channel is resolved based on the OMAP version and, in case of DSI, the DSI module id. This resolved channel is stored into a new field in output, dispc_channel. The few places where dssdev->channel was used are changed to use output->recommended_channel. After this patch, dssdev->channel is obsolete. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/dpi.c | 38 ++++++++++++++++++++---- drivers/video/omap2/dss/dsi.c | 50 ++++++++++++++++++++++++++++++++ drivers/video/omap2/dss/hdmi.c | 3 +- drivers/video/omap2/dss/rfbi.c | 1 + drivers/video/omap2/dss/sdi.c | 1 + drivers/video/omap2/dss/venc.c | 3 +- drivers/video/omap2/omapfb/omapfb-main.c | 2 +- 7 files changed, 87 insertions(+), 11 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index e393b6ab60db..ab6d8b0e94c7 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -396,6 +396,36 @@ static int __init dpi_verify_dsi_pll(struct platform_device *dsidev) return 0; } +/* + * Return a hardcoded channel for the DPI output. This should work for + * current use cases, but this can be later expanded to either resolve + * the channel in some more dynamic manner, or get the channel as a user + * parameter. + */ +static enum omap_channel dpi_get_channel(void) +{ + switch (omapdss_get_version()) { + case OMAPDSS_VER_OMAP24xx: + case OMAPDSS_VER_OMAP34xx_ES1: + case OMAPDSS_VER_OMAP34xx_ES3: + case OMAPDSS_VER_OMAP3630: + case OMAPDSS_VER_AM35xx: + return OMAP_DSS_CHANNEL_LCD; + + case OMAPDSS_VER_OMAP4430_ES1: + case OMAPDSS_VER_OMAP4430_ES2: + case OMAPDSS_VER_OMAP4: + return OMAP_DSS_CHANNEL_LCD2; + + case OMAPDSS_VER_OMAP5: + return OMAP_DSS_CHANNEL_LCD3; + + default: + DSSWARN("unsupported DSS version\n"); + return OMAP_DSS_CHANNEL_LCD; + } +} + static int __init dpi_init_display(struct omap_dss_device *dssdev) { struct platform_device *dsidev; @@ -416,12 +446,7 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev) dpi.vdds_dsi_reg = vdds_dsi; } - /* - * XXX We shouldn't need dssdev->channel for this. The dsi pll clock - * source for DPI is SoC integration detail, not something that should - * be configured in the dssdev - */ - dsidev = dpi_get_dsidev(dssdev->channel); + dsidev = dpi_get_dsidev(dpi.output.dispc_channel); if (dsidev && dpi_verify_dsi_pll(dsidev)) { dsidev = NULL; @@ -513,6 +538,7 @@ static void __init dpi_init_output(struct platform_device *pdev) out->id = OMAP_DSS_OUTPUT_DPI; out->type = OMAP_DISPLAY_TYPE_DPI; out->name = "dpi.0"; + out->dispc_channel = dpi_get_channel(); dss_register_output(out); } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 294c83299cea..d13e77c01d7e 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4946,6 +4946,55 @@ void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev, } EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings); +/* + * Return a hardcoded channel for the DSI output. This should work for + * current use cases, but this can be later expanded to either resolve + * the channel in some more dynamic manner, or get the channel as a user + * parameter. + */ +static enum omap_channel dsi_get_channel(int module_id) +{ + switch (omapdss_get_version()) { + case OMAPDSS_VER_OMAP24xx: + DSSWARN("DSI not supported\n"); + return OMAP_DSS_CHANNEL_LCD; + + case OMAPDSS_VER_OMAP34xx_ES1: + case OMAPDSS_VER_OMAP34xx_ES3: + case OMAPDSS_VER_OMAP3630: + case OMAPDSS_VER_AM35xx: + return OMAP_DSS_CHANNEL_LCD; + + case OMAPDSS_VER_OMAP4430_ES1: + case OMAPDSS_VER_OMAP4430_ES2: + case OMAPDSS_VER_OMAP4: + switch (module_id) { + case 0: + return OMAP_DSS_CHANNEL_LCD; + case 1: + return OMAP_DSS_CHANNEL_LCD2; + default: + DSSWARN("unsupported module id\n"); + return OMAP_DSS_CHANNEL_LCD; + } + + case OMAPDSS_VER_OMAP5: + switch (module_id) { + case 0: + return OMAP_DSS_CHANNEL_LCD; + case 1: + return OMAP_DSS_CHANNEL_LCD3; + default: + DSSWARN("unsupported module id\n"); + return OMAP_DSS_CHANNEL_LCD; + } + + default: + DSSWARN("unsupported DSS version\n"); + return OMAP_DSS_CHANNEL_LCD; + } +} + static int __init dsi_init_display(struct omap_dss_device *dssdev) { struct platform_device *dsidev = @@ -5184,6 +5233,7 @@ static void __init dsi_init_output(struct platform_device *dsidev) out->type = OMAP_DISPLAY_TYPE_DSI; out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1"; + out->dispc_channel = dsi_get_channel(dsi->module_id); dss_register_output(out); } diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 9cbca03eff43..a6f953898d94 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -1012,8 +1012,6 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev) hdmi.ls_oe_gpio = priv->ls_oe_gpio; hdmi.hpd_gpio = priv->hpd_gpio; - dssdev->channel = OMAP_DSS_CHANNEL_DIGIT; - r = hdmi_init_display(dssdev); if (r) { DSSERR("device %s init failed: %d\n", dssdev->name, r); @@ -1047,6 +1045,7 @@ static void __init hdmi_init_output(struct platform_device *pdev) out->id = OMAP_DSS_OUTPUT_HDMI; out->type = OMAP_DISPLAY_TYPE_HDMI; out->name = "hdmi.0"; + out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; dss_register_output(out); } diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index d9d7f3511a7b..1a691bb27547 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -1026,6 +1026,7 @@ static void __init rfbi_init_output(struct platform_device *pdev) out->id = OMAP_DSS_OUTPUT_DBI; out->type = OMAP_DISPLAY_TYPE_DBI; out->name = "rfbi.0"; + out->dispc_channel = OMAP_DSS_CHANNEL_LCD; dss_register_output(out); } diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index c27b58ad8e4d..3888cfa0881c 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -279,6 +279,7 @@ static void __init sdi_init_output(struct platform_device *pdev) out->id = OMAP_DSS_OUTPUT_SDI; out->type = OMAP_DISPLAY_TYPE_SDI; out->name = "sdi.0"; + out->dispc_channel = OMAP_DSS_CHANNEL_LCD; dss_register_output(out); } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 4c07a25d3d9b..5cb983e2f170 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -786,8 +786,6 @@ static void __init venc_probe_pdata(struct platform_device *vencdev) dss_copy_device_pdata(dssdev, plat_dssdev); - dssdev->channel = OMAP_DSS_CHANNEL_DIGIT; - r = venc_init_display(dssdev); if (r) { DSSERR("device %s init failed: %d\n", dssdev->name, r); @@ -820,6 +818,7 @@ static void __init venc_init_output(struct platform_device *pdev) out->id = OMAP_DSS_OUTPUT_VENC; out->type = OMAP_DISPLAY_TYPE_VENC; out->name = "venc.0"; + out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; dss_register_output(out); } diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index ca585ef37f25..f38348ea3375 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -2388,7 +2388,7 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev, struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; struct omap_dss_output *out = dssdev->output; - mgr = omap_dss_get_overlay_manager(dssdev->channel); + mgr = omap_dss_get_overlay_manager(out->dispc_channel); if (!mgr || !out) continue; -- cgit v1.2.1 From b7dec9b66f49304470291a95ea3855c9c9fe193b Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 22 Feb 2013 12:58:35 +0200 Subject: OMAPDSS: DSI: delay dispc initialization We currently setup both DSI and DISPC related things when the DSI bus is enabled. There's no need for DISPC related thing at that point, though, but only later when the video output is enabled. To make it possible to use the DSI bus before DISPC overlay manager is selected, this patch moves DSI's DISPC initialization to dsi_enable_video_output(), from omapdss_dsi_display_enable(). We also move the selection of DISPC's LCD clock to dsi_enable_video_output. This way there are no DISPC dependencies until the video output is enabled. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/dsi.c | 75 +++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 35 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index d13e77c01d7e..c9f9d0faf8e3 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -200,6 +200,11 @@ struct dsi_reg { u16 idx; }; typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); +static int dsi_display_init_dispc(struct platform_device *dsidev, + struct omap_overlay_manager *mgr); +static void dsi_display_uninit_dispc(struct platform_device *dsidev, + struct omap_overlay_manager *mgr); + #define DSI_MAX_NR_ISRS 2 #define DSI_MAX_NR_LANES 5 @@ -4342,10 +4347,20 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct omap_overlay_manager *mgr = dsi->output.manager; int bpp = dsi_get_pixel_size(dsi->pix_fmt); + struct omap_dss_output *out = &dsi->output; u8 data_type; u16 word_count; int r; + if (out == NULL || out->manager == NULL) { + DSSERR("failed to enable display: no output/manager\n"); + return -ENODEV; + } + + r = dsi_display_init_dispc(dsidev, mgr); + if (r) + goto err_init_dispc; + if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { switch (dsi->pix_fmt) { case OMAP_DSS_DSI_FMT_RGB888: @@ -4361,8 +4376,8 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; break; default: - BUG(); - return -EINVAL; + r = -EINVAL; + goto err_pix_fmt; }; dsi_if_enable(dsidev, false); @@ -4381,16 +4396,20 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) } r = dss_mgr_enable(mgr); - if (r) { - if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { - dsi_if_enable(dsidev, false); - dsi_vc_enable(dsidev, channel, false); - } - - return r; - } + if (r) + goto err_mgr_enable; return 0; + +err_mgr_enable: + if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { + dsi_if_enable(dsidev, false); + dsi_vc_enable(dsidev, channel, false); + } +err_pix_fmt: + dsi_display_uninit_dispc(dsidev, mgr); +err_init_dispc: + return r; } EXPORT_SYMBOL(dsi_enable_video_output); @@ -4412,6 +4431,8 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) } dss_mgr_disable(mgr); + + dsi_display_uninit_dispc(dsidev, mgr); } EXPORT_SYMBOL(dsi_disable_video_output); @@ -4605,12 +4626,14 @@ static int dsi_configure_dispc_clocks(struct platform_device *dsidev) return 0; } -static int dsi_display_init_dispc(struct platform_device *dsidev) +static int dsi_display_init_dispc(struct platform_device *dsidev, + struct omap_overlay_manager *mgr) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - struct omap_overlay_manager *mgr = dsi->output.manager; int r; + dss_select_lcd_clk_source(mgr->id, dsi->user_lcd_clk_src); + if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { dsi->timings.hsw = 1; dsi->timings.hfp = 1; @@ -4663,17 +4686,20 @@ err1: dss_mgr_unregister_framedone_handler(mgr, dsi_framedone_irq_callback, dsidev); err: + dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); return r; } -static void dsi_display_uninit_dispc(struct platform_device *dsidev) +static void dsi_display_uninit_dispc(struct platform_device *dsidev, + struct omap_overlay_manager *mgr) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - struct omap_overlay_manager *mgr = dsi->output.manager; if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) dss_mgr_unregister_framedone_handler(mgr, dsi_framedone_irq_callback, dsidev); + + dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); } static int dsi_configure_dsi_clocks(struct platform_device *dsidev) @@ -4702,7 +4728,6 @@ static int dsi_configure_dsi_clocks(struct platform_device *dsidev) static int dsi_display_init_dsi(struct platform_device *dsidev) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - struct omap_overlay_manager *mgr = dsi->output.manager; int r; r = dsi_pll_init(dsidev, true, true); @@ -4714,7 +4739,6 @@ static int dsi_display_init_dsi(struct platform_device *dsidev) goto err1; dss_select_dsi_clk_source(dsi->module_id, dsi->user_dsi_fclk_src); - dss_select_lcd_clk_source(mgr->id, dsi->user_lcd_clk_src); DSSDBG("PLL OK\n"); @@ -4747,8 +4771,6 @@ err3: dsi_cio_uninit(dsidev); err2: dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); - dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); - err1: dsi_pll_uninit(dsidev, true); err0: @@ -4759,7 +4781,6 @@ static void dsi_display_uninit_dsi(struct platform_device *dsidev, bool disconnect_lanes, bool enter_ulps) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - struct omap_overlay_manager *mgr = dsi->output.manager; if (enter_ulps && !dsi->ulps_enabled) dsi_enter_ulps(dsidev); @@ -4772,7 +4793,6 @@ static void dsi_display_uninit_dsi(struct platform_device *dsidev, dsi_vc_enable(dsidev, 3, 0); dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); - dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); dsi_cio_uninit(dsidev); dsi_pll_uninit(dsidev, disconnect_lanes); } @@ -4781,7 +4801,6 @@ 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 = &dsi->output; int r = 0; DSSDBG("dsi_display_enable\n"); @@ -4790,12 +4809,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) mutex_lock(&dsi->lock); - if (out == NULL || out->manager == NULL) { - DSSERR("failed to enable display: no output/manager\n"); - r = -ENODEV; - goto err_start_dev; - } - r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); @@ -4810,10 +4823,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) _dsi_initialize_irq(dsidev); - r = dsi_display_init_dispc(dsidev); - if (r) - goto err_init_dispc; - r = dsi_display_init_dsi(dsidev); if (r) goto err_init_dsi; @@ -4823,8 +4832,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) return 0; err_init_dsi: - dsi_display_uninit_dispc(dsidev); -err_init_dispc: dsi_enable_pll_clock(dsidev, 0); dsi_runtime_put(dsidev); err_get_dsi: @@ -4853,8 +4860,6 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, dsi_sync_vc(dsidev, 2); dsi_sync_vc(dsidev, 3); - dsi_display_uninit_dispc(dsidev); - dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps); dsi_runtime_put(dsidev); -- cgit v1.2.1 From 2c1a3ea0dc48d6b5d580781578a40f9a9e4acef8 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 22 Feb 2013 13:42:59 +0200 Subject: OMAPDSS: DSI: fix DSI channel source initialization During the initialization of the DSI protocol registers, we always set the sources of all DSI channels to L4. However, we don't update the value in the dsi_data, so we may end up with a different value in the register and in the dsi_data, leading to DSI problems. This patch fixes the issue by initializing also the channel source in the dsi_data. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/dsi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index c9f9d0faf8e3..b0eed4323394 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2794,6 +2794,7 @@ static int dsi_vc_enable(struct platform_device *dsidev, int channel, static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) { + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); u32 r; DSSDBG("Initial config of virtual channel %d", channel); @@ -2818,6 +2819,8 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); + + dsi->vc[channel].source = DSI_VC_SOURCE_L4; } static int dsi_vc_config_source(struct platform_device *dsidev, int channel, -- cgit v1.2.1 From d9f4e46714b11503f53619e9896db0506c35351c Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 4 Mar 2013 12:57:35 +0200 Subject: OMAPDSS: Taal: remove rotate & mirror support Taal panel driver has support to set rotation and mirroring. However, these features cannot be used without causing tearing, and are never used. The code is just extra bloat, so let's remove it. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/displays/panel-taal.c | 170 +----------------------------- 1 file changed, 2 insertions(+), 168 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 038a815ba6c8..bc4c95ee41cc 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -76,8 +76,6 @@ struct taal_data { /* runtime variables */ bool enabled; - u8 rotate; - bool mirror; bool te_enabled; @@ -202,49 +200,6 @@ static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3) return 0; } -static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) -{ - int r; - u8 mode; - int b5, b6, b7; - - r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode); - if (r) - return r; - - switch (rotate) { - default: - case 0: - b7 = 0; - b6 = 0; - b5 = 0; - break; - case 1: - b7 = 0; - b6 = 1; - b5 = 1; - break; - case 2: - b7 = 1; - b6 = 1; - b5 = 0; - break; - case 3: - b7 = 1; - b6 = 0; - b5 = 1; - break; - } - - if (mirror) - b6 = !b6; - - mode &= ~((1<<7) | (1<<6) | (1<<5)); - mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); - - return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode); -} - static int taal_set_update_window(struct taal_data *td, u16 x, u16 y, u16 w, u16 h) { @@ -455,15 +410,8 @@ static const struct backlight_ops taal_bl_ops = { static void taal_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) { - struct taal_data *td = dev_get_drvdata(&dssdev->dev); - - if (td->rotate == 0 || td->rotate == 2) { - *xres = dssdev->panel.timings.x_res; - *yres = dssdev->panel.timings.y_res; - } else { - *yres = dssdev->panel.timings.x_res; - *xres = dssdev->panel.timings.y_res; - } + *xres = dssdev->panel.timings.x_res; + *yres = dssdev->panel.timings.y_res; } static ssize_t taal_num_errors_show(struct device *dev, @@ -1025,10 +973,6 @@ static int taal_power_on(struct omap_dss_device *dssdev) if (r) goto err; - r = taal_set_addr_mode(td, td->rotate, td->mirror); - if (r) - goto err; - if (!td->cabc_broken) { r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode); if (r) @@ -1340,112 +1284,6 @@ static int taal_get_te(struct omap_dss_device *dssdev) return r; } -static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) -{ - struct taal_data *td = dev_get_drvdata(&dssdev->dev); - u16 dw, dh; - int r; - - dev_dbg(&dssdev->dev, "rotate %d\n", rotate); - - mutex_lock(&td->lock); - - if (td->rotate == rotate) - goto end; - - dsi_bus_lock(dssdev); - - if (td->enabled) { - r = taal_wake_up(dssdev); - if (r) - goto err; - - r = taal_set_addr_mode(td, rotate, td->mirror); - if (r) - goto err; - } - - if (rotate == 0 || rotate == 2) { - dw = dssdev->panel.timings.x_res; - dh = dssdev->panel.timings.y_res; - } else { - dw = dssdev->panel.timings.y_res; - dh = dssdev->panel.timings.x_res; - } - - omapdss_dsi_set_size(dssdev, dw, dh); - - td->rotate = rotate; - - dsi_bus_unlock(dssdev); -end: - mutex_unlock(&td->lock); - return 0; -err: - dsi_bus_unlock(dssdev); - mutex_unlock(&td->lock); - return r; -} - -static u8 taal_get_rotate(struct omap_dss_device *dssdev) -{ - struct taal_data *td = dev_get_drvdata(&dssdev->dev); - int r; - - mutex_lock(&td->lock); - r = td->rotate; - mutex_unlock(&td->lock); - - return r; -} - -static int taal_mirror(struct omap_dss_device *dssdev, bool enable) -{ - struct taal_data *td = dev_get_drvdata(&dssdev->dev); - int r; - - dev_dbg(&dssdev->dev, "mirror %d\n", enable); - - mutex_lock(&td->lock); - - if (td->mirror == enable) - goto end; - - dsi_bus_lock(dssdev); - if (td->enabled) { - r = taal_wake_up(dssdev); - if (r) - goto err; - - r = taal_set_addr_mode(td, td->rotate, enable); - if (r) - goto err; - } - - td->mirror = enable; - - dsi_bus_unlock(dssdev); -end: - mutex_unlock(&td->lock); - return 0; -err: - dsi_bus_unlock(dssdev); - mutex_unlock(&td->lock); - return r; -} - -static bool taal_get_mirror(struct omap_dss_device *dssdev) -{ - struct taal_data *td = dev_get_drvdata(&dssdev->dev); - int r; - - mutex_lock(&td->lock); - r = td->mirror; - mutex_unlock(&td->lock); - - return r; -} - static int taal_run_test(struct omap_dss_device *dssdev, int test_num) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); @@ -1679,10 +1517,6 @@ static struct omap_dss_driver taal_driver = { .enable_te = taal_enable_te, .get_te = taal_get_te, - .set_rotate = taal_rotate, - .get_rotate = taal_get_rotate, - .set_mirror = taal_mirror, - .get_mirror = taal_get_mirror, .run_test = taal_run_test, .memory_read = taal_memory_read, -- cgit v1.2.1 From f8ad984ce0372f43006f5c700310c2d6f301085d Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 11 Mar 2013 13:57:38 +0200 Subject: OMAPDSS: DPI: fix dpi_get_dsidev() for omap5 On OMAP5 the DISPC channels and DSI PLLs are not connected the same way. LCD2 on OMAP5 cannot use any DSI PLL as a source clock, but LCD3 can use DSI2's PLL. This patch fixes dpi_get_dsidev() by adding separate case for OMAP5 to handle the difference. Signed-off-by: Tomi Valkeinen Reviewed-by: Archit Taneja --- drivers/video/omap2/dss/dpi.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index ab6d8b0e94c7..c8c7776c8cfa 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -63,15 +63,29 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel) case OMAPDSS_VER_OMAP3630: case OMAPDSS_VER_AM35xx: return NULL; - default: - break; - } - switch (channel) { - case OMAP_DSS_CHANNEL_LCD: - return dsi_get_dsidev_from_id(0); - case OMAP_DSS_CHANNEL_LCD2: - return dsi_get_dsidev_from_id(1); + case OMAPDSS_VER_OMAP4430_ES1: + case OMAPDSS_VER_OMAP4430_ES2: + case OMAPDSS_VER_OMAP4: + switch (channel) { + case OMAP_DSS_CHANNEL_LCD: + return dsi_get_dsidev_from_id(0); + case OMAP_DSS_CHANNEL_LCD2: + return dsi_get_dsidev_from_id(1); + default: + return NULL; + } + + case OMAPDSS_VER_OMAP5: + switch (channel) { + case OMAP_DSS_CHANNEL_LCD: + return dsi_get_dsidev_from_id(0); + case OMAP_DSS_CHANNEL_LCD3: + return dsi_get_dsidev_from_id(1); + default: + return NULL; + } + default: return NULL; } -- cgit v1.2.1 From 7b3926b3b9d11d0fbb613ae747f44200142e1c98 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 6 Mar 2013 15:54:11 +0200 Subject: OMAPDSS: DISPC: store core clk rate Store dispc core clock rate so that it's available for calculations even if the HW is disabled. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 05ff2b91d9e8..f564955ddd9e 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -97,6 +97,8 @@ static struct { int irq; + unsigned long core_clk_rate; + u32 fifo_size[DISPC_MAX_NR_FIFOS]; /* maps which plane is using a fifo. fifo-id -> plane-id */ int fifo_assignment[DISPC_MAX_NR_FIFOS]; @@ -2951,6 +2953,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, dispc_write_reg(DISPC_DIVISORo(channel), FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); + + if (dss_has_feature(FEAT_CORE_CLK_DIV) == false && + channel == OMAP_DSS_CHANNEL_LCD) + dispc.core_clk_rate = dispc_fclk_rate() / lck_div; } static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div, @@ -3056,15 +3062,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) unsigned long dispc_core_clk_rate(void) { - int lcd; - unsigned long fclk = dispc_fclk_rate(); - - if (dss_has_feature(FEAT_CORE_CLK_DIV)) - lcd = REG_GET(DISPC_DIVISOR, 23, 16); - else - lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16); - - return fclk / lcd; + return dispc.core_clk_rate; } static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) @@ -3451,6 +3449,8 @@ static void _omap_dispc_initial_config(void) l = FLD_MOD(l, 1, 0, 0); l = FLD_MOD(l, 1, 23, 16); dispc_write_reg(DISPC_DIVISOR, l); + + dispc.core_clk_rate = dispc_fclk_rate(); } /* FUNCGATED */ -- cgit v1.2.1 From 17518189218cdf4c8136ce6f0284519b9a878a09 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 7 Mar 2013 11:21:45 +0200 Subject: OMAPDSS: DSI: fix wrong unsigned long long use dsi_configure_dispc_clocks() stores dsi func clock into unsigned long long, but it should really be just unsigned long. Fix this. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index b0eed4323394..dd13bd9138fc 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4611,7 +4611,7 @@ static int dsi_configure_dispc_clocks(struct platform_device *dsidev) struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct dispc_clock_info dispc_cinfo; int r; - unsigned long long fck; + unsigned long fck; fck = dsi_get_pll_hsdiv_dispc_rate(dsidev); -- cgit v1.2.1 From 777f05cc79892c1a5c25a72cfb3cc24554378a45 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 6 Mar 2013 11:10:29 +0200 Subject: OMAPDSS: DSI: simplify dsi configuration We have a bunch of dsi functions that are used to do the basic configuration for DSI. To simplify things, and to make sure we have all the necessary information, create a single dsi config function, which does the basic configuration. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/panel-taal.c | 16 ++++--- drivers/video/omap2/dss/dsi.c | 74 +++++-------------------------- 2 files changed, 19 insertions(+), 71 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index bc4c95ee41cc..eb86cbae8c2a 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -919,6 +919,13 @@ static int taal_power_on(struct omap_dss_device *dssdev) struct taal_data *td = dev_get_drvdata(&dssdev->dev); u8 id1, id2, id3; int r; + struct omap_dss_dsi_config dsi_config = { + .mode = OMAP_DSS_DSI_CMD_MODE, + .pixel_format = OMAP_DSS_DSI_FMT_RGB888, + .timings = &dssdev->panel.timings, + .hs_clk = 216000000, + .lp_clk = 10000000, + }; r = omapdss_dsi_configure_pins(dssdev, &td->pin_config); if (r) { @@ -926,14 +933,9 @@ static int taal_power_on(struct omap_dss_device *dssdev) goto err0; }; - omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res, - dssdev->panel.timings.y_res); - omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888); - omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE); - - r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000); + r = omapdss_dsi_set_config(dssdev, &dsi_config); if (r) { - dev_err(&dssdev->dev, "failed to set HS and LP clocks\n"); + dev_err(&dssdev->dev, "failed to configure DSI\n"); goto err0; } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index dd13bd9138fc..8cb43af60fe1 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4278,7 +4278,7 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev, } EXPORT_SYMBOL(omapdss_dsi_configure_pins); -int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, +static int 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); @@ -4293,8 +4293,6 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, DSSDBG("Setting DSI clocks: 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) @@ -4336,13 +4334,10 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, 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) { @@ -4884,75 +4879,26 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) } EXPORT_SYMBOL(omapdss_dsi_enable_te); -void omapdss_dsi_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) +int omapdss_dsi_set_config(struct omap_dss_device *dssdev, + const struct omap_dss_dsi_config *config) { 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 = *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 = *config->timings; + dsi->vm_timings = *config->vm_timings; + dsi->pix_fmt = config->pixel_format; + dsi->mode = config->mode; - dsi->timings.x_res = w; - dsi->timings.y_res = h; + dsi_set_clocks(dssdev, config->hs_clk, config->lp_clk); 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); + return 0; } -EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings); +EXPORT_SYMBOL(omapdss_dsi_set_config); /* * Return a hardcoded channel for the DSI output. This should work for -- cgit v1.2.1 From 99322577e80da240cebc087da9ea328bb0960be1 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 10:37:02 +0200 Subject: OMAPDSS: DSI: get line buffer size at probe To find out the DSI line buffer size we need to read HW registers. To make it possible to do DSI configuration calculations without HW powered up, store the line buffer size at DSI driver's probe. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 8cb43af60fe1..590da06e6a82 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -336,6 +336,7 @@ struct dsi_data { unsigned long lpdiv_max; unsigned num_lanes_supported; + unsigned line_buffer_size; struct dsi_lane_config lanes[DSI_MAX_NR_LANES]; unsigned num_lanes_used; @@ -3791,13 +3792,12 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev) 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 = &dsi->timings; /* * Don't use line buffers if width is greater than the video * port's line buffer size */ - if (line_buf_size <= timings->x_res * bpp / 8) + if (dsi->line_buffer_size <= timings->x_res * bpp / 8) num_line_buffers = 0; else num_line_buffers = 2; @@ -4447,7 +4447,7 @@ static void dsi_update_screen_dispc(struct platform_device *dsidev) u32 l; int r; const unsigned channel = dsi->update_channel; - const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); + const unsigned line_buf_size = dsi->line_buffer_size; u16 w = dsi->timings.x_res; u16 h = dsi->timings.y_res; @@ -5293,6 +5293,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev) else dsi->num_lanes_supported = 3; + dsi->line_buffer_size = dsi_get_line_buf_size(dsidev); + dsi_init_output(dsidev); dsi_probe_pdata(dsidev); -- cgit v1.2.1 From 478d7df8af89f449bacc4e67ff35dc630400c0ca Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 16:29:36 +0200 Subject: OMAPDSS: DSI: add enum omap_dss_dsi_trans_mode Instead of managing DSI sync ends with booleans, add an enum for the DSI transfer mode. This is much cleaner way to handle the DSI syncs. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 590da06e6a82..e8f5bdb2796c 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3813,18 +3813,22 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev) static void dsi_config_vp_sync_events(struct platform_device *dsidev) { 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; + bool sync_end; u32 r; + if (dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE) + sync_end = true; + else + sync_end = false; + r = dsi_read_reg(dsidev, DSI_CTRL); r = FLD_MOD(r, 1, 9, 9); /* VP_DE_POL */ r = FLD_MOD(r, 1, 10, 10); /* VP_HSYNC_POL */ r = FLD_MOD(r, 1, 11, 11); /* VP_VSYNC_POL */ r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */ - r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */ + r = FLD_MOD(r, sync_end, 16, 16); /* VP_VSYNC_END */ r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */ - r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */ + r = FLD_MOD(r, sync_end, 18, 18); /* VP_HSYNC_END */ dsi_write_reg(dsidev, DSI_CTRL, r); } @@ -4171,11 +4175,12 @@ static void dsi_proto_timings(struct platform_device *dsidev) 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; + bool hsync_end; struct omap_video_timings *timings = &dsi->timings; int bpp = dsi_get_pixel_size(dsi->pix_fmt); int tl, t_he, width_bytes; + hsync_end = dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE; t_he = hsync_end ? ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; -- cgit v1.2.1 From 4ce9e33c0f6abc4203f25f5fc287bf072de32513 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 17:11:16 +0200 Subject: OMAPDSS: DSI remove unneeded clk source setup code We always use the same clock sources for DSI, so let's remove the unnecessary clock source fields from dsi_data. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index e8f5bdb2796c..110a505332db 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -269,10 +269,6 @@ struct dsi_data { struct dispc_clock_info user_dispc_cinfo; struct dsi_clock_info user_dsi_cinfo; - enum omap_dss_clk_source user_dispc_fclk_src; - enum omap_dss_clk_source user_lcd_clk_src; - enum omap_dss_clk_source user_dsi_fclk_src; - struct dsi_clock_info current_cinfo; bool vdds_dsi_enabled; @@ -4327,18 +4323,6 @@ static int dsi_set_clocks(struct omap_dss_device *dssdev, dsi->user_dispc_cinfo.lck_div = dispc_cinfo.lck_div; dsi->user_dispc_cinfo.pck_div = dispc_cinfo.pck_div; - dsi->user_dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK; - - dsi->user_lcd_clk_src = - dsi->module_id == 0 ? - OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : - OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC; - - dsi->user_dsi_fclk_src = - dsi->module_id == 0 ? - OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : - OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI; - return 0; err: return r; @@ -4635,7 +4619,9 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int r; - dss_select_lcd_clk_source(mgr->id, dsi->user_lcd_clk_src); + dss_select_lcd_clk_source(mgr->id, dsi->module_id == 0 ? + OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : + OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC); if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { dsi->timings.hsw = 1; @@ -4741,7 +4727,9 @@ static int dsi_display_init_dsi(struct platform_device *dsidev) if (r) goto err1; - dss_select_dsi_clk_source(dsi->module_id, dsi->user_dsi_fclk_src); + dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ? + OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : + OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI); DSSDBG("PLL OK\n"); -- cgit v1.2.1 From 7c284e6ee3710e96bf246e6b52032f3d766fa094 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 16:32:08 +0200 Subject: OMAPDSS: DISPC: add new clock calculation code Add new way to iterate over DISPC clock divisors. dispc_div_calc() provides a generic way to go over all the divisors, within given pixel clock range. dispc_div_calc() will call a callback function for each divider set, making the function reusable for all use cases. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 60 +++++++++++++++++++++++++++++++++++++++++ drivers/video/omap2/dss/dss.h | 6 +++++ 2 files changed, 66 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index f564955ddd9e..cd54e8fe2d58 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3374,6 +3374,66 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, return 0; } +bool dispc_div_calc(unsigned long dispc, + unsigned long pck_min, unsigned long pck_max, + dispc_div_calc_func func, void *data) +{ + int lckd, lckd_start, lckd_stop; + int pckd, pckd_start, pckd_stop; + unsigned long pck, lck; + unsigned long lck_max; + unsigned long pckd_hw_min, pckd_hw_max; + unsigned min_fck_per_pck; + unsigned long fck; + +#ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK + min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; +#else + min_fck_per_pck = 0; +#endif + + pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); + pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); + + lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + + pck_min = pck_min ? pck_min : 1; + pck_max = pck_max ? pck_max : ULONG_MAX; + + lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul); + lckd_stop = min(dispc / pck_min, 255ul); + + for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) { + lck = dispc / lckd; + + pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min); + pckd_stop = min(lck / pck_min, pckd_hw_max); + + for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) { + pck = lck / pckd; + + /* + * For OMAP2/3 the DISPC fclk is the same as LCD's logic + * clock, which means we're configuring DISPC fclk here + * also. Thus we need to use the calculated lck. For + * OMAP4+ the DISPC fclk is a separate clock. + */ + if (dss_has_feature(FEAT_CORE_CLK_DIV)) + fck = dispc_core_clk_rate(); + else + fck = lck; + + if (fck < pck * min_fck_per_pck) + continue; + + if (func(lckd, pckd, lck, pck, data)) + return true; + } + } + + return false; +} + void dispc_mgr_set_clock_div(enum omap_channel channel, const struct dispc_clock_info *cinfo) { diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 610c8e563daa..0ff41dd8f3c5 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -376,6 +376,12 @@ void dispc_enable_fifomerge(bool enable); void dispc_enable_gamma_table(bool enable); void dispc_set_loadmode(enum omap_dss_load_mode mode); +typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck, + unsigned long pck, void *data); +bool dispc_div_calc(unsigned long dispc, + unsigned long pck_min, unsigned long pck_max, + dispc_div_calc_func func, void *data); + bool dispc_mgr_timings_ok(enum omap_channel channel, const struct omap_video_timings *timings); unsigned long dispc_fclk_rate(void); -- cgit v1.2.1 From 43417823fd8210edb7e714bea82ea9bd77089635 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 16:34:05 +0200 Subject: OMAPDSS: DSS: add new clock calculation code Add new way to iterate over DSS clock divisors. dss_div_calc() provides a generic way to go over all the divisors, within given clock range. dss_div_calc() will call a callback function for each divider set, making the function reusable for all use cases. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/video/omap2/dss/dss.h | 3 +++ 2 files changed, 42 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 054c2a22b3f1..eba4127b61a6 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -473,6 +473,45 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo) return 0; } +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) +{ + int fckd, fckd_start, fckd_stop; + unsigned long fck; + unsigned long fck_hw_max; + unsigned long fckd_hw_max; + unsigned long prate; + + if (dss.dpll4_m4_ck == NULL) { + /* + * TODO: dss1_fclk can be changed on OMAP2, but the available + * dividers are not continuous. We just use the pre-set rate for + * now. + */ + fck = clk_get_rate(dss.dss_clk); + fckd = 1; + return func(fckd, fck, data); + } + + fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + fckd_hw_max = dss.feat->fck_div_max; + + prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier; + + fck_min = fck_min ? fck_min : 1; + + fckd_start = min(prate / fck_min, fckd_hw_max); + fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul); + + for (fckd = fckd_start; fckd >= fckd_stop; --fckd) { + fck = prate / fckd; + + if (func(fckd, fck, data)) + return true; + } + + return false; +} + int dss_set_clock_div(struct dss_clock_info *cinfo) { if (dss.dpll4_m4_ck) { diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 0ff41dd8f3c5..4180302a7fb3 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -271,6 +271,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo); int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, struct dispc_clock_info *dispc_cinfo); +typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data); +bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data); + /* SDI */ int sdi_init_platform_driver(void) __init; void sdi_uninit_platform_driver(void) __exit; -- cgit v1.2.1 From 72658f0716f36efad19d37517456b4a8a7cc7840 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 16:39:00 +0200 Subject: OMAPDSS: DSI: add new clock calculation code Add new way to iterate over DSI PLL and HSDIV clock divisors. dsi_pll_calc() and dss_hsdiv_calc() provide a generic way to go over all the divisors, within given clock range. The functions will call a callback function for each divider set, making the function reusable for all use cases. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 69 +++++++++++++++++++++++++++++++++++++++++++ drivers/video/omap2/dss/dss.h | 12 ++++++++ 2 files changed, 81 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 110a505332db..a4e0560c2799 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1280,6 +1280,75 @@ static int dsi_pll_power(struct platform_device *dsidev, return 0; } +unsigned long dsi_get_pll_clkin(struct platform_device *dsidev) +{ + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + return clk_get_rate(dsi->sys_clk); +} + +bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll, + unsigned long out_min, dsi_hsdiv_calc_func func, void *data) +{ + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + int regm, regm_start, regm_stop; + unsigned long out_max; + unsigned long out; + + out_min = out_min ? out_min : 1; + out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + + regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul); + regm_stop = min(pll / out_min, dsi->regm_dispc_max); + + for (regm = regm_start; regm <= regm_stop; ++regm) { + out = pll / regm; + + if (func(regm, out, data)) + return true; + } + + return false; +} + +bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin, + unsigned long pll_min, unsigned long pll_max, + dsi_pll_calc_func func, void *data) +{ + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + int regn, regn_start, regn_stop; + int regm, regm_start, regm_stop; + unsigned long fint, pll; + const unsigned long pll_hw_max = 1800000000; + unsigned long fint_hw_min, fint_hw_max; + + fint_hw_min = dsi->fint_min; + fint_hw_max = dsi->fint_max; + + regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); + regn_stop = min(clkin / fint_hw_min, dsi->regn_max); + + pll_max = pll_max ? pll_max : ULONG_MAX; + + for (regn = regn_start; regn <= regn_stop; ++regn) { + fint = clkin / regn; + + regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2), + 1ul); + regm_stop = min3(pll_max / fint / 2, + pll_hw_max / fint / 2, + dsi->regm_max); + + for (regm = regm_start; regm <= regm_stop; ++regm) { + pll = 2 * regm * fint; + + if (func(regn, regm, fint, pll, data)) + return true; + } + } + + return false; +} + /* calculate clock rates using dividers in cinfo */ static int dsi_calc_clock_rates(struct platform_device *dsidev, struct dsi_clock_info *cinfo) diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 4180302a7fb3..dde6cc109480 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -295,6 +295,18 @@ void dsi_dump_clocks(struct seq_file *s); void dsi_irq_handler(void); u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); +unsigned long dsi_get_pll_clkin(struct platform_device *dsidev); + +typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint, + unsigned long pll, void *data); +typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc, + void *data); +bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll, + unsigned long out_min, dsi_hsdiv_calc_func func, void *data); +bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin, + unsigned long pll_min, unsigned long pll_max, + dsi_pll_calc_func func, void *data); + unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); int dsi_pll_set_clock_div(struct platform_device *dsidev, struct dsi_clock_info *cinfo); -- cgit v1.2.1 From 36816faadff37ac7d29be20471d37a2b938ece5d Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 17:06:26 +0200 Subject: OMAPDSS: SDI: use new clock calculation code Use the new clock calculation code in the SDI driver. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/sdi.c | 68 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 3888cfa0881c..e6baee2e84f8 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -41,6 +41,72 @@ static struct { struct omap_dss_output output; } sdi; +struct sdi_clk_calc_ctx { + unsigned long pck_min, pck_max; + + struct dss_clock_info dss_cinfo; + struct dispc_clock_info dispc_cinfo; +}; + +static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck, + unsigned long pck, void *data) +{ + struct sdi_clk_calc_ctx *ctx = data; + + ctx->dispc_cinfo.lck_div = lckd; + ctx->dispc_cinfo.pck_div = pckd; + ctx->dispc_cinfo.lck = lck; + ctx->dispc_cinfo.pck = pck; + + return true; +} + +static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data) +{ + struct sdi_clk_calc_ctx *ctx = data; + + ctx->dss_cinfo.fck = fck; + ctx->dss_cinfo.fck_div = fckd; + + return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max, + dpi_calc_dispc_cb, ctx); +} + +static int sdi_calc_clock_div(unsigned long pclk, + struct dss_clock_info *dss_cinfo, + struct dispc_clock_info *dispc_cinfo) +{ + int i; + struct sdi_clk_calc_ctx ctx; + + /* + * DSS fclk gives us very few possibilities, so finding a good pixel + * clock may not be possible. We try multiple times to find the clock, + * each time widening the pixel clock range we look for, up to + * +/- 1MHz. + */ + + for (i = 0; i < 10; ++i) { + bool ok; + + memset(&ctx, 0, sizeof(ctx)); + if (pclk > 1000 * i * i * i) + ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu); + else + ctx.pck_min = 0; + ctx.pck_max = pclk + 1000 * i * i * i; + + ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx); + if (ok) { + *dss_cinfo = ctx.dss_cinfo; + *dispc_cinfo = ctx.dispc_cinfo; + return 0; + } + } + + return -EINVAL; +} + static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) { struct omap_overlay_manager *mgr = dssdev->output->manager; @@ -88,7 +154,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; - r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); + r = sdi_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); if (r) goto err_calc_clock_div; -- cgit v1.2.1 From 100c826235793345efe06b3558cc9d36166b1e26 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 17:07:16 +0200 Subject: OMAPDSS: DPI: use new clock calculation code Use the new clock calculation code in the DPI driver. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dpi.c | 212 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 172 insertions(+), 40 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index c8c7776c8cfa..abe1a4e23c36 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -105,31 +105,170 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel) } } +struct dpi_clk_calc_ctx { + struct platform_device *dsidev; + + /* inputs */ + + unsigned long pck_min, pck_max; + + /* outputs */ + + struct dsi_clock_info dsi_cinfo; + struct dss_clock_info dss_cinfo; + struct dispc_clock_info dispc_cinfo; +}; + +static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck, + unsigned long pck, void *data) +{ + struct dpi_clk_calc_ctx *ctx = data; + + /* + * Odd dividers give us uneven duty cycle, causing problem when level + * shifted. So skip all odd dividers when the pixel clock is on the + * higher side. + */ + if (ctx->pck_min >= 1000000) { + if (lckd > 1 && lckd % 2 != 0) + return false; + + if (pckd > 1 && pckd % 2 != 0) + return false; + } + + ctx->dispc_cinfo.lck_div = lckd; + ctx->dispc_cinfo.pck_div = pckd; + ctx->dispc_cinfo.lck = lck; + ctx->dispc_cinfo.pck = pck; + + return true; +} + + +static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, + void *data) +{ + struct dpi_clk_calc_ctx *ctx = data; + + /* + * Odd dividers give us uneven duty cycle, causing problem when level + * shifted. So skip all odd dividers when the pixel clock is on the + * higher side. + */ + if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 1000000) + return false; + + ctx->dsi_cinfo.regm_dispc = regm_dispc; + ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc; + + return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max, + dpi_calc_dispc_cb, ctx); +} + + +static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint, + unsigned long pll, + void *data) +{ + struct dpi_clk_calc_ctx *ctx = data; + + ctx->dsi_cinfo.regn = regn; + ctx->dsi_cinfo.regm = regm; + ctx->dsi_cinfo.fint = fint; + ctx->dsi_cinfo.clkin4ddr = pll; + + return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min, + dpi_calc_hsdiv_cb, ctx); +} + +static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data) +{ + struct dpi_clk_calc_ctx *ctx = data; + + ctx->dss_cinfo.fck = fck; + ctx->dss_cinfo.fck_div = fckd; + + return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max, + dpi_calc_dispc_cb, ctx); +} + +static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) +{ + unsigned long clkin; + unsigned long pll_min, pll_max; + + clkin = dsi_get_pll_clkin(dpi.dsidev); + + memset(ctx, 0, sizeof(*ctx)); + ctx->dsidev = dpi.dsidev; + ctx->pck_min = pck - 1000; + ctx->pck_max = pck + 1000; + ctx->dsi_cinfo.clkin = clkin; + + pll_min = 0; + pll_max = 0; + + return dsi_pll_calc(dpi.dsidev, clkin, + pll_min, pll_max, + dpi_calc_pll_cb, ctx); +} + +static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) +{ + int i; + + /* + * DSS fck gives us very few possibilities, so finding a good pixel + * clock may not be possible. We try multiple times to find the clock, + * each time widening the pixel clock range we look for, up to + * +/- 1MHz. + */ + + for (i = 0; i < 10; ++i) { + bool ok; + + memset(ctx, 0, sizeof(*ctx)); + if (pck > 1000 * i * i * i) + ctx->pck_min = max(pck - 1000 * i * i * i, 0lu); + else + ctx->pck_min = 0; + ctx->pck_max = pck + 1000 * i * i * i; + + ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx); + if (ok) + return ok; + } + + return false; +} + + + static int dpi_set_dsi_clk(enum omap_channel channel, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { - struct dsi_clock_info dsi_cinfo; - struct dispc_clock_info dispc_cinfo; + struct dpi_clk_calc_ctx ctx; int r; + bool ok; - r = dsi_pll_calc_clock_div_pck(dpi.dsidev, pck_req, &dsi_cinfo, - &dispc_cinfo); - if (r) - return r; + ok = dpi_dsi_clk_calc(pck_req, &ctx); + if (!ok) + return -EINVAL; - r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo); + r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo); if (r) return r; dss_select_lcd_clk_source(channel, dpi_get_alt_clk_src(channel)); - dpi.mgr_config.clock_info = dispc_cinfo; + dpi.mgr_config.clock_info = ctx.dispc_cinfo; - *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; - *lck_div = dispc_cinfo.lck_div; - *pck_div = dispc_cinfo.pck_div; + *fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk; + *lck_div = ctx.dispc_cinfo.lck_div; + *pck_div = ctx.dispc_cinfo.pck_div; return 0; } @@ -137,23 +276,23 @@ static int dpi_set_dsi_clk(enum omap_channel channel, static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { - struct dss_clock_info dss_cinfo; - struct dispc_clock_info dispc_cinfo; + struct dpi_clk_calc_ctx ctx; int r; + bool ok; - r = dss_calc_clock_div(pck_req, &dss_cinfo, &dispc_cinfo); - if (r) - return r; + ok = dpi_dss_clk_calc(pck_req, &ctx); + if (!ok) + return -EINVAL; - r = dss_set_clock_div(&dss_cinfo); + r = dss_set_clock_div(&ctx.dss_cinfo); if (r) return r; - dpi.mgr_config.clock_info = dispc_cinfo; + dpi.mgr_config.clock_info = ctx.dispc_cinfo; - *fck = dss_cinfo.fck; - *lck_div = dispc_cinfo.lck_div; - *pck_div = dispc_cinfo.pck_div; + *fck = ctx.dss_cinfo.fck; + *lck_div = ctx.dispc_cinfo.lck_div; + *pck_div = ctx.dispc_cinfo.pck_div; return 0; } @@ -333,12 +472,12 @@ EXPORT_SYMBOL(omapdss_dpi_set_timings); int dpi_check_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { - int r; struct omap_overlay_manager *mgr = dpi.output.manager; int lck_div, pck_div; unsigned long fck; unsigned long pck; - struct dispc_clock_info dispc_cinfo; + struct dpi_clk_calc_ctx ctx; + bool ok; if (mgr && !dispc_mgr_timings_ok(mgr->id, timings)) return -EINVAL; @@ -347,28 +486,21 @@ int dpi_check_timings(struct omap_dss_device *dssdev, return -EINVAL; if (dpi.dsidev) { - struct dsi_clock_info dsi_cinfo; - r = dsi_pll_calc_clock_div_pck(dpi.dsidev, - timings->pixel_clock * 1000, - &dsi_cinfo, &dispc_cinfo); + ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx); + if (!ok) + return -EINVAL; - if (r) - return r; - - fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; + fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk; } else { - struct dss_clock_info dss_cinfo; - r = dss_calc_clock_div(timings->pixel_clock * 1000, - &dss_cinfo, &dispc_cinfo); - - if (r) - return r; + ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &ctx); + if (!ok) + return -EINVAL; - fck = dss_cinfo.fck; + fck = ctx.dss_cinfo.fck; } - lck_div = dispc_cinfo.lck_div; - pck_div = dispc_cinfo.pck_div; + lck_div = ctx.dispc_cinfo.lck_div; + pck_div = ctx.dispc_cinfo.pck_div; pck = fck / lck_div / pck_div / 1000; -- cgit v1.2.1 From f1e0001f973cfbec62d702cbd3d56f6b703cc90e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 17:21:35 +0200 Subject: OMAPDSS: DSI: use new clock calculation code Use the new clock calculation code in the DSI driver. The new code does not need DSI video mode parameters from the panel driver, like the old code does. Instead the new code is given the normal video timings, and a few DSI parameters, which are used to create DSI video timings. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/panel-taal.c | 7 +- drivers/video/omap2/dss/dsi.c | 557 +++++++++++++++++++++++++++++- 2 files changed, 549 insertions(+), 15 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index eb86cbae8c2a..2fc923de23cc 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -787,6 +787,7 @@ static int taal_probe(struct omap_dss_device *dssdev) dssdev->panel.timings.x_res = 864; dssdev->panel.timings.y_res = 480; + dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000); dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; @@ -923,8 +924,10 @@ static int taal_power_on(struct omap_dss_device *dssdev) .mode = OMAP_DSS_DSI_CMD_MODE, .pixel_format = OMAP_DSS_DSI_FMT_RGB888, .timings = &dssdev->panel.timings, - .hs_clk = 216000000, - .lp_clk = 10000000, + .hs_clk_min = 150000000, + .hs_clk_max = 300000000, + .lp_clk_min = 7000000, + .lp_clk_max = 10000000, }; r = omapdss_dsi_configure_pins(dssdev, &td->pin_config); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index a4e0560c2799..de88e69ef0a2 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -255,6 +255,24 @@ struct dsi_isr_tables { struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; }; +struct dsi_clk_calc_ctx { + struct platform_device *dsidev; + + /* inputs */ + + const struct omap_dss_dsi_config *config; + + unsigned long req_pck_min, req_pck_nom, req_pck_max; + + /* outputs */ + + struct dsi_clock_info dsi_cinfo; + struct dispc_clock_info dispc_cinfo; + + struct omap_video_timings dispc_vm; + struct omap_dss_dsi_videomode_timings dsi_vm; +}; + struct dsi_data { struct platform_device *pdev; void __iomem *base; @@ -1201,6 +1219,25 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev) return r; } +static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo, + unsigned long lp_clk_min, unsigned long lp_clk_max) +{ + unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk; + unsigned lp_clk_div; + unsigned long lp_clk; + + lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2); + lp_clk = dsi_fclk / 2 / lp_clk_div; + + if (lp_clk < lp_clk_min || lp_clk > lp_clk_max) + return -EINVAL; + + cinfo->lp_clk_div = lp_clk_div; + cinfo->lp_clk = lp_clk; + + return 0; +} + static int dsi_set_lp_clk_divisor(struct platform_device *dsidev) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); @@ -1577,8 +1614,7 @@ found: return 0; } -static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev, - struct dsi_clock_info *cinfo) +static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo) { unsigned long max_dsi_fck; @@ -4369,7 +4405,7 @@ static int dsi_set_clocks(struct omap_dss_device *dssdev, goto err; /* Calculate PLL's DSI clock */ - dsi_pll_calc_dsi_fck(dsidev, &cinfo); + dsi_pll_calc_dsi_fck(&cinfo); /* Calculate PLL's DISPC clock and pck & lck divs */ pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp; @@ -4693,13 +4729,6 @@ static int dsi_display_init_dispc(struct platform_device *dsidev, OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC); 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; - r = dss_mgr_register_framedone_handler(mgr, dsi_framedone_irq_callback, dsidev); if (r) { @@ -4941,24 +4970,526 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) } EXPORT_SYMBOL(omapdss_dsi_enable_te); +#ifdef PRINT_VERBOSE_VM_TIMINGS +static void print_dsi_vm(const char *str, + const struct omap_dss_dsi_videomode_timings *t) +{ + unsigned long byteclk = t->hsclk / 4; + int bl, wc, pps, tot; + + wc = DIV_ROUND_UP(t->hact * t->bitspp, 8); + pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */ + bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp; + tot = bl + pps; + +#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk)) + + pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, " + "%u/%u/%u/%u/%u/%u = %u + %u = %u\n", + str, + byteclk, + t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp, + bl, pps, tot, + TO_DSI_T(t->hss), + TO_DSI_T(t->hsa), + TO_DSI_T(t->hse), + TO_DSI_T(t->hbp), + TO_DSI_T(pps), + TO_DSI_T(t->hfp), + + TO_DSI_T(bl), + TO_DSI_T(pps), + + TO_DSI_T(tot)); +#undef TO_DSI_T +} + +static void print_dispc_vm(const char *str, const struct omap_video_timings *t) +{ + unsigned long pck = t->pixel_clock * 1000; + int hact, bl, tot; + + hact = t->x_res; + bl = t->hsw + t->hbp + t->hfp; + tot = hact + bl; + +#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck)) + + pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, " + "%u/%u/%u/%u = %u + %u = %u\n", + str, + pck, + t->hsw, t->hbp, hact, t->hfp, + bl, hact, tot, + TO_DISPC_T(t->hsw), + TO_DISPC_T(t->hbp), + TO_DISPC_T(hact), + TO_DISPC_T(t->hfp), + TO_DISPC_T(bl), + TO_DISPC_T(hact), + TO_DISPC_T(tot)); +#undef TO_DISPC_T +} + +/* note: this is not quite accurate */ +static void print_dsi_dispc_vm(const char *str, + const struct omap_dss_dsi_videomode_timings *t) +{ + struct omap_video_timings vm = { 0 }; + unsigned long byteclk = t->hsclk / 4; + unsigned long pck; + u64 dsi_tput; + int dsi_hact, dsi_htot; + + dsi_tput = (u64)byteclk * t->ndl * 8; + pck = (u32)div64_u64(dsi_tput, t->bitspp); + dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl); + dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp; + + vm.pixel_clock = pck / 1000; + vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk); + vm.hbp = div64_u64((u64)t->hbp * pck, byteclk); + vm.hfp = div64_u64((u64)t->hfp * pck, byteclk); + vm.x_res = t->hact; + + print_dispc_vm(str, &vm); +} +#endif /* PRINT_VERBOSE_VM_TIMINGS */ + +static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, + unsigned long pck, void *data) +{ + struct dsi_clk_calc_ctx *ctx = data; + struct omap_video_timings *t = &ctx->dispc_vm; + + ctx->dispc_cinfo.lck_div = lckd; + ctx->dispc_cinfo.pck_div = pckd; + ctx->dispc_cinfo.lck = lck; + ctx->dispc_cinfo.pck = pck; + + *t = *ctx->config->timings; + t->pixel_clock = pck / 1000; + t->x_res = ctx->config->timings->x_res; + t->y_res = ctx->config->timings->y_res; + t->hsw = t->hfp = t->hbp = t->vsw = 1; + t->vfp = t->vbp = 0; + + return true; +} + +static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, + void *data) +{ + struct dsi_clk_calc_ctx *ctx = data; + + ctx->dsi_cinfo.regm_dispc = regm_dispc; + ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc; + + return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max, + dsi_cm_calc_dispc_cb, ctx); +} + +static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint, + unsigned long pll, void *data) +{ + struct dsi_clk_calc_ctx *ctx = data; + + ctx->dsi_cinfo.regn = regn; + ctx->dsi_cinfo.regm = regm; + ctx->dsi_cinfo.fint = fint; + ctx->dsi_cinfo.clkin4ddr = pll; + + return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min, + dsi_cm_calc_hsdiv_cb, ctx); +} + +static bool dsi_cm_calc(struct dsi_data *dsi, + const struct omap_dss_dsi_config *cfg, + struct dsi_clk_calc_ctx *ctx) +{ + unsigned long clkin; + int bitspp, ndl; + unsigned long pll_min, pll_max; + unsigned long pck, txbyteclk; + + clkin = clk_get_rate(dsi->sys_clk); + bitspp = dsi_get_pixel_size(cfg->pixel_format); + ndl = dsi->num_lanes_used - 1; + + /* + * Here we should calculate minimum txbyteclk to be able to send the + * frame in time, and also to handle TE. That's not very simple, though, + * especially as we go to LP between each pixel packet due to HW + * "feature". So let's just estimate very roughly and multiply by 1.5. + */ + pck = cfg->timings->pixel_clock * 1000; + pck = pck * 3 / 2; + txbyteclk = pck * bitspp / 8 / ndl; + + memset(ctx, 0, sizeof(*ctx)); + ctx->dsidev = dsi->pdev; + ctx->config = cfg; + ctx->req_pck_min = pck; + ctx->req_pck_nom = pck; + ctx->req_pck_max = pck * 3 / 2; + ctx->dsi_cinfo.clkin = clkin; + + pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4); + pll_max = cfg->hs_clk_max * 4; + + return dsi_pll_calc(dsi->pdev, clkin, + pll_min, pll_max, + dsi_cm_calc_pll_cb, ctx); +} + +static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) +{ + struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev); + const struct omap_dss_dsi_config *cfg = ctx->config; + int bitspp = dsi_get_pixel_size(cfg->pixel_format); + int ndl = dsi->num_lanes_used - 1; + unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4; + unsigned long byteclk = hsclk / 4; + + unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max; + int xres; + int panel_htot, panel_hbl; /* pixels */ + int dispc_htot, dispc_hbl; /* pixels */ + int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */ + int hfp, hsa, hbp; + const struct omap_video_timings *req_vm; + struct omap_video_timings *dispc_vm; + struct omap_dss_dsi_videomode_timings *dsi_vm; + u64 dsi_tput, dispc_tput; + + dsi_tput = (u64)byteclk * ndl * 8; + + req_vm = cfg->timings; + req_pck_min = ctx->req_pck_min; + req_pck_max = ctx->req_pck_max; + req_pck_nom = ctx->req_pck_nom; + + dispc_pck = ctx->dispc_cinfo.pck; + dispc_tput = (u64)dispc_pck * bitspp; + + xres = req_vm->x_res; + + panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw; + panel_htot = xres + panel_hbl; + + dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl); + + /* + * When there are no line buffers, DISPC and DSI must have the + * same tput. Otherwise DISPC tput needs to be higher than DSI's. + */ + if (dsi->line_buffer_size < xres * bitspp / 8) { + if (dispc_tput != dsi_tput) + return false; + } else { + if (dispc_tput < dsi_tput) + return false; + } + + /* DSI tput must be over the min requirement */ + if (dsi_tput < (u64)bitspp * req_pck_min) + return false; + + /* When non-burst mode, DSI tput must be below max requirement. */ + if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) { + if (dsi_tput > (u64)bitspp * req_pck_max) + return false; + } + + hss = DIV_ROUND_UP(4, ndl); + + if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) { + if (ndl == 3 && req_vm->hsw == 0) + hse = 1; + else + hse = DIV_ROUND_UP(4, ndl); + } else { + hse = 0; + } + + /* DSI htot to match the panel's nominal pck */ + dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom); + + /* fail if there would be no time for blanking */ + if (dsi_htot < hss + hse + dsi_hact) + return false; + + /* total DSI blanking needed to achieve panel's TL */ + dsi_hbl = dsi_htot - dsi_hact; + + /* DISPC htot to match the DSI TL */ + dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk); + + /* verify that the DSI and DISPC TLs are the same */ + if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk) + return false; + + dispc_hbl = dispc_htot - xres; + + /* setup DSI videomode */ + + dsi_vm = &ctx->dsi_vm; + memset(dsi_vm, 0, sizeof(*dsi_vm)); + + dsi_vm->hsclk = hsclk; + + dsi_vm->ndl = ndl; + dsi_vm->bitspp = bitspp; + + if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) { + hsa = 0; + } else if (ndl == 3 && req_vm->hsw == 0) { + hsa = 0; + } else { + hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom); + hsa = max(hsa - hse, 1); + } + + hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom); + hbp = max(hbp, 1); + + hfp = dsi_hbl - (hss + hsa + hse + hbp); + if (hfp < 1) { + int t; + /* we need to take cycles from hbp */ + + t = 1 - hfp; + hbp = max(hbp - t, 1); + hfp = dsi_hbl - (hss + hsa + hse + hbp); + + if (hfp < 1 && hsa > 0) { + /* we need to take cycles from hsa */ + t = 1 - hfp; + hsa = max(hsa - t, 1); + hfp = dsi_hbl - (hss + hsa + hse + hbp); + } + } + + if (hfp < 1) + return false; + + dsi_vm->hss = hss; + dsi_vm->hsa = hsa; + dsi_vm->hse = hse; + dsi_vm->hbp = hbp; + dsi_vm->hact = xres; + dsi_vm->hfp = hfp; + + dsi_vm->vsa = req_vm->vsw; + dsi_vm->vbp = req_vm->vbp; + dsi_vm->vact = req_vm->y_res; + dsi_vm->vfp = req_vm->vfp; + + dsi_vm->trans_mode = cfg->trans_mode; + + dsi_vm->blanking_mode = 0; + dsi_vm->hsa_blanking_mode = 1; + dsi_vm->hfp_blanking_mode = 1; + dsi_vm->hbp_blanking_mode = 1; + + dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on; + dsi_vm->window_sync = 4; + + /* setup DISPC videomode */ + + dispc_vm = &ctx->dispc_vm; + *dispc_vm = *req_vm; + dispc_vm->pixel_clock = dispc_pck / 1000; + + if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) { + hsa = div64_u64((u64)req_vm->hsw * dispc_pck, + req_pck_nom); + hsa = max(hsa, 1); + } else { + hsa = 1; + } + + hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom); + hbp = max(hbp, 1); + + hfp = dispc_hbl - hsa - hbp; + if (hfp < 1) { + int t; + /* we need to take cycles from hbp */ + + t = 1 - hfp; + hbp = max(hbp - t, 1); + hfp = dispc_hbl - hsa - hbp; + + if (hfp < 1) { + /* we need to take cycles from hsa */ + t = 1 - hfp; + hsa = max(hsa - t, 1); + hfp = dispc_hbl - hsa - hbp; + } + } + + if (hfp < 1) + return false; + + dispc_vm->hfp = hfp; + dispc_vm->hsw = hsa; + dispc_vm->hbp = hbp; + + return true; +} + + +static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, + unsigned long pck, void *data) +{ + struct dsi_clk_calc_ctx *ctx = data; + + ctx->dispc_cinfo.lck_div = lckd; + ctx->dispc_cinfo.pck_div = pckd; + ctx->dispc_cinfo.lck = lck; + ctx->dispc_cinfo.pck = pck; + + if (dsi_vm_calc_blanking(ctx) == false) + return false; + +#ifdef PRINT_VERBOSE_VM_TIMINGS + print_dispc_vm("dispc", &ctx->dispc_vm); + print_dsi_vm("dsi ", &ctx->dsi_vm); + print_dispc_vm("req ", ctx->config->timings); + print_dsi_dispc_vm("act ", &ctx->dsi_vm); +#endif + + return true; +} + +static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, + void *data) +{ + struct dsi_clk_calc_ctx *ctx = data; + unsigned long pck_max; + + ctx->dsi_cinfo.regm_dispc = regm_dispc; + ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc; + + /* + * In burst mode we can let the dispc pck be arbitrarily high, but it + * limits our scaling abilities. So for now, don't aim too high. + */ + + if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE) + pck_max = ctx->req_pck_max + 10000000; + else + pck_max = ctx->req_pck_max; + + return dispc_div_calc(dispc, ctx->req_pck_min, pck_max, + dsi_vm_calc_dispc_cb, ctx); +} + +static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint, + unsigned long pll, void *data) +{ + struct dsi_clk_calc_ctx *ctx = data; + + ctx->dsi_cinfo.regn = regn; + ctx->dsi_cinfo.regm = regm; + ctx->dsi_cinfo.fint = fint; + ctx->dsi_cinfo.clkin4ddr = pll; + + return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min, + dsi_vm_calc_hsdiv_cb, ctx); +} + +static bool dsi_vm_calc(struct dsi_data *dsi, + const struct omap_dss_dsi_config *cfg, + struct dsi_clk_calc_ctx *ctx) +{ + const struct omap_video_timings *t = cfg->timings; + unsigned long clkin; + unsigned long pll_min; + unsigned long pll_max; + int ndl = dsi->num_lanes_used - 1; + int bitspp = dsi_get_pixel_size(cfg->pixel_format); + unsigned long byteclk_min; + + clkin = clk_get_rate(dsi->sys_clk); + + memset(ctx, 0, sizeof(*ctx)); + ctx->dsidev = dsi->pdev; + ctx->config = cfg; + + ctx->dsi_cinfo.clkin = clkin; + + /* these limits should come from the panel driver */ + ctx->req_pck_min = t->pixel_clock * 1000 - 1000; + ctx->req_pck_nom = t->pixel_clock * 1000; + ctx->req_pck_max = t->pixel_clock * 1000 + 1000; + + byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8); + pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4); + + if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) { + pll_max = cfg->hs_clk_max * 4; + } else { + unsigned long byteclk_max; + byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp, + ndl * 8); + + pll_max = byteclk_max * 4 * 4; + } + + return dsi_pll_calc(dsi->pdev, clkin, + pll_min, pll_max, + dsi_vm_calc_pll_cb, ctx); +} + int omapdss_dsi_set_config(struct omap_dss_device *dssdev, const struct omap_dss_dsi_config *config) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct dsi_clk_calc_ctx ctx; + bool ok; + int r; mutex_lock(&dsi->lock); - dsi->timings = *config->timings; - dsi->vm_timings = *config->vm_timings; dsi->pix_fmt = config->pixel_format; dsi->mode = config->mode; - dsi_set_clocks(dssdev, config->hs_clk, config->lp_clk); + if (config->mode == OMAP_DSS_DSI_VIDEO_MODE) + ok = dsi_vm_calc(dsi, config, &ctx); + else + ok = dsi_cm_calc(dsi, config, &ctx); + + if (!ok) { + DSSERR("failed to find suitable DSI clock settings\n"); + r = -EINVAL; + goto err; + } + + dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo); + + r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min, + config->lp_clk_max); + if (r) { + DSSERR("failed to find suitable DSI LP clock settings\n"); + goto err; + } + + dsi->user_dsi_cinfo = ctx.dsi_cinfo; + dsi->user_dispc_cinfo = ctx.dispc_cinfo; + + dsi->timings = ctx.dispc_vm; + dsi->vm_timings = ctx.dsi_vm; mutex_unlock(&dsi->lock); return 0; +err: + mutex_unlock(&dsi->lock); + + return r; } EXPORT_SYMBOL(omapdss_dsi_set_config); -- cgit v1.2.1 From b7ec96c78b0d5c89f5a1082e62e0d0021b2920ed Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 5 Mar 2013 17:23:59 +0200 Subject: OMAPDSS: remove unused old clock calculation code Now that the old clock calculation code is no longer used, we can remove it from the driver. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 48 ------ drivers/video/omap2/dss/dsi.c | 317 ---------------------------------------- drivers/video/omap2/dss/dss.c | 115 --------------- drivers/video/omap2/dss/dss.h | 15 -- 4 files changed, 495 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index cd54e8fe2d58..8cfa27b4fdd8 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3311,54 +3311,6 @@ static void dispc_dump_regs(struct seq_file *s) #undef DUMPREG } -/* with fck as input clock rate, find dispc dividers that produce req_pck */ -void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, - struct dispc_clock_info *cinfo) -{ - u16 pcd_min, pcd_max; - unsigned long best_pck; - u16 best_ld, cur_ld; - u16 best_pd, cur_pd; - - pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); - pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); - - best_pck = 0; - best_ld = 0; - best_pd = 0; - - for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { - unsigned long lck = fck / cur_ld; - - for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) { - unsigned long pck = lck / cur_pd; - long old_delta = abs(best_pck - req_pck); - long new_delta = abs(pck - req_pck); - - if (best_pck == 0 || new_delta < old_delta) { - best_pck = pck; - best_ld = cur_ld; - best_pd = cur_pd; - - if (pck == req_pck) - goto found; - } - - if (pck < req_pck) - break; - } - - if (lck / pcd_min < req_pck) - break; - } - -found: - cinfo->lck_div = best_ld; - cinfo->pck_div = best_pd; - cinfo->lck = fck / cinfo->lck_div; - cinfo->pck = cinfo->lck / cinfo->pck_div; -} - /* calculate clock rates using dividers in cinfo */ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, struct dispc_clock_info *cinfo) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index de88e69ef0a2..8db29bff0423 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1430,190 +1430,6 @@ static int dsi_calc_clock_rates(struct platform_device *dsidev, return 0; } -int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, - unsigned long req_pck, struct dsi_clock_info *dsi_cinfo, - struct dispc_clock_info *dispc_cinfo) -{ - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - struct dsi_clock_info cur, best; - struct dispc_clock_info best_dispc; - int min_fck_per_pck; - int match = 0; - unsigned long dss_sys_clk, max_dss_fck; - - dss_sys_clk = clk_get_rate(dsi->sys_clk); - - max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); - - if (req_pck == dsi->cache_req_pck && - dsi->cache_cinfo.clkin == dss_sys_clk) { - DSSDBG("DSI clock info found from cache\n"); - *dsi_cinfo = dsi->cache_cinfo; - dispc_find_clk_divs(req_pck, dsi_cinfo->dsi_pll_hsdiv_dispc_clk, - dispc_cinfo); - return 0; - } - - 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; - } - - DSSDBG("dsi_pll_calc\n"); - -retry: - memset(&best, 0, sizeof(best)); - memset(&best_dispc, 0, sizeof(best_dispc)); - - memset(&cur, 0, sizeof(cur)); - cur.clkin = dss_sys_clk; - - /* 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) { - 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; - - /* dsi_pll_hsdiv_dispc_clk(MHz) = - * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ - for (cur.regm_dispc = 1; cur.regm_dispc < - dsi->regm_dispc_max; ++cur.regm_dispc) { - struct dispc_clock_info cur_dispc; - cur.dsi_pll_hsdiv_dispc_clk = - cur.clkin4ddr / cur.regm_dispc; - - if (cur.regm_dispc > 1 && - cur.regm_dispc % 2 != 0 && - req_pck >= 1000000) - continue; - - /* this will narrow down the search a bit, - * but still give pixclocks below what was - * requested */ - if (cur.dsi_pll_hsdiv_dispc_clk < req_pck) - break; - - if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck) - continue; - - if (min_fck_per_pck && - cur.dsi_pll_hsdiv_dispc_clk < - req_pck * min_fck_per_pck) - continue; - - match = 1; - - dispc_find_clk_divs(req_pck, - cur.dsi_pll_hsdiv_dispc_clk, - &cur_dispc); - - if (abs(cur_dispc.pck - req_pck) < - abs(best_dispc.pck - req_pck)) { - best = cur; - best_dispc = cur_dispc; - - if (cur_dispc.pck == req_pck) - goto found; - } - } - } - } -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; - } - - /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */ - best.regm_dsi = 0; - best.dsi_pll_hsdiv_dsi_clk = 0; - - if (dsi_cinfo) - *dsi_cinfo = best; - if (dispc_cinfo) - *dispc_cinfo = best_dispc; - - dsi->cache_req_pck = req_pck; - dsi->cache_clk_freq = 0; - dsi->cache_cinfo = best; - - 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 dsi_clock_info *cinfo) { unsigned long max_dsi_fck; @@ -1624,90 +1440,6 @@ static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo) 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) { @@ -4384,55 +4116,6 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev, } EXPORT_SYMBOL(omapdss_dsi_configure_pins); -static int 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; - - DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk); - - /* 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(&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); - - dsi->user_dsi_cinfo.regn = cinfo.regn; - dsi->user_dsi_cinfo.regm = cinfo.regm; - dsi->user_dsi_cinfo.regm_dispc = cinfo.regm_dispc; - dsi->user_dsi_cinfo.regm_dsi = cinfo.regm_dsi; - - dsi->user_dsi_cinfo.lp_clk_div = lp_clk_div; - - dsi->user_dispc_cinfo.lck_div = dispc_cinfo.lck_div; - dsi->user_dispc_cinfo.pck_div = dispc_cinfo.pck_div; - - return 0; -err: - return r; -} - int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index eba4127b61a6..fdd32e8d9212 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -581,121 +581,6 @@ static int dss_setup_default_clock(void) return 0; } -int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, - struct dispc_clock_info *dispc_cinfo) -{ - unsigned long prate; - struct dss_clock_info best_dss; - struct dispc_clock_info best_dispc; - - unsigned long fck, max_dss_fck; - - u16 fck_div; - - int match = 0; - int min_fck_per_pck; - - prate = dss_get_dpll4_rate(); - - max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); - - fck = clk_get_rate(dss.dss_clk); - if (req_pck == dss.cache_req_pck && prate == dss.cache_prate && - dss.cache_dss_cinfo.fck == fck) { - DSSDBG("dispc clock info found from cache.\n"); - *dss_cinfo = dss.cache_dss_cinfo; - *dispc_cinfo = dss.cache_dispc_cinfo; - return 0; - } - - 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: - memset(&best_dss, 0, sizeof(best_dss)); - memset(&best_dispc, 0, sizeof(best_dispc)); - - if (dss.dpll4_m4_ck == NULL) { - struct dispc_clock_info cur_dispc; - /* XXX can we change the clock on omap2? */ - fck = clk_get_rate(dss.dss_clk); - fck_div = 1; - - dispc_find_clk_divs(req_pck, fck, &cur_dispc); - match = 1; - - best_dss.fck = fck; - best_dss.fck_div = fck_div; - - best_dispc = cur_dispc; - - goto found; - } else { - for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) { - struct dispc_clock_info cur_dispc; - - fck = prate / fck_div * dss.feat->dss_fck_multiplier; - - if (fck > max_dss_fck) - continue; - - if (min_fck_per_pck && - fck < req_pck * min_fck_per_pck) - continue; - - match = 1; - - dispc_find_clk_divs(req_pck, fck, &cur_dispc); - - if (abs(cur_dispc.pck - req_pck) < - abs(best_dispc.pck - req_pck)) { - - best_dss.fck = fck; - best_dss.fck_div = fck_div; - - best_dispc = cur_dispc; - - if (cur_dispc.pck == req_pck) - goto found; - } - } - } - -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; - } - - if (dss_cinfo) - *dss_cinfo = best_dss; - if (dispc_cinfo) - *dispc_cinfo = best_dispc; - - dss.cache_req_pck = req_pck; - dss.cache_prate = prate; - dss.cache_dss_cinfo = best_dss; - dss.cache_dispc_cinfo = best_dispc; - - return 0; -} - void dss_set_venc_output(enum omap_dss_venc_type type) { int l = 0; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index dde6cc109480..faaf35857b0e 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -268,8 +268,6 @@ void dss_set_dac_pwrdn_bgz(bool enable); unsigned long dss_get_dpll4_rate(void); int dss_calc_clock_rates(struct dss_clock_info *cinfo); int dss_set_clock_div(struct dss_clock_info *cinfo); -int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, - struct dispc_clock_info *dispc_cinfo); typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data); bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data); @@ -310,9 +308,6 @@ bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin, unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); int dsi_pll_set_clock_div(struct platform_device *dsidev, struct dsi_clock_info *cinfo); -int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, - unsigned long req_pck, struct dsi_clock_info *cinfo, - struct dispc_clock_info *dispc_cinfo); int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, bool enable_hsdiv); void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); @@ -343,14 +338,6 @@ static inline int dsi_pll_set_clock_div(struct platform_device *dsidev, WARN("%s: DSI not compiled in\n", __func__); return -ENODEV; } -static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, - unsigned long req_pck, - struct dsi_clock_info *dsi_cinfo, - struct dispc_clock_info *dispc_cinfo) -{ - WARN("%s: DSI not compiled in\n", __func__); - return -ENODEV; -} static inline int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, bool enable_hsdiv) { @@ -400,8 +387,6 @@ bool dispc_div_calc(unsigned long dispc, bool dispc_mgr_timings_ok(enum omap_channel channel, const struct omap_video_timings *timings); unsigned long dispc_fclk_rate(void); -void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, - struct dispc_clock_info *cinfo); int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, struct dispc_clock_info *cinfo); -- cgit v1.2.1 From 48c2169fd9922314d990f944068f107a3284434e Mon Sep 17 00:00:00 2001 From: Alexandru Gheorghiu Date: Tue, 19 Mar 2013 10:03:14 +0200 Subject: drivers: video: omap2: dss: Use PTR_RET function Use PTR_RET function instead of IS_ERR and PTR_ERR. Patch found using coccinelle. Signed-off-by: Alexandru Gheorghiu Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index f8779d4750ba..60cc6fee6548 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -181,10 +181,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, write, &dss_debug_fops); - if (IS_ERR(d)) - return PTR_ERR(d); - - return 0; + return PTR_RET(d); } #else /* CONFIG_OMAP2_DSS_DEBUGFS */ static inline int dss_initialize_debugfs(void) -- cgit v1.2.1 From 5303b3aa77a175a6a312aee6867e740ad1809171 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 2 Apr 2013 14:33:00 +0300 Subject: OMAPDSS: DSI: Use devm_clk_get() Using devm_clk_get cleans up some code. Signed-off-by: Sachin Kamat Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 28d41d16b7be..36de3fedc3f6 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -5073,7 +5073,7 @@ static int dsi_get_clocks(struct platform_device *dsidev) struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct clk *clk; - clk = clk_get(&dsidev->dev, "fck"); + clk = devm_clk_get(&dsidev->dev, "fck"); if (IS_ERR(clk)) { DSSERR("can't get fck\n"); return PTR_ERR(clk); @@ -5081,11 +5081,9 @@ static int dsi_get_clocks(struct platform_device *dsidev) dsi->dss_clk = clk; - clk = clk_get(&dsidev->dev, "sys_clk"); + clk = devm_clk_get(&dsidev->dev, "sys_clk"); if (IS_ERR(clk)) { DSSERR("can't get sys_clk\n"); - clk_put(dsi->dss_clk); - dsi->dss_clk = NULL; return PTR_ERR(clk); } @@ -5094,16 +5092,6 @@ static int dsi_get_clocks(struct platform_device *dsidev) return 0; } -static void dsi_put_clocks(struct platform_device *dsidev) -{ - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - - if (dsi->dss_clk) - clk_put(dsi->dss_clk); - if (dsi->sys_clk) - clk_put(dsi->sys_clk); -} - static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; @@ -5314,7 +5302,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev) err_runtime_get: pm_runtime_disable(&dsidev->dev); - dsi_put_clocks(dsidev); return r; } @@ -5330,8 +5317,6 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev) pm_runtime_disable(&dsidev->dev); - dsi_put_clocks(dsidev); - if (dsi->vdds_dsi_reg != NULL) { if (dsi->vdds_dsi_enabled) { regulator_disable(dsi->vdds_dsi_reg); -- cgit v1.2.1 From ca5ca69cab83f9efc301ba0b44dc4f71bb167050 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 26 Mar 2013 19:15:22 +0530 Subject: omapdss: DISPC: add max pixel clock limits for LCD and TV managers Each version of OMAP has a limitation on the maximum pixel clock frequency supported by an overlay manager. This limit isn't checked by omapdss. Add dispc feats for lcd and tv managers and check whether the target timings can be supported or not. The pixel clock limitations are actually more complex. They depend on which OPP OMAP is in, and they also depend on which encoder is the manager connected to. The OPP dependence is ignored as DSS forces the PM framework to be on OPP100 when DSS is enabled, and the encoder dependencies are ignored by DISPC for now. These limits should come from the encoder driver. The OMAP2 TRM doesn't mention the maximum pixel clock limit. This value is left as half of DSS_FCLK, as OMAP2 requires the PCD to be atleast 2. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 05ff2b91d9e8..a375de3126e5 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -69,6 +69,8 @@ struct dispc_features { u8 mgr_height_start; u16 mgr_width_max; u16 mgr_height_max; + unsigned long max_lcd_pclk; + unsigned long max_tv_pclk; int (*calc_scaling) (unsigned long pclk, unsigned long lclk, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, @@ -2823,6 +2825,15 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, return true; } +static bool _dispc_mgr_pclk_ok(enum omap_channel channel, + unsigned long pclk) +{ + if (dss_mgr_is_lcd(channel)) + return pclk <= dispc.feat->max_lcd_pclk ? true : false; + else + return pclk <= dispc.feat->max_tv_pclk ? true : false; +} + bool dispc_mgr_timings_ok(enum omap_channel channel, const struct omap_video_timings *timings) { @@ -2830,11 +2841,13 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res); - if (dss_mgr_is_lcd(channel)) - timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw, - timings->hfp, timings->hbp, - timings->vsw, timings->vfp, - timings->vbp); + timings_ok &= _dispc_mgr_pclk_ok(channel, timings->pixel_clock * 1000); + + if (dss_mgr_is_lcd(channel)) { + timings_ok &= _dispc_lcd_timings_ok(timings->hsw, timings->hfp, + timings->hbp, timings->vsw, timings->vfp, + timings->vbp); + } return timings_ok; } @@ -3479,6 +3492,7 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .max_lcd_pclk = 66500000, .calc_scaling = dispc_ovl_calc_scaling_24xx, .calc_core_clk = calc_core_clk_24xx, .num_fifos = 3, @@ -3496,6 +3510,8 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .max_lcd_pclk = 173000000, + .max_tv_pclk = 59000000, .calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_core_clk = calc_core_clk_34xx, .num_fifos = 3, @@ -3513,6 +3529,8 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .max_lcd_pclk = 173000000, + .max_tv_pclk = 59000000, .calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_core_clk = calc_core_clk_34xx, .num_fifos = 3, @@ -3530,6 +3548,8 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = { .mgr_height_start = 26, .mgr_width_max = 2048, .mgr_height_max = 2048, + .max_lcd_pclk = 170000000, + .max_tv_pclk = 185625000, .calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_core_clk = calc_core_clk_44xx, .num_fifos = 5, @@ -3547,6 +3567,8 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = { .mgr_height_start = 27, .mgr_width_max = 4096, .mgr_height_max = 4096, + .max_lcd_pclk = 170000000, + .max_tv_pclk = 186000000, .calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_core_clk = calc_core_clk_44xx, .num_fifos = 5, -- cgit v1.2.1 From 3729a70b5837a60d736e8e5edb116b8eecd1bedb Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 26 Mar 2013 19:15:23 +0530 Subject: omapdss: Features: Fix some parameter ranges Increase the DSS_FCLK and DSI_FCLK max supported frequencies, these come because some frequencies were increased from OMAP5 ES1 to OMAP5 ES2. We support only OMAP5 ES2 in the kernel, so replace the ES1 values with ES2 values. Increase the DSI PLL Fint range, this was previously just copied from the OMAP4 param range struct. Fix the maximum DSS_FCLK on OMAP2, it's 133 Mhz according to the TRM. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss_features.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 7f791aeda4d2..77dbe0cfb34c 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -414,7 +414,7 @@ static const char * const omap5_dss_clk_source_names[] = { }; static const struct dss_param_range omap2_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, + [FEAT_PARAM_DSS_FCK] = { 0, 133000000 }, [FEAT_PARAM_DSS_PCD] = { 2, 255 }, [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, @@ -459,15 +459,15 @@ static const struct dss_param_range omap4_dss_param_range[] = { }; static const struct dss_param_range omap5_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 200000000 }, + [FEAT_PARAM_DSS_FCK] = { 0, 209250000 }, [FEAT_PARAM_DSS_PCD] = { 1, 255 }, [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, - [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, + [FEAT_PARAM_DSIPLL_FINT] = { 150000, 52000000 }, [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, - [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, + [FEAT_PARAM_DSI_FCK] = { 0, 209250000 }, [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, }; -- cgit v1.2.1 From c35eeb2e80a4dd3aa1a4ceac8f74f4c4e61f6463 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 26 Mar 2013 19:15:24 +0530 Subject: OMAPDSS: DISPC: Configure doublestride for NV12 when using 2D Tiler buffers When using a DISPC video pipeline to a fetch a NV12 buffer in a 2D container, we need to set set a doublestride bit in the video pipe's ATTRIBUTES register. This is needed because the stride for the UV plane(using a 16 bit Tiler container) is double the stride for the Y plane(using a 8 bit Tiler container) for the 0 or 180 degree views. The ROW_INC register is meant for the Y plane, and the HW will calculate the row increment needed for the UV plane by using double the stride value based on whether this bit is set or not. Set the bit when we are using a 2D Tiler buffer and when rotation is 0 or 180 degrees. The stride value is the same for 90 and 270 degree Tiler views, hence the bit shouldn't be set. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a375de3126e5..e7ed1f7bb302 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1586,6 +1586,7 @@ static void dispc_ovl_set_scaling(enum omap_plane plane, } static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, + enum omap_dss_rotation_type rotation_type, bool mirroring, enum omap_color_mode color_mode) { bool row_repeat = false; @@ -1636,6 +1637,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, if (dss_has_feature(FEAT_ROWREPEATENABLE)) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), row_repeat ? 1 : 0, 18, 18); + + if (color_mode == OMAP_DSS_COLOR_NV12) { + bool doublestride = (rotation_type == OMAP_DSS_ROT_TILER) && + (rotation == OMAP_DSS_ROT_0 || + rotation == OMAP_DSS_ROT_180); + /* DOUBLESTRIDE */ + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), doublestride, 22, 22); + } + } static int color_mode_to_bpp(enum omap_color_mode color_mode) @@ -2514,7 +2524,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane, dispc_ovl_set_vid_color_conv(plane, cconv); } - dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode); + dispc_ovl_set_rotation_attrs(plane, rotation, rotation_type, mirror, + color_mode); dispc_ovl_set_zorder(plane, caps, zorder); dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha); -- cgit v1.2.1 From d0df9a2c8f856b290407dec1069eb320b4bbb705 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 26 Mar 2013 19:15:25 +0530 Subject: OMAPDSS: DISPC: Revert to older DISPC Smart Standby mechanism for OMAP5 DISPC on OMAP5 has a more optimised mechanism of asserting Mstandby to achieve more power savings when DISPC is configured in Smart Standby mode. This mechanism leads to underflows when multiple DISPC pipes are enabled. There is a register field which can let us revert to the older mechanism of asserting Mstandby. Configure this field to prevent underflows. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 7 +++++++ drivers/video/omap2/dss/dispc.h | 1 + 2 files changed, 8 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index e7ed1f7bb302..ea9a8481059c 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -87,6 +87,9 @@ struct dispc_features { /* no DISPC_IRQ_FRAMEDONETV on this SoC */ bool no_framedone_tv:1; + + /* revert to the OMAP4 mechanism of DISPC Smart Standby operation */ + bool mstandby_workaround:1; }; #define DISPC_MAX_NR_FIFOS 5 @@ -3490,6 +3493,9 @@ static void _omap_dispc_initial_config(void) dispc_configure_burst_sizes(); dispc_ovl_enable_zorder_planes(); + + if (dispc.feat->mstandby_workaround) + REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0); } static const struct dispc_features omap24xx_dispc_feats __initconst = { @@ -3584,6 +3590,7 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = { .calc_core_clk = calc_core_clk_44xx, .num_fifos = 5, .gfx_fifo_workaround = true, + .mstandby_workaround = true, }; static int __init dispc_init_features(struct platform_device *pdev) diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h index 222363c6e623..de4863d21ab7 100644 --- a/drivers/video/omap2/dss/dispc.h +++ b/drivers/video/omap2/dss/dispc.h @@ -39,6 +39,7 @@ #define DISPC_GLOBAL_BUFFER 0x0800 #define DISPC_CONTROL3 0x0848 #define DISPC_CONFIG3 0x084C +#define DISPC_MSTANDBY_CTRL 0x0858 /* DISPC overlay registers */ #define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \ -- cgit v1.2.1 From 3aff5b122b7e01945ba787df306c182bae9f6762 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 7 Apr 2013 12:14:00 +0300 Subject: OMAPDSS: nec-nl8048 panel: Use dev_pm_ops Use dev_pm_ops instead of the deprecated legacy suspend/resume callbacks. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tomi Valkeinen --- .../video/omap2/displays/panel-nec-nl8048hl11-01b.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c index c4e9c2b1b465..bd3ad8830a54 100644 --- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c +++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c @@ -303,16 +303,22 @@ static int nec_8048_spi_remove(struct spi_device *spi) return 0; } -static int nec_8048_spi_suspend(struct spi_device *spi, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP + +static int nec_8048_spi_suspend(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); + nec_8048_spi_send(spi, 2, 0x01); mdelay(40); return 0; } -static int nec_8048_spi_resume(struct spi_device *spi) +static int nec_8048_spi_resume(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); + /* reinitialize the panel */ spi_setup(spi); nec_8048_spi_send(spi, 2, 0x00); @@ -321,14 +327,20 @@ static int nec_8048_spi_resume(struct spi_device *spi) return 0; } +static SIMPLE_DEV_PM_OPS(nec_8048_spi_pm_ops, nec_8048_spi_suspend, + nec_8048_spi_resume); +#define NEC_8048_SPI_PM_OPS (&nec_8048_spi_pm_ops) +#else +#define NEC_8048_SPI_PM_OPS NULL +#endif + static struct spi_driver nec_8048_spi_driver = { .probe = nec_8048_spi_probe, .remove = nec_8048_spi_remove, - .suspend = nec_8048_spi_suspend, - .resume = nec_8048_spi_resume, .driver = { .name = "nec_8048_spi", .owner = THIS_MODULE, + .pm = NEC_8048_SPI_PM_OPS, }, }; -- cgit v1.2.1 From b2c9c8ee7cec4c7d8fa90375f9de92ecf3045ebb Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 8 Apr 2013 11:55:00 +0300 Subject: omapdss: use devm_clk_get() Use devm_clk_get() instead of clk_get() for dss, and for outputs hdmi and venc. This reduces code and simplifies error handling. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 18 +++--------------- drivers/video/omap2/dss/hdmi.c | 16 ++-------------- drivers/video/omap2/dss/venc.c | 10 +--------- 3 files changed, 6 insertions(+), 38 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 054c2a22b3f1..645b3bc12ede 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -767,13 +767,11 @@ int dss_dpi_select_source(enum omap_channel channel) static int dss_get_clocks(void) { struct clk *clk; - int r; - clk = clk_get(&dss.pdev->dev, "fck"); + clk = devm_clk_get(&dss.pdev->dev, "fck"); if (IS_ERR(clk)) { DSSERR("can't get clock fck\n"); - r = PTR_ERR(clk); - goto err; + return PTR_ERR(clk); } dss.dss_clk = clk; @@ -782,8 +780,7 @@ static int dss_get_clocks(void) clk = clk_get(NULL, dss.feat->clk_name); if (IS_ERR(clk)) { DSSERR("Failed to get %s\n", dss.feat->clk_name); - r = PTR_ERR(clk); - goto err; + return PTR_ERR(clk); } } else { clk = NULL; @@ -792,21 +789,12 @@ static int dss_get_clocks(void) dss.dpll4_m4_ck = clk; return 0; - -err: - if (dss.dss_clk) - clk_put(dss.dss_clk); - if (dss.dpll4_m4_ck) - clk_put(dss.dpll4_m4_ck); - - return r; } static void dss_put_clocks(void) { if (dss.dpll4_m4_ck) clk_put(dss.dpll4_m4_ck); - clk_put(dss.dss_clk); } static int dss_runtime_get(void) diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 72923645dcce..c7e0bf748a6d 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -804,7 +804,7 @@ static int hdmi_get_clocks(struct platform_device *pdev) { struct clk *clk; - clk = clk_get(&pdev->dev, "sys_clk"); + clk = devm_clk_get(&pdev->dev, "sys_clk"); if (IS_ERR(clk)) { DSSERR("can't get sys_clk\n"); return PTR_ERR(clk); @@ -815,12 +815,6 @@ static int hdmi_get_clocks(struct platform_device *pdev) return 0; } -static void hdmi_put_clocks(void) -{ - if (hdmi.sys_clk) - clk_put(hdmi.sys_clk); -} - #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) { @@ -1100,7 +1094,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) r = hdmi_panel_init(); if (r) { DSSERR("can't init panel\n"); - goto err_panel_init; + return r; } dss_debugfs_create_file("hdmi", hdmi_dump_regs); @@ -1110,10 +1104,6 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) hdmi_probe_pdata(pdev); return 0; - -err_panel_init: - hdmi_put_clocks(); - return r; } static int __exit hdmi_remove_child(struct device *dev, void *data) @@ -1135,8 +1125,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); - hdmi_put_clocks(); - return 0; } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 006caf3cb509..c27ab6ff5a37 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -721,7 +721,7 @@ static int venc_get_clocks(struct platform_device *pdev) struct clk *clk; if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { - clk = clk_get(&pdev->dev, "tv_dac_clk"); + clk = devm_clk_get(&pdev->dev, "tv_dac_clk"); if (IS_ERR(clk)) { DSSERR("can't get tv_dac_clk\n"); return PTR_ERR(clk); @@ -735,12 +735,6 @@ static int venc_get_clocks(struct platform_device *pdev) return 0; } -static void venc_put_clocks(void) -{ - if (venc.tv_dac_clk) - clk_put(venc.tv_dac_clk); -} - static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; @@ -886,7 +880,6 @@ static int __init omap_venchw_probe(struct platform_device *pdev) err_panel_init: err_runtime_get: pm_runtime_disable(&pdev->dev); - venc_put_clocks(); return r; } @@ -904,7 +897,6 @@ static int __exit omap_venchw_remove(struct platform_device *pdev) venc_uninit_output(pdev); pm_runtime_disable(&pdev->dev); - venc_put_clocks(); return 0; } -- cgit v1.2.1 From 648a55e1254117bd7500747a789f0b112c7af240 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 10 Apr 2013 14:47:38 +0300 Subject: OMAPDSS: fix dss_fck clock rate rounding DSS func clock is calculated with prate / div * m. However, the current omapdss code calculates it with prate * m / div, which yields a slightly different result when there's a remainder. For example, 432000000 / 14 * 2 = 61714284, but 432000000 * 2 / 14 = 61714285. In addition to that, the clock framework wants the clock rate given with clk_set_rate to be higher than the actual (truncated) end result. So, if prate is 432000000, and div is 14, the real result is 30857142.8571... We need to call clk_set_rate with 30857143, which gives us a clock of 30857142. That's why we need to use DIV_ROUND_UP() when calling clk_set_rate. This patch fixes the clock calculation. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index fdd32e8d9212..b9f6f245d4a1 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -480,6 +480,7 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) unsigned long fck_hw_max; unsigned long fckd_hw_max; unsigned long prate; + unsigned m; if (dss.dpll4_m4_ck == NULL) { /* @@ -495,15 +496,16 @@ bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); fckd_hw_max = dss.feat->fck_div_max; - prate = dss_get_dpll4_rate() * dss.feat->dss_fck_multiplier; + m = dss.feat->dss_fck_multiplier; + prate = dss_get_dpll4_rate(); fck_min = fck_min ? fck_min : 1; - fckd_start = min(prate / fck_min, fckd_hw_max); - fckd_stop = max(DIV_ROUND_UP(prate, fck_hw_max), 1ul); + fckd_start = min(prate * m / fck_min, fckd_hw_max); + fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul); for (fckd = fckd_start; fckd >= fckd_stop; --fckd) { - fck = prate / fckd; + fck = prate / fckd * m; if (func(fckd, fck, data)) return true; @@ -521,7 +523,8 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); DSSDBG("dpll4_m4 = %ld\n", prate); - r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); + r = clk_set_rate(dss.dpll4_m4_ck, + DIV_ROUND_UP(prate, cinfo->fck_div)); if (r) return r; } else { @@ -531,7 +534,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) dss.dss_clk_rate = clk_get_rate(dss.dss_clk); - WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch"); + WARN_ONCE(dss.dss_clk_rate != cinfo->fck, + "clk rate mismatch: %lu != %lu", dss.dss_clk_rate, + cinfo->fck); DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); -- cgit v1.2.1 From 2c6360fb41e71d86ef2a870fd94c0fc9dcd9779e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 10 Apr 2013 14:54:54 +0300 Subject: OMAPDSS: DPI: widen the pck search when using dss fck When not using DSI PLL to generate the pixel clock, but DSS FCK, the possible pixel clock rates are rather limited. DSS FCK is currently used on OMAP2 and OMAP3. When using Beagleboard with a monitor that supports high resolutions, the clock rates do not match (at least for me) for the monitor's pixel clocks within the current threshold in the code, which is +/- 1MHz. This patch widens the search up to +/- 15MHz. The search is done in steps, i.e. it first tries to find a rather exact clock, than a bit less exact, etc. so this should not change the cases where a clock was already found. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index abe1a4e23c36..e93c4debea7f 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -222,10 +222,10 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) * DSS fck gives us very few possibilities, so finding a good pixel * clock may not be possible. We try multiple times to find the clock, * each time widening the pixel clock range we look for, up to - * +/- 1MHz. + * +/- ~15MHz. */ - for (i = 0; i < 10; ++i) { + for (i = 0; i < 25; ++i) { bool ok; memset(ctx, 0, sizeof(*ctx)); -- cgit v1.2.1