From a0d8dde9cbde712fad65822152d2721eec1ca656 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 12 Feb 2013 16:46:46 +0530 Subject: OMAPDSS: panels: keep platform data of all panels in a single header Structs for platform data of omapdss panels are found in headers in the 'include/video/' path. Board files populate these structs with platform specific values, and the panel driver uses these to configure the panel. Currently, each panel has it's own header in the above path. Move all the omapdss panel platform data structs to a single header omap-panel-data.h. This is useful because: - All other omapdss panel drivers will be modified to use platform data. This would lead to a lot of panel headers usable only by omapdss. A lot of these platform data structs are trivial, and don't really need a separate header. - Platform data would be eventually removed, and platform information would be passed via device tree. Therefore, omapdss panel platform data structs are temporary, and will be easier to remove if they are all in the same header. - All board files will have to include the same header to configure a panel's platform data, that makes the board files more consistent. Signed-off-by: Archit Taneja --- include/video/omap-panel-data.h | 103 +++++++++++++++++++++++++++++++++ include/video/omap-panel-generic-dpi.h | 37 ------------ include/video/omap-panel-n8x0.h | 15 ----- include/video/omap-panel-nokia-dsi.h | 32 ---------- include/video/omap-panel-picodlp.h | 23 -------- include/video/omap-panel-tfp410.h | 35 ----------- 6 files changed, 103 insertions(+), 142 deletions(-) create mode 100644 include/video/omap-panel-data.h delete mode 100644 include/video/omap-panel-generic-dpi.h delete mode 100644 include/video/omap-panel-n8x0.h delete mode 100644 include/video/omap-panel-nokia-dsi.h delete mode 100644 include/video/omap-panel-picodlp.h delete mode 100644 include/video/omap-panel-tfp410.h (limited to 'include/video') diff --git a/include/video/omap-panel-data.h b/include/video/omap-panel-data.h new file mode 100644 index 000000000000..40a06b5b82de --- /dev/null +++ b/include/video/omap-panel-data.h @@ -0,0 +1,103 @@ +/* + * Header containing platform_data structs for omap panels + * + * Copyright (C) 2013 Texas Instruments + * Author: Tomi Valkeinen + * Archit Taneja + * + * Copyright (C) 2011 Texas Instruments + * Author: Mayuresh Janorkar + * + * Copyright (C) 2010 Canonical Ltd. + * Author: Bryan Wu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef __OMAP_PANEL_DATA_H +#define __OMAP_PANEL_DATA_H + +struct omap_dss_device; + +/** + * struct panel_generic_dpi_data - panel driver configuration data + * @name: panel name + * @platform_enable: platform specific panel enable function + * @platform_disable: platform specific panel disable function + */ +struct panel_generic_dpi_data { + const char *name; + int (*platform_enable)(struct omap_dss_device *dssdev); + void (*platform_disable)(struct omap_dss_device *dssdev); +}; + +/** + * struct panel_n8x0_data - N800 panel driver configuration data + */ +struct panel_n8x0_data { + int (*platform_enable)(struct omap_dss_device *dssdev); + void (*platform_disable)(struct omap_dss_device *dssdev); + int panel_reset; + int ctrl_pwrdown; + + int (*set_backlight)(struct omap_dss_device *dssdev, int level); +}; + +/** + * struct nokia_dsi_panel_data - Nokia DSI panel driver configuration data + * @name: panel name + * @use_ext_te: use external TE + * @ext_te_gpio: external TE GPIO + * @esd_interval: interval of ESD checks, 0 = disabled (ms) + * @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms) + * @use_dsi_backlight: true if panel uses DSI command to control backlight + * @pin_config: DSI pin configuration + */ + +struct nokia_dsi_panel_data { + const char *name; + + int reset_gpio; + + bool use_ext_te; + int ext_te_gpio; + + unsigned esd_interval; + unsigned ulps_timeout; + + bool use_dsi_backlight; + + struct omap_dsi_pin_config pin_config; +}; + +/** + * struct picodlp_panel_data - picodlp panel driver configuration data + * @picodlp_adapter_id: i2c_adapter number for picodlp + */ +struct picodlp_panel_data { + int picodlp_adapter_id; + int emu_done_gpio; + int pwrgood_gpio; +}; + +/** + * struct tfp410_platform_data - tfp410 panel driver configuration data + * @i2c_bus_num: i2c bus id for the panel + * @power_down_gpio: gpio number for PD pin (or -1 if not available) + */ +struct tfp410_platform_data { + int i2c_bus_num; + int power_down_gpio; +}; + +#endif /* __OMAP_PANEL_DATA_H */ diff --git a/include/video/omap-panel-generic-dpi.h b/include/video/omap-panel-generic-dpi.h deleted file mode 100644 index 127e3f20328e..000000000000 --- a/include/video/omap-panel-generic-dpi.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Header for generic DPI panel driver - * - * Copyright (C) 2010 Canonical Ltd. - * Author: Bryan Wu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#ifndef __OMAP_PANEL_GENERIC_DPI_H -#define __OMAP_PANEL_GENERIC_DPI_H - -struct omap_dss_device; - -/** - * struct panel_generic_dpi_data - panel driver configuration data - * @name: panel name - * @platform_enable: platform specific panel enable function - * @platform_disable: platform specific panel disable function - */ -struct panel_generic_dpi_data { - const char *name; - int (*platform_enable)(struct omap_dss_device *dssdev); - void (*platform_disable)(struct omap_dss_device *dssdev); -}; - -#endif /* __OMAP_PANEL_GENERIC_DPI_H */ diff --git a/include/video/omap-panel-n8x0.h b/include/video/omap-panel-n8x0.h deleted file mode 100644 index 50a1302e2cfd..000000000000 --- a/include/video/omap-panel-n8x0.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __OMAP_PANEL_N8X0_H -#define __OMAP_PANEL_N8X0_H - -struct omap_dss_device; - -struct panel_n8x0_data { - int (*platform_enable)(struct omap_dss_device *dssdev); - void (*platform_disable)(struct omap_dss_device *dssdev); - int panel_reset; - int ctrl_pwrdown; - - int (*set_backlight)(struct omap_dss_device *dssdev, int level); -}; - -#endif diff --git a/include/video/omap-panel-nokia-dsi.h b/include/video/omap-panel-nokia-dsi.h deleted file mode 100644 index 04219a295539..000000000000 --- a/include/video/omap-panel-nokia-dsi.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __OMAP_NOKIA_DSI_PANEL_H -#define __OMAP_NOKIA_DSI_PANEL_H - -struct omap_dss_device; - -/** - * struct nokia_dsi_panel_data - Nokia DSI panel driver configuration - * @name: panel name - * @use_ext_te: use external TE - * @ext_te_gpio: external TE GPIO - * @esd_interval: interval of ESD checks, 0 = disabled (ms) - * @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms) - * @use_dsi_backlight: true if panel uses DSI command to control backlight - * @pin_config: DSI pin configuration - */ -struct nokia_dsi_panel_data { - const char *name; - - int reset_gpio; - - bool use_ext_te; - int ext_te_gpio; - - unsigned esd_interval; - unsigned ulps_timeout; - - bool use_dsi_backlight; - - struct omap_dsi_pin_config pin_config; -}; - -#endif /* __OMAP_NOKIA_DSI_PANEL_H */ diff --git a/include/video/omap-panel-picodlp.h b/include/video/omap-panel-picodlp.h deleted file mode 100644 index 1c342ef6f3a1..000000000000 --- a/include/video/omap-panel-picodlp.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * panel data for picodlp panel - * - * Copyright (C) 2011 Texas Instruments - * - * Author: Mayuresh Janorkar - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef __PANEL_PICODLP_H -#define __PANEL_PICODLP_H -/** - * struct : picodlp panel data - * picodlp_adapter_id: i2c_adapter number for picodlp - */ -struct picodlp_panel_data { - int picodlp_adapter_id; - int emu_done_gpio; - int pwrgood_gpio; -}; -#endif /* __PANEL_PICODLP_H */ diff --git a/include/video/omap-panel-tfp410.h b/include/video/omap-panel-tfp410.h deleted file mode 100644 index aef35e48bc7e..000000000000 --- a/include/video/omap-panel-tfp410.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Header for TFP410 chip driver - * - * Copyright (C) 2011 Texas Instruments Inc - * Author: Tomi Valkeinen - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#ifndef __OMAP_PANEL_TFP410_H -#define __OMAP_PANEL_TFP410_H - -struct omap_dss_device; - -/** - * struct tfp410_platform_data - panel driver configuration data - * @i2c_bus_num: i2c bus id for the panel - * @power_down_gpio: gpio number for PD pin (or -1 if not available) - */ -struct tfp410_platform_data { - int i2c_bus_num; - int power_down_gpio; -}; - -#endif /* __OMAP_PANEL_TFP410_H */ -- cgit v1.2.3 From c3f80cbcac28dee4503a229bf1cc50c43425d857 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 12 Feb 2013 14:59:17 +0530 Subject: OMAPDSS: add fields to panels' platform data Forthcoming panel patches will change the panel drivers to use platform data to pass panel's gpios to the panel driver. This patch adds the required fields and platform data structs to the omap-panel-data.h file, so that the board files can be changed independently of the panel driver changes. Signed-off-by: Tomi Valkeinen Signed-off-by: Archit Taneja --- include/video/omap-panel-data.h | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'include/video') diff --git a/include/video/omap-panel-data.h b/include/video/omap-panel-data.h index 40a06b5b82de..6b55839b73fc 100644 --- a/include/video/omap-panel-data.h +++ b/include/video/omap-panel-data.h @@ -34,11 +34,18 @@ struct omap_dss_device; * @name: panel name * @platform_enable: platform specific panel enable function * @platform_disable: platform specific panel disable function + * @num_gpios: number of gpios connected to panel + * @gpios: gpio numbers on the platform + * @gpio_invert: configure gpio as active high or low */ struct panel_generic_dpi_data { const char *name; int (*platform_enable)(struct omap_dss_device *dssdev); void (*platform_disable)(struct omap_dss_device *dssdev); + + int num_gpios; + int gpios[10]; + bool gpio_invert[10]; }; /** @@ -100,4 +107,46 @@ struct tfp410_platform_data { int power_down_gpio; }; +/** + * sharp ls panel driver configuration data + * @resb_gpio: reset signal + * @ini_gpio: power on control + * @mo_gpio: selection for resolution(VGA/QVGA) + * @lr_gpio: selection for horizontal scanning direction + * @ud_gpio: selection for vertical scanning direction + */ +struct panel_sharp_ls037v7dw01_data { + int resb_gpio; + int ini_gpio; + int mo_gpio; + int lr_gpio; + int ud_gpio; +}; + +/** + * acx565akm panel driver configuration data + * @reset_gpio: reset signal + */ +struct panel_acx565akm_data { + int reset_gpio; +}; + +/** + * nec nl8048 panel driver configuration data + * @res_gpio: reset signal + * @qvga_gpio: selection for resolution(QVGA/WVGA) + */ +struct panel_nec_nl8048_data { + int res_gpio; + int qvga_gpio; +}; + +/** + * tpo td043 panel driver configuration data + * @nreset_gpio: reset signal + */ +struct panel_tpo_td043_data { + int nreset_gpio; +}; + #endif /* __OMAP_PANEL_DATA_H */ -- cgit v1.2.3 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 ++++++++++++++++++++++++------------------- include/video/omapdss.h | 21 ------------------- 2 files changed, 26 insertions(+), 42 deletions(-) (limited to 'include/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"); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index caefa093337d..255bcf558f89 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -591,27 +591,6 @@ struct omap_dss_device { } phy; struct { - struct { - struct { - u16 lck_div; - u16 pck_div; - enum omap_dss_clk_source lcd_clk_src; - } channel; - - enum omap_dss_clk_source dispc_fclk_src; - } dispc; - - struct { - /* regn is one greater than TRM's REGN value */ - u16 regn; - u16 regm; - u16 regm_dispc; - u16 regm_dsi; - - u16 lp_clk_div; - enum omap_dss_clk_source dsi_fclk_src; - } dsi; - struct { /* regn is one greater than TRM's REGN value */ u16 regn; -- cgit v1.2.3 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 +++-------- include/video/omapdss.h | 8 -------- 2 files changed, 3 insertions(+), 16 deletions(-) (limited to 'include/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 diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 255bcf558f89..2cb2b0e812af 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -590,14 +590,6 @@ struct omap_dss_device { } venc; } phy; - struct { - struct { - /* regn is one greater than TRM's REGN value */ - u16 regn; - u16 regm2; - } hdmi; - } clocks; - struct { struct omap_video_timings timings; -- cgit v1.2.3 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 + include/video/omapdss.h | 2 ++ 7 files changed, 8 insertions(+) (limited to 'include/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); } diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 2cb2b0e812af..fa800b7ef832 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -541,6 +541,8 @@ struct omap_dss_writeback_info { struct omap_dss_output { struct list_head list; + const char *name; + /* display type supported by the output */ enum omap_display_type type; -- cgit v1.2.3 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 +- include/video/omapdss.h | 4 +++ 8 files changed, 91 insertions(+), 11 deletions(-) (limited to 'include/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; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index fa800b7ef832..41fb434093e9 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -546,6 +546,9 @@ struct omap_dss_output { /* display type supported by the output */ enum omap_display_type type; + /* DISPC channel for this output */ + enum omap_channel dispc_channel; + /* output instance */ enum omap_dss_output_id id; @@ -563,6 +566,7 @@ struct omap_dss_device { enum omap_display_type type; + /* obsolete, to be removed */ enum omap_channel channel; union { -- cgit v1.2.3 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 +++++-------------------------- include/video/omapdss.h | 23 +++++----- 3 files changed, 31 insertions(+), 82 deletions(-) (limited to 'include/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 diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 41fb434093e9..4dd4cea41bd4 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -282,6 +282,16 @@ struct omap_dss_dsi_videomode_timings { int window_sync; }; +struct omap_dss_dsi_config { + enum omap_dss_dsi_mode mode; + enum omap_dss_dsi_pixel_format pixel_format; + const struct omap_video_timings *timings; + const struct omap_dss_dsi_videomode_timings *vm_timings; + + unsigned long hs_clk; + unsigned long lp_clk; +}; + void dsi_bus_lock(struct omap_dss_device *dssdev); void dsi_bus_unlock(struct omap_dss_device *dssdev); int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, @@ -806,15 +816,8 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, bool enable); int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable); -void omapdss_dsi_set_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); -void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h); -void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev, - enum omap_dss_dsi_pixel_format fmt); -void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev, - enum omap_dss_dsi_mode mode); -void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev, - struct omap_dss_dsi_videomode_timings *timings); +int omapdss_dsi_set_config(struct omap_dss_device *dssdev, + const struct omap_dss_dsi_config *config); int omap_dsi_update(struct omap_dss_device *dssdev, int channel, void (*callback)(int, void *), void *data); @@ -823,8 +826,6 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id); void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel); int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev, const struct omap_dsi_pin_config *pin_cfg); -int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, - unsigned long ddr_clk, unsigned long lp_clk); int omapdss_dsi_display_enable(struct omap_dss_device *dssdev); void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, -- cgit v1.2.3 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 ++++++++++----- include/video/omapdss.h | 13 ++++++++++--- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'include/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; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 4dd4cea41bd4..7f774c5f8b6b 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -257,6 +257,15 @@ void rfbi_bus_unlock(void); /* DSI */ +enum omap_dss_dsi_trans_mode { + /* Sync Pulses: both sync start and end packets sent */ + OMAP_DSS_DSI_PULSE_MODE, + /* Sync Events: only sync start packets sent */ + OMAP_DSS_DSI_EVENT_MODE, + /* Burst: only sync start packets sent, pixels are time compressed */ + OMAP_DSS_DSI_BURST_MODE, +}; + struct omap_dss_dsi_videomode_timings { /* DSI video mode blanking data */ /* Unit: byte clock cycles */ @@ -274,9 +283,7 @@ struct omap_dss_dsi_videomode_timings { int hbp_blanking_mode; int hfp_blanking_mode; - /* Video port sync events */ - bool vp_vsync_end; - bool vp_hsync_end; + enum omap_dss_dsi_trans_mode trans_mode; bool ddr_clk_always_on; int window_sync; -- cgit v1.2.3 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 +++++++++++++++++++++++++++++- include/video/omapdss.h | 20 +- 3 files changed, 566 insertions(+), 18 deletions(-) (limited to 'include/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); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 7f774c5f8b6b..8821d933d9fd 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -267,9 +267,21 @@ enum omap_dss_dsi_trans_mode { }; struct omap_dss_dsi_videomode_timings { + unsigned long hsclk; + + unsigned ndl; + unsigned bitspp; + + /* pixels */ + u16 hact; + /* lines */ + u16 vact; + /* DSI video mode blanking data */ /* Unit: byte clock cycles */ + u16 hss; u16 hsa; + u16 hse; u16 hfp; u16 hbp; /* Unit: line clocks */ @@ -293,10 +305,12 @@ struct omap_dss_dsi_config { enum omap_dss_dsi_mode mode; enum omap_dss_dsi_pixel_format pixel_format; const struct omap_video_timings *timings; - const struct omap_dss_dsi_videomode_timings *vm_timings; - unsigned long hs_clk; - unsigned long lp_clk; + unsigned long hs_clk_min, hs_clk_max; + unsigned long lp_clk_min, lp_clk_max; + + bool ddr_clk_always_on; + enum omap_dss_dsi_trans_mode trans_mode; }; void dsi_bus_lock(struct omap_dss_device *dssdev); -- cgit v1.2.3 From 77d3595b29e2289cb6f9e4cece5fca1335554d56 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 6 Mar 2013 17:17:26 +0200 Subject: OMAPDSS: remove dsi videomode from dssdev DSI videomode is no longer needed in the omap_dss_device, so remove it. Signed-off-by: Tomi Valkeinen --- include/video/omapdss.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/video') diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 8821d933d9fd..62ca9a77c1d6 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -632,7 +632,6 @@ struct omap_dss_device { enum omap_dss_dsi_pixel_format dsi_pix_fmt; enum omap_dss_dsi_mode dsi_mode; - struct omap_dss_dsi_videomode_timings dsi_vm_timings; } panel; struct { -- cgit v1.2.3 From a4419f3eac875e66a01b654024f6eda17d0dd558 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 12 Feb 2013 16:45:23 +0530 Subject: OMAPDSS: n8x0: remove platform backlight calls The n8x0 panel contains support to call platform backlight functions. These are not used by any board, and can be removed. Signed-off-by: Tomi Valkeinen Signed-off-by: Archit Taneja --- drivers/video/omap2/displays/panel-n8x0.c | 74 ------------------------------- include/video/omap-panel-data.h | 2 - 2 files changed, 76 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c index 9c6b5fafeb2e..9c55c9152863 100644 --- a/drivers/video/omap2/displays/panel-n8x0.c +++ b/drivers/video/omap2/displays/panel-n8x0.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include