diff options
68 files changed, 6465 insertions, 4567 deletions
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index bb5452eb842..69d698c6c5d 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -39,6 +39,9 @@  #include <plat/usb.h>  #include <plat/gpmc-smc91x.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> +  #include "mux.h"  #include "hsmmc.h"  #include "common-board-devices.h" @@ -99,20 +102,72 @@ static struct platform_device sdp2430_flash_device = {  	.resource	= &sdp2430_flash_resource,  }; -static struct platform_device sdp2430_lcd_device = { -	.name		= "sdp2430_lcd", -	.id		= -1, -}; -  static struct platform_device *sdp2430_devices[] __initdata = {  	&sdp2430_flash_device, +}; + +/* LCD */ +#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO	91 +#define SDP2430_LCD_PANEL_ENABLE_GPIO		154 + +static int sdp2430_panel_enable_lcd(struct omap_dss_device *dssdev) +{ +	gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 1); +	gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 1); + +	return 0; +} + +static void sdp2430_panel_disable_lcd(struct omap_dss_device *dssdev) +{ +	gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 0); +	gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 0); +} + +static struct panel_generic_dpi_data sdp2430_panel_data = { +	.name			= "nec_nl2432dr22-11b", +	.platform_enable	= sdp2430_panel_enable_lcd, +	.platform_disable	= sdp2430_panel_disable_lcd, +}; + +static struct omap_dss_device sdp2430_lcd_device = { +	.name			= "lcd", +	.driver_name		= "generic_dpi_panel", +	.type			= OMAP_DISPLAY_TYPE_DPI, +	.phy.dpi.data_lines	= 16, +	.data			= &sdp2430_panel_data, +}; + +static struct omap_dss_device *sdp2430_dss_devices[] = {  	&sdp2430_lcd_device,  }; -static struct omap_lcd_config sdp2430_lcd_config __initdata = { -	.ctrl_name	= "internal", +static struct omap_dss_board_info sdp2430_dss_data = { +	.num_devices	= ARRAY_SIZE(sdp2430_dss_devices), +	.devices	= sdp2430_dss_devices, +	.default_device	= &sdp2430_lcd_device,  }; +static void __init sdp2430_display_init(void) +{ +	int r; + +	static struct gpio gpios[] __initdata = { +		{ SDP2430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW, +			"LCD reset" }, +		{ SDP2430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW, +			"LCD Backlight" }, +	}; + +	r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); +	if (r) { +		pr_err("Cannot request LCD GPIOs, error %d\n", r); +		return; +	} + +	omap_display_init(&sdp2430_dss_data); +} +  #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)  static struct omap_smc91x_platform_data board_smc91x_data = { @@ -137,10 +192,6 @@ static inline void board_smc91x_init(void)  #endif -static struct omap_board_config_kernel sdp2430_config[] __initdata = { -	{OMAP_TAG_LCD, &sdp2430_lcd_config}, -}; -  static struct regulator_consumer_supply sdp2430_vmmc1_supplies[] = {  	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),  }; @@ -222,9 +273,6 @@ static void __init omap_2430sdp_init(void)  {  	omap2430_mux_init(board_mux, OMAP_PACKAGE_ZAC); -	omap_board_config = sdp2430_config; -	omap_board_config_size = ARRAY_SIZE(sdp2430_config); -  	omap2430_i2c_init();  	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices)); @@ -241,6 +289,8 @@ static void __init omap_2430sdp_init(void)  	/* Turn off secondary LCD backlight */  	gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,  			 "Secondary LCD backlight"); + +	sdp2430_display_init();  }  MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board") diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 5b5999caf71..77142c13fa1 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -37,7 +37,7 @@  #include <plat/dma.h>  #include <plat/gpmc.h>  #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include <plat/gpmc-smc91x.h> @@ -186,8 +186,7 @@ static struct omap_dss_device sdp3430_lcd_device = {  	.platform_disable	= sdp3430_panel_disable_lcd,  }; -static struct panel_generic_dpi_data dvi_panel = { -	.name			= "generic", +static struct panel_dvi_platform_data dvi_panel = {  	.platform_enable	= sdp3430_panel_enable_dvi,  	.platform_disable	= sdp3430_panel_disable_dvi,  }; @@ -195,7 +194,7 @@ static struct panel_generic_dpi_data dvi_panel = {  static struct omap_dss_device sdp3430_dvi_device = {  	.name			= "dvi",  	.type			= OMAP_DISPLAY_TYPE_DPI, -	.driver_name		= "generic_dpi_panel", +	.driver_name		= "dvi",  	.data			= &dvi_panel,  	.phy.dpi.data_lines	= 24,  }; diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 6a4fbb2b4aa..32a3a7fe0e9 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -38,6 +38,8 @@  #include <plat/mmc.h>  #include <plat/omap4-keypad.h>  #include <video/omapdss.h> +#include <video/omap-panel-nokia-dsi.h> +#include <video/omap-panel-picodlp.h>  #include <linux/wl12xx.h>  #include "mux.h" @@ -52,6 +54,8 @@  #define OMAP4_SFH7741_ENABLE_GPIO		188  #define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */  #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ +#define DISPLAY_SEL_GPIO	59	/* LCD2/PicoDLP switch */ +#define DLP_POWER_ON_GPIO	40  #define GPIO_WIFI_PMENA		54  #define GPIO_WIFI_IRQ		53 @@ -340,11 +344,6 @@ static int __init omap_ethernet_init(void)  	return status;  } -static struct platform_device sdp4430_lcd_device = { -	.name		= "sdp4430_lcd", -	.id		= -1, -}; -  static struct regulator_consumer_supply sdp4430_vbat_supply[] = {  	REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"),  	REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"), @@ -374,21 +373,12 @@ static struct platform_device sdp4430_vbat = {  };  static struct platform_device *sdp4430_devices[] __initdata = { -	&sdp4430_lcd_device,  	&sdp4430_gpio_keys_device,  	&sdp4430_leds_gpio,  	&sdp4430_leds_pwm,  	&sdp4430_vbat,  }; -static struct omap_lcd_config sdp4430_lcd_config __initdata = { -	.ctrl_name	= "internal", -}; - -static struct omap_board_config_kernel sdp4430_config[] __initdata = { -	{ OMAP_TAG_LCD,		&sdp4430_lcd_config }, -}; -  static struct omap_musb_board_data musb_board_data = {  	.interface_type		= MUSB_INTERFACE_UTMI,  	.mode			= MUSB_OTG, @@ -642,37 +632,202 @@ static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)  	gpio_free(HDMI_GPIO_HPD);  } -static struct omap_dss_device sdp4430_hdmi_device = { -	.name = "hdmi", -	.driver_name = "hdmi_panel", -	.type = OMAP_DISPLAY_TYPE_HDMI, -	.clocks	= { -		.dispc	= { +static struct nokia_dsi_panel_data dsi1_panel = { +		.name		= "taal", +		.reset_gpio	= 102, +		.use_ext_te	= false, +		.ext_te_gpio	= 101, +		.esd_interval	= 0, +}; + +static struct omap_dss_device sdp4430_lcd_device = { +	.name			= "lcd", +	.driver_name		= "taal", +	.type			= OMAP_DISPLAY_TYPE_DSI, +	.data			= &dsi1_panel, +	.phy.dsi		= { +		.clk_lane	= 1, +		.clk_pol	= 0, +		.data1_lane	= 2, +		.data1_pol	= 0, +		.data2_lane	= 3, +		.data2_pol	= 0, + +		.module		= 0, +	}, + +	.clocks = { +		.dispc = { +			.channel = { +				/* Logic Clock = 172.8 MHz */ +				.lck_div	= 1, +				/* Pixel Clock = 34.56 MHz */ +				.pck_div	= 5, +				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, +			}, +			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK, +		}, + +		.dsi = { +			.regn		= 16,	/* Fint = 2.4 MHz */ +			.regm		= 180,	/* DDR Clock = 216 MHz */ +			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */ +			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */ + +			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */ +			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, +		}, +	}, +	.channel		= OMAP_DSS_CHANNEL_LCD, +}; + +static struct nokia_dsi_panel_data dsi2_panel = { +		.name		= "taal", +		.reset_gpio	= 104, +		.use_ext_te	= false, +		.ext_te_gpio	= 103, +		.esd_interval	= 0, +}; + +static struct omap_dss_device sdp4430_lcd2_device = { +	.name			= "lcd2", +	.driver_name		= "taal", +	.type			= OMAP_DISPLAY_TYPE_DSI, +	.data			= &dsi2_panel, +	.phy.dsi		= { +		.clk_lane	= 1, +		.clk_pol	= 0, +		.data1_lane	= 2, +		.data1_pol	= 0, +		.data2_lane	= 3, +		.data2_pol	= 0, + +		.module		= 1, +	}, + +	.clocks = { +		.dispc = { +			.channel = { +				/* Logic Clock = 172.8 MHz */ +				.lck_div	= 1, +				/* Pixel Clock = 34.56 MHz */ +				.pck_div	= 5, +				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC, +			},  			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,  		}, -		.hdmi	= { -			.regn	= 15, -			.regm2	= 1, + +		.dsi = { +			.regn		= 16,	/* Fint = 2.4 MHz */ +			.regm		= 180,	/* DDR Clock = 216 MHz */ +			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */ +			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */ + +			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */ +			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI,  		},  	}, +	.channel		= OMAP_DSS_CHANNEL_LCD2, +}; + +static void sdp4430_lcd_init(void) +{ +	int r; + +	r = gpio_request_one(dsi1_panel.reset_gpio, GPIOF_DIR_OUT, +		"lcd1_reset_gpio"); +	if (r) +		pr_err("%s: Could not get lcd1_reset_gpio\n", __func__); + +	r = gpio_request_one(dsi2_panel.reset_gpio, GPIOF_DIR_OUT, +		"lcd2_reset_gpio"); +	if (r) +		pr_err("%s: Could not get lcd2_reset_gpio\n", __func__); +} + +static struct omap_dss_device sdp4430_hdmi_device = { +	.name = "hdmi", +	.driver_name = "hdmi_panel", +	.type = OMAP_DISPLAY_TYPE_HDMI,  	.platform_enable = sdp4430_panel_enable_hdmi,  	.platform_disable = sdp4430_panel_disable_hdmi,  	.channel = OMAP_DSS_CHANNEL_DIGIT,  }; +static struct picodlp_panel_data sdp4430_picodlp_pdata = { +	.picodlp_adapter_id	= 2, +	.emu_done_gpio		= 44, +	.pwrgood_gpio		= 45, +}; + +static void sdp4430_picodlp_init(void) +{ +	int r; +	const struct gpio picodlp_gpios[] = { +		{DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW, +			"DLP POWER ON"}, +		{sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN, +			"DLP EMU DONE"}, +		{sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW, +			"DLP PWRGOOD"}, +	}; + +	r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios)); +	if (r) +		pr_err("Cannot request PicoDLP GPIOs, error %d\n", r); +} + +static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev) +{ +	gpio_set_value(DISPLAY_SEL_GPIO, 0); +	gpio_set_value(DLP_POWER_ON_GPIO, 1); + +	return 0; +} + +static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev) +{ +	gpio_set_value(DLP_POWER_ON_GPIO, 0); +	gpio_set_value(DISPLAY_SEL_GPIO, 1); +} + +static struct omap_dss_device sdp4430_picodlp_device = { +	.name			= "picodlp", +	.driver_name		= "picodlp_panel", +	.type			= OMAP_DISPLAY_TYPE_DPI, +	.phy.dpi.data_lines	= 24, +	.channel		= OMAP_DSS_CHANNEL_LCD2, +	.platform_enable	= sdp4430_panel_enable_picodlp, +	.platform_disable	= sdp4430_panel_disable_picodlp, +	.data			= &sdp4430_picodlp_pdata, +}; +  static struct omap_dss_device *sdp4430_dss_devices[] = { +	&sdp4430_lcd_device, +	&sdp4430_lcd2_device,  	&sdp4430_hdmi_device, +	&sdp4430_picodlp_device,  };  static struct omap_dss_board_info sdp4430_dss_data = {  	.num_devices	= ARRAY_SIZE(sdp4430_dss_devices),  	.devices	= sdp4430_dss_devices, -	.default_device	= &sdp4430_hdmi_device, +	.default_device	= &sdp4430_lcd_device,  }; -void omap_4430sdp_display_init(void) +static void omap_4430sdp_display_init(void)  { +	int r; + +	/* Enable LCD2 by default (instead of Pico DLP) */ +	r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH, +			"display_sel"); +	if (r) +		pr_err("%s: Could not get display_sel GPIO\n", __func__); + +	sdp4430_lcd_init();  	sdp4430_hdmi_mux_init(); +	sdp4430_picodlp_init();  	omap_display_init(&sdp4430_dss_data);  } @@ -796,9 +951,6 @@ static void __init omap_4430sdp_init(void)  		package = OMAP_PACKAGE_CBL;  	omap4_mux_init(board_mux, NULL, package); -	omap_board_config = sdp4430_config; -	omap_board_config_size = ARRAY_SIZE(sdp4430_config); -  	omap4_i2c_init();  	omap_sfh7741prox_init();  	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices)); diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 65a5912278a..d314f033c9d 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -36,6 +36,7 @@  #include <plat/usb.h>  #include <video/omapdss.h>  #include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include "mux.h"  #include "control.h" @@ -333,8 +334,7 @@ static void am3517_evm_panel_disable_dvi(struct omap_dss_device *dssdev)  	dvi_enabled = 0;  } -static struct panel_generic_dpi_data dvi_panel = { -	.name			= "generic", +static struct panel_dvi_platform_data dvi_panel = {  	.platform_enable	= am3517_evm_panel_enable_dvi,  	.platform_disable	= am3517_evm_panel_disable_dvi,  }; @@ -342,7 +342,7 @@ static struct panel_generic_dpi_data dvi_panel = {  static struct omap_dss_device am3517_evm_dvi_device = {  	.type			= OMAP_DISPLAY_TYPE_DPI,  	.name			= "dvi", -	.driver_name		= "generic_dpi_panel", +	.driver_name		= "dvi",  	.data			= &dvi_panel,  	.phy.dpi.data_lines	= 24,  }; diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 29c409b68b5..de8134b7f58 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -40,6 +40,9 @@  #include <plat/common.h>  #include <plat/gpmc.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> +  #include "mux.h"  #include "control.h" @@ -149,11 +152,6 @@ static struct platform_device apollon_smc91x_device = {  	.resource	= apollon_smc91x_resources,  }; -static struct platform_device apollon_lcd_device = { -	.name		= "apollon_lcd", -	.id		= -1, -}; -  static struct omap_led_config apollon_led_config[] = {  	{  		.cdev	= { @@ -191,7 +189,6 @@ static struct platform_device apollon_led_device = {  static struct platform_device *apollon_devices[] __initdata = {  	&apollon_onenand_device,  	&apollon_smc91x_device, -	&apollon_lcd_device,  	&apollon_led_device,  }; @@ -265,12 +262,26 @@ static struct omap_usb_config apollon_usb_config __initdata = {  	.pins[0]	= 6,  }; -static struct omap_lcd_config apollon_lcd_config __initdata = { -	.ctrl_name	= "internal", +static struct panel_generic_dpi_data apollon_panel_data = { +	.name			= "apollon", +}; + +static struct omap_dss_device apollon_lcd_device = { +	.name			= "lcd", +	.driver_name		= "generic_dpi_panel", +	.type			= OMAP_DISPLAY_TYPE_DPI, +	.phy.dpi.data_lines	= 18, +	.data			= &apollon_panel_data, +}; + +static struct omap_dss_device *apollon_dss_devices[] = { +	&apollon_lcd_device,  }; -static struct omap_board_config_kernel apollon_config[] __initdata = { -	{ OMAP_TAG_LCD,		&apollon_lcd_config }, +static struct omap_dss_board_info apollon_dss_data = { +	.num_devices	= ARRAY_SIZE(apollon_dss_devices), +	.devices	= apollon_dss_devices, +	.default_device	= &apollon_lcd_device,  };  static struct gpio apollon_gpio_leds[] __initdata = { @@ -308,8 +319,6 @@ static void __init omap_apollon_init(void)  	u32 v;  	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC); -	omap_board_config = apollon_config; -	omap_board_config_size = ARRAY_SIZE(apollon_config);  	apollon_init_smc91x();  	apollon_led_init(); @@ -335,6 +344,7 @@ static void __init omap_apollon_init(void)  	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));  	omap_serial_init();  	omap_sdrc_init(NULL, NULL); +	omap_display_init(&apollon_dss_data);  }  MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon") diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 5665e688bd2..bd1bcacb40f 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -43,6 +43,7 @@  #include <plat/usb.h>  #include <video/omapdss.h>  #include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include <plat/mcspi.h>  #include <mach/hardware.h> @@ -242,8 +243,7 @@ static struct omap_dss_device cm_t35_lcd_device = {  	.phy.dpi.data_lines	= 18,  }; -static struct panel_generic_dpi_data dvi_panel = { -	.name			= "generic", +static struct panel_dvi_platform_data dvi_panel = {  	.platform_enable	= cm_t35_panel_enable_dvi,  	.platform_disable	= cm_t35_panel_disable_dvi,  }; @@ -251,7 +251,7 @@ static struct panel_generic_dpi_data dvi_panel = {  static struct omap_dss_device cm_t35_dvi_device = {  	.name			= "dvi",  	.type			= OMAP_DISPLAY_TYPE_DPI, -	.driver_name		= "generic_dpi_panel", +	.driver_name		= "dvi",  	.data			= &dvi_panel,  	.phy.dpi.data_lines	= 24,  }; diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 556df32d88e..42918940c53 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -47,6 +47,7 @@  #include <plat/usb.h>  #include <video/omapdss.h>  #include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include <plat/mcspi.h>  #include <linux/input/matrix_keypad.h> @@ -139,7 +140,7 @@ static struct regulator_consumer_supply devkit8000_vio_supply[] = {  };  static struct panel_generic_dpi_data lcd_panel = { -	.name			= "generic", +	.name			= "innolux_at070tn83",  	.platform_enable        = devkit8000_panel_enable_lcd,  	.platform_disable       = devkit8000_panel_disable_lcd,  }; @@ -152,8 +153,7 @@ static struct omap_dss_device devkit8000_lcd_device = {  	.phy.dpi.data_lines     = 24,  }; -static struct panel_generic_dpi_data dvi_panel = { -	.name			= "generic", +static struct panel_dvi_platform_data dvi_panel = {  	.platform_enable        = devkit8000_panel_enable_dvi,  	.platform_disable       = devkit8000_panel_disable_dvi,  }; @@ -161,7 +161,7 @@ static struct panel_generic_dpi_data dvi_panel = {  static struct omap_dss_device devkit8000_dvi_device = {  	.name                   = "dvi",  	.type                   = OMAP_DISPLAY_TYPE_DPI, -	.driver_name            = "generic_dpi_panel", +	.driver_name            = "dvi",  	.data			= &dvi_panel,  	.phy.dpi.data_lines     = 24,  }; @@ -267,7 +267,7 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = {  static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {  	REGULATOR_SUPPLY("vdds_dsi", "omapdss"), -	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),  };  /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index fe75c195f69..9a114bd910b 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -40,6 +40,9 @@  #include <plat/dma.h>  #include <plat/gpmc.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> +  #include "mux.h"  #include "control.h" @@ -157,17 +160,33 @@ static struct platform_device h4_kp_device = {  	},  }; -static struct platform_device h4_lcd_device = { -	.name		= "lcd_h4", -	.id		= -1, -}; -  static struct platform_device *h4_devices[] __initdata = {  	&h4_flash_device,  	&h4_kp_device, +}; + +static struct panel_generic_dpi_data h4_panel_data = { +	.name			= "h4", +}; + +static struct omap_dss_device h4_lcd_device = { +	.name			= "lcd", +	.driver_name		= "generic_dpi_panel", +	.type			= OMAP_DISPLAY_TYPE_DPI, +	.phy.dpi.data_lines	= 16, +	.data			= &h4_panel_data, +}; + +static struct omap_dss_device *h4_dss_devices[] = {  	&h4_lcd_device,  }; +static struct omap_dss_board_info h4_dss_data = { +	.num_devices	= ARRAY_SIZE(h4_dss_devices), +	.devices	= h4_dss_devices, +	.default_device	= &h4_lcd_device, +}; +  /* 2420 Sysboot setup (2430 is different) */  static u32 get_sysboot_value(void)  { @@ -271,10 +290,6 @@ static void __init h4_init_flash(void)  	h4_flash_resource.end	= base + SZ_64M - 1;  } -static struct omap_lcd_config h4_lcd_config __initdata = { -	.ctrl_name	= "internal", -}; -  static struct omap_usb_config h4_usb_config __initdata = {  	/* S1.10 OFF -- usb "download port"  	 * usb0 switched to Mini-B port and isp1105 transceiver; @@ -286,10 +301,6 @@ static struct omap_usb_config h4_usb_config __initdata = {  	.hmc_mode	= 0x00,		/* 0:dev|otg 1:disable 2:disable */  }; -static struct omap_board_config_kernel h4_config[] __initdata = { -	{ OMAP_TAG_LCD,		&h4_lcd_config }, -}; -  static struct at24_platform_data m24c01 = {  	.byte_len	= SZ_1K / 8,  	.page_size	= 16, @@ -320,9 +331,6 @@ static void __init omap_h4_init(void)  {  	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAF); -	omap_board_config = h4_config; -	omap_board_config_size = ARRAY_SIZE(h4_config); -  	/*  	 * Make sure the serial ports are muxed on at this point.  	 * You have to mux them off in device drivers later on @@ -362,6 +370,8 @@ static void __init omap_h4_init(void)  	omap_serial_init();  	omap_sdrc_init(NULL, NULL);  	h4_init_flash(); + +	omap_display_init(&h4_dss_data);  }  MACHINE_START(OMAP_H4, "OMAP2420 H4 board") diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index e20cad6a083..d0a3f78a9b6 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -32,7 +32,7 @@  #include <plat/gpmc.h>  #include <plat/usb.h>  #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include <plat/onenand.h>  #include "mux.h" @@ -455,16 +455,16 @@ static void igep2_disable_dvi(struct omap_dss_device *dssdev)  	gpio_direction_output(IGEP2_GPIO_DVI_PUP, 0);  } -static struct panel_generic_dpi_data dvi_panel = { -	.name			= "generic", +static struct panel_dvi_platform_data dvi_panel = {  	.platform_enable	= igep2_enable_dvi,  	.platform_disable	= igep2_disable_dvi, +	.i2c_bus_num = 3,  };  static struct omap_dss_device igep2_dvi_device = {  	.type			= OMAP_DISPLAY_TYPE_DPI,  	.name			= "dvi", -	.driver_name		= "generic_dpi_panel", +	.driver_name		= "dvi",  	.data			= &dvi_panel,  	.phy.dpi.data_lines	= 24,  }; diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 0fa28be2cfd..2a2545153d1 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -27,6 +27,7 @@  #include <linux/io.h>  #include <linux/smsc911x.h>  #include <linux/mmc/host.h> +#include <linux/gpio.h>  #include <mach/hardware.h>  #include <asm/mach-types.h> @@ -34,7 +35,6 @@  #include <asm/mach/map.h>  #include <plat/mcspi.h> -#include <mach/gpio.h>  #include <plat/board.h>  #include <plat/common.h>  #include <plat/gpmc.h> @@ -44,6 +44,9 @@  #include <plat/usb.h>  #include <plat/gpmc-smsc911x.h> +#include <video/omapdss.h> +#include <video/omap-panel-generic-dpi.h> +  #include "board-flash.h"  #include "mux.h"  #include "hsmmc.h" @@ -180,23 +183,102 @@ static inline void __init ldp_init_smsc911x(void)  	gpmc_smsc911x_init(&smsc911x_cfg);  } -static struct platform_device ldp_lcd_device = { -	.name		= "ldp_lcd", -	.id		= -1, +/* LCD */ + +static int ldp_backlight_gpio; +static int ldp_lcd_enable_gpio; + +#define LCD_PANEL_RESET_GPIO		55 +#define LCD_PANEL_QVGA_GPIO		56 + +static int ldp_panel_enable_lcd(struct omap_dss_device *dssdev) +{ +	if (gpio_is_valid(ldp_lcd_enable_gpio)) +		gpio_direction_output(ldp_lcd_enable_gpio, 1); +	if (gpio_is_valid(ldp_backlight_gpio)) +		gpio_direction_output(ldp_backlight_gpio, 1); + +	return 0; +} + +static void ldp_panel_disable_lcd(struct omap_dss_device *dssdev) +{ +	if (gpio_is_valid(ldp_lcd_enable_gpio)) +		gpio_direction_output(ldp_lcd_enable_gpio, 0); +	if (gpio_is_valid(ldp_backlight_gpio)) +		gpio_direction_output(ldp_backlight_gpio, 0); +} + +static struct panel_generic_dpi_data ldp_panel_data = { +	.name			= "nec_nl2432dr22-11b", +	.platform_enable	= ldp_panel_enable_lcd, +	.platform_disable	= ldp_panel_disable_lcd,  }; -static struct omap_lcd_config ldp_lcd_config __initdata = { -	.ctrl_name	= "internal", +static struct omap_dss_device ldp_lcd_device = { +	.name			= "lcd", +	.driver_name		= "generic_dpi_panel", +	.type			= OMAP_DISPLAY_TYPE_DPI, +	.phy.dpi.data_lines	= 18, +	.data			= &ldp_panel_data, +}; + +static struct omap_dss_device *ldp_dss_devices[] = { +	&ldp_lcd_device,  }; -static struct omap_board_config_kernel ldp_config[] __initdata = { -	{ OMAP_TAG_LCD,		&ldp_lcd_config }, +static struct omap_dss_board_info ldp_dss_data = { +	.num_devices	= ARRAY_SIZE(ldp_dss_devices), +	.devices	= ldp_dss_devices, +	.default_device	= &ldp_lcd_device,  }; +static void __init ldp_display_init(void) +{ +	int r; + +	static struct gpio gpios[] __initdata = { +		{LCD_PANEL_RESET_GPIO, GPIOF_OUT_INIT_HIGH, "LCD RESET"}, +		{LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "LCD QVGA"}, +	}; + +	r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); +	if (r) { +		pr_err("Cannot request LCD GPIOs, error %d\n", r); +		return; +	} + +	omap_display_init(&ldp_dss_data); +} + +static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) +{ +	int r; + +	struct gpio gpios[] = { +		{gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"}, +		{gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"}, +	}; + +	r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); +	if (r) { +		pr_err("Cannot request LCD GPIOs, error %d\n", r); +		ldp_backlight_gpio = -EINVAL; +		ldp_lcd_enable_gpio = -EINVAL; +		return r; +	} + +	ldp_backlight_gpio = gpio + 15; +	ldp_lcd_enable_gpio = gpio + 7; + +	return 0; +} +  static struct twl4030_gpio_platform_data ldp_gpio_data = {  	.gpio_base	= OMAP_MAX_GPIO_LINES,  	.irq_base	= TWL4030_GPIO_IRQ_BASE,  	.irq_end	= TWL4030_GPIO_IRQ_END, +	.setup		= ldp_twl_gpio_setup,  };  static struct regulator_consumer_supply ldp_vmmc1_supply[] = { @@ -238,10 +320,31 @@ static struct regulator_init_data ldp_vaux1 = {  	.consumer_supplies		= ldp_vaux1_supplies,  }; +static struct regulator_consumer_supply ldp_vpll2_supplies[] = { +	REGULATOR_SUPPLY("vdds_dsi", "omapdss"), +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +}; + +static struct regulator_init_data ldp_vpll2 = { +	.constraints = { +		.name			= "VDVI", +		.min_uV			= 1800000, +		.max_uV			= 1800000, +		.apply_uV		= true, +		.valid_modes_mask	= REGULATOR_MODE_NORMAL +					| REGULATOR_MODE_STANDBY, +		.valid_ops_mask		= REGULATOR_CHANGE_MODE +					| REGULATOR_CHANGE_STATUS, +	}, +	.num_consumer_supplies	= ARRAY_SIZE(ldp_vpll2_supplies), +	.consumer_supplies	= ldp_vpll2_supplies, +}; +  static struct twl4030_platform_data ldp_twldata = {  	/* platform_data for children goes here */  	.vmmc1		= &ldp_vmmc1,  	.vaux1		= &ldp_vaux1, +	.vpll2		= &ldp_vpll2,  	.gpio		= &ldp_gpio_data,  	.keypad		= &ldp_kp_twl4030_data,  }; @@ -267,7 +370,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {  };  static struct platform_device *ldp_devices[] __initdata = { -	&ldp_lcd_device,  	&ldp_gpio_keys_device,  }; @@ -312,8 +414,6 @@ static struct mtd_partition ldp_nand_partitions[] = {  static void __init omap_ldp_init(void)  {  	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); -	omap_board_config = ldp_config; -	omap_board_config_size = ARRAY_SIZE(ldp_config);  	ldp_init_smsc911x();  	omap_i2c_init();  	platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices)); @@ -325,6 +425,7 @@ static void __init omap_ldp_init(void)  		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);  	omap2_hsmmc_init(mmc); +	ldp_display_init();  }  MACHINE_START(OMAP_LDP, "OMAP LDP board") diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 3826493d1b2..474a7e2cb63 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -42,7 +42,7 @@  #include <plat/board.h>  #include <plat/common.h>  #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include <plat/gpmc.h>  #include <plat/nand.h>  #include <plat/usb.h> @@ -203,16 +203,16 @@ static void beagle_disable_dvi(struct omap_dss_device *dssdev)  		gpio_set_value(dssdev->reset_gpio, 0);  } -static struct panel_generic_dpi_data dvi_panel = { -	.name = "generic", +static struct panel_dvi_platform_data dvi_panel = {  	.platform_enable = beagle_enable_dvi,  	.platform_disable = beagle_disable_dvi, +	.i2c_bus_num = 3,  };  static struct omap_dss_device beagle_dvi_device = {  	.type = OMAP_DISPLAY_TYPE_DPI,  	.name = "dvi", -	.driver_name = "generic_dpi_panel", +	.driver_name = "dvi",  	.data = &dvi_panel,  	.phy.dpi.data_lines = 24,  	.reset_gpio = -EINVAL, diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index aa6a9351ce4..2d24e287e8c 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -45,7 +45,7 @@  #include <plat/common.h>  #include <plat/mcspi.h>  #include <video/omapdss.h> -#include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include "mux.h"  #include "sdram-micron-mt46h32m32lf-6.h" @@ -247,8 +247,7 @@ static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev)  	dvi_enabled = 0;  } -static struct panel_generic_dpi_data dvi_panel = { -	.name			= "generic", +static struct panel_dvi_platform_data dvi_panel = {  	.platform_enable	= omap3_evm_enable_dvi,  	.platform_disable	= omap3_evm_disable_dvi,  }; @@ -256,7 +255,7 @@ static struct panel_generic_dpi_data dvi_panel = {  static struct omap_dss_device omap3_evm_dvi_device = {  	.name			= "dvi",  	.type			= OMAP_DISPLAY_TYPE_DPI, -	.driver_name		= "generic_dpi_panel", +	.driver_name		= "dvi",  	.data			= &dvi_panel,  	.phy.dpi.data_lines	= 24,  }; diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index fed2f7dfdf8..f7811f4cfc3 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -335,7 +335,7 @@ static struct regulator_consumer_supply pandora_vmmc3_supply[] = {  static struct regulator_consumer_supply pandora_vdds_supplies[] = {  	REGULATOR_SUPPLY("vdds_sdi", "omapdss"),  	REGULATOR_SUPPLY("vdds_dsi", "omapdss"), -	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),  };  static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = { diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index 170e1ebd6e6..ddb7d6663c6 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -41,6 +41,7 @@  #include <plat/usb.h>  #include <video/omapdss.h>  #include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include <plat/mcspi.h>  #include <linux/input/matrix_keypad.h> @@ -107,39 +108,6 @@ static void __init omap3_stalker_display_init(void)  	return;  } -static int omap3_stalker_enable_lcd(struct omap_dss_device *dssdev) -{ -	if (dvi_enabled) { -		printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); -		return -EINVAL; -	} -	gpio_set_value(DSS_ENABLE_GPIO, 1); -	gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 1); -	lcd_enabled = 1; -	return 0; -} - -static void omap3_stalker_disable_lcd(struct omap_dss_device *dssdev) -{ -	gpio_set_value(DSS_ENABLE_GPIO, 0); -	gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 0); -	lcd_enabled = 0; -} - -static struct panel_generic_dpi_data lcd_panel = { -	.name			= "generic", -	.platform_enable	= omap3_stalker_enable_lcd, -	.platform_disable	= omap3_stalker_disable_lcd, -}; - -static struct omap_dss_device omap3_stalker_lcd_device = { -	.name			= "lcd", -	.driver_name		= "generic_dpi_panel", -	.data			= &lcd_panel, -	.phy.dpi.data_lines	= 24, -	.type			= OMAP_DISPLAY_TYPE_DPI, -}; -  static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev)  {  	return 0; @@ -179,8 +147,7 @@ static void omap3_stalker_disable_dvi(struct omap_dss_device *dssdev)  	dvi_enabled = 0;  } -static struct panel_generic_dpi_data dvi_panel = { -	.name			= "generic", +static struct panel_dvi_platform_data dvi_panel = {  	.platform_enable	= omap3_stalker_enable_dvi,  	.platform_disable	= omap3_stalker_disable_dvi,  }; @@ -188,13 +155,12 @@ static struct panel_generic_dpi_data dvi_panel = {  static struct omap_dss_device omap3_stalker_dvi_device = {  	.name			= "dvi",  	.type			= OMAP_DISPLAY_TYPE_DPI, -	.driver_name		= "generic_dpi_panel", +	.driver_name		= "dvi",  	.data			= &dvi_panel,  	.phy.dpi.data_lines	= 24,  };  static struct omap_dss_device *omap3_stalker_dss_devices[] = { -	&omap3_stalker_lcd_device,  	&omap3_stalker_tv_device,  	&omap3_stalker_dvi_device,  }; diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index c2d5348f542..a2d0d1971e2 100644 --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -104,15 +104,6 @@ static struct omap2_hsmmc_info mmc[] = {  	{}	/* Terminator */  }; -static struct platform_device omap3_touchbook_lcd_device = { -	.name		= "omap3touchbook_lcd", -	.id		= -1, -}; - -static struct omap_lcd_config omap3_touchbook_lcd_config __initdata = { -	.ctrl_name	= "internal", -}; -  static struct regulator_consumer_supply touchbook_vmmc1_supply[] = {  	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),  }; @@ -165,14 +156,12 @@ static struct twl4030_gpio_platform_data touchbook_gpio_data = {  static struct regulator_consumer_supply touchbook_vdac_supply[] = {  {  	.supply		= "vdac", -	.dev		= &omap3_touchbook_lcd_device.dev,  },  };  static struct regulator_consumer_supply touchbook_vdvi_supply[] = {  {  	.supply		= "vdvi", -	.dev		= &omap3_touchbook_lcd_device.dev,  },  }; @@ -316,10 +305,6 @@ static struct platform_device keys_gpio = {  	},  }; -static struct omap_board_config_kernel omap3_touchbook_config[] __initdata = { -	{ OMAP_TAG_LCD,		&omap3_touchbook_lcd_config }, -}; -  #ifdef CONFIG_OMAP_MUX  static struct omap_board_mux board_mux[] __initdata = {  	{ .reg_offset = OMAP_MUX_TERMINATOR }, @@ -327,7 +312,6 @@ static struct omap_board_mux board_mux[] __initdata = {  #endif  static struct platform_device *omap3_touchbook_devices[] __initdata = { -	&omap3_touchbook_lcd_device,  	&leds_gpio,  	&keys_gpio,  }; @@ -364,8 +348,6 @@ early_param("tbr", early_touchbook_revision);  static void __init omap3_touchbook_init(void)  {  	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); -	omap_board_config = omap3_touchbook_config; -	omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config);  	pm_power_off = omap3_touchbook_poweroff; diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 2141894eb9f..a8c2c4263e3 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -40,7 +40,7 @@  #include <plat/common.h>  #include <plat/usb.h>  #include <plat/mmc.h> -#include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include "hsmmc.h"  #include "control.h" @@ -449,16 +449,16 @@ static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev)  }  /* Using generic display panel */ -static struct panel_generic_dpi_data omap4_dvi_panel = { -	.name			= "generic", +static struct panel_dvi_platform_data omap4_dvi_panel = {  	.platform_enable	= omap4_panda_enable_dvi,  	.platform_disable	= omap4_panda_disable_dvi, +	.i2c_bus_num = 3,  };  struct omap_dss_device omap4_panda_dvi_device = {  	.type			= OMAP_DISPLAY_TYPE_DPI,  	.name			= "dvi", -	.driver_name		= "generic_dpi_panel", +	.driver_name		= "dvi",  	.data			= &omap4_dvi_panel,  	.phy.dpi.data_lines	= 24,  	.reset_gpio		= PANDA_DVI_TFP410_POWER_DOWN_GPIO, diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 9f13dc22df7..4cf7aeabab8 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -46,6 +46,7 @@  #include <plat/common.h>  #include <video/omapdss.h>  #include <video/omap-panel-generic-dpi.h> +#include <video/omap-panel-dvi.h>  #include <plat/gpmc.h>  #include <mach/hardware.h>  #include <plat/nand.h> @@ -182,16 +183,16 @@ static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)  	dvi_enabled = 0;  } -static struct panel_generic_dpi_data dvi_panel = { -	.name			= "generic", +static struct panel_dvi_platform_data dvi_panel = {  	.platform_enable	= overo_panel_enable_dvi,  	.platform_disable	= overo_panel_disable_dvi, +	.i2c_bus_num		= 3,  };  static struct omap_dss_device overo_dvi_device = {  	.name			= "dvi",  	.type			= OMAP_DISPLAY_TYPE_DPI, -	.driver_name		= "generic_dpi_panel", +	.driver_name		= "dvi",  	.data			= &dvi_panel,  	.phy.dpi.data_lines	= 24,  }; diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c index 74c8aadc0a1..4af7c4b2881 100644 --- a/arch/arm/mach-omap2/board-rx51.c +++ b/arch/arm/mach-omap2/board-rx51.c @@ -79,29 +79,6 @@ static struct cpuidle_params rx51_cpuidle_params[] = {  	{7505 + 15274, 484329, 1},  }; -static struct omap_lcd_config rx51_lcd_config = { -	.ctrl_name	= "internal", -}; - -static struct omap_fbmem_config rx51_fbmem0_config = { -	.size = 752 * 1024, -}; - -static struct omap_fbmem_config rx51_fbmem1_config = { -	.size = 752 * 1024, -}; - -static struct omap_fbmem_config rx51_fbmem2_config = { -	.size = 752 * 1024, -}; - -static struct omap_board_config_kernel rx51_config[] = { -	{ OMAP_TAG_FBMEM,	&rx51_fbmem0_config }, -	{ OMAP_TAG_FBMEM,	&rx51_fbmem1_config }, -	{ OMAP_TAG_FBMEM,	&rx51_fbmem2_config }, -	{ OMAP_TAG_LCD,		&rx51_lcd_config }, -}; -  extern void __init rx51_peripherals_init(void);  #ifdef CONFIG_OMAP_MUX @@ -121,8 +98,6 @@ static void __init rx51_init(void)  	struct omap_sdrc_params *sdrc_params;  	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); -	omap_board_config = rx51_config; -	omap_board_config_size = ARRAY_SIZE(rx51_config);  	omap3_pm_init_cpuidle(rx51_cpuidle_params);  	omap_serial_init(); diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 18693f6de04..836f0f7d8c0 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -27,6 +27,8 @@  #include <plat/omap_device.h>  #include <plat/omap-pm.h> +#include "control.h" +  static struct platform_device omap_display_device = {  	.name          = "omapdss",  	.id            = -1, @@ -61,7 +63,7 @@ static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = {  	{ "dss_dispc", "omapdss_dispc", -1 },  	{ "dss_rfbi", "omapdss_rfbi", -1 },  	{ "dss_venc", "omapdss_venc", -1 }, -	{ "dss_dsi1", "omapdss_dsi1", -1 }, +	{ "dss_dsi1", "omapdss_dsi", 0 },  };  static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = { @@ -69,11 +71,58 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {  	{ "dss_dispc", "omapdss_dispc", -1 },  	{ "dss_rfbi", "omapdss_rfbi", -1 },  	{ "dss_venc", "omapdss_venc", -1 }, -	{ "dss_dsi1", "omapdss_dsi1", -1 }, -	{ "dss_dsi2", "omapdss_dsi2", -1 }, +	{ "dss_dsi1", "omapdss_dsi", 0 }, +	{ "dss_dsi2", "omapdss_dsi", 1 },  	{ "dss_hdmi", "omapdss_hdmi", -1 },  }; +static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes) +{ +	u32 enable_mask, enable_shift; +	u32 pipd_mask, pipd_shift; +	u32 reg; + +	if (dsi_id == 0) { +		enable_mask = OMAP4_DSI1_LANEENABLE_MASK; +		enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT; +		pipd_mask = OMAP4_DSI1_PIPD_MASK; +		pipd_shift = OMAP4_DSI1_PIPD_SHIFT; +	} else if (dsi_id == 1) { +		enable_mask = OMAP4_DSI2_LANEENABLE_MASK; +		enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT; +		pipd_mask = OMAP4_DSI2_PIPD_MASK; +		pipd_shift = OMAP4_DSI2_PIPD_SHIFT; +	} else { +		return -ENODEV; +	} + +	reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY); + +	reg &= ~enable_mask; +	reg &= ~pipd_mask; + +	reg |= (lanes << enable_shift) & enable_mask; +	reg |= (lanes << pipd_shift) & pipd_mask; + +	omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY); + +	return 0; +} + +static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask) +{ +	if (cpu_is_omap44xx()) +		return omap4_dsi_mux_pads(dsi_id, lane_mask); + +	return 0; +} + +static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask) +{ +	if (cpu_is_omap44xx()) +		omap4_dsi_mux_pads(dsi_id, 0); +} +  int __init omap_display_init(struct omap_dss_board_info *board_data)  {  	int r = 0; @@ -96,6 +145,11 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)  		oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);  	} +	if (board_data->dsi_enable_pads == NULL) +		board_data->dsi_enable_pads = omap_dsi_enable_pads; +	if (board_data->dsi_disable_pads == NULL) +		board_data->dsi_disable_pads = omap_dsi_disable_pads; +  	pdata.board_data = board_data;  	pdata.board_data->get_context_loss_count =  		omap_pm_get_dev_context_loss_count; diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index daa056ed873..52243577216 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -99,7 +99,7 @@ static struct regulator_init_data omap3_vdac_idata = {  static struct regulator_consumer_supply omap3_vpll2_supplies[] = {  	REGULATOR_SUPPLY("vdds_dsi", "omapdss"), -	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),  };  static struct regulator_init_data omap3_vpll2_idata = { @@ -235,6 +235,12 @@ static struct regulator_init_data omap4_vana_idata = {  	},  }; +static struct regulator_consumer_supply omap4_vcxio_supply[] = { +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"), +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.1"), +}; +  static struct regulator_init_data omap4_vcxio_idata = {  	.constraints = {  		.min_uV			= 1800000, @@ -243,7 +249,10 @@ static struct regulator_init_data omap4_vcxio_idata = {  					| REGULATOR_MODE_STANDBY,  		.valid_ops_mask		= REGULATOR_CHANGE_MODE  					| REGULATOR_CHANGE_STATUS, +		.always_on		= true,  	}, +	.num_consumer_supplies	= ARRAY_SIZE(omap4_vcxio_supply), +	.consumer_supplies	= omap4_vcxio_supply,  };  static struct regulator_init_data omap4_vusb_idata = { diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index b3a5ecdb33a..30d8896bb71 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -400,7 +400,6 @@ static int omapvid_setup_overlay(struct omap_vout_device *vout,  	ovl->get_overlay_info(ovl, &info);  	info.paddr = addr; -	info.vaddr = NULL;  	info.width = cropwidth;  	info.height = cropheight;  	info.color_mode = vout->dss_mode; @@ -1165,12 +1164,17 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,  {  	int ret = 0;  	struct omap_vout_device *vout = fh; +	struct omap_overlay *ovl; +	struct omapvideo_info *ovid;  	struct v4l2_window *win = &f->fmt.win; +	ovid = &vout->vid_info; +	ovl = ovid->overlays[0]; +  	ret = omap_vout_try_window(&vout->fbuf, win);  	if (!ret) { -		if (vout->vid == OMAP_VIDEO1) +		if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)  			win->global_alpha = 255;  		else  			win->global_alpha = f->fmt.win.global_alpha; @@ -1194,8 +1198,8 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,  	ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);  	if (!ret) { -		/* Video1 plane does not support global alpha */ -		if (ovl->id == OMAP_DSS_VIDEO1) +		/* Video1 plane does not support global alpha on OMAP3 */ +		if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)  			vout->win.global_alpha = 255;  		else  			vout->win.global_alpha = f->fmt.win.global_alpha; @@ -1788,7 +1792,9 @@ static int vidioc_s_fbuf(struct file *file, void *fh,  	if (ovl->manager && ovl->manager->get_manager_info &&  			ovl->manager->set_manager_info) {  		ovl->manager->get_manager_info(ovl->manager, &info); -		info.alpha_enabled = enable; +		/* enable this only if there is no zorder cap */ +		if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) +			info.partial_alpha_enabled = enable;  		if (ovl->manager->set_manager_info(ovl->manager, &info))  			return -EINVAL;  	} @@ -1820,7 +1826,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh,  	}  	if (ovl->manager && ovl->manager->get_manager_info) {  		ovl->manager->get_manager_info(ovl->manager, &info); -		if (info.alpha_enabled) +		if (info.partial_alpha_enabled)  			a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;  	} diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 196fa2e7f43..84ff23208c2 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -9,35 +9,6 @@ config FB_OMAP  	help            Frame buffer driver for OMAP based boards. -config FB_OMAP_LCD_VGA -        bool "Use LCD in VGA mode" -	        depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP -		help -		  Set LCD resolution as VGA (640 X 480). -		  Default resolution without this option is QVGA(320 X 240). -		  Please take a look at drivers/video/omap/lcd_ldp.c file -		  for lcd driver code. -choice -	depends on FB_OMAP && MACH_OVERO -	prompt "Screen resolution" -	default FB_OMAP_079M3R -	help -	  Selected desired screen resolution - -config FB_OMAP_031M3R -	boolean "640 x 480 @ 60 Hz Reduced blanking" - -config FB_OMAP_048M3R -	boolean "800 x 600 @ 60 Hz Reduced blanking" - -config FB_OMAP_079M3R -	boolean "1024 x 768 @ 60 Hz Reduced blanking" - -config FB_OMAP_092M9R -	boolean "1280 x 720 @ 60 Hz Reduced blanking" - -endchoice -  config FB_OMAP_LCDC_EXTERNAL  	bool "External LCD controller support"  	depends on FB_OMAP diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index 25db55696e1..ef78550917f 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile @@ -17,7 +17,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o  objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o  objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o -objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o  objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o  objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o  objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o @@ -26,14 +25,7 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o  objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o  objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o -objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o -objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o -objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o -objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o -objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o -objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o  objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o -objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o  objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o  omapfb-objs := $(objs-yy) diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c deleted file mode 100644 index e3eccc9af78..00000000000 --- a/drivers/video/omap/lcd_2430sdp.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * LCD panel support for the TI 2430SDP board - * - * Copyright (C) 2007 MontaVista - * Author: Hunyue Yau <hyau@mvista.com> - * - * Derived from drivers/video/omap/lcd-apollon.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/gpio.h> -#include <linux/i2c/twl.h> - -#include <plat/mux.h> -#include <asm/mach-types.h> - -#include "omapfb.h" - -#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO	91 -#define SDP2430_LCD_PANEL_ENABLE_GPIO		154 -#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO	24 -#define SDP3430_LCD_PANEL_ENABLE_GPIO		28 - -static unsigned backlight_gpio; -static unsigned enable_gpio; - -#define LCD_PIXCLOCK_MAX		5400 /* freq 5.4 MHz */ -#define PM_RECEIVER             TWL4030_MODULE_PM_RECEIVER -#define ENABLE_VAUX2_DEDICATED  0x09 -#define ENABLE_VAUX2_DEV_GRP    0x20 -#define ENABLE_VAUX3_DEDICATED	0x03 -#define ENABLE_VAUX3_DEV_GRP	0x20 - -#define ENABLE_VPLL2_DEDICATED          0x05 -#define ENABLE_VPLL2_DEV_GRP            0xE0 -#define TWL4030_VPLL2_DEV_GRP           0x33 -#define TWL4030_VPLL2_DEDICATED         0x36 - -#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v) - - -static int sdp2430_panel_init(struct lcd_panel *panel, -				struct omapfb_device *fbdev) -{ -	if (machine_is_omap_3430sdp()) { -		enable_gpio    = SDP3430_LCD_PANEL_ENABLE_GPIO; -		backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; -	} else { -		enable_gpio    = SDP2430_LCD_PANEL_ENABLE_GPIO; -		backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO; -	} - -	gpio_request(enable_gpio, "LCD enable");	/* LCD panel */ -	gpio_request(backlight_gpio, "LCD bl");		/* LCD backlight */ -	gpio_direction_output(enable_gpio, 0); -	gpio_direction_output(backlight_gpio, 0); - -	return 0; -} - -static void sdp2430_panel_cleanup(struct lcd_panel *panel) -{ -	gpio_free(backlight_gpio); -	gpio_free(enable_gpio); -} - -static int sdp2430_panel_enable(struct lcd_panel *panel) -{ -	u8 ded_val, ded_reg; -	u8 grp_val, grp_reg; - -	if (machine_is_omap_3430sdp()) { -		ded_reg = TWL4030_VAUX3_DEDICATED; -		ded_val = ENABLE_VAUX3_DEDICATED; -		grp_reg = TWL4030_VAUX3_DEV_GRP; -		grp_val = ENABLE_VAUX3_DEV_GRP; - -		if (omap_rev() > OMAP3430_REV_ES1_0) { -			t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED, -					TWL4030_VPLL2_DEDICATED); -			t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP, -					TWL4030_VPLL2_DEV_GRP); -		} -	} else { -		ded_reg = TWL4030_VAUX2_DEDICATED; -		ded_val = ENABLE_VAUX2_DEDICATED; -		grp_reg = TWL4030_VAUX2_DEV_GRP; -		grp_val = ENABLE_VAUX2_DEV_GRP; -	} - -	gpio_set_value(enable_gpio, 1); -	gpio_set_value(backlight_gpio, 1); - -	if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg)) -		return -EIO; -	if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg)) -		return -EIO; - -	return 0; -} - -static void sdp2430_panel_disable(struct lcd_panel *panel) -{ -	gpio_set_value(enable_gpio, 0); -	gpio_set_value(backlight_gpio, 0); -	if (omap_rev() > OMAP3430_REV_ES1_0) { -		t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED); -		t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP); -		msleep(4); -	} -} - -static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel) -{ -	return 0; -} - -struct lcd_panel sdp2430_panel = { -	.name		= "sdp2430", -	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | -			  OMAP_LCDC_INV_HSYNC, - -	.bpp		= 16, -	.data_lines	= 16, -	.x_res		= 240, -	.y_res		= 320, -	.hsw		= 3,		/* hsync_len (4) - 1 */ -	.hfp		= 3,		/* right_margin (4) - 1 */ -	.hbp		= 39,		/* left_margin (40) - 1 */ -	.vsw		= 1,		/* vsync_len (2) - 1 */ -	.vfp		= 2,		/* lower_margin */ -	.vbp		= 7,		/* upper_margin (8) - 1 */ - -	.pixel_clock	= LCD_PIXCLOCK_MAX, - -	.init		= sdp2430_panel_init, -	.cleanup	= sdp2430_panel_cleanup, -	.enable		= sdp2430_panel_enable, -	.disable	= sdp2430_panel_disable, -	.get_caps	= sdp2430_panel_get_caps, -}; - -static int sdp2430_panel_probe(struct platform_device *pdev) -{ -	omapfb_register_panel(&sdp2430_panel); -	return 0; -} - -static int sdp2430_panel_remove(struct platform_device *pdev) -{ -	return 0; -} - -static int sdp2430_panel_suspend(struct platform_device *pdev, -					pm_message_t mesg) -{ -	return 0; -} - -static int sdp2430_panel_resume(struct platform_device *pdev) -{ -	return 0; -} - -struct platform_driver sdp2430_panel_driver = { -	.probe		= sdp2430_panel_probe, -	.remove		= sdp2430_panel_remove, -	.suspend	= sdp2430_panel_suspend, -	.resume		= sdp2430_panel_resume, -	.driver		= { -		.name	= "sdp2430_lcd", -		.owner	= THIS_MODULE, -	}, -}; - -static int __init sdp2430_panel_drv_init(void) -{ -	return platform_driver_register(&sdp2430_panel_driver); -} - -static void __exit sdp2430_panel_drv_exit(void) -{ -	platform_driver_unregister(&sdp2430_panel_driver); -} - -module_init(sdp2430_panel_drv_init); -module_exit(sdp2430_panel_drv_exit); diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c deleted file mode 100644 index 10459d8bd9a..00000000000 --- a/drivers/video/omap/lcd_apollon.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * LCD panel support for the Samsung OMAP2 Apollon board - * - * Copyright (C) 2005,2006 Samsung Electronics - * Author: Kyungmin Park <kyungmin.park@samsung.com> - * - * Derived from drivers/video/omap/lcd-h4.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> - -#include <mach/gpio.h> - -#include "omapfb.h" - -/* #define USE_35INCH_LCD 1 */ - -static int apollon_panel_init(struct lcd_panel *panel, -				struct omapfb_device *fbdev) -{ -	return 0; -} - -static void apollon_panel_cleanup(struct lcd_panel *panel) -{ -} - -static int apollon_panel_enable(struct lcd_panel *panel) -{ -	return 0; -} - -static void apollon_panel_disable(struct lcd_panel *panel) -{ -} - -static unsigned long apollon_panel_get_caps(struct lcd_panel *panel) -{ -	return 0; -} - -struct lcd_panel apollon_panel = { -	.name		= "apollon", -	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | -			  OMAP_LCDC_INV_HSYNC, - -	.bpp		= 16, -	.data_lines	= 18, -#ifdef USE_35INCH_LCD -	.x_res		= 240, -	.y_res		= 320, -	.hsw		= 2, -	.hfp		= 3, -	.hbp		= 9, -	.vsw		= 4, -	.vfp		= 3, -	.vbp		= 5, -#else -	.x_res		= 480, -	.y_res		= 272, -	.hsw		= 41, -	.hfp		= 2, -	.hbp		= 2, -	.vsw		= 10, -	.vfp		= 2, -	.vbp		= 2, -#endif -	.pixel_clock	= 6250, - -	.init		= apollon_panel_init, -	.cleanup	= apollon_panel_cleanup, -	.enable		= apollon_panel_enable, -	.disable	= apollon_panel_disable, -	.get_caps	= apollon_panel_get_caps, -}; - -static int apollon_panel_probe(struct platform_device *pdev) -{ -	omapfb_register_panel(&apollon_panel); -	return 0; -} - -static int apollon_panel_remove(struct platform_device *pdev) -{ -	return 0; -} - -static int apollon_panel_suspend(struct platform_device *pdev, -				  pm_message_t mesg) -{ -	return 0; -} - -static int apollon_panel_resume(struct platform_device *pdev) -{ -	return 0; -} - -struct platform_driver apollon_panel_driver = { -	.probe		= apollon_panel_probe, -	.remove		= apollon_panel_remove, -	.suspend	= apollon_panel_suspend, -	.resume		= apollon_panel_resume, -	.driver		= { -		.name	= "apollon_lcd", -		.owner	= THIS_MODULE, -	}, -}; - -static int __init apollon_panel_drv_init(void) -{ -	return platform_driver_register(&apollon_panel_driver); -} - -static void __exit apollon_panel_drv_exit(void) -{ -	platform_driver_unregister(&apollon_panel_driver); -} - -module_init(apollon_panel_drv_init); -module_exit(apollon_panel_drv_exit); diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c deleted file mode 100644 index 03a06a98275..00000000000 --- a/drivers/video/omap/lcd_h4.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * LCD panel support for the TI OMAP H4 board - * - * Copyright (C) 2004 Nokia Corporation - * Author: Imre Deak <imre.deak@nokia.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> - -#include "omapfb.h" - -static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) -{ -	return 0; -} - -static void h4_panel_cleanup(struct lcd_panel *panel) -{ -} - -static int h4_panel_enable(struct lcd_panel *panel) -{ -	return 0; -} - -static void h4_panel_disable(struct lcd_panel *panel) -{ -} - -static unsigned long h4_panel_get_caps(struct lcd_panel *panel) -{ -	return 0; -} - -static struct lcd_panel h4_panel = { -	.name		= "h4", -	.config		= OMAP_LCDC_PANEL_TFT, - -	.bpp		= 16, -	.data_lines	= 16, -	.x_res		= 240, -	.y_res		= 320, -	.pixel_clock	= 6250, -	.hsw		= 15, -	.hfp		= 15, -	.hbp		= 60, -	.vsw		= 1, -	.vfp		= 1, -	.vbp		= 1, - -	.init		= h4_panel_init, -	.cleanup	= h4_panel_cleanup, -	.enable		= h4_panel_enable, -	.disable	= h4_panel_disable, -	.get_caps	= h4_panel_get_caps, -}; - -static int h4_panel_probe(struct platform_device *pdev) -{ -	omapfb_register_panel(&h4_panel); -	return 0; -} - -static int h4_panel_remove(struct platform_device *pdev) -{ -	return 0; -} - -static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg) -{ -	return 0; -} - -static int h4_panel_resume(struct platform_device *pdev) -{ -	return 0; -} - -static struct platform_driver h4_panel_driver = { -	.probe		= h4_panel_probe, -	.remove		= h4_panel_remove, -	.suspend	= h4_panel_suspend, -	.resume		= h4_panel_resume, -	.driver		= { -		.name	= "lcd_h4", -		.owner	= THIS_MODULE, -	}, -}; - -static int __init h4_panel_drv_init(void) -{ -	return platform_driver_register(&h4_panel_driver); -} - -static void __exit h4_panel_drv_cleanup(void) -{ -	platform_driver_unregister(&h4_panel_driver); -} - -module_init(h4_panel_drv_init); -module_exit(h4_panel_drv_cleanup); - diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c deleted file mode 100644 index 0f5952cae85..00000000000 --- a/drivers/video/omap/lcd_ldp.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * LCD panel support for the TI LDP board - * - * Copyright (C) 2007 WindRiver - * Author: Stanley Miao <stanley.miao@windriver.com> - * - * Derived from drivers/video/omap/lcd-2430sdp.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/i2c/twl.h> - -#include <mach/gpio.h> -#include <plat/mux.h> -#include <asm/mach-types.h> - -#include "omapfb.h" - -#define LCD_PANEL_BACKLIGHT_GPIO	(15 + OMAP_MAX_GPIO_LINES) -#define LCD_PANEL_ENABLE_GPIO		(7 + OMAP_MAX_GPIO_LINES) - -#define LCD_PANEL_RESET_GPIO		55 -#define LCD_PANEL_QVGA_GPIO		56 - -#ifdef CONFIG_FB_OMAP_LCD_VGA -#define LCD_XRES		480 -#define LCD_YRES		640 -#define LCD_PIXCLOCK_MAX	41700 -#else -#define LCD_XRES		240 -#define LCD_YRES		320 -#define LCD_PIXCLOCK_MAX	185186 -#endif - -#define PM_RECEIVER             TWL4030_MODULE_PM_RECEIVER -#define ENABLE_VAUX2_DEDICATED  0x09 -#define ENABLE_VAUX2_DEV_GRP    0x20 -#define ENABLE_VAUX3_DEDICATED	0x03 -#define ENABLE_VAUX3_DEV_GRP	0x20 - -#define ENABLE_VPLL2_DEDICATED          0x05 -#define ENABLE_VPLL2_DEV_GRP            0xE0 -#define TWL4030_VPLL2_DEV_GRP           0x33 -#define TWL4030_VPLL2_DEDICATED         0x36 - -#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v) - - -static int ldp_panel_init(struct lcd_panel *panel, -				struct omapfb_device *fbdev) -{ -	gpio_request(LCD_PANEL_RESET_GPIO, "lcd reset"); -	gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga"); -	gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd panel"); -	gpio_request(LCD_PANEL_BACKLIGHT_GPIO, "lcd backlight"); - -	gpio_direction_output(LCD_PANEL_QVGA_GPIO, 0); -	gpio_direction_output(LCD_PANEL_RESET_GPIO, 0); -	gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); -	gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0); - -#ifdef CONFIG_FB_OMAP_LCD_VGA -	gpio_set_value(LCD_PANEL_QVGA_GPIO, 0); -#else -	gpio_set_value(LCD_PANEL_QVGA_GPIO, 1); -#endif -	gpio_set_value(LCD_PANEL_RESET_GPIO, 1); - -	return 0; -} - -static void ldp_panel_cleanup(struct lcd_panel *panel) -{ -	gpio_free(LCD_PANEL_BACKLIGHT_GPIO); -	gpio_free(LCD_PANEL_ENABLE_GPIO); -	gpio_free(LCD_PANEL_QVGA_GPIO); -	gpio_free(LCD_PANEL_RESET_GPIO); -} - -static int ldp_panel_enable(struct lcd_panel *panel) -{ -	if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED, -			TWL4030_VPLL2_DEDICATED)) -		return -EIO; -	if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP, -			TWL4030_VPLL2_DEV_GRP)) -		return -EIO; - -	gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1); -	gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 1); - -	if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEDICATED, -				TWL4030_VAUX3_DEDICATED)) -		return -EIO; -	if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEV_GRP, -				TWL4030_VAUX3_DEV_GRP)) -		return -EIO; - -	return 0; -} - -static void ldp_panel_disable(struct lcd_panel *panel) -{ -	gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); -	gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0); - -	t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED); -	t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP); -	msleep(4); -} - -static unsigned long ldp_panel_get_caps(struct lcd_panel *panel) -{ -	return 0; -} - -struct lcd_panel ldp_panel = { -	.name		= "ldp", -	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | -			  OMAP_LCDC_INV_HSYNC, - -	.bpp		= 16, -	.data_lines	= 18, -	.x_res		= LCD_XRES, -	.y_res		= LCD_YRES, -	.hsw		= 3,		/* hsync_len (4) - 1 */ -	.hfp		= 3,		/* right_margin (4) - 1 */ -	.hbp		= 39,		/* left_margin (40) - 1 */ -	.vsw		= 1,		/* vsync_len (2) - 1 */ -	.vfp		= 2,		/* lower_margin */ -	.vbp		= 7,		/* upper_margin (8) - 1 */ - -	.pixel_clock	= LCD_PIXCLOCK_MAX, - -	.init		= ldp_panel_init, -	.cleanup	= ldp_panel_cleanup, -	.enable		= ldp_panel_enable, -	.disable	= ldp_panel_disable, -	.get_caps	= ldp_panel_get_caps, -}; - -static int ldp_panel_probe(struct platform_device *pdev) -{ -	omapfb_register_panel(&ldp_panel); -	return 0; -} - -static int ldp_panel_remove(struct platform_device *pdev) -{ -	return 0; -} - -static int ldp_panel_suspend(struct platform_device *pdev, pm_message_t mesg) -{ -	return 0; -} - -static int ldp_panel_resume(struct platform_device *pdev) -{ -	return 0; -} - -struct platform_driver ldp_panel_driver = { -	.probe		= ldp_panel_probe, -	.remove		= ldp_panel_remove, -	.suspend	= ldp_panel_suspend, -	.resume		= ldp_panel_resume, -	.driver		= { -		.name	= "ldp_lcd", -		.owner	= THIS_MODULE, -	}, -}; - -static int __init ldp_panel_drv_init(void) -{ -	return platform_driver_register(&ldp_panel_driver); -} - -static void __exit ldp_panel_drv_exit(void) -{ -	platform_driver_unregister(&ldp_panel_driver); -} - -module_init(ldp_panel_drv_init); -module_exit(ldp_panel_drv_exit); diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c deleted file mode 100644 index d7c6c3e0afc..00000000000 --- a/drivers/video/omap/lcd_omap3beagle.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * LCD panel support for the TI OMAP3 Beagle board - * - * Author: Koen Kooi <koen@openembedded.org> - * - * Derived from drivers/video/omap/lcd-omap3evm.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/i2c/twl.h> - -#include <asm/mach-types.h> - -#include "omapfb.h" - -#define LCD_PANEL_ENABLE_GPIO       170 - -static int omap3beagle_panel_init(struct lcd_panel *panel, -				struct omapfb_device *fbdev) -{ -	gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable"); -	return 0; -} - -static void omap3beagle_panel_cleanup(struct lcd_panel *panel) -{ -	gpio_free(LCD_PANEL_ENABLE_GPIO); -} - -static int omap3beagle_panel_enable(struct lcd_panel *panel) -{ -	gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); -	return 0; -} - -static void omap3beagle_panel_disable(struct lcd_panel *panel) -{ -	gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); -} - -static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel) -{ -	return 0; -} - -struct lcd_panel omap3beagle_panel = { -	.name		= "omap3beagle", -	.config		= OMAP_LCDC_PANEL_TFT, - -	.bpp		= 16, -	.data_lines	= 24, -	.x_res		= 1024, -	.y_res		= 768, -	.hsw		= 3,		/* hsync_len (4) - 1 */ -	.hfp		= 3,		/* right_margin (4) - 1 */ -	.hbp		= 39,		/* left_margin (40) - 1 */ -	.vsw		= 1,		/* vsync_len (2) - 1 */ -	.vfp		= 2,		/* lower_margin */ -	.vbp		= 7,		/* upper_margin (8) - 1 */ - -	.pixel_clock	= 64000, - -	.init		= omap3beagle_panel_init, -	.cleanup	= omap3beagle_panel_cleanup, -	.enable		= omap3beagle_panel_enable, -	.disable	= omap3beagle_panel_disable, -	.get_caps	= omap3beagle_panel_get_caps, -}; - -static int omap3beagle_panel_probe(struct platform_device *pdev) -{ -	omapfb_register_panel(&omap3beagle_panel); -	return 0; -} - -static int omap3beagle_panel_remove(struct platform_device *pdev) -{ -	return 0; -} - -static int omap3beagle_panel_suspend(struct platform_device *pdev, -				   pm_message_t mesg) -{ -	return 0; -} - -static int omap3beagle_panel_resume(struct platform_device *pdev) -{ -	return 0; -} - -struct platform_driver omap3beagle_panel_driver = { -	.probe		= omap3beagle_panel_probe, -	.remove		= omap3beagle_panel_remove, -	.suspend	= omap3beagle_panel_suspend, -	.resume		= omap3beagle_panel_resume, -	.driver		= { -		.name	= "omap3beagle_lcd", -		.owner	= THIS_MODULE, -	}, -}; - -static int __init omap3beagle_panel_drv_init(void) -{ -	return platform_driver_register(&omap3beagle_panel_driver); -} - -static void __exit omap3beagle_panel_drv_exit(void) -{ -	platform_driver_unregister(&omap3beagle_panel_driver); -} - -module_init(omap3beagle_panel_drv_init); -module_exit(omap3beagle_panel_drv_exit); diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c deleted file mode 100644 index 06840da0b09..00000000000 --- a/drivers/video/omap/lcd_omap3evm.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * LCD panel support for the TI OMAP3 EVM board - * - * Author: Steve Sakoman <steve@sakoman.com> - * - * Derived from drivers/video/omap/lcd-apollon.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/i2c/twl.h> - -#include <plat/mux.h> -#include <asm/mach-types.h> - -#include "omapfb.h" - -#define LCD_PANEL_ENABLE_GPIO       153 -#define LCD_PANEL_LR                2 -#define LCD_PANEL_UD                3 -#define LCD_PANEL_INI               152 -#define LCD_PANEL_QVGA              154 -#define LCD_PANEL_RESB              155 - -#define ENABLE_VDAC_DEDICATED	0x03 -#define ENABLE_VDAC_DEV_GRP	0x20 -#define ENABLE_VPLL2_DEDICATED	0x05 -#define ENABLE_VPLL2_DEV_GRP	0xE0 - -#define TWL_LED_LEDEN		0x00 -#define TWL_PWMA_PWMAON		0x00 -#define TWL_PWMA_PWMAOFF	0x01 - -static unsigned int bklight_level; - -static int omap3evm_panel_init(struct lcd_panel *panel, -				struct omapfb_device *fbdev) -{ -	gpio_request(LCD_PANEL_LR, "LCD lr"); -	gpio_request(LCD_PANEL_UD, "LCD ud"); -	gpio_request(LCD_PANEL_INI, "LCD ini"); -	gpio_request(LCD_PANEL_RESB, "LCD resb"); -	gpio_request(LCD_PANEL_QVGA, "LCD qvga"); - -	gpio_direction_output(LCD_PANEL_RESB, 1); -	gpio_direction_output(LCD_PANEL_INI, 1); -	gpio_direction_output(LCD_PANEL_QVGA, 0); -	gpio_direction_output(LCD_PANEL_LR, 1); -	gpio_direction_output(LCD_PANEL_UD, 1); - -	twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN); -	twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON); -	twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF); -	bklight_level = 100; - -	return 0; -} - -static void omap3evm_panel_cleanup(struct lcd_panel *panel) -{ -	gpio_free(LCD_PANEL_QVGA); -	gpio_free(LCD_PANEL_RESB); -	gpio_free(LCD_PANEL_INI); -	gpio_free(LCD_PANEL_UD); -	gpio_free(LCD_PANEL_LR); -} - -static int omap3evm_panel_enable(struct lcd_panel *panel) -{ -	gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); -	return 0; -} - -static void omap3evm_panel_disable(struct lcd_panel *panel) -{ -	gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); -} - -static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel) -{ -	return 0; -} - -static int omap3evm_bklight_setlevel(struct lcd_panel *panel, -						unsigned int level) -{ -	u8 c; -	if ((level >= 0) && (level <= 100)) { -		c = (125 * (100 - level)) / 100 + 2; -		twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF); -		bklight_level = level; -	} -	return 0; -} - -static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel) -{ -	return bklight_level; -} - -static unsigned int omap3evm_bklight_getmaxlevel(struct lcd_panel *panel) -{ -	return 100; -} - -struct lcd_panel omap3evm_panel = { -	.name		= "omap3evm", -	.config		= OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | -			  OMAP_LCDC_INV_HSYNC, - -	.bpp		= 16, -	.data_lines	= 18, -	.x_res		= 480, -	.y_res		= 640, -	.hsw		= 3,		/* hsync_len (4) - 1 */ -	.hfp		= 3,		/* right_margin (4) - 1 */ -	.hbp		= 39,		/* left_margin (40) - 1 */ -	.vsw		= 1,		/* vsync_len (2) - 1 */ -	.vfp		= 2,		/* lower_margin */ -	.vbp		= 7,		/* upper_margin (8) - 1 */ - -	.pixel_clock	= 26000, - -	.init		= omap3evm_panel_init, -	.cleanup	= omap3evm_panel_cleanup, -	.enable		= omap3evm_panel_enable, -	.disable	= omap3evm_panel_disable, -	.get_caps	= omap3evm_panel_get_caps, -	.set_bklight_level      = omap3evm_bklight_setlevel, -	.get_bklight_level      = omap3evm_bklight_getlevel, -	.get_bklight_max        = omap3evm_bklight_getmaxlevel, -}; - -static int omap3evm_panel_probe(struct platform_device *pdev) -{ -	omapfb_register_panel(&omap3evm_panel); -	return 0; -} - -static int omap3evm_panel_remove(struct platform_device *pdev) -{ -	return 0; -} - -static int omap3evm_panel_suspend(struct platform_device *pdev, -				   pm_message_t mesg) -{ -	return 0; -} - -static int omap3evm_panel_resume(struct platform_device *pdev) -{ -	return 0; -} - -struct platform_driver omap3evm_panel_driver = { -	.probe		= omap3evm_panel_probe, -	.remove		= omap3evm_panel_remove, -	.suspend	= omap3evm_panel_suspend, -	.resume		= omap3evm_panel_resume, -	.driver		= { -		.name	= "omap3evm_lcd", -		.owner	= THIS_MODULE, -	}, -}; - -static int __init omap3evm_panel_drv_init(void) -{ -	return platform_driver_register(&omap3evm_panel_driver); -} - -static void __exit omap3evm_panel_drv_exit(void) -{ -	platform_driver_unregister(&omap3evm_panel_driver); -} - -module_init(omap3evm_panel_drv_init); -module_exit(omap3evm_panel_drv_exit); diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c deleted file mode 100644 index 564933ffac6..00000000000 --- a/drivers/video/omap/lcd_overo.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * LCD panel support for the Gumstix Overo - * - * Author: Steve Sakoman <steve@sakoman.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * 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, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - * - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/i2c/twl.h> - -#include <mach/gpio.h> -#include <plat/mux.h> -#include <asm/mach-types.h> - -#include "omapfb.h" - -#define LCD_ENABLE       144 - -static int overo_panel_init(struct lcd_panel *panel, -				struct omapfb_device *fbdev) -{ -	if ((gpio_request(LCD_ENABLE, "LCD_ENABLE") == 0) && -	    (gpio_direction_output(LCD_ENABLE, 1) == 0)) -		gpio_export(LCD_ENABLE, 0); -	else -		printk(KERN_ERR "could not obtain gpio for LCD_ENABLE\n"); - -	return 0; -} - -static void overo_panel_cleanup(struct lcd_panel *panel) -{ -	gpio_free(LCD_ENABLE); -} - -static int overo_panel_enable(struct lcd_panel *panel) -{ -	gpio_set_value(LCD_ENABLE, 1); -	return 0; -} - -static void overo_panel_disable(struct lcd_panel *panel) -{ -	gpio_set_value(LCD_ENABLE, 0); -} - -static unsigned long overo_panel_get_caps(struct lcd_panel *panel) -{ -	return 0; -} - -struct lcd_panel overo_panel = { -	.name		= "overo", -	.config		= OMAP_LCDC_PANEL_TFT, -	.bpp		= 16, -	.data_lines	= 24, - -#if defined CONFIG_FB_OMAP_031M3R - -	/* 640 x 480 @ 60 Hz  Reduced blanking VESA CVT 0.31M3-R */ -	.x_res		= 640, -	.y_res		= 480, -	.hfp		= 48, -	.hsw		= 32, -	.hbp		= 80, -	.vfp		= 3, -	.vsw		= 4, -	.vbp		= 7, -	.pixel_clock	= 23500, - -#elif defined CONFIG_FB_OMAP_048M3R - -	/* 800 x 600 @ 60 Hz  Reduced blanking VESA CVT 0.48M3-R */ -	.x_res		= 800, -	.y_res		= 600, -	.hfp		= 48, -	.hsw		= 32, -	.hbp		= 80, -	.vfp		= 3, -	.vsw		= 4, -	.vbp		= 11, -	.pixel_clock	= 35500, - -#elif defined CONFIG_FB_OMAP_079M3R - -	/* 1024 x 768 @ 60 Hz  Reduced blanking VESA CVT 0.79M3-R */ -	.x_res		= 1024, -	.y_res		= 768, -	.hfp		= 48, -	.hsw		= 32, -	.hbp		= 80, -	.vfp		= 3, -	.vsw		= 4, -	.vbp		= 15, -	.pixel_clock	= 56000, - -#elif defined CONFIG_FB_OMAP_092M9R - -	/* 1280 x 720 @ 60 Hz  Reduced blanking VESA CVT 0.92M9-R */ -	.x_res		= 1280, -	.y_res		= 720, -	.hfp		= 48, -	.hsw		= 32, -	.hbp		= 80, -	.vfp		= 3, -	.vsw		= 5, -	.vbp		= 13, -	.pixel_clock	= 64000, - -#else - -	/* use 640 x 480 if no config option */ -	/* 640 x 480 @ 60 Hz  Reduced blanking VESA CVT 0.31M3-R */ -	.x_res		= 640, -	.y_res		= 480, -	.hfp		= 48, -	.hsw		= 32, -	.hbp		= 80, -	.vfp		= 3, -	.vsw		= 4, -	.vbp		= 7, -	.pixel_clock	= 23500, - -#endif - -	.init		= overo_panel_init, -	.cleanup	= overo_panel_cleanup, -	.enable		= overo_panel_enable, -	.disable	= overo_panel_disable, -	.get_caps	= overo_panel_get_caps, -}; - -static int overo_panel_probe(struct platform_device *pdev) -{ -	omapfb_register_panel(&overo_panel); -	return 0; -} - -static int overo_panel_remove(struct platform_device *pdev) -{ -	/* omapfb does not have unregister_panel */ -	return 0; -} - -static struct platform_driver overo_panel_driver = { -	.probe		= overo_panel_probe, -	.remove		= overo_panel_remove, -	.driver		= { -		.name	= "overo_lcd", -		.owner	= THIS_MODULE, -	}, -}; - -static int __init overo_panel_drv_init(void) -{ -	return platform_driver_register(&overo_panel_driver); -} - -static void __exit overo_panel_drv_exit(void) -{ -	platform_driver_unregister(&overo_panel_driver); -} - -module_init(overo_panel_drv_init); -module_exit(overo_panel_drv_exit); diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 609a2807317..8d8e1fe1901 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig @@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI  	  Supports LCD Panel used in TI SDP3430 and EVM boards,  	  OMAP3517 EVM boards and CM-T35. +config PANEL_DVI +	tristate "DVI output" +	depends on OMAP2_DSS_DPI +	help +	  Driver for external monitors, connected via DVI. The driver uses i2c +	  to read EDID information from the monitor. +  config PANEL_LGPHILIPS_LB035Q02  	tristate "LG.Philips LB035Q02 LCD Panel"  	depends on OMAP2_DSS_DPI && SPI @@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02  config PANEL_SHARP_LS037V7DW01          tristate "Sharp LS037V7DW01 LCD Panel"          depends on OMAP2_DSS_DPI -        select BACKLIGHT_CLASS_DEVICE +        depends on BACKLIGHT_CLASS_DEVICE          help            LCD Panel used in TI's SDP3430 and EVM boards  config PANEL_NEC_NL8048HL11_01B  	tristate "NEC NL8048HL11-01B Panel"  	depends on OMAP2_DSS_DPI +	depends on SPI +	depends on BACKLIGHT_CLASS_DEVICE  	help  		This NEC NL8048HL11-01B panel is TFT LCD  		used in the Zoom2/3/3630 sdp boards. +config PANEL_PICODLP +	tristate "TI PICO DLP mini-projector" +	depends on OMAP2_DSS && I2C +	help +		A mini-projector used in TI's SDP4430 and EVM boards +		For more info please visit http://www.dlp.com/projector/ +  config PANEL_TAAL          tristate "Taal DSI Panel"          depends on OMAP2_DSS_DSI +        depends on BACKLIGHT_CLASS_DEVICE          help            Taal DSI command mode panel from TPO. @@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1  config PANEL_ACX565AKM  	tristate "ACX565AKM Panel"  	depends on OMAP2_DSS_SDI && SPI -	select BACKLIGHT_CLASS_DEVICE +	depends on BACKLIGHT_CLASS_DEVICE  	help  	  This is the LCD panel used on Nokia N900 + +config PANEL_N8X0 +	tristate "N8X0 Panel" +	depends on OMAP2_DSS_RFBI && SPI +	depends on BACKLIGHT_CLASS_DEVICE +	help +	  This is the LCD panel used on Nokia N8x0  endmenu diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index 0f601ab3abf..fbfafc6eebb 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile @@ -1,8 +1,11 @@  obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o +obj-$(CONFIG_PANEL_DVI) += panel-dvi.o  obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o  obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o  obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o  obj-$(CONFIG_PANEL_TAAL) += panel-taal.o +obj-$(CONFIG_PANEL_PICODLP) +=  panel-picodlp.o  obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o  obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o +obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-dvi.c new file mode 100644 index 00000000000..03eb14af33e --- /dev/null +++ b/drivers/video/omap2/displays/panel-dvi.c @@ -0,0 +1,363 @@ +/* + * DVI output support + * + * Copyright (C) 2011 Texas Instruments Inc + * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include <video/omapdss.h> +#include <linux/i2c.h> +#include <drm/drm_edid.h> + +#include <video/omap-panel-dvi.h> + +static const struct omap_video_timings panel_dvi_default_timings = { +	.x_res		= 640, +	.y_res		= 480, + +	.pixel_clock	= 23500, + +	.hfp		= 48, +	.hsw		= 32, +	.hbp		= 80, + +	.vfp		= 3, +	.vsw		= 4, +	.vbp		= 7, +}; + +struct panel_drv_data { +	struct omap_dss_device *dssdev; + +	struct mutex lock; +}; + +static inline struct panel_dvi_platform_data +*get_pdata(const struct omap_dss_device *dssdev) +{ +	return dssdev->data; +} + +static int panel_dvi_power_on(struct omap_dss_device *dssdev) +{ +	struct panel_dvi_platform_data *pdata = get_pdata(dssdev); +	int r; + +	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) +		return 0; + +	r = omapdss_dpi_display_enable(dssdev); +	if (r) +		goto err0; + +	if (pdata->platform_enable) { +		r = pdata->platform_enable(dssdev); +		if (r) +			goto err1; +	} + +	return 0; +err1: +	omapdss_dpi_display_disable(dssdev); +err0: +	return r; +} + +static void panel_dvi_power_off(struct omap_dss_device *dssdev) +{ +	struct panel_dvi_platform_data *pdata = get_pdata(dssdev); + +	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) +		return; + +	if (pdata->platform_disable) +		pdata->platform_disable(dssdev); + +	omapdss_dpi_display_disable(dssdev); +} + +static int panel_dvi_probe(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata; + +	ddata = kzalloc(sizeof(*ddata), GFP_KERNEL); +	if (!ddata) +		return -ENOMEM; + +	dssdev->panel.timings = panel_dvi_default_timings; +	dssdev->panel.config = OMAP_DSS_LCD_TFT; + +	ddata->dssdev = dssdev; +	mutex_init(&ddata->lock); + +	dev_set_drvdata(&dssdev->dev, ddata); + +	return 0; +} + +static void __exit panel_dvi_remove(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&ddata->lock); + +	dev_set_drvdata(&dssdev->dev, NULL); + +	mutex_unlock(&ddata->lock); + +	kfree(ddata); +} + +static int panel_dvi_enable(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); +	int r; + +	mutex_lock(&ddata->lock); + +	r = panel_dvi_power_on(dssdev); +	if (r == 0) +		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +	mutex_unlock(&ddata->lock); + +	return r; +} + +static void panel_dvi_disable(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&ddata->lock); + +	panel_dvi_power_off(dssdev); + +	dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + +	mutex_unlock(&ddata->lock); +} + +static int panel_dvi_suspend(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&ddata->lock); + +	panel_dvi_power_off(dssdev); + +	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + +	mutex_unlock(&ddata->lock); + +	return 0; +} + +static int panel_dvi_resume(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); +	int r; + +	mutex_lock(&ddata->lock); + +	r = panel_dvi_power_on(dssdev); +	if (r == 0) +		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +	mutex_unlock(&ddata->lock); + +	return r; +} + +static void panel_dvi_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&ddata->lock); +	dpi_set_timings(dssdev, timings); +	mutex_unlock(&ddata->lock); +} + +static void panel_dvi_get_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&ddata->lock); +	*timings = dssdev->panel.timings; +	mutex_unlock(&ddata->lock); +} + +static int panel_dvi_check_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); +	int r; + +	mutex_lock(&ddata->lock); +	r = dpi_check_timings(dssdev, timings); +	mutex_unlock(&ddata->lock); + +	return r; +} + + +static int panel_dvi_ddc_read(struct i2c_adapter *adapter, +		unsigned char *buf, u16 count, u8 offset) +{ +	int r, retries; + +	for (retries = 3; retries > 0; retries--) { +		struct i2c_msg msgs[] = { +			{ +				.addr   = DDC_ADDR, +				.flags  = 0, +				.len    = 1, +				.buf    = &offset, +			}, { +				.addr   = DDC_ADDR, +				.flags  = I2C_M_RD, +				.len    = count, +				.buf    = buf, +			} +		}; + +		r = i2c_transfer(adapter, msgs, 2); +		if (r == 2) +			return 0; + +		if (r != -EAGAIN) +			break; +	} + +	return r < 0 ? r : -EIO; +} + +static int panel_dvi_read_edid(struct omap_dss_device *dssdev, +		u8 *edid, int len) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); +	struct panel_dvi_platform_data *pdata = get_pdata(dssdev); +	struct i2c_adapter *adapter; +	int r, l, bytes_read; + +	mutex_lock(&ddata->lock); + +	if (pdata->i2c_bus_num == 0) { +		r = -ENODEV; +		goto err; +	} + +	adapter = i2c_get_adapter(pdata->i2c_bus_num); +	if (!adapter) { +		dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", +				pdata->i2c_bus_num); +		r = -EINVAL; +		goto err; +	} + +	l = min(EDID_LENGTH, len); +	r = panel_dvi_ddc_read(adapter, edid, l, 0); +	if (r) +		goto err; + +	bytes_read = l; + +	/* if there are extensions, read second block */ +	if (len > EDID_LENGTH && edid[0x7e] > 0) { +		l = min(EDID_LENGTH, len - EDID_LENGTH); + +		r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH, +				l, EDID_LENGTH); +		if (r) +			goto err; + +		bytes_read += l; +	} + +	mutex_unlock(&ddata->lock); + +	return bytes_read; + +err: +	mutex_unlock(&ddata->lock); +	return r; +} + +static bool panel_dvi_detect(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); +	struct panel_dvi_platform_data *pdata = get_pdata(dssdev); +	struct i2c_adapter *adapter; +	unsigned char out; +	int r; + +	mutex_lock(&ddata->lock); + +	if (pdata->i2c_bus_num == 0) +		goto out; + +	adapter = i2c_get_adapter(pdata->i2c_bus_num); +	if (!adapter) +		goto out; + +	r = panel_dvi_ddc_read(adapter, &out, 1, 0); + +	mutex_unlock(&ddata->lock); + +	return r == 0; + +out: +	mutex_unlock(&ddata->lock); +	return true; +} + +static struct omap_dss_driver panel_dvi_driver = { +	.probe		= panel_dvi_probe, +	.remove		= __exit_p(panel_dvi_remove), + +	.enable		= panel_dvi_enable, +	.disable	= panel_dvi_disable, +	.suspend	= panel_dvi_suspend, +	.resume		= panel_dvi_resume, + +	.set_timings	= panel_dvi_set_timings, +	.get_timings	= panel_dvi_get_timings, +	.check_timings	= panel_dvi_check_timings, + +	.read_edid	= panel_dvi_read_edid, +	.detect		= panel_dvi_detect, + +	.driver         = { +		.name   = "dvi", +		.owner  = THIS_MODULE, +	}, +}; + +static int __init panel_dvi_init(void) +{ +	return omap_dss_register_driver(&panel_dvi_driver); +} + +static void __exit panel_dvi_exit(void) +{ +	omap_dss_unregister_driver(&panel_dvi_driver); +} + +module_init(panel_dvi_init); +module_exit(panel_dvi_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 9c90f75653f..519c47d2057 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c @@ -58,30 +58,6 @@ struct panel_config {  /* Panel configurations */  static struct panel_config generic_dpi_panels[] = { -	/* Generic Panel */ -	{ -		{ -			.x_res		= 640, -			.y_res		= 480, - -			.pixel_clock	= 23500, - -			.hfp		= 48, -			.hsw		= 32, -			.hbp		= 80, - -			.vfp		= 3, -			.vsw		= 4, -			.vbp		= 7, -		}, -		.acbi			= 0x0, -		.acb			= 0x0, -		.config			= OMAP_DSS_LCD_TFT, -		.power_on_delay		= 0, -		.power_off_delay	= 0, -		.name			= "generic", -	}, -  	/* Sharp LQ043T1DG01 */  	{  		{ @@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = {  		.power_off_delay	= 0,  		.name			= "powertip_ph480272t",  	}, + +	/* Innolux AT070TN83 */ +	{ +		{ +			.x_res		= 800, +			.y_res		= 480, + +			.pixel_clock	= 40000, + +			.hsw		= 48, +			.hfp		= 1, +			.hbp		= 1, + +			.vsw		= 3, +			.vfp		= 12, +			.vbp		= 25, +		}, +		.acbi			= 0x0, +		.acb			= 0x28, +		.config			= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | +					  OMAP_DSS_LCD_IHS, +		.power_on_delay		= 0, +		.power_off_delay	= 0, +		.name			= "innolux_at070tn83", +	}, + +	/* NEC NL2432DR22-11B */ +	{ +		{ +			.x_res		= 240, +			.y_res		= 320, + +			.pixel_clock	= 5400, + +			.hsw		= 3, +			.hfp		= 3, +			.hbp		= 39, + +			.vsw		= 1, +			.vfp		= 2, +			.vbp		= 7, +		}, +		.config			= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | +						OMAP_DSS_LCD_IHS, +		.name			= "nec_nl2432dr22-11b", +	}, + +	/* Unknown panel used in OMAP H4 */ +	{ +		{ +			.x_res		= 240, +			.y_res		= 320, + +			.pixel_clock	= 6250, + +			.hsw		= 15, +			.hfp		= 15, +			.hbp		= 60, + +			.vsw		= 1, +			.vfp		= 1, +			.vbp		= 1, +		}, +		.config			= OMAP_DSS_LCD_TFT, + +		.name			= "h4", +	}, + +	/* Unknown panel used in Samsung OMAP2 Apollon */ +	{ +		{ +			.x_res		= 480, +			.y_res		= 272, + +			.pixel_clock	= 6250, + +			.hsw		= 41, +			.hfp		= 2, +			.hbp		= 2, + +			.vsw		= 10, +			.vfp		= 2, +			.vbp		= 2, +		}, +		.config			= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | +						OMAP_DSS_LCD_IHS, + +		.name			= "apollon", +	},  };  struct panel_drv_data { diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c new file mode 100644 index 00000000000..150e8bae35a --- /dev/null +++ b/drivers/video/omap2/displays/panel-n8x0.c @@ -0,0 +1,747 @@ +/* #define DEBUG */ + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/backlight.h> +#include <linux/fb.h> + +#include <video/omapdss.h> +#include <video/omap-panel-n8x0.h> + +#define BLIZZARD_REV_CODE                      0x00 +#define BLIZZARD_CONFIG                        0x02 +#define BLIZZARD_PLL_DIV                       0x04 +#define BLIZZARD_PLL_LOCK_RANGE                0x06 +#define BLIZZARD_PLL_CLOCK_SYNTH_0             0x08 +#define BLIZZARD_PLL_CLOCK_SYNTH_1             0x0a +#define BLIZZARD_PLL_MODE                      0x0c +#define BLIZZARD_CLK_SRC                       0x0e +#define BLIZZARD_MEM_BANK0_ACTIVATE            0x10 +#define BLIZZARD_MEM_BANK0_STATUS              0x14 +#define BLIZZARD_PANEL_CONFIGURATION           0x28 +#define BLIZZARD_HDISP                         0x2a +#define BLIZZARD_HNDP                          0x2c +#define BLIZZARD_VDISP0                        0x2e +#define BLIZZARD_VDISP1                        0x30 +#define BLIZZARD_VNDP                          0x32 +#define BLIZZARD_HSW                           0x34 +#define BLIZZARD_VSW                           0x38 +#define BLIZZARD_DISPLAY_MODE                  0x68 +#define BLIZZARD_INPUT_WIN_X_START_0           0x6c +#define BLIZZARD_DATA_SOURCE_SELECT            0x8e +#define BLIZZARD_DISP_MEM_DATA_PORT            0x90 +#define BLIZZARD_DISP_MEM_READ_ADDR0           0x92 +#define BLIZZARD_POWER_SAVE                    0xE6 +#define BLIZZARD_NDISP_CTRL_STATUS             0xE8 + +/* Data source select */ +/* For S1D13745 */ +#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND	0x00 +#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE	0x01 +#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE	0x04 +#define BLIZZARD_SRC_DISABLE_OVERLAY		0x05 +/* For S1D13744 */ +#define BLIZZARD_SRC_WRITE_LCD			0x00 +#define BLIZZARD_SRC_BLT_LCD			0x06 + +#define BLIZZARD_COLOR_RGB565			0x01 +#define BLIZZARD_COLOR_YUV420			0x09 + +#define BLIZZARD_VERSION_S1D13745		0x01	/* Hailstorm */ +#define BLIZZARD_VERSION_S1D13744		0x02	/* Blizzard */ + +#define MIPID_CMD_READ_DISP_ID		0x04 +#define MIPID_CMD_READ_RED		0x06 +#define MIPID_CMD_READ_GREEN		0x07 +#define MIPID_CMD_READ_BLUE		0x08 +#define MIPID_CMD_READ_DISP_STATUS	0x09 +#define MIPID_CMD_RDDSDR		0x0F +#define MIPID_CMD_SLEEP_IN		0x10 +#define MIPID_CMD_SLEEP_OUT		0x11 +#define MIPID_CMD_DISP_OFF		0x28 +#define MIPID_CMD_DISP_ON		0x29 + +static struct panel_drv_data { +	struct mutex lock; + +	struct omap_dss_device *dssdev; +	struct spi_device *spidev; +	struct backlight_device *bldev; + +	int blizzard_ver; +} s_drv_data; + + +static inline +struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev) +{ +	return dssdev->data; +} + +static inline +struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev) +{ +	return &s_drv_data; +} + + +static inline void blizzard_cmd(u8 cmd) +{ +	omap_rfbi_write_command(&cmd, 1); +} + +static inline void blizzard_write(u8 cmd, const u8 *buf, int len) +{ +	omap_rfbi_write_command(&cmd, 1); +	omap_rfbi_write_data(buf, len); +} + +static inline void blizzard_read(u8 cmd, u8 *buf, int len) +{ +	omap_rfbi_write_command(&cmd, 1); +	omap_rfbi_read_data(buf, len); +} + +static u8 blizzard_read_reg(u8 cmd) +{ +	u8 data; +	blizzard_read(cmd, &data, 1); +	return data; +} + +static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev, +		int x, int y, int w, int h) +{ +	struct panel_drv_data *ddata = get_drv_data(dssdev); +	u8 tmp[18]; +	int x_end, y_end; + +	x_end = x + w - 1; +	y_end = y + h - 1; + +	tmp[0] = x; +	tmp[1] = x >> 8; +	tmp[2] = y; +	tmp[3] = y >> 8; +	tmp[4] = x_end; +	tmp[5] = x_end >> 8; +	tmp[6] = y_end; +	tmp[7] = y_end >> 8; + +	/* scaling? */ +	tmp[8] = x; +	tmp[9] = x >> 8; +	tmp[10] = y; +	tmp[11] = y >> 8; +	tmp[12] = x_end; +	tmp[13] = x_end >> 8; +	tmp[14] = y_end; +	tmp[15] = y_end >> 8; + +	tmp[16] = BLIZZARD_COLOR_RGB565; + +	if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745) +		tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND; +	else +		tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ? +			BLIZZARD_SRC_WRITE_LCD : +			BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; + +	omap_rfbi_configure(dssdev, 16, 8); + +	blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); + +	omap_rfbi_configure(dssdev, 16, 16); +} + +static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf, +		int wlen, u8 *rbuf, int rlen) +{ +	struct spi_message	m; +	struct spi_transfer	*x, xfer[4]; +	u16			w; +	int			r; + +	spi_message_init(&m); + +	memset(xfer, 0, sizeof(xfer)); +	x = &xfer[0]; + +	cmd &=  0xff; +	x->tx_buf		= &cmd; +	x->bits_per_word	= 9; +	x->len			= 2; +	spi_message_add_tail(x, &m); + +	if (wlen) { +		x++; +		x->tx_buf		= wbuf; +		x->len			= wlen; +		x->bits_per_word	= 9; +		spi_message_add_tail(x, &m); +	} + +	if (rlen) { +		x++; +		x->rx_buf	= &w; +		x->len		= 1; +		spi_message_add_tail(x, &m); + +		if (rlen > 1) { +			/* Arrange for the extra clock before the first +			 * data bit. +			 */ +			x->bits_per_word = 9; +			x->len		 = 2; + +			x++; +			x->rx_buf	 = &rbuf[1]; +			x->len		 = rlen - 1; +			spi_message_add_tail(x, &m); +		} +	} + +	r = spi_sync(spi, &m); +	if (r < 0) +		dev_dbg(&spi->dev, "spi_sync %d\n", r); + +	if (rlen) +		rbuf[0] = w & 0xff; +} + +static inline void mipid_cmd(struct spi_device *spi, int cmd) +{ +	mipid_transfer(spi, cmd, NULL, 0, NULL, 0); +} + +static inline void mipid_write(struct spi_device *spi, +		int reg, const u8 *buf, int len) +{ +	mipid_transfer(spi, reg, buf, len, NULL, 0); +} + +static inline void mipid_read(struct spi_device *spi, +		int reg, u8 *buf, int len) +{ +	mipid_transfer(spi, reg, NULL, 0, buf, len); +} + +static void set_data_lines(struct spi_device *spi, int data_lines) +{ +	u16 par; + +	switch (data_lines) { +	case 16: +		par = 0x150; +		break; +	case 18: +		par = 0x160; +		break; +	case 24: +		par = 0x170; +		break; +	} + +	mipid_write(spi, 0x3a, (u8 *)&par, 2); +} + +static void send_init_string(struct spi_device *spi) +{ +	u16 initpar[] = { 0x0102, 0x0100, 0x0100 }; +	mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar)); +} + +static void send_display_on(struct spi_device *spi) +{ +	mipid_cmd(spi, MIPID_CMD_DISP_ON); +} + +static void send_display_off(struct spi_device *spi) +{ +	mipid_cmd(spi, MIPID_CMD_DISP_OFF); +} + +static void send_sleep_out(struct spi_device *spi) +{ +	mipid_cmd(spi, MIPID_CMD_SLEEP_OUT); +	msleep(120); +} + +static void send_sleep_in(struct spi_device *spi) +{ +	mipid_cmd(spi, MIPID_CMD_SLEEP_IN); +	msleep(50); +} + +static int n8x0_panel_power_on(struct omap_dss_device *dssdev) +{ +	int r; +	struct panel_n8x0_data *bdata = get_board_data(dssdev); +	struct panel_drv_data *ddata = get_drv_data(dssdev); +	struct spi_device *spi = ddata->spidev; +	u8 rev, conf; +	u8 display_id[3]; +	const char *panel_name; + +	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) +		return 0; + +	gpio_direction_output(bdata->ctrl_pwrdown, 1); + +	if (bdata->platform_enable) { +		r = bdata->platform_enable(dssdev); +		if (r) +			goto err_plat_en; +	} + +	r = omapdss_rfbi_display_enable(dssdev); +	if (r) +		goto err_rfbi_en; + +	rev = blizzard_read_reg(BLIZZARD_REV_CODE); +	conf = blizzard_read_reg(BLIZZARD_CONFIG); + +	switch (rev & 0xfc) { +	case 0x9c: +		ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744; +		dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d " +			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); +		break; +	case 0xa4: +		ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745; +		dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d " +			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); +		break; +	default: +		dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev); +		r = -ENODEV; +		goto err_inv_chip; +	} + +	/* panel */ + +	gpio_direction_output(bdata->panel_reset, 1); + +	mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3); +	dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n", +			display_id[0], display_id[1], display_id[2]); + +	switch (display_id[0]) { +	case 0x45: +		panel_name = "lph8923"; +		break; +	case 0x83: +		panel_name = "ls041y3"; +		break; +	default: +		dev_err(&dssdev->dev, "invalid display ID 0x%x\n", +				display_id[0]); +		r = -ENODEV; +		goto err_inv_panel; +	} + +	dev_info(&dssdev->dev, "%s rev %02x LCD detected\n", +			panel_name, display_id[1]); + +	send_sleep_out(spi); +	send_init_string(spi); +	set_data_lines(spi, 24); +	send_display_on(spi); + +	return 0; + +err_inv_panel: +	/* +	 * HACK: we should turn off the panel here, but there is some problem +	 * with the initialization sequence, and we fail to init the panel if we +	 * have turned it off +	 */ +	/* gpio_direction_output(bdata->panel_reset, 0); */ +err_inv_chip: +	omapdss_rfbi_display_disable(dssdev); +err_rfbi_en: +	if (bdata->platform_disable) +		bdata->platform_disable(dssdev); +err_plat_en: +	gpio_direction_output(bdata->ctrl_pwrdown, 0); +	return r; +} + +static void n8x0_panel_power_off(struct omap_dss_device *dssdev) +{ +	struct panel_n8x0_data *bdata = get_board_data(dssdev); +	struct panel_drv_data *ddata = get_drv_data(dssdev); +	struct spi_device *spi = ddata->spidev; + +	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) +		return; + +	send_display_off(spi); +	send_sleep_in(spi); + +	if (bdata->platform_disable) +		bdata->platform_disable(dssdev); + +	/* +	 * HACK: we should turn off the panel here, but there is some problem +	 * with the initialization sequence, and we fail to init the panel if we +	 * have turned it off +	 */ +	/* gpio_direction_output(bdata->panel_reset, 0); */ +	gpio_direction_output(bdata->ctrl_pwrdown, 0); +	omapdss_rfbi_display_disable(dssdev); +} + +static const struct rfbi_timings n8x0_panel_timings = { +	.cs_on_time     = 0, + +	.we_on_time     = 9000, +	.we_off_time    = 18000, +	.we_cycle_time  = 36000, + +	.re_on_time     = 9000, +	.re_off_time    = 27000, +	.re_cycle_time  = 36000, + +	.access_time    = 27000, +	.cs_off_time    = 36000, + +	.cs_pulse_width = 0, +}; + +static int n8x0_bl_update_status(struct backlight_device *dev) +{ +	struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); +	struct panel_n8x0_data *bdata = get_board_data(dssdev); +	struct panel_drv_data *ddata = get_drv_data(dssdev); +	int r; +	int level; + +	mutex_lock(&ddata->lock); + +	if (dev->props.fb_blank == FB_BLANK_UNBLANK && +			dev->props.power == FB_BLANK_UNBLANK) +		level = dev->props.brightness; +	else +		level = 0; + +	dev_dbg(&dssdev->dev, "update brightness to %d\n", level); + +	if (!bdata->set_backlight) +		r = -EINVAL; +	else +		r = bdata->set_backlight(dssdev, level); + +	mutex_unlock(&ddata->lock); + +	return r; +} + +static int n8x0_bl_get_intensity(struct backlight_device *dev) +{ +	if (dev->props.fb_blank == FB_BLANK_UNBLANK && +			dev->props.power == FB_BLANK_UNBLANK) +		return dev->props.brightness; + +	return 0; +} + +static const struct backlight_ops n8x0_bl_ops = { +	.get_brightness = n8x0_bl_get_intensity, +	.update_status  = n8x0_bl_update_status, +}; + +static int n8x0_panel_probe(struct omap_dss_device *dssdev) +{ +	struct panel_n8x0_data *bdata = get_board_data(dssdev); +	struct panel_drv_data *ddata; +	struct backlight_device *bldev; +	struct backlight_properties props; +	int r; + +	dev_dbg(&dssdev->dev, "probe\n"); + +	if (!bdata) +		return -EINVAL; + +	s_drv_data.dssdev = dssdev; + +	ddata = &s_drv_data; + +	mutex_init(&ddata->lock); + +	dssdev->panel.config = OMAP_DSS_LCD_TFT; +	dssdev->panel.timings.x_res = 800; +	dssdev->panel.timings.y_res = 480; +	dssdev->ctrl.pixel_size = 16; +	dssdev->ctrl.rfbi_timings = n8x0_panel_timings; + +	memset(&props, 0, sizeof(props)); +	props.max_brightness = 127; +	props.type = BACKLIGHT_PLATFORM; +	bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, +			dssdev, &n8x0_bl_ops, &props); +	if (IS_ERR(bldev)) { +		r = PTR_ERR(bldev); +		dev_err(&dssdev->dev, "register backlight failed\n"); +		return r; +	} + +	ddata->bldev = bldev; + +	bldev->props.fb_blank = FB_BLANK_UNBLANK; +	bldev->props.power = FB_BLANK_UNBLANK; +	bldev->props.brightness = 127; + +	n8x0_bl_update_status(bldev); + +	return 0; +} + +static void n8x0_panel_remove(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = get_drv_data(dssdev); +	struct backlight_device *bldev; + +	dev_dbg(&dssdev->dev, "remove\n"); + +	bldev = ddata->bldev; +	bldev->props.power = FB_BLANK_POWERDOWN; +	n8x0_bl_update_status(bldev); +	backlight_device_unregister(bldev); + +	dev_set_drvdata(&dssdev->dev, NULL); +} + +static int n8x0_panel_enable(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = get_drv_data(dssdev); +	int r; + +	dev_dbg(&dssdev->dev, "enable\n"); + +	mutex_lock(&ddata->lock); + +	rfbi_bus_lock(); + +	r = n8x0_panel_power_on(dssdev); + +	rfbi_bus_unlock(); + +	if (r) { +		mutex_unlock(&ddata->lock); +		return r; +	} + +	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +	mutex_unlock(&ddata->lock); + +	return 0; +} + +static void n8x0_panel_disable(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = get_drv_data(dssdev); + +	dev_dbg(&dssdev->dev, "disable\n"); + +	mutex_lock(&ddata->lock); + +	rfbi_bus_lock(); + +	n8x0_panel_power_off(dssdev); + +	rfbi_bus_unlock(); + +	dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + +	mutex_unlock(&ddata->lock); +} + +static int n8x0_panel_suspend(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = get_drv_data(dssdev); + +	dev_dbg(&dssdev->dev, "suspend\n"); + +	mutex_lock(&ddata->lock); + +	rfbi_bus_lock(); + +	n8x0_panel_power_off(dssdev); + +	rfbi_bus_unlock(); + +	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + +	mutex_unlock(&ddata->lock); + +	return 0; +} + +static int n8x0_panel_resume(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = get_drv_data(dssdev); +	int r; + +	dev_dbg(&dssdev->dev, "resume\n"); + +	mutex_lock(&ddata->lock); + +	rfbi_bus_lock(); + +	r = n8x0_panel_power_on(dssdev); + +	rfbi_bus_unlock(); + +	if (r) { +		mutex_unlock(&ddata->lock); +		return r; +	} + +	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +	mutex_unlock(&ddata->lock); + +	return 0; +} + +static void n8x0_panel_get_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings) +{ +	*timings = dssdev->panel.timings; +} + +static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, +		u16 *xres, u16 *yres) +{ +	*xres = dssdev->panel.timings.x_res; +	*yres = dssdev->panel.timings.y_res; +} + +static void update_done(void *data) +{ +	rfbi_bus_unlock(); +} + +static int n8x0_panel_update(struct omap_dss_device *dssdev, +		u16 x, u16 y, u16 w, u16 h) +{ +	struct panel_drv_data *ddata = get_drv_data(dssdev); + +	dev_dbg(&dssdev->dev, "update\n"); + +	mutex_lock(&ddata->lock); +	rfbi_bus_lock(); + +	omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h); + +	blizzard_ctrl_setup_update(dssdev, x, y, w, h); + +	omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL); + +	mutex_unlock(&ddata->lock); + +	return 0; +} + +static int n8x0_panel_sync(struct omap_dss_device *dssdev) +{ +	struct panel_drv_data *ddata = get_drv_data(dssdev); + +	dev_dbg(&dssdev->dev, "sync\n"); + +	mutex_lock(&ddata->lock); +	rfbi_bus_lock(); +	rfbi_bus_unlock(); +	mutex_unlock(&ddata->lock); + +	return 0; +} + +static struct omap_dss_driver n8x0_panel_driver = { +	.probe		= n8x0_panel_probe, +	.remove		= n8x0_panel_remove, + +	.enable		= n8x0_panel_enable, +	.disable	= n8x0_panel_disable, +	.suspend	= n8x0_panel_suspend, +	.resume		= n8x0_panel_resume, + +	.update		= n8x0_panel_update, +	.sync		= n8x0_panel_sync, + +	.get_resolution	= n8x0_panel_get_resolution, +	.get_recommended_bpp = omapdss_default_get_recommended_bpp, + +	.get_timings	= n8x0_panel_get_timings, + +	.driver         = { +		.name   = "n8x0_panel", +		.owner  = THIS_MODULE, +	}, +}; + +/* PANEL */ + +static int mipid_spi_probe(struct spi_device *spi) +{ +	dev_dbg(&spi->dev, "mipid_spi_probe\n"); + +	spi->mode = SPI_MODE_0; + +	s_drv_data.spidev = spi; + +	return 0; +} + +static int mipid_spi_remove(struct spi_device *spi) +{ +	dev_dbg(&spi->dev, "mipid_spi_remove\n"); +	return 0; +} + +static struct spi_driver mipid_spi_driver = { +	.driver = { +		.name	= "lcd_mipid", +		.bus	= &spi_bus_type, +		.owner	= THIS_MODULE, +	}, +	.probe	= mipid_spi_probe, +	.remove	= __devexit_p(mipid_spi_remove), +}; + +static int __init n8x0_panel_drv_init(void) +{ +	int r; + +	r = spi_register_driver(&mipid_spi_driver); +	if (r) { +		pr_err("n8x0_panel: spi driver registration failed\n"); +		return r; +	} + +	r = omap_dss_register_driver(&n8x0_panel_driver); +	if (r) { +		pr_err("n8x0_panel: dss driver registration failed\n"); +		spi_unregister_driver(&mipid_spi_driver); +		return r; +	} + +	return 0; +} + +static void __exit n8x0_panel_drv_exit(void) +{ +	spi_unregister_driver(&mipid_spi_driver); + +	omap_dss_unregister_driver(&n8x0_panel_driver); +} + +module_init(n8x0_panel_drv_init); +module_exit(n8x0_panel_drv_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c new file mode 100644 index 00000000000..98ebdaddab5 --- /dev/null +++ b/drivers/video/omap2/displays/panel-picodlp.c @@ -0,0 +1,594 @@ +/* + * picodlp panel driver + * picodlp_i2c_driver: i2c_client driver + * + * Copyright (C) 2009-2011 Texas Instruments + * Author: Mythri P K <mythripk@ti.com> + * Mayuresh Janorkar <mayur@ti.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <linux/module.h> +#include <linux/input.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/firmware.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/i2c.h> +#include <linux/delay.h> +#include <linux/gpio.h> + +#include <video/omapdss.h> +#include <video/omap-panel-picodlp.h> + +#include "panel-picodlp.h" + +struct picodlp_data { +	struct mutex lock; +	struct i2c_client *picodlp_i2c_client; +}; + +static struct i2c_board_info picodlp_i2c_board_info = { +	I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b), +}; + +struct picodlp_i2c_data { +	struct mutex xfer_lock; +}; + +static struct i2c_device_id picodlp_i2c_id[] = { +	{ "picodlp_i2c_driver", 0 }, +}; + +struct picodlp_i2c_command { +	u8 reg; +	u32 value; +}; + +static struct omap_video_timings pico_ls_timings = { +	.x_res		= 864, +	.y_res		= 480, +	.hsw		= 7, +	.hfp		= 11, +	.hbp		= 7, + +	.pixel_clock	= 19200, + +	.vsw		= 2, +	.vfp		= 3, +	.vbp		= 14, +}; + +static inline struct picodlp_panel_data +		*get_panel_data(const struct omap_dss_device *dssdev) +{ +	return (struct picodlp_panel_data *) dssdev->data; +} + +static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg) +{ +	u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4]; +	struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client); +	struct i2c_msg msg[2]; + +	mutex_lock(&picodlp_i2c_data->xfer_lock); + +	msg[0].addr = client->addr; +	msg[0].flags = 0; +	msg[0].len = 2; +	msg[0].buf = read_cmd; + +	msg[1].addr = client->addr; +	msg[1].flags = I2C_M_RD; +	msg[1].len = 4; +	msg[1].buf = data; + +	i2c_transfer(client->adapter, msg, 2); +	mutex_unlock(&picodlp_i2c_data->xfer_lock); +	return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24)); +} + +static int picodlp_i2c_write_block(struct i2c_client *client, +					u8 *data, int len) +{ +	struct i2c_msg msg; +	int i, r, msg_count = 1; + +	struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client); + +	if (len < 1 || len > 32) { +		dev_err(&client->dev, +			"too long syn_write_block len %d\n", len); +		return -EIO; +	} +	mutex_lock(&picodlp_i2c_data->xfer_lock); + +	msg.addr = client->addr; +	msg.flags = 0; +	msg.len = len; +	msg.buf = data; +	r = i2c_transfer(client->adapter, &msg, msg_count); +	mutex_unlock(&picodlp_i2c_data->xfer_lock); + +	/* +	 * i2c_transfer returns: +	 * number of messages sent in case of success +	 * a negative error number in case of failure +	 */ +	if (r != msg_count) +		goto err; + +	/* In case of success */ +	for (i = 0; i < len; i++) +		dev_dbg(&client->dev, +			"addr %x bw 0x%02x[%d]: 0x%02x\n", +			client->addr, data[0] + i, i, data[i]); + +	return 0; +err: +	dev_err(&client->dev, "picodlp_i2c_write error\n"); +	return r; +} + +static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value) +{ +	u8 data[5]; +	int i; + +	data[0] = reg; +	for (i = 1; i < 5; i++) +		data[i] = (value >> (32 - (i) * 8)) & 0xFF; + +	return picodlp_i2c_write_block(client, data, 5); +} + +static int picodlp_i2c_write_array(struct i2c_client *client, +			const struct picodlp_i2c_command commands[], +			int count) +{ +	int i, r = 0; +	for (i = 0; i < count; i++) { +		r = picodlp_i2c_write(client, commands[i].reg, +						commands[i].value); +		if (r) +			return r; +	} +	return r; +} + +static int picodlp_wait_for_dma_done(struct i2c_client *client) +{ +	u8 trial = 100; + +	do { +		msleep(1); +		if (!trial--) +			return -ETIMEDOUT; +	} while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS); + +	return 0; +} + +/** + * picodlp_i2c_init:	i2c_initialization routine + * client:	i2c_client for communication + * + * return + *		0	: Success, no error + *	error code	: Failure + */ +static int picodlp_i2c_init(struct i2c_client *client) +{ +	int r; +	static const struct picodlp_i2c_command init_cmd_set1[] = { +		{SOFT_RESET, 1}, +		{DMD_PARK_TRIGGER, 1}, +		{MISC_REG, 5}, +		{SEQ_CONTROL, 0}, +		{SEQ_VECTOR, 0x100}, +		{DMD_BLOCK_COUNT, 7}, +		{DMD_VCC_CONTROL, 0x109}, +		{DMD_PARK_PULSE_COUNT, 0xA}, +		{DMD_PARK_PULSE_WIDTH, 0xB}, +		{DMD_PARK_DELAY, 0x2ED}, +		{DMD_SHADOW_ENABLE, 0}, +		{FLASH_OPCODE, 0xB}, +		{FLASH_DUMMY_BYTES, 1}, +		{FLASH_ADDR_BYTES, 3}, +		{PBC_CONTROL, 0}, +		{FLASH_START_ADDR, CMT_LUT_0_START_ADDR}, +		{FLASH_READ_BYTES, CMT_LUT_0_SIZE}, +		{CMT_SPLASH_LUT_START_ADDR, 0}, +		{CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL}, +		{PBC_CONTROL, 1}, +	}; + +	static const struct picodlp_i2c_command init_cmd_set2[] = { +		{PBC_CONTROL, 0}, +		{CMT_SPLASH_LUT_DEST_SELECT, 0}, +		{PBC_CONTROL, 0}, +		{FLASH_START_ADDR, SEQUENCE_0_START_ADDR}, +		{FLASH_READ_BYTES, SEQUENCE_0_SIZE}, +		{SEQ_RESET_LUT_START_ADDR, 0}, +		{SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT}, +		{PBC_CONTROL, 1}, +	}; + +	static const struct picodlp_i2c_command init_cmd_set3[] = { +		{PBC_CONTROL, 0}, +		{SEQ_RESET_LUT_DEST_SELECT, 0}, +		{PBC_CONTROL, 0}, +		{FLASH_START_ADDR, DRC_TABLE_0_START_ADDR}, +		{FLASH_READ_BYTES, DRC_TABLE_0_SIZE}, +		{SEQ_RESET_LUT_START_ADDR, 0}, +		{SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL}, +		{PBC_CONTROL, 1}, +	}; + +	static const struct picodlp_i2c_command init_cmd_set4[] = { +		{PBC_CONTROL, 0}, +		{SEQ_RESET_LUT_DEST_SELECT, 0}, +		{SDC_ENABLE, 1}, +		{AGC_CTRL, 7}, +		{CCA_C1A, 0x100}, +		{CCA_C1B, 0x0}, +		{CCA_C1C, 0x0}, +		{CCA_C2A, 0x0}, +		{CCA_C2B, 0x100}, +		{CCA_C2C, 0x0}, +		{CCA_C3A, 0x0}, +		{CCA_C3B, 0x0}, +		{CCA_C3C, 0x100}, +		{CCA_C7A, 0x100}, +		{CCA_C7B, 0x100}, +		{CCA_C7C, 0x100}, +		{CCA_ENABLE, 1}, +		{CPU_IF_MODE, 1}, +		{SHORT_FLIP, 1}, +		{CURTAIN_CONTROL, 0}, +		{DMD_PARK_TRIGGER, 0}, +		{R_DRIVE_CURRENT, 0x298}, +		{G_DRIVE_CURRENT, 0x298}, +		{B_DRIVE_CURRENT, 0x298}, +		{RGB_DRIVER_ENABLE, 7}, +		{SEQ_CONTROL, 0}, +		{ACTGEN_CONTROL, 0x10}, +		{SEQUENCE_MODE, SEQ_LOCK}, +		{DATA_FORMAT, RGB888}, +		{INPUT_RESOLUTION, WVGA_864_LANDSCAPE}, +		{INPUT_SOURCE, PARALLEL_RGB}, +		{CPU_IF_SYNC_METHOD, 1}, +		{SEQ_CONTROL, 1} +	}; + +	r = picodlp_i2c_write_array(client, init_cmd_set1, +						ARRAY_SIZE(init_cmd_set1)); +	if (r) +		return r; + +	r = picodlp_wait_for_dma_done(client); +	if (r) +		return r; + +	r = picodlp_i2c_write_array(client, init_cmd_set2, +					ARRAY_SIZE(init_cmd_set2)); +	if (r) +		return r; + +	r = picodlp_wait_for_dma_done(client); +	if (r) +		return r; + +	r = picodlp_i2c_write_array(client, init_cmd_set3, +					ARRAY_SIZE(init_cmd_set3)); +	if (r) +		return r; + +	r = picodlp_wait_for_dma_done(client); +	if (r) +		return r; + +	r = picodlp_i2c_write_array(client, init_cmd_set4, +					ARRAY_SIZE(init_cmd_set4)); +	if (r) +		return r; + +	return 0; +} + +static int picodlp_i2c_probe(struct i2c_client *client, +		const struct i2c_device_id *id) +{ +	struct picodlp_i2c_data *picodlp_i2c_data; + +	picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL); + +	if (!picodlp_i2c_data) +		return -ENOMEM; + +	mutex_init(&picodlp_i2c_data->xfer_lock); +	i2c_set_clientdata(client, picodlp_i2c_data); + +	return 0; +} + +static int picodlp_i2c_remove(struct i2c_client *client) +{ +	struct picodlp_i2c_data *picodlp_i2c_data = +					i2c_get_clientdata(client); +	kfree(picodlp_i2c_data); +	return 0; +} + +static struct i2c_driver picodlp_i2c_driver = { +	.driver = { +		.name	= "picodlp_i2c_driver", +	}, +	.probe		= picodlp_i2c_probe, +	.remove		= picodlp_i2c_remove, +	.id_table	= picodlp_i2c_id, +}; + +static int picodlp_panel_power_on(struct omap_dss_device *dssdev) +{ +	int r, trial = 100; +	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); +	struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); + +	if (dssdev->platform_enable) { +		r = dssdev->platform_enable(dssdev); +		if (r) +			return r; +	} + +	gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); +	msleep(1); +	gpio_set_value(picodlp_pdata->pwrgood_gpio, 1); + +	while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) { +		if (!trial--) { +			dev_err(&dssdev->dev, "emu_done signal not" +						" going high\n"); +			return -ETIMEDOUT; +		} +		msleep(5); +	} +	/* +	 * As per dpp2600 programming guide, +	 * it is required to sleep for 1000ms after emu_done signal goes high +	 * then only i2c commands can be successfully sent to dpp2600 +	 */ +	msleep(1000); +	r = omapdss_dpi_display_enable(dssdev); +	if (r) { +		dev_err(&dssdev->dev, "failed to enable DPI\n"); +		goto err1; +	} + +	r = picodlp_i2c_init(picod->picodlp_i2c_client); +	if (r) +		goto err; + +	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +	return r; +err: +	omapdss_dpi_display_disable(dssdev); +err1: +	if (dssdev->platform_disable) +		dssdev->platform_disable(dssdev); + +	return r; +} + +static void picodlp_panel_power_off(struct omap_dss_device *dssdev) +{ +	struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); + +	omapdss_dpi_display_disable(dssdev); + +	gpio_set_value(picodlp_pdata->emu_done_gpio, 0); +	gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); + +	if (dssdev->platform_disable) +		dssdev->platform_disable(dssdev); +} + +static int picodlp_panel_probe(struct omap_dss_device *dssdev) +{ +	struct picodlp_data *picod; +	struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); +	struct i2c_adapter *adapter; +	struct i2c_client *picodlp_i2c_client; +	int r = 0, picodlp_adapter_id; + +	dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF | +				OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS; +	dssdev->panel.acb = 0x0; +	dssdev->panel.timings = pico_ls_timings; + +	picod =  kzalloc(sizeof(struct picodlp_data), GFP_KERNEL); +	if (!picod) +		return -ENOMEM; + +	mutex_init(&picod->lock); + +	picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id; + +	adapter = i2c_get_adapter(picodlp_adapter_id); +	if (!adapter) { +		dev_err(&dssdev->dev, "can't get i2c adapter\n"); +		r = -ENODEV; +		goto err; +	} + +	picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info); +	if (!picodlp_i2c_client) { +		dev_err(&dssdev->dev, "can't add i2c device::" +					 " picodlp_i2c_client is NULL\n"); +		r = -ENODEV; +		goto err; +	} + +	picod->picodlp_i2c_client = picodlp_i2c_client; + +	dev_set_drvdata(&dssdev->dev, picod); +	return r; +err: +	kfree(picod); +	return r; +} + +static void picodlp_panel_remove(struct omap_dss_device *dssdev) +{ +	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); + +	i2c_unregister_device(picod->picodlp_i2c_client); +	dev_set_drvdata(&dssdev->dev, NULL); +	dev_dbg(&dssdev->dev, "removing picodlp panel\n"); + +	kfree(picod); +} + +static int picodlp_panel_enable(struct omap_dss_device *dssdev) +{ +	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); +	int r; + +	dev_dbg(&dssdev->dev, "enabling picodlp panel\n"); + +	mutex_lock(&picod->lock); +	if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { +		mutex_unlock(&picod->lock); +		return -EINVAL; +	} + +	r = picodlp_panel_power_on(dssdev); +	mutex_unlock(&picod->lock); + +	return r; +} + +static void picodlp_panel_disable(struct omap_dss_device *dssdev) +{ +	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&picod->lock); +	/* Turn off DLP Power */ +	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) +		picodlp_panel_power_off(dssdev); + +	dssdev->state = OMAP_DSS_DISPLAY_DISABLED; +	mutex_unlock(&picod->lock); + +	dev_dbg(&dssdev->dev, "disabling picodlp panel\n"); +} + +static int picodlp_panel_suspend(struct omap_dss_device *dssdev) +{ +	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&picod->lock); +	/* Turn off DLP Power */ +	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { +		mutex_unlock(&picod->lock); +		dev_err(&dssdev->dev, "unable to suspend picodlp panel," +					" panel is not ACTIVE\n"); +		return -EINVAL; +	} + +	picodlp_panel_power_off(dssdev); + +	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; +	mutex_unlock(&picod->lock); + +	dev_dbg(&dssdev->dev, "suspending picodlp panel\n"); +	return 0; +} + +static int picodlp_panel_resume(struct omap_dss_device *dssdev) +{ +	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); +	int r; + +	mutex_lock(&picod->lock); +	if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { +		mutex_unlock(&picod->lock); +		dev_err(&dssdev->dev, "unable to resume picodlp panel," +			" panel is not ACTIVE\n"); +		return -EINVAL; +	} + +	r = picodlp_panel_power_on(dssdev); +	mutex_unlock(&picod->lock); +	dev_dbg(&dssdev->dev, "resuming picodlp panel\n"); +	return r; +} + +static void picodlp_get_resolution(struct omap_dss_device *dssdev, +					u16 *xres, u16 *yres) +{ +	*xres = dssdev->panel.timings.x_res; +	*yres = dssdev->panel.timings.y_res; +} + +static struct omap_dss_driver picodlp_driver = { +	.probe		= picodlp_panel_probe, +	.remove		= picodlp_panel_remove, + +	.enable		= picodlp_panel_enable, +	.disable	= picodlp_panel_disable, + +	.get_resolution	= picodlp_get_resolution, + +	.suspend	= picodlp_panel_suspend, +	.resume		= picodlp_panel_resume, + +	.driver		= { +		.name	= "picodlp_panel", +		.owner	= THIS_MODULE, +	}, +}; + +static int __init picodlp_init(void) +{ +	int r = 0; + +	r = i2c_add_driver(&picodlp_i2c_driver); +	if (r) { +		printk(KERN_WARNING "picodlp_i2c_driver" \ +			" registration failed\n"); +		return r; +	} + +	r = omap_dss_register_driver(&picodlp_driver); +	if (r) +		i2c_del_driver(&picodlp_i2c_driver); + +	return r; +} + +static void __exit picodlp_exit(void) +{ +	i2c_del_driver(&picodlp_i2c_driver); +	omap_dss_unregister_driver(&picodlp_driver); +} + +module_init(picodlp_init); +module_exit(picodlp_exit); + +MODULE_AUTHOR("Mythri P K <mythripk@ti.com>"); +MODULE_DESCRIPTION("picodlp driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h new file mode 100644 index 00000000000..a34b431a726 --- /dev/null +++ b/drivers/video/omap2/displays/panel-picodlp.h @@ -0,0 +1,288 @@ +/* + * Header file required by picodlp panel driver + * + * Copyright (C) 2009-2011 Texas Instruments + * Author: Mythri P K <mythripk@ti.com> + * + * 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 <http://www.gnu.org/licenses/>. +*/ + +#ifndef __OMAP2_DISPLAY_PANEL_PICODLP_H +#define __OMAP2_DISPLAY_PANEL_PICODLP_H + +/* Commands used for configuring picodlp panel */ + +#define MAIN_STATUS			0x03 +#define PBC_CONTROL			0x08 +#define INPUT_SOURCE			0x0B +#define INPUT_RESOLUTION		0x0C +#define DATA_FORMAT			0x0D +#define IMG_ROTATION			0x0E +#define LONG_FLIP			0x0F +#define SHORT_FLIP			0x10 +#define TEST_PAT_SELECT			0x11 +#define R_DRIVE_CURRENT			0x12 +#define G_DRIVE_CURRENT			0x13 +#define B_DRIVE_CURRENT			0x14 +#define READ_REG_SELECT			0x15 +#define RGB_DRIVER_ENABLE		0x16 + +#define CPU_IF_MODE			0x18 +#define FRAME_RATE			0x19 +#define CPU_IF_SYNC_METHOD		0x1A +#define CPU_IF_SOF			0x1B +#define CPU_IF_EOF			0x1C +#define CPU_IF_SLEEP			0x1D + +#define SEQUENCE_MODE			0x1E +#define SOFT_RESET			0x1F +#define FRONT_END_RESET			0x21 +#define AUTO_PWR_ENABLE			0x22 + +#define VSYNC_LINE_DELAY		0x23 +#define CPU_PI_HORIZ_START		0x24 +#define CPU_PI_VERT_START		0x25 +#define CPU_PI_HORIZ_WIDTH		0x26 +#define CPU_PI_VERT_HEIGHT		0x27 + +#define PIXEL_MASK_CROP			0x28 +#define CROP_FIRST_LINE			0x29 +#define CROP_LAST_LINE			0x2A +#define CROP_FIRST_PIXEL		0x2B +#define CROP_LAST_PIXEL			0x2C +#define DMD_PARK_TRIGGER		0x2D + +#define MISC_REG			0x30 + +/* AGC registers */ +#define AGC_CTRL			0x50 +#define AGC_CLIPPED_PIXS		0x55 +#define AGC_BRIGHT_PIXS			0x56 +#define AGC_BG_PIXS			0x57 +#define AGC_SAFETY_MARGIN		0x17 + +/* Color Coordinate Adjustment registers */ +#define CCA_ENABLE		0x5E +#define CCA_C1A			0x5F +#define CCA_C1B			0x60 +#define CCA_C1C			0x61 +#define CCA_C2A			0x62 +#define CCA_C2B			0x63 +#define CCA_C2C			0x64 +#define CCA_C3A			0x65 +#define CCA_C3B			0x66 +#define CCA_C3C			0x67 +#define CCA_C7A			0x71 +#define CCA_C7B			0x72 +#define CCA_C7C			0x73 + +/** + * DLP Pico Processor 2600 comes with flash + * We can do DMA operations from flash for accessing Look Up Tables + */ +#define DMA_STATUS			0x100 +#define FLASH_ADDR_BYTES		0x74 +#define FLASH_DUMMY_BYTES		0x75 +#define FLASH_WRITE_BYTES		0x76 +#define FLASH_READ_BYTES		0x77 +#define FLASH_OPCODE			0x78 +#define FLASH_START_ADDR		0x79 +#define FLASH_DUMMY2			0x7A +#define FLASH_WRITE_DATA		0x7B + +#define TEMPORAL_DITH_DISABLE		0x7E +#define SEQ_CONTROL			0x82 +#define SEQ_VECTOR			0x83 + +/* DMD is Digital Micromirror Device */ +#define DMD_BLOCK_COUNT			0x84 +#define DMD_VCC_CONTROL			0x86 +#define DMD_PARK_PULSE_COUNT		0x87 +#define DMD_PARK_PULSE_WIDTH		0x88 +#define DMD_PARK_DELAY			0x89 +#define DMD_SHADOW_ENABLE		0x8E +#define SEQ_STATUS			0x8F +#define FLASH_CLOCK_CONTROL		0x98 +#define DMD_PARK			0x2D + +#define SDRAM_BIST_ENABLE		0x46 +#define DDR_DRIVER_STRENGTH		0x9A +#define SDC_ENABLE			0x9D +#define SDC_BUFF_SWAP_DISABLE		0xA3 +#define CURTAIN_CONTROL			0xA6 +#define DDR_BUS_SWAP_ENABLE		0xA7 +#define DMD_TRC_ENABLE			0xA8 +#define DMD_BUS_SWAP_ENABLE		0xA9 + +#define ACTGEN_ENABLE			0xAE +#define ACTGEN_CONTROL			0xAF +#define ACTGEN_HORIZ_BP			0xB0 +#define ACTGEN_VERT_BP			0xB1 + +/* Look Up Table access */ +#define CMT_SPLASH_LUT_START_ADDR	0xFA +#define CMT_SPLASH_LUT_DEST_SELECT	0xFB +#define CMT_SPLASH_LUT_DATA		0xFC +#define SEQ_RESET_LUT_START_ADDR	0xFD +#define SEQ_RESET_LUT_DEST_SELECT	0xFE +#define SEQ_RESET_LUT_DATA		0xFF + +/* Input source definitions */ +#define PARALLEL_RGB		0 +#define INT_TEST_PATTERN	1 +#define SPLASH_SCREEN		2 +#define CPU_INTF		3 +#define BT656			4 + +/* Standard input resolution definitions */ +#define QWVGA_LANDSCAPE		3	/* (427h*240v) */ +#define WVGA_864_LANDSCAPE	21	/* (864h*480v) */ +#define WVGA_DMD_OPTICAL_TEST	35	/* (608h*684v) */ + +/* Standard data format definitions */ +#define RGB565			0 +#define RGB666			1 +#define RGB888			2 + +/* Test Pattern definitions */ +#define TPG_CHECKERBOARD	0 +#define TPG_BLACK		1 +#define TPG_WHITE		2 +#define TPG_RED			3 +#define TPG_BLUE		4 +#define TPG_GREEN		5 +#define TPG_VLINES_BLACK	6 +#define TPG_HLINES_BLACK	7 +#define TPG_VLINES_ALT		8 +#define TPG_HLINES_ALT		9 +#define TPG_DIAG_LINES		10 +#define TPG_GREYRAMP_VERT	11 +#define TPG_GREYRAMP_HORIZ	12 +#define TPG_ANSI_CHECKERBOARD	13 + +/* sequence mode definitions */ +#define SEQ_FREE_RUN		0 +#define SEQ_LOCK		1 + +/* curtain color definitions */ +#define CURTAIN_BLACK		0 +#define CURTAIN_RED		1 +#define CURTAIN_GREEN		2 +#define CURTAIN_BLUE		3 +#define CURTAIN_YELLOW		4 +#define CURTAIN_MAGENTA		5 +#define CURTAIN_CYAN		6 +#define CURTAIN_WHITE		7 + +/* LUT definitions */ +#define CMT_LUT_NONE		0 +#define CMT_LUT_GREEN		1 +#define CMT_LUT_RED		2 +#define CMT_LUT_BLUE		3 +#define CMT_LUT_ALL		4 +#define SPLASH_LUT		5 + +#define SEQ_LUT_NONE		0 +#define SEQ_DRC_LUT_0		1 +#define SEQ_DRC_LUT_1		2 +#define SEQ_DRC_LUT_2		3 +#define SEQ_DRC_LUT_3		4 +#define SEQ_SEQ_LUT		5 +#define SEQ_DRC_LUT_ALL		6 +#define WPC_PROGRAM_LUT		7 + +#define BITSTREAM_START_ADDR		0x00000000 +#define BITSTREAM_SIZE			0x00040000 + +#define WPC_FW_0_START_ADDR		0x00040000 +#define WPC_FW_0_SIZE			0x00000ce8 + +#define SEQUENCE_0_START_ADDR		0x00044000 +#define SEQUENCE_0_SIZE			0x00001000 + +#define SEQUENCE_1_START_ADDR		0x00045000 +#define SEQUENCE_1_SIZE			0x00000d10 + +#define SEQUENCE_2_START_ADDR		0x00046000 +#define SEQUENCE_2_SIZE			0x00000d10 + +#define SEQUENCE_3_START_ADDR		0x00047000 +#define SEQUENCE_3_SIZE			0x00000d10 + +#define SEQUENCE_4_START_ADDR		0x00048000 +#define SEQUENCE_4_SIZE			0x00000d10 + +#define SEQUENCE_5_START_ADDR		0x00049000 +#define SEQUENCE_5_SIZE			0x00000d10 + +#define SEQUENCE_6_START_ADDR		0x0004a000 +#define SEQUENCE_6_SIZE			0x00000d10 + +#define CMT_LUT_0_START_ADDR		0x0004b200 +#define CMT_LUT_0_SIZE			0x00000600 + +#define CMT_LUT_1_START_ADDR		0x0004b800 +#define CMT_LUT_1_SIZE			0x00000600 + +#define CMT_LUT_2_START_ADDR		0x0004be00 +#define CMT_LUT_2_SIZE			0x00000600 + +#define CMT_LUT_3_START_ADDR		0x0004c400 +#define CMT_LUT_3_SIZE			0x00000600 + +#define CMT_LUT_4_START_ADDR		0x0004ca00 +#define CMT_LUT_4_SIZE			0x00000600 + +#define CMT_LUT_5_START_ADDR		0x0004d000 +#define CMT_LUT_5_SIZE			0x00000600 + +#define CMT_LUT_6_START_ADDR		0x0004d600 +#define CMT_LUT_6_SIZE			0x00000600 + +#define DRC_TABLE_0_START_ADDR		0x0004dc00 +#define DRC_TABLE_0_SIZE		0x00000100 + +#define SPLASH_0_START_ADDR		0x0004dd00 +#define SPLASH_0_SIZE			0x00032280 + +#define SEQUENCE_7_START_ADDR		0x00080000 +#define SEQUENCE_7_SIZE			0x00000d10 + +#define SEQUENCE_8_START_ADDR		0x00081800 +#define SEQUENCE_8_SIZE			0x00000d10 + +#define SEQUENCE_9_START_ADDR		0x00083000 +#define SEQUENCE_9_SIZE			0x00000d10 + +#define CMT_LUT_7_START_ADDR		0x0008e000 +#define CMT_LUT_7_SIZE			0x00000600 + +#define CMT_LUT_8_START_ADDR		0x0008e800 +#define CMT_LUT_8_SIZE			0x00000600 + +#define CMT_LUT_9_START_ADDR		0x0008f000 +#define CMT_LUT_9_SIZE			0x00000600 + +#define SPLASH_1_START_ADDR		0x0009a000 +#define SPLASH_1_SIZE			0x00032280 + +#define SPLASH_2_START_ADDR		0x000cd000 +#define SPLASH_2_SIZE			0x00032280 + +#define SPLASH_3_START_ADDR		0x00100000 +#define SPLASH_3_SIZE			0x00032280 + +#define OPT_SPLASH_0_START_ADDR		0x00134000 +#define OPT_SPLASH_0_SIZE		0x000cb100 + +#endif diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 4e888ac09b3..7f91002cc3b 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -35,26 +35,12 @@  #include <video/omapdss.h>  #include <video/omap-panel-nokia-dsi.h> +#include <video/mipi_display.h>  /* DSI Virtual channel. Hardcoded for now. */  #define TCH 0  #define DCS_READ_NUM_ERRORS	0x05 -#define DCS_READ_POWER_MODE	0x0a -#define DCS_READ_MADCTL		0x0b -#define DCS_READ_PIXEL_FORMAT	0x0c -#define DCS_RDDSDR		0x0f -#define DCS_SLEEP_IN		0x10 -#define DCS_SLEEP_OUT		0x11 -#define DCS_DISPLAY_OFF		0x28 -#define DCS_DISPLAY_ON		0x29 -#define DCS_COLUMN_ADDR		0x2a -#define DCS_PAGE_ADDR		0x2b -#define DCS_MEMORY_WRITE	0x2c -#define DCS_TEAR_OFF		0x34 -#define DCS_TEAR_ON		0x35 -#define DCS_MEM_ACC_CTRL	0x36 -#define DCS_PIXEL_FORMAT	0x3a  #define DCS_BRIGHTNESS		0x51  #define DCS_CTRL_DISPLAY	0x53  #define DCS_WRITE_CABC		0x55 @@ -222,8 +208,6 @@ struct taal_data {  	struct delayed_work te_timeout_work; -	bool use_dsi_bl; -  	bool cabc_broken;  	unsigned cabc_mode; @@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td)  	hw_guard_wait(td); -	cmd = DCS_SLEEP_IN; +	cmd = MIPI_DCS_ENTER_SLEEP_MODE;  	r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);  	if (r)  		return r; @@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td)  	hw_guard_wait(td); -	r = taal_dcs_write_0(td, DCS_SLEEP_OUT); +	r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE);  	if (r)  		return r; @@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)  	u8 mode;  	int b5, b6, b7; -	r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode); +	r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);  	if (r)  		return r; @@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)  	mode &= ~((1<<7) | (1<<6) | (1<<5));  	mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); -	return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode); +	return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);  }  static int taal_set_update_window(struct taal_data *td, @@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td,  	u16 y2 = y + h - 1;  	u8 buf[5]; -	buf[0] = DCS_COLUMN_ADDR; +	buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;  	buf[1] = (x1 >> 8) & 0xff;  	buf[2] = (x1 >> 0) & 0xff;  	buf[3] = (x2 >> 8) & 0xff; @@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td,  	if (r)  		return r; -	buf[0] = DCS_PAGE_ADDR; +	buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;  	buf[1] = (y1 >> 8) & 0xff;  	buf[2] = (y1 >> 0) & 0xff;  	buf[3] = (y2 >> 8) & 0xff; @@ -555,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev)  {  	struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);  	struct taal_data *td = dev_get_drvdata(&dssdev->dev); -	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);  	int r;  	int level; @@ -569,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev)  	mutex_lock(&td->lock); -	if (td->use_dsi_bl) { -		if (td->enabled) { -			dsi_bus_lock(dssdev); +	if (td->enabled) { +		dsi_bus_lock(dssdev); -			r = taal_wake_up(dssdev); -			if (!r) -				r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); +		r = taal_wake_up(dssdev); +		if (!r) +			r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); -			dsi_bus_unlock(dssdev); -		} else { -			r = 0; -		} +		dsi_bus_unlock(dssdev);  	} else { -		if (!panel_data->set_backlight) -			r = -EINVAL; -		else -			r = panel_data->set_backlight(dssdev, level); +		r = 0;  	}  	mutex_unlock(&td->lock); @@ -964,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev)  {  	struct backlight_properties props;  	struct taal_data *td; -	struct backlight_device *bldev; +	struct backlight_device *bldev = NULL;  	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);  	struct panel_config *panel_config = NULL;  	int r, i; @@ -990,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev)  	dssdev->panel.config = OMAP_DSS_LCD_TFT;  	dssdev->panel.timings = panel_config->timings; -	dssdev->ctrl.pixel_size = 24; +	dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;  	td = kzalloc(sizeof(*td), GFP_KERNEL);  	if (!td) { @@ -1025,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev)  	taal_hw_reset(dssdev); -	/* if no platform set_backlight() defined, presume DSI backlight -	 * control */ -	memset(&props, 0, sizeof(struct backlight_properties)); -	if (!panel_data->set_backlight) -		td->use_dsi_bl = true; - -	if (td->use_dsi_bl) +	if (panel_data->use_dsi_backlight) { +		memset(&props, 0, sizeof(struct backlight_properties));  		props.max_brightness = 255; -	else -		props.max_brightness = 127; -	props.type = BACKLIGHT_RAW; -	bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, -					dssdev, &taal_bl_ops, &props); -	if (IS_ERR(bldev)) { -		r = PTR_ERR(bldev); -		goto err_bl; -	} +		props.type = BACKLIGHT_RAW; +		bldev = backlight_device_register(dev_name(&dssdev->dev), +				&dssdev->dev, dssdev, &taal_bl_ops, &props); +		if (IS_ERR(bldev)) { +			r = PTR_ERR(bldev); +			goto err_bl; +		} -	td->bldev = bldev; +		td->bldev = bldev; -	bldev->props.fb_blank = FB_BLANK_UNBLANK; -	bldev->props.power = FB_BLANK_UNBLANK; -	if (td->use_dsi_bl) +		bldev->props.fb_blank = FB_BLANK_UNBLANK; +		bldev->props.power = FB_BLANK_UNBLANK;  		bldev->props.brightness = 255; -	else -		bldev->props.brightness = 127; -	taal_bl_update_status(bldev); +		taal_bl_update_status(bldev); +	}  	if (panel_data->use_ext_te) {  		int gpio = panel_data->ext_te_gpio; @@ -1111,7 +1078,8 @@ err_irq:  	if (panel_data->use_ext_te)  		gpio_free(panel_data->ext_te_gpio);  err_gpio: -	backlight_device_unregister(bldev); +	if (bldev != NULL) +		backlight_device_unregister(bldev);  err_bl:  	destroy_workqueue(td->workqueue);  err_wq: @@ -1140,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)  	}  	bldev = td->bldev; -	bldev->props.power = FB_BLANK_POWERDOWN; -	taal_bl_update_status(bldev); -	backlight_device_unregister(bldev); +	if (bldev != NULL) { +		bldev->props.power = FB_BLANK_POWERDOWN; +		taal_bl_update_status(bldev); +		backlight_device_unregister(bldev); +	}  	taal_cancel_ulps_work(dssdev);  	taal_cancel_esd_work(dssdev); @@ -1195,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)  	if (r)  		goto err; -	r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ +	r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT, +		MIPI_DCS_PIXEL_FMT_24BIT);  	if (r)  		goto err; @@ -1209,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)  			goto err;  	} -	r = taal_dcs_write_0(td, DCS_DISPLAY_ON); +	r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON);  	if (r)  		goto err; @@ -1246,7 +1217,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)  	struct taal_data *td = dev_get_drvdata(&dssdev->dev);  	int r; -	r = taal_dcs_write_0(td, DCS_DISPLAY_OFF); +	r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);  	if (!r)  		r = taal_sleep_in(td); @@ -1529,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)  	int r;  	if (enable) -		r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); +		r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);  	else -		r = taal_dcs_write_0(td, DCS_TEAR_OFF); +		r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);  	if (!panel_data->use_ext_te)  		omapdss_dsi_enable_te(dssdev, enable); @@ -1851,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work)  		goto err;  	} -	r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); +	r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1);  	if (r) {  		dev_err(&dssdev->dev, "failed to read Taal status\n");  		goto err; @@ -1864,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work)  		goto err;  	} -	r = taal_dcs_read_1(td, DCS_RDDSDR, &state2); +	r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2);  	if (r) {  		dev_err(&dssdev->dev, "failed to read Taal status\n");  		goto err; @@ -1880,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work)  	/* Self-diagnostics result is also shown on TE GPIO line. We need  	 * to re-enable TE after self diagnostics */  	if (td->te_enabled && panel_data->use_ext_te) { -		r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); +		r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);  		if (r)  			goto err;  	} diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 0d12524db14..7be7c06a249 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -1,5 +1,5 @@  menuconfig OMAP2_DSS -        tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)" +        tristate "OMAP2+ Display Subsystem support"          depends on ARCH_OMAP2PLUS          help  	  OMAP2+ Display Subsystem support. diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 10d9d3bb3e2..bd34ac5b202 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -6,4 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o  omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o  omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o  omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ -				    hdmi_omap4_panel.o +				    hdmi_panel.o ti_hdmi_4xxx_ip.o diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 76821fefce9..86ec12e16c7 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -145,6 +145,10 @@ static int dss_initialize_debugfs(void)  	debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,  			&venc_dump_regs, &dss_debug_fops);  #endif +#ifdef CONFIG_OMAP4_DSS_HDMI +	debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir, +			&hdmi_dump_regs, &dss_debug_fops); +#endif  	return 0;  } diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 0f3961a1ce2..6892cfd2e3b 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -106,7 +106,7 @@ static struct {  	int irq;  	struct clk *dss_clk; -	u32	fifo_size[3]; +	u32	fifo_size[MAX_DSS_OVERLAYS];  	spinlock_t irq_lock;  	u32 irq_error_mask; @@ -171,172 +171,98 @@ static int dispc_get_ctx_loss_count(void)  static void dispc_save_context(void)  { -	int i; +	int i, j;  	DSSDBG("dispc_save_context\n");  	SR(IRQENABLE);  	SR(CONTROL);  	SR(CONFIG); -	SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); -	SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); -	SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); -	SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));  	SR(LINE_NUMBER); -	SR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); -	SR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); -	SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); -	SR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); -	if (dss_has_feature(FEAT_GLOBAL_ALPHA)) +	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || +			dss_has_feature(FEAT_ALPHA_FREE_ZORDER))  		SR(GLOBAL_ALPHA); -	SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); -	SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));  	if (dss_has_feature(FEAT_MGR_LCD2)) {  		SR(CONTROL2); -		SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); -		SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); -		SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); -		SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); -		SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); -		SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); -		SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));  		SR(CONFIG2);  	} -	SR(OVL_BA0(OMAP_DSS_GFX)); -	SR(OVL_BA1(OMAP_DSS_GFX)); -	SR(OVL_POSITION(OMAP_DSS_GFX)); -	SR(OVL_SIZE(OMAP_DSS_GFX)); -	SR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); -	SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); -	SR(OVL_ROW_INC(OMAP_DSS_GFX)); -	SR(OVL_PIXEL_INC(OMAP_DSS_GFX)); -	SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); -	SR(OVL_TABLE_BA(OMAP_DSS_GFX)); +	for (i = 0; i < dss_feat_get_num_mgrs(); i++) { +		SR(DEFAULT_COLOR(i)); +		SR(TRANS_COLOR(i)); +		SR(SIZE_MGR(i)); +		if (i == OMAP_DSS_CHANNEL_DIGIT) +			continue; +		SR(TIMING_H(i)); +		SR(TIMING_V(i)); +		SR(POL_FREQ(i)); +		SR(DIVISORo(i)); -	SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); -	SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); -	SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); +		SR(DATA_CYCLE1(i)); +		SR(DATA_CYCLE2(i)); +		SR(DATA_CYCLE3(i)); -	if (dss_has_feature(FEAT_CPR)) { -		SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); -		SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); -		SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); -	} -	if (dss_has_feature(FEAT_MGR_LCD2)) {  		if (dss_has_feature(FEAT_CPR)) { -			SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); -			SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); -			SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); +			SR(CPR_COEF_R(i)); +			SR(CPR_COEF_G(i)); +			SR(CPR_COEF_B(i));  		} - -		SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); -		SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); -		SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));  	} -	if (dss_has_feature(FEAT_PRELOAD)) -		SR(OVL_PRELOAD(OMAP_DSS_GFX)); - -	/* VID1 */ -	SR(OVL_BA0(OMAP_DSS_VIDEO1)); -	SR(OVL_BA1(OMAP_DSS_VIDEO1)); -	SR(OVL_POSITION(OMAP_DSS_VIDEO1)); -	SR(OVL_SIZE(OMAP_DSS_VIDEO1)); -	SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); -	SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); -	SR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); -	SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); -	SR(OVL_FIR(OMAP_DSS_VIDEO1)); -	SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); -	SR(OVL_ACCU0(OMAP_DSS_VIDEO1)); -	SR(OVL_ACCU1(OMAP_DSS_VIDEO1)); - -	for (i = 0; i < 8; i++) -		SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); - -	for (i = 0; i < 8; i++) -		SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); - -	for (i = 0; i < 5; i++) -		SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); - -	if (dss_has_feature(FEAT_FIR_COEF_V)) { -		for (i = 0; i < 8; i++) -			SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); -	} - -	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { -		SR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); -		SR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); -		SR(OVL_FIR2(OMAP_DSS_VIDEO1)); -		SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); -		SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); - -		for (i = 0; i < 8; i++) -			SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); - -		for (i = 0; i < 8; i++) -			SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); - -		for (i = 0; i < 8; i++) -			SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); -	} -	if (dss_has_feature(FEAT_ATTR2)) -		SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); - -	if (dss_has_feature(FEAT_PRELOAD)) -		SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); - -	/* VID2 */ -	SR(OVL_BA0(OMAP_DSS_VIDEO2)); -	SR(OVL_BA1(OMAP_DSS_VIDEO2)); -	SR(OVL_POSITION(OMAP_DSS_VIDEO2)); -	SR(OVL_SIZE(OMAP_DSS_VIDEO2)); -	SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); -	SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); -	SR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); -	SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); -	SR(OVL_FIR(OMAP_DSS_VIDEO2)); -	SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); -	SR(OVL_ACCU0(OMAP_DSS_VIDEO2)); -	SR(OVL_ACCU1(OMAP_DSS_VIDEO2)); +	for (i = 0; i < dss_feat_get_num_ovls(); i++) { +		SR(OVL_BA0(i)); +		SR(OVL_BA1(i)); +		SR(OVL_POSITION(i)); +		SR(OVL_SIZE(i)); +		SR(OVL_ATTRIBUTES(i)); +		SR(OVL_FIFO_THRESHOLD(i)); +		SR(OVL_ROW_INC(i)); +		SR(OVL_PIXEL_INC(i)); +		if (dss_has_feature(FEAT_PRELOAD)) +			SR(OVL_PRELOAD(i)); +		if (i == OMAP_DSS_GFX) { +			SR(OVL_WINDOW_SKIP(i)); +			SR(OVL_TABLE_BA(i)); +			continue; +		} +		SR(OVL_FIR(i)); +		SR(OVL_PICTURE_SIZE(i)); +		SR(OVL_ACCU0(i)); +		SR(OVL_ACCU1(i)); -	for (i = 0; i < 8; i++) -		SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); +		for (j = 0; j < 8; j++) +			SR(OVL_FIR_COEF_H(i, j)); -	for (i = 0; i < 8; i++) -		SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); +		for (j = 0; j < 8; j++) +			SR(OVL_FIR_COEF_HV(i, j)); -	for (i = 0; i < 5; i++) -		SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); +		for (j = 0; j < 5; j++) +			SR(OVL_CONV_COEF(i, j)); -	if (dss_has_feature(FEAT_FIR_COEF_V)) { -		for (i = 0; i < 8; i++) -			SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); -	} +		if (dss_has_feature(FEAT_FIR_COEF_V)) { +			for (j = 0; j < 8; j++) +				SR(OVL_FIR_COEF_V(i, j)); +		} -	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { -		SR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); -		SR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); -		SR(OVL_FIR2(OMAP_DSS_VIDEO2)); -		SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); -		SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); +		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { +			SR(OVL_BA0_UV(i)); +			SR(OVL_BA1_UV(i)); +			SR(OVL_FIR2(i)); +			SR(OVL_ACCU2_0(i)); +			SR(OVL_ACCU2_1(i)); -		for (i = 0; i < 8; i++) -			SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); +			for (j = 0; j < 8; j++) +				SR(OVL_FIR_COEF_H2(i, j)); -		for (i = 0; i < 8; i++) -			SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); +			for (j = 0; j < 8; j++) +				SR(OVL_FIR_COEF_HV2(i, j)); -		for (i = 0; i < 8; i++) -			SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); +			for (j = 0; j < 8; j++) +				SR(OVL_FIR_COEF_V2(i, j)); +		} +		if (dss_has_feature(FEAT_ATTR2)) +			SR(OVL_ATTRIBUTES2(i));  	} -	if (dss_has_feature(FEAT_ATTR2)) -		SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); - -	if (dss_has_feature(FEAT_PRELOAD)) -		SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));  	if (dss_has_feature(FEAT_CORE_CLK_DIV))  		SR(DIVISOR); @@ -349,7 +275,7 @@ static void dispc_save_context(void)  static void dispc_restore_context(void)  { -	int i, ctx; +	int i, j, ctx;  	DSSDBG("dispc_restore_context\n"); @@ -367,165 +293,89 @@ static void dispc_restore_context(void)  	/*RR(IRQENABLE);*/  	/*RR(CONTROL);*/  	RR(CONFIG); -	RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); -	RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); -	RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); -	RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));  	RR(LINE_NUMBER); -	RR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); -	RR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); -	RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); -	RR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); -	if (dss_has_feature(FEAT_GLOBAL_ALPHA)) +	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || +			dss_has_feature(FEAT_ALPHA_FREE_ZORDER))  		RR(GLOBAL_ALPHA); -	RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); -	RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); -	if (dss_has_feature(FEAT_MGR_LCD2)) { -		RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); -		RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); -		RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); -		RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); -		RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); -		RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); -		RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2)); +	if (dss_has_feature(FEAT_MGR_LCD2))  		RR(CONFIG2); -	} - -	RR(OVL_BA0(OMAP_DSS_GFX)); -	RR(OVL_BA1(OMAP_DSS_GFX)); -	RR(OVL_POSITION(OMAP_DSS_GFX)); -	RR(OVL_SIZE(OMAP_DSS_GFX)); -	RR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); -	RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); -	RR(OVL_ROW_INC(OMAP_DSS_GFX)); -	RR(OVL_PIXEL_INC(OMAP_DSS_GFX)); -	RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); -	RR(OVL_TABLE_BA(OMAP_DSS_GFX)); +	for (i = 0; i < dss_feat_get_num_mgrs(); i++) { +		RR(DEFAULT_COLOR(i)); +		RR(TRANS_COLOR(i)); +		RR(SIZE_MGR(i)); +		if (i == OMAP_DSS_CHANNEL_DIGIT) +			continue; +		RR(TIMING_H(i)); +		RR(TIMING_V(i)); +		RR(POL_FREQ(i)); +		RR(DIVISORo(i)); -	RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); -	RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); -	RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); - -	if (dss_has_feature(FEAT_CPR)) { -		RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); -		RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); -		RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); -	} -	if (dss_has_feature(FEAT_MGR_LCD2)) { -		RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); -		RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); -		RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); +		RR(DATA_CYCLE1(i)); +		RR(DATA_CYCLE2(i)); +		RR(DATA_CYCLE3(i));  		if (dss_has_feature(FEAT_CPR)) { -			RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); -			RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); -			RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); +			RR(CPR_COEF_R(i)); +			RR(CPR_COEF_G(i)); +			RR(CPR_COEF_B(i));  		}  	} -	if (dss_has_feature(FEAT_PRELOAD)) -		RR(OVL_PRELOAD(OMAP_DSS_GFX)); - -	/* VID1 */ -	RR(OVL_BA0(OMAP_DSS_VIDEO1)); -	RR(OVL_BA1(OMAP_DSS_VIDEO1)); -	RR(OVL_POSITION(OMAP_DSS_VIDEO1)); -	RR(OVL_SIZE(OMAP_DSS_VIDEO1)); -	RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); -	RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); -	RR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); -	RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); -	RR(OVL_FIR(OMAP_DSS_VIDEO1)); -	RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); -	RR(OVL_ACCU0(OMAP_DSS_VIDEO1)); -	RR(OVL_ACCU1(OMAP_DSS_VIDEO1)); - -	for (i = 0; i < 8; i++) -		RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); - -	for (i = 0; i < 8; i++) -		RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); - -	for (i = 0; i < 5; i++) -		RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); - -	if (dss_has_feature(FEAT_FIR_COEF_V)) { -		for (i = 0; i < 8; i++) -			RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); -	} - -	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { -		RR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); -		RR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); -		RR(OVL_FIR2(OMAP_DSS_VIDEO1)); -		RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); -		RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); - -		for (i = 0; i < 8; i++) -			RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); - -		for (i = 0; i < 8; i++) -			RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); - -		for (i = 0; i < 8; i++) -			RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); -	} -	if (dss_has_feature(FEAT_ATTR2)) -		RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); - -	if (dss_has_feature(FEAT_PRELOAD)) -		RR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); - -	/* VID2 */ -	RR(OVL_BA0(OMAP_DSS_VIDEO2)); -	RR(OVL_BA1(OMAP_DSS_VIDEO2)); -	RR(OVL_POSITION(OMAP_DSS_VIDEO2)); -	RR(OVL_SIZE(OMAP_DSS_VIDEO2)); -	RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); -	RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); -	RR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); -	RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); -	RR(OVL_FIR(OMAP_DSS_VIDEO2)); -	RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); -	RR(OVL_ACCU0(OMAP_DSS_VIDEO2)); -	RR(OVL_ACCU1(OMAP_DSS_VIDEO2)); +	for (i = 0; i < dss_feat_get_num_ovls(); i++) { +		RR(OVL_BA0(i)); +		RR(OVL_BA1(i)); +		RR(OVL_POSITION(i)); +		RR(OVL_SIZE(i)); +		RR(OVL_ATTRIBUTES(i)); +		RR(OVL_FIFO_THRESHOLD(i)); +		RR(OVL_ROW_INC(i)); +		RR(OVL_PIXEL_INC(i)); +		if (dss_has_feature(FEAT_PRELOAD)) +			RR(OVL_PRELOAD(i)); +		if (i == OMAP_DSS_GFX) { +			RR(OVL_WINDOW_SKIP(i)); +			RR(OVL_TABLE_BA(i)); +			continue; +		} +		RR(OVL_FIR(i)); +		RR(OVL_PICTURE_SIZE(i)); +		RR(OVL_ACCU0(i)); +		RR(OVL_ACCU1(i)); -	for (i = 0; i < 8; i++) -		RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); +		for (j = 0; j < 8; j++) +			RR(OVL_FIR_COEF_H(i, j)); -	for (i = 0; i < 8; i++) -		RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); +		for (j = 0; j < 8; j++) +			RR(OVL_FIR_COEF_HV(i, j)); -	for (i = 0; i < 5; i++) -		RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); +		for (j = 0; j < 5; j++) +			RR(OVL_CONV_COEF(i, j)); -	if (dss_has_feature(FEAT_FIR_COEF_V)) { -		for (i = 0; i < 8; i++) -			RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); -	} +		if (dss_has_feature(FEAT_FIR_COEF_V)) { +			for (j = 0; j < 8; j++) +				RR(OVL_FIR_COEF_V(i, j)); +		} -	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { -		RR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); -		RR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); -		RR(OVL_FIR2(OMAP_DSS_VIDEO2)); -		RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); -		RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); +		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { +			RR(OVL_BA0_UV(i)); +			RR(OVL_BA1_UV(i)); +			RR(OVL_FIR2(i)); +			RR(OVL_ACCU2_0(i)); +			RR(OVL_ACCU2_1(i)); -		for (i = 0; i < 8; i++) -			RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); +			for (j = 0; j < 8; j++) +				RR(OVL_FIR_COEF_H2(i, j)); -		for (i = 0; i < 8; i++) -			RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); +			for (j = 0; j < 8; j++) +				RR(OVL_FIR_COEF_HV2(i, j)); -		for (i = 0; i < 8; i++) -			RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); +			for (j = 0; j < 8; j++) +				RR(OVL_FIR_COEF_V2(i, j)); +		} +		if (dss_has_feature(FEAT_ATTR2)) +			RR(OVL_ATTRIBUTES2(i));  	} -	if (dss_has_feature(FEAT_ATTR2)) -		RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); - -	if (dss_has_feature(FEAT_PRELOAD)) -		RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));  	if (dss_has_feature(FEAT_CORE_CLK_DIV))  		RR(DIVISOR); @@ -570,13 +420,28 @@ void dispc_runtime_put(void)  	WARN_ON(r < 0);  } +static inline bool dispc_mgr_is_lcd(enum omap_channel channel) +{ +	if (channel == OMAP_DSS_CHANNEL_LCD || +			channel == OMAP_DSS_CHANNEL_LCD2) +		return true; +	else +		return false; +} + +static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel) +{ +	struct omap_overlay_manager *mgr = +		omap_dss_get_overlay_manager(channel); -bool dispc_go_busy(enum omap_channel channel) +	return mgr ? mgr->device : NULL; +} + +bool dispc_mgr_go_busy(enum omap_channel channel)  {  	int bit; -	if (channel == OMAP_DSS_CHANNEL_LCD || -			channel == OMAP_DSS_CHANNEL_LCD2) +	if (dispc_mgr_is_lcd(channel))  		bit = 5; /* GOLCD */  	else  		bit = 6; /* GODIGIT */ @@ -587,13 +452,12 @@ bool dispc_go_busy(enum omap_channel channel)  		return REG_GET(DISPC_CONTROL, bit, bit) == 1;  } -void dispc_go(enum omap_channel channel) +void dispc_mgr_go(enum omap_channel channel)  {  	int bit;  	bool enable_bit, go_bit; -	if (channel == OMAP_DSS_CHANNEL_LCD || -			channel == OMAP_DSS_CHANNEL_LCD2) +	if (dispc_mgr_is_lcd(channel))  		bit = 0; /* LCDENABLE */  	else  		bit = 1; /* DIGITALENABLE */ @@ -607,8 +471,7 @@ void dispc_go(enum omap_channel channel)  	if (!enable_bit)  		return; -	if (channel == OMAP_DSS_CHANNEL_LCD || -			channel == OMAP_DSS_CHANNEL_LCD2) +	if (dispc_mgr_is_lcd(channel))  		bit = 5; /* GOLCD */  	else  		bit = 6; /* GODIGIT */ @@ -632,43 +495,44 @@ void dispc_go(enum omap_channel channel)  		REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);  } -static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)  {  	dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);  } -static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value)  {  	dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);  } -static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value)  {  	dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);  } -static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value)  {  	BUG_ON(plane == OMAP_DSS_GFX);  	dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);  } -static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg, +		u32 value)  {  	BUG_ON(plane == OMAP_DSS_GFX);  	dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);  } -static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)  {  	BUG_ON(plane == OMAP_DSS_GFX);  	dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);  } -static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, +static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,  				  int vscaleup, int five_taps,  				  enum omap_color_component color_comp)  { @@ -769,11 +633,11 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,  			| FLD_VAL(v_coef[i].vc2, 31, 24);  		if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { -			_dispc_write_firh_reg(plane, i, h); -			_dispc_write_firhv_reg(plane, i, hv); +			dispc_ovl_write_firh_reg(plane, i, h); +			dispc_ovl_write_firhv_reg(plane, i, hv);  		} else { -			_dispc_write_firh2_reg(plane, i, h); -			_dispc_write_firhv2_reg(plane, i, hv); +			dispc_ovl_write_firh2_reg(plane, i, h); +			dispc_ovl_write_firhv2_reg(plane, i, hv);  		}  	} @@ -784,15 +648,16 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,  			v = FLD_VAL(v_coef[i].vc00, 7, 0)  				| FLD_VAL(v_coef[i].vc22, 15, 8);  			if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) -				_dispc_write_firv_reg(plane, i, v); +				dispc_ovl_write_firv_reg(plane, i, v);  			else -				_dispc_write_firv2_reg(plane, i, v); +				dispc_ovl_write_firv2_reg(plane, i, v);  		}  	}  }  static void _dispc_setup_color_conv_coef(void)  { +	int i;  	const struct color_conv_coef {  		int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;  		int  full_range; @@ -806,65 +671,54 @@ static void _dispc_setup_color_conv_coef(void)  	ct = &ctbl_bt601_5; -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0), -		CVAL(ct->rcr, ct->ry)); -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1), -		CVAL(ct->gy,  ct->rcb)); -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2), -		CVAL(ct->gcb, ct->gcr)); -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3), -		CVAL(ct->bcr, ct->by)); -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4), -		CVAL(0, ct->bcb)); +	for (i = 1; i < dss_feat_get_num_ovls(); i++) { +		dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0), +			CVAL(ct->rcr, ct->ry)); +		dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1), +			CVAL(ct->gy,  ct->rcb)); +		dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2), +			CVAL(ct->gcb, ct->gcr)); +		dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3), +			CVAL(ct->bcr, ct->by)); +		dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4), +			CVAL(0, ct->bcb)); -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0), -		CVAL(ct->rcr, ct->ry)); -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1), -		CVAL(ct->gy, ct->rcb)); -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2), -		CVAL(ct->gcb, ct->gcr)); -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3), -		CVAL(ct->bcr, ct->by)); -	dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4), -		CVAL(0, ct->bcb)); +		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range, +			11, 11); +	}  #undef CVAL - -	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1), -		ct->full_range, 11, 11); -	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2), -		ct->full_range, 11, 11);  } -static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) +static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)  {  	dispc_write_reg(DISPC_OVL_BA0(plane), paddr);  } -static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) +static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr)  {  	dispc_write_reg(DISPC_OVL_BA1(plane), paddr);  } -static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr) +static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr)  {  	dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);  } -static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr) +static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)  {  	dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);  } -static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) +static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y)  {  	u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);  	dispc_write_reg(DISPC_OVL_POSITION(plane), val);  } -static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) +static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height)  {  	u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); @@ -874,7 +728,7 @@ static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)  		dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);  } -static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) +static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)  {  	u32 val; @@ -885,44 +739,61 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)  	dispc_write_reg(DISPC_OVL_SIZE(plane), val);  } -static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) +static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) +{ +	struct omap_overlay *ovl = omap_dss_get_overlay(plane); + +	if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) +		return; + +	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); +} + +static void dispc_ovl_enable_zorder_planes(void)  { -	if (!dss_has_feature(FEAT_PRE_MULT_ALPHA)) +	int i; + +	if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER))  		return; -	if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && -		plane == OMAP_DSS_VIDEO1) +	for (i = 0; i < dss_feat_get_num_ovls(); i++) +		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); +} + +static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) +{ +	struct omap_overlay *ovl = omap_dss_get_overlay(plane); + +	if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)  		return;  	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);  } -static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) +static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha)  { -	if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) -		return; +	static const unsigned shifts[] = { 0, 8, 16, 24, }; +	int shift; +	struct omap_overlay *ovl = omap_dss_get_overlay(plane); -	if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && -		plane == OMAP_DSS_VIDEO1) +	if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)  		return; -	if (plane == OMAP_DSS_GFX) -		REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); -	else if (plane == OMAP_DSS_VIDEO2) -		REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16); +	shift = shifts[plane]; +	REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);  } -static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) +static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc)  {  	dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);  } -static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) +static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc)  {  	dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);  } -static void _dispc_set_color_mode(enum omap_plane plane, +static void dispc_ovl_set_color_mode(enum omap_plane plane,  		enum omap_color_mode color_mode)  {  	u32 m = 0; @@ -1003,7 +874,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,  	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);  } -void dispc_set_channel_out(enum omap_plane plane, +static void dispc_ovl_set_channel_out(enum omap_plane plane,  		enum omap_channel channel)  {  	int shift; @@ -1016,6 +887,7 @@ void dispc_set_channel_out(enum omap_plane plane,  		break;  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2: +	case OMAP_DSS_VIDEO3:  		shift = 16;  		break;  	default: @@ -1050,24 +922,13 @@ void dispc_set_channel_out(enum omap_plane plane,  	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);  } -static void dispc_set_burst_size(enum omap_plane plane, +static void dispc_ovl_set_burst_size(enum omap_plane plane,  		enum omap_burst_size burst_size)  { +	static const unsigned shifts[] = { 6, 14, 14, 14, };  	int shift; -	switch (plane) { -	case OMAP_DSS_GFX: -		shift = 6; -		break; -	case OMAP_DSS_VIDEO1: -	case OMAP_DSS_VIDEO2: -		shift = 14; -		break; -	default: -		BUG(); -		return; -	} - +	shift = shifts[plane];  	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);  } @@ -1078,10 +939,10 @@ static void dispc_configure_burst_sizes(void)  	/* Configure burst size always to maximum size */  	for (i = 0; i < omap_dss_get_num_overlays(); ++i) -		dispc_set_burst_size(i, burst_size); +		dispc_ovl_set_burst_size(i, burst_size);  } -u32 dispc_get_burst_size(enum omap_plane plane) +u32 dispc_ovl_get_burst_size(enum omap_plane plane)  {  	unsigned unit = dss_feat_get_burst_size_unit();  	/* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ @@ -1102,7 +963,7 @@ void dispc_enable_gamma_table(bool enable)  	REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);  } -void dispc_enable_cpr(enum omap_channel channel, bool enable) +void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)  {  	u16 reg; @@ -1116,12 +977,12 @@ void dispc_enable_cpr(enum omap_channel channel, bool enable)  	REG_FLD_MOD(reg, enable, 15, 15);  } -void dispc_set_cpr_coef(enum omap_channel channel, +void dispc_mgr_set_cpr_coef(enum omap_channel channel,  		struct omap_dss_cpr_coefs *coefs)  {  	u32 coef_r, coef_g, coef_b; -	if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2) +	if (!dispc_mgr_is_lcd(channel))  		return;  	coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | @@ -1136,7 +997,7 @@ void dispc_set_cpr_coef(enum omap_channel channel,  	dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);  } -static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) +static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)  {  	u32 val; @@ -1147,19 +1008,16 @@ static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)  	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);  } -void dispc_enable_replication(enum omap_plane plane, bool enable) +static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable)  { -	int bit; - -	if (plane == OMAP_DSS_GFX) -		bit = 5; -	else -		bit = 10; +	static const unsigned shifts[] = { 5, 10, 10, 10 }; +	int shift; -	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); +	shift = shifts[plane]; +	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);  } -void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) +void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height)  {  	u32 val;  	BUG_ON((width > (1 << 11)) || (height > (1 << 11))); @@ -1186,19 +1044,20 @@ static void dispc_read_plane_fifo_sizes(void)  	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); -	for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { +	for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) {  		size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);  		size *= unit;  		dispc.fifo_size[plane] = size;  	}  } -u32 dispc_get_plane_fifo_size(enum omap_plane plane) +u32 dispc_ovl_get_fifo_size(enum omap_plane plane)  {  	return dispc.fifo_size[plane];  } -void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) +static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, +		u32 high)  {  	u8 hi_start, hi_end, lo_start, lo_end;  	u32 unit; @@ -1233,7 +1092,7 @@ void dispc_enable_fifomerge(bool enable)  	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);  } -static void _dispc_set_fir(enum omap_plane plane, +static void dispc_ovl_set_fir(enum omap_plane plane,  				int hinc, int vinc,  				enum omap_color_component color_comp)  { @@ -1256,7 +1115,7 @@ static void _dispc_set_fir(enum omap_plane plane,  	}  } -static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) +static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)  {  	u32 val;  	u8 hor_start, hor_end, vert_start, vert_end; @@ -1270,7 +1129,7 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)  	dispc_write_reg(DISPC_OVL_ACCU0(plane), val);  } -static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) +static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)  {  	u32 val;  	u8 hor_start, hor_end, vert_start, vert_end; @@ -1284,7 +1143,8 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)  	dispc_write_reg(DISPC_OVL_ACCU1(plane), val);  } -static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu) +static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu, +		int vaccu)  {  	u32 val; @@ -1292,7 +1152,8 @@ static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)  	dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);  } -static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu) +static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu, +		int vaccu)  {  	u32 val; @@ -1300,7 +1161,7 @@ static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)  	dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);  } -static void _dispc_set_scale_param(enum omap_plane plane, +static void dispc_ovl_set_scale_param(enum omap_plane plane,  		u16 orig_width, u16 orig_height,  		u16 out_width, u16 out_height,  		bool five_taps, u8 rotation, @@ -1312,15 +1173,16 @@ static void _dispc_set_scale_param(enum omap_plane plane,  	hscaleup = orig_width <= out_width;  	vscaleup = orig_height <= out_height; -	_dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp); +	dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps, +			color_comp);  	fir_hinc = 1024 * orig_width / out_width;  	fir_vinc = 1024 * orig_height / out_height; -	_dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp); +	dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);  } -static void _dispc_set_scaling_common(enum omap_plane plane, +static void dispc_ovl_set_scaling_common(enum omap_plane plane,  		u16 orig_width, u16 orig_height,  		u16 out_width, u16 out_height,  		bool ilace, bool five_taps, @@ -1331,7 +1193,7 @@ static void _dispc_set_scaling_common(enum omap_plane plane,  	int accu1 = 0;  	u32 l; -	_dispc_set_scale_param(plane, orig_width, orig_height, +	dispc_ovl_set_scale_param(plane, orig_width, orig_height,  				out_width, out_height, five_taps,  				rotation, DISPC_COLOR_COMPONENT_RGB_Y);  	l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); @@ -1370,11 +1232,11 @@ static void _dispc_set_scaling_common(enum omap_plane plane,  		}  	} -	_dispc_set_vid_accu0(plane, 0, accu0); -	_dispc_set_vid_accu1(plane, 0, accu1); +	dispc_ovl_set_vid_accu0(plane, 0, accu0); +	dispc_ovl_set_vid_accu1(plane, 0, accu1);  } -static void _dispc_set_scaling_uv(enum omap_plane plane, +static void dispc_ovl_set_scaling_uv(enum omap_plane plane,  		u16 orig_width, u16 orig_height,  		u16 out_width, u16 out_height,  		bool ilace, bool five_taps, @@ -1422,7 +1284,7 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,  	if (out_height != orig_height)  		scale_y = true; -	_dispc_set_scale_param(plane, orig_width, orig_height, +	dispc_ovl_set_scale_param(plane, orig_width, orig_height,  			out_width, out_height, five_taps,  				rotation, DISPC_COLOR_COMPONENT_UV); @@ -1433,11 +1295,11 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,  	/* set V scaling */  	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); -	_dispc_set_vid_accu2_0(plane, 0x80, 0); -	_dispc_set_vid_accu2_1(plane, 0x80, 0); +	dispc_ovl_set_vid_accu2_0(plane, 0x80, 0); +	dispc_ovl_set_vid_accu2_1(plane, 0x80, 0);  } -static void _dispc_set_scaling(enum omap_plane plane, +static void dispc_ovl_set_scaling(enum omap_plane plane,  		u16 orig_width, u16 orig_height,  		u16 out_width, u16 out_height,  		bool ilace, bool five_taps, @@ -1446,14 +1308,14 @@ static void _dispc_set_scaling(enum omap_plane plane,  {  	BUG_ON(plane == OMAP_DSS_GFX); -	_dispc_set_scaling_common(plane, +	dispc_ovl_set_scaling_common(plane,  			orig_width, orig_height,  			out_width, out_height,  			ilace, five_taps,  			fieldmode, color_mode,  			rotation); -	_dispc_set_scaling_uv(plane, +	dispc_ovl_set_scaling_uv(plane,  		orig_width, orig_height,  		out_width, out_height,  		ilace, five_taps, @@ -1461,7 +1323,7 @@ static void _dispc_set_scaling(enum omap_plane plane,  		rotation);  } -static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, +static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,  		bool mirroring, enum omap_color_mode color_mode)  {  	bool row_repeat = false; @@ -1789,12 +1651,11 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,  		enum omap_color_mode color_mode)  {  	u32 fclk = 0; -	/* FIXME venc pclk? */ -	u64 tmp, pclk = dispc_pclk_rate(channel); +	u64 tmp, pclk = dispc_mgr_pclk_rate(channel);  	if (height > out_height) { -		/* FIXME get real display PPL */ -		unsigned int ppl = 800; +		struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); +		unsigned int ppl = dssdev->panel.timings.x_res;  		tmp = pclk * height * out_width;  		do_div(tmp, 2 * out_height * ppl); @@ -1846,114 +1707,120 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,  	else  		vf = 1; -	/* FIXME venc pclk? */ -	return dispc_pclk_rate(channel) * vf * hf; +	return dispc_mgr_pclk_rate(channel) * vf * hf;  } -int dispc_setup_plane(enum omap_plane plane, -		u32 paddr, u16 screen_width, -		u16 pos_x, u16 pos_y, -		u16 width, u16 height, +static int dispc_ovl_calc_scaling(enum omap_plane plane, +		enum omap_channel channel, u16 width, u16 height,  		u16 out_width, u16 out_height, -		enum omap_color_mode color_mode, -		bool ilace, -		enum omap_dss_rotation_type rotation_type, -		u8 rotation, bool mirror, -		u8 global_alpha, u8 pre_mult_alpha, -		enum omap_channel channel, u32 puv_addr) +		enum omap_color_mode color_mode, bool *five_taps)  { -	const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; -	bool five_taps = 0; -	bool fieldmode = 0; -	int cconv = 0; -	unsigned offset0, offset1; -	s32 row_inc; -	s32 pix_inc; -	u16 frame_height = height; -	unsigned int field_offset = 0; +	struct omap_overlay *ovl = omap_dss_get_overlay(plane); +	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); +	unsigned long fclk = 0; -	DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " -	       "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", -	       plane, paddr, screen_width, pos_x, pos_y, -	       width, height, -	       out_width, out_height, -	       ilace, color_mode, -	       rotation, mirror, channel); +	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { +		if (width != out_width || height != out_height) +			return -EINVAL; +		else +			return 0; +	} -	if (paddr == 0) +	if (out_width < width / maxdownscale || +			out_width > width * 8)  		return -EINVAL; -	if (ilace && height == out_height) -		fieldmode = 1; +	if (out_height < height / maxdownscale || +			out_height > height * 8) +		return -EINVAL; -	if (ilace) { -		if (fieldmode) -			height /= 2; -		pos_y /= 2; -		out_height /= 2; +	/* Must use 5-tap filter? */ +	*five_taps = height > out_height * 2; -		DSSDBG("adjusting for ilace: height %d, pos_y %d, " -				"out_height %d\n", -				height, pos_y, out_height); +	if (!*five_taps) { +		fclk = calc_fclk(channel, width, height, out_width, +				out_height); + +		/* Try 5-tap filter if 3-tap fclk is too high */ +		if (cpu_is_omap34xx() && height > out_height && +				fclk > dispc_fclk_rate()) +			*five_taps = true;  	} -	if (!dss_feat_color_mode_supported(plane, color_mode)) +	if (width > (2048 >> *five_taps)) { +		DSSERR("failed to set up scaling, fclk too low\n");  		return -EINVAL; +	} -	if (plane == OMAP_DSS_GFX) { -		if (width != out_width || height != out_height) -			return -EINVAL; -	} else { -		/* video plane */ +	if (*five_taps) +		fclk = calc_fclk_five_taps(channel, width, height, +				out_width, out_height, color_mode); -		unsigned long fclk = 0; +	DSSDBG("required fclk rate = %lu Hz\n", fclk); +	DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); -		if (out_width < width / maxdownscale || -		   out_width > width * 8) -			return -EINVAL; +	if (!fclk || fclk > dispc_fclk_rate()) { +		DSSERR("failed to set up scaling, " +			"required fclk rate = %lu Hz, " +			"current fclk rate = %lu Hz\n", +			fclk, dispc_fclk_rate()); +		return -EINVAL; +	} -		if (out_height < height / maxdownscale || -		   out_height > height * 8) -			return -EINVAL; +	return 0; +} -		if (color_mode == OMAP_DSS_COLOR_YUV2 || -			color_mode == OMAP_DSS_COLOR_UYVY || -			color_mode == OMAP_DSS_COLOR_NV12) -			cconv = 1; +int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, +		bool ilace, enum omap_channel channel, bool replication, +		u32 fifo_low, u32 fifo_high) +{ +	struct omap_overlay *ovl = omap_dss_get_overlay(plane); +	bool five_taps = false; +	bool fieldmode = 0; +	int r, cconv = 0; +	unsigned offset0, offset1; +	s32 row_inc; +	s32 pix_inc; +	u16 frame_height = oi->height; +	unsigned int field_offset = 0; -		/* Must use 5-tap filter? */ -		five_taps = height > out_height * 2; +	DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " +		"%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d " +		"fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr, +		oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, +		oi->out_width, oi->out_height, oi->color_mode, oi->rotation, +		oi->mirror, ilace, channel, replication, fifo_low, fifo_high); -		if (!five_taps) { -			fclk = calc_fclk(channel, width, height, out_width, -					out_height); +	if (oi->paddr == 0) +		return -EINVAL; -			/* Try 5-tap filter if 3-tap fclk is too high */ -			if (cpu_is_omap34xx() && height > out_height && -					fclk > dispc_fclk_rate()) -				five_taps = true; -		} +	if (ilace && oi->height == oi->out_height) +		fieldmode = 1; -		if (width > (2048 >> five_taps)) { -			DSSERR("failed to set up scaling, fclk too low\n"); -			return -EINVAL; -		} +	if (ilace) { +		if (fieldmode) +			oi->height /= 2; +		oi->pos_y /= 2; +		oi->out_height /= 2; + +		DSSDBG("adjusting for ilace: height %d, pos_y %d, " +				"out_height %d\n", +				oi->height, oi->pos_y, oi->out_height); +	} -		if (five_taps) -			fclk = calc_fclk_five_taps(channel, width, height, -					out_width, out_height, color_mode); +	if (!dss_feat_color_mode_supported(plane, oi->color_mode)) +		return -EINVAL; -		DSSDBG("required fclk rate = %lu Hz\n", fclk); -		DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); +	r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, +			oi->out_width, oi->out_height, oi->color_mode, +			&five_taps); +	if (r) +		return r; -		if (!fclk || fclk > dispc_fclk_rate()) { -			DSSERR("failed to set up scaling, " -					"required fclk rate = %lu Hz, " -					"current fclk rate = %lu Hz\n", -					fclk, dispc_fclk_rate()); -			return -EINVAL; -		} -	} +	if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || +			oi->color_mode == OMAP_DSS_COLOR_UYVY || +			oi->color_mode == OMAP_DSS_COLOR_NV12) +		cconv = 1;  	if (ilace && !fieldmode) {  		/* @@ -1963,69 +1830,76 @@ int dispc_setup_plane(enum omap_plane plane,  		 * so the integer part must be added to the base address of the  		 * bottom field.  		 */ -		if (!height || height == out_height) +		if (!oi->height || oi->height == oi->out_height)  			field_offset = 0;  		else -			field_offset = height / out_height / 2; +			field_offset = oi->height / oi->out_height / 2;  	}  	/* Fields are independent but interleaved in memory. */  	if (fieldmode)  		field_offset = 1; -	if (rotation_type == OMAP_DSS_ROT_DMA) -		calc_dma_rotation_offset(rotation, mirror, -				screen_width, width, frame_height, color_mode, -				fieldmode, field_offset, +	if (oi->rotation_type == OMAP_DSS_ROT_DMA) +		calc_dma_rotation_offset(oi->rotation, oi->mirror, +				oi->screen_width, oi->width, frame_height, +				oi->color_mode, fieldmode, field_offset,  				&offset0, &offset1, &row_inc, &pix_inc);  	else -		calc_vrfb_rotation_offset(rotation, mirror, -				screen_width, width, frame_height, color_mode, -				fieldmode, field_offset, +		calc_vrfb_rotation_offset(oi->rotation, oi->mirror, +				oi->screen_width, oi->width, frame_height, +				oi->color_mode, fieldmode, field_offset,  				&offset0, &offset1, &row_inc, &pix_inc);  	DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",  			offset0, offset1, row_inc, pix_inc); -	_dispc_set_color_mode(plane, color_mode); +	dispc_ovl_set_color_mode(plane, oi->color_mode); -	_dispc_set_plane_ba0(plane, paddr + offset0); -	_dispc_set_plane_ba1(plane, paddr + offset1); +	dispc_ovl_set_ba0(plane, oi->paddr + offset0); +	dispc_ovl_set_ba1(plane, oi->paddr + offset1); -	if (OMAP_DSS_COLOR_NV12 == color_mode) { -		_dispc_set_plane_ba0_uv(plane, puv_addr + offset0); -		_dispc_set_plane_ba1_uv(plane, puv_addr + offset1); +	if (OMAP_DSS_COLOR_NV12 == oi->color_mode) { +		dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0); +		dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1);  	} -	_dispc_set_row_inc(plane, row_inc); -	_dispc_set_pix_inc(plane, pix_inc); +	dispc_ovl_set_row_inc(plane, row_inc); +	dispc_ovl_set_pix_inc(plane, pix_inc); -	DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height, -			out_width, out_height); +	DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, +			oi->height, oi->out_width, oi->out_height); -	_dispc_set_plane_pos(plane, pos_x, pos_y); +	dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); -	_dispc_set_pic_size(plane, width, height); +	dispc_ovl_set_pic_size(plane, oi->width, oi->height); -	if (plane != OMAP_DSS_GFX) { -		_dispc_set_scaling(plane, width, height, -				   out_width, out_height, +	if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { +		dispc_ovl_set_scaling(plane, oi->width, oi->height, +				   oi->out_width, oi->out_height,  				   ilace, five_taps, fieldmode, -				   color_mode, rotation); -		_dispc_set_vid_size(plane, out_width, out_height); -		_dispc_set_vid_color_conv(plane, cconv); +				   oi->color_mode, oi->rotation); +		dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height); +		dispc_ovl_set_vid_color_conv(plane, cconv);  	} -	_dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); +	dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror, +			oi->color_mode); + +	dispc_ovl_set_zorder(plane, oi->zorder); +	dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); +	dispc_ovl_setup_global_alpha(plane, oi->global_alpha); -	_dispc_set_pre_mult_alpha(plane, pre_mult_alpha); -	_dispc_setup_global_alpha(plane, global_alpha); +	dispc_ovl_set_channel_out(plane, channel); + +	dispc_ovl_enable_replication(plane, replication); +	dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high);  	return 0;  } -int dispc_enable_plane(enum omap_plane plane, bool enable) +int dispc_ovl_enable(enum omap_plane plane, bool enable)  {  	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); @@ -2048,7 +1922,7 @@ static void _enable_lcd_out(enum omap_channel channel, bool enable)  		REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);  } -static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) +static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)  {  	struct completion frame_done_completion;  	bool is_on; @@ -2095,14 +1969,19 @@ static void _enable_digit_out(bool enable)  	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);  } -static void dispc_enable_digit_out(bool enable) +static void dispc_mgr_enable_digit_out(bool enable)  {  	struct completion frame_done_completion; -	int r; +	enum dss_hdmi_venc_clk_source_select src; +	int r, i; +	u32 irq_mask; +	int num_irqs;  	if (REG_GET(DISPC_CONTROL, 1, 1) == enable)  		return; +	src = dss_get_hdmi_venc_clk_source(); +  	if (enable) {  		unsigned long flags;  		/* When we enable digit output, we'll get an extra digit @@ -2119,43 +1998,47 @@ static void dispc_enable_digit_out(bool enable)  	 * wait for the extra sync losts */  	init_completion(&frame_done_completion); +	if (src == DSS_HDMI_M_PCLK && enable == false) { +		irq_mask = DISPC_IRQ_FRAMEDONETV; +		num_irqs = 1; +	} else { +		irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; +		/* XXX I understand from TRM that we should only wait for the +		 * current field to complete. But it seems we have to wait for +		 * both fields */ +		num_irqs = 2; +	} +  	r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, -			DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); +			irq_mask);  	if (r) -		DSSERR("failed to register EVSYNC isr\n"); +		DSSERR("failed to register %x isr\n", irq_mask);  	_enable_digit_out(enable); -	/* XXX I understand from TRM that we should only wait for the -	 * current field to complete. But it seems we have to wait -	 * for both fields */ -	if (!wait_for_completion_timeout(&frame_done_completion, -				msecs_to_jiffies(100))) -		DSSERR("timeout waiting for EVSYNC\n"); - -	if (!wait_for_completion_timeout(&frame_done_completion, -				msecs_to_jiffies(100))) -		DSSERR("timeout waiting for EVSYNC\n"); +	for (i = 0; i < num_irqs; ++i) { +		if (!wait_for_completion_timeout(&frame_done_completion, +					msecs_to_jiffies(100))) +			DSSERR("timeout waiting for digit out to %s\n", +					enable ? "start" : "stop"); +	} -	r = omap_dispc_unregister_isr(dispc_disable_isr, -			&frame_done_completion, -			DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); +	r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion, +			irq_mask);  	if (r) -		DSSERR("failed to unregister EVSYNC isr\n"); +		DSSERR("failed to unregister %x isr\n", irq_mask);  	if (enable) {  		unsigned long flags;  		spin_lock_irqsave(&dispc.irq_lock, flags); -		dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; -		if (dss_has_feature(FEAT_MGR_LCD2)) -			dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; +		dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;  		dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);  		_omap_dispc_set_irqs();  		spin_unlock_irqrestore(&dispc.irq_lock, flags);  	}  } -bool dispc_is_channel_enabled(enum omap_channel channel) +bool dispc_mgr_is_enabled(enum omap_channel channel)  {  	if (channel == OMAP_DSS_CHANNEL_LCD)  		return !!REG_GET(DISPC_CONTROL, 0, 0); @@ -2167,13 +2050,12 @@ bool dispc_is_channel_enabled(enum omap_channel channel)  		BUG();  } -void dispc_enable_channel(enum omap_channel channel, bool enable) +void dispc_mgr_enable(enum omap_channel channel, bool enable)  { -	if (channel == OMAP_DSS_CHANNEL_LCD || -			channel == OMAP_DSS_CHANNEL_LCD2) -		dispc_enable_lcd_out(channel, enable); +	if (dispc_mgr_is_lcd(channel)) +		dispc_mgr_enable_lcd_out(channel, enable);  	else if (channel == OMAP_DSS_CHANNEL_DIGIT) -		dispc_enable_digit_out(enable); +		dispc_mgr_enable_digit_out(enable);  	else  		BUG();  } @@ -2202,7 +2084,7 @@ void dispc_pck_free_enable(bool enable)  	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);  } -void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) +void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)  {  	if (channel == OMAP_DSS_CHANNEL_LCD2)  		REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); @@ -2211,7 +2093,7 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)  } -void dispc_set_lcd_display_type(enum omap_channel channel, +void dispc_mgr_set_lcd_display_type(enum omap_channel channel,  		enum omap_lcd_display_type type)  {  	int mode; @@ -2242,12 +2124,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)  } -void dispc_set_default_color(enum omap_channel channel, u32 color) +void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)  {  	dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);  } -u32 dispc_get_default_color(enum omap_channel channel) +u32 dispc_mgr_get_default_color(enum omap_channel channel)  {  	u32 l; @@ -2260,7 +2142,7 @@ u32 dispc_get_default_color(enum omap_channel channel)  	return l;  } -void dispc_set_trans_key(enum omap_channel ch, +void dispc_mgr_set_trans_key(enum omap_channel ch,  		enum omap_dss_trans_key_type type,  		u32 trans_key)  { @@ -2274,7 +2156,7 @@ void dispc_set_trans_key(enum omap_channel ch,  	dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);  } -void dispc_get_trans_key(enum omap_channel ch, +void dispc_mgr_get_trans_key(enum omap_channel ch,  		enum omap_dss_trans_key_type *type,  		u32 *trans_key)  { @@ -2293,7 +2175,7 @@ void dispc_get_trans_key(enum omap_channel ch,  		*trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));  } -void dispc_enable_trans_key(enum omap_channel ch, bool enable) +void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)  {  	if (ch == OMAP_DSS_CHANNEL_LCD)  		REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); @@ -2302,39 +2184,36 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable)  	else /* OMAP_DSS_CHANNEL_LCD2 */  		REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);  } -void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) + +void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)  { -	if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) +	if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))  		return;  	if (ch == OMAP_DSS_CHANNEL_LCD)  		REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);  	else if (ch == OMAP_DSS_CHANNEL_DIGIT)  		REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); -	else /* OMAP_DSS_CHANNEL_LCD2 */ -		REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);  } -bool dispc_alpha_blending_enabled(enum omap_channel ch) + +bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch)  {  	bool enabled; -	if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) +	if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))  		return false;  	if (ch == OMAP_DSS_CHANNEL_LCD)  		enabled = REG_GET(DISPC_CONFIG, 18, 18);  	else if (ch == OMAP_DSS_CHANNEL_DIGIT)  		enabled = REG_GET(DISPC_CONFIG, 19, 19); -	else if (ch == OMAP_DSS_CHANNEL_LCD2) -		enabled = REG_GET(DISPC_CONFIG2, 18, 18);  	else  		BUG();  	return enabled;  } - -bool dispc_trans_key_enabled(enum omap_channel ch) +bool dispc_mgr_trans_key_enabled(enum omap_channel ch)  {  	bool enabled; @@ -2351,7 +2230,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)  } -void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) +void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)  {  	int code; @@ -2379,46 +2258,41 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)  		REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);  } -void dispc_set_parallel_interface_mode(enum omap_channel channel, -		enum omap_parallel_interface_mode mode) +void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)  {  	u32 l; -	int stallmode; -	int gpout0 = 1; -	int gpout1; +	int gpout0, gpout1;  	switch (mode) { -	case OMAP_DSS_PARALLELMODE_BYPASS: -		stallmode = 0; -		gpout1 = 1; +	case DSS_IO_PAD_MODE_RESET: +		gpout0 = 0; +		gpout1 = 0;  		break; - -	case OMAP_DSS_PARALLELMODE_RFBI: -		stallmode = 1; +	case DSS_IO_PAD_MODE_RFBI: +		gpout0 = 1;  		gpout1 = 0;  		break; - -	case OMAP_DSS_PARALLELMODE_DSI: -		stallmode = 1; +	case DSS_IO_PAD_MODE_BYPASS: +		gpout0 = 1;  		gpout1 = 1;  		break; -  	default:  		BUG();  		return;  	} -	if (channel == OMAP_DSS_CHANNEL_LCD2) { -		l = dispc_read_reg(DISPC_CONTROL2); -		l = FLD_MOD(l, stallmode, 11, 11); -		dispc_write_reg(DISPC_CONTROL2, l); -	} else { -		l = dispc_read_reg(DISPC_CONTROL); -		l = FLD_MOD(l, stallmode, 11, 11); -		l = FLD_MOD(l, gpout0, 15, 15); -		l = FLD_MOD(l, gpout1, 16, 16); -		dispc_write_reg(DISPC_CONTROL, l); -	} +	l = dispc_read_reg(DISPC_CONTROL); +	l = FLD_MOD(l, gpout0, 15, 15); +	l = FLD_MOD(l, gpout1, 16, 16); +	dispc_write_reg(DISPC_CONTROL, l); +} + +void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) +{ +	if (channel == OMAP_DSS_CHANNEL_LCD2) +		REG_FLD_MOD(DISPC_CONTROL2, enable, 11, 11); +	else +		REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11);  }  static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, @@ -2452,7 +2326,7 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings)  			timings->vfp, timings->vbp);  } -static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, +static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,  		int hfp, int hbp, int vsw, int vfp, int vbp)  {  	u32 timing_h, timing_v; @@ -2476,7 +2350,7 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,  }  /* change name to mode? */ -void dispc_set_lcd_timings(enum omap_channel channel, +void dispc_mgr_set_lcd_timings(enum omap_channel channel,  		struct omap_video_timings *timings)  {  	unsigned xtot, ytot; @@ -2487,11 +2361,11 @@ void dispc_set_lcd_timings(enum omap_channel channel,  				timings->vfp, timings->vbp))  		BUG(); -	_dispc_set_lcd_timings(channel, timings->hsw, timings->hfp, +	_dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp,  			timings->hbp, timings->vsw, timings->vfp,  			timings->vbp); -	dispc_set_lcd_size(channel, timings->x_res, timings->y_res); +	dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res);  	xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;  	ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; @@ -2509,17 +2383,17 @@ void dispc_set_lcd_timings(enum omap_channel channel,  	DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);  } -static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, +static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,  		u16 pck_div)  {  	BUG_ON(lck_div < 1); -	BUG_ON(pck_div < 2); +	BUG_ON(pck_div < 1);  	dispc_write_reg(DISPC_DIVISORo(channel),  			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));  } -static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, +static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,  		int *pck_div)  {  	u32 l; @@ -2552,7 +2426,7 @@ unsigned long dispc_fclk_rate(void)  	return r;  } -unsigned long dispc_lclk_rate(enum omap_channel channel) +unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)  {  	struct platform_device *dsidev;  	int lcd; @@ -2582,19 +2456,34 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)  	return r / lcd;  } -unsigned long dispc_pclk_rate(enum omap_channel channel) +unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)  { -	int pcd;  	unsigned long r; -	u32 l; -	l = dispc_read_reg(DISPC_DIVISORo(channel)); +	if (dispc_mgr_is_lcd(channel)) { +		int pcd; +		u32 l; + +		l = dispc_read_reg(DISPC_DIVISORo(channel)); -	pcd = FLD_GET(l, 7, 0); +		pcd = FLD_GET(l, 7, 0); -	r = dispc_lclk_rate(channel); +		r = dispc_mgr_lclk_rate(channel); + +		return r / pcd; +	} else { +		struct omap_dss_device *dssdev = +			dispc_mgr_get_device(channel); -	return r / pcd; +		switch (dssdev->type) { +		case OMAP_DISPLAY_TYPE_VENC: +			return venc_get_pixel_clock(); +		case OMAP_DISPLAY_TYPE_HDMI: +			return hdmi_get_pixel_clock(); +		default: +			BUG(); +		} +	}  }  void dispc_dump_clocks(struct seq_file *s) @@ -2631,12 +2520,12 @@ void dispc_dump_clocks(struct seq_file *s)  		dss_get_generic_clk_source_name(lcd_clk_src),  		dss_feat_get_clk_source_name(lcd_clk_src)); -	dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); +	dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);  	seq_printf(s, "lck\t\t%-16lulck div\t%u\n", -			dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd); +			dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);  	seq_printf(s, "pck\t\t%-16lupck div\t%u\n", -			dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd); +			dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);  	if (dss_has_feature(FEAT_MGR_LCD2)) {  		seq_printf(s, "- LCD2 -\n"); @@ -2646,12 +2535,12 @@ void dispc_dump_clocks(struct seq_file *s)  			dss_get_generic_clk_source_name(lcd_clk_src),  			dss_feat_get_clk_source_name(lcd_clk_src)); -		dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); +		dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);  		seq_printf(s, "lck\t\t%-16lulck div\t%u\n", -				dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd); +				dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);  		seq_printf(s, "pck\t\t%-16lupck div\t%u\n", -				dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); +				dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);  	}  	dispc_runtime_put(); @@ -2692,6 +2581,10 @@ void dispc_dump_irqs(struct seq_file *s)  	PIS(VID1_END_WIN);  	PIS(VID2_FIFO_UNDERFLOW);  	PIS(VID2_END_WIN); +	if (dss_feat_get_num_ovls() > 3) { +		PIS(VID3_FIFO_UNDERFLOW); +		PIS(VID3_END_WIN); +	}  	PIS(SYNC_LOST);  	PIS(SYNC_LOST_DIGIT);  	PIS(WAKEUP); @@ -2707,11 +2600,26 @@ void dispc_dump_irqs(struct seq_file *s)  void dispc_dump_regs(struct seq_file *s)  { +	int i, j; +	const char *mgr_names[] = { +		[OMAP_DSS_CHANNEL_LCD]		= "LCD", +		[OMAP_DSS_CHANNEL_DIGIT]	= "TV", +		[OMAP_DSS_CHANNEL_LCD2]		= "LCD2", +	}; +	const char *ovl_names[] = { +		[OMAP_DSS_GFX]		= "GFX", +		[OMAP_DSS_VIDEO1]	= "VID1", +		[OMAP_DSS_VIDEO2]	= "VID2", +		[OMAP_DSS_VIDEO3]	= "VID3", +	}; +	const char **p_names; +  #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))  	if (dispc_runtime_get())  		return; +	/* DISPC common registers */  	DUMPREG(DISPC_REVISION);  	DUMPREG(DISPC_SYSCONFIG);  	DUMPREG(DISPC_SYSSTATUS); @@ -2720,247 +2628,139 @@ void dispc_dump_regs(struct seq_file *s)  	DUMPREG(DISPC_CONTROL);  	DUMPREG(DISPC_CONFIG);  	DUMPREG(DISPC_CAPABLE); -	DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); -	DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); -	DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); -	DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));  	DUMPREG(DISPC_LINE_STATUS);  	DUMPREG(DISPC_LINE_NUMBER); -	DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD)); -	DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD)); -	DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD)); -	DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD)); -	if (dss_has_feature(FEAT_GLOBAL_ALPHA)) +	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || +			dss_has_feature(FEAT_ALPHA_FREE_ZORDER))  		DUMPREG(DISPC_GLOBAL_ALPHA); -	DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); -	DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));  	if (dss_has_feature(FEAT_MGR_LCD2)) {  		DUMPREG(DISPC_CONTROL2);  		DUMPREG(DISPC_CONFIG2); -		DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); -		DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); -		DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2)); -		DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2)); -		DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); -		DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2)); -		DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));  	} -	DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX)); -	DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX)); +#undef DUMPREG -	DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); -	DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); -	DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); +#define DISPC_REG(i, name) name(i) +#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \ +	48 - strlen(#r) - strlen(p_names[i]), " ", \ +	dispc_read_reg(DISPC_REG(i, r))) -	if (dss_has_feature(FEAT_CPR)) { -		DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); -		DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); -		DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); -	} -	if (dss_has_feature(FEAT_MGR_LCD2)) { -		DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); -		DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); -		DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); +	p_names = mgr_names; -		if (dss_has_feature(FEAT_CPR)) { -			DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); -			DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); -			DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); -		} -	} +	/* DISPC channel specific registers */ +	for (i = 0; i < dss_feat_get_num_mgrs(); i++) { +		DUMPREG(i, DISPC_DEFAULT_COLOR); +		DUMPREG(i, DISPC_TRANS_COLOR); +		DUMPREG(i, DISPC_SIZE_MGR); -	if (dss_has_feature(FEAT_PRELOAD)) -		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); +		if (i == OMAP_DSS_CHANNEL_DIGIT) +			continue; -	DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1)); -	DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1)); +		DUMPREG(i, DISPC_DEFAULT_COLOR); +		DUMPREG(i, DISPC_TRANS_COLOR); +		DUMPREG(i, DISPC_TIMING_H); +		DUMPREG(i, DISPC_TIMING_V); +		DUMPREG(i, DISPC_POL_FREQ); +		DUMPREG(i, DISPC_DIVISORo); +		DUMPREG(i, DISPC_SIZE_MGR); -	DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2)); -	DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2)); +		DUMPREG(i, DISPC_DATA_CYCLE1); +		DUMPREG(i, DISPC_DATA_CYCLE2); +		DUMPREG(i, DISPC_DATA_CYCLE3); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4)); -	if (dss_has_feature(FEAT_FIR_COEF_V)) { -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7)); +		if (dss_has_feature(FEAT_CPR)) { +			DUMPREG(i, DISPC_CPR_COEF_R); +			DUMPREG(i, DISPC_CPR_COEF_G); +			DUMPREG(i, DISPC_CPR_COEF_B); +		}  	} -	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { -		DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1)); -		DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1)); -		DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1)); -		DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1)); -		DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1)); +	p_names = ovl_names; -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7)); +	for (i = 0; i < dss_feat_get_num_ovls(); i++) { +		DUMPREG(i, DISPC_OVL_BA0); +		DUMPREG(i, DISPC_OVL_BA1); +		DUMPREG(i, DISPC_OVL_POSITION); +		DUMPREG(i, DISPC_OVL_SIZE); +		DUMPREG(i, DISPC_OVL_ATTRIBUTES); +		DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD); +		DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS); +		DUMPREG(i, DISPC_OVL_ROW_INC); +		DUMPREG(i, DISPC_OVL_PIXEL_INC); +		if (dss_has_feature(FEAT_PRELOAD)) +			DUMPREG(i, DISPC_OVL_PRELOAD); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7)); +		if (i == OMAP_DSS_GFX) { +			DUMPREG(i, DISPC_OVL_WINDOW_SKIP); +			DUMPREG(i, DISPC_OVL_TABLE_BA); +			continue; +		} -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7)); +		DUMPREG(i, DISPC_OVL_FIR); +		DUMPREG(i, DISPC_OVL_PICTURE_SIZE); +		DUMPREG(i, DISPC_OVL_ACCU0); +		DUMPREG(i, DISPC_OVL_ACCU1); +		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { +			DUMPREG(i, DISPC_OVL_BA0_UV); +			DUMPREG(i, DISPC_OVL_BA1_UV); +			DUMPREG(i, DISPC_OVL_FIR2); +			DUMPREG(i, DISPC_OVL_ACCU2_0); +			DUMPREG(i, DISPC_OVL_ACCU2_1); +		} +		if (dss_has_feature(FEAT_ATTR2)) +			DUMPREG(i, DISPC_OVL_ATTRIBUTES2); +		if (dss_has_feature(FEAT_PRELOAD)) +			DUMPREG(i, DISPC_OVL_PRELOAD);  	} -	if (dss_has_feature(FEAT_ATTR2)) -		DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); +#undef DISPC_REG +#undef DUMPREG -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6)); -	DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6)); -	DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3)); -	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4)); +#define DISPC_REG(plane, name, i) name(plane, i) +#define DUMPREG(plane, name, i) \ +	seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \ +	46 - strlen(#name) - strlen(p_names[plane]), " ", \ +	dispc_read_reg(DISPC_REG(plane, name, i))) -	if (dss_has_feature(FEAT_FIR_COEF_V)) { -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6)); -		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7)); -	} +	/* Video pipeline coefficient registers */ -	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { -		DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2)); -		DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2)); -		DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2)); -		DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2)); -		DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2)); +	/* start from OMAP_DSS_VIDEO1 */ +	for (i = 1; i < dss_feat_get_num_ovls(); i++) { +		for (j = 0; j < 8; j++) +			DUMPREG(i, DISPC_OVL_FIR_COEF_H, j); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6)); -		DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7)); +		for (j = 0; j < 8; j++) +			DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6)); -		DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7)); +		for (j = 0; j < 5; j++) +			DUMPREG(i, DISPC_OVL_CONV_COEF, j); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6)); -		DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7)); -	} -	if (dss_has_feature(FEAT_ATTR2)) -		DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); +		if (dss_has_feature(FEAT_FIR_COEF_V)) { +			for (j = 0; j < 8; j++) +				DUMPREG(i, DISPC_OVL_FIR_COEF_V, j); +		} + +		if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { +			for (j = 0; j < 8; j++) +				DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j); -	if (dss_has_feature(FEAT_PRELOAD)) { -		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1)); -		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); +			for (j = 0; j < 8; j++) +				DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j); + +			for (j = 0; j < 8; j++) +				DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j); +		}  	}  	dispc_runtime_put(); + +#undef DISPC_REG  #undef DUMPREG  } -static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, -		bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb) +static void _dispc_mgr_set_pol_freq(enum omap_channel channel, bool onoff, +		bool rf, bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, +		u8 acb)  {  	u32 l = 0; @@ -2979,10 +2779,10 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,  	dispc_write_reg(DISPC_POL_FREQ(channel), l);  } -void dispc_set_pol_freq(enum omap_channel channel, +void dispc_mgr_set_pol_freq(enum omap_channel channel,  		enum omap_panel_config config, u8 acbi, u8 acb)  { -	_dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0, +	_dispc_mgr_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,  			(config & OMAP_DSS_LCD_RF) != 0,  			(config & OMAP_DSS_LCD_IEO) != 0,  			(config & OMAP_DSS_LCD_IPC) != 0, @@ -2995,11 +2795,17 @@ void dispc_set_pol_freq(enum omap_channel channel,  void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,  		struct dispc_clock_info *cinfo)  { -	u16 pcd_min = is_tft ? 2 : 3; +	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); + +	if (!is_tft) +		pcd_min = 3; +  	best_pck = 0;  	best_ld = 0;  	best_pd = 0; @@ -3007,7 +2813,7 @@ void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,  	for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {  		unsigned long lck = fck / cur_ld; -		for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { +		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); @@ -3042,7 +2848,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,  {  	if (cinfo->lck_div > 255 || cinfo->lck_div == 0)  		return -EINVAL; -	if (cinfo->pck_div < 2 || cinfo->pck_div > 255) +	if (cinfo->pck_div < 1 || cinfo->pck_div > 255)  		return -EINVAL;  	cinfo->lck = dispc_fclk_rate / cinfo->lck_div; @@ -3051,18 +2857,18 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,  	return 0;  } -int dispc_set_clock_div(enum omap_channel channel, +int dispc_mgr_set_clock_div(enum omap_channel channel,  		struct dispc_clock_info *cinfo)  {  	DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);  	DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); -	dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); +	dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);  	return 0;  } -int dispc_get_clock_div(enum omap_channel channel, +int dispc_mgr_get_clock_div(enum omap_channel channel,  		struct dispc_clock_info *cinfo)  {  	unsigned long fck; @@ -3207,6 +3013,8 @@ static void print_irq_status(u32 status)  	PIS(OCP_ERR);  	PIS(VID1_FIFO_UNDERFLOW);  	PIS(VID2_FIFO_UNDERFLOW); +	if (dss_feat_get_num_ovls() > 3) +		PIS(VID3_FIFO_UNDERFLOW);  	PIS(SYNC_LOST);  	PIS(SYNC_LOST_DIGIT);  	if (dss_has_feature(FEAT_MGR_LCD2)) @@ -3300,178 +3108,72 @@ static void dispc_error_worker(struct work_struct *work)  	int i;  	u32 errors;  	unsigned long flags; +	static const unsigned fifo_underflow_bits[] = { +		DISPC_IRQ_GFX_FIFO_UNDERFLOW, +		DISPC_IRQ_VID1_FIFO_UNDERFLOW, +		DISPC_IRQ_VID2_FIFO_UNDERFLOW, +		DISPC_IRQ_VID3_FIFO_UNDERFLOW, +	}; + +	static const unsigned sync_lost_bits[] = { +		DISPC_IRQ_SYNC_LOST, +		DISPC_IRQ_SYNC_LOST_DIGIT, +		DISPC_IRQ_SYNC_LOST2, +	};  	spin_lock_irqsave(&dispc.irq_lock, flags);  	errors = dispc.error_irqs;  	dispc.error_irqs = 0;  	spin_unlock_irqrestore(&dispc.irq_lock, flags); -	if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) { -		DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n"); -		for (i = 0; i < omap_dss_get_num_overlays(); ++i) { -			struct omap_overlay *ovl; -			ovl = omap_dss_get_overlay(i); - -			if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) -				continue; - -			if (ovl->id == 0) { -				dispc_enable_plane(ovl->id, 0); -				dispc_go(ovl->manager->id); -				mdelay(50); -				break; -			} -		} -	} - -	if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) { -		DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n"); -		for (i = 0; i < omap_dss_get_num_overlays(); ++i) { -			struct omap_overlay *ovl; -			ovl = omap_dss_get_overlay(i); +	dispc_runtime_get(); -			if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) -				continue; +	for (i = 0; i < omap_dss_get_num_overlays(); ++i) { +		struct omap_overlay *ovl; +		unsigned bit; -			if (ovl->id == 1) { -				dispc_enable_plane(ovl->id, 0); -				dispc_go(ovl->manager->id); -				mdelay(50); -				break; -			} -		} -	} - -	if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) { -		DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n"); -		for (i = 0; i < omap_dss_get_num_overlays(); ++i) { -			struct omap_overlay *ovl; -			ovl = omap_dss_get_overlay(i); - -			if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) -				continue; - -			if (ovl->id == 2) { -				dispc_enable_plane(ovl->id, 0); -				dispc_go(ovl->manager->id); -				mdelay(50); -				break; -			} -		} -	} - -	if (errors & DISPC_IRQ_SYNC_LOST) { -		struct omap_overlay_manager *manager = NULL; -		bool enable = false; - -		DSSERR("SYNC_LOST, disabling LCD\n"); - -		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { -			struct omap_overlay_manager *mgr; -			mgr = omap_dss_get_overlay_manager(i); - -			if (mgr->id == OMAP_DSS_CHANNEL_LCD) { -				manager = mgr; -				enable = mgr->device->state == -						OMAP_DSS_DISPLAY_ACTIVE; -				mgr->device->driver->disable(mgr->device); -				break; -			} -		} - -		if (manager) { -			struct omap_dss_device *dssdev = manager->device; -			for (i = 0; i < omap_dss_get_num_overlays(); ++i) { -				struct omap_overlay *ovl; -				ovl = omap_dss_get_overlay(i); - -				if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) -					continue; - -				if (ovl->id != 0 && ovl->manager == manager) -					dispc_enable_plane(ovl->id, 0); -			} +		ovl = omap_dss_get_overlay(i); +		bit = fifo_underflow_bits[i]; -			dispc_go(manager->id); +		if (bit & errors) { +			DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n", +					ovl->name); +			dispc_ovl_enable(ovl->id, false); +			dispc_mgr_go(ovl->manager->id);  			mdelay(50); -			if (enable) -				dssdev->driver->enable(dssdev);  		}  	} -	if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) { -		struct omap_overlay_manager *manager = NULL; -		bool enable = false; - -		DSSERR("SYNC_LOST_DIGIT, disabling TV\n"); - -		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { -			struct omap_overlay_manager *mgr; -			mgr = omap_dss_get_overlay_manager(i); - -			if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) { -				manager = mgr; -				enable = mgr->device->state == -						OMAP_DSS_DISPLAY_ACTIVE; -				mgr->device->driver->disable(mgr->device); -				break; -			} -		} - -		if (manager) { -			struct omap_dss_device *dssdev = manager->device; -			for (i = 0; i < omap_dss_get_num_overlays(); ++i) { -				struct omap_overlay *ovl; -				ovl = omap_dss_get_overlay(i); - -				if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) -					continue; - -				if (ovl->id != 0 && ovl->manager == manager) -					dispc_enable_plane(ovl->id, 0); -			} - -			dispc_go(manager->id); -			mdelay(50); -			if (enable) -				dssdev->driver->enable(dssdev); -		} -	} +	for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { +		struct omap_overlay_manager *mgr; +		unsigned bit; -	if (errors & DISPC_IRQ_SYNC_LOST2) { -		struct omap_overlay_manager *manager = NULL; -		bool enable = false; +		mgr = omap_dss_get_overlay_manager(i); +		bit = sync_lost_bits[i]; -		DSSERR("SYNC_LOST for LCD2, disabling LCD2\n"); +		if (bit & errors) { +			struct omap_dss_device *dssdev = mgr->device; +			bool enable; -		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { -			struct omap_overlay_manager *mgr; -			mgr = omap_dss_get_overlay_manager(i); +			DSSERR("SYNC_LOST on channel %s, restarting the output " +					"with video overlays disabled\n", +					mgr->name); -			if (mgr->id == OMAP_DSS_CHANNEL_LCD2) { -				manager = mgr; -				enable = mgr->device->state == -						OMAP_DSS_DISPLAY_ACTIVE; -				mgr->device->driver->disable(mgr->device); -				break; -			} -		} +			enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE; +			dssdev->driver->disable(dssdev); -		if (manager) { -			struct omap_dss_device *dssdev = manager->device;  			for (i = 0; i < omap_dss_get_num_overlays(); ++i) {  				struct omap_overlay *ovl;  				ovl = omap_dss_get_overlay(i); -				if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) -					continue; - -				if (ovl->id != 0 && ovl->manager == manager) -					dispc_enable_plane(ovl->id, 0); +				if (ovl->id != OMAP_DSS_GFX && +						ovl->manager == mgr) +					dispc_ovl_enable(ovl->id, false);  			} -			dispc_go(manager->id); +			dispc_mgr_go(mgr->id);  			mdelay(50); +  			if (enable)  				dssdev->driver->enable(dssdev);  		} @@ -3482,9 +3184,7 @@ static void dispc_error_worker(struct work_struct *work)  		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {  			struct omap_overlay_manager *mgr;  			mgr = omap_dss_get_overlay_manager(i); - -			if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC) -				mgr->device->driver->disable(mgr->device); +			mgr->device->driver->disable(mgr->device);  		}  	} @@ -3492,6 +3192,8 @@ static void dispc_error_worker(struct work_struct *work)  	dispc.irq_error_mask |= errors;  	_omap_dispc_set_irqs();  	spin_unlock_irqrestore(&dispc.irq_lock, flags); + +	dispc_runtime_put();  }  int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) @@ -3586,6 +3288,8 @@ static void _omap_dispc_initialize_irq(void)  	dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;  	if (dss_has_feature(FEAT_MGR_LCD2))  		dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; +	if (dss_feat_get_num_ovls() > 3) +		dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;  	/* there's SYNC_LOST_DIGIT waiting after enabling the DSS,  	 * so clear it */ @@ -3635,6 +3339,8 @@ static void _omap_dispc_initial_config(void)  	dispc_read_plane_fifo_sizes();  	dispc_configure_burst_sizes(); + +	dispc_ovl_enable_zorder_planes();  }  /* DISPC HW IP initialisation */ @@ -3734,7 +3440,6 @@ static int omap_dispchw_remove(struct platform_device *pdev)  static int dispc_runtime_suspend(struct device *dev)  {  	dispc_save_context(); -	clk_disable(dispc.dss_clk);  	dss_runtime_put();  	return 0; @@ -3748,7 +3453,6 @@ static int dispc_runtime_resume(struct device *dev)  	if (r < 0)  		return r; -	clk_enable(dispc.dss_clk);  	dispc_restore_context();  	return 0; diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h index 6c9ee0a0efb..c06efc38983 100644 --- a/drivers/video/omap2/dss/dispc.h +++ b/drivers/video/omap2/dss/dispc.h @@ -291,6 +291,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)  		return 0x00BC;  	case OMAP_DSS_VIDEO2:  		return 0x014C; +	case OMAP_DSS_VIDEO3: +		return 0x0300;  	default:  		BUG();  	} @@ -304,6 +306,8 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0000; +	case OMAP_DSS_VIDEO3: +		return 0x0008;  	default:  		BUG();  	} @@ -316,6 +320,8 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0004; +	case OMAP_DSS_VIDEO3: +		return 0x000C;  	default:  		BUG();  	} @@ -330,6 +336,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)  		return 0x0544;  	case OMAP_DSS_VIDEO2:  		return 0x04BC; +	case OMAP_DSS_VIDEO3: +		return 0x0310;  	default:  		BUG();  	} @@ -344,6 +352,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)  		return 0x0548;  	case OMAP_DSS_VIDEO2:  		return 0x04C0; +	case OMAP_DSS_VIDEO3: +		return 0x0314;  	default:  		BUG();  	} @@ -356,6 +366,8 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0008; +	case OMAP_DSS_VIDEO3: +		return 0x009C;  	default:  		BUG();  	} @@ -368,6 +380,8 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x000C; +	case OMAP_DSS_VIDEO3: +		return 0x00A8;  	default:  		BUG();  	} @@ -381,6 +395,8 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0010; +	case OMAP_DSS_VIDEO3: +		return 0x0070;  	default:  		BUG();  	} @@ -395,6 +411,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)  		return 0x0568;  	case OMAP_DSS_VIDEO2:  		return 0x04DC; +	case OMAP_DSS_VIDEO3: +		return 0x032C;  	default:  		BUG();  	} @@ -408,6 +426,8 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0014; +	case OMAP_DSS_VIDEO3: +		return 0x008C;  	default:  		BUG();  	} @@ -421,6 +441,8 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0018; +	case OMAP_DSS_VIDEO3: +		return 0x0088;  	default:  		BUG();  	} @@ -434,6 +456,8 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x001C; +	case OMAP_DSS_VIDEO3: +		return 0x00A4;  	default:  		BUG();  	} @@ -447,6 +471,8 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0020; +	case OMAP_DSS_VIDEO3: +		return 0x0098;  	default:  		BUG();  	} @@ -459,6 +485,7 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)  		return 0x0034;  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2: +	case OMAP_DSS_VIDEO3:  		BUG();  	default:  		BUG(); @@ -472,6 +499,7 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)  		return 0x0038;  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2: +	case OMAP_DSS_VIDEO3:  		BUG();  	default:  		BUG(); @@ -486,6 +514,8 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0024; +	case OMAP_DSS_VIDEO3: +		return 0x0090;  	default:  		BUG();  	} @@ -500,6 +530,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)  		return 0x0580;  	case OMAP_DSS_VIDEO2:  		return 0x055C; +	case OMAP_DSS_VIDEO3: +		return 0x0424;  	default:  		BUG();  	} @@ -513,6 +545,8 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0028; +	case OMAP_DSS_VIDEO3: +		return 0x0094;  	default:  		BUG();  	} @@ -527,6 +561,8 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x002C; +	case OMAP_DSS_VIDEO3: +		return 0x0000;  	default:  		BUG();  	} @@ -541,6 +577,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)  		return 0x0584;  	case OMAP_DSS_VIDEO2:  		return 0x0560; +	case OMAP_DSS_VIDEO3: +		return 0x0428;  	default:  		BUG();  	} @@ -554,6 +592,8 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0030; +	case OMAP_DSS_VIDEO3: +		return 0x0004;  	default:  		BUG();  	} @@ -568,6 +608,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)  		return 0x0588;  	case OMAP_DSS_VIDEO2:  		return 0x0564; +	case OMAP_DSS_VIDEO3: +		return 0x042C;  	default:  		BUG();  	} @@ -582,6 +624,8 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0034 + i * 0x8; +	case OMAP_DSS_VIDEO3: +		return 0x0010 + i * 0x8;  	default:  		BUG();  	} @@ -597,6 +641,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)  		return 0x058C + i * 0x8;  	case OMAP_DSS_VIDEO2:  		return 0x0568 + i * 0x8; +	case OMAP_DSS_VIDEO3: +		return 0x0430 + i * 0x8;  	default:  		BUG();  	} @@ -611,6 +657,8 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  		return 0x0038 + i * 0x8; +	case OMAP_DSS_VIDEO3: +		return 0x0014 + i * 0x8;  	default:  		BUG();  	} @@ -626,6 +674,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)  		return 0x0590 + i * 8;  	case OMAP_DSS_VIDEO2:  		return 0x056C + i * 0x8; +	case OMAP_DSS_VIDEO3: +		return 0x0434 + i * 0x8;  	default:  		BUG();  	} @@ -639,6 +689,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)  		BUG();  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2: +	case OMAP_DSS_VIDEO3:  		return 0x0074 + i * 0x4;  	default:  		BUG(); @@ -655,6 +706,8 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)  		return 0x0124 + i * 0x4;  	case OMAP_DSS_VIDEO2:  		return 0x00B4 + i * 0x4; +	case OMAP_DSS_VIDEO3: +		return 0x0050 + i * 0x4;  	default:  		BUG();  	} @@ -670,6 +723,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)  		return 0x05CC + i * 0x4;  	case OMAP_DSS_VIDEO2:  		return 0x05A8 + i * 0x4; +	case OMAP_DSS_VIDEO3: +		return 0x0470 + i * 0x4;  	default:  		BUG();  	} @@ -684,6 +739,8 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)  		return 0x0174;  	case OMAP_DSS_VIDEO2:  		return 0x00E8; +	case OMAP_DSS_VIDEO3: +		return 0x00A0;  	default:  		BUG();  	} diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 94495e45ec5..be331dc5a61 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -45,14 +45,13 @@ static ssize_t display_enabled_store(struct device *dev,  		const char *buf, size_t size)  {  	struct omap_dss_device *dssdev = to_dss_device(dev); -	int r, enabled; +	int r; +	bool enabled; -	r = kstrtoint(buf, 0, &enabled); +	r = strtobool(buf, &enabled);  	if (r)  		return r; -	enabled = !!enabled; -  	if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {  		if (enabled) {  			r = dssdev->driver->enable(dssdev); @@ -79,17 +78,16 @@ static ssize_t display_tear_store(struct device *dev,  		struct device_attribute *attr, const char *buf, size_t size)  {  	struct omap_dss_device *dssdev = to_dss_device(dev); -	int te, r; +	int r; +	bool te;  	if (!dssdev->driver->enable_te || !dssdev->driver->get_te)  		return -ENOENT; -	r = kstrtoint(buf, 0, &te); +	r = strtobool(buf, &te);  	if (r)  		return r; -	te = !!te; -  	r = dssdev->driver->enable_te(dssdev, te);  	if (r)  		return r; @@ -195,17 +193,16 @@ static ssize_t display_mirror_store(struct device *dev,  		struct device_attribute *attr, const char *buf, size_t size)  {  	struct omap_dss_device *dssdev = to_dss_device(dev); -	int mirror, r; +	int r; +	bool mirror;  	if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)  		return -ENOENT; -	r = kstrtoint(buf, 0, &mirror); +	r = strtobool(buf, &mirror);  	if (r)  		return r; -	mirror = !!mirror; -  	r = dssdev->driver->set_mirror(dssdev, mirror);  	if (r)  		return r; @@ -302,11 +299,15 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)  			return 16;  	case OMAP_DISPLAY_TYPE_DBI: -	case OMAP_DISPLAY_TYPE_DSI:  		if (dssdev->ctrl.pixel_size == 24)  			return 24;  		else  			return 16; +	case OMAP_DISPLAY_TYPE_DSI: +		if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16) +			return 24; +		else +			return 16;  	case OMAP_DISPLAY_TYPE_VENC:  	case OMAP_DISPLAY_TYPE_SDI:  	case OMAP_DISPLAY_TYPE_HDMI: @@ -342,9 +343,11 @@ bool dss_use_replication(struct omap_dss_device *dssdev,  		bpp = 24;  		break;  	case OMAP_DISPLAY_TYPE_DBI: -	case OMAP_DISPLAY_TYPE_DSI:  		bpp = dssdev->ctrl.pixel_size;  		break; +	case OMAP_DISPLAY_TYPE_DSI: +		bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +		break;  	default:  		BUG();  	} diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index f053b180ecd..483888a85cf 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -82,9 +82,11 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,  	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); -	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); -	if (r) +	r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); +	if (r) { +		dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);  		return r; +	}  	*fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;  	*lck_div = dispc_cinfo.lck_div; @@ -109,7 +111,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,  	if (r)  		return r; -	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); +	r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);  	if (r)  		return r; @@ -129,7 +131,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)  	bool is_tft;  	int r = 0; -	dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, +	dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,  			dssdev->panel.acbi, dssdev->panel.acb);  	is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; @@ -153,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)  		t->pixel_clock = pck;  	} -	dispc_set_lcd_timings(dssdev->manager->id, t); +	dispc_mgr_set_lcd_timings(dssdev->manager->id, t);  	return 0;  } @@ -164,11 +166,12 @@ static void dpi_basic_init(struct omap_dss_device *dssdev)  	is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; -	dispc_set_parallel_interface_mode(dssdev->manager->id, -			OMAP_DSS_PARALLELMODE_BYPASS); -	dispc_set_lcd_display_type(dssdev->manager->id, is_tft ? +	dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS); +	dispc_mgr_enable_stallmode(dssdev->manager->id, false); + +	dispc_mgr_set_lcd_display_type(dssdev->manager->id, is_tft ?  			OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); -	dispc_set_tft_data_lines(dssdev->manager->id, +	dispc_mgr_set_tft_data_lines(dssdev->manager->id,  			dssdev->phy.dpi.data_lines);  } @@ -176,6 +179,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)  {  	int r; +	if (dssdev->manager == NULL) { +		DSSERR("failed to enable display: no manager\n"); +		return -ENODEV; +	} +  	r = omap_dss_start_device(dssdev);  	if (r) {  		DSSERR("failed to start device\n"); @@ -277,7 +285,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev,  		}  		dpi_set_mode(dssdev); -		dispc_go(dssdev->manager->id); +		dispc_mgr_go(dssdev->manager->id);  		dispc_runtime_put();  		dss_runtime_put(); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 7adbbeb8433..43c04a9889c 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -39,6 +39,7 @@  #include <linux/pm_runtime.h>  #include <video/omapdss.h> +#include <video/mipi_display.h>  #include <plat/clock.h>  #include "dss.h" @@ -131,7 +132,7 @@ struct dsi_reg { u16 idx; };  #define DSI_IRQ_TA_TIMEOUT	(1 << 20)  #define DSI_IRQ_ERROR_MASK \  	(DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ -	DSI_IRQ_TA_TIMEOUT) +	DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST)  #define DSI_IRQ_CHANNEL_MASK	0xf  /* Virtual channel interrupts */ @@ -198,18 +199,6 @@ struct dsi_reg { u16 idx; };  	 DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \  	 DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5) -#define DSI_DT_DCS_SHORT_WRITE_0	0x05 -#define DSI_DT_DCS_SHORT_WRITE_1	0x15 -#define DSI_DT_DCS_READ			0x06 -#define DSI_DT_SET_MAX_RET_PKG_SIZE	0x37 -#define DSI_DT_NULL_PACKET		0x09 -#define DSI_DT_DCS_LONG_WRITE		0x39 - -#define DSI_DT_RX_ACK_WITH_ERR		0x02 -#define DSI_DT_RX_DCS_LONG_READ		0x1c -#define DSI_DT_RX_SHORT_READ_1		0x21 -#define DSI_DT_RX_SHORT_READ_2		0x22 -  typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);  #define DSI_MAX_NR_ISRS                2 @@ -228,9 +217,9 @@ enum fifo_size {  	DSI_FIFO_SIZE_128	= 4,  }; -enum dsi_vc_mode { -	DSI_VC_MODE_L4 = 0, -	DSI_VC_MODE_VP, +enum dsi_vc_source { +	DSI_VC_SOURCE_L4 = 0, +	DSI_VC_SOURCE_VP,  };  enum dsi_lane { @@ -274,7 +263,8 @@ struct dsi_data {  	struct clk *dss_clk;  	struct clk *sys_clk; -	void (*dsi_mux_pads)(bool enable); +	int (*enable_pads)(int dsi_id, unsigned lane_mask); +	void (*disable_pads)(int dsi_id, unsigned lane_mask);  	struct dsi_clock_info current_cinfo; @@ -282,7 +272,7 @@ struct dsi_data {  	struct regulator *vdds_dsi_reg;  	struct { -		enum dsi_vc_mode mode; +		enum dsi_vc_source source;  		struct omap_dss_device *dssdev;  		enum fifo_size fifo_size;  		int vc_id; @@ -368,14 +358,9 @@ struct platform_device *dsi_get_dsidev_from_id(int module)  	return dsi_pdev_map[module];  } -static int dsi_get_dsidev_id(struct platform_device *dsidev) +static inline int dsi_get_dsidev_id(struct platform_device *dsidev)  { -	/* TEMP: Pass 0 as the dsi module index till the time the dsi platform -	 * device names aren't changed to the form "omapdss_dsi.0", -	 * "omapdss_dsi.1" and so on */ -	BUG_ON(dsidev->id != -1); - -	return 0; +	return dsidev->id;  }  static inline void dsi_write_reg(struct platform_device *dsidev, @@ -437,6 +422,21 @@ static inline int wait_for_bit_change(struct platform_device *dsidev,  	return value;  } +u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) +{ +	switch (fmt) { +	case OMAP_DSS_DSI_FMT_RGB888: +	case OMAP_DSS_DSI_FMT_RGB666: +		return 24; +	case OMAP_DSS_DSI_FMT_RGB666_PACKED: +		return 18; +	case OMAP_DSS_DSI_FMT_RGB565: +		return 16; +	default: +		BUG(); +	} +} +  #ifdef DEBUG  static void dsi_perf_mark_setup(struct platform_device *dsidev)  { @@ -453,6 +453,7 @@ static void dsi_perf_mark_start(struct platform_device *dsidev)  static void dsi_perf_show(struct platform_device *dsidev, const char *name)  {  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_dss_device *dssdev = dsi->update_region.device;  	ktime_t t, setup_time, trans_time;  	u32 total_bytes;  	u32 setup_us, trans_us, total_us; @@ -476,7 +477,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)  	total_bytes = dsi->update_region.w *  		dsi->update_region.h * -		dsi->update_region.device->ctrl.pixel_size / 8; +		dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;  	printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "  			"%u bytes, %u kbytes/sec\n", @@ -1287,7 +1288,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,  		 * with DSS_SYS_CLK source also */  		cinfo->highfreq = 0;  	} else { -		cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); +		cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id);  		if (cinfo->clkin < 32000000)  			cinfo->highfreq = 0; @@ -2360,6 +2361,24 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)  	return 0;  } +static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) +{ +	unsigned lanes = 0; + +	if (dssdev->phy.dsi.clk_lane != 0) +		lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1); +	if (dssdev->phy.dsi.data1_lane != 0) +		lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1); +	if (dssdev->phy.dsi.data2_lane != 0) +		lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1); +	if (dssdev->phy.dsi.data3_lane != 0) +		lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1); +	if (dssdev->phy.dsi.data4_lane != 0) +		lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1); + +	return lanes; +} +  static int dsi_cio_init(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -2370,8 +2389,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  	DSSDBGF(); -	if (dsi->dsi_mux_pads) -		dsi->dsi_mux_pads(true); +	r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); +	if (r) +		return r;  	dsi_enable_scp_clk(dsidev); @@ -2452,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  	dsi_cio_timings(dsidev); +	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +		/* DDR_CLK_ALWAYS_ON */ +		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, +			dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); +	} +  	dsi->ulps_enabled = false;  	DSSDBG("CIO init done\n"); @@ -2467,19 +2493,21 @@ err_cio_pwr:  		dsi_cio_disable_lane_override(dsidev);  err_scp_clk_dom:  	dsi_disable_scp_clk(dsidev); -	if (dsi->dsi_mux_pads) -		dsi->dsi_mux_pads(false); +	dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));  	return r;  } -static void dsi_cio_uninit(struct platform_device *dsidev) +static void dsi_cio_uninit(struct omap_dss_device *dssdev)  { +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	/* DDR_CLK_ALWAYS_ON */ +	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13); +  	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);  	dsi_disable_scp_clk(dsidev); -	if (dsi->dsi_mux_pads) -		dsi->dsi_mux_pads(false); +	dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));  }  static void dsi_config_tx_fifo(struct platform_device *dsidev, @@ -2669,10 +2697,10 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel)  	if (!dsi_vc_is_enabled(dsidev, channel))  		return 0; -	switch (dsi->vc[channel].mode) { -	case DSI_VC_MODE_VP: +	switch (dsi->vc[channel].source) { +	case DSI_VC_SOURCE_VP:  		return dsi_sync_vc_vp(dsidev, channel); -	case DSI_VC_MODE_L4: +	case DSI_VC_SOURCE_L4:  		return dsi_sync_vc_l4(dsidev, channel);  	default:  		BUG(); @@ -2726,43 +2754,12 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)  	dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);  } -static int dsi_vc_config_l4(struct platform_device *dsidev, int channel) -{ -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - -	if (dsi->vc[channel].mode == DSI_VC_MODE_L4) -		return 0; - -	DSSDBGF("%d", channel); - -	dsi_sync_vc(dsidev, channel); - -	dsi_vc_enable(dsidev, channel, 0); - -	/* VC_BUSY */ -	if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) { -		DSSERR("vc(%d) busy when trying to config for L4\n", channel); -		return -EIO; -	} - -	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ - -	/* DCS_CMD_ENABLE */ -	if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) -		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30); - -	dsi_vc_enable(dsidev, channel, 1); - -	dsi->vc[channel].mode = DSI_VC_MODE_L4; - -	return 0; -} - -static int dsi_vc_config_vp(struct platform_device *dsidev, int channel) +static int dsi_vc_config_source(struct platform_device *dsidev, int channel, +		enum dsi_vc_source source)  {  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	if (dsi->vc[channel].mode == DSI_VC_MODE_VP) +	if (dsi->vc[channel].source == source)  		return 0;  	DSSDBGF("%d", channel); @@ -2777,21 +2774,22 @@ static int dsi_vc_config_vp(struct platform_device *dsidev, int channel)  		return -EIO;  	} -	/* SOURCE, 1 = video port */ -	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1); +	/* SOURCE, 0 = L4, 1 = video port */ +	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);  	/* DCS_CMD_ENABLE */ -	if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) -		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30); +	if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { +		bool enable = source == DSI_VC_SOURCE_VP; +		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30); +	}  	dsi_vc_enable(dsidev, channel, 1); -	dsi->vc[channel].mode = DSI_VC_MODE_VP; +	dsi->vc[channel].source = source;  	return 0;  } -  void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,  		bool enable)  { @@ -2810,6 +2808,10 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,  	dsi_if_enable(dsidev, 1);  	dsi_force_tx_stop_mode_io(dsidev); + +	/* start the DDR clock by sending a NULL packet */ +	if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable) +		dsi_vc_send_null(dssdev, channel);  }  EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); @@ -2873,16 +2875,16 @@ static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev,  		val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));  		DSSERR("\trawval %#08x\n", val);  		dt = FLD_GET(val, 5, 0); -		if (dt == DSI_DT_RX_ACK_WITH_ERR) { +		if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {  			u16 err = FLD_GET(val, 23, 8);  			dsi_show_rx_ack_with_err(err); -		} else if (dt == DSI_DT_RX_SHORT_READ_1) { +		} else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) {  			DSSERR("\tDCS short response, 1 byte: %#x\n",  					FLD_GET(val, 23, 8)); -		} else if (dt == DSI_DT_RX_SHORT_READ_2) { +		} else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {  			DSSERR("\tDCS short response, 2 byte: %#x\n",  					FLD_GET(val, 23, 8)); -		} else if (dt == DSI_DT_RX_DCS_LONG_READ) { +		} else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {  			DSSERR("\tDCS long response, len %d\n",  					FLD_GET(val, 23, 8));  			dsi_vc_flush_long_data(dsidev, channel); @@ -3007,7 +3009,7 @@ static int dsi_vc_send_long(struct platform_device *dsidev, int channel,  		return -EINVAL;  	} -	dsi_vc_config_l4(dsidev, channel); +	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);  	dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc); @@ -3066,7 +3068,7 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,  				channel,  				data_type, data & 0xff, (data >> 8) & 0xff); -	dsi_vc_config_l4(dsidev, channel); +	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);  	if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) {  		DSSERR("ERROR FIFO FULL, aborting transfer\n"); @@ -3085,44 +3087,66 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,  int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); -	u8 nullpkg[] = {0, 0, 0, 0}; -	return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg, -		4, 0); +	return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL, +		0, 0);  }  EXPORT_SYMBOL(dsi_vc_send_null); -int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, -		u8 *data, int len) +static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, +		int channel, u8 *data, int len, enum dss_dsi_content_type type)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r; -	BUG_ON(len == 0); - -	if (len == 1) { -		r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0, -				data[0], 0); +	if (len == 0) { +		BUG_ON(type == DSS_DSI_CONTENT_DCS); +		r = dsi_vc_send_short(dsidev, channel, +				MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0); +	} else if (len == 1) { +		r = dsi_vc_send_short(dsidev, channel, +				type == DSS_DSI_CONTENT_GENERIC ? +				MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM : +				MIPI_DSI_DCS_SHORT_WRITE, data[0], 0);  	} else if (len == 2) { -		r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1, +		r = dsi_vc_send_short(dsidev, channel, +				type == DSS_DSI_CONTENT_GENERIC ? +				MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM : +				MIPI_DSI_DCS_SHORT_WRITE_PARAM,  				data[0] | (data[1] << 8), 0);  	} else { -		/* 0x39 = DCS Long Write */ -		r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE, -				data, len, 0); +		r = dsi_vc_send_long(dsidev, channel, +				type == DSS_DSI_CONTENT_GENERIC ? +				MIPI_DSI_GENERIC_LONG_WRITE : +				MIPI_DSI_DCS_LONG_WRITE, data, len, 0);  	}  	return r;  } + +int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, +		u8 *data, int len) +{ +	return dsi_vc_write_nosync_common(dssdev, channel, data, len, +			DSS_DSI_CONTENT_DCS); +}  EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); -int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, -		int len) +int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, +		u8 *data, int len) +{ +	return dsi_vc_write_nosync_common(dssdev, channel, data, len, +			DSS_DSI_CONTENT_GENERIC); +} +EXPORT_SYMBOL(dsi_vc_generic_write_nosync); + +static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel, +		u8 *data, int len, enum dss_dsi_content_type type)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r; -	r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len); +	r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type);  	if (r)  		goto err; @@ -3140,18 +3164,39 @@ int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,  	return 0;  err: -	DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n", +	DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n",  			channel, data[0], len);  	return r;  } + +int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, +		int len) +{ +	return dsi_vc_write_common(dssdev, channel, data, len, +			DSS_DSI_CONTENT_DCS); +}  EXPORT_SYMBOL(dsi_vc_dcs_write); +int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data, +		int len) +{ +	return dsi_vc_write_common(dssdev, channel, data, len, +			DSS_DSI_CONTENT_GENERIC); +} +EXPORT_SYMBOL(dsi_vc_generic_write); +  int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd)  {  	return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1);  }  EXPORT_SYMBOL(dsi_vc_dcs_write_0); +int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel) +{ +	return dsi_vc_generic_write(dssdev, channel, NULL, 0); +} +EXPORT_SYMBOL(dsi_vc_generic_write_0); +  int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  		u8 param)  { @@ -3162,25 +3207,87 @@ int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  }  EXPORT_SYMBOL(dsi_vc_dcs_write_1); -int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, -		u8 *buf, int buflen) +int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel, +		u8 param) +{ +	return dsi_vc_generic_write(dssdev, channel, ¶m, 1); +} +EXPORT_SYMBOL(dsi_vc_generic_write_1); + +int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel, +		u8 param1, u8 param2) +{ +	u8 buf[2]; +	buf[0] = param1; +	buf[1] = param2; +	return dsi_vc_generic_write(dssdev, channel, buf, 2); +} +EXPORT_SYMBOL(dsi_vc_generic_write_2); + +static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, +		int channel, u8 dcs_cmd)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	u32 val; -	u8 dt;  	int r;  	if (dsi->debug_read) -		DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); +		DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n", +			channel, dcs_cmd); -	r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0); -	if (r) -		goto err; +	r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0); +	if (r) { +		DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)" +			" failed\n", channel, dcs_cmd); +		return r; +	} -	r = dsi_vc_send_bta_sync(dssdev, channel); -	if (r) -		goto err; +	return 0; +} + +static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, +		int channel, u8 *reqdata, int reqlen) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	u16 data; +	u8 data_type; +	int r; + +	if (dsi->debug_read) +		DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n", +			channel, reqlen); + +	if (reqlen == 0) { +		data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM; +		data = 0; +	} else if (reqlen == 1) { +		data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM; +		data = reqdata[0]; +	} else if (reqlen == 2) { +		data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; +		data = reqdata[0] | (reqdata[1] << 8); +	} else { +		BUG(); +	} + +	r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); +	if (r) { +		DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)" +			" failed\n", channel, reqlen); +		return r; +	} + +	return 0; +} + +static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel, +		u8 *buf, int buflen, enum dss_dsi_content_type type) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	u32 val; +	u8 dt; +	int r;  	/* RX_FIFO_NOT_EMPTY */  	if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) { @@ -3193,16 +3300,20 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  	if (dsi->debug_read)  		DSSDBG("\theader: %08x\n", val);  	dt = FLD_GET(val, 5, 0); -	if (dt == DSI_DT_RX_ACK_WITH_ERR) { +	if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {  		u16 err = FLD_GET(val, 23, 8);  		dsi_show_rx_ack_with_err(err);  		r = -EIO;  		goto err; -	} else if (dt == DSI_DT_RX_SHORT_READ_1) { +	} else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? +			MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE : +			MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) {  		u8 data = FLD_GET(val, 15, 8);  		if (dsi->debug_read) -			DSSDBG("\tDCS short response, 1 byte: %02x\n", data); +			DSSDBG("\t%s short response, 1 byte: %02x\n", +				type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : +				"DCS", data);  		if (buflen < 1) {  			r = -EIO; @@ -3212,10 +3323,14 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  		buf[0] = data;  		return 1; -	} else if (dt == DSI_DT_RX_SHORT_READ_2) { +	} else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? +			MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE : +			MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) {  		u16 data = FLD_GET(val, 23, 8);  		if (dsi->debug_read) -			DSSDBG("\tDCS short response, 2 byte: %04x\n", data); +			DSSDBG("\t%s short response, 2 byte: %04x\n", +				type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : +				"DCS", data);  		if (buflen < 2) {  			r = -EIO; @@ -3226,11 +3341,15 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  		buf[1] = (data >> 8) & 0xff;  		return 2; -	} else if (dt == DSI_DT_RX_DCS_LONG_READ) { +	} else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? +			MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE : +			MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) {  		int w;  		int len = FLD_GET(val, 23, 8);  		if (dsi->debug_read) -			DSSDBG("\tDCS long response, len %d\n", len); +			DSSDBG("\t%s long response, len %d\n", +				type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : +				"DCS", len);  		if (len > buflen) {  			r = -EIO; @@ -3266,58 +3385,126 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  	BUG();  err: -	DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", -			channel, dcs_cmd); +	DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, +		type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); +  	return r; +} +int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, +		u8 *buf, int buflen) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	int r; + +	r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd); +	if (r) +		goto err; + +	r = dsi_vc_send_bta_sync(dssdev, channel); +	if (r) +		goto err; + +	r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen, +		DSS_DSI_CONTENT_DCS); +	if (r < 0) +		goto err; + +	if (r != buflen) { +		r = -EIO; +		goto err; +	} + +	return 0; +err: +	DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd); +	return r;  }  EXPORT_SYMBOL(dsi_vc_dcs_read); -int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, -		u8 *data) +static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel, +		u8 *reqdata, int reqlen, u8 *buf, int buflen)  { +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r; -	r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1); +	r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); +	if (r) +		return r; + +	r = dsi_vc_send_bta_sync(dssdev, channel); +	if (r) +		return r; +	r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen, +		DSS_DSI_CONTENT_GENERIC);  	if (r < 0)  		return r; -	if (r != 1) -		return -EIO; +	if (r != buflen) { +		r = -EIO; +		return r; +	}  	return 0;  } -EXPORT_SYMBOL(dsi_vc_dcs_read_1); -int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, -		u8 *data1, u8 *data2) +int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf, +		int buflen)  { -	u8 buf[2];  	int r; -	r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2); +	r = dsi_vc_generic_read(dssdev, channel, NULL, 0, buf, buflen); +	if (r) { +		DSSERR("dsi_vc_generic_read_0(ch %d) failed\n", channel); +		return r; +	} -	if (r < 0) +	return 0; +} +EXPORT_SYMBOL(dsi_vc_generic_read_0); + +int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param, +		u8 *buf, int buflen) +{ +	int r; + +	r = dsi_vc_generic_read(dssdev, channel, ¶m, 1, buf, buflen); +	if (r) { +		DSSERR("dsi_vc_generic_read_1(ch %d) failed\n", channel);  		return r; +	} -	if (r != 2) -		return -EIO; +	return 0; +} +EXPORT_SYMBOL(dsi_vc_generic_read_1); -	*data1 = buf[0]; -	*data2 = buf[1]; +int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel, +		u8 param1, u8 param2, u8 *buf, int buflen) +{ +	int r; +	u8 reqdata[2]; + +	reqdata[0] = param1; +	reqdata[1] = param2; + +	r = dsi_vc_generic_read(dssdev, channel, reqdata, 2, buf, buflen); +	if (r) { +		DSSERR("dsi_vc_generic_read_2(ch %d) failed\n", channel); +		return r; +	}  	return 0;  } -EXPORT_SYMBOL(dsi_vc_dcs_read_2); +EXPORT_SYMBOL(dsi_vc_generic_read_2);  int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,  		u16 len)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); -	return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE, -			len, 0); +	return dsi_vc_send_short(dsidev, channel, +			MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);  }  EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); @@ -3508,6 +3695,75 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,  			ticks, x4 ? " x4" : "", x16 ? " x16" : "",  			(total_ticks * 1000) / (fck / 1000 / 1000));  } + +static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	int num_line_buffers; + +	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +		int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +		unsigned line_buf_size = dsi_get_line_buf_size(dsidev); +		struct omap_video_timings *timings = &dssdev->panel.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) +			num_line_buffers = 0; +		else +			num_line_buffers = 2; +	} else { +		/* Use maximum number of line buffers in command mode */ +		num_line_buffers = 2; +	} + +	/* LINE_BUFFER */ +	REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12); +} + +static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	int de_pol = dssdev->panel.dsi_vm_data.vp_de_pol; +	int hsync_pol = dssdev->panel.dsi_vm_data.vp_hsync_pol; +	int vsync_pol = dssdev->panel.dsi_vm_data.vp_vsync_pol; +	bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; +	bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; +	u32 r; + +	r = dsi_read_reg(dsidev, DSI_CTRL); +	r = FLD_MOD(r, de_pol, 9, 9);		/* VP_DE_POL */ +	r = FLD_MOD(r, hsync_pol, 10, 10);	/* VP_HSYNC_POL */ +	r = FLD_MOD(r, vsync_pol, 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, 1, 17, 17);		/* VP_HSYNC_START */ +	r = FLD_MOD(r, hsync_end, 18, 18);	/* VP_HSYNC_END */ +	dsi_write_reg(dsidev, DSI_CTRL, r); +} + +static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode; +	int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode; +	int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode; +	int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode; +	u32 r; + +	/* +	 * 0 = TX FIFO packets sent or LPS in corresponding blanking periods +	 * 1 = Long blanking packets are sent in corresponding blanking periods +	 */ +	r = dsi_read_reg(dsidev, DSI_CTRL); +	r = FLD_MOD(r, blanking_mode, 20, 20);		/* BLANKING_MODE */ +	r = FLD_MOD(r, hfp_blanking_mode, 21, 21);	/* HFP_BLANKING */ +	r = FLD_MOD(r, hbp_blanking_mode, 22, 22);	/* HBP_BLANKING */ +	r = FLD_MOD(r, hsa_blanking_mode, 23, 23);	/* HSA_BLANKING */ +	dsi_write_reg(dsidev, DSI_CTRL, r); +} +  static int dsi_proto_config(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -3530,7 +3786,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);  	dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); -	switch (dssdev->ctrl.pixel_size) { +	switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) {  	case 16:  		buswidth = 0;  		break; @@ -3551,7 +3807,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	r = FLD_MOD(r, 1, 4, 4);	/* VP_CLK_RATIO, always 1, see errata*/  	r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */  	r = FLD_MOD(r, 0, 8, 8);	/* VP_CLK_POL */ -	r = FLD_MOD(r, 2, 13, 12);	/* LINE_BUFFER, 2 lines */  	r = FLD_MOD(r, 1, 14, 14);	/* TRIGGER_RESET_MODE */  	r = FLD_MOD(r, 1, 19, 19);	/* EOT_ENABLE */  	if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { @@ -3562,6 +3817,13 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	dsi_write_reg(dsidev, DSI_CTRL, r); +	dsi_config_vp_num_line_buffers(dssdev); + +	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +		dsi_config_vp_sync_events(dssdev); +		dsi_config_blanking_modes(dssdev); +	} +  	dsi_vc_initial_config(dsidev, 0);  	dsi_vc_initial_config(dsidev, 1);  	dsi_vc_initial_config(dsidev, 2); @@ -3580,6 +3842,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)  	unsigned ddr_clk_pre, ddr_clk_post;  	unsigned enter_hs_mode_lat, exit_hs_mode_lat;  	unsigned ths_eot; +	int ndl = dsi_get_num_data_lanes_dssdev(dssdev);  	u32 r;  	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); @@ -3602,7 +3865,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)  	/* min 60ns + 52*UI */  	tclk_post = ns2ddr(dsidev, 60) + 26; -	ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev)); +	ths_eot = DIV_ROUND_UP(4, ndl);  	ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,  			4); @@ -3632,162 +3895,114 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)  	DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",  			enter_hs_mode_lat, exit_hs_mode_lat); -} +	 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +		/* TODO: Implement a video mode check_timings function */ +		int hsa = dssdev->panel.dsi_vm_data.hsa; +		int hfp = dssdev->panel.dsi_vm_data.hfp; +		int hbp = dssdev->panel.dsi_vm_data.hbp; +		int vsa = dssdev->panel.dsi_vm_data.vsa; +		int vfp = dssdev->panel.dsi_vm_data.vfp; +		int vbp = dssdev->panel.dsi_vm_data.vbp; +		int window_sync = dssdev->panel.dsi_vm_data.window_sync; +		bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; +		struct omap_video_timings *timings = &dssdev->panel.timings; +		int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +		int tl, t_he, width_bytes; -#define DSI_DECL_VARS \ -	int __dsi_cb = 0; u32 __dsi_cv = 0; +		t_he = hsync_end ? +			((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; -#define DSI_FLUSH(dsidev, ch) \ -	if (__dsi_cb > 0) { \ -		/*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ -		dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ -		__dsi_cb = __dsi_cv = 0; \ -	} +		width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); -#define DSI_PUSH(dsidev, ch, data) \ -	do { \ -		__dsi_cv |= (data) << (__dsi_cb * 8); \ -		/*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ -		if (++__dsi_cb > 3) \ -			DSI_FLUSH(dsidev, ch); \ -	} while (0) +		/* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */ +		tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp + +			DIV_ROUND_UP(width_bytes + 6, ndl) + hbp; -static int dsi_update_screen_l4(struct omap_dss_device *dssdev, -			int x, int y, int w, int h) -{ -	/* Note: supports only 24bit colors in 32bit container */ -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	int first = 1; -	int fifo_stalls = 0; -	int max_dsi_packet_size; -	int max_data_per_packet; -	int max_pixels_per_packet; -	int pixels_left; -	int bytespp = dssdev->ctrl.pixel_size / 8; -	int scr_width; -	u32 __iomem *data; -	int start_offset; -	int horiz_inc; -	int current_x; -	struct omap_overlay *ovl; +		DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp, +			hfp, hsync_end ? hsa : 0, tl); +		DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp, +			vsa, timings->y_res); -	debug_irq = 0; - -	DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n", -			x, y, w, h); +		r = dsi_read_reg(dsidev, DSI_VM_TIMING1); +		r = FLD_MOD(r, hbp, 11, 0);	/* HBP */ +		r = FLD_MOD(r, hfp, 23, 12);	/* HFP */ +		r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24);	/* HSA */ +		dsi_write_reg(dsidev, DSI_VM_TIMING1, r); -	ovl = dssdev->manager->overlays[0]; +		r = dsi_read_reg(dsidev, DSI_VM_TIMING2); +		r = FLD_MOD(r, vbp, 7, 0);	/* VBP */ +		r = FLD_MOD(r, vfp, 15, 8);	/* VFP */ +		r = FLD_MOD(r, vsa, 23, 16);	/* VSA */ +		r = FLD_MOD(r, window_sync, 27, 24);	/* WINDOW_SYNC */ +		dsi_write_reg(dsidev, DSI_VM_TIMING2, r); -	if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U) -		return -EINVAL; - -	if (dssdev->ctrl.pixel_size != 24) -		return -EINVAL; - -	scr_width = ovl->info.screen_width; -	data = ovl->info.vaddr; - -	start_offset = scr_width * y + x; -	horiz_inc = scr_width - w; -	current_x = x; - -	/* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes -	 * in fifo */ - -	/* When using CPU, max long packet size is TX buffer size */ -	max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4; - -	/* we seem to get better perf if we divide the tx fifo to half, -	   and while the other half is being sent, we fill the other half -	   max_dsi_packet_size /= 2; */ - -	max_data_per_packet = max_dsi_packet_size - 4 - 1; - -	max_pixels_per_packet = max_data_per_packet / bytespp; +		r = dsi_read_reg(dsidev, DSI_VM_TIMING3); +		r = FLD_MOD(r, timings->y_res, 14, 0);	/* VACT */ +		r = FLD_MOD(r, tl, 31, 16);		/* TL */ +		dsi_write_reg(dsidev, DSI_VM_TIMING3, r); +	} +} -	DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet); +int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +	u8 data_type; +	u16 word_count; -	pixels_left = w * h; +	switch (dssdev->panel.dsi_pix_fmt) { +	case OMAP_DSS_DSI_FMT_RGB888: +		data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; +		break; +	case OMAP_DSS_DSI_FMT_RGB666: +		data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; +		break; +	case OMAP_DSS_DSI_FMT_RGB666_PACKED: +		data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; +		break; +	case OMAP_DSS_DSI_FMT_RGB565: +		data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; +		break; +	default: +		BUG(); +	}; -	DSSDBG("total pixels %d\n", pixels_left); +	dsi_if_enable(dsidev, false); +	dsi_vc_enable(dsidev, channel, false); -	data += start_offset; +	/* MODE, 1 = video mode */ +	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); -	while (pixels_left > 0) { -		/* 0x2c = write_memory_start */ -		/* 0x3c = write_memory_continue */ -		u8 dcs_cmd = first ? 0x2c : 0x3c; -		int pixels; -		DSI_DECL_VARS; -		first = 0; +	word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); -#if 1 -		/* using fifo not empty */ -		/* TX_FIFO_NOT_EMPTY */ -		while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) { -			fifo_stalls++; -			if (fifo_stalls > 0xfffff) { -				DSSERR("fifo stalls overflow, pixels left %d\n", -						pixels_left); -				dsi_if_enable(dsidev, 0); -				return -EIO; -			} -			udelay(1); -		} -#elif 1 -		/* using fifo emptiness */ -		while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < -				max_dsi_packet_size) { -			fifo_stalls++; -			if (fifo_stalls > 0xfffff) { -				DSSERR("fifo stalls overflow, pixels left %d\n", -					       pixels_left); -				dsi_if_enable(dsidev, 0); -				return -EIO; -			} -		} -#else -		while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, -				7, 0) + 1) * 4 == 0) { -			fifo_stalls++; -			if (fifo_stalls > 0xfffff) { -				DSSERR("fifo stalls overflow, pixels left %d\n", -					       pixels_left); -				dsi_if_enable(dsidev, 0); -				return -EIO; -			} -		} -#endif -		pixels = min(max_pixels_per_packet, pixels_left); +	dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0); -		pixels_left -= pixels; +	dsi_vc_enable(dsidev, channel, true); +	dsi_if_enable(dsidev, true); -		dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE, -				1 + pixels * bytespp, 0); +	dssdev->manager->enable(dssdev->manager); -		DSI_PUSH(dsidev, 0, dcs_cmd); +	return 0; +} +EXPORT_SYMBOL(dsi_video_mode_enable); -		while (pixels-- > 0) { -			u32 pix = __raw_readl(data++); +void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); -			DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff); -			DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff); -			DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff); +	dsi_if_enable(dsidev, false); +	dsi_vc_enable(dsidev, channel, false); -			current_x++; -			if (current_x == x+w) { -				current_x = x; -				data += horiz_inc; -			} -		} +	/* MODE, 0 = command mode */ +	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4); -		DSI_FLUSH(dsidev, 0); -	} +	dsi_vc_enable(dsidev, channel, true); +	dsi_if_enable(dsidev, true); -	return 0; +	dssdev->manager->disable(dssdev->manager);  } +EXPORT_SYMBOL(dsi_video_mode_disable);  static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,  		u16 x, u16 y, u16 w, u16 h) @@ -3808,9 +4023,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,  	DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",  			x, y, w, h); -	dsi_vc_config_vp(dsidev, channel); +	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); -	bytespp	= dssdev->ctrl.pixel_size / 8; +	bytespp	= dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;  	bytespl = w * bytespp;  	bytespf = bytespl * h; @@ -3831,7 +4046,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,  	l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */  	dsi_write_reg(dsidev, DSI_VC_TE(channel), l); -	dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE, +	dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE,  		packet_len, 0);  	if (dsi->te_enabled) @@ -3956,11 +4171,9 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,  	dsi_perf_mark_setup(dsidev); -	if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { -		dss_setup_partial_planes(dssdev, x, y, w, h, -				enlarge_update_area); -		dispc_set_lcd_size(dssdev->manager->id, *w, *h); -	} +	dss_setup_partial_planes(dssdev, x, y, w, h, +			enlarge_update_area); +	dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);  	return 0;  } @@ -3982,27 +4195,16 @@ int omap_dsi_update(struct omap_dss_device *dssdev,  	 * see rather obscure HW error happening, as DSS halts. */  	BUG_ON(x % 2 == 1); -	if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { -		dsi->framedone_callback = callback; -		dsi->framedone_data = data; - -		dsi->update_region.x = x; -		dsi->update_region.y = y; -		dsi->update_region.w = w; -		dsi->update_region.h = h; -		dsi->update_region.device = dssdev; - -		dsi_update_screen_dispc(dssdev, x, y, w, h); -	} else { -		int r; +	dsi->framedone_callback = callback; +	dsi->framedone_data = data; -		r = dsi_update_screen_l4(dssdev, x, y, w, h); -		if (r) -			return r; +	dsi->update_region.x = x; +	dsi->update_region.y = y; +	dsi->update_region.w = w; +	dsi->update_region.h = h; +	dsi->update_region.device = dssdev; -		dsi_perf_show(dsidev, "L4"); -		callback(0, data); -	} +	dsi_update_screen_dispc(dssdev, x, y, w, h);  	return 0;  } @@ -4013,28 +4215,9 @@ EXPORT_SYMBOL(omap_dsi_update);  static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  {  	int r; -	u32 irq; - -	irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? -		DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; -	r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev, -			irq); -	if (r) { -		DSSERR("can't get FRAMEDONE irq\n"); -		return r; -	} - -	dispc_set_lcd_display_type(dssdev->manager->id, -			OMAP_DSS_LCD_DISPLAY_TFT); - -	dispc_set_parallel_interface_mode(dssdev->manager->id, -			OMAP_DSS_PARALLELMODE_DSI); -	dispc_enable_fifohandcheck(dssdev->manager->id, 1); - -	dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); - -	{ +	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { +		u32 irq;  		struct omap_video_timings timings = {  			.hsw		= 1,  			.hfp		= 1, @@ -4044,21 +4227,46 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  			.vbp		= 0,  		}; -		dispc_set_lcd_timings(dssdev->manager->id, &timings); +		irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? +			DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; + +		r = omap_dispc_register_isr(dsi_framedone_irq_callback, +			(void *) dssdev, irq); +		if (r) { +			DSSERR("can't get FRAMEDONE irq\n"); +			return r; +		} + +		dispc_mgr_enable_stallmode(dssdev->manager->id, true); +		dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); + +		dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); +	} else { +		dispc_mgr_enable_stallmode(dssdev->manager->id, false); +		dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); + +		dispc_mgr_set_lcd_timings(dssdev->manager->id, +			&dssdev->panel.timings);  	} +		dispc_mgr_set_lcd_display_type(dssdev->manager->id, +			OMAP_DSS_LCD_DISPLAY_TFT); +		dispc_mgr_set_tft_data_lines(dssdev->manager->id, +			dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt));  	return 0;  }  static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)  { -	u32 irq; +	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { +		u32 irq; -	irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? -		DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; +		irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? +			DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; -	omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev, -			irq); +		omap_dispc_unregister_isr(dsi_framedone_irq_callback, +			(void *) dssdev, irq); +	}  }  static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) @@ -4106,7 +4314,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)  		return r;  	} -	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); +	r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);  	if (r) {  		DSSERR("Failed to set dispc clocks\n");  		return r; @@ -4166,10 +4374,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)  	return 0;  err3: -	dsi_cio_uninit(dsidev); +	dsi_cio_uninit(dssdev);  err2:  	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);  	dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); +	dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); +  err1:  	dsi_pll_uninit(dsidev, true);  err0: @@ -4195,7 +4405,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,  	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);  	dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); -	dsi_cio_uninit(dsidev); +	dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); +	dsi_cio_uninit(dssdev);  	dsi_pll_uninit(dsidev, disconnect_lanes);  } @@ -4211,6 +4422,12 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)  	mutex_lock(&dsi->lock); +	if (dssdev->manager == NULL) { +		DSSERR("failed to enable display: no manager\n"); +		r = -ENODEV; +		goto err_start_dev; +	} +  	r = omap_dss_start_device(dssdev);  	if (r) {  		DSSERR("failed to start device\n"); @@ -4307,9 +4524,10 @@ int dsi_init_display(struct omap_dss_device *dssdev)  	DSSDBG("DSI init\n"); -	/* XXX these should be figured out dynamically */ -	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | -		OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; +	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { +		dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | +			OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; +	}  	if (dsi->vdds_dsi_reg == NULL) {  		struct regulator *vdds_dsi; @@ -4435,10 +4653,7 @@ static int dsi_get_clocks(struct platform_device *dsidev)  	dsi->dss_clk = clk; -	if (cpu_is_omap34xx() || cpu_is_omap3630()) -		clk = clk_get(&dsidev->dev, "dss2_alwon_fck"); -	else -		clk = clk_get(&dsidev->dev, "sys_clk"); +	clk = clk_get(&dsidev->dev, "sys_clk");  	if (IS_ERR(clk)) {  		DSSERR("can't get sys_clk\n");  		clk_put(dsi->dss_clk); @@ -4462,7 +4677,7 @@ static void dsi_put_clocks(struct platform_device *dsidev)  }  /* DSI1 HW IP initialisation */ -static int omap_dsi1hw_probe(struct platform_device *dsidev) +static int omap_dsihw_probe(struct platform_device *dsidev)  {  	struct omap_display_platform_data *dss_plat_data;  	struct omap_dss_board_info *board_info; @@ -4483,7 +4698,8 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)  	dss_plat_data = dsidev->dev.platform_data;  	board_info = dss_plat_data->board_data; -	dsi->dsi_mux_pads = board_info->dsi_mux_pads; +	dsi->enable_pads = board_info->dsi_enable_pads; +	dsi->disable_pads = board_info->dsi_disable_pads;  	spin_lock_init(&dsi->irq_lock);  	spin_lock_init(&dsi->errors_lock); @@ -4539,7 +4755,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)  	/* DSI VCs initialization */  	for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { -		dsi->vc[i].mode = DSI_VC_MODE_L4; +		dsi->vc[i].source = DSI_VC_SOURCE_L4;  		dsi->vc[i].dssdev = NULL;  		dsi->vc[i].vc_id = 0;  	} @@ -4572,7 +4788,7 @@ err_alloc:  	return r;  } -static int omap_dsi1hw_remove(struct platform_device *dsidev) +static int omap_dsihw_remove(struct platform_device *dsidev)  {  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); @@ -4602,10 +4818,6 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)  static int dsi_runtime_suspend(struct device *dev)  { -	struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); - -	clk_disable(dsi->dss_clk); -  	dispc_runtime_put();  	dss_runtime_put(); @@ -4614,7 +4826,6 @@ static int dsi_runtime_suspend(struct device *dev)  static int dsi_runtime_resume(struct device *dev)  { -	struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));  	int r;  	r = dss_runtime_get(); @@ -4625,8 +4836,6 @@ static int dsi_runtime_resume(struct device *dev)  	if (r)  		goto err_get_dispc; -	clk_enable(dsi->dss_clk); -  	return 0;  err_get_dispc: @@ -4640,11 +4849,11 @@ static const struct dev_pm_ops dsi_pm_ops = {  	.runtime_resume = dsi_runtime_resume,  }; -static struct platform_driver omap_dsi1hw_driver = { -	.probe          = omap_dsi1hw_probe, -	.remove         = omap_dsi1hw_remove, +static struct platform_driver omap_dsihw_driver = { +	.probe          = omap_dsihw_probe, +	.remove         = omap_dsihw_remove,  	.driver         = { -		.name   = "omapdss_dsi1", +		.name   = "omapdss_dsi",  		.owner  = THIS_MODULE,  		.pm	= &dsi_pm_ops,  	}, @@ -4652,10 +4861,10 @@ static struct platform_driver omap_dsi1hw_driver = {  int dsi_init_platform_driver(void)  { -	return platform_driver_register(&omap_dsi1hw_driver); +	return platform_driver_register(&omap_dsihw_driver);  }  void dsi_uninit_platform_driver(void)  { -	return platform_driver_unregister(&omap_dsi1hw_driver); +	return platform_driver_unregister(&omap_dsihw_driver);  } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 0f9c3a6457a..3e09726d32c 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -639,6 +639,17 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)  	REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15);	/* VENC_HDMI_SWITCH */  } +enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) +{ +	enum omap_display_type displays; + +	displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT); +	if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0) +		return DSS_VENC_TV_CLK; + +	return REG_GET(DSS_CONTROL, 15, 15); +} +  static int dss_get_clocks(void)  {  	struct clk *clk; @@ -691,11 +702,6 @@ static void dss_put_clocks(void)  	clk_put(dss.dss_clk);  } -struct clk *dss_get_ick(void) -{ -	return clk_get(&dss.pdev->dev, "ick"); -} -  int dss_runtime_get(void)  {  	int r; @@ -824,13 +830,11 @@ static int omap_dsshw_remove(struct platform_device *pdev)  static int dss_runtime_suspend(struct device *dev)  {  	dss_save_context(); -	clk_disable(dss.dss_clk);  	return 0;  }  static int dss_runtime_resume(struct device *dev)  { -	clk_enable(dss.dss_clk);  	dss_restore_context();  	return 0;  } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 9c94b1152c2..6308fc59fc9 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -97,10 +97,10 @@ extern unsigned int dss_debug;  #define FLD_MOD(orig, val, start, end) \  	(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) -enum omap_parallel_interface_mode { -	OMAP_DSS_PARALLELMODE_BYPASS,		/* MIPI DPI */ -	OMAP_DSS_PARALLELMODE_RFBI,		/* MIPI DBI */ -	OMAP_DSS_PARALLELMODE_DSI, +enum dss_io_pad_mode { +	DSS_IO_PAD_MODE_RESET, +	DSS_IO_PAD_MODE_RFBI, +	DSS_IO_PAD_MODE_BYPASS,  };  enum dss_hdmi_venc_clk_source_select { @@ -108,6 +108,11 @@ enum dss_hdmi_venc_clk_source_select {  	DSS_HDMI_M_PCLK = 1,  }; +enum dss_dsi_content_type { +	DSS_DSI_CONTENT_DCS, +	DSS_DSI_CONTENT_GENERIC, +}; +  struct dss_clock_info {  	/* rates that we get with dividers below */  	unsigned long fck; @@ -150,16 +155,6 @@ struct dsi_clock_info {  	bool use_sys_clk;  }; -/* HDMI PLL structure */ -struct hdmi_pll_info { -	u16 regn; -	u16 regm; -	u32 regmf; -	u16 regm2; -	u16 regsd; -	u16 dcofreq; -}; -  struct seq_file;  struct platform_device; @@ -209,9 +204,8 @@ void dss_uninit_platform_driver(void);  int dss_runtime_get(void);  void dss_runtime_put(void); -struct clk *dss_get_ick(void); -  void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); +enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);  const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);  void dss_dump_clocks(struct seq_file *s); @@ -279,6 +273,8 @@ void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,  int dsi_init_display(struct omap_dss_device *display);  void dsi_irq_handler(void); +u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); +  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); @@ -309,6 +305,11 @@ static inline int dsi_runtime_get(struct platform_device *dsidev)  static inline void dsi_runtime_put(struct platform_device *dsidev)  {  } +static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) +{ +	WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__); +	return 0; +}  static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)  {  	WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); @@ -385,90 +386,71 @@ void dispc_disable_sidle(void);  void dispc_lcd_enable_signal_polarity(bool act_high);  void dispc_lcd_enable_signal(bool enable);  void dispc_pck_free_enable(bool enable); -void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable); - -void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);  void dispc_set_digit_size(u16 width, u16 height); -u32 dispc_get_plane_fifo_size(enum omap_plane plane); -void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);  void dispc_enable_fifomerge(bool enable); -u32 dispc_get_burst_size(enum omap_plane plane); -void dispc_enable_cpr(enum omap_channel channel, bool enable); -void dispc_set_cpr_coef(enum omap_channel channel, -		struct omap_dss_cpr_coefs *coefs); +void dispc_enable_gamma_table(bool enable); +void dispc_set_loadmode(enum omap_dss_load_mode mode); + +bool dispc_lcd_timings_ok(struct omap_video_timings *timings); +unsigned long dispc_fclk_rate(void); +void dispc_find_clk_divs(bool is_tft, 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); -void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); -void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); -void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y); -void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); -void dispc_set_channel_out(enum omap_plane plane, -		enum omap_channel channel_out); -void dispc_enable_gamma_table(bool enable); -int dispc_setup_plane(enum omap_plane plane, -		      u32 paddr, u16 screen_width, -		      u16 pos_x, u16 pos_y, -		      u16 width, u16 height, -		      u16 out_width, u16 out_height, -		      enum omap_color_mode color_mode, -		      bool ilace, -		      enum omap_dss_rotation_type rotation_type, -		      u8 rotation, bool mirror, -		      u8 global_alpha, u8 pre_mult_alpha, -		      enum omap_channel channel, -		      u32 puv_addr); +u32 dispc_ovl_get_fifo_size(enum omap_plane plane); +u32 dispc_ovl_get_burst_size(enum omap_plane plane); +int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, +		bool ilace, enum omap_channel channel, bool replication, +		u32 fifo_low, u32 fifo_high); +int dispc_ovl_enable(enum omap_plane plane, bool enable); -bool dispc_go_busy(enum omap_channel channel); -void dispc_go(enum omap_channel channel); -void dispc_enable_channel(enum omap_channel channel, bool enable); -bool dispc_is_channel_enabled(enum omap_channel channel); -int dispc_enable_plane(enum omap_plane plane, bool enable); -void dispc_enable_replication(enum omap_plane plane, bool enable); -void dispc_set_parallel_interface_mode(enum omap_channel channel, -		enum omap_parallel_interface_mode mode); -void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines); -void dispc_set_lcd_display_type(enum omap_channel channel, +void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); +void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height); +void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable); +void dispc_mgr_set_cpr_coef(enum omap_channel channel, +		struct omap_dss_cpr_coefs *coefs); +bool dispc_mgr_go_busy(enum omap_channel channel); +void dispc_mgr_go(enum omap_channel channel); +void dispc_mgr_enable(enum omap_channel channel, bool enable); +bool dispc_mgr_is_channel_enabled(enum omap_channel channel); +void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode); +void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable); +void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); +void dispc_mgr_set_lcd_display_type(enum omap_channel channel,  		enum omap_lcd_display_type type); -void dispc_set_loadmode(enum omap_dss_load_mode mode); - -void dispc_set_default_color(enum omap_channel channel, u32 color); -u32 dispc_get_default_color(enum omap_channel channel); -void dispc_set_trans_key(enum omap_channel ch, +void dispc_mgr_set_default_color(enum omap_channel channel, u32 color); +u32 dispc_mgr_get_default_color(enum omap_channel channel); +void dispc_mgr_set_trans_key(enum omap_channel ch,  		enum omap_dss_trans_key_type type,  		u32 trans_key); -void dispc_get_trans_key(enum omap_channel ch, +void dispc_mgr_get_trans_key(enum omap_channel ch,  		enum omap_dss_trans_key_type *type,  		u32 *trans_key); -void dispc_enable_trans_key(enum omap_channel ch, bool enable); -void dispc_enable_alpha_blending(enum omap_channel ch, bool enable); -bool dispc_trans_key_enabled(enum omap_channel ch); -bool dispc_alpha_blending_enabled(enum omap_channel ch); - -bool dispc_lcd_timings_ok(struct omap_video_timings *timings); -void dispc_set_lcd_timings(enum omap_channel channel, +void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable); +void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable); +bool dispc_mgr_trans_key_enabled(enum omap_channel ch); +bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch); +void dispc_mgr_set_lcd_timings(enum omap_channel channel,  		struct omap_video_timings *timings); -unsigned long dispc_fclk_rate(void); -unsigned long dispc_lclk_rate(enum omap_channel channel); -unsigned long dispc_pclk_rate(enum omap_channel channel); -void dispc_set_pol_freq(enum omap_channel channel, +void dispc_mgr_set_pol_freq(enum omap_channel channel,  		enum omap_panel_config config, u8 acbi, u8 acb); -void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, +unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); +unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); +int dispc_mgr_set_clock_div(enum omap_channel channel,  		struct dispc_clock_info *cinfo); -int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, -		struct dispc_clock_info *cinfo); -int dispc_set_clock_div(enum omap_channel channel, -		struct dispc_clock_info *cinfo); -int dispc_get_clock_div(enum omap_channel channel, +int dispc_mgr_get_clock_div(enum omap_channel channel,  		struct dispc_clock_info *cinfo); -  /* VENC */  #ifdef CONFIG_OMAP2_DSS_VENC  int venc_init_platform_driver(void);  void venc_uninit_platform_driver(void);  void venc_dump_regs(struct seq_file *s);  int venc_init_display(struct omap_dss_device *display); +unsigned long venc_get_pixel_clock(void);  #else  static inline int venc_init_platform_driver(void)  { @@ -477,6 +459,11 @@ static inline int venc_init_platform_driver(void)  static inline void venc_uninit_platform_driver(void)  {  } +static inline unsigned long venc_get_pixel_clock(void) +{ +	WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__); +	return 0; +}  #endif  /* HDMI */ @@ -484,6 +471,8 @@ static inline void venc_uninit_platform_driver(void)  int hdmi_init_platform_driver(void);  void hdmi_uninit_platform_driver(void);  int hdmi_init_display(struct omap_dss_device *dssdev); +unsigned long hdmi_get_pixel_clock(void); +void hdmi_dump_regs(struct seq_file *s);  #else  static inline int hdmi_init_display(struct omap_dss_device *dssdev)  { @@ -496,12 +485,19 @@ static inline int hdmi_init_platform_driver(void)  static inline void hdmi_uninit_platform_driver(void)  {  } +static inline unsigned long hdmi_get_pixel_clock(void) +{ +	WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__); +	return 0; +}  #endif  int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);  void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);  void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);  int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,  					struct omap_video_timings *timings); +int omapdss_hdmi_read_edid(u8 *buf, int len); +bool omapdss_hdmi_detect(void);  int hdmi_panel_init(void);  void hdmi_panel_exit(void); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index b415c4ee621..b402699168a 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -47,6 +47,7 @@ struct omap_dss_features {  	const int num_ovls;  	const enum omap_display_type *supported_displays;  	const enum omap_color_mode *supported_color_modes; +	const enum omap_overlay_caps *overlay_caps;  	const char * const *clksrc_names;  	const struct dss_param_range *dss_params; @@ -209,6 +210,68 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {  	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |  	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |  	OMAP_DSS_COLOR_RGBX32, + +	/* OMAP_DSS_VIDEO3 */ +	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | +	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 | +	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 | +	OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U | +	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY | +	OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | +	OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | +	OMAP_DSS_COLOR_RGBX32, +}; + +static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { +	/* OMAP_DSS_GFX */ +	0, + +	/* OMAP_DSS_VIDEO1 */ +	OMAP_DSS_OVL_CAP_SCALE, + +	/* OMAP_DSS_VIDEO2 */ +	OMAP_DSS_OVL_CAP_SCALE, +}; + +static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { +	/* OMAP_DSS_GFX */ +	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, + +	/* OMAP_DSS_VIDEO1 */ +	OMAP_DSS_OVL_CAP_SCALE, + +	/* OMAP_DSS_VIDEO2 */ +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, +}; + +static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { +	/* OMAP_DSS_GFX */ +	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, + +	/* OMAP_DSS_VIDEO1 */ +	OMAP_DSS_OVL_CAP_SCALE, + +	/* OMAP_DSS_VIDEO2 */ +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | +		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, +}; + +static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { +	/* OMAP_DSS_GFX */ +	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | +		OMAP_DSS_OVL_CAP_ZORDER, + +	/* OMAP_DSS_VIDEO1 */ +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | +		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, + +	/* OMAP_DSS_VIDEO2 */ +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | +		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, + +	/* OMAP_DSS_VIDEO3 */ +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | +		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,  };  static const char * const omap2_dss_clk_source_names[] = { @@ -233,32 +296,38 @@ static const char * const omap4_dss_clk_source_names[] = {  static const struct dss_param_range omap2_dss_param_range[] = {  	[FEAT_PARAM_DSS_FCK]			= { 0, 173000000 }, +	[FEAT_PARAM_DSS_PCD]			= { 2, 255 },  	[FEAT_PARAM_DSIPLL_REGN]		= { 0, 0 },  	[FEAT_PARAM_DSIPLL_REGM]		= { 0, 0 },  	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, 0 },  	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, 0 },  	[FEAT_PARAM_DSIPLL_FINT]		= { 0, 0 },  	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, 0 }, +	[FEAT_PARAM_DOWNSCALE]			= { 1, 2 },  };  static const struct dss_param_range omap3_dss_param_range[] = {  	[FEAT_PARAM_DSS_FCK]			= { 0, 173000000 }, +	[FEAT_PARAM_DSS_PCD]			= { 1, 255 },  	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1 << 7) - 1 },  	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1 << 11) - 1 },  	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1 << 4) - 1 },  	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 4) - 1 },  	[FEAT_PARAM_DSIPLL_FINT]		= { 750000, 2100000 },  	[FEAT_PARAM_DSIPLL_LPDIV]		= { 1, (1 << 13) - 1}, +	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },  };  static const struct dss_param_range omap4_dss_param_range[] = {  	[FEAT_PARAM_DSS_FCK]			= { 0, 186000000 }, +	[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_LPDIV]		= { 0, (1 << 13) - 1 }, +	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },  };  /* OMAP2 DSS Features */ @@ -275,6 +344,7 @@ static const struct omap_dss_features omap2_dss_features = {  	.num_ovls = 3,  	.supported_displays = omap2_dss_supported_displays,  	.supported_color_modes = omap2_dss_supported_color_modes, +	.overlay_caps = omap2_dss_overlay_caps,  	.clksrc_names = omap2_dss_clk_source_names,  	.dss_params = omap2_dss_param_range,  	.buffer_size_unit = 1, @@ -287,18 +357,19 @@ static const struct omap_dss_features omap3430_dss_features = {  	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),  	.has_feature	= -		FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | +		FEAT_LCDENABLEPOL |  		FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |  		FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |  		FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |  		FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |  		FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | -		FEAT_FIR_COEF_V, +		FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,  	.num_mgrs = 2,  	.num_ovls = 3,  	.supported_displays = omap3430_dss_supported_displays,  	.supported_color_modes = omap3_dss_supported_color_modes, +	.overlay_caps = omap3430_dss_overlay_caps,  	.clksrc_names = omap3_dss_clk_source_names,  	.dss_params = omap3_dss_param_range,  	.buffer_size_unit = 1, @@ -310,18 +381,19 @@ static const struct omap_dss_features omap3630_dss_features = {  	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),  	.has_feature    = -		FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | +		FEAT_LCDENABLEPOL |  		FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | -		FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | +		FEAT_FUNCGATED |  		FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |  		FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |  		FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | -		FEAT_FIR_COEF_V, +		FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,  	.num_mgrs = 2,  	.num_ovls = 3,  	.supported_displays = omap3630_dss_supported_displays,  	.supported_color_modes = omap3_dss_supported_color_modes, +	.overlay_caps = omap3630_dss_overlay_caps,  	.clksrc_names = omap3_dss_clk_source_names,  	.dss_params = omap3_dss_param_range,  	.buffer_size_unit = 1, @@ -335,17 +407,18 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {  	.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),  	.has_feature	= -		FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | -		FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | +		FEAT_MGR_LCD2 |  		FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |  		FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |  		FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | -		FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V, +		FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V | +		FEAT_ALPHA_FREE_ZORDER,  	.num_mgrs = 3, -	.num_ovls = 3, +	.num_ovls = 4,  	.supported_displays = omap4_dss_supported_displays,  	.supported_color_modes = omap4_dss_supported_color_modes, +	.overlay_caps = omap4_dss_overlay_caps,  	.clksrc_names = omap4_dss_clk_source_names,  	.dss_params = omap4_dss_param_range,  	.buffer_size_unit = 16, @@ -358,24 +431,50 @@ static const struct omap_dss_features omap4_dss_features = {  	.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),  	.has_feature	= -		FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | -		FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | +		FEAT_MGR_LCD2 |  		FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |  		FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |  		FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |  		FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | -		FEAT_PRELOAD | FEAT_FIR_COEF_V, +		FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER,  	.num_mgrs = 3, -	.num_ovls = 3, +	.num_ovls = 4,  	.supported_displays = omap4_dss_supported_displays,  	.supported_color_modes = omap4_dss_supported_color_modes, +	.overlay_caps = omap4_dss_overlay_caps,  	.clksrc_names = omap4_dss_clk_source_names,  	.dss_params = omap4_dss_param_range,  	.buffer_size_unit = 16,  	.burst_size_unit = 16,  }; +#if defined(CONFIG_OMAP4_DSS_HDMI) +/* HDMI OMAP4 Functions*/ +static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { + +	.video_configure	=	ti_hdmi_4xxx_basic_configure, +	.phy_enable		=	ti_hdmi_4xxx_phy_enable, +	.phy_disable		=	ti_hdmi_4xxx_phy_disable, +	.read_edid		=	ti_hdmi_4xxx_read_edid, +	.detect			=	ti_hdmi_4xxx_detect, +	.pll_enable		=	ti_hdmi_4xxx_pll_enable, +	.pll_disable		=	ti_hdmi_4xxx_pll_disable, +	.video_enable		=	ti_hdmi_4xxx_wp_video_start, +	.dump_wrapper		=	ti_hdmi_4xxx_wp_dump, +	.dump_core		=	ti_hdmi_4xxx_core_dump, +	.dump_pll		=	ti_hdmi_4xxx_pll_dump, +	.dump_phy		=	ti_hdmi_4xxx_phy_dump, + +}; + +void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data) +{ +	if (cpu_is_omap44xx()) +		ip_data->ops = &omap4_hdmi_functions; +} +#endif +  /* Functions returning values related to a DSS feature */  int dss_feat_get_num_mgrs(void)  { @@ -407,6 +506,11 @@ enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)  	return omap_current_dss_features->supported_color_modes[plane];  } +enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane) +{ +	return omap_current_dss_features->overlay_caps[plane]; +} +  bool dss_feat_color_mode_supported(enum omap_plane plane,  		enum omap_color_mode color_mode)  { diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index b7398cbcda5..6a6c05dd45c 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -20,16 +20,17 @@  #ifndef __OMAP2_DSS_FEATURES_H  #define __OMAP2_DSS_FEATURES_H +#if defined(CONFIG_OMAP4_DSS_HDMI) +#include "ti_hdmi.h" +#endif +  #define MAX_DSS_MANAGERS	3 -#define MAX_DSS_OVERLAYS	3 +#define MAX_DSS_OVERLAYS	4  #define MAX_DSS_LCD_MANAGERS	2  #define MAX_NUM_DSI		2  /* DSS has feature id */  enum dss_feat_id { -	FEAT_GLOBAL_ALPHA		= 1 << 0, -	FEAT_GLOBAL_ALPHA_VID1		= 1 << 1, -	FEAT_PRE_MULT_ALPHA		= 1 << 2,  	FEAT_LCDENABLEPOL		= 1 << 3,  	FEAT_LCDENABLESIGNAL		= 1 << 4,  	FEAT_PCKFREEENABLE		= 1 << 5, @@ -55,6 +56,8 @@ enum dss_feat_id {  	FEAT_CPR			= 1 << 23,  	FEAT_PRELOAD			= 1 << 24,  	FEAT_FIR_COEF_V			= 1 << 25, +	FEAT_ALPHA_FIXED_ZORDER		= 1 << 26, +	FEAT_ALPHA_FREE_ZORDER		= 1 << 27,  };  /* DSS register field id */ @@ -75,12 +78,14 @@ enum dss_feat_reg_field {  enum dss_range_param {  	FEAT_PARAM_DSS_FCK, +	FEAT_PARAM_DSS_PCD,  	FEAT_PARAM_DSIPLL_REGN,  	FEAT_PARAM_DSIPLL_REGM,  	FEAT_PARAM_DSIPLL_REGM_DISPC,  	FEAT_PARAM_DSIPLL_REGM_DSI,  	FEAT_PARAM_DSIPLL_FINT,  	FEAT_PARAM_DSIPLL_LPDIV, +	FEAT_PARAM_DOWNSCALE,  };  /* DSS Feature Functions */ @@ -90,6 +95,7 @@ unsigned long dss_feat_get_param_min(enum dss_range_param param);  unsigned long dss_feat_get_param_max(enum dss_range_param param);  enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);  enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); +enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);  bool dss_feat_color_mode_supported(enum omap_plane plane,  		enum omap_color_mode color_mode);  const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); @@ -100,4 +106,7 @@ u32 dss_feat_get_burst_size_unit(void);		/* in bytes */  bool dss_has_feature(enum dss_feat_id id);  void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);  void dss_features_init(void); +#if defined(CONFIG_OMAP4_DSS_HDMI) +void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data); +#endif  #endif diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 256f27a9064..3262f0f1fa3 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -37,26 +37,41 @@  	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)  #include <sound/soc.h>  #include <sound/pcm_params.h> +#include "ti_hdmi_4xxx_ip.h"  #endif +#include "ti_hdmi.h"  #include "dss.h" -#include "hdmi.h"  #include "dss_features.h" +#define HDMI_WP			0x0 +#define HDMI_CORE_SYS		0x400 +#define HDMI_CORE_AV		0x900 +#define HDMI_PLLCTRL		0x200 +#define HDMI_PHY		0x300 + +/* HDMI EDID Length move this */ +#define HDMI_EDID_MAX_LENGTH			256 +#define EDID_TIMING_DESCRIPTOR_SIZE		0x12 +#define EDID_DESCRIPTOR_BLOCK0_ADDRESS		0x36 +#define EDID_DESCRIPTOR_BLOCK1_ADDRESS		0x80 +#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR	4 +#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR	4 + +#define OMAP_HDMI_TIMINGS_NB			34 + +#define HDMI_DEFAULT_REGN 16 +#define HDMI_DEFAULT_REGM2 1 +  static struct {  	struct mutex lock;  	struct omap_display_platform_data *pdata;  	struct platform_device *pdev; -	void __iomem *base_wp;	/* HDMI wrapper */ +	struct hdmi_ip_data ip_data;  	int code;  	int mode; -	u8 edid[HDMI_EDID_MAX_LENGTH]; -	u8 edid_set; -	bool custom_set; -	struct hdmi_config cfg;  	struct clk *sys_clk; -	struct clk *hdmi_clk;  } hdmi;  /* @@ -144,30 +159,6 @@ static const int code_vesa[85] = {  	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  	-1, 27, 28, -1, 33}; -static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; - -static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val) -{ -	__raw_writel(val, hdmi.base_wp + idx.idx); -} - -static inline u32 hdmi_read_reg(const struct hdmi_reg idx) -{ -	return __raw_readl(hdmi.base_wp + idx.idx); -} - -static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, -				int b2, int b1, u32 val) -{ -	u32 t = 0; -	while (val != REG_GET(idx, b2, b1)) { -		udelay(1); -		if (t++ > 10000) -			return !val; -	} -	return val; -} -  static int hdmi_runtime_get(void)  {  	int r; @@ -193,304 +184,7 @@ int hdmi_init_display(struct omap_dss_device *dssdev)  {  	DSSDBG("init_display\n"); -	return 0; -} - -static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq, -		struct hdmi_pll_info *fmt, u16 sd) -{ -	u32 r; - -	/* PLL start always use manual mode */ -	REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0); - -	r = hdmi_read_reg(PLLCTRL_CFG1); -	r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ -	r = FLD_MOD(r, fmt->regn, 8, 1);  /* CFG1_PLL_REGN */ - -	hdmi_write_reg(PLLCTRL_CFG1, r); - -	r = hdmi_read_reg(PLLCTRL_CFG2); - -	r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ -	r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ -	r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ - -	if (dcofreq) { -		/* divider programming for frequency beyond 1000Mhz */ -		REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10); -		r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ -	} else { -		r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ -	} - -	hdmi_write_reg(PLLCTRL_CFG2, r); - -	r = hdmi_read_reg(PLLCTRL_CFG4); -	r = FLD_MOD(r, fmt->regm2, 24, 18); -	r = FLD_MOD(r, fmt->regmf, 17, 0); - -	hdmi_write_reg(PLLCTRL_CFG4, r); - -	/* go now */ -	REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0); - -	/* wait for bit change */ -	if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) { -		DSSERR("PLL GO bit not set\n"); -		return -ETIMEDOUT; -	} - -	/* Wait till the lock bit is set in PLL status */ -	if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { -		DSSWARN("cannot lock PLL\n"); -		DSSWARN("CFG1 0x%x\n", -			hdmi_read_reg(PLLCTRL_CFG1)); -		DSSWARN("CFG2 0x%x\n", -			hdmi_read_reg(PLLCTRL_CFG2)); -		DSSWARN("CFG4 0x%x\n", -			hdmi_read_reg(PLLCTRL_CFG4)); -		return -ETIMEDOUT; -	} - -	DSSDBG("PLL locked!\n"); - -	return 0; -} - -/* PHY_PWR_CMD */ -static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val) -{ -	/* Command for power control of HDMI PHY */ -	REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6); - -	/* Status of the power control of HDMI PHY */ -	if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) { -		DSSERR("Failed to set PHY power mode to %d\n", val); -		return -ETIMEDOUT; -	} - -	return 0; -} - -/* PLL_PWR_CMD */ -static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val) -{ -	/* Command for power control of HDMI PLL */ -	REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2); - -	/* wait till PHY_PWR_STATUS is set */ -	if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) { -		DSSERR("Failed to set PHY_PWR_STATUS\n"); -		return -ETIMEDOUT; -	} - -	return 0; -} - -static int hdmi_pll_reset(void) -{ -	/* SYSRESET  controlled by power FSM */ -	REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3); - -	/* READ 0x0 reset is in progress */ -	if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { -		DSSERR("Failed to sysreset PLL\n"); -		return -ETIMEDOUT; -	} - -	return 0; -} - -static int hdmi_phy_init(void) -{ -	u16 r = 0; - -	r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON); -	if (r) -		return r; - -	r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON); -	if (r) -		return r; - -	/* -	 * Read address 0 in order to get the SCP reset done completed -	 * Dummy access performed to make sure reset is done -	 */ -	hdmi_read_reg(HDMI_TXPHY_TX_CTRL); - -	/* -	 * Write to phy address 0 to configure the clock -	 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field -	 */ -	REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); - -	/* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ -	hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); - -	/* Setup max LDO voltage */ -	REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); - -	/* Write to phy address 3 to change the polarity control */ -	REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); - -	return 0; -} - -static int hdmi_pll_program(struct hdmi_pll_info *fmt) -{ -	u16 r = 0; -	enum hdmi_clk_refsel refsel; - -	r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); -	if (r) -		return r; - -	r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS); -	if (r) -		return r; - -	r = hdmi_pll_reset(); -	if (r) -		return r; - -	refsel = HDMI_REFSEL_SYSCLK; - -	r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); -	if (r) -		return r; - -	return 0; -} - -static void hdmi_phy_off(void) -{ -	hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF); -} - -static int hdmi_core_ddc_edid(u8 *pedid, int ext) -{ -	u32 i, j; -	char checksum = 0; -	u32 offset = 0; - -	/* Turn on CLK for DDC */ -	REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0); - -	/* -	 * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / -	 * right shifted values( The behavior is not consistent and seen only -	 * with some TV's) -	 */ -	usleep_range(800, 1000); - -	if (!ext) { -		/* Clk SCL Devices */ -		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0); - -		/* HDMI_CORE_DDC_STATUS_IN_PROG */ -		if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, -						4, 4, 0) != 0) { -			DSSERR("Failed to program DDC\n"); -			return -ETIMEDOUT; -		} - -		/* Clear FIFO */ -		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0); - -		/* HDMI_CORE_DDC_STATUS_IN_PROG */ -		if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, -						4, 4, 0) != 0) { -			DSSERR("Failed to program DDC\n"); -			return -ETIMEDOUT; -		} - -	} else { -		if (ext % 2 != 0) -			offset = 0x80; -	} - -	/* Load Segment Address Register */ -	REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0); - -	/* Load Slave Address Register */ -	REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); - -	/* Load Offset Address Register */ -	REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0); - -	/* Load Byte Count */ -	REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); -	REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); - -	/* Set DDC_CMD */ -	if (ext) -		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0); -	else -		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0); - -	/* HDMI_CORE_DDC_STATUS_BUS_LOW */ -	if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) { -		DSSWARN("I2C Bus Low?\n"); -		return -EIO; -	} -	/* HDMI_CORE_DDC_STATUS_NO_ACK */ -	if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) { -		DSSWARN("I2C No Ack\n"); -		return -EIO; -	} - -	i = ext * 128; -	j = 0; -	while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) || -			(REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && -			j < 128) { - -		if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) { -			/* FIFO not empty */ -			pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0); -			j++; -		} -	} - -	for (j = 0; j < 128; j++) -		checksum += pedid[j]; - -	if (checksum != 0) { -		DSSERR("E-EDID checksum failed!!\n"); -		return -EIO; -	} - -	return 0; -} - -static int read_edid(u8 *pedid, u16 max_length) -{ -	int r = 0, n = 0, i = 0; -	int max_ext_blocks = (max_length / 128) - 1; - -	r = hdmi_core_ddc_edid(pedid, 0); -	if (r) { -		return r; -	} else { -		n = pedid[0x7e]; - -		/* -		 * README: need to comply with max_length set by the caller. -		 * Better implementation should be to allocate necessary -		 * memory to store EDID according to nb_block field found -		 * in first block -		 */ -		if (n > max_ext_blocks) -			n = max_ext_blocks; - -		for (i = 1; i <= n; i++) { -			r = hdmi_core_ddc_edid(pedid, i); -			if (r) -				return r; -		} -	} +	dss_init_hdmi_ip_ops(&hdmi.ip_data);  	return 0;  } @@ -518,7 +212,7 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)  {  	int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0;  	int timing_vsync = 0, timing_hsync = 0; -	struct omap_video_timings temp; +	struct hdmi_video_timings temp;  	struct hdmi_cm cm = {-1};  	DSSDBG("hdmi_get_code\n"); @@ -556,500 +250,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)  	return cm;  } -static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid , -		struct omap_video_timings *timings) -{ -	/* X and Y resolution */ -	timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) | -			 edid[current_descriptor_addrs + 2]); -	timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) | -			 edid[current_descriptor_addrs + 5]); - -	timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) | -				edid[current_descriptor_addrs]); - -	timings->pixel_clock = 10 * timings->pixel_clock; - -	/* HORIZONTAL FRONT PORCH */ -	timings->hfp = edid[current_descriptor_addrs + 8] | -			((edid[current_descriptor_addrs + 11] & 0xc0) << 2); -	/* HORIZONTAL SYNC WIDTH */ -	timings->hsw = edid[current_descriptor_addrs + 9] | -			((edid[current_descriptor_addrs + 11] & 0x30) << 4); -	/* HORIZONTAL BACK PORCH */ -	timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) | -			edid[current_descriptor_addrs + 3]) - -			(timings->hfp + timings->hsw); -	/* VERTICAL FRONT PORCH */ -	timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) | -			((edid[current_descriptor_addrs + 11] & 0x0f) << 2); -	/* VERTICAL SYNC WIDTH */ -	timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) | -			((edid[current_descriptor_addrs + 11] & 0x03) << 4); -	/* VERTICAL BACK PORCH */ -	timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | -			edid[current_descriptor_addrs + 6]) - -			(timings->vfp + timings->vsw); - -} - -/* Description : This function gets the resolution information from EDID */ -static void get_edid_timing_data(u8 *edid) -{ -	u8 count; -	u16 current_descriptor_addrs; -	struct hdmi_cm cm; -	struct omap_video_timings edid_timings; - -	/* search block 0, there are 4 DTDs arranged in priority order */ -	for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { -		current_descriptor_addrs = -			EDID_DESCRIPTOR_BLOCK0_ADDRESS + -			count * EDID_TIMING_DESCRIPTOR_SIZE; -		get_horz_vert_timing_info(current_descriptor_addrs, -				edid, &edid_timings); -		cm = hdmi_get_code(&edid_timings); -		DSSDBG("Block0[%d] value matches code = %d , mode = %d\n", -			count, cm.code, cm.mode); -		if (cm.code == -1) { -			continue; -		} else { -			hdmi.code = cm.code; -			hdmi.mode = cm.mode; -			DSSDBG("code = %d , mode = %d\n", -				hdmi.code, hdmi.mode); -			return; -		} -	} -	if (edid[0x7e] != 0x00) { -		for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; -			count++) { -			current_descriptor_addrs = -			EDID_DESCRIPTOR_BLOCK1_ADDRESS + -			count * EDID_TIMING_DESCRIPTOR_SIZE; -			get_horz_vert_timing_info(current_descriptor_addrs, -						edid, &edid_timings); -			cm = hdmi_get_code(&edid_timings); -			DSSDBG("Block1[%d] value matches code = %d, mode = %d", -				count, cm.code, cm.mode); -			if (cm.code == -1) { -				continue; -			} else { -				hdmi.code = cm.code; -				hdmi.mode = cm.mode; -				DSSDBG("code = %d , mode = %d\n", -					hdmi.code, hdmi.mode); -				return; -			} -		} -	} - -	DSSINFO("no valid timing found , falling back to VGA\n"); -	hdmi.code = 4; /* setting default value of 640 480 VGA */ -	hdmi.mode = HDMI_DVI; -} - -static void hdmi_read_edid(struct omap_video_timings *dp) -{ -	int ret = 0, code; - -	memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH); - -	if (!hdmi.edid_set) -		ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH); - -	if (!ret) { -		if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { -			/* search for timings of default resolution */ -			get_edid_timing_data(hdmi.edid); -			hdmi.edid_set = true; -		} -	} else { -		DSSWARN("failed to read E-EDID\n"); -	} - -	if (!hdmi.edid_set) { -		DSSINFO("fallback to VGA\n"); -		hdmi.code = 4; /* setting default value of 640 480 VGA */ -		hdmi.mode = HDMI_DVI; -	} - -	code = get_timings_index(); - -	*dp = cea_vesa_timings[code].timings; -} - -static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, -			struct hdmi_core_infoframe_avi *avi_cfg, -			struct hdmi_core_packet_enable_repeat *repeat_cfg) -{ -	DSSDBG("Enter hdmi_core_init\n"); - -	/* video core */ -	video_cfg->ip_bus_width = HDMI_INPUT_8BIT; -	video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; -	video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; -	video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; -	video_cfg->hdmi_dvi = HDMI_DVI; -	video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; - -	/* info frame */ -	avi_cfg->db1_format = 0; -	avi_cfg->db1_active_info = 0; -	avi_cfg->db1_bar_info_dv = 0; -	avi_cfg->db1_scan_info = 0; -	avi_cfg->db2_colorimetry = 0; -	avi_cfg->db2_aspect_ratio = 0; -	avi_cfg->db2_active_fmt_ar = 0; -	avi_cfg->db3_itc = 0; -	avi_cfg->db3_ec = 0; -	avi_cfg->db3_q_range = 0; -	avi_cfg->db3_nup_scaling = 0; -	avi_cfg->db4_videocode = 0; -	avi_cfg->db5_pixel_repeat = 0; -	avi_cfg->db6_7_line_eoftop = 0 ; -	avi_cfg->db8_9_line_sofbottom = 0; -	avi_cfg->db10_11_pixel_eofleft = 0; -	avi_cfg->db12_13_pixel_sofright = 0; - -	/* packet enable and repeat */ -	repeat_cfg->audio_pkt = 0; -	repeat_cfg->audio_pkt_repeat = 0; -	repeat_cfg->avi_infoframe = 0; -	repeat_cfg->avi_infoframe_repeat = 0; -	repeat_cfg->gen_cntrl_pkt = 0; -	repeat_cfg->gen_cntrl_pkt_repeat = 0; -	repeat_cfg->generic_pkt = 0; -	repeat_cfg->generic_pkt_repeat = 0; -} - -static void hdmi_core_powerdown_disable(void) -{ -	DSSDBG("Enter hdmi_core_powerdown_disable\n"); -	REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0); -} - -static void hdmi_core_swreset_release(void) -{ -	DSSDBG("Enter hdmi_core_swreset_release\n"); -	REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0); -} - -static void hdmi_core_swreset_assert(void) -{ -	DSSDBG("Enter hdmi_core_swreset_assert\n"); -	REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0); -} - -/* DSS_HDMI_CORE_VIDEO_CONFIG */ -static void hdmi_core_video_config(struct hdmi_core_video_config *cfg) -{ -	u32 r = 0; - -	/* sys_ctrl1 default configuration not tunable */ -	r = hdmi_read_reg(HDMI_CORE_CTRL1); -	r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); -	r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); -	r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); -	r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); -	hdmi_write_reg(HDMI_CORE_CTRL1, r); - -	REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); - -	/* Vid_Mode */ -	r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE); - -	/* dither truncation configuration */ -	if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { -		r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); -		r = FLD_MOD(r, 1, 5, 5); -	} else { -		r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); -		r = FLD_MOD(r, 0, 5, 5); -	} -	hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r); - -	/* HDMI_Ctrl */ -	r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL); -	r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); -	r = FLD_MOD(r, cfg->pkt_mode, 5, 3); -	r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); -	hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r); - -	/* TMDS_CTRL */ -	REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL, -		cfg->tclk_sel_clkmult, 6, 5); -} - -static void hdmi_core_aux_infoframe_avi_config( -		struct hdmi_core_infoframe_avi info_avi) -{ -	u32 val; -	char sum = 0, checksum = 0; - -	sum += 0x82 + 0x002 + 0x00D; -	hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082); -	hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002); -	hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D); - -	val = (info_avi.db1_format << 5) | -		(info_avi.db1_active_info << 4) | -		(info_avi.db1_bar_info_dv << 2) | -		(info_avi.db1_scan_info); -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val); -	sum += val; - -	val = (info_avi.db2_colorimetry << 6) | -		(info_avi.db2_aspect_ratio << 4) | -		(info_avi.db2_active_fmt_ar); -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val); -	sum += val; - -	val = (info_avi.db3_itc << 7) | -		(info_avi.db3_ec << 4) | -		(info_avi.db3_q_range << 2) | -		(info_avi.db3_nup_scaling); -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val); -	sum += val; - -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode); -	sum += info_avi.db4_videocode; - -	val = info_avi.db5_pixel_repeat; -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val); -	sum += val; - -	val = info_avi.db6_7_line_eoftop & 0x00FF; -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val); -	sum += val; - -	val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val); -	sum += val; - -	val = info_avi.db8_9_line_sofbottom & 0x00FF; -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val); -	sum += val; - -	val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val); -	sum += val; - -	val = info_avi.db10_11_pixel_eofleft & 0x00FF; -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val); -	sum += val; - -	val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val); -	sum += val; - -	val = info_avi.db12_13_pixel_sofright & 0x00FF; -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val); -	sum += val; - -	val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); -	hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val); -	sum += val; - -	checksum = 0x100 - sum; -	hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum); -} - -static void hdmi_core_av_packet_config( -		struct hdmi_core_packet_enable_repeat repeat_cfg) -{ -	/* enable/repeat the infoframe */ -	hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1, -		(repeat_cfg.audio_pkt << 5) | -		(repeat_cfg.audio_pkt_repeat << 4) | -		(repeat_cfg.avi_infoframe << 1) | -		(repeat_cfg.avi_infoframe_repeat)); - -	/* enable/repeat the packet */ -	hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2, -		(repeat_cfg.gen_cntrl_pkt << 3) | -		(repeat_cfg.gen_cntrl_pkt_repeat << 2) | -		(repeat_cfg.generic_pkt << 1) | -		(repeat_cfg.generic_pkt_repeat)); -} - -static void hdmi_wp_init(struct omap_video_timings *timings, -			struct hdmi_video_format *video_fmt, -			struct hdmi_video_interface *video_int) -{ -	DSSDBG("Enter hdmi_wp_init\n"); - -	timings->hbp = 0; -	timings->hfp = 0; -	timings->hsw = 0; -	timings->vbp = 0; -	timings->vfp = 0; -	timings->vsw = 0; - -	video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; -	video_fmt->y_res = 0; -	video_fmt->x_res = 0; - -	video_int->vsp = 0; -	video_int->hsp = 0; - -	video_int->interlacing = 0; -	video_int->tm = 0; /* HDMI_TIMING_SLAVE */ - -} - -static void hdmi_wp_video_start(bool start) -{ -	REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31); -} - -static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, -	struct omap_video_timings *timings, struct hdmi_config *param) -{ -	DSSDBG("Enter hdmi_wp_video_init_format\n"); - -	video_fmt->y_res = param->timings.timings.y_res; -	video_fmt->x_res = param->timings.timings.x_res; - -	timings->hbp = param->timings.timings.hbp; -	timings->hfp = param->timings.timings.hfp; -	timings->hsw = param->timings.timings.hsw; -	timings->vbp = param->timings.timings.vbp; -	timings->vfp = param->timings.timings.vfp; -	timings->vsw = param->timings.timings.vsw; -} - -static void hdmi_wp_video_config_format( -		struct hdmi_video_format *video_fmt) -{ -	u32 l = 0; - -	REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8); - -	l |= FLD_VAL(video_fmt->y_res, 31, 16); -	l |= FLD_VAL(video_fmt->x_res, 15, 0); -	hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l); -} - -static void hdmi_wp_video_config_interface( -		struct hdmi_video_interface *video_int) -{ -	u32 r; -	DSSDBG("Enter hdmi_wp_video_config_interface\n"); - -	r = hdmi_read_reg(HDMI_WP_VIDEO_CFG); -	r = FLD_MOD(r, video_int->vsp, 7, 7); -	r = FLD_MOD(r, video_int->hsp, 6, 6); -	r = FLD_MOD(r, video_int->interlacing, 3, 3); -	r = FLD_MOD(r, video_int->tm, 1, 0); -	hdmi_write_reg(HDMI_WP_VIDEO_CFG, r); -} - -static void hdmi_wp_video_config_timing( -		struct omap_video_timings *timings) -{ -	u32 timing_h = 0; -	u32 timing_v = 0; - -	DSSDBG("Enter hdmi_wp_video_config_timing\n"); - -	timing_h |= FLD_VAL(timings->hbp, 31, 20); -	timing_h |= FLD_VAL(timings->hfp, 19, 8); -	timing_h |= FLD_VAL(timings->hsw, 7, 0); -	hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h); - -	timing_v |= FLD_VAL(timings->vbp, 31, 20); -	timing_v |= FLD_VAL(timings->vfp, 19, 8); -	timing_v |= FLD_VAL(timings->vsw, 7, 0); -	hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v); -} - -static void hdmi_basic_configure(struct hdmi_config *cfg) -{ -	/* HDMI */ -	struct omap_video_timings video_timing; -	struct hdmi_video_format video_format; -	struct hdmi_video_interface video_interface; -	/* HDMI core */ -	struct hdmi_core_infoframe_avi avi_cfg; -	struct hdmi_core_video_config v_core_cfg; -	struct hdmi_core_packet_enable_repeat repeat_cfg; - -	hdmi_wp_init(&video_timing, &video_format, -		&video_interface); - -	hdmi_core_init(&v_core_cfg, -		&avi_cfg, -		&repeat_cfg); - -	hdmi_wp_video_init_format(&video_format, -			&video_timing, cfg); - -	hdmi_wp_video_config_timing(&video_timing); - -	/* video config */ -	video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; - -	hdmi_wp_video_config_format(&video_format); - -	video_interface.vsp = cfg->timings.vsync_pol; -	video_interface.hsp = cfg->timings.hsync_pol; -	video_interface.interlacing = cfg->interlace; -	video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ - -	hdmi_wp_video_config_interface(&video_interface); - -	/* -	 * configure core video part -	 * set software reset in the core -	 */ -	hdmi_core_swreset_assert(); - -	/* power down off */ -	hdmi_core_powerdown_disable(); - -	v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; -	v_core_cfg.hdmi_dvi = cfg->cm.mode; - -	hdmi_core_video_config(&v_core_cfg); - -	/* release software reset in the core */ -	hdmi_core_swreset_release(); - -	/* -	 * configure packet -	 * info frame video see doc CEA861-D page 65 -	 */ -	avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; -	avi_cfg.db1_active_info = -		HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; -	avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; -	avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; -	avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; -	avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; -	avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; -	avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; -	avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; -	avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; -	avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; -	avi_cfg.db4_videocode = cfg->cm.code; -	avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; -	avi_cfg.db6_7_line_eoftop = 0; -	avi_cfg.db8_9_line_sofbottom = 0; -	avi_cfg.db10_11_pixel_eofleft = 0; -	avi_cfg.db12_13_pixel_sofright = 0; - -	hdmi_core_aux_infoframe_avi_config(avi_cfg); - -	/* enable/repeat the infoframe */ -	repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; -	repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; -	/* wakeup */ -	repeat_cfg.audio_pkt = HDMI_PACKETENABLE; -	repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; -	hdmi_core_av_packet_config(repeat_cfg); -} -  static void update_hdmi_timings(struct hdmi_config *cfg,  		struct omap_video_timings *timings, int code)  { @@ -1066,6 +266,12 @@ static void update_hdmi_timings(struct hdmi_config *cfg,  	cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;  } +unsigned long hdmi_get_pixel_clock(void) +{ +	/* HDMI Pixel Clock in Mhz */ +	return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000; +} +  static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,  		struct hdmi_pll_info *pi)  { @@ -1077,15 +283,23 @@ 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  	 */ -	pi->regn = dssdev->clocks.hdmi.regn; -	refclk = clkin / (pi->regn + 1); +	if (dssdev->clocks.hdmi.regn == 0) +		pi->regn = HDMI_DEFAULT_REGN; +	else +		pi->regn = dssdev->clocks.hdmi.regn; + +	refclk = clkin / pi->regn;  	/*  	 * multiplier is pixel_clk/ref_clk  	 * Multiplying by 100 to avoid fractional part removal  	 */  	pi->regm = (phy * 100 / (refclk)) / 100; -	pi->regm2 = dssdev->clocks.hdmi.regm2; + +	if (dssdev->clocks.hdmi.regm2 == 0) +		pi->regm2 = HDMI_DEFAULT_REGM2; +	else +		pi->regm2 = dssdev->clocks.hdmi.regm2;  	/*  	 * fractional multiplier is remainder of the difference between @@ -1100,7 +314,10 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,  	 * is greater than 1000MHz  	 */  	pi->dcofreq = phy > 1000 * 100; -	pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; +	pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; + +	/* Set the reference clock to sysclk reference */ +	pi->refsel = HDMI_REFSEL_SYSCLK;  	DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);  	DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); @@ -1109,7 +326,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,  static int hdmi_power_on(struct omap_dss_device *dssdev)  {  	int r, code = 0; -	struct hdmi_pll_info pll_data;  	struct omap_video_timings *p;  	unsigned long phy; @@ -1117,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)  	if (r)  		return r; -	dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); +	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);  	p = &dssdev->panel.timings; @@ -1125,36 +341,31 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)  		dssdev->panel.timings.x_res,  		dssdev->panel.timings.y_res); -	if (!hdmi.custom_set) { -		DSSDBG("Read EDID as no EDID is not set on poweron\n"); -		hdmi_read_edid(p); -	}  	code = get_timings_index(); -	dssdev->panel.timings = cea_vesa_timings[code].timings; -	update_hdmi_timings(&hdmi.cfg, p, code); +	update_hdmi_timings(&hdmi.ip_data.cfg, p, code);  	phy = p->pixel_clock; -	hdmi_compute_pll(dssdev, phy, &pll_data); +	hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); -	hdmi_wp_video_start(0); +	hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); -	/* config the PLL and PHY first */ -	r = hdmi_pll_program(&pll_data); +	/* config the PLL and PHY hdmi_set_pll_pwrfirst */ +	r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);  	if (r) {  		DSSDBG("Failed to lock PLL\n");  		goto err;  	} -	r = hdmi_phy_init(); +	r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);  	if (r) {  		DSSDBG("Failed to start PHY\n");  		goto err;  	} -	hdmi.cfg.cm.mode = hdmi.mode; -	hdmi.cfg.cm.code = hdmi.code; -	hdmi_basic_configure(&hdmi.cfg); +	hdmi.ip_data.cfg.cm.mode = hdmi.mode; +	hdmi.ip_data.cfg.cm.code = hdmi.code; +	hdmi.ip_data.ops->video_configure(&hdmi.ip_data);  	/* Make selection of HDMI in DSS */  	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); @@ -1174,9 +385,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)  	dispc_set_digit_size(dssdev->panel.timings.x_res,  			dssdev->panel.timings.y_res); -	dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); +	hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1); -	hdmi_wp_video_start(1); +	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1);  	return 0;  err: @@ -1186,14 +397,12 @@ err:  static void hdmi_power_off(struct omap_dss_device *dssdev)  { -	dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); +	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); -	hdmi_wp_video_start(0); -	hdmi_phy_off(); -	hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); +	hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); +	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); +	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);  	hdmi_runtime_put(); - -	hdmi.edid_set = 0;  }  int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, @@ -1203,7 +412,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,  	cm = hdmi_get_code(timings);  	if (cm.code == -1) { -		DSSERR("Invalid timing entered\n");  		return -EINVAL;  	} @@ -1215,12 +423,69 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)  {  	struct hdmi_cm cm; -	hdmi.custom_set = 1;  	cm = hdmi_get_code(&dssdev->panel.timings);  	hdmi.code = cm.code;  	hdmi.mode = cm.mode; -	omapdss_hdmi_display_enable(dssdev); -	hdmi.custom_set = 0; + +	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { +		int r; + +		hdmi_power_off(dssdev); + +		r = hdmi_power_on(dssdev); +		if (r) +			DSSERR("failed to power on device\n"); +	} +} + +void hdmi_dump_regs(struct seq_file *s) +{ +	mutex_lock(&hdmi.lock); + +	if (hdmi_runtime_get()) +		return; + +	hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s); +	hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); +	hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s); +	hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s); + +	hdmi_runtime_put(); +	mutex_unlock(&hdmi.lock); +} + +int omapdss_hdmi_read_edid(u8 *buf, int len) +{ +	int r; + +	mutex_lock(&hdmi.lock); + +	r = hdmi_runtime_get(); +	BUG_ON(r); + +	r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len); + +	hdmi_runtime_put(); +	mutex_unlock(&hdmi.lock); + +	return r; +} + +bool omapdss_hdmi_detect(void) +{ +	int r; + +	mutex_lock(&hdmi.lock); + +	r = hdmi_runtime_get(); +	BUG_ON(r); + +	r = hdmi.ip_data.ops->detect(&hdmi.ip_data); + +	hdmi_runtime_put(); +	mutex_unlock(&hdmi.lock); + +	return r == 1;  }  int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) @@ -1231,6 +496,12 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)  	mutex_lock(&hdmi.lock); +	if (dssdev->manager == NULL) { +		DSSERR("failed to enable display: no manager\n"); +		r = -ENODEV; +		goto err0; +	} +  	r = omap_dss_start_device(dssdev);  	if (r) {  		DSSERR("failed to start device\n"); @@ -1282,219 +553,9 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)  #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \  	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) -static void hdmi_wp_audio_config_format( -		struct hdmi_audio_format *aud_fmt) -{ -	u32 r; - -	DSSDBG("Enter hdmi_wp_audio_config_format\n"); - -	r = hdmi_read_reg(HDMI_WP_AUDIO_CFG); -	r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); -	r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); -	r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); -	r = FLD_MOD(r, aud_fmt->type, 4, 4); -	r = FLD_MOD(r, aud_fmt->justification, 3, 3); -	r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); -	r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); -	r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); -	hdmi_write_reg(HDMI_WP_AUDIO_CFG, r); -} - -static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma) -{ -	u32 r; - -	DSSDBG("Enter hdmi_wp_audio_config_dma\n"); - -	r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2); -	r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); -	r = FLD_MOD(r, aud_dma->block_size, 7, 0); -	hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r); - -	r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL); -	r = FLD_MOD(r, aud_dma->mode, 9, 9); -	r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); -	hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r); -} - -static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg) -{ -	u32 r; - -	/* audio clock recovery parameters */ -	r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL); -	r = FLD_MOD(r, cfg->use_mclk, 2, 2); -	r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); -	r = FLD_MOD(r, cfg->cts_mode, 0, 0); -	hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r); - -	REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); -	REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); -	REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); - -	if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { -		REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); -		REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); -		REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); -	} else { -		/* -		 * HDMI IP uses this configuration to divide the MCLK to -		 * update CTS value. -		 */ -		REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); - -		/* Configure clock for audio packets */ -		REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1, -			cfg->aud_par_busclk, 7, 0); -		REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2, -			(cfg->aud_par_busclk >> 8), 7, 0); -		REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3, -			(cfg->aud_par_busclk >> 16), 7, 0); -	} - -	/* Override of SPDIF sample frequency with value in I2S_CHST4 */ -	REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1); - -	/* I2S parameters */ -	REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0); - -	r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL); -	r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); -	r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); -	r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); -	r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); -	r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); -	r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); -	r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); -	r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); -	hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r); - -	r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5); -	r = FLD_MOD(r, cfg->freq_sample, 7, 4); -	r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); -	r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); -	hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r); - -	REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0); - -	/* Audio channels and mode parameters */ -	REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); -	r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE); -	r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); -	r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); -	r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); -	r = FLD_MOD(r, cfg->en_spdif, 1, 1); -	hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r); -} - -static void hdmi_core_audio_infoframe_config( -		struct hdmi_core_infoframe_audio *info_aud) -{ -	u8 val; -	u8 sum = 0, checksum = 0; - -	/* -	 * Set audio info frame type, version and length as -	 * described in HDMI 1.4a Section 8.2.2 specification. -	 * Checksum calculation is defined in Section 5.3.5. -	 */ -	hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84); -	hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01); -	hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a); -	sum += 0x84 + 0x001 + 0x00a; - -	val = (info_aud->db1_coding_type << 4) -			| (info_aud->db1_channel_count - 1); -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val); -	sum += val; -	val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val); -	sum += val; - -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00); - -	val = info_aud->db4_channel_alloc; -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val); -	sum += val; - -	val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val); -	sum += val; - -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00); -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00); -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00); -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00); -	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00); - -	checksum = 0x100 - sum; -	hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum); - -	/* -	 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing -	 * is available. -	 */ -} - -static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts) -{ -	u32 r; -	u32 deep_color = 0; -	u32 pclk = hdmi.cfg.timings.timings.pixel_clock; - -	if (n == NULL || cts == NULL) -		return -EINVAL; -	/* -	 * Obtain current deep color configuration. This needed -	 * to calculate the TMDS clock based on the pixel clock. -	 */ -	r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0); -	switch (r) { -	case 1: /* No deep color selected */ -		deep_color = 100; -		break; -	case 2: /* 10-bit deep color selected */ -		deep_color = 125; -		break; -	case 3: /* 12-bit deep color selected */ -		deep_color = 150; -		break; -	default: -		return -EINVAL; -	} - -	switch (sample_freq) { -	case 32000: -		if ((deep_color == 125) && ((pclk == 54054) -				|| (pclk == 74250))) -			*n = 8192; -		else -			*n = 4096; -		break; -	case 44100: -		*n = 6272; -		break; -	case 48000: -		if ((deep_color == 125) && ((pclk == 54054) -				|| (pclk == 74250))) -			*n = 8192; -		else -			*n = 6144; -		break; -	default: -		*n = 0; -		return -EINVAL; -	} - -	/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ -	*cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); - -	return 0; -} - -static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, +static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data, +					struct snd_pcm_substream *substream,  				    struct snd_pcm_hw_params *params,  				    struct snd_soc_dai *dai)  { @@ -1548,7 +609,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,  		return -EINVAL;  	} -	err = hdmi_config_audio_acr(params_rate(params), &n, &cts); +	err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts);  	if (err < 0)  		return err; @@ -1564,8 +625,8 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,  	audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;  	audio_dma.fifo_threshold = 0x20; /* in number of samples */ -	hdmi_wp_audio_config_dma(&audio_dma); -	hdmi_wp_audio_config_format(&audio_format); +	hdmi_wp_audio_config_dma(ip_data, &audio_dma); +	hdmi_wp_audio_config_format(ip_data, &audio_format);  	/*  	 * I2S config @@ -1609,7 +670,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,  	/* Use parallel audio interface */  	core_cfg.en_parallel_aud_input = true; -	hdmi_core_audio_config(&core_cfg); +	hdmi_core_audio_config(ip_data, &core_cfg);  	/*  	 * Configure packet @@ -1623,36 +684,10 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,  	aud_if_cfg.db5_downmix_inh = false;  	aud_if_cfg.db5_lsv = 0; -	hdmi_core_audio_infoframe_config(&aud_if_cfg); +	hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg);  	return 0;  } -static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, -				  struct snd_soc_dai *dai) -{ -	int err = 0; -	switch (cmd) { -	case SNDRV_PCM_TRIGGER_START: -	case SNDRV_PCM_TRIGGER_RESUME: -	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -		REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0); -		REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31); -		REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30); -		break; - -	case SNDRV_PCM_TRIGGER_STOP: -	case SNDRV_PCM_TRIGGER_SUSPEND: -	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -		REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0); -		REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30); -		REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31); -		break; -	default: -		err = -EINVAL; -	} -	return err; -} -  static int hdmi_audio_startup(struct snd_pcm_substream *substream,  				  struct snd_soc_dai *dai)  { @@ -1698,15 +733,6 @@ static int hdmi_get_clocks(struct platform_device *pdev)  	hdmi.sys_clk = clk; -	clk = clk_get(&pdev->dev, "dss_48mhz_clk"); -	if (IS_ERR(clk)) { -		DSSERR("can't get hdmi_clk\n"); -		clk_put(hdmi.sys_clk); -		return PTR_ERR(clk); -	} - -	hdmi.hdmi_clk = clk; -  	return 0;  } @@ -1714,8 +740,6 @@ static void hdmi_put_clocks(void)  {  	if (hdmi.sys_clk)  		clk_put(hdmi.sys_clk); -	if (hdmi.hdmi_clk) -		clk_put(hdmi.hdmi_clk);  }  /* HDMI HW IP initialisation */ @@ -1736,20 +760,26 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)  	}  	/* Base address taken from platform */ -	hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); -	if (!hdmi.base_wp) { +	hdmi.ip_data.base_wp = ioremap(hdmi_mem->start, +						resource_size(hdmi_mem)); +	if (!hdmi.ip_data.base_wp) {  		DSSERR("can't ioremap WP\n");  		return -ENOMEM;  	}  	r = hdmi_get_clocks(pdev);  	if (r) { -		iounmap(hdmi.base_wp); +		iounmap(hdmi.ip_data.base_wp);  		return r;  	}  	pm_runtime_enable(&pdev->dev); +	hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS; +	hdmi.ip_data.core_av_offset = HDMI_CORE_AV; +	hdmi.ip_data.pll_offset = HDMI_PLLCTRL; +	hdmi.ip_data.phy_offset = HDMI_PHY; +  	hdmi_panel_init();  #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ @@ -1779,14 +809,13 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)  	hdmi_put_clocks(); -	iounmap(hdmi.base_wp); +	iounmap(hdmi.ip_data.base_wp);  	return 0;  }  static int hdmi_runtime_suspend(struct device *dev)  { -	clk_disable(hdmi.hdmi_clk);  	clk_disable(hdmi.sys_clk);  	dispc_runtime_put(); @@ -1809,7 +838,6 @@ static int hdmi_runtime_resume(struct device *dev)  	clk_enable(hdmi.sys_clk); -	clk_enable(hdmi.hdmi_clk);  	return 0; diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_panel.c index 7d4f2bd7c50..533d5dc634d 100644 --- a/drivers/video/omap2/dss/hdmi_omap4_panel.c +++ b/drivers/video/omap2/dss/hdmi_panel.c @@ -1,5 +1,5 @@  /* - * hdmi_omap4_panel.c + * hdmi_panel.c   *   * HDMI library support functions for TI OMAP4 processors.   * @@ -25,6 +25,7 @@  #include <linux/mutex.h>  #include <linux/module.h>  #include <video/omapdss.h> +#include <linux/slab.h>  #include "dss.h" @@ -40,13 +41,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev)  	dssdev->panel.config = OMAP_DSS_LCD_TFT |  			OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; -	/* -	 * Initialize the timings to 640 * 480 -	 * This is only for framebuffer update not for TV timing setting -	 * Setting TV timing will be done only on enable -	 */ -	dssdev->panel.timings.x_res = 640; -	dssdev->panel.timings.y_res = 480; +	dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31};  	DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",  		dssdev->panel.timings.x_res, @@ -161,12 +156,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,  	mutex_lock(&hdmi.hdmi_lock);  	dssdev->panel.timings = *timings; - -	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { -		/* turn the hdmi off and on to get new timings to use */ -		omapdss_hdmi_display_disable(dssdev); -		omapdss_hdmi_display_set_timing(dssdev); -	} +	omapdss_hdmi_display_set_timing(dssdev);  	mutex_unlock(&hdmi.hdmi_lock);  } @@ -181,12 +171,54 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,  	mutex_lock(&hdmi.hdmi_lock);  	r = omapdss_hdmi_display_check_timing(dssdev, timings); -	if (r) { -		DSSERR("Timing cannot be applied\n"); -		goto err; + +	mutex_unlock(&hdmi.hdmi_lock); +	return r; +} + +static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len) +{ +	int r; + +	mutex_lock(&hdmi.hdmi_lock); + +	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { +		r = omapdss_hdmi_display_enable(dssdev); +		if (r) +			goto err; +	} + +	r = omapdss_hdmi_read_edid(buf, len); + +	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || +			dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) +		omapdss_hdmi_display_disable(dssdev); +err: +	mutex_unlock(&hdmi.hdmi_lock); + +	return r; +} + +static bool hdmi_detect(struct omap_dss_device *dssdev) +{ +	int r; + +	mutex_lock(&hdmi.hdmi_lock); + +	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { +		r = omapdss_hdmi_display_enable(dssdev); +		if (r) +			goto err;  	} + +	r = omapdss_hdmi_detect(); + +	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || +			dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) +		omapdss_hdmi_display_disable(dssdev);  err:  	mutex_unlock(&hdmi.hdmi_lock); +  	return r;  } @@ -200,6 +232,8 @@ static struct omap_dss_driver hdmi_driver = {  	.get_timings	= hdmi_get_timings,  	.set_timings	= hdmi_set_timings,  	.check_timings	= hdmi_check_timings, +	.read_edid	= hdmi_read_edid, +	.detect		= hdmi_detect,  	.driver			= {  		.name   = "hdmi_panel",  		.owner  = THIS_MODULE, diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 13d72d5c714..6e63845cc7d 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -106,7 +106,7 @@ put_device:  static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,  					  char *buf)  { -	return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color); +	return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color);  }  static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, @@ -116,8 +116,9 @@ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,  	u32 color;  	int r; -	if (sscanf(buf, "%d", &color) != 1) -		return -EINVAL; +	r = kstrtouint(buf, 0, &color); +	if (r) +		return r;  	mgr->get_manager_info(mgr, &info); @@ -184,7 +185,7 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,  static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,  					    char *buf)  { -	return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key); +	return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key);  }  static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, @@ -194,8 +195,9 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,  	u32 key_value;  	int r; -	if (sscanf(buf, "%d", &key_value) != 1) -		return -EINVAL; +	r = kstrtouint(buf, 0, &key_value); +	if (r) +		return r;  	mgr->get_manager_info(mgr, &info); @@ -222,15 +224,16 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,  					       const char *buf, size_t size)  {  	struct omap_overlay_manager_info info; -	int enable; +	bool enable;  	int r; -	if (sscanf(buf, "%d", &enable) != 1) -		return -EINVAL; +	r = strtobool(buf, &enable); +	if (r) +		return r;  	mgr->get_manager_info(mgr, &info); -	info.trans_enabled = enable ? true : false; +	info.trans_enabled = enable;  	r = mgr->set_manager_info(mgr, &info);  	if (r) @@ -246,7 +249,10 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,  static ssize_t manager_alpha_blending_enabled_show(  		struct omap_overlay_manager *mgr, char *buf)  { -	return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled); +	WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); + +	return snprintf(buf, PAGE_SIZE, "%d\n", +		mgr->info.partial_alpha_enabled);  }  static ssize_t manager_alpha_blending_enabled_store( @@ -254,15 +260,18 @@ static ssize_t manager_alpha_blending_enabled_store(  		const char *buf, size_t size)  {  	struct omap_overlay_manager_info info; -	int enable; +	bool enable;  	int r; -	if (sscanf(buf, "%d", &enable) != 1) -		return -EINVAL; +	WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); + +	r = strtobool(buf, &enable); +	if (r) +		return r;  	mgr->get_manager_info(mgr, &info); -	info.alpha_enabled = enable ? true : false; +	info.partial_alpha_enabled = enable;  	r = mgr->set_manager_info(mgr, &info);  	if (r) @@ -285,19 +294,16 @@ static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,  		const char *buf, size_t size)  {  	struct omap_overlay_manager_info info; -	int v;  	int r;  	bool enable;  	if (!dss_has_feature(FEAT_CPR))  		return -ENODEV; -	r = kstrtoint(buf, 0, &v); +	r = strtobool(buf, &enable);  	if (r)  		return r; -	enable = !!v; -  	mgr->get_manager_info(mgr, &info);  	if (info.cpr_enable == enable) @@ -586,6 +592,13 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr)  		return -EINVAL;  	} +	/* +	 * Don't allow currently enabled displays to have the overlay manager +	 * pulled out from underneath them +	 */ +	if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) +		return -EINVAL; +  	mgr->device->manager = NULL;  	mgr->device = NULL;  	mgr->device_changed = true; @@ -801,7 +814,7 @@ static int configure_overlay(enum omap_plane plane)  {  	struct overlay_cache_data *c;  	struct manager_cache_data *mc; -	struct omap_overlay_info *oi; +	struct omap_overlay_info *oi, new_oi;  	struct omap_overlay_manager_info *mi;  	u16 outw, outh;  	u16 x, y, w, h; @@ -815,7 +828,7 @@ static int configure_overlay(enum omap_plane plane)  	oi = &c->info;  	if (!c->enabled) { -		dispc_enable_plane(plane, 0); +		dispc_ovl_enable(plane, 0);  		return 0;  	} @@ -843,7 +856,7 @@ static int configure_overlay(enum omap_plane plane)  		/* If the overlay is outside the update region, disable it */  		if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,  					x, y, outw, outh)) { -			dispc_enable_plane(plane, 0); +			dispc_ovl_enable(plane, 0);  			return 0;  		} @@ -921,34 +934,27 @@ static int configure_overlay(enum omap_plane plane)  		}  	} -	r = dispc_setup_plane(plane, -			paddr, -			oi->screen_width, -			x, y, -			w, h, -			outw, outh, -			oi->color_mode, -			c->ilace, -			oi->rotation_type, -			oi->rotation, -			oi->mirror, -			oi->global_alpha, -			oi->pre_mult_alpha, -			c->channel, -			oi->p_uv_addr); +	new_oi = *oi; + +	/* update new_oi members which could have been possibly updated */ +	new_oi.pos_x = x; +	new_oi.pos_y = y; +	new_oi.width = w; +	new_oi.height = h; +	new_oi.out_width = outw; +	new_oi.out_height = outh; +	new_oi.paddr = paddr; +	r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel, +		c->replication, c->fifo_low, c->fifo_high);  	if (r) {  		/* this shouldn't happen */ -		DSSERR("dispc_setup_plane failed for ovl %d\n", plane); -		dispc_enable_plane(plane, 0); +		DSSERR("dispc_ovl_setup failed for ovl %d\n", plane); +		dispc_ovl_enable(plane, 0);  		return r;  	} -	dispc_enable_replication(plane, c->replication); - -	dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high); - -	dispc_enable_plane(plane, 1); +	dispc_ovl_enable(plane, 1);  	return 0;  } @@ -962,13 +968,13 @@ static void configure_manager(enum omap_channel channel)  	/* picking info from the cache */  	mi = &dss_cache.manager_cache[channel].info; -	dispc_set_default_color(channel, mi->default_color); -	dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key); -	dispc_enable_trans_key(channel, mi->trans_enabled); -	dispc_enable_alpha_blending(channel, mi->alpha_enabled); +	dispc_mgr_set_default_color(channel, mi->default_color); +	dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key); +	dispc_mgr_enable_trans_key(channel, mi->trans_enabled); +	dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled);  	if (dss_has_feature(FEAT_CPR)) { -		dispc_enable_cpr(channel, mi->cpr_enable); -		dispc_set_cpr_coef(channel, &mi->cpr_coefs); +		dispc_mgr_enable_cpr(channel, mi->cpr_enable); +		dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs);  	}  } @@ -992,7 +998,7 @@ static int configure_dispc(void)  	busy = false;  	for (i = 0; i < num_mgrs; i++) { -		mgr_busy[i] = dispc_go_busy(i); +		mgr_busy[i] = dispc_mgr_go_busy(i);  		mgr_go[i] = false;  	} @@ -1053,7 +1059,7 @@ static int configure_dispc(void)  		 * always be turned off after frame, and new settings will be  		 * taken in to use at next update */  		if (!mc->manual_update) -			dispc_go(i); +			dispc_mgr_go(i);  	}  	if (busy) @@ -1258,7 +1264,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)  	u32 irq_mask;  	for (i = 0; i < num_mgrs; i++) -		mgr_busy[i] = dispc_go_busy(i); +		mgr_busy[i] = dispc_mgr_go_busy(i);  	spin_lock(&dss_cache.lock); @@ -1280,7 +1286,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)  	/* re-read busy flags */  	for (i = 0; i < num_mgrs; i++) -		mgr_busy[i] = dispc_go_busy(i); +		mgr_busy[i] = dispc_mgr_go_busy(i);  	/* keep running as long as there are busy managers, so that  	 * we can collect overlay-applied information */ @@ -1326,11 +1332,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)  		ovl = omap_dss_get_overlay(i); -		if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) -			continue; -  		oc = &dss_cache.overlay_cache[ovl->id]; +		if (ovl->manager_changed) { +			ovl->manager_changed = false; +			ovl->info_dirty  = true; +		} +  		if (!overlay_enabled(ovl)) {  			if (oc->enabled) {  				oc->enabled = false; @@ -1375,9 +1383,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)  	list_for_each_entry(mgr, &manager_list, list) {  		struct omap_dss_device *dssdev; -		if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC)) -			continue; -  		mc = &dss_cache.manager_cache[mgr->id];  		if (mgr->device_changed) { @@ -1423,9 +1428,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)  		ovl = omap_dss_get_overlay(i); -		if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) -			continue; -  		oc = &dss_cache.overlay_cache[ovl->id];  		if (!oc->enabled) @@ -1433,11 +1435,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)  		dssdev = ovl->manager->device; -		size = dispc_get_plane_fifo_size(ovl->id); +		size = dispc_ovl_get_fifo_size(ovl->id);  		if (use_fifomerge)  			size *= 3; -		burst_size = dispc_get_burst_size(ovl->id); +		burst_size = dispc_ovl_get_burst_size(ovl->id);  		switch (dssdev->type) {  		case OMAP_DISPLAY_TYPE_DPI: @@ -1484,12 +1486,17 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)  static int dss_check_manager(struct omap_overlay_manager *mgr)  { -	/* OMAP supports only graphics source transparency color key and alpha -	 * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */ - -	if (mgr->info.alpha_enabled && mgr->info.trans_enabled && -			mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) -		return -EINVAL; +	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) { +		/* +		 * OMAP3 supports only graphics source transparency color key +		 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2 +		 * Alpha Mode +		 */ +		if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled +			&& mgr->info.trans_key_type != +				OMAP_DSS_COLOR_KEY_GFX_DST) +			return -EINVAL; +	}  	return 0;  } @@ -1522,13 +1529,13 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,  static int dss_mgr_enable(struct omap_overlay_manager *mgr)  { -	dispc_enable_channel(mgr->id, 1); +	dispc_mgr_enable(mgr->id, 1);  	return 0;  }  static int dss_mgr_disable(struct omap_overlay_manager *mgr)  { -	dispc_enable_channel(mgr->id, 0); +	dispc_mgr_enable(mgr->id, 0);  	return 0;  } @@ -1580,7 +1587,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)  		mgr->enable = &dss_mgr_enable;  		mgr->disable = &dss_mgr_disable; -		mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; +		mgr->caps = 0;  		mgr->supported_displays =  			dss_feat_get_supported_displays(mgr->id); @@ -1597,42 +1604,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)  		}  	} -#ifdef L4_EXAMPLE -	{ -		int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr) -		{ -			DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name); - -			return 0; -		} - -		struct omap_overlay_manager *mgr; -		mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); - -		BUG_ON(mgr == NULL); - -		mgr->name = "l4"; -		mgr->supported_displays = -			OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI; - -		mgr->set_device = &omap_dss_set_device; -		mgr->unset_device = &omap_dss_unset_device; -		mgr->apply = &omap_dss_mgr_apply_l4; -		mgr->set_manager_info = &omap_dss_mgr_set_info; -		mgr->get_manager_info = &omap_dss_mgr_get_info; - -		dss_overlay_setup_l4_manager(mgr); - -		omap_dss_add_overlay_manager(mgr); - -		r = kobject_init_and_add(&mgr->kobj, &manager_ktype, -				&pdev->dev.kobj, "managerl4"); - -		if (r) -			DSSERR("failed to create sysfs file\n"); -	} -#endif -  	return 0;  } diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index c84380c53c3..ab8e40e4875 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -211,16 +211,17 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)  static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,  		size_t size)  { -	int r, enable; +	int r; +	bool enable;  	struct omap_overlay_info info;  	ovl->get_overlay_info(ovl, &info); -	r = kstrtoint(buf, 0, &enable); +	r = strtobool(buf, &enable);  	if (r)  		return r; -	info.enabled = !!enable; +	info.enabled = enable;  	r = ovl->set_overlay_info(ovl, &info);  	if (r) @@ -248,7 +249,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,  	u8 alpha;  	struct omap_overlay_info info; -	if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) +	if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)  		return -ENODEV;  	r = kstrtou8(buf, 0, &alpha); @@ -257,14 +258,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,  	ovl->get_overlay_info(ovl, &info); -	/* Video1 plane does not support global alpha -	 * to always make it 255 completely opaque -	 */ -	if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && -			ovl->id == OMAP_DSS_VIDEO1) -		info.global_alpha = 255; -	else -		info.global_alpha = alpha; +	info.global_alpha = alpha;  	r = ovl->set_overlay_info(ovl, &info);  	if (r) @@ -293,20 +287,52 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,  	u8 alpha;  	struct omap_overlay_info info; +	if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) +		return -ENODEV; +  	r = kstrtou8(buf, 0, &alpha);  	if (r)  		return r;  	ovl->get_overlay_info(ovl, &info); -	/* only GFX and Video2 plane support pre alpha multiplied -	 * set zero for Video1 plane -	 */ -	if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && -		ovl->id == OMAP_DSS_VIDEO1) -		info.pre_mult_alpha = 0; -	else -		info.pre_mult_alpha = alpha; +	info.pre_mult_alpha = alpha; + +	r = ovl->set_overlay_info(ovl, &info); +	if (r) +		return r; + +	if (ovl->manager) { +		r = ovl->manager->apply(ovl->manager); +		if (r) +			return r; +	} + +	return size; +} + +static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf) +{ +	return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder); +} + +static ssize_t overlay_zorder_store(struct omap_overlay *ovl, +		const char *buf, size_t size) +{ +	int r; +	u8 zorder; +	struct omap_overlay_info info; + +	if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) +		return -ENODEV; + +	r = kstrtou8(buf, 0, &zorder); +	if (r) +		return r; + +	ovl->get_overlay_info(ovl, &info); + +	info.zorder = zorder;  	r = ovl->set_overlay_info(ovl, &info);  	if (r) @@ -347,6 +373,8 @@ static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,  static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,  		overlay_pre_mult_alpha_show,  		overlay_pre_mult_alpha_store); +static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR, +		overlay_zorder_show, overlay_zorder_store);  static struct attribute *overlay_sysfs_attrs[] = {  	&overlay_attr_name.attr, @@ -358,6 +386,7 @@ static struct attribute *overlay_sysfs_attrs[] = {  	&overlay_attr_enabled.attr,  	&overlay_attr_global_alpha.attr,  	&overlay_attr_pre_mult_alpha.attr, +	&overlay_attr_zorder.attr,  	NULL  }; @@ -407,6 +436,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)  	struct omap_overlay_info *info;  	u16 outw, outh;  	u16 dw, dh; +	int i;  	if (!dssdev)  		return 0; @@ -462,6 +492,31 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)  		return -EINVAL;  	} +	if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) { +		if (info->zorder < 0 || info->zorder > 3) { +			DSSERR("zorder out of range: %d\n", +				info->zorder); +			return -EINVAL; +		} +		/* +		 * Check that zorder doesn't match with zorder of any other +		 * overlay which is enabled and is also connected to the same +		 * manager +		 */ +		for (i = 0; i < omap_dss_get_num_overlays(); i++) { +			struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i); + +			if (tmp_ovl->id != ovl->id && +					tmp_ovl->manager == ovl->manager && +					tmp_ovl->info.enabled == true && +					tmp_ovl->info.zorder == info->zorder) { +				DSSERR("%s and %s have same zorder: %d\n", +					ovl->name, tmp_ovl->name, info->zorder); +				return -EINVAL; +			} +		} +	} +  	return 0;  } @@ -516,6 +571,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,  	}  	ovl->manager = mgr; +	ovl->manager_changed = true;  	/* XXX: When there is an overlay on a DSI manual update display, and  	 * the overlay is first disabled, then moved to tv, and enabled, we @@ -529,15 +585,12 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,  	 * Userspace workaround for this is to update the LCD after disabling  	 * the overlay, but before moving the overlay to TV.  	 */ -	dispc_set_channel_out(ovl->id, mgr->id);  	return 0;  }  static int omap_dss_unset_manager(struct omap_overlay *ovl)  { -	int r; -  	if (!ovl->manager) {  		DSSERR("failed to detach overlay: manager not set\n");  		return -EINVAL; @@ -548,11 +601,8 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl)  		return -EINVAL;  	} -	r = ovl->wait_for_go(ovl); -	if (r) -		return r; -  	ovl->manager = NULL; +	ovl->manager_changed = true;  	return 0;  } @@ -618,22 +668,29 @@ void dss_init_overlays(struct platform_device *pdev)  		case 0:  			ovl->name = "gfx";  			ovl->id = OMAP_DSS_GFX; -			ovl->caps = OMAP_DSS_OVL_CAP_DISPC;  			ovl->info.global_alpha = 255; +			ovl->info.zorder = 0;  			break;  		case 1:  			ovl->name = "vid1";  			ovl->id = OMAP_DSS_VIDEO1; -			ovl->caps = OMAP_DSS_OVL_CAP_SCALE | -				OMAP_DSS_OVL_CAP_DISPC;  			ovl->info.global_alpha = 255; +			ovl->info.zorder = +				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;  			break;  		case 2:  			ovl->name = "vid2";  			ovl->id = OMAP_DSS_VIDEO2; -			ovl->caps = OMAP_DSS_OVL_CAP_SCALE | -				OMAP_DSS_OVL_CAP_DISPC;  			ovl->info.global_alpha = 255; +			ovl->info.zorder = +				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0; +			break; +		case 3: +			ovl->name = "vid3"; +			ovl->id = OMAP_DSS_VIDEO3; +			ovl->info.global_alpha = 255; +			ovl->info.zorder = +				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;  			break;  		} @@ -643,6 +700,7 @@ void dss_init_overlays(struct platform_device *pdev)  		ovl->get_overlay_info = &dss_ovl_get_overlay_info;  		ovl->wait_for_go = &dss_ovl_wait_for_go; +		ovl->caps = dss_feat_get_overlay_caps(ovl->id);  		ovl->supported_modes =  			dss_feat_get_supported_color_modes(ovl->id); diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 39f4c597026..1bd3703e42f 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -309,9 +309,9 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,  	DSSDBG("rfbi_transfer_area %dx%d\n", width, height); -	dispc_set_lcd_size(dssdev->manager->id, width, height); +	dispc_mgr_set_lcd_size(dssdev->manager->id, width, height); -	dispc_enable_channel(dssdev->manager->id, true); +	dispc_mgr_enable(dssdev->manager->id, true);  	rfbi.framedone_callback = callback;  	rfbi.framedone_callback_data = data; @@ -783,10 +783,8 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,  	if (*w == 0 || *h == 0)  		return -EINVAL; -	if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { -		dss_setup_partial_planes(dssdev, x, y, w, h, true); -		dispc_set_lcd_size(dssdev->manager->id, *w, *h); -	} +	dss_setup_partial_planes(dssdev, x, y, w, h, true); +	dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);  	return 0;  } @@ -796,22 +794,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev,  		u16 x, u16 y, u16 w, u16 h,  		void (*callback)(void *), void *data)  { -	if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { -		rfbi_transfer_area(dssdev, w, h, callback, data); -	} else { -		struct omap_overlay *ovl; -		void __iomem *addr; -		int scr_width; - -		ovl = dssdev->manager->overlays[0]; -		scr_width = ovl->info.screen_width; -		addr = ovl->info.vaddr; - -		omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); - -		callback(data); -	} - +	rfbi_transfer_area(dssdev, w, h, callback, data);  	return 0;  }  EXPORT_SYMBOL(omap_rfbi_update); @@ -860,6 +843,11 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)  {  	int r; +	if (dssdev->manager == NULL) { +		DSSERR("failed to enable display: no manager\n"); +		return -ENODEV; +	} +  	r = rfbi_runtime_get();  	if (r)  		return r; @@ -877,13 +865,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)  		goto err1;  	} -	dispc_set_lcd_display_type(dssdev->manager->id, +	dispc_mgr_set_lcd_display_type(dssdev->manager->id,  			OMAP_DSS_LCD_DISPLAY_TFT); -	dispc_set_parallel_interface_mode(dssdev->manager->id, -			OMAP_DSS_PARALLELMODE_RFBI); +	dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_RFBI); +	dispc_mgr_enable_stallmode(dssdev->manager->id, true); -	dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); +	dispc_mgr_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);  	rfbi_configure(dssdev->phy.rfbi.channel,  			       dssdev->ctrl.pixel_size, @@ -952,10 +940,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev)  	msleep(10); -	if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630()) -		clk = dss_get_ick(); -	else -		clk = clk_get(&pdev->dev, "ick"); +	clk = clk_get(&pdev->dev, "ick");  	if (IS_ERR(clk)) {  		DSSERR("can't get ick\n");  		r = PTR_ERR(clk); diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 3a688c871a4..695dc04cabb 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -35,13 +35,13 @@ static struct {  static void sdi_basic_init(struct omap_dss_device *dssdev)  { -	dispc_set_parallel_interface_mode(dssdev->manager->id, -			OMAP_DSS_PARALLELMODE_BYPASS); +	dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS); +	dispc_mgr_enable_stallmode(dssdev->manager->id, false); -	dispc_set_lcd_display_type(dssdev->manager->id, +	dispc_mgr_set_lcd_display_type(dssdev->manager->id,  			OMAP_DSS_LCD_DISPLAY_TFT); -	dispc_set_tft_data_lines(dssdev->manager->id, 24); +	dispc_mgr_set_tft_data_lines(dssdev->manager->id, 24);  	dispc_lcd_enable_signal_polarity(1);  } @@ -55,6 +55,11 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)  	unsigned long pck;  	int r; +	if (dssdev->manager == NULL) { +		DSSERR("failed to enable display: no manager\n"); +		return -ENODEV; +	} +  	r = omap_dss_start_device(dssdev);  	if (r) {  		DSSERR("failed to start device\n"); @@ -78,7 +83,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)  	/* 15.5.9.1.2 */  	dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; -	dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, +	dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,  			dssdev->panel.acbi, dssdev->panel.acb);  	r = dss_calc_clock_div(1, t->pixel_clock * 1000, @@ -101,13 +106,13 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)  	} -	dispc_set_lcd_timings(dssdev->manager->id, t); +	dispc_mgr_set_lcd_timings(dssdev->manager->id, t);  	r = dss_set_clock_div(&dss_cinfo);  	if (r)  		goto err_set_dss_clock_div; -	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); +	r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);  	if (r)  		goto err_set_dispc_clock_div; diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h new file mode 100644 index 00000000000..2c3443dabb1 --- /dev/null +++ b/drivers/video/omap2/dss/ti_hdmi.h @@ -0,0 +1,138 @@ +/* + * ti_hdmi.h + * + * HDMI driver definition for TI OMAP4, DM81xx, DM38xx  Processor. + * + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef _TI_HDMI_H +#define _TI_HDMI_H + +struct hdmi_ip_data; + +enum hdmi_pll_pwr { +	HDMI_PLLPWRCMD_ALLOFF = 0, +	HDMI_PLLPWRCMD_PLLONLY = 1, +	HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, +	HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 +}; + +enum hdmi_core_hdmi_dvi { +	HDMI_DVI = 0, +	HDMI_HDMI = 1 +}; + +enum hdmi_clk_refsel { +	HDMI_REFSEL_PCLK = 0, +	HDMI_REFSEL_REF1 = 1, +	HDMI_REFSEL_REF2 = 2, +	HDMI_REFSEL_SYSCLK = 3 +}; + +struct hdmi_video_timings { +	u16 x_res; +	u16 y_res; +	/* Unit: KHz */ +	u32 pixel_clock; +	u16 hsw; +	u16 hfp; +	u16 hbp; +	u16 vsw; +	u16 vfp; +	u16 vbp; +}; + +/* HDMI timing structure */ +struct hdmi_timings { +	struct hdmi_video_timings timings; +	int vsync_pol; +	int hsync_pol; +}; + +struct hdmi_cm { +	int	code; +	int	mode; +}; + +struct hdmi_config { +	struct hdmi_timings timings; +	u16	interlace; +	struct hdmi_cm cm; +}; + +/* HDMI PLL structure */ +struct hdmi_pll_info { +	u16 regn; +	u16 regm; +	u32 regmf; +	u16 regm2; +	u16 regsd; +	u16 dcofreq; +	enum hdmi_clk_refsel refsel; +}; + +struct ti_hdmi_ip_ops { + +	void (*video_configure)(struct hdmi_ip_data *ip_data); + +	int (*phy_enable)(struct hdmi_ip_data *ip_data); + +	void (*phy_disable)(struct hdmi_ip_data *ip_data); + +	int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len); + +	bool (*detect)(struct hdmi_ip_data *ip_data); + +	int (*pll_enable)(struct hdmi_ip_data *ip_data); + +	void (*pll_disable)(struct hdmi_ip_data *ip_data); + +	void (*video_enable)(struct hdmi_ip_data *ip_data, bool start); + +	void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s); + +	void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s); + +	void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s); + +	void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); + +}; + +struct hdmi_ip_data { +	void __iomem	*base_wp;	/* HDMI wrapper */ +	unsigned long	core_sys_offset; +	unsigned long	core_av_offset; +	unsigned long	pll_offset; +	unsigned long	phy_offset; +	const struct ti_hdmi_ip_ops *ops; +	struct hdmi_config cfg; +	struct hdmi_pll_info pll_data; +}; +int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); +void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); +int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); +bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data); +void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start); +int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); +void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); +void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); +void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); +void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); +void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); +void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); + +#endif diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c new file mode 100644 index 00000000000..e1a6ce518af --- /dev/null +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -0,0 +1,1239 @@ +/* + * ti_hdmi_4xxx_ip.c + * + * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * Authors: Yong Zhi + *	Mythri pk <mythripk@ti.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/mutex.h> +#include <linux/delay.h> +#include <linux/string.h> +#include <linux/seq_file.h> + +#include "ti_hdmi_4xxx_ip.h" +#include "dss.h" + +static inline void hdmi_write_reg(void __iomem *base_addr, +				const u16 idx, u32 val) +{ +	__raw_writel(val, base_addr + idx); +} + +static inline u32 hdmi_read_reg(void __iomem *base_addr, +				const u16 idx) +{ +	return __raw_readl(base_addr + idx); +} + +static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data) +{ +	return ip_data->base_wp; +} + +static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data) +{ +	return ip_data->base_wp + ip_data->phy_offset; +} + +static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data) +{ +	return ip_data->base_wp + ip_data->pll_offset; +} + +static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data) +{ +	return ip_data->base_wp + ip_data->core_av_offset; +} + +static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data) +{ +	return ip_data->base_wp + ip_data->core_sys_offset; +} + +static inline int hdmi_wait_for_bit_change(void __iomem *base_addr, +				const u16 idx, +				int b2, int b1, u32 val) +{ +	u32 t = 0; +	while (val != REG_GET(base_addr, idx, b2, b1)) { +		udelay(1); +		if (t++ > 10000) +			return !val; +	} +	return val; +} + +static int hdmi_pll_init(struct hdmi_ip_data *ip_data) +{ +	u32 r; +	void __iomem *pll_base = hdmi_pll_base(ip_data); +	struct hdmi_pll_info *fmt = &ip_data->pll_data; + +	/* PLL start always use manual mode */ +	REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0); + +	r = hdmi_read_reg(pll_base, PLLCTRL_CFG1); +	r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ +	r = FLD_MOD(r, fmt->regn - 1, 8, 1);  /* CFG1_PLL_REGN */ + +	hdmi_write_reg(pll_base, PLLCTRL_CFG1, r); + +	r = hdmi_read_reg(pll_base, PLLCTRL_CFG2); + +	r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ +	r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ +	r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ +	r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */ + +	if (fmt->dcofreq) { +		/* divider programming for frequency beyond 1000Mhz */ +		REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 17, 10); +		r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ +	} else { +		r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ +	} + +	hdmi_write_reg(pll_base, PLLCTRL_CFG2, r); + +	r = hdmi_read_reg(pll_base, PLLCTRL_CFG4); +	r = FLD_MOD(r, fmt->regm2, 24, 18); +	r = FLD_MOD(r, fmt->regmf, 17, 0); + +	hdmi_write_reg(pll_base, PLLCTRL_CFG4, r); + +	/* go now */ +	REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0); + +	/* wait for bit change */ +	if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO, +							0, 0, 1) != 1) { +		pr_err("PLL GO bit not set\n"); +		return -ETIMEDOUT; +	} + +	/* Wait till the lock bit is set in PLL status */ +	if (hdmi_wait_for_bit_change(pll_base, +				PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { +		pr_err("cannot lock PLL\n"); +		pr_err("CFG1 0x%x\n", +			hdmi_read_reg(pll_base, PLLCTRL_CFG1)); +		pr_err("CFG2 0x%x\n", +			hdmi_read_reg(pll_base, PLLCTRL_CFG2)); +		pr_err("CFG4 0x%x\n", +			hdmi_read_reg(pll_base, PLLCTRL_CFG4)); +		return -ETIMEDOUT; +	} + +	pr_debug("PLL locked!\n"); + +	return 0; +} + +/* PHY_PWR_CMD */ +static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val) +{ +	/* Command for power control of HDMI PHY */ +	REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6); + +	/* Status of the power control of HDMI PHY */ +	if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), +				HDMI_WP_PWR_CTRL, 5, 4, val) != val) { +		pr_err("Failed to set PHY power mode to %d\n", val); +		return -ETIMEDOUT; +	} + +	return 0; +} + +/* PLL_PWR_CMD */ +static int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val) +{ +	/* Command for power control of HDMI PLL */ +	REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2); + +	/* wait till PHY_PWR_STATUS is set */ +	if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, +						1, 0, val) != val) { +		pr_err("Failed to set PLL_PWR_STATUS\n"); +		return -ETIMEDOUT; +	} + +	return 0; +} + +static int hdmi_pll_reset(struct hdmi_ip_data *ip_data) +{ +	/* SYSRESET  controlled by power FSM */ +	REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3); + +	/* READ 0x0 reset is in progress */ +	if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data), +				PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { +		pr_err("Failed to sysreset PLL\n"); +		return -ETIMEDOUT; +	} + +	return 0; +} + +int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data) +{ +	u16 r = 0; + +	r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); +	if (r) +		return r; + +	r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); +	if (r) +		return r; + +	r = hdmi_pll_reset(ip_data); +	if (r) +		return r; + +	r = hdmi_pll_init(ip_data); +	if (r) +		return r; + +	return 0; +} + +void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data) +{ +	hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); +} + +int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data) +{ +	u16 r = 0; +	void __iomem *phy_base = hdmi_phy_base(ip_data); + +	r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); +	if (r) +		return r; + +	r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); +	if (r) +		return r; + +	/* +	 * Read address 0 in order to get the SCP reset done completed +	 * Dummy access performed to make sure reset is done +	 */ +	hdmi_read_reg(phy_base, HDMI_TXPHY_TX_CTRL); + +	/* +	 * Write to phy address 0 to configure the clock +	 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field +	 */ +	REG_FLD_MOD(phy_base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); + +	/* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ +	hdmi_write_reg(phy_base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); + +	/* Setup max LDO voltage */ +	REG_FLD_MOD(phy_base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); + +	/* Write to phy address 3 to change the polarity control */ +	REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); + +	return 0; +} + +void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data) +{ +	hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); +} + +static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data) +{ +	void __iomem *base = hdmi_core_sys_base(ip_data); + +	/* Turn on CLK for DDC */ +	REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0); + +	/* IN_PROG */ +	if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) { +		/* Abort transaction */ +		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0); +		/* IN_PROG */ +		if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, +					4, 4, 0) != 0) { +			DSSERR("Timeout aborting DDC transaction\n"); +			return -ETIMEDOUT; +		} +	} + +	/* Clk SCL Devices */ +	REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0); + +	/* HDMI_CORE_DDC_STATUS_IN_PROG */ +	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, +				4, 4, 0) != 0) { +		DSSERR("Timeout starting SCL clock\n"); +		return -ETIMEDOUT; +	} + +	/* Clear FIFO */ +	REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0); + +	/* HDMI_CORE_DDC_STATUS_IN_PROG */ +	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, +				4, 4, 0) != 0) { +		DSSERR("Timeout clearing DDC fifo\n"); +		return -ETIMEDOUT; +	} + +	return 0; +} + +static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, +		u8 *pedid, int ext) +{ +	void __iomem *base = hdmi_core_sys_base(ip_data); +	u32 i; +	char checksum; +	u32 offset = 0; + +	/* HDMI_CORE_DDC_STATUS_IN_PROG */ +	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, +				4, 4, 0) != 0) { +		DSSERR("Timeout waiting DDC to be ready\n"); +		return -ETIMEDOUT; +	} + +	if (ext % 2 != 0) +		offset = 0x80; + +	/* Load Segment Address Register */ +	REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0); + +	/* Load Slave Address Register */ +	REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); + +	/* Load Offset Address Register */ +	REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0); + +	/* Load Byte Count */ +	REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); +	REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); + +	/* Set DDC_CMD */ +	if (ext) +		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0); +	else +		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0); + +	/* HDMI_CORE_DDC_STATUS_BUS_LOW */ +	if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) { +		pr_err("I2C Bus Low?\n"); +		return -EIO; +	} +	/* HDMI_CORE_DDC_STATUS_NO_ACK */ +	if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) { +		pr_err("I2C No Ack\n"); +		return -EIO; +	} + +	for (i = 0; i < 0x80; ++i) { +		int t; + +		/* IN_PROG */ +		if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) { +			DSSERR("operation stopped when reading edid\n"); +			return -EIO; +		} + +		t = 0; +		/* FIFO_EMPTY */ +		while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) { +			if (t++ > 10000) { +				DSSERR("timeout reading edid\n"); +				return -ETIMEDOUT; +			} +			udelay(1); +		} + +		pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); +	} + +	checksum = 0; +	for (i = 0; i < 0x80; ++i) +		checksum += pedid[i]; + +	if (checksum != 0) { +		pr_err("E-EDID checksum failed!!\n"); +		return -EIO; +	} + +	return 0; +} + +int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, +				u8 *edid, int len) +{ +	int r, l; + +	if (len < 128) +		return -EINVAL; + +	r = hdmi_core_ddc_init(ip_data); +	if (r) +		return r; + +	r = hdmi_core_ddc_edid(ip_data, edid, 0); +	if (r) +		return r; + +	l = 128; + +	if (len >= 128 * 2 && edid[0x7e] > 0) { +		r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1); +		if (r) +			return r; +		l += 128; +	} + +	return l; +} + +bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data) +{ +	int r; + +	void __iomem *base = hdmi_core_sys_base(ip_data); + +	/* HPD */ +	r = REG_GET(base, HDMI_CORE_SYS_SYS_STAT, 1, 1); + +	return r == 1; +} + +static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, +			struct hdmi_core_infoframe_avi *avi_cfg, +			struct hdmi_core_packet_enable_repeat *repeat_cfg) +{ +	pr_debug("Enter hdmi_core_init\n"); + +	/* video core */ +	video_cfg->ip_bus_width = HDMI_INPUT_8BIT; +	video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; +	video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; +	video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; +	video_cfg->hdmi_dvi = HDMI_DVI; +	video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; + +	/* info frame */ +	avi_cfg->db1_format = 0; +	avi_cfg->db1_active_info = 0; +	avi_cfg->db1_bar_info_dv = 0; +	avi_cfg->db1_scan_info = 0; +	avi_cfg->db2_colorimetry = 0; +	avi_cfg->db2_aspect_ratio = 0; +	avi_cfg->db2_active_fmt_ar = 0; +	avi_cfg->db3_itc = 0; +	avi_cfg->db3_ec = 0; +	avi_cfg->db3_q_range = 0; +	avi_cfg->db3_nup_scaling = 0; +	avi_cfg->db4_videocode = 0; +	avi_cfg->db5_pixel_repeat = 0; +	avi_cfg->db6_7_line_eoftop = 0 ; +	avi_cfg->db8_9_line_sofbottom = 0; +	avi_cfg->db10_11_pixel_eofleft = 0; +	avi_cfg->db12_13_pixel_sofright = 0; + +	/* packet enable and repeat */ +	repeat_cfg->audio_pkt = 0; +	repeat_cfg->audio_pkt_repeat = 0; +	repeat_cfg->avi_infoframe = 0; +	repeat_cfg->avi_infoframe_repeat = 0; +	repeat_cfg->gen_cntrl_pkt = 0; +	repeat_cfg->gen_cntrl_pkt_repeat = 0; +	repeat_cfg->generic_pkt = 0; +	repeat_cfg->generic_pkt_repeat = 0; +} + +static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data) +{ +	pr_debug("Enter hdmi_core_powerdown_disable\n"); +	REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0); +} + +static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data) +{ +	pr_debug("Enter hdmi_core_swreset_release\n"); +	REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0); +} + +static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data) +{ +	pr_debug("Enter hdmi_core_swreset_assert\n"); +	REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0); +} + +/* HDMI_CORE_VIDEO_CONFIG */ +static void hdmi_core_video_config(struct hdmi_ip_data *ip_data, +				struct hdmi_core_video_config *cfg) +{ +	u32 r = 0; +	void __iomem *core_sys_base = hdmi_core_sys_base(ip_data); + +	/* sys_ctrl1 default configuration not tunable */ +	r = hdmi_read_reg(core_sys_base, HDMI_CORE_CTRL1); +	r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); +	r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); +	r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); +	r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); +	hdmi_write_reg(core_sys_base, HDMI_CORE_CTRL1, r); + +	REG_FLD_MOD(core_sys_base, +			HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); + +	/* Vid_Mode */ +	r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE); + +	/* dither truncation configuration */ +	if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { +		r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); +		r = FLD_MOD(r, 1, 5, 5); +	} else { +		r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); +		r = FLD_MOD(r, 0, 5, 5); +	} +	hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r); + +	/* HDMI_Ctrl */ +	r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL); +	r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); +	r = FLD_MOD(r, cfg->pkt_mode, 5, 3); +	r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); +	hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r); + +	/* TMDS_CTRL */ +	REG_FLD_MOD(core_sys_base, +			HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); +} + +static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data, +		struct hdmi_core_infoframe_avi info_avi) +{ +	u32 val; +	char sum = 0, checksum = 0; +	void __iomem *av_base = hdmi_av_base(ip_data); + +	sum += 0x82 + 0x002 + 0x00D; +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D); + +	val = (info_avi.db1_format << 5) | +		(info_avi.db1_active_info << 4) | +		(info_avi.db1_bar_info_dv << 2) | +		(info_avi.db1_scan_info); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val); +	sum += val; + +	val = (info_avi.db2_colorimetry << 6) | +		(info_avi.db2_aspect_ratio << 4) | +		(info_avi.db2_active_fmt_ar); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val); +	sum += val; + +	val = (info_avi.db3_itc << 7) | +		(info_avi.db3_ec << 4) | +		(info_avi.db3_q_range << 2) | +		(info_avi.db3_nup_scaling); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val); +	sum += val; + +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3), +					info_avi.db4_videocode); +	sum += info_avi.db4_videocode; + +	val = info_avi.db5_pixel_repeat; +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val); +	sum += val; + +	val = info_avi.db6_7_line_eoftop & 0x00FF; +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val); +	sum += val; + +	val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val); +	sum += val; + +	val = info_avi.db8_9_line_sofbottom & 0x00FF; +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val); +	sum += val; + +	val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val); +	sum += val; + +	val = info_avi.db10_11_pixel_eofleft & 0x00FF; +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val); +	sum += val; + +	val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val); +	sum += val; + +	val = info_avi.db12_13_pixel_sofright & 0x00FF; +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val); +	sum += val; + +	val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val); +	sum += val; + +	checksum = 0x100 - sum; +	hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum); +} + +static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data, +		struct hdmi_core_packet_enable_repeat repeat_cfg) +{ +	/* enable/repeat the infoframe */ +	hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1, +		(repeat_cfg.audio_pkt << 5) | +		(repeat_cfg.audio_pkt_repeat << 4) | +		(repeat_cfg.avi_infoframe << 1) | +		(repeat_cfg.avi_infoframe_repeat)); + +	/* enable/repeat the packet */ +	hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2, +		(repeat_cfg.gen_cntrl_pkt << 3) | +		(repeat_cfg.gen_cntrl_pkt_repeat << 2) | +		(repeat_cfg.generic_pkt << 1) | +		(repeat_cfg.generic_pkt_repeat)); +} + +static void hdmi_wp_init(struct omap_video_timings *timings, +			struct hdmi_video_format *video_fmt, +			struct hdmi_video_interface *video_int) +{ +	pr_debug("Enter hdmi_wp_init\n"); + +	timings->hbp = 0; +	timings->hfp = 0; +	timings->hsw = 0; +	timings->vbp = 0; +	timings->vfp = 0; +	timings->vsw = 0; + +	video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; +	video_fmt->y_res = 0; +	video_fmt->x_res = 0; + +	video_int->vsp = 0; +	video_int->hsp = 0; + +	video_int->interlacing = 0; +	video_int->tm = 0; /* HDMI_TIMING_SLAVE */ + +} + +void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start) +{ +	REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31); +} + +static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, +	struct omap_video_timings *timings, struct hdmi_config *param) +{ +	pr_debug("Enter hdmi_wp_video_init_format\n"); + +	video_fmt->y_res = param->timings.timings.y_res; +	video_fmt->x_res = param->timings.timings.x_res; + +	timings->hbp = param->timings.timings.hbp; +	timings->hfp = param->timings.timings.hfp; +	timings->hsw = param->timings.timings.hsw; +	timings->vbp = param->timings.timings.vbp; +	timings->vfp = param->timings.timings.vfp; +	timings->vsw = param->timings.timings.vsw; +} + +static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data, +		struct hdmi_video_format *video_fmt) +{ +	u32 l = 0; + +	REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, +			video_fmt->packing_mode, 10, 8); + +	l |= FLD_VAL(video_fmt->y_res, 31, 16); +	l |= FLD_VAL(video_fmt->x_res, 15, 0); +	hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l); +} + +static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data, +		struct hdmi_video_interface *video_int) +{ +	u32 r; +	pr_debug("Enter hdmi_wp_video_config_interface\n"); + +	r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG); +	r = FLD_MOD(r, video_int->vsp, 7, 7); +	r = FLD_MOD(r, video_int->hsp, 6, 6); +	r = FLD_MOD(r, video_int->interlacing, 3, 3); +	r = FLD_MOD(r, video_int->tm, 1, 0); +	hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r); +} + +static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data, +		struct omap_video_timings *timings) +{ +	u32 timing_h = 0; +	u32 timing_v = 0; + +	pr_debug("Enter hdmi_wp_video_config_timing\n"); + +	timing_h |= FLD_VAL(timings->hbp, 31, 20); +	timing_h |= FLD_VAL(timings->hfp, 19, 8); +	timing_h |= FLD_VAL(timings->hsw, 7, 0); +	hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h); + +	timing_v |= FLD_VAL(timings->vbp, 31, 20); +	timing_v |= FLD_VAL(timings->vfp, 19, 8); +	timing_v |= FLD_VAL(timings->vsw, 7, 0); +	hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v); +} + +void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) +{ +	/* HDMI */ +	struct omap_video_timings video_timing; +	struct hdmi_video_format video_format; +	struct hdmi_video_interface video_interface; +	/* HDMI core */ +	struct hdmi_core_infoframe_avi avi_cfg; +	struct hdmi_core_video_config v_core_cfg; +	struct hdmi_core_packet_enable_repeat repeat_cfg; +	struct hdmi_config *cfg = &ip_data->cfg; + +	hdmi_wp_init(&video_timing, &video_format, +		&video_interface); + +	hdmi_core_init(&v_core_cfg, +		&avi_cfg, +		&repeat_cfg); + +	hdmi_wp_video_init_format(&video_format, &video_timing, cfg); + +	hdmi_wp_video_config_timing(ip_data, &video_timing); + +	/* video config */ +	video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; + +	hdmi_wp_video_config_format(ip_data, &video_format); + +	video_interface.vsp = cfg->timings.vsync_pol; +	video_interface.hsp = cfg->timings.hsync_pol; +	video_interface.interlacing = cfg->interlace; +	video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ + +	hdmi_wp_video_config_interface(ip_data, &video_interface); + +	/* +	 * configure core video part +	 * set software reset in the core +	 */ +	hdmi_core_swreset_assert(ip_data); + +	/* power down off */ +	hdmi_core_powerdown_disable(ip_data); + +	v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; +	v_core_cfg.hdmi_dvi = cfg->cm.mode; + +	hdmi_core_video_config(ip_data, &v_core_cfg); + +	/* release software reset in the core */ +	hdmi_core_swreset_release(ip_data); + +	/* +	 * configure packet +	 * info frame video see doc CEA861-D page 65 +	 */ +	avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; +	avi_cfg.db1_active_info = +		HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; +	avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; +	avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; +	avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; +	avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; +	avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; +	avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; +	avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; +	avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; +	avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; +	avi_cfg.db4_videocode = cfg->cm.code; +	avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; +	avi_cfg.db6_7_line_eoftop = 0; +	avi_cfg.db8_9_line_sofbottom = 0; +	avi_cfg.db10_11_pixel_eofleft = 0; +	avi_cfg.db12_13_pixel_sofright = 0; + +	hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg); + +	/* enable/repeat the infoframe */ +	repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; +	repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; +	/* wakeup */ +	repeat_cfg.audio_pkt = HDMI_PACKETENABLE; +	repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; +	hdmi_core_av_packet_config(ip_data, repeat_cfg); +} + +void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) +{ +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\ +		hdmi_read_reg(hdmi_wp_base(ip_data), r)) + +	DUMPREG(HDMI_WP_REVISION); +	DUMPREG(HDMI_WP_SYSCONFIG); +	DUMPREG(HDMI_WP_IRQSTATUS_RAW); +	DUMPREG(HDMI_WP_IRQSTATUS); +	DUMPREG(HDMI_WP_PWR_CTRL); +	DUMPREG(HDMI_WP_IRQENABLE_SET); +	DUMPREG(HDMI_WP_VIDEO_CFG); +	DUMPREG(HDMI_WP_VIDEO_SIZE); +	DUMPREG(HDMI_WP_VIDEO_TIMING_H); +	DUMPREG(HDMI_WP_VIDEO_TIMING_V); +	DUMPREG(HDMI_WP_WP_CLK); +	DUMPREG(HDMI_WP_AUDIO_CFG); +	DUMPREG(HDMI_WP_AUDIO_CFG2); +	DUMPREG(HDMI_WP_AUDIO_CTRL); +	DUMPREG(HDMI_WP_AUDIO_DATA); +} + +void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) +{ +#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ +		hdmi_read_reg(hdmi_pll_base(ip_data), r)) + +	DUMPPLL(PLLCTRL_PLL_CONTROL); +	DUMPPLL(PLLCTRL_PLL_STATUS); +	DUMPPLL(PLLCTRL_PLL_GO); +	DUMPPLL(PLLCTRL_CFG1); +	DUMPPLL(PLLCTRL_CFG2); +	DUMPPLL(PLLCTRL_CFG3); +	DUMPPLL(PLLCTRL_CFG4); +} + +void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) +{ +	int i; + +#define CORE_REG(i, name) name(i) +#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ +		hdmi_read_reg(hdmi_pll_base(ip_data), r)) +#define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ +		(i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \ +		hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r))) + +	DUMPCORE(HDMI_CORE_SYS_VND_IDL); +	DUMPCORE(HDMI_CORE_SYS_DEV_IDL); +	DUMPCORE(HDMI_CORE_SYS_DEV_IDH); +	DUMPCORE(HDMI_CORE_SYS_DEV_REV); +	DUMPCORE(HDMI_CORE_SYS_SRST); +	DUMPCORE(HDMI_CORE_CTRL1); +	DUMPCORE(HDMI_CORE_SYS_SYS_STAT); +	DUMPCORE(HDMI_CORE_SYS_VID_ACEN); +	DUMPCORE(HDMI_CORE_SYS_VID_MODE); +	DUMPCORE(HDMI_CORE_SYS_INTR_STATE); +	DUMPCORE(HDMI_CORE_SYS_INTR1); +	DUMPCORE(HDMI_CORE_SYS_INTR2); +	DUMPCORE(HDMI_CORE_SYS_INTR3); +	DUMPCORE(HDMI_CORE_SYS_INTR4); +	DUMPCORE(HDMI_CORE_SYS_UMASK1); +	DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); +	DUMPCORE(HDMI_CORE_SYS_DE_DLY); +	DUMPCORE(HDMI_CORE_SYS_DE_CTRL); +	DUMPCORE(HDMI_CORE_SYS_DE_TOP); +	DUMPCORE(HDMI_CORE_SYS_DE_CNTL); +	DUMPCORE(HDMI_CORE_SYS_DE_CNTH); +	DUMPCORE(HDMI_CORE_SYS_DE_LINL); +	DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); + +	DUMPCORE(HDMI_CORE_DDC_CMD); +	DUMPCORE(HDMI_CORE_DDC_STATUS); +	DUMPCORE(HDMI_CORE_DDC_ADDR); +	DUMPCORE(HDMI_CORE_DDC_OFFSET); +	DUMPCORE(HDMI_CORE_DDC_COUNT1); +	DUMPCORE(HDMI_CORE_DDC_COUNT2); +	DUMPCORE(HDMI_CORE_DDC_DATA); +	DUMPCORE(HDMI_CORE_DDC_SEGM); + +	DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); +	DUMPCORE(HDMI_CORE_AV_DPD); +	DUMPCORE(HDMI_CORE_AV_PB_CTRL1); +	DUMPCORE(HDMI_CORE_AV_PB_CTRL2); +	DUMPCORE(HDMI_CORE_AV_AVI_TYPE); +	DUMPCORE(HDMI_CORE_AV_AVI_VERS); +	DUMPCORE(HDMI_CORE_AV_AVI_LEN); +	DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); + +	for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++) +		DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE); + +	for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++) +		DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE); + +	for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++) +		DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE); + +	for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++) +		DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE); + +	for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++) +		DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE); + +	for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++) +		DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE); + +	DUMPCORE(HDMI_CORE_AV_ACR_CTRL); +	DUMPCORE(HDMI_CORE_AV_FREQ_SVAL); +	DUMPCORE(HDMI_CORE_AV_N_SVAL1); +	DUMPCORE(HDMI_CORE_AV_N_SVAL2); +	DUMPCORE(HDMI_CORE_AV_N_SVAL3); +	DUMPCORE(HDMI_CORE_AV_CTS_SVAL1); +	DUMPCORE(HDMI_CORE_AV_CTS_SVAL2); +	DUMPCORE(HDMI_CORE_AV_CTS_SVAL3); +	DUMPCORE(HDMI_CORE_AV_CTS_HVAL1); +	DUMPCORE(HDMI_CORE_AV_CTS_HVAL2); +	DUMPCORE(HDMI_CORE_AV_CTS_HVAL3); +	DUMPCORE(HDMI_CORE_AV_AUD_MODE); +	DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL); +	DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS); +	DUMPCORE(HDMI_CORE_AV_SWAP_I2S); +	DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH); +	DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP); +	DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL); +	DUMPCORE(HDMI_CORE_AV_I2S_CHST0); +	DUMPCORE(HDMI_CORE_AV_I2S_CHST1); +	DUMPCORE(HDMI_CORE_AV_I2S_CHST2); +	DUMPCORE(HDMI_CORE_AV_I2S_CHST4); +	DUMPCORE(HDMI_CORE_AV_I2S_CHST5); +	DUMPCORE(HDMI_CORE_AV_ASRC); +	DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN); +	DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); +	DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT); +	DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1); +	DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2); +	DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3); +	DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL); +	DUMPCORE(HDMI_CORE_AV_DPD); +	DUMPCORE(HDMI_CORE_AV_PB_CTRL1); +	DUMPCORE(HDMI_CORE_AV_PB_CTRL2); +	DUMPCORE(HDMI_CORE_AV_AVI_TYPE); +	DUMPCORE(HDMI_CORE_AV_AVI_VERS); +	DUMPCORE(HDMI_CORE_AV_AVI_LEN); +	DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); +	DUMPCORE(HDMI_CORE_AV_SPD_TYPE); +	DUMPCORE(HDMI_CORE_AV_SPD_VERS); +	DUMPCORE(HDMI_CORE_AV_SPD_LEN); +	DUMPCORE(HDMI_CORE_AV_SPD_CHSUM); +	DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE); +	DUMPCORE(HDMI_CORE_AV_AUDIO_VERS); +	DUMPCORE(HDMI_CORE_AV_AUDIO_LEN); +	DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM); +	DUMPCORE(HDMI_CORE_AV_MPEG_TYPE); +	DUMPCORE(HDMI_CORE_AV_MPEG_VERS); +	DUMPCORE(HDMI_CORE_AV_MPEG_LEN); +	DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM); +	DUMPCORE(HDMI_CORE_AV_CP_BYTE1); +	DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID); +} + +void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) +{ +#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ +		hdmi_read_reg(hdmi_phy_base(ip_data), r)) + +	DUMPPHY(HDMI_TXPHY_TX_CTRL); +	DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL); +	DUMPPHY(HDMI_TXPHY_POWER_CTRL); +	DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); +} + +#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ +	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) +void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data, +					struct hdmi_audio_format *aud_fmt) +{ +	u32 r; + +	DSSDBG("Enter hdmi_wp_audio_config_format\n"); + +	r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG); +	r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); +	r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); +	r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); +	r = FLD_MOD(r, aud_fmt->type, 4, 4); +	r = FLD_MOD(r, aud_fmt->justification, 3, 3); +	r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); +	r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); +	r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); +	hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r); +} + +void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, +					struct hdmi_audio_dma *aud_dma) +{ +	u32 r; + +	DSSDBG("Enter hdmi_wp_audio_config_dma\n"); + +	r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2); +	r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); +	r = FLD_MOD(r, aud_dma->block_size, 7, 0); +	hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r); + +	r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL); +	r = FLD_MOD(r, aud_dma->mode, 9, 9); +	r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); +	hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r); +} + +void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, +					struct hdmi_core_audio_config *cfg) +{ +	u32 r; +	void __iomem *av_base = hdmi_av_base(ip_data); + +	/* audio clock recovery parameters */ +	r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL); +	r = FLD_MOD(r, cfg->use_mclk, 2, 2); +	r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); +	r = FLD_MOD(r, cfg->cts_mode, 0, 0); +	hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r); + +	REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); +	REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); +	REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); + +	if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { +		REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); +		REG_FLD_MOD(av_base, +				HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); +		REG_FLD_MOD(av_base, +				HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); +	} else { +		/* +		 * HDMI IP uses this configuration to divide the MCLK to +		 * update CTS value. +		 */ +		REG_FLD_MOD(av_base, +				HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); + +		/* Configure clock for audio packets */ +		REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1, +				cfg->aud_par_busclk, 7, 0); +		REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2, +				(cfg->aud_par_busclk >> 8), 7, 0); +		REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3, +				(cfg->aud_par_busclk >> 16), 7, 0); +	} + +	/* Override of SPDIF sample frequency with value in I2S_CHST4 */ +	REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, +						cfg->fs_override, 1, 1); + +	/* I2S parameters */ +	REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4, +						cfg->freq_sample, 3, 0); + +	r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL); +	r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); +	r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); +	r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); +	r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); +	r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); +	r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); +	r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); +	r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); +	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r); + +	r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_CHST5); +	r = FLD_MOD(r, cfg->freq_sample, 7, 4); +	r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); +	r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); +	hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, r); + +	REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN, +			cfg->i2s_cfg.in_length_bits, 3, 0); + +	/* Audio channels and mode parameters */ +	REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); +	r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE); +	r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); +	r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); +	r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); +	r = FLD_MOD(r, cfg->en_spdif, 1, 1); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r); +} + +void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, +		struct hdmi_core_infoframe_audio *info_aud) +{ +	u8 val; +	u8 sum = 0, checksum = 0; +	void __iomem *av_base = hdmi_av_base(ip_data); + +	/* +	 * Set audio info frame type, version and length as +	 * described in HDMI 1.4a Section 8.2.2 specification. +	 * Checksum calculation is defined in Section 5.3.5. +	 */ +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a); +	sum += 0x84 + 0x001 + 0x00a; + +	val = (info_aud->db1_coding_type << 4) +			| (info_aud->db1_channel_count - 1); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val); +	sum += val; + +	val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val); +	sum += val; + +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00); + +	val = info_aud->db4_channel_alloc; +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val); +	sum += val; + +	val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val); +	sum += val; + +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00); +	hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00); + +	checksum = 0x100 - sum; +	hdmi_write_reg(av_base, +					HDMI_CORE_AV_AUDIO_CHSUM, checksum); + +	/* +	 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing +	 * is available. +	 */ +} + +int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, +				u32 sample_freq, u32 *n, u32 *cts) +{ +	u32 r; +	u32 deep_color = 0; +	u32 pclk = ip_data->cfg.timings.timings.pixel_clock; + +	if (n == NULL || cts == NULL) +		return -EINVAL; +	/* +	 * Obtain current deep color configuration. This needed +	 * to calculate the TMDS clock based on the pixel clock. +	 */ +	r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0); +	switch (r) { +	case 1: /* No deep color selected */ +		deep_color = 100; +		break; +	case 2: /* 10-bit deep color selected */ +		deep_color = 125; +		break; +	case 3: /* 12-bit deep color selected */ +		deep_color = 150; +		break; +	default: +		return -EINVAL; +	} + +	switch (sample_freq) { +	case 32000: +		if ((deep_color == 125) && ((pclk == 54054) +				|| (pclk == 74250))) +			*n = 8192; +		else +			*n = 4096; +		break; +	case 44100: +		*n = 6272; +		break; +	case 48000: +		if ((deep_color == 125) && ((pclk == 54054) +				|| (pclk == 74250))) +			*n = 8192; +		else +			*n = 6144; +		break; +	default: +		*n = 0; +		return -EINVAL; +	} + +	/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ +	*cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); + +	return 0; +} + +int hdmi_audio_trigger(struct hdmi_ip_data *ip_data, +				struct snd_pcm_substream *substream, int cmd, +				struct snd_soc_dai *dai) +{ +	int err = 0; +	switch (cmd) { +	case SNDRV_PCM_TRIGGER_START: +	case SNDRV_PCM_TRIGGER_RESUME: +	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: +		REG_FLD_MOD(hdmi_av_base(ip_data), +					HDMI_CORE_AV_AUD_MODE, 1, 0, 0); +		REG_FLD_MOD(hdmi_wp_base(ip_data), +					HDMI_WP_AUDIO_CTRL, 1, 31, 31); +		REG_FLD_MOD(hdmi_wp_base(ip_data), +					HDMI_WP_AUDIO_CTRL, 1, 30, 30); +		break; + +	case SNDRV_PCM_TRIGGER_STOP: +	case SNDRV_PCM_TRIGGER_SUSPEND: +	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: +		REG_FLD_MOD(hdmi_av_base(ip_data), +					HDMI_CORE_AV_AUD_MODE, 0, 0, 0); +		REG_FLD_MOD(hdmi_wp_base(ip_data), +					HDMI_WP_AUDIO_CTRL, 0, 30, 30); +		REG_FLD_MOD(hdmi_wp_base(ip_data), +					HDMI_WP_AUDIO_CTRL, 0, 31, 31); +		break; +	default: +		err = -EINVAL; +	} +	return err; +} +#endif diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h index c885f9cb065..204095632d2 100644 --- a/drivers/video/omap2/dss/hdmi.h +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h @@ -1,7 +1,7 @@  /* - * hdmi.h + * ti_hdmi_4xxx_ip.h   * - * HDMI driver definition for TI OMAP4 processors. + * HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors.   *   * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/   * @@ -18,202 +18,177 @@   * this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef _OMAP4_DSS_HDMI_H_ -#define _OMAP4_DSS_HDMI_H_ +#ifndef _HDMI_TI_4xxx_H_ +#define _HDMI_TI_4xxx_H_  #include <linux/string.h>  #include <video/omapdss.h> - -#define HDMI_WP		0x0 -#define HDMI_CORE_SYS		0x400 -#define HDMI_CORE_AV		0x900 -#define HDMI_PLLCTRL		0x200 -#define HDMI_PHY		0x300 - -struct hdmi_reg { u16 idx; }; - -#define HDMI_REG(idx)			((const struct hdmi_reg) { idx }) +#include "ti_hdmi.h" +#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ +	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) +#include <sound/soc.h> +#include <sound/pcm_params.h> +#endif  /* HDMI Wrapper */ -#define HDMI_WP_REG(idx)			HDMI_REG(HDMI_WP + idx) -#define HDMI_WP_REVISION			HDMI_WP_REG(0x0) -#define HDMI_WP_SYSCONFIG			HDMI_WP_REG(0x10) -#define HDMI_WP_IRQSTATUS_RAW			HDMI_WP_REG(0x24) -#define HDMI_WP_IRQSTATUS			HDMI_WP_REG(0x28) -#define HDMI_WP_PWR_CTRL			HDMI_WP_REG(0x40) -#define HDMI_WP_IRQENABLE_SET			HDMI_WP_REG(0x2C) -#define HDMI_WP_VIDEO_CFG			HDMI_WP_REG(0x50) -#define HDMI_WP_VIDEO_SIZE			HDMI_WP_REG(0x60) -#define HDMI_WP_VIDEO_TIMING_H			HDMI_WP_REG(0x68) -#define HDMI_WP_VIDEO_TIMING_V			HDMI_WP_REG(0x6C) -#define HDMI_WP_WP_CLK				HDMI_WP_REG(0x70) -#define HDMI_WP_AUDIO_CFG			HDMI_WP_REG(0x80) -#define HDMI_WP_AUDIO_CFG2			HDMI_WP_REG(0x84) -#define HDMI_WP_AUDIO_CTRL			HDMI_WP_REG(0x88) -#define HDMI_WP_AUDIO_DATA			HDMI_WP_REG(0x8C) +#define HDMI_WP_REVISION			0x0 +#define HDMI_WP_SYSCONFIG			0x10 +#define HDMI_WP_IRQSTATUS_RAW			0x24 +#define HDMI_WP_IRQSTATUS			0x28 +#define HDMI_WP_PWR_CTRL			0x40 +#define HDMI_WP_IRQENABLE_SET			0x2C +#define HDMI_WP_VIDEO_CFG			0x50 +#define HDMI_WP_VIDEO_SIZE			0x60 +#define HDMI_WP_VIDEO_TIMING_H			0x68 +#define HDMI_WP_VIDEO_TIMING_V			0x6C +#define HDMI_WP_WP_CLK				0x70 +#define HDMI_WP_AUDIO_CFG			0x80 +#define HDMI_WP_AUDIO_CFG2			0x84 +#define HDMI_WP_AUDIO_CTRL			0x88 +#define HDMI_WP_AUDIO_DATA			0x8C  /* HDMI IP Core System */ -#define HDMI_CORE_SYS_REG(idx)			HDMI_REG(HDMI_CORE_SYS + idx) -#define HDMI_CORE_SYS_VND_IDL			HDMI_CORE_SYS_REG(0x0) -#define HDMI_CORE_SYS_DEV_IDL			HDMI_CORE_SYS_REG(0x8) -#define HDMI_CORE_SYS_DEV_IDH			HDMI_CORE_SYS_REG(0xC) -#define HDMI_CORE_SYS_DEV_REV			HDMI_CORE_SYS_REG(0x10) -#define HDMI_CORE_SYS_SRST			HDMI_CORE_SYS_REG(0x14) -#define HDMI_CORE_CTRL1			HDMI_CORE_SYS_REG(0x20) -#define HDMI_CORE_SYS_SYS_STAT			HDMI_CORE_SYS_REG(0x24) -#define HDMI_CORE_SYS_VID_ACEN			HDMI_CORE_SYS_REG(0x124) -#define HDMI_CORE_SYS_VID_MODE			HDMI_CORE_SYS_REG(0x128) -#define HDMI_CORE_SYS_INTR_STATE		HDMI_CORE_SYS_REG(0x1C0) -#define HDMI_CORE_SYS_INTR1			HDMI_CORE_SYS_REG(0x1C4) -#define HDMI_CORE_SYS_INTR2			HDMI_CORE_SYS_REG(0x1C8) -#define HDMI_CORE_SYS_INTR3			HDMI_CORE_SYS_REG(0x1CC) -#define HDMI_CORE_SYS_INTR4			HDMI_CORE_SYS_REG(0x1D0) -#define HDMI_CORE_SYS_UMASK1			HDMI_CORE_SYS_REG(0x1D4) -#define HDMI_CORE_SYS_TMDS_CTRL		HDMI_CORE_SYS_REG(0x208) -#define HDMI_CORE_SYS_DE_DLY			HDMI_CORE_SYS_REG(0xC8) -#define HDMI_CORE_SYS_DE_CTRL			HDMI_CORE_SYS_REG(0xCC) -#define HDMI_CORE_SYS_DE_TOP			HDMI_CORE_SYS_REG(0xD0) -#define HDMI_CORE_SYS_DE_CNTL			HDMI_CORE_SYS_REG(0xD8) -#define HDMI_CORE_SYS_DE_CNTH			HDMI_CORE_SYS_REG(0xDC) -#define HDMI_CORE_SYS_DE_LINL			HDMI_CORE_SYS_REG(0xE0) -#define HDMI_CORE_SYS_DE_LINH_1		HDMI_CORE_SYS_REG(0xE4) +#define HDMI_CORE_SYS_VND_IDL			0x0 +#define HDMI_CORE_SYS_DEV_IDL			0x8 +#define HDMI_CORE_SYS_DEV_IDH			0xC +#define HDMI_CORE_SYS_DEV_REV			0x10 +#define HDMI_CORE_SYS_SRST			0x14 +#define HDMI_CORE_CTRL1				0x20 +#define HDMI_CORE_SYS_SYS_STAT			0x24 +#define HDMI_CORE_SYS_VID_ACEN			0x124 +#define HDMI_CORE_SYS_VID_MODE			0x128 +#define HDMI_CORE_SYS_INTR_STATE		0x1C0 +#define HDMI_CORE_SYS_INTR1			0x1C4 +#define HDMI_CORE_SYS_INTR2			0x1C8 +#define HDMI_CORE_SYS_INTR3			0x1CC +#define HDMI_CORE_SYS_INTR4			0x1D0 +#define HDMI_CORE_SYS_UMASK1			0x1D4 +#define HDMI_CORE_SYS_TMDS_CTRL			0x208 +#define HDMI_CORE_SYS_DE_DLY			0xC8 +#define HDMI_CORE_SYS_DE_CTRL			0xCC +#define HDMI_CORE_SYS_DE_TOP			0xD0 +#define HDMI_CORE_SYS_DE_CNTL			0xD8 +#define HDMI_CORE_SYS_DE_CNTH			0xDC +#define HDMI_CORE_SYS_DE_LINL			0xE0 +#define HDMI_CORE_SYS_DE_LINH_1			0xE4  #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC	0x1  #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC	0x1  #define HDMI_CORE_CTRL1_BSEL_24BITBUS		0x1  #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE	0x1  /* HDMI DDC E-DID */ -#define HDMI_CORE_DDC_CMD			HDMI_CORE_SYS_REG(0x3CC) -#define HDMI_CORE_DDC_STATUS			HDMI_CORE_SYS_REG(0x3C8) -#define HDMI_CORE_DDC_ADDR			HDMI_CORE_SYS_REG(0x3B4) -#define HDMI_CORE_DDC_OFFSET			HDMI_CORE_SYS_REG(0x3BC) -#define HDMI_CORE_DDC_COUNT1			HDMI_CORE_SYS_REG(0x3C0) -#define HDMI_CORE_DDC_COUNT2			HDMI_CORE_SYS_REG(0x3C4) -#define HDMI_CORE_DDC_DATA			HDMI_CORE_SYS_REG(0x3D0) -#define HDMI_CORE_DDC_SEGM			HDMI_CORE_SYS_REG(0x3B8) +#define HDMI_CORE_DDC_CMD			0x3CC +#define HDMI_CORE_DDC_STATUS			0x3C8 +#define HDMI_CORE_DDC_ADDR			0x3B4 +#define HDMI_CORE_DDC_OFFSET			0x3BC +#define HDMI_CORE_DDC_COUNT1			0x3C0 +#define HDMI_CORE_DDC_COUNT2			0x3C4 +#define HDMI_CORE_DDC_DATA			0x3D0 +#define HDMI_CORE_DDC_SEGM			0x3B8  /* HDMI IP Core Audio Video */ -#define HDMI_CORE_AV_REG(idx)			HDMI_REG(HDMI_CORE_AV + idx) -#define HDMI_CORE_AV_HDMI_CTRL			HDMI_CORE_AV_REG(0xBC) -#define HDMI_CORE_AV_DPD			HDMI_CORE_AV_REG(0xF4) -#define HDMI_CORE_AV_PB_CTRL1			HDMI_CORE_AV_REG(0xF8) -#define HDMI_CORE_AV_PB_CTRL2			HDMI_CORE_AV_REG(0xFC) -#define HDMI_CORE_AV_AVI_TYPE			HDMI_CORE_AV_REG(0x100) -#define HDMI_CORE_AV_AVI_VERS			HDMI_CORE_AV_REG(0x104) -#define HDMI_CORE_AV_AVI_LEN			HDMI_CORE_AV_REG(0x108) -#define HDMI_CORE_AV_AVI_CHSUM			HDMI_CORE_AV_REG(0x10C) -#define HDMI_CORE_AV_AVI_DBYTE(n)		HDMI_CORE_AV_REG(n * 4 + 0x110) -#define HDMI_CORE_AV_AVI_DBYTE_NELEMS		HDMI_CORE_AV_REG(15) -#define HDMI_CORE_AV_SPD_DBYTE			HDMI_CORE_AV_REG(0x190) -#define HDMI_CORE_AV_SPD_DBYTE_NELEMS		HDMI_CORE_AV_REG(27) -#define HDMI_CORE_AV_AUD_DBYTE(n)		HDMI_CORE_AV_REG(n * 4 + 0x210) -#define HDMI_CORE_AV_AUD_DBYTE_NELEMS		HDMI_CORE_AV_REG(10) -#define HDMI_CORE_AV_MPEG_DBYTE		HDMI_CORE_AV_REG(0x290) -#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS		HDMI_CORE_AV_REG(27) -#define HDMI_CORE_AV_GEN_DBYTE			HDMI_CORE_AV_REG(0x300) -#define HDMI_CORE_AV_GEN_DBYTE_NELEMS		HDMI_CORE_AV_REG(31) -#define HDMI_CORE_AV_GEN2_DBYTE		HDMI_CORE_AV_REG(0x380) -#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS		HDMI_CORE_AV_REG(31) -#define HDMI_CORE_AV_ACR_CTRL			HDMI_CORE_AV_REG(0x4) -#define HDMI_CORE_AV_FREQ_SVAL			HDMI_CORE_AV_REG(0x8) -#define HDMI_CORE_AV_N_SVAL1			HDMI_CORE_AV_REG(0xC) -#define HDMI_CORE_AV_N_SVAL2			HDMI_CORE_AV_REG(0x10) -#define HDMI_CORE_AV_N_SVAL3			HDMI_CORE_AV_REG(0x14) -#define HDMI_CORE_AV_CTS_SVAL1			HDMI_CORE_AV_REG(0x18) -#define HDMI_CORE_AV_CTS_SVAL2			HDMI_CORE_AV_REG(0x1C) -#define HDMI_CORE_AV_CTS_SVAL3			HDMI_CORE_AV_REG(0x20) -#define HDMI_CORE_AV_CTS_HVAL1			HDMI_CORE_AV_REG(0x24) -#define HDMI_CORE_AV_CTS_HVAL2			HDMI_CORE_AV_REG(0x28) -#define HDMI_CORE_AV_CTS_HVAL3			HDMI_CORE_AV_REG(0x2C) -#define HDMI_CORE_AV_AUD_MODE			HDMI_CORE_AV_REG(0x50) -#define HDMI_CORE_AV_SPDIF_CTRL		HDMI_CORE_AV_REG(0x54) -#define HDMI_CORE_AV_HW_SPDIF_FS		HDMI_CORE_AV_REG(0x60) -#define HDMI_CORE_AV_SWAP_I2S			HDMI_CORE_AV_REG(0x64) -#define HDMI_CORE_AV_SPDIF_ERTH		HDMI_CORE_AV_REG(0x6C) -#define HDMI_CORE_AV_I2S_IN_MAP		HDMI_CORE_AV_REG(0x70) -#define HDMI_CORE_AV_I2S_IN_CTRL		HDMI_CORE_AV_REG(0x74) -#define HDMI_CORE_AV_I2S_CHST0			HDMI_CORE_AV_REG(0x78) -#define HDMI_CORE_AV_I2S_CHST1			HDMI_CORE_AV_REG(0x7C) -#define HDMI_CORE_AV_I2S_CHST2			HDMI_CORE_AV_REG(0x80) -#define HDMI_CORE_AV_I2S_CHST4			HDMI_CORE_AV_REG(0x84) -#define HDMI_CORE_AV_I2S_CHST5			HDMI_CORE_AV_REG(0x88) -#define HDMI_CORE_AV_ASRC			HDMI_CORE_AV_REG(0x8C) -#define HDMI_CORE_AV_I2S_IN_LEN		HDMI_CORE_AV_REG(0x90) -#define HDMI_CORE_AV_HDMI_CTRL			HDMI_CORE_AV_REG(0xBC) -#define HDMI_CORE_AV_AUDO_TXSTAT		HDMI_CORE_AV_REG(0xC0) -#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1		HDMI_CORE_AV_REG(0xCC) -#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2		HDMI_CORE_AV_REG(0xD0) -#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3		HDMI_CORE_AV_REG(0xD4) -#define HDMI_CORE_AV_TEST_TXCTRL		HDMI_CORE_AV_REG(0xF0) -#define HDMI_CORE_AV_DPD			HDMI_CORE_AV_REG(0xF4) -#define HDMI_CORE_AV_PB_CTRL1			HDMI_CORE_AV_REG(0xF8) -#define HDMI_CORE_AV_PB_CTRL2			HDMI_CORE_AV_REG(0xFC) -#define HDMI_CORE_AV_AVI_TYPE			HDMI_CORE_AV_REG(0x100) -#define HDMI_CORE_AV_AVI_VERS			HDMI_CORE_AV_REG(0x104) -#define HDMI_CORE_AV_AVI_LEN			HDMI_CORE_AV_REG(0x108) -#define HDMI_CORE_AV_AVI_CHSUM			HDMI_CORE_AV_REG(0x10C) -#define HDMI_CORE_AV_SPD_TYPE			HDMI_CORE_AV_REG(0x180) -#define HDMI_CORE_AV_SPD_VERS			HDMI_CORE_AV_REG(0x184) -#define HDMI_CORE_AV_SPD_LEN			HDMI_CORE_AV_REG(0x188) -#define HDMI_CORE_AV_SPD_CHSUM			HDMI_CORE_AV_REG(0x18C) -#define HDMI_CORE_AV_AUDIO_TYPE		HDMI_CORE_AV_REG(0x200) -#define HDMI_CORE_AV_AUDIO_VERS		HDMI_CORE_AV_REG(0x204) -#define HDMI_CORE_AV_AUDIO_LEN			HDMI_CORE_AV_REG(0x208) -#define HDMI_CORE_AV_AUDIO_CHSUM		HDMI_CORE_AV_REG(0x20C) -#define HDMI_CORE_AV_MPEG_TYPE			HDMI_CORE_AV_REG(0x280) -#define HDMI_CORE_AV_MPEG_VERS			HDMI_CORE_AV_REG(0x284) -#define HDMI_CORE_AV_MPEG_LEN			HDMI_CORE_AV_REG(0x288) -#define HDMI_CORE_AV_MPEG_CHSUM		HDMI_CORE_AV_REG(0x28C) -#define HDMI_CORE_AV_CP_BYTE1			HDMI_CORE_AV_REG(0x37C) -#define HDMI_CORE_AV_CEC_ADDR_ID		HDMI_CORE_AV_REG(0x3FC) +#define HDMI_CORE_AV_HDMI_CTRL			0xBC +#define HDMI_CORE_AV_DPD			0xF4 +#define HDMI_CORE_AV_PB_CTRL1			0xF8 +#define HDMI_CORE_AV_PB_CTRL2			0xFC +#define HDMI_CORE_AV_AVI_TYPE			0x100 +#define HDMI_CORE_AV_AVI_VERS			0x104 +#define HDMI_CORE_AV_AVI_LEN			0x108 +#define HDMI_CORE_AV_AVI_CHSUM			0x10C +#define HDMI_CORE_AV_AVI_DBYTE(n)		(n * 4 + 0x110) +#define HDMI_CORE_AV_AVI_DBYTE_NELEMS		15 +#define HDMI_CORE_AV_SPD_DBYTE(n)		(n * 4 + 0x190) +#define HDMI_CORE_AV_SPD_DBYTE_NELEMS		27 +#define HDMI_CORE_AV_AUD_DBYTE(n)		(n * 4 + 0x210) +#define HDMI_CORE_AV_AUD_DBYTE_NELEMS		10 +#define HDMI_CORE_AV_MPEG_DBYTE(n)		(n * 4 + 0x290) +#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS		27 +#define HDMI_CORE_AV_GEN_DBYTE(n)		(n * 4 + 0x300) +#define HDMI_CORE_AV_GEN_DBYTE_NELEMS		31 +#define HDMI_CORE_AV_GEN2_DBYTE(n)		(n * 4 + 0x380) +#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS		31 +#define HDMI_CORE_AV_ACR_CTRL			0x4 +#define HDMI_CORE_AV_FREQ_SVAL			0x8 +#define HDMI_CORE_AV_N_SVAL1			0xC +#define HDMI_CORE_AV_N_SVAL2			0x10 +#define HDMI_CORE_AV_N_SVAL3			0x14 +#define HDMI_CORE_AV_CTS_SVAL1			0x18 +#define HDMI_CORE_AV_CTS_SVAL2			0x1C +#define HDMI_CORE_AV_CTS_SVAL3			0x20 +#define HDMI_CORE_AV_CTS_HVAL1			0x24 +#define HDMI_CORE_AV_CTS_HVAL2			0x28 +#define HDMI_CORE_AV_CTS_HVAL3			0x2C +#define HDMI_CORE_AV_AUD_MODE			0x50 +#define HDMI_CORE_AV_SPDIF_CTRL			0x54 +#define HDMI_CORE_AV_HW_SPDIF_FS		0x60 +#define HDMI_CORE_AV_SWAP_I2S			0x64 +#define HDMI_CORE_AV_SPDIF_ERTH			0x6C +#define HDMI_CORE_AV_I2S_IN_MAP			0x70 +#define HDMI_CORE_AV_I2S_IN_CTRL		0x74 +#define HDMI_CORE_AV_I2S_CHST0			0x78 +#define HDMI_CORE_AV_I2S_CHST1			0x7C +#define HDMI_CORE_AV_I2S_CHST2			0x80 +#define HDMI_CORE_AV_I2S_CHST4			0x84 +#define HDMI_CORE_AV_I2S_CHST5			0x88 +#define HDMI_CORE_AV_ASRC			0x8C +#define HDMI_CORE_AV_I2S_IN_LEN			0x90 +#define HDMI_CORE_AV_HDMI_CTRL			0xBC +#define HDMI_CORE_AV_AUDO_TXSTAT		0xC0 +#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1		0xCC +#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2		0xD0 +#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3		0xD4 +#define HDMI_CORE_AV_TEST_TXCTRL		0xF0 +#define HDMI_CORE_AV_DPD			0xF4 +#define HDMI_CORE_AV_PB_CTRL1			0xF8 +#define HDMI_CORE_AV_PB_CTRL2			0xFC +#define HDMI_CORE_AV_AVI_TYPE			0x100 +#define HDMI_CORE_AV_AVI_VERS			0x104 +#define HDMI_CORE_AV_AVI_LEN			0x108 +#define HDMI_CORE_AV_AVI_CHSUM			0x10C +#define HDMI_CORE_AV_SPD_TYPE			0x180 +#define HDMI_CORE_AV_SPD_VERS			0x184 +#define HDMI_CORE_AV_SPD_LEN			0x188 +#define HDMI_CORE_AV_SPD_CHSUM			0x18C +#define HDMI_CORE_AV_AUDIO_TYPE			0x200 +#define HDMI_CORE_AV_AUDIO_VERS			0x204 +#define HDMI_CORE_AV_AUDIO_LEN			0x208 +#define HDMI_CORE_AV_AUDIO_CHSUM		0x20C +#define HDMI_CORE_AV_MPEG_TYPE			0x280 +#define HDMI_CORE_AV_MPEG_VERS			0x284 +#define HDMI_CORE_AV_MPEG_LEN			0x288 +#define HDMI_CORE_AV_MPEG_CHSUM			0x28C +#define HDMI_CORE_AV_CP_BYTE1			0x37C +#define HDMI_CORE_AV_CEC_ADDR_ID		0x3FC  #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE		0x4  #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE		0x4  #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE		0x4  #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE		0x4  /* PLL */ -#define HDMI_PLL_REG(idx)			HDMI_REG(HDMI_PLLCTRL + idx) -#define PLLCTRL_PLL_CONTROL			HDMI_PLL_REG(0x0) -#define PLLCTRL_PLL_STATUS			HDMI_PLL_REG(0x4) -#define PLLCTRL_PLL_GO				HDMI_PLL_REG(0x8) -#define PLLCTRL_CFG1				HDMI_PLL_REG(0xC) -#define PLLCTRL_CFG2				HDMI_PLL_REG(0x10) -#define PLLCTRL_CFG3				HDMI_PLL_REG(0x14) -#define PLLCTRL_CFG4				HDMI_PLL_REG(0x20) +#define PLLCTRL_PLL_CONTROL			0x0 +#define PLLCTRL_PLL_STATUS			0x4 +#define PLLCTRL_PLL_GO				0x8 +#define PLLCTRL_CFG1				0xC +#define PLLCTRL_CFG2				0x10 +#define PLLCTRL_CFG3				0x14 +#define PLLCTRL_CFG4				0x20  /* HDMI PHY */ -#define HDMI_PHY_REG(idx)			HDMI_REG(HDMI_PHY + idx) - -#define HDMI_TXPHY_TX_CTRL			HDMI_PHY_REG(0x0) -#define HDMI_TXPHY_DIGITAL_CTRL		HDMI_PHY_REG(0x4) -#define HDMI_TXPHY_POWER_CTRL			HDMI_PHY_REG(0x8) -#define HDMI_TXPHY_PAD_CFG_CTRL		HDMI_PHY_REG(0xC) -/* HDMI EDID Length  */ -#define HDMI_EDID_MAX_LENGTH			256 -#define EDID_TIMING_DESCRIPTOR_SIZE		0x12 -#define EDID_DESCRIPTOR_BLOCK0_ADDRESS		0x36 -#define EDID_DESCRIPTOR_BLOCK1_ADDRESS		0x80 -#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR	4 -#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR	4 +#define HDMI_TXPHY_TX_CTRL			0x0 +#define HDMI_TXPHY_DIGITAL_CTRL			0x4 +#define HDMI_TXPHY_POWER_CTRL			0x8 +#define HDMI_TXPHY_PAD_CFG_CTRL			0xC -#define OMAP_HDMI_TIMINGS_NB			34 - -#define REG_FLD_MOD(idx, val, start, end) \ -	hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end)) -#define REG_GET(idx, start, end) \ -	FLD_GET(hdmi_read_reg(idx), start, end) - -/* HDMI timing structure */ -struct hdmi_timings { -	struct omap_video_timings timings; -	int vsync_pol; -	int hsync_pol; -}; +#define REG_FLD_MOD(base, idx, val, start, end) \ +	hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\ +							val, start, end)) +#define REG_GET(base, idx, start, end) \ +	FLD_GET(hdmi_read_reg(base, idx), start, end)  enum hdmi_phy_pwr {  	HDMI_PHYPWRCMD_OFF = 0, @@ -221,20 +196,6 @@ enum hdmi_phy_pwr {  	HDMI_PHYPWRCMD_TXON = 2  }; -enum hdmi_pll_pwr { -	HDMI_PLLPWRCMD_ALLOFF = 0, -	HDMI_PLLPWRCMD_PLLONLY = 1, -	HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, -	HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 -}; - -enum hdmi_clk_refsel { -	HDMI_REFSEL_PCLK = 0, -	HDMI_REFSEL_REF1 = 1, -	HDMI_REFSEL_REF2 = 2, -	HDMI_REFSEL_SYSCLK = 3 -}; -  enum hdmi_core_inputbus_width {  	HDMI_INPUT_8BIT = 0,  	HDMI_INPUT_10BIT = 1, @@ -263,11 +224,6 @@ enum hdmi_core_packet_mode {  	HDMI_PACKETMODE48BITPERPIXEL = 7  }; -enum hdmi_core_hdmi_dvi { -	HDMI_DVI = 0, -	HDMI_HDMI = 1 -}; -  enum hdmi_core_tclkselclkmult {  	HDMI_FPLL05IDCK = 0,  	HDMI_FPLL10IDCK = 1, @@ -495,40 +451,40 @@ struct hdmi_core_video_config {   * details about infoframe databytes   */  struct hdmi_core_infoframe_avi { +	/* Y0, Y1 rgb,yCbCr */  	u8	db1_format; -		/* Y0, Y1 rgb,yCbCr */ +	/* A0  Active information Present */  	u8	db1_active_info; -		/* A0  Active information Present */ +	/* B0, B1 Bar info data valid */  	u8	db1_bar_info_dv; -		/* B0, B1 Bar info data valid */ +	/* S0, S1 scan information */  	u8	db1_scan_info; -		/* S0, S1 scan information */ +	/* C0, C1 colorimetry */  	u8	db2_colorimetry; -		/* C0, C1 colorimetry */ +	/* M0, M1 Aspect ratio (4:3, 16:9) */  	u8	db2_aspect_ratio; -		/* M0, M1 Aspect ratio (4:3, 16:9) */ +	/* R0...R3 Active format aspect ratio */  	u8	db2_active_fmt_ar; -		/* R0...R3 Active format aspect ratio */ +	/* ITC IT content. */  	u8	db3_itc; -		/* ITC IT content. */ +	/* EC0, EC1, EC2 Extended colorimetry */  	u8	db3_ec; -		/* EC0, EC1, EC2 Extended colorimetry */ +	/* Q1, Q0 Quantization range */  	u8	db3_q_range; -		/* Q1, Q0 Quantization range */ +	/* SC1, SC0 Non-uniform picture scaling */  	u8	db3_nup_scaling; -		/* SC1, SC0 Non-uniform picture scaling */ +	/* VIC0..6 Video format identification */  	u8	db4_videocode; -		/* VIC0..6 Video format identification */ +	/* PR0..PR3 Pixel repetition factor */  	u8	db5_pixel_repeat; -		/* PR0..PR3 Pixel repetition factor */ +	/* Line number end of top bar */  	u16	db6_7_line_eoftop; -		/* Line number end of top bar */ +	/* Line number start of bottom bar */  	u16	db8_9_line_sofbottom; -		/* Line number start of bottom bar */ +	/* Pixel number end of left bar */  	u16	db10_11_pixel_eofleft; -		/* Pixel number end of left bar */ +	/* Pixel number start of right bar */  	u16	db12_13_pixel_sofright; -		/* Pixel number start of right bar */  };  /*   * Refer to section 8.2 in HDMI 1.3 specification for @@ -568,17 +524,6 @@ struct hdmi_video_interface {  	int	tm;	/* Timing mode */  }; -struct hdmi_cm { -	int	code; -	int	mode; -}; - -struct hdmi_config { -	struct hdmi_timings timings; -	u16	interlace; -	struct hdmi_cm cm; -}; -  struct hdmi_audio_format {  	enum hdmi_stereo_channels		stereo_channels;  	u8					active_chnnls_msk; @@ -628,4 +573,21 @@ struct hdmi_core_audio_config {  	bool					en_parallel_aud_input;  	bool					en_spdif;  }; + +#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ +	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) +int hdmi_audio_trigger(struct hdmi_ip_data *ip_data, +				struct snd_pcm_substream *substream, int cmd, +				struct snd_soc_dai *dai); +int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, +				u32 sample_freq, u32 *n, u32 *cts); +void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, +		struct hdmi_core_infoframe_audio *info_aud); +void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, +					struct hdmi_core_audio_config *cfg); +void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, +					struct hdmi_audio_dma *aud_dma); +void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data, +					struct hdmi_audio_format *aud_fmt); +#endif  #endif diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 173c66430da..7533458ba4d 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -295,7 +295,6 @@ static struct {  	u32 wss_data;  	struct regulator *vdda_dac_reg; -	struct clk	*tv_clk;  	struct clk	*tv_dac_clk;  } venc; @@ -464,9 +463,11 @@ static void venc_power_off(struct omap_dss_device *dssdev)  	regulator_disable(venc.vdda_dac_reg);  } - - - +unsigned long venc_get_pixel_clock(void) +{ +	/* VENC Pixel Clock in Mhz */ +	return 13500000; +}  /* driver */  static int venc_panel_probe(struct omap_dss_device *dssdev) @@ -732,22 +733,10 @@ static int venc_get_clocks(struct platform_device *pdev)  {  	struct clk *clk; -	clk = clk_get(&pdev->dev, "fck"); -	if (IS_ERR(clk)) { -		DSSERR("can't get fck\n"); -		return PTR_ERR(clk); -	} - -	venc.tv_clk = clk; -  	if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { -		if (cpu_is_omap34xx() || cpu_is_omap3630()) -			clk = clk_get(&pdev->dev, "dss_96m_fck"); -		else -			clk = clk_get(&pdev->dev, "tv_dac_clk"); +		clk = clk_get(&pdev->dev, "tv_dac_clk");  		if (IS_ERR(clk)) {  			DSSERR("can't get tv_dac_clk\n"); -			clk_put(venc.tv_clk);  			return PTR_ERR(clk);  		}  	} else { @@ -761,8 +750,6 @@ static int venc_get_clocks(struct platform_device *pdev)  static void venc_put_clocks(void)  { -	if (venc.tv_clk) -		clk_put(venc.tv_clk);  	if (venc.tv_dac_clk)  		clk_put(venc.tv_dac_clk);  } @@ -838,7 +825,6 @@ static int venc_runtime_suspend(struct device *dev)  {  	if (venc.tv_dac_clk)  		clk_disable(venc.tv_dac_clk); -	clk_disable(venc.tv_clk);  	dispc_runtime_put();  	dss_runtime_put(); @@ -858,7 +844,6 @@ static int venc_runtime_resume(struct device *dev)  	if (r < 0)  		goto err_get_dispc; -	clk_enable(venc.tv_clk);  	if (venc.tv_dac_clk)  		clk_enable(venc.tv_dac_clk); diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig index aa33386c81f..83d3fe7ec9a 100644 --- a/drivers/video/omap2/omapfb/Kconfig +++ b/drivers/video/omap2/omapfb/Kconfig @@ -1,5 +1,5 @@  menuconfig FB_OMAP2 -        tristate "OMAP2+ frame buffer support (EXPERIMENTAL)" +        tristate "OMAP2+ frame buffer support"          depends on FB && OMAP2_DSS  	select OMAP2_VRAM diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 602b71a92d3..70aa47de714 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -808,19 +808,15 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,  static void omapfb_calc_addr(const struct omapfb_info *ofbi,  			     const struct fb_var_screeninfo *var,  			     const struct fb_fix_screeninfo *fix, -			     int rotation, u32 *paddr, void __iomem **vaddr) +			     int rotation, u32 *paddr)  {  	u32 data_start_p; -	void __iomem *data_start_v;  	int offset; -	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { +	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)  		data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); -		data_start_v = NULL; -	} else { +	else  		data_start_p = omapfb_get_region_paddr(ofbi); -		data_start_v = omapfb_get_region_vaddr(ofbi); -	}  	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)  		offset = calc_rotation_offset_vrfb(var, fix, rotation); @@ -828,16 +824,14 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,  		offset = calc_rotation_offset_dma(var, fix, rotation);  	data_start_p += offset; -	data_start_v += offset;  	if (offset)  		DBG("offset %d, %d = %d\n",  		    var->xoffset, var->yoffset, offset); -	DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v); +	DBG("paddr %x\n", data_start_p);  	*paddr = data_start_p; -	*vaddr = data_start_v;  }  /* setup overlay according to the fb */ @@ -850,7 +844,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,  	struct fb_fix_screeninfo *fix = &fbi->fix;  	enum omap_color_mode mode = 0;  	u32 data_start_p = 0; -	void __iomem *data_start_v = NULL;  	struct omap_overlay_info info;  	int xres, yres;  	int screen_width; @@ -880,8 +873,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,  	}  	if (ofbi->region->size) -		omapfb_calc_addr(ofbi, var, fix, rotation, -				 &data_start_p, &data_start_v); +		omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);  	r = fb_mode_to_dss_mode(var, &mode);  	if (r) { @@ -910,7 +902,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,  		mirror = ofbi->mirror;  	info.paddr = data_start_p; -	info.vaddr = data_start_v;  	info.screen_width = screen_width;  	info.width = xres;  	info.height = yres; @@ -2276,6 +2267,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)  	return r;  } +static void fb_videomode_to_omap_timings(struct fb_videomode *m, +		struct omap_video_timings *t) +{ +	t->x_res = m->xres; +	t->y_res = m->yres; +	t->pixel_clock = PICOS2KHZ(m->pixclock); +	t->hsw = m->hsync_len; +	t->hfp = m->right_margin; +	t->hbp = m->left_margin; +	t->vsw = m->vsync_len; +	t->vfp = m->lower_margin; +	t->vbp = m->upper_margin; +} + +static int omapfb_find_best_mode(struct omap_dss_device *display, +		struct omap_video_timings *timings) +{ +	struct fb_monspecs *specs; +	u8 *edid; +	int r, i, best_xres, best_idx, len; + +	if (!display->driver->read_edid) +		return -ENODEV; + +	len = 0x80 * 2; +	edid = kmalloc(len, GFP_KERNEL); + +	r = display->driver->read_edid(display, edid, len); +	if (r < 0) +		goto err1; + +	specs = kzalloc(sizeof(*specs), GFP_KERNEL); + +	fb_edid_to_monspecs(edid, specs); + +	if (edid[126] > 0) +		fb_edid_add_monspecs(edid + 0x80, specs); + +	best_xres = 0; +	best_idx = -1; + +	for (i = 0; i < specs->modedb_len; ++i) { +		struct fb_videomode *m; +		struct omap_video_timings t; + +		m = &specs->modedb[i]; + +		if (m->pixclock == 0) +			continue; + +		/* skip repeated pixel modes */ +		if (m->xres == 2880 || m->xres == 1440) +			continue; + +		fb_videomode_to_omap_timings(m, &t); + +		r = display->driver->check_timings(display, &t); +		if (r == 0 && best_xres < m->xres) { +			best_xres = m->xres; +			best_idx = i; +		} +	} + +	if (best_xres == 0) { +		r = -ENOENT; +		goto err2; +	} + +	fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings); + +	r = 0; + +err2: +	fb_destroy_modedb(specs->modedb); +	kfree(specs); +err1: +	kfree(edid); + +	return r; +} +  static int omapfb_init_display(struct omapfb2_device *fbdev,  		struct omap_dss_device *dssdev)  { @@ -2373,8 +2445,10 @@ static int omapfb_probe(struct platform_device *pdev)  		omap_dss_get_device(dssdev);  		if (!dssdev->driver) { -			dev_err(&pdev->dev, "no driver for display\n"); -			r = -ENODEV; +			dev_warn(&pdev->dev, "no driver for display: %s\n", +				dssdev->name); +			omap_dss_put_device(dssdev); +			continue;  		}  		d = &fbdev->displays[fbdev->num_displays++]; @@ -2402,9 +2476,27 @@ static int omapfb_probe(struct platform_device *pdev)  	for (i = 0; i < fbdev->num_managers; i++)  		fbdev->managers[i] = omap_dss_get_overlay_manager(i); +	/* gfx overlay should be the default one. find a display +	 * connected to that, and use it as default display */ +	ovl = omap_dss_get_overlay(0); +	if (ovl->manager && ovl->manager->device) { +		def_display = ovl->manager->device; +	} else { +		dev_warn(&pdev->dev, "cannot find default display\n"); +		def_display = NULL; +	} +  	if (def_mode && strlen(def_mode) > 0) {  		if (omapfb_parse_def_modes(fbdev))  			dev_warn(&pdev->dev, "cannot parse default modes\n"); +	} else if (def_display && def_display->driver->set_timings && +			def_display->driver->check_timings) { +		struct omap_video_timings t; + +		r = omapfb_find_best_mode(def_display, &t); + +		if (r == 0) +			def_display->driver->set_timings(def_display, &t);  	}  	r = omapfb_create_framebuffers(fbdev); @@ -2421,16 +2513,6 @@ static int omapfb_probe(struct platform_device *pdev)  	DBG("mgr->apply'ed\n"); -	/* gfx overlay should be the default one. find a display -	 * connected to that, and use it as default display */ -	ovl = omap_dss_get_overlay(0); -	if (ovl->manager && ovl->manager->device) { -		def_display = ovl->manager->device; -	} else { -		dev_warn(&pdev->dev, "cannot find default display\n"); -		def_display = NULL; -	} -  	if (def_display) {  		r = omapfb_init_display(fbdev, def_display);  		if (r) { diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 153bf1aceeb..1694d5148f3 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c @@ -104,16 +104,14 @@ static ssize_t store_mirror(struct device *dev,  {  	struct fb_info *fbi = dev_get_drvdata(dev);  	struct omapfb_info *ofbi = FB2OFB(fbi); -	int mirror; +	bool mirror;  	int r;  	struct fb_var_screeninfo new_var; -	r = kstrtoint(buf, 0, &mirror); +	r = strtobool(buf, &mirror);  	if (r)  		return r; -	mirror = !!mirror; -  	if (!lock_fb_info(fbi))  		return -ENODEV; diff --git a/include/video/omap-panel-dvi.h b/include/video/omap-panel-dvi.h new file mode 100644 index 00000000000..87ad567b422 --- /dev/null +++ b/include/video/omap-panel-dvi.h @@ -0,0 +1,37 @@ +/* + * Header for DVI output driver + * + * Copyright (C) 2011 Texas Instruments Inc + * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef __OMAP_PANEL_DVI_H +#define __OMAP_PANEL_DVI_H + +struct omap_dss_device; + +/** + * struct panel_dvi_platform_data - panel driver configuration data + * @platform_enable: platform specific panel enable function + * @platform_disable: platform specific panel disable function + * @i2c_bus_num: i2c bus id for the panel + */ +struct panel_dvi_platform_data { +	int (*platform_enable)(struct omap_dss_device *dssdev); +	void (*platform_disable)(struct omap_dss_device *dssdev); +	u16 i2c_bus_num; +}; + +#endif /* __OMAP_PANEL_DVI_H */ diff --git a/include/video/omap-panel-n8x0.h b/include/video/omap-panel-n8x0.h new file mode 100644 index 00000000000..50a1302e2cf --- /dev/null +++ b/include/video/omap-panel-n8x0.h @@ -0,0 +1,15 @@ +#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 index 921ae932722..7dc71f9c13e 100644 --- a/include/video/omap-panel-nokia-dsi.h +++ b/include/video/omap-panel-nokia-dsi.h @@ -10,9 +10,7 @@ struct omap_dss_device;   * @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) - * @max_backlight_level: maximum backlight level - * @set_backlight: pointer to backlight set function - * @get_backlight: pointer to backlight get function + * @use_dsi_backlight: true if panel uses DSI command to control backlight   */  struct nokia_dsi_panel_data {  	const char *name; @@ -25,9 +23,7 @@ struct nokia_dsi_panel_data {  	unsigned esd_interval;  	unsigned ulps_timeout; -	int max_backlight_level; -	int (*set_backlight)(struct omap_dss_device *dssdev, int level); -	int (*get_backlight)(struct omap_dss_device *dssdev); +	bool use_dsi_backlight;  };  #endif /* __OMAP_NOKIA_DSI_PANEL_H */ diff --git a/include/video/omap-panel-picodlp.h b/include/video/omap-panel-picodlp.h new file mode 100644 index 00000000000..1c342ef6f3a --- /dev/null +++ b/include/video/omap-panel-picodlp.h @@ -0,0 +1,23 @@ +/* + * panel data for picodlp panel + * + * Copyright (C) 2011 Texas Instruments + * + * Author: Mayuresh Janorkar <mayur@ti.com> + * + * 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/omapdss.h b/include/video/omapdss.h index 3b55ef22f8d..b66ebb2032c 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -41,8 +41,13 @@  #define DISPC_IRQ_WAKEUP		(1 << 16)  #define DISPC_IRQ_SYNC_LOST2		(1 << 17)  #define DISPC_IRQ_VSYNC2		(1 << 18) +#define DISPC_IRQ_VID3_END_WIN		(1 << 19) +#define DISPC_IRQ_VID3_FIFO_UNDERFLOW	(1 << 20)  #define DISPC_IRQ_ACBIAS_COUNT_STAT2	(1 << 21)  #define DISPC_IRQ_FRAMEDONE2		(1 << 22) +#define DISPC_IRQ_FRAMEDONEWB		(1 << 23) +#define DISPC_IRQ_FRAMEDONETV		(1 << 24) +#define DISPC_IRQ_WBBUFFEROVERFLOW	(1 << 25)  struct omap_dss_device;  struct omap_overlay_manager; @@ -60,7 +65,8 @@ enum omap_display_type {  enum omap_plane {  	OMAP_DSS_GFX	= 0,  	OMAP_DSS_VIDEO1	= 1, -	OMAP_DSS_VIDEO2	= 2 +	OMAP_DSS_VIDEO2	= 2, +	OMAP_DSS_VIDEO3	= 3,  };  enum omap_channel { @@ -129,6 +135,18 @@ enum omap_dss_venc_type {  	OMAP_DSS_VENC_TYPE_SVIDEO,  }; +enum omap_dss_dsi_pixel_format { +	OMAP_DSS_DSI_FMT_RGB888, +	OMAP_DSS_DSI_FMT_RGB666, +	OMAP_DSS_DSI_FMT_RGB666_PACKED, +	OMAP_DSS_DSI_FMT_RGB565, +}; + +enum omap_dss_dsi_mode { +	OMAP_DSS_DSI_CMD_MODE = 0, +	OMAP_DSS_DSI_VIDEO_MODE, +}; +  enum omap_display_caps {  	OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE	= 1 << 0,  	OMAP_DSS_DISPLAY_CAP_TEAR_ELIM		= 1 << 1, @@ -162,11 +180,13 @@ enum omap_dss_rotation_angle {  enum omap_overlay_caps {  	OMAP_DSS_OVL_CAP_SCALE = 1 << 0, -	OMAP_DSS_OVL_CAP_DISPC = 1 << 1, +	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1, +	OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2, +	OMAP_DSS_OVL_CAP_ZORDER = 1 << 3,  };  enum omap_overlay_manager_caps { -	OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0, +	OMAP_DSS_DUMMY_VALUE, /* add a dummy value to prevent compiler error */  };  enum omap_dss_clk_source { @@ -215,26 +235,67 @@ void rfbi_bus_lock(void);  void rfbi_bus_unlock(void);  /* DSI */ + +struct omap_dss_dsi_videomode_data { +	/* DSI video mode blanking data */ +	/* Unit: byte clock cycles */ +	u16 hsa; +	u16 hfp; +	u16 hbp; +	/* Unit: line clocks */ +	u16 vsa; +	u16 vfp; +	u16 vbp; + +	/* DSI blanking modes */ +	int blanking_mode; +	int hsa_blanking_mode; +	int hbp_blanking_mode; +	int hfp_blanking_mode; + +	/* Video port sync events */ +	int vp_de_pol; +	int vp_hsync_pol; +	int vp_vsync_pol; +	bool vp_vsync_end; +	bool vp_hsync_end; + +	bool ddr_clk_always_on; +	int window_sync; +}; +  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,  		int len); -int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, -		u8 dcs_cmd); +int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data, +		int len); +int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd); +int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel);  int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  		u8 param); +int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel, +		u8 param); +int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel, +		u8 param1, u8 param2);  int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,  		u8 *data, int len); +int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, +		u8 *data, int len);  int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  		u8 *buf, int buflen); -int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, -		u8 *data); -int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, -		u8 *data1, u8 *data2); +int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf, +		int buflen); +int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param, +		u8 *buf, int buflen); +int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel, +		u8 param1, u8 param2, u8 *buf, int buflen);  int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,  		u16 len);  int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);  int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel); +int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel); +void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel);  /* Board specific data */  struct omap_dss_board_info { @@ -242,7 +303,8 @@ struct omap_dss_board_info {  	int num_devices;  	struct omap_dss_device **devices;  	struct omap_dss_device *default_device; -	void (*dsi_mux_pads)(bool enable); +	int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask); +	void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);  };  #if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS) @@ -300,7 +362,6 @@ struct omap_overlay_info {  	bool enabled;  	u32 paddr; -	void __iomem *vaddr;  	u32 p_uv_addr;  /* for NV12 format */  	u16 screen_width;  	u16 width; @@ -316,6 +377,7 @@ struct omap_overlay_info {  	u16 out_height;	/* if 0, out_height == height */  	u8 global_alpha;  	u8 pre_mult_alpha; +	u8 zorder;  };  struct omap_overlay { @@ -324,7 +386,7 @@ struct omap_overlay {  	/* static fields */  	const char *name; -	int id; +	enum omap_plane id;  	enum omap_color_mode supported_modes;  	enum omap_overlay_caps caps; @@ -332,6 +394,7 @@ struct omap_overlay {  	struct omap_overlay_manager *manager;  	struct omap_overlay_info info; +	bool manager_changed;  	/* if true, info has been changed, but not applied() yet */  	bool info_dirty; @@ -354,7 +417,7 @@ struct omap_overlay_manager_info {  	u32 trans_key;  	bool trans_enabled; -	bool alpha_enabled; +	bool partial_alpha_enabled;  	bool cpr_enable;  	struct omap_dss_cpr_coefs cpr_coefs; @@ -366,7 +429,7 @@ struct omap_overlay_manager {  	/* static fields */  	const char *name; -	int id; +	enum omap_channel id;  	enum omap_overlay_manager_caps caps;  	int num_overlays;  	struct omap_overlay **overlays; @@ -454,6 +517,7 @@ struct omap_dss_device {  		} dispc;  		struct { +			/* regn is one greater than TRM's REGN value */  			u16 regn;  			u16 regm;  			u16 regm_dispc; @@ -464,6 +528,7 @@ struct omap_dss_device {  		} dsi;  		struct { +			/* regn is one greater than TRM's REGN value */  			u16 regn;  			u16 regm2;  		} hdmi; @@ -477,6 +542,10 @@ struct omap_dss_device {  		int acb;	/* ac-bias pin frequency */  		enum omap_panel_config config; + +		enum omap_dss_dsi_pixel_format dsi_pix_fmt; +		enum omap_dss_dsi_mode dsi_mode; +		struct omap_dss_dsi_videomode_data dsi_vm_data;  	} panel;  	struct { @@ -557,6 +626,9 @@ struct omap_dss_driver {  	int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);  	u32 (*get_wss)(struct omap_dss_device *dssdev); + +	int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); +	bool (*detect)(struct omap_dss_device *dssdev);  };  int omap_dss_register_driver(struct omap_dss_driver *);  |