diff options
127 files changed, 5347 insertions, 4718 deletions
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index 480cd78f192..85fc2feb0af 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -29,6 +29,7 @@  #include <drm/exynos_drm.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <media/m5mols.h>  #include <media/s5k6aa.h>  #include <media/s5p_fimc.h> @@ -39,7 +40,6 @@  #include <asm/mach-types.h>  #include <plat/adc.h> -#include <plat/regs-fb-v4.h>  #include <plat/regs-serial.h>  #include <plat/cpu.h>  #include <plat/devs.h> diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 67b50bb89c0..c11a62e23dc 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -30,9 +30,9 @@  #include <asm/mach-types.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <plat/regs-serial.h> -#include <plat/regs-fb-v4.h>  #include <plat/cpu.h>  #include <plat/devs.h>  #include <plat/sdhci.h> diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c index 7a265d1a82d..730f1ac6592 100644 --- a/arch/arm/mach-exynos/mach-smdk4x12.c +++ b/arch/arm/mach-exynos/mach-smdk4x12.c @@ -27,6 +27,7 @@  #include <asm/hardware/gic.h>  #include <asm/mach-types.h> +#include <video/samsung_fimd.h>  #include <plat/backlight.h>  #include <plat/clock.h>  #include <plat/cpu.h> @@ -36,7 +37,6 @@  #include <linux/platform_data/i2c-s3c2410.h>  #include <plat/keypad.h>  #include <plat/mfc.h> -#include <plat/regs-fb.h>  #include <plat/regs-serial.h>  #include <plat/sdhci.h> diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index c15d2238ceb..ee4fb1a9cb7 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c @@ -27,9 +27,9 @@  #include <asm/mach-types.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <plat/regs-serial.h>  #include <plat/regs-srom.h> -#include <plat/regs-fb-v4.h>  #include <plat/cpu.h>  #include <plat/devs.h>  #include <plat/fb.h> diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index 98d3aced228..08b81fd9950 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -30,6 +30,7 @@  #include <asm/hardware/gic.h>  #include <asm/mach-types.h> +#include <video/samsung_fimd.h>  #include <plat/regs-serial.h>  #include <plat/clock.h>  #include <plat/cpu.h> @@ -39,7 +40,6 @@  #include <plat/fb.h>  #include <plat/mfc.h>  #include <plat/sdhci.h> -#include <plat/regs-fb-v4.h>  #include <plat/fimc-core.h>  #include <plat/s5p-time.h>  #include <plat/camport.h> diff --git a/arch/arm/mach-exynos/setup-fimd0.c b/arch/arm/mach-exynos/setup-fimd0.c index 07a6dbeecdd..5665bb4e980 100644 --- a/arch/arm/mach-exynos/setup-fimd0.c +++ b/arch/arm/mach-exynos/setup-fimd0.c @@ -13,8 +13,8 @@  #include <linux/fb.h>  #include <linux/gpio.h> +#include <video/samsung_fimd.h>  #include <plat/gpio-cfg.h> -#include <plat/regs-fb-v4.h>  #include <mach/map.h> diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 5ff28afbefe..3669c120c7e 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -607,29 +607,6 @@ static void __init omap_sfh7741prox_init(void)  			__func__, OMAP4_SFH7741_ENABLE_GPIO, error);  } -static struct gpio sdp4430_hdmi_gpios[] = { -	{ HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" }, -	{ HDMI_GPIO_LS_OE,	GPIOF_OUT_INIT_HIGH,	"hdmi_gpio_ls_oe" }, -	{ HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" }, -}; - -static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev) -{ -	int status; - -	status = gpio_request_array(sdp4430_hdmi_gpios, -				    ARRAY_SIZE(sdp4430_hdmi_gpios)); -	if (status) -		pr_err("%s: Cannot request HDMI GPIOs\n", __func__); - -	return status; -} - -static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev) -{ -	gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios)); -} -  static struct nokia_dsi_panel_data dsi1_panel = {  		.name		= "taal",  		.reset_gpio	= 102, @@ -650,29 +627,6 @@ static struct omap_dss_device sdp4430_lcd_device = {  	.phy.dsi		= {  		.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,  }; @@ -697,33 +651,12 @@ static struct omap_dss_device sdp4430_lcd2_device = {  		.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, -		}, - -		.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 struct omap_dss_hdmi_data sdp4430_hdmi_data = { +	.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD, +	.ls_oe_gpio = HDMI_GPIO_LS_OE,  	.hpd_gpio = HDMI_GPIO_HPD,  }; @@ -731,8 +664,6 @@ 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,  	.data = &sdp4430_hdmi_data,  }; diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index f62b903f3ea..bfcd397e233 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -428,30 +428,9 @@ static struct omap_dss_device omap4_panda_dvi_device = {  	.channel		= OMAP_DSS_CHANNEL_LCD2,  }; -static struct gpio panda_hdmi_gpios[] = { -	{ HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" }, -	{ HDMI_GPIO_LS_OE,	GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, -	{ HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" }, -}; - -static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev) -{ -	int status; - -	status = gpio_request_array(panda_hdmi_gpios, -				    ARRAY_SIZE(panda_hdmi_gpios)); -	if (status) -		pr_err("Cannot request HDMI GPIOs\n"); - -	return status; -} - -static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev) -{ -	gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios)); -} -  static struct omap_dss_hdmi_data omap4_panda_hdmi_data = { +	.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD, +	.ls_oe_gpio = HDMI_GPIO_LS_OE,  	.hpd_gpio = HDMI_GPIO_HPD,  }; @@ -459,8 +438,6 @@ static struct omap_dss_device  omap4_panda_hdmi_device = {  	.name = "hdmi",  	.driver_name = "hdmi_panel",  	.type = OMAP_DISPLAY_TYPE_HDMI, -	.platform_enable = omap4_panda_panel_enable_hdmi, -	.platform_disable = omap4_panda_panel_disable_hdmi,  	.channel = OMAP_DSS_CHANNEL_DIGIT,  	.data = &omap4_panda_hdmi_data,  }; diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index a51ece491b9..1011995f150 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -95,7 +95,6 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {  	{ "dss_core", "omapdss_dss", -1 },  	{ "dss_dispc", "omapdss_dispc", -1 },  	{ "dss_rfbi", "omapdss_rfbi", -1 }, -	{ "dss_venc", "omapdss_venc", -1 },  	{ "dss_dsi1", "omapdss_dsi", 0 },  	{ "dss_dsi2", "omapdss_dsi", 1 },  	{ "dss_hdmi", "omapdss_hdmi", -1 }, diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index d83ae4540b9..635e109f5ad 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -239,6 +239,10 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,  static struct twl4030_usb_data omap4_usb_pdata = {  }; +static struct regulator_consumer_supply omap4_vdda_hdmi_dac_supplies[] = { +	REGULATOR_SUPPLY("vdda_hdmi_dac", "omapdss_hdmi"), +}; +  static struct regulator_init_data omap4_vdac_idata = {  	.constraints = {  		.min_uV			= 1800000, @@ -248,6 +252,8 @@ static struct regulator_init_data omap4_vdac_idata = {  		.valid_ops_mask		= REGULATOR_CHANGE_MODE  					| REGULATOR_CHANGE_STATUS,  	}, +	.num_consumer_supplies	= ARRAY_SIZE(omap4_vdda_hdmi_dac_supplies), +	.consumer_supplies	= omap4_vdda_hdmi_dac_supplies,  	.supply_regulator	= "V2V1",  }; diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c index db2787aa1e5..f30d7fccbfe 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c @@ -29,6 +29,7 @@  #include <asm/mach/map.h>  #include <asm/mach/irq.h> +#include <video/samsung_fimd.h>  #include <mach/hardware.h>  #include <asm/irq.h>  #include <asm/mach-types.h> @@ -52,7 +53,6 @@  #include <linux/platform_data/usb-s3c2410_udc.h>  #include <linux/platform_data/s3c-hsudc.h> -#include <plat/regs-fb-v4.h>  #include <plat/fb.h>  #include <plat/common-smdk.h> diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c index 15c58dfc458..99e82ac81b6 100644 --- a/arch/arm/mach-s3c64xx/mach-anw6410.c +++ b/arch/arm/mach-s3c64xx/mach-anw6410.c @@ -29,6 +29,7 @@  #include <linux/dm9000.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <asm/hardware/vic.h>  #include <asm/mach/arch.h> @@ -44,7 +45,6 @@  #include <plat/regs-serial.h>  #include <linux/platform_data/i2c-s3c2410.h>  #include <plat/fb.h> -#include <plat/regs-fb-v4.h>  #include <plat/clock.h>  #include <plat/devs.h> diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 8b4d4670664..13b7eaa45fd 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -46,6 +46,7 @@  #include <asm/mach/arch.h>  #include <asm/mach-types.h> +#include <video/samsung_fimd.h>  #include <mach/hardware.h>  #include <mach/map.h> @@ -57,7 +58,6 @@  #include <mach/regs-gpio-memport.h>  #include <plat/regs-serial.h> -#include <plat/regs-fb-v4.h>  #include <plat/fb.h>  #include <plat/sdhci.h>  #include <plat/gpio-cfg.h> diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c index 02222b32b7d..2b144893ddc 100644 --- a/arch/arm/mach-s3c64xx/mach-hmt.c +++ b/arch/arm/mach-s3c64xx/mach-hmt.c @@ -26,6 +26,7 @@  #include <asm/mach/map.h>  #include <asm/mach/irq.h> +#include <video/samsung_fimd.h>  #include <mach/hardware.h>  #include <mach/map.h> @@ -41,7 +42,6 @@  #include <plat/clock.h>  #include <plat/devs.h>  #include <plat/cpu.h> -#include <plat/regs-fb-v4.h>  #include "common.h" diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c index 09311cc4011..07c349cca33 100644 --- a/arch/arm/mach-s3c64xx/mach-mini6410.c +++ b/arch/arm/mach-s3c64xx/mach-mini6410.c @@ -41,9 +41,9 @@  #include <linux/platform_data/mtd-nand-s3c2410.h>  #include <plat/regs-serial.h>  #include <linux/platform_data/touchscreen-s3c2410.h> -#include <plat/regs-fb-v4.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include "common.h" diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c index 46ee88d1681..e5f9a79b535 100644 --- a/arch/arm/mach-s3c64xx/mach-ncp.c +++ b/arch/arm/mach-s3c64xx/mach-ncp.c @@ -24,6 +24,7 @@  #include <linux/delay.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <asm/hardware/vic.h>  #include <asm/mach/arch.h> @@ -43,7 +44,6 @@  #include <plat/clock.h>  #include <plat/devs.h>  #include <plat/cpu.h> -#include <plat/regs-fb-v4.h>  #include "common.h" diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index 6daca203e72..7476f7c722a 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c @@ -42,9 +42,9 @@  #include <linux/platform_data/mtd-nand-s3c2410.h>  #include <plat/regs-serial.h>  #include <linux/platform_data/touchscreen-s3c2410.h> -#include <plat/regs-fb-v4.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include "common.h" diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c index d6266d8b43c..96d6da2b6b5 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq5.c +++ b/arch/arm/mach-s3c64xx/mach-smartq5.c @@ -21,6 +21,7 @@  #include <asm/mach-types.h>  #include <asm/mach/arch.h> +#include <video/samsung_fimd.h>  #include <mach/map.h>  #include <mach/regs-gpio.h> @@ -28,7 +29,6 @@  #include <plat/devs.h>  #include <plat/fb.h>  #include <plat/gpio-cfg.h> -#include <plat/regs-fb-v4.h>  #include "common.h"  #include "mach-smartq.h" diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c index 0957d2a980e..7d1167bdc92 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq7.c +++ b/arch/arm/mach-s3c64xx/mach-smartq7.c @@ -21,6 +21,7 @@  #include <asm/mach-types.h>  #include <asm/mach/arch.h> +#include <video/samsung_fimd.h>  #include <mach/map.h>  #include <mach/regs-gpio.h> @@ -28,7 +29,6 @@  #include <plat/devs.h>  #include <plat/fb.h>  #include <plat/gpio-cfg.h> -#include <plat/regs-fb-v4.h>  #include "common.h"  #include "mach-smartq.h" diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index 2547a884647..da1a771a29e 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -43,6 +43,7 @@  #endif  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <asm/hardware/vic.h>  #include <asm/mach/arch.h> @@ -72,7 +73,6 @@  #include <linux/platform_data/touchscreen-s3c2410.h>  #include <plat/keypad.h>  #include <plat/backlight.h> -#include <plat/regs-fb-v4.h>  #include "common.h" diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index dea78a84824..96ea1fe0ec9 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -27,6 +27,7 @@  #include <linux/mmc/host.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <asm/hardware/vic.h>  #include <asm/mach/arch.h> @@ -52,7 +53,6 @@  #include <plat/s5p-time.h>  #include <plat/backlight.h>  #include <plat/fb.h> -#include <plat/regs-fb.h>  #include <plat/sdhci.h>  #include "common.h" diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c index 6f14fc729b8..12748b6eaa7 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -27,6 +27,7 @@  #include <linux/mmc/host.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <asm/hardware/vic.h>  #include <asm/mach/arch.h> @@ -52,7 +53,6 @@  #include <plat/s5p-time.h>  #include <plat/backlight.h>  #include <plat/fb.h> -#include <plat/regs-fb.h>  #include <plat/sdhci.h>  #include "common.h" diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index 5d2c0934928..dba7384a87b 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -33,6 +33,7 @@  #include <mach/regs-gpio.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <asm/irq.h>  #include <asm/mach-types.h> @@ -51,7 +52,6 @@  #include <linux/platform_data/touchscreen-s3c2410.h>  #include <linux/platform_data/asoc-s3c.h>  #include <plat/backlight.h> -#include <plat/regs-fb-v4.h>  #include "common.h" diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 78028df86c5..ee9fa5c2ef2 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -28,6 +28,7 @@  #include <asm/setup.h>  #include <asm/mach-types.h> +#include <video/samsung_fimd.h>  #include <mach/map.h>  #include <mach/regs-clock.h> @@ -39,7 +40,6 @@  #include <plat/fimc-core.h>  #include <plat/sdhci.h>  #include <plat/s5p-time.h> -#include <plat/regs-fb-v4.h>  #include "common.h" diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index 00f1e47d490..55e1dba4ffd 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -35,6 +35,7 @@  #include <asm/setup.h>  #include <asm/mach-types.h> +#include <video/samsung_fimd.h>  #include <mach/map.h>  #include <mach/regs-clock.h> @@ -49,7 +50,6 @@  #include <plat/clock.h>  #include <plat/s5p-time.h>  #include <plat/mfc.h> -#include <plat/regs-fb-v4.h>  #include <plat/camport.h>  #include <media/v4l2-mediabus.h> diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index 7d6fab42050..4cdb5bb7bbc 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -28,6 +28,7 @@  #include <asm/mach-types.h>  #include <video/platform_lcd.h> +#include <video/samsung_fimd.h>  #include <mach/map.h>  #include <mach/regs-clock.h> @@ -46,7 +47,6 @@  #include <plat/fb.h>  #include <plat/s5p-time.h>  #include <plat/backlight.h> -#include <plat/regs-fb-v4.h>  #include <plat/mfc.h>  #include <plat/clock.h> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h deleted file mode 100644 index 4c3647f8005..00000000000 --- a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h +++ /dev/null @@ -1,159 +0,0 @@ -/* arch/arm/plat-samsung/include/plat/regs-fb-v4.h - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - *      http://armlinux.simtec.co.uk/ - *      Ben Dooks <ben@simtec.co.uk> - * - * S3C64XX - new-style framebuffer register definitions - * - * This is the register set for the new style framebuffer interface - * found from the S3C2443 onwards and specifically the S3C64XX series - * S3C6400 and S3C6410. - * - * The file contains the cpu specific items which change between whichever - * architecture is selected. See <plat/regs-fb.h> for the core definitions - * that are the same. - * - * 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. -*/ - -/* include the core definitions here, in case we really do need to - * override them at a later date. -*/ - -#include <plat/regs-fb.h> - -#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */ -#define VIDCON1_FSTATUS_EVEN	(1 << 15) - -/* Video timing controls */ -#define VIDTCON0				(0x10) -#define VIDTCON1				(0x14) -#define VIDTCON2				(0x18) - -/* Window position controls */ - -#define WINCON(_win)				(0x20 + ((_win) * 4)) - -/* OSD1 and OSD4 do not have register D */ - -#define VIDOSD_BASE				(0x40) - -#define VIDINTCON0				(0x130) - -/* WINCONx */ - -#define WINCONx_CSCWIDTH_MASK			(0x3 << 26) -#define WINCONx_CSCWIDTH_SHIFT			(26) -#define WINCONx_CSCWIDTH_WIDE			(0x0 << 26) -#define WINCONx_CSCWIDTH_NARROW			(0x3 << 26) - -#define WINCONx_ENLOCAL				(1 << 22) -#define WINCONx_BUFSTATUS			(1 << 21) -#define WINCONx_BUFSEL				(1 << 20) -#define WINCONx_BUFAUTOEN			(1 << 19) -#define WINCONx_YCbCr				(1 << 13) - -#define WINCON1_LOCALSEL_CAMIF			(1 << 23) - -#define WINCON2_LOCALSEL_CAMIF			(1 << 23) -#define WINCON2_BLD_PIX				(1 << 6) - -#define WINCON2_ALPHA_SEL			(1 << 1) -#define WINCON2_BPPMODE_MASK			(0xf << 2) -#define WINCON2_BPPMODE_SHIFT			(2) -#define WINCON2_BPPMODE_1BPP			(0x0 << 2) -#define WINCON2_BPPMODE_2BPP			(0x1 << 2) -#define WINCON2_BPPMODE_4BPP			(0x2 << 2) -#define WINCON2_BPPMODE_8BPP_1232		(0x4 << 2) -#define WINCON2_BPPMODE_16BPP_565		(0x5 << 2) -#define WINCON2_BPPMODE_16BPP_A1555		(0x6 << 2) -#define WINCON2_BPPMODE_16BPP_I1555		(0x7 << 2) -#define WINCON2_BPPMODE_18BPP_666		(0x8 << 2) -#define WINCON2_BPPMODE_18BPP_A1665		(0x9 << 2) -#define WINCON2_BPPMODE_19BPP_A1666		(0xa << 2) -#define WINCON2_BPPMODE_24BPP_888		(0xb << 2) -#define WINCON2_BPPMODE_24BPP_A1887		(0xc << 2) -#define WINCON2_BPPMODE_25BPP_A1888		(0xd << 2) -#define WINCON2_BPPMODE_28BPP_A4888		(0xd << 2) - -#define WINCON3_BLD_PIX				(1 << 6) - -#define WINCON3_ALPHA_SEL			(1 << 1) -#define WINCON3_BPPMODE_MASK			(0xf << 2) -#define WINCON3_BPPMODE_SHIFT			(2) -#define WINCON3_BPPMODE_1BPP			(0x0 << 2) -#define WINCON3_BPPMODE_2BPP			(0x1 << 2) -#define WINCON3_BPPMODE_4BPP			(0x2 << 2) -#define WINCON3_BPPMODE_16BPP_565		(0x5 << 2) -#define WINCON3_BPPMODE_16BPP_A1555		(0x6 << 2) -#define WINCON3_BPPMODE_16BPP_I1555		(0x7 << 2) -#define WINCON3_BPPMODE_18BPP_666		(0x8 << 2) -#define WINCON3_BPPMODE_18BPP_A1665		(0x9 << 2) -#define WINCON3_BPPMODE_19BPP_A1666		(0xa << 2) -#define WINCON3_BPPMODE_24BPP_888		(0xb << 2) -#define WINCON3_BPPMODE_24BPP_A1887		(0xc << 2) -#define WINCON3_BPPMODE_25BPP_A1888		(0xd << 2) -#define WINCON3_BPPMODE_28BPP_A4888		(0xd << 2) - -#define VIDINTCON0_FIFIOSEL_WINDOW2		(0x10 << 5) -#define VIDINTCON0_FIFIOSEL_WINDOW3		(0x20 << 5) -#define VIDINTCON0_FIFIOSEL_WINDOW4		(0x40 << 5) - -#define DITHMODE				(0x170) -#define WINxMAP(_win)				(0x180 + ((_win) * 4)) - - -#define DITHMODE_R_POS_MASK			(0x3 << 5) -#define DITHMODE_R_POS_SHIFT			(5) -#define DITHMODE_R_POS_8BIT			(0x0 << 5) -#define DITHMODE_R_POS_6BIT			(0x1 << 5) -#define DITHMODE_R_POS_5BIT			(0x2 << 5) - -#define DITHMODE_G_POS_MASK			(0x3 << 3) -#define DITHMODE_G_POS_SHIFT			(3) -#define DITHMODE_G_POS_8BIT			(0x0 << 3) -#define DITHMODE_G_POS_6BIT			(0x1 << 3) -#define DITHMODE_G_POS_5BIT			(0x2 << 3) - -#define DITHMODE_B_POS_MASK			(0x3 << 1) -#define DITHMODE_B_POS_SHIFT			(1) -#define DITHMODE_B_POS_8BIT			(0x0 << 1) -#define DITHMODE_B_POS_6BIT			(0x1 << 1) -#define DITHMODE_B_POS_5BIT			(0x2 << 1) - -#define DITHMODE_DITH_EN			(1 << 0) - -#define WPALCON					(0x1A0) - -/* Palette control */ -/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L), - * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */ -#define WPALCON_W4PAL_16BPP_A555		(1 << 8) -#define WPALCON_W3PAL_16BPP_A555		(1 << 7) -#define WPALCON_W2PAL_16BPP_A555		(1 << 6) - - -/* Notes on per-window bpp settings - * - * Value	Win0	 Win1	  Win2	   Win3	    Win 4 - * 0000		1(P)	 1(P)	  1(P)	   1(P)	    1(P) - * 0001		2(P)	 2(P)     2(P)	   2(P)	    2(P) - * 0010		4(P)	 4(P)     4(P)	   4(P)     -none- - * 0011		8(P)	 8(P)     -none-   -none-   -none- - * 0100		-none-	 8(A232)  8(A232)  -none-   -none- - * 0101		16(565)	 16(565)  16(565)  16(565)   16(565) - * 0110		-none-	 16(A555) 16(A555) 16(A555)  16(A555) - * 0111		16(I555) 16(I565) 16(I555) 16(I555)  16(I555) - * 1000		18(666)	 18(666)  18(666)  18(666)   18(666) - * 1001		-none-	 18(A665) 18(A665) 18(A665)  16(A665) - * 1010		-none-	 19(A666) 19(A666) 19(A666)  19(A666) - * 1011		24(888)	 24(888)  24(888)  24(888)   24(888) - * 1100		-none-	 24(A887) 24(A887) 24(A887)  24(A887) - * 1101		-none-	 25(A888) 25(A888) 25(A888)  25(A888) - * 1110		-none-	 -none-	  -none-   -none-    -none- - * 1111		-none-	 -none-   -none-   -none-    -none- -*/ diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index a32837951dd..130a2b510d4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -19,8 +19,8 @@  #include <linux/clk.h>  #include <linux/pm_runtime.h> +#include <video/samsung_fimd.h>  #include <drm/exynos_drm.h> -#include <plat/regs-fb-v4.h>  #include "exynos_drm_drv.h"  #include "exynos_drm_fbdev.h" diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 134016f0e66..a3b1a34c896 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -455,11 +455,15 @@ static int omapvid_init(struct omap_vout_device *vout, u32 addr)  	win = &vout->win;  	for (i = 0; i < ovid->num_overlays; i++) { +		struct omap_dss_device *dssdev; +  		ovl = ovid->overlays[i]; -		if (!ovl->manager || !ovl->manager->device) +		dssdev = ovl->get_device(ovl); + +		if (!dssdev)  			return -EINVAL; -		timing = &ovl->manager->device->panel.timings; +		timing = &dssdev->panel.timings;  		outw = win->w.width;  		outh = win->w.height; @@ -516,8 +520,11 @@ static int omapvid_apply_changes(struct omap_vout_device *vout)  	struct omapvideo_info *ovid = &vout->vid_info;  	for (i = 0; i < ovid->num_overlays; i++) { +		struct omap_dss_device *dssdev; +  		ovl = ovid->overlays[i]; -		if (!ovl->manager || !ovl->manager->device) +		dssdev = ovl->get_device(ovl); +		if (!dssdev)  			return -EINVAL;  		ovl->manager->apply(ovl->manager);  	} @@ -580,12 +587,14 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus)  	ovid = &vout->vid_info;  	ovl = ovid->overlays[0]; -	/* get the display device attached to the overlay */ -	if (!ovl->manager || !ovl->manager->device) -		return;  	mgr_id = ovl->manager->id; -	cur_display = ovl->manager->device; + +	/* get the display device attached to the overlay */ +	cur_display = ovl->get_device(ovl); + +	if (!cur_display) +		return;  	spin_lock(&vout->vbq_lock);  	do_gettimeofday(&timevalue); @@ -949,7 +958,9 @@ static int omap_vout_release(struct file *file)  	/* Disable all the overlay managers connected with this interface */  	for (i = 0; i < ovid->num_overlays; i++) {  		struct omap_overlay *ovl = ovid->overlays[i]; -		if (ovl->manager && ovl->manager->device) +		struct omap_dss_device *dssdev = ovl->get_device(ovl); + +		if (dssdev)  			ovl->disable(ovl);  	}  	/* Turn off the pipeline */ @@ -1082,14 +1093,17 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *fh,  	struct omapvideo_info *ovid;  	struct omap_video_timings *timing;  	struct omap_vout_device *vout = fh; +	struct omap_dss_device *dssdev;  	ovid = &vout->vid_info;  	ovl = ovid->overlays[0]; +	/* get the display device attached to the overlay */ +	dssdev = ovl->get_device(ovl); -	if (!ovl->manager || !ovl->manager->device) +	if (!dssdev)  		return -EINVAL; -	/* get the display device attached to the overlay */ -	timing = &ovl->manager->device->panel.timings; + +	timing = &dssdev->panel.timings;  	vout->fbuf.fmt.height = timing->y_res;  	vout->fbuf.fmt.width = timing->x_res; @@ -1106,6 +1120,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,  	struct omapvideo_info *ovid;  	struct omap_video_timings *timing;  	struct omap_vout_device *vout = fh; +	struct omap_dss_device *dssdev;  	if (vout->streaming)  		return -EBUSY; @@ -1114,13 +1129,14 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,  	ovid = &vout->vid_info;  	ovl = ovid->overlays[0]; +	dssdev = ovl->get_device(ovl);  	/* get the display device attached to the overlay */ -	if (!ovl->manager || !ovl->manager->device) { +	if (!dssdev) {  		ret = -EINVAL;  		goto s_fmt_vid_out_exit;  	} -	timing = &ovl->manager->device->panel.timings; +	timing = &dssdev->panel.timings;  	/* We dont support RGB24-packed mode if vrfb rotation  	 * is enabled*/ @@ -1299,6 +1315,7 @@ static int vidioc_s_crop(struct file *file, void *fh, const struct v4l2_crop *cr  	struct omapvideo_info *ovid;  	struct omap_overlay *ovl;  	struct omap_video_timings *timing; +	struct omap_dss_device *dssdev;  	if (vout->streaming)  		return -EBUSY; @@ -1306,13 +1323,15 @@ static int vidioc_s_crop(struct file *file, void *fh, const struct v4l2_crop *cr  	mutex_lock(&vout->lock);  	ovid = &vout->vid_info;  	ovl = ovid->overlays[0]; +	/* get the display device attached to the overlay */ +	dssdev = ovl->get_device(ovl); -	if (!ovl->manager || !ovl->manager->device) { +	if (!dssdev) {  		ret = -EINVAL;  		goto s_crop_err;  	} -	/* get the display device attached to the overlay */ -	timing = &ovl->manager->device->panel.timings; + +	timing = &dssdev->panel.timings;  	if (is_rotation_90_or_270(vout)) {  		vout->fbuf.fmt.height = timing->x_res; @@ -1668,7 +1687,7 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)  	for (j = 0; j < ovid->num_overlays; j++) {  		struct omap_overlay *ovl = ovid->overlays[j]; -		if (ovl->manager && ovl->manager->device) { +		if (ovl->get_device(ovl)) {  			struct omap_overlay_info info;  			ovl->get_overlay_info(ovl, &info);  			info.paddr = addr; @@ -1691,8 +1710,9 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)  	for (j = 0; j < ovid->num_overlays; j++) {  		struct omap_overlay *ovl = ovid->overlays[j]; +		struct omap_dss_device *dssdev = ovl->get_device(ovl); -		if (ovl->manager && ovl->manager->device) { +		if (dssdev) {  			ret = ovl->enable(ovl);  			if (ret)  				goto streamon_err1; @@ -1727,8 +1747,9 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)  	for (j = 0; j < ovid->num_overlays; j++) {  		struct omap_overlay *ovl = ovid->overlays[j]; +		struct omap_dss_device *dssdev = ovl->get_device(ovl); -		if (ovl->manager && ovl->manager->device) +		if (dssdev)  			ovl->disable(ovl);  	} @@ -1891,8 +1912,8 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)  	struct video_device *vfd;  	struct v4l2_pix_format *pix;  	struct v4l2_control *control; -	struct omap_dss_device *display = -		vout->vid_info.overlays[0]->manager->device; +	struct omap_overlay *ovl = vout->vid_info.overlays[0]; +	struct omap_dss_device *display = ovl->get_device(ovl);  	/* set the default pix */  	pix = &vout->pix; @@ -2207,8 +2228,10 @@ static int __init omap_vout_probe(struct platform_device *pdev)  	 */  	for (i = 1; i < vid_dev->num_overlays; i++) {  		ovl = omap_dss_get_overlay(i); -		if (ovl->manager && ovl->manager->device) { -			def_display = ovl->manager->device; +		dssdev = ovl->get_device(ovl); + +		if (dssdev) { +			def_display = dssdev;  		} else {  			dev_warn(&pdev->dev, "cannot find display\n");  			def_display = NULL; @@ -2255,8 +2278,10 @@ probe_err1:  	for (i = 1; i < vid_dev->num_overlays; i++) {  		def_display = NULL;  		ovl = omap_dss_get_overlay(i); -		if (ovl->manager && ovl->manager->device) -			def_display = ovl->manager->device; +		dssdev = ovl->get_device(ovl); + +		if (dssdev) +			def_display = dssdev;  		if (def_display && def_display->driver)  			def_display->driver->disable(def_display); diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 2ec5264dd00..ebdb0b67673 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -106,7 +106,8 @@ static void dump_video_chains(void)  	for (i = 0; i < omap_dss_get_num_overlays(); i++) {  		struct omap_overlay *ovl = omap_dss_get_overlay(i);  		struct omap_overlay_manager *mgr = ovl->manager; -		struct omap_dss_device *dssdev = mgr ? mgr->device : NULL; +		struct omap_dss_device *dssdev = mgr ? +					mgr->get_device(mgr) : NULL;  		if (dssdev) {  			DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name,  						dssdev->name); @@ -185,7 +186,7 @@ static int create_connector(struct drm_device *dev,  	for (j = 0; j < priv->num_encoders; j++) {  		struct omap_overlay_manager *mgr =  			omap_encoder_get_manager(priv->encoders[j]); -		if (mgr->device == dssdev) { +		if (mgr->get_device(mgr) == dssdev) {  			drm_mode_connector_attach_encoder(connector,  					priv->encoders[j]);  		} diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 20c33c42600..d08d7998a4a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2139,21 +2139,6 @@ config FB_UDL  	  mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.  	  To compile as a module, choose M here: the module name is udlfb. -config FB_PNX4008_DUM -	tristate "Display Update Module support on Philips PNX4008 board" -	depends on FB && ARCH_PNX4008 -	---help--- -	  Say Y here to enable support for PNX4008 Display Update Module (DUM) - -config FB_PNX4008_DUM_RGB -	tristate "RGB Framebuffer support on Philips PNX4008 board" -	depends on FB_PNX4008_DUM -	select FB_CFB_FILLRECT -	select FB_CFB_COPYAREA -	select FB_CFB_IMAGEBLIT -	---help--- -	  Say Y here to enable support for PNX4008 RGB Framebuffer -  config FB_IBM_GXT4500  	tristate "Framebuffer support for IBM GXT4500P adaptor"  	depends on FB && PPC diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 194035986af..23e948ebfab 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -127,8 +127,6 @@ obj-$(CONFIG_FB_S3C)		  += s3c-fb.o  obj-$(CONFIG_FB_S3C2410)	  += s3c2410fb.o  obj-$(CONFIG_FB_FSL_DIU)	  += fsl-diu-fb.o  obj-$(CONFIG_FB_COBALT)           += cobalt_lcdfb.o -obj-$(CONFIG_FB_PNX4008_DUM)	  += pnx4008/ -obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/  obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o  obj-$(CONFIG_FB_PS3)		  += ps3fb.o  obj-$(CONFIG_FB_SM501)            += sm501fb.o diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 887df9d8142..7fa1bf82372 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -949,7 +949,6 @@ static int round_down_bpp = 1;	/* for mode probing */  static int amifb_ilbm = 0;	/* interleaved or normal bitplanes */ -static int amifb_inverse = 0;  static u32 amifb_hfmin __initdata;	/* monitor hfreq lower limit (Hz) */  static u32 amifb_hfmax __initdata;	/* monitor hfreq upper limit (Hz) */ @@ -2355,7 +2354,6 @@ static int __init amifb_setup(char *options)  		if (!*this_opt)  			continue;  		if (!strcmp(this_opt, "inverse")) { -			amifb_inverse = 1;  			fb_invert_cmaps();  		} else if (!strcmp(this_opt, "ilbm"))  			amifb_ilbm = 1; diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index a1d58e9d307..4659d5da6ff 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -552,6 +552,7 @@ static int __devinit arcfb_probe(struct platform_device *dev)  				"arcfb", info)) {  			printk(KERN_INFO  				"arcfb: Failed req IRQ %d\n", par->irq); +			retval = -EBUSY;  			goto err1;  		}  	} diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 15055395cd9..94cac9f9919 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -931,8 +931,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)  		}  		info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); -		if (!info->screen_base) +		if (!info->screen_base) { +			ret = -ENOMEM;  			goto release_intmem; +		}  		/*  		 * Don't clear the framebuffer -- someone may have set @@ -960,6 +962,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)  	sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);  	if (!sinfo->mmio) {  		dev_err(dev, "cannot map LCDC registers\n"); +		ret = -ENOMEM;  		goto release_mem;  	} diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c index befbc80d11f..7347aa1e5e4 100644 --- a/drivers/video/bf537-lq035.c +++ b/drivers/video/bf537-lq035.c @@ -760,18 +760,20 @@ static int __devinit bfin_lq035_probe(struct platform_device *pdev)  	bfin_lq035_fb.flags = FBINFO_DEFAULT; -	bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL); +	bfin_lq035_fb.pseudo_palette = devm_kzalloc(&pdev->dev, +						    sizeof(u32) * 16, +						    GFP_KERNEL);  	if (bfin_lq035_fb.pseudo_palette == NULL) {  		pr_err("failed to allocate pseudo_palette\n");  		ret = -ENOMEM; -		goto out_palette; +		goto out_table;  	}  	if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {  		pr_err("failed to allocate colormap (%d entries)\n",  			NBR_PALETTE);  		ret = -EFAULT; -		goto out_cmap; +		goto out_table;  	}  	if (register_framebuffer(&bfin_lq035_fb) < 0) { @@ -804,9 +806,6 @@ out_lcd:  	unregister_framebuffer(&bfin_lq035_fb);  out_reg:  	fb_dealloc_cmap(&bfin_lq035_fb.cmap); -out_cmap: -	kfree(bfin_lq035_fb.pseudo_palette); -out_palette:  out_table:  	dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);  	fb_buffer = NULL; @@ -834,7 +833,6 @@ static int __devexit bfin_lq035_remove(struct platform_device *pdev)  	free_dma(CH_PPI); -	kfree(bfin_lq035_fb.pseudo_palette);  	fb_dealloc_cmap(&bfin_lq035_fb.cmap); diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index dc2f0047769..ff5663f5c64 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -525,6 +525,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)  	info = fbinfo->par;  	info->fb = fbinfo;  	info->dev = &pdev->dev; +	spin_lock_init(&info->lock);  	platform_set_drvdata(pdev, fbinfo); @@ -601,7 +602,8 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)  	fbinfo->fbops = &bfin_bf54x_fb_ops; -	fbinfo->pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL); +	fbinfo->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16, +					      GFP_KERNEL);  	if (!fbinfo->pseudo_palette) {  		printk(KERN_ERR DRIVER_NAME  		       "Fail to allocate pseudo_palette\n"); @@ -616,7 +618,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)  		       "Fail to allocate colormap (%d entries)\n",  		       BFIN_LCD_NBR_PALETTE_ENTRIES);  		ret = -EFAULT; -		goto out5; +		goto out4;  	}  	if (request_ports(info)) { @@ -671,8 +673,6 @@ out7:  	free_ports(info);  out6:  	fb_dealloc_cmap(&fbinfo->cmap); -out5: -	kfree(fbinfo->pseudo_palette);  out4:  	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,  			  info->dma_handle); @@ -699,7 +699,6 @@ static int __devexit bfin_bf54x_remove(struct platform_device *pdev)  		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,  				  info->dma_handle); -	kfree(fbinfo->pseudo_palette);  	fb_dealloc_cmap(&fbinfo->cmap);  #ifndef NO_BL_SUPPORT diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c index 353c02fe8a9..6fbc75c2f0a 100644 --- a/drivers/video/bfin-lq035q1-fb.c +++ b/drivers/video/bfin-lq035q1-fb.c @@ -577,6 +577,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)  	info = fbinfo->par;  	info->fb = fbinfo;  	info->dev = &pdev->dev; +	spin_lock_init(&info->lock);  	info->disp_info = pdev->dev.platform_data; @@ -853,17 +854,7 @@ static struct platform_driver bfin_lq035q1_driver = {  	},  }; -static int __init bfin_lq035q1_driver_init(void) -{ -	return platform_driver_register(&bfin_lq035q1_driver); -} -module_init(bfin_lq035q1_driver_init); - -static void __exit bfin_lq035q1_driver_cleanup(void) -{ -	platform_driver_unregister(&bfin_lq035q1_driver); -} -module_exit(bfin_lq035q1_driver_cleanup); +module_platform_driver(bfin_lq035q1_driver);  MODULE_DESCRIPTION("Blackfin TFT LCD Driver");  MODULE_LICENSE("GPL"); diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 7a0c05f3537..ae0fb24b8b4 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -447,6 +447,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)  	info = fbinfo->par;  	info->fb = fbinfo;  	info->dev = &pdev->dev; +	spin_lock_init(&info->lock);  	platform_set_drvdata(pdev, fbinfo); diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 7ba74cd4be6..6bea9a93679 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -319,8 +319,10 @@ static int __devinit bw2_probe(struct platform_device *op)  	info->screen_base = of_ioremap(&op->resource[0], 0,  				       info->fix.smem_len, "bw2 ram"); -	if (!info->screen_base) +	if (!info->screen_base) { +		err = -ENOMEM;  		goto out_unmap_regs; +	}  	bw2_blank(FB_BLANK_UNBLANK, info); diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index f927a7b1a8d..c5e7612ff87 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -398,7 +398,8 @@ static int __devinit cg3_probe(struct platform_device *op)  			goto out_unmap_screen;  	} -	if (fb_alloc_cmap(&info->cmap, 256, 0)) +	err = fb_alloc_cmap(&info->cmap, 256, 0); +	if (err)  		goto out_unmap_screen;  	fb_set_cmap(&info->cmap, info); diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index eae46f6457e..01a4ee7cc6b 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c @@ -348,7 +348,8 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)  	}  	info->screen_size = resource_size(res); -	info->screen_base = ioremap(res->start, info->screen_size); +	info->screen_base = devm_ioremap(&dev->dev, res->start, +					 info->screen_size);  	info->fbops = &cobalt_lcd_fbops;  	info->fix = cobalt_lcdfb_fix;  	info->fix.smem_start = res->start; @@ -359,7 +360,6 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)  	retval = register_framebuffer(info);  	if (retval < 0) { -		iounmap(info->screen_base);  		framebuffer_release(info);  		return retval;  	} @@ -380,7 +380,6 @@ static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)  	info = platform_get_drvdata(dev);  	if (info) { -		iounmap(info->screen_base);  		unregister_framebuffer(info);  		framebuffer_release(info);  	} diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c index fa6e698e63c..838caa1cfef 100644 --- a/drivers/video/console/font_mini_4x6.c +++ b/drivers/video/console/font_mini_4x6.c @@ -1092,7 +1092,7 @@ static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {  	/*{*/ 	/*   Char 124: '|' */  	0x44,	/*=   [ *  ]        */  	0x44,	/*=   [ *  ]        */ -	0x00,	/*=   [    ]        */ +	0x44,	/*=   [ *  ]        */  	0x44,	/*=   [ *  ]        */  	0x44,	/*=   [ *  ]        */  	0x00,	/*=   [    ]        */ diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c index 5abf290c6eb..268151325b8 100644 --- a/drivers/video/console/font_sun8x16.c +++ b/drivers/video/console/font_sun8x16.c @@ -127,7 +127,7 @@ static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {  /*y*/ 0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00,  /*z*/ 0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,  /*{*/ 0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, -/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,  /*}*/ 0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,  /*~*/ 0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00, diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index c1527f5b47e..e40125cb313 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1804,8 +1804,10 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  	cfb->irq = dev->irq;  	cfb->region = pci_ioremap_bar(dev, 0); -	if (!cfb->region) +	if (!cfb->region) { +		err = -ENOMEM;  		goto failed_ioremap; +	}  	cfb->regs = cfb->region + MMIO_OFFSET;  	cfb->fb.device = &dev->dev; diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 113d43a16f5..80665f66ac1 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -26,7 +26,9 @@  #include <linux/device.h>  #include <linux/platform_device.h>  #include <linux/uaccess.h> +#include <linux/pm_runtime.h>  #include <linux/interrupt.h> +#include <linux/wait.h>  #include <linux/clk.h>  #include <linux/cpufreq.h>  #include <linux/console.h> @@ -48,6 +50,7 @@  #define LCD_PL_LOAD_DONE		BIT(6)  #define LCD_FIFO_UNDERFLOW		BIT(5)  #define LCD_SYNC_LOST			BIT(2) +#define LCD_FRAME_DONE			BIT(0)  /* LCD DMA Control Register */  #define LCD_DMA_BURST_SIZE(x)		((x) << 4) @@ -86,6 +89,8 @@  #define LCD_V2_LIDD_CLK_EN		BIT(1)  #define LCD_V2_CORE_CLK_EN		BIT(0)  #define LCD_V2_LPP_B10			26 +#define LCD_V2_TFT_24BPP_MODE		BIT(25) +#define LCD_V2_TFT_24BPP_UNPACK		BIT(26)  /* LCD Raster Timing 2 Register */  #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)	((x) << 16) @@ -135,6 +140,8 @@ static void __iomem *da8xx_fb_reg_base;  static struct resource *lcdc_regs;  static unsigned int lcd_revision;  static irq_handler_t lcdc_irq_handler; +static wait_queue_head_t frame_done_wq; +static int frame_done_flag;  static inline unsigned int lcdc_read(unsigned int addr)  { @@ -156,7 +163,6 @@ struct da8xx_fb_par {  	unsigned int		dma_end;  	struct clk *lcdc_clk;  	int irq; -	unsigned short pseudo_palette[16];  	unsigned int palette_sz;  	unsigned int pxl_clk;  	int blank; @@ -175,6 +181,7 @@ struct da8xx_fb_par {  	unsigned int		lcd_fck_rate;  #endif  	void (*panel_power_ctrl)(int); +	u32 pseudo_palette[16];  };  /* Variable Screen Information */ @@ -288,13 +295,26 @@ static inline void lcd_enable_raster(void)  }  /* Disable the Raster Engine of the LCD Controller */ -static inline void lcd_disable_raster(void) +static inline void lcd_disable_raster(bool wait_for_frame_done)  {  	u32 reg; +	int ret;  	reg = lcdc_read(LCD_RASTER_CTRL_REG);  	if (reg & LCD_RASTER_ENABLE)  		lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); +	else +		/* return if already disabled */ +		return; + +	if ((wait_for_frame_done == true) && (lcd_revision == LCD_VERSION_2)) { +		frame_done_flag = 0; +		ret = wait_event_interruptible_timeout(frame_done_wq, +				frame_done_flag != 0, +				msecs_to_jiffies(50)); +		if (ret == 0) +			pr_err("LCD Controller timed out\n"); +	}  }  static void lcd_blit(int load_mode, struct da8xx_fb_par *par) @@ -321,7 +341,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)  		} else {  			reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |  				LCD_V2_END_OF_FRAME0_INT_ENA | -				LCD_V2_END_OF_FRAME1_INT_ENA; +				LCD_V2_END_OF_FRAME1_INT_ENA | +				LCD_FRAME_DONE;  			lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);  		}  		reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; @@ -499,6 +520,9 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,  {  	u32 reg; +	if (bpp > 16 && lcd_revision == LCD_VERSION_1) +		return -EINVAL; +  	/* Set the Panel Width */  	/* Pixels per line = (PPL + 1)*16 */  	if (lcd_revision == LCD_VERSION_1) { @@ -542,14 +566,19 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,  	reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);  	if (raster_order)  		reg |= LCD_RASTER_ORDER; -	lcdc_write(reg, LCD_RASTER_CTRL_REG); + +	par->palette_sz = 16 * 2;  	switch (bpp) {  	case 1:  	case 2:  	case 4:  	case 16: -		par->palette_sz = 16 * 2; +		break; +	case 24: +		reg |= LCD_V2_TFT_24BPP_MODE; +	case 32: +		reg |= LCD_V2_TFT_24BPP_UNPACK;  		break;  	case 8: @@ -560,9 +589,12 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,  		return -EINVAL;  	} +	lcdc_write(reg, LCD_RASTER_CTRL_REG); +  	return 0;  } +#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)  static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,  			      unsigned blue, unsigned transp,  			      struct fb_info *info) @@ -578,13 +610,38 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,  	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)  		return 1; -	if (info->var.bits_per_pixel == 4) { -		if (regno > 15) -			return 1; +	if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1) +		return -EINVAL; -		if (info->var.grayscale) { -			pal = regno; -		} else { +	switch (info->fix.visual) { +	case FB_VISUAL_TRUECOLOR: +		red = CNVT_TOHW(red, info->var.red.length); +		green = CNVT_TOHW(green, info->var.green.length); +		blue = CNVT_TOHW(blue, info->var.blue.length); +		break; +	case FB_VISUAL_PSEUDOCOLOR: +		switch (info->var.bits_per_pixel) { +		case 4: +			if (regno > 15) +				return -EINVAL; + +			if (info->var.grayscale) { +				pal = regno; +			} else { +				red >>= 4; +				green >>= 8; +				blue >>= 12; + +				pal = red & 0x0f00; +				pal |= green & 0x00f0; +				pal |= blue & 0x000f; +			} +			if (regno == 0) +				pal |= 0x2000; +			palette[regno] = pal; +			break; + +		case 8:  			red >>= 4;  			green >>= 8;  			blue >>= 12; @@ -592,36 +649,36 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,  			pal = (red & 0x0f00);  			pal |= (green & 0x00f0);  			pal |= (blue & 0x000f); -		} -		if (regno == 0) -			pal |= 0x2000; -		palette[regno] = pal; - -	} else if (info->var.bits_per_pixel == 8) { -		red >>= 4; -		green >>= 8; -		blue >>= 12; - -		pal = (red & 0x0f00); -		pal |= (green & 0x00f0); -		pal |= (blue & 0x000f); -		if (palette[regno] != pal) { -			update_hw = 1; -			palette[regno] = pal; +			if (palette[regno] != pal) { +				update_hw = 1; +				palette[regno] = pal; +			} +			break;  		} -	} else if ((info->var.bits_per_pixel == 16) && regno < 16) { -		red >>= (16 - info->var.red.length); -		red <<= info->var.red.offset; +		break; +	} -		green >>= (16 - info->var.green.length); -		green <<= info->var.green.offset; +	/* Truecolor has hardware independent palette */ +	if (info->fix.visual == FB_VISUAL_TRUECOLOR) { +		u32 v; -		blue >>= (16 - info->var.blue.length); -		blue <<= info->var.blue.offset; +		if (regno > 15) +			return -EINVAL; -		par->pseudo_palette[regno] = red | green | blue; +		v = (red << info->var.red.offset) | +			(green << info->var.green.offset) | +			(blue << info->var.blue.offset); +		switch (info->var.bits_per_pixel) { +		case 16: +			((u16 *) (info->pseudo_palette))[regno] = v; +			break; +		case 24: +		case 32: +			((u32 *) (info->pseudo_palette))[regno] = v; +			break; +		}  		if (palette[0] != 0x4000) {  			update_hw = 1;  			palette[0] = 0x4000; @@ -634,11 +691,12 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,  	return 0;  } +#undef CNVT_TOHW  static void lcd_reset(struct da8xx_fb_par *par)  {  	/* Disable the Raster if previously Enabled */ -	lcd_disable_raster(); +	lcd_disable_raster(false);  	/* DMA has to be disabled */  	lcdc_write(0, LCD_DMA_CTRL_REG); @@ -734,7 +792,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)  	u32 stat = lcdc_read(LCD_MASKED_STAT_REG);  	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { -		lcd_disable_raster(); +		lcd_disable_raster(false);  		lcdc_write(stat, LCD_MASKED_STAT_REG);  		lcd_enable_raster();  	} else if (stat & LCD_PL_LOAD_DONE) { @@ -744,7 +802,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)  		 * interrupt via the following write to the status register. If  		 * this is done after then one gets multiple PL done interrupts.  		 */ -		lcd_disable_raster(); +		lcd_disable_raster(false);  		lcdc_write(stat, LCD_MASKED_STAT_REG); @@ -775,6 +833,14 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)  			par->vsync_flag = 1;  			wake_up_interruptible(&par->vsync_wait);  		} + +		/* Set only when controller is disabled and at the end of +		 * active frame +		 */ +		if (stat & BIT(0)) { +			frame_done_flag = 1; +			wake_up_interruptible(&frame_done_wq); +		}  	}  	lcdc_write(0, LCD_END_OF_INT_IND_REG); @@ -789,7 +855,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)  	u32 reg_ras;  	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { -		lcd_disable_raster(); +		lcd_disable_raster(false);  		lcdc_write(stat, LCD_STAT_REG);  		lcd_enable_raster();  	} else if (stat & LCD_PL_LOAD_DONE) { @@ -799,7 +865,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)  		 * interrupt via the following write to the status register. If  		 * this is done after then one gets multiple PL done interrupts.  		 */ -		lcd_disable_raster(); +		lcd_disable_raster(false);  		lcdc_write(stat, LCD_STAT_REG); @@ -842,6 +908,9 @@ static int fb_check_var(struct fb_var_screeninfo *var,  {  	int err = 0; +	if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1) +		return -EINVAL; +  	switch (var->bits_per_pixel) {  	case 1:  	case 8: @@ -877,6 +946,26 @@ static int fb_check_var(struct fb_var_screeninfo *var,  		var->transp.length = 0;  		var->nonstd = 0;  		break; +	case 24: +		var->red.offset = 16; +		var->red.length = 8; +		var->green.offset = 8; +		var->green.length = 8; +		var->blue.offset = 0; +		var->blue.length = 8; +		var->nonstd = 0; +		break; +	case 32: +		var->transp.offset = 24; +		var->transp.length = 8; +		var->red.offset = 16; +		var->red.length = 8; +		var->green.offset = 8; +		var->green.length = 8; +		var->blue.offset = 0; +		var->blue.length = 8; +		var->nonstd = 0; +		break;  	default:  		err = -EINVAL;  	} @@ -898,9 +987,10 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,  	if (val == CPUFREQ_POSTCHANGE) {  		if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {  			par->lcd_fck_rate = clk_get_rate(par->lcdc_clk); -			lcd_disable_raster(); +			lcd_disable_raster(true);  			lcd_calc_clk_divider(par); -			lcd_enable_raster(); +			if (par->blank == FB_BLANK_UNBLANK) +				lcd_enable_raster();  		}  	} @@ -935,7 +1025,7 @@ static int __devexit fb_remove(struct platform_device *dev)  		if (par->panel_power_ctrl)  			par->panel_power_ctrl(0); -		lcd_disable_raster(); +		lcd_disable_raster(true);  		lcdc_write(0, LCD_RASTER_CTRL_REG);  		/* disable DMA  */ @@ -948,8 +1038,8 @@ static int __devexit fb_remove(struct platform_device *dev)  		dma_free_coherent(NULL, par->vram_size, par->vram_virt,  				  par->vram_phys);  		free_irq(par->irq, par); -		clk_disable(par->lcdc_clk); -		clk_put(par->lcdc_clk); +		pm_runtime_put_sync(&dev->dev); +		pm_runtime_disable(&dev->dev);  		framebuffer_release(info);  		iounmap(da8xx_fb_reg_base);  		release_mem_region(lcdc_regs->start, resource_size(lcdc_regs)); @@ -1051,7 +1141,7 @@ static int cfb_blank(int blank, struct fb_info *info)  		if (par->panel_power_ctrl)  			par->panel_power_ctrl(0); -		lcd_disable_raster(); +		lcd_disable_raster(true);  		break;  	default:  		ret = -EINVAL; @@ -1183,9 +1273,9 @@ static int __devinit fb_probe(struct platform_device *device)  		ret = -ENODEV;  		goto err_ioremap;  	} -	ret = clk_enable(fb_clk); -	if (ret) -		goto err_clk_put; + +	pm_runtime_enable(&device->dev); +	pm_runtime_get_sync(&device->dev);  	/* Determine LCD IP Version */  	switch (lcdc_read(LCD_PID_REG)) { @@ -1213,7 +1303,7 @@ static int __devinit fb_probe(struct platform_device *device)  	if (i == ARRAY_SIZE(known_lcd_panels)) {  		dev_err(&device->dev, "GLCD: No valid panel found\n");  		ret = -ENODEV; -		goto err_clk_disable; +		goto err_pm_runtime_disable;  	} else  		dev_info(&device->dev, "GLCD: Found %s panel\n",  					fb_pdata->type); @@ -1225,7 +1315,7 @@ static int __devinit fb_probe(struct platform_device *device)  	if (!da8xx_fb_info) {  		dev_dbg(&device->dev, "Memory allocation failed for fb_info\n");  		ret = -ENOMEM; -		goto err_clk_disable; +		goto err_pm_runtime_disable;  	}  	par = da8xx_fb_info->par; @@ -1356,8 +1446,10 @@ static int __devinit fb_probe(struct platform_device *device)  	if (lcd_revision == LCD_VERSION_1)  		lcdc_irq_handler = lcdc_irq_handler_rev01; -	else +	else { +		init_waitqueue_head(&frame_done_wq);  		lcdc_irq_handler = lcdc_irq_handler_rev02; +	}  	ret = request_irq(par->irq, lcdc_irq_handler, 0,  			DRIVER_NAME, par); @@ -1385,11 +1477,9 @@ err_release_fb_mem:  err_release_fb:  	framebuffer_release(da8xx_fb_info); -err_clk_disable: -	clk_disable(fb_clk); - -err_clk_put: -	clk_put(fb_clk); +err_pm_runtime_disable: +	pm_runtime_put_sync(&device->dev); +	pm_runtime_disable(&device->dev);  err_ioremap:  	iounmap(da8xx_fb_reg_base); @@ -1401,6 +1491,69 @@ err_request_mem:  }  #ifdef CONFIG_PM +struct lcdc_context { +	u32 clk_enable; +	u32 ctrl; +	u32 dma_ctrl; +	u32 raster_timing_0; +	u32 raster_timing_1; +	u32 raster_timing_2; +	u32 int_enable_set; +	u32 dma_frm_buf_base_addr_0; +	u32 dma_frm_buf_ceiling_addr_0; +	u32 dma_frm_buf_base_addr_1; +	u32 dma_frm_buf_ceiling_addr_1; +	u32 raster_ctrl; +} reg_context; + +static void lcd_context_save(void) +{ +	if (lcd_revision == LCD_VERSION_2) { +		reg_context.clk_enable = lcdc_read(LCD_CLK_ENABLE_REG); +		reg_context.int_enable_set = lcdc_read(LCD_INT_ENABLE_SET_REG); +	} + +	reg_context.ctrl = lcdc_read(LCD_CTRL_REG); +	reg_context.dma_ctrl = lcdc_read(LCD_DMA_CTRL_REG); +	reg_context.raster_timing_0 = lcdc_read(LCD_RASTER_TIMING_0_REG); +	reg_context.raster_timing_1 = lcdc_read(LCD_RASTER_TIMING_1_REG); +	reg_context.raster_timing_2 = lcdc_read(LCD_RASTER_TIMING_2_REG); +	reg_context.dma_frm_buf_base_addr_0 = +		lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); +	reg_context.dma_frm_buf_ceiling_addr_0 = +		lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); +	reg_context.dma_frm_buf_base_addr_1 = +		lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); +	reg_context.dma_frm_buf_ceiling_addr_1 = +		lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); +	reg_context.raster_ctrl = lcdc_read(LCD_RASTER_CTRL_REG); +	return; +} + +static void lcd_context_restore(void) +{ +	if (lcd_revision == LCD_VERSION_2) { +		lcdc_write(reg_context.clk_enable, LCD_CLK_ENABLE_REG); +		lcdc_write(reg_context.int_enable_set, LCD_INT_ENABLE_SET_REG); +	} + +	lcdc_write(reg_context.ctrl, LCD_CTRL_REG); +	lcdc_write(reg_context.dma_ctrl, LCD_DMA_CTRL_REG); +	lcdc_write(reg_context.raster_timing_0, LCD_RASTER_TIMING_0_REG); +	lcdc_write(reg_context.raster_timing_1, LCD_RASTER_TIMING_1_REG); +	lcdc_write(reg_context.raster_timing_2, LCD_RASTER_TIMING_2_REG); +	lcdc_write(reg_context.dma_frm_buf_base_addr_0, +			LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); +	lcdc_write(reg_context.dma_frm_buf_ceiling_addr_0, +			LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); +	lcdc_write(reg_context.dma_frm_buf_base_addr_1, +			LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); +	lcdc_write(reg_context.dma_frm_buf_ceiling_addr_1, +			LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); +	lcdc_write(reg_context.raster_ctrl, LCD_RASTER_CTRL_REG); +	return; +} +  static int fb_suspend(struct platform_device *dev, pm_message_t state)  {  	struct fb_info *info = platform_get_drvdata(dev); @@ -1411,8 +1564,9 @@ static int fb_suspend(struct platform_device *dev, pm_message_t state)  		par->panel_power_ctrl(0);  	fb_set_suspend(info, 1); -	lcd_disable_raster(); -	clk_disable(par->lcdc_clk); +	lcd_disable_raster(true); +	lcd_context_save(); +	pm_runtime_put_sync(&dev->dev);  	console_unlock();  	return 0; @@ -1423,11 +1577,14 @@ static int fb_resume(struct platform_device *dev)  	struct da8xx_fb_par *par = info->par;  	console_lock(); -	clk_enable(par->lcdc_clk); -	lcd_enable_raster(); +	pm_runtime_get_sync(&dev->dev); +	lcd_context_restore(); +	if (par->blank == FB_BLANK_UNBLANK) { +		lcd_enable_raster(); -	if (par->panel_power_ctrl) -		par->panel_power_ctrl(1); +		if (par->panel_power_ctrl) +			par->panel_power_ctrl(1); +	}  	fb_set_suspend(info, 0);  	console_unlock(); diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c index f2c092da84b..755ef3e65ca 100644 --- a/drivers/video/ep93xx-fb.c +++ b/drivers/video/ep93xx-fb.c @@ -529,7 +529,8 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)  	 * any of the framebuffer registers.  	 */  	fbi->res = res; -	fbi->mmio_base = ioremap(res->start, resource_size(res)); +	fbi->mmio_base = devm_ioremap(&pdev->dev, res->start, +				      resource_size(res));  	if (!fbi->mmio_base) {  		err = -ENXIO;  		goto failed_resource; @@ -553,20 +554,20 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)  	if (err == 0) {  		dev_err(info->dev, "No suitable video mode found\n");  		err = -EINVAL; -		goto failed_mode; +		goto failed_resource;  	}  	if (mach_info->setup) {  		err = mach_info->setup(pdev);  		if (err) -			goto failed_mode; +			goto failed_resource;  	}  	err = ep93xxfb_check_var(&info->var, info);  	if (err)  		goto failed_check; -	fbi->clk = clk_get(info->dev, NULL); +	fbi->clk = devm_clk_get(&pdev->dev, NULL);  	if (IS_ERR(fbi->clk)) {  		err = PTR_ERR(fbi->clk);  		fbi->clk = NULL; @@ -578,19 +579,15 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)  	err = register_framebuffer(info);  	if (err) -		goto failed; +		goto failed_check;  	dev_info(info->dev, "registered. Mode = %dx%d-%d\n",  		 info->var.xres, info->var.yres, info->var.bits_per_pixel);  	return 0; -failed: -	clk_put(fbi->clk);  failed_check:  	if (fbi->mach_info->teardown)  		fbi->mach_info->teardown(pdev); -failed_mode: -	iounmap(fbi->mmio_base);  failed_resource:  	ep93xxfb_dealloc_videomem(info);  failed_videomem: @@ -609,8 +606,6 @@ static int __devexit ep93xxfb_remove(struct platform_device *pdev)  	unregister_framebuffer(info);  	clk_disable(fbi->clk); -	clk_put(fbi->clk); -	iounmap(fbi->mmio_base);  	ep93xxfb_dealloc_videomem(info);  	fb_dealloc_cmap(&info->cmap); diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index c6c016a506c..d55470e7541 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c @@ -29,6 +29,9 @@ static int exynos_dp_init_dp(struct exynos_dp_device *dp)  	exynos_dp_swreset(dp); +	exynos_dp_init_analog_param(dp); +	exynos_dp_init_interrupt(dp); +  	/* SW defined function Normal operation */  	exynos_dp_enable_sw_function(dp); @@ -260,7 +263,7 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,  static void exynos_dp_link_start(struct exynos_dp_device *dp)  { -	u8 buf[5]; +	u8 buf[4];  	int lane;  	int lane_count; @@ -295,10 +298,10 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)  	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);  	/* Set RX training pattern */ -	buf[0] = DPCD_SCRAMBLING_DISABLED | -		 DPCD_TRAINING_PATTERN_1;  	exynos_dp_write_byte_to_dpcd(dp, -		DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]); +		DPCD_ADDR_TRAINING_PATTERN_SET, +		DPCD_SCRAMBLING_DISABLED | +		DPCD_TRAINING_PATTERN_1);  	for (lane = 0; lane < lane_count; lane++)  		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 | @@ -308,7 +311,7 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)  		lane_count, buf);  } -static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane) +static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)  {  	int shift = (lane & 1) * 4;  	u8 link_value = link_status[lane>>1]; @@ -316,7 +319,7 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)  	return (link_value >> shift) & 0xf;  } -static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count) +static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)  {  	int lane;  	u8 lane_status; @@ -329,22 +332,23 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)  	return 0;  } -static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count) +static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)  {  	int lane;  	u8 lane_align;  	u8 lane_status; -	lane_align = link_status[2]; +	lane_align = link_align[2];  	if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0)  		return -EINVAL;  	for (lane = 0; lane < lane_count; lane++) { -		lane_status = exynos_dp_get_lane_status(link_status, lane); +		lane_status = exynos_dp_get_lane_status(link_align, lane);  		lane_status &= DPCD_CHANNEL_EQ_BITS;  		if (lane_status != DPCD_CHANNEL_EQ_BITS)  			return -EINVAL;  	} +  	return 0;  } @@ -417,69 +421,17 @@ static unsigned int exynos_dp_get_lane_link_training(  static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)  { -	if (dp->link_train.link_rate == LINK_RATE_2_70GBPS) { -		/* set to reduced bit rate */ -		dp->link_train.link_rate = LINK_RATE_1_62GBPS; -		dev_err(dp->dev, "set to bandwidth %.2x\n", -			dp->link_train.link_rate); -		dp->link_train.lt_state = START; -	} else { -		exynos_dp_training_pattern_dis(dp); -		/* set enhanced mode if available */ -		exynos_dp_set_enhanced_mode(dp); -		dp->link_train.lt_state = FAILED; -	} -} - -static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp, -				u8 adjust_request[2]) -{ -	int lane; -	int lane_count; -	u8 voltage_swing; -	u8 pre_emphasis; -	u8 training_lane; +	exynos_dp_training_pattern_dis(dp); +	exynos_dp_set_enhanced_mode(dp); -	lane_count = dp->link_train.lane_count; -	for (lane = 0; lane < lane_count; lane++) { -		voltage_swing = exynos_dp_get_adjust_request_voltage( -						adjust_request, lane); -		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( -						adjust_request, lane); -		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | -				DPCD_PRE_EMPHASIS_SET(pre_emphasis); - -		if (voltage_swing == VOLTAGE_LEVEL_3 || -		   pre_emphasis == PRE_EMPHASIS_LEVEL_3) { -			training_lane |= DPCD_MAX_SWING_REACHED; -			training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; -		} -		dp->link_train.training_lane[lane] = training_lane; -	} -} - -static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp, -					u8 voltage_swing) -{ -	int lane; -	int lane_count; - -	lane_count = dp->link_train.lane_count; -	for (lane = 0; lane < lane_count; lane++) { -		if (voltage_swing == VOLTAGE_LEVEL_3 || -			dp->link_train.cr_loop[lane] == MAX_CR_LOOP) -			return -EINVAL; -	} -	return 0; +	dp->link_train.lt_state = FAILED;  }  static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)  { -	u8 data; -	u8 link_status[6]; +	u8 link_status[2];  	int lane;  	int lane_count; -	u8 buf[5];  	u8 adjust_request[2];  	u8 voltage_swing; @@ -488,100 +440,154 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)  	usleep_range(100, 101); -	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, -				6, link_status);  	lane_count = dp->link_train.lane_count; +	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, +				2, link_status); +  	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {  		/* set training pattern 2 for EQ */  		exynos_dp_set_training_pattern(dp, TRAINING_PTN2); -		adjust_request[0] = link_status[4]; -		adjust_request[1] = link_status[5]; +		for (lane = 0; lane < lane_count; lane++) { +			exynos_dp_read_bytes_from_dpcd(dp, +					DPCD_ADDR_ADJUST_REQUEST_LANE0_1, +					2, adjust_request); +			voltage_swing = exynos_dp_get_adjust_request_voltage( +							adjust_request, lane); +			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( +							adjust_request, lane); +			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | +					DPCD_PRE_EMPHASIS_SET(pre_emphasis); -		exynos_dp_get_adjust_train(dp, adjust_request); +			if (voltage_swing == VOLTAGE_LEVEL_3) +				training_lane |= DPCD_MAX_SWING_REACHED; +			if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) +				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; -		buf[0] = DPCD_SCRAMBLING_DISABLED | -			 DPCD_TRAINING_PATTERN_2; -		exynos_dp_write_byte_to_dpcd(dp, -			DPCD_ADDR_TRAINING_PATTERN_SET, -			buf[0]); +			dp->link_train.training_lane[lane] = training_lane; -		for (lane = 0; lane < lane_count; lane++) {  			exynos_dp_set_lane_link_training(dp,  				dp->link_train.training_lane[lane],  				lane); -			buf[lane] = dp->link_train.training_lane[lane]; -			exynos_dp_write_byte_to_dpcd(dp, -				DPCD_ADDR_TRAINING_LANE0_SET + lane, -				buf[lane]);  		} -		dp->link_train.lt_state = EQUALIZER_TRAINING; -	} else { -		exynos_dp_read_byte_from_dpcd(dp, -			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, -			&data); -		adjust_request[0] = data; -		exynos_dp_read_byte_from_dpcd(dp, -			DPCD_ADDR_ADJUST_REQUEST_LANE2_3, -			&data); -		adjust_request[1] = data; +		exynos_dp_write_byte_to_dpcd(dp, +			DPCD_ADDR_TRAINING_PATTERN_SET, +			DPCD_SCRAMBLING_DISABLED | +			DPCD_TRAINING_PATTERN_2); + +		exynos_dp_write_bytes_to_dpcd(dp, +			DPCD_ADDR_TRAINING_LANE0_SET, +			lane_count, +			dp->link_train.training_lane); +		dev_info(dp->dev, "Link Training Clock Recovery success\n"); +		dp->link_train.lt_state = EQUALIZER_TRAINING; +	} else {  		for (lane = 0; lane < lane_count; lane++) {  			training_lane = exynos_dp_get_lane_link_training(  							dp, lane); +			exynos_dp_read_bytes_from_dpcd(dp, +					DPCD_ADDR_ADJUST_REQUEST_LANE0_1, +					2, adjust_request);  			voltage_swing = exynos_dp_get_adjust_request_voltage(  							adjust_request, lane);  			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(  							adjust_request, lane); -			if ((DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing) && -			    (DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis)) -				dp->link_train.cr_loop[lane]++; -			dp->link_train.training_lane[lane] = training_lane; -		} -		if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) { -			exynos_dp_reduce_link_rate(dp); -		} else { -			exynos_dp_get_adjust_train(dp, adjust_request); +			if (voltage_swing == VOLTAGE_LEVEL_3 || +			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) { +				dev_err(dp->dev, "voltage or pre emphasis reached max level\n"); +				goto reduce_link_rate; +			} -			for (lane = 0; lane < lane_count; lane++) { -				exynos_dp_set_lane_link_training(dp, -					dp->link_train.training_lane[lane], -					lane); -				buf[lane] = dp->link_train.training_lane[lane]; -				exynos_dp_write_byte_to_dpcd(dp, -					DPCD_ADDR_TRAINING_LANE0_SET + lane, -					buf[lane]); +			if ((DPCD_VOLTAGE_SWING_GET(training_lane) == +					voltage_swing) && +			   (DPCD_PRE_EMPHASIS_GET(training_lane) == +					pre_emphasis)) { +				dp->link_train.cr_loop[lane]++; +				if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) { +					dev_err(dp->dev, "CR Max loop\n"); +					goto reduce_link_rate; +				}  			} + +			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | +					DPCD_PRE_EMPHASIS_SET(pre_emphasis); + +			if (voltage_swing == VOLTAGE_LEVEL_3) +				training_lane |= DPCD_MAX_SWING_REACHED; +			if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) +				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; + +			dp->link_train.training_lane[lane] = training_lane; + +			exynos_dp_set_lane_link_training(dp, +				dp->link_train.training_lane[lane], lane);  		} + +		exynos_dp_write_bytes_to_dpcd(dp, +			DPCD_ADDR_TRAINING_LANE0_SET, +			lane_count, +			dp->link_train.training_lane);  	}  	return 0; + +reduce_link_rate: +	exynos_dp_reduce_link_rate(dp); +	return -EIO;  }  static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)  { -	u8 link_status[6]; +	u8 link_status[2]; +	u8 link_align[3];  	int lane;  	int lane_count; -	u8 buf[5];  	u32 reg;  	u8 adjust_request[2]; +	u8 voltage_swing; +	u8 pre_emphasis; +	u8 training_lane;  	usleep_range(400, 401); -	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, -				6, link_status);  	lane_count = dp->link_train.lane_count; +	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, +				2, link_status); +  	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { -		adjust_request[0] = link_status[4]; -		adjust_request[1] = link_status[5]; +		link_align[0] = link_status[0]; +		link_align[1] = link_status[1]; + +		exynos_dp_read_byte_from_dpcd(dp, +			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, +			&link_align[2]); + +		for (lane = 0; lane < lane_count; lane++) { +			exynos_dp_read_bytes_from_dpcd(dp, +					DPCD_ADDR_ADJUST_REQUEST_LANE0_1, +					2, adjust_request); +			voltage_swing = exynos_dp_get_adjust_request_voltage( +							adjust_request, lane); +			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( +							adjust_request, lane); +			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | +					DPCD_PRE_EMPHASIS_SET(pre_emphasis); -		if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) { +			if (voltage_swing == VOLTAGE_LEVEL_3) +				training_lane |= DPCD_MAX_SWING_REACHED; +			if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) +				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED; + +			dp->link_train.training_lane[lane] = training_lane; +		} + +		if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) {  			/* traing pattern Set to Normal */  			exynos_dp_training_pattern_dis(dp); @@ -596,39 +602,42 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)  			dp->link_train.lane_count = reg;  			dev_dbg(dp->dev, "final lane count = %.2x\n",  				dp->link_train.lane_count); +  			/* set enhanced mode if available */  			exynos_dp_set_enhanced_mode(dp); -  			dp->link_train.lt_state = FINISHED;  		} else {  			/* not all locked */  			dp->link_train.eq_loop++;  			if (dp->link_train.eq_loop > MAX_EQ_LOOP) { -				exynos_dp_reduce_link_rate(dp); -			} else { -				exynos_dp_get_adjust_train(dp, adjust_request); - -				for (lane = 0; lane < lane_count; lane++) { -					exynos_dp_set_lane_link_training(dp, -						dp->link_train.training_lane[lane], -						lane); -					buf[lane] = dp->link_train.training_lane[lane]; -					exynos_dp_write_byte_to_dpcd(dp, -						DPCD_ADDR_TRAINING_LANE0_SET + lane, -						buf[lane]); -				} +				dev_err(dp->dev, "EQ Max loop\n"); +				goto reduce_link_rate;  			} + +			for (lane = 0; lane < lane_count; lane++) +				exynos_dp_set_lane_link_training(dp, +					dp->link_train.training_lane[lane], +					lane); + +			exynos_dp_write_bytes_to_dpcd(dp, +				DPCD_ADDR_TRAINING_LANE0_SET, +				lane_count, +				dp->link_train.training_lane);  		}  	} else { -		exynos_dp_reduce_link_rate(dp); +		goto reduce_link_rate;  	}  	return 0; + +reduce_link_rate: +	exynos_dp_reduce_link_rate(dp); +	return -EIO;  }  static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, -			u8 *bandwidth) +					u8 *bandwidth)  {  	u8 data; @@ -641,7 +650,7 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,  }  static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, -			u8 *lane_count) +					u8 *lane_count)  {  	u8 data; @@ -693,13 +702,7 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,  static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)  {  	int retval = 0; -	int training_finished; - -	/* Turn off unnecessary lane */ -	if (dp->link_train.lane_count == 1) -		exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1); - -	training_finished = 0; +	int training_finished = 0;  	dp->link_train.lt_state = START; @@ -710,10 +713,14 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)  			exynos_dp_link_start(dp);  			break;  		case CLOCK_RECOVERY: -			exynos_dp_process_clock_recovery(dp); +			retval = exynos_dp_process_clock_recovery(dp); +			if (retval) +				dev_err(dp->dev, "LT CR failed!\n");  			break;  		case EQUALIZER_TRAINING: -			exynos_dp_process_equalizer_training(dp); +			retval = exynos_dp_process_equalizer_training(dp); +			if (retval) +				dev_err(dp->dev, "LT EQ failed!\n");  			break;  		case FINISHED:  			training_finished = 1; @@ -872,40 +879,33 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)  	dp->dev = &pdev->dev; -	dp->clock = clk_get(&pdev->dev, "dp"); +	dp->clock = devm_clk_get(&pdev->dev, "dp");  	if (IS_ERR(dp->clock)) {  		dev_err(&pdev->dev, "failed to get clock\n");  		return PTR_ERR(dp->clock);  	} -	clk_enable(dp->clock); +	clk_prepare_enable(dp->clock);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(&pdev->dev, "failed to get registers\n"); -		ret = -EINVAL; -		goto err_clock; -	}  	dp->reg_base = devm_request_and_ioremap(&pdev->dev, res);  	if (!dp->reg_base) {  		dev_err(&pdev->dev, "failed to ioremap\n"); -		ret = -ENOMEM; -		goto err_clock; +		return -ENOMEM;  	}  	dp->irq = platform_get_irq(pdev, 0);  	if (!dp->irq) {  		dev_err(&pdev->dev, "failed to get irq\n"); -		ret = -ENODEV; -		goto err_clock; +		return -ENODEV;  	}  	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,  				"exynos-dp", dp);  	if (ret) {  		dev_err(&pdev->dev, "failed to request irq\n"); -		goto err_clock; +		return ret;  	}  	dp->video_info = pdata->video_info; @@ -917,7 +917,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)  	ret = exynos_dp_detect_hpd(dp);  	if (ret) {  		dev_err(&pdev->dev, "unable to detect hpd\n"); -		goto err_clock; +		return ret;  	}  	exynos_dp_handle_edid(dp); @@ -926,7 +926,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)  				dp->video_info->link_rate);  	if (ret) {  		dev_err(&pdev->dev, "unable to do link train\n"); -		goto err_clock; +		return ret;  	}  	exynos_dp_enable_scramble(dp, 1); @@ -940,17 +940,12 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)  	ret = exynos_dp_config_video(dp, dp->video_info);  	if (ret) {  		dev_err(&pdev->dev, "unable to config video\n"); -		goto err_clock; +		return ret;  	}  	platform_set_drvdata(pdev, dp);  	return 0; - -err_clock: -	clk_put(dp->clock); - -	return ret;  }  static int __devexit exynos_dp_remove(struct platform_device *pdev) @@ -961,8 +956,7 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)  	if (pdata && pdata->phy_exit)  		pdata->phy_exit(); -	clk_disable(dp->clock); -	clk_put(dp->clock); +	clk_disable_unprepare(dp->clock);  	return 0;  } @@ -977,7 +971,7 @@ static int exynos_dp_suspend(struct device *dev)  	if (pdata && pdata->phy_exit)  		pdata->phy_exit(); -	clk_disable(dp->clock); +	clk_disable_unprepare(dp->clock);  	return 0;  } @@ -991,7 +985,7 @@ static int exynos_dp_resume(struct device *dev)  	if (pdata && pdata->phy_init)  		pdata->phy_init(); -	clk_enable(dp->clock); +	clk_prepare_enable(dp->clock);  	exynos_dp_init_dp(dp); diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h index 8526e548c38..57b8a6531c0 100644 --- a/drivers/video/exynos/exynos_dp_core.h +++ b/drivers/video/exynos/exynos_dp_core.h @@ -43,7 +43,7 @@ void exynos_dp_init_interrupt(struct exynos_dp_device *dp);  void exynos_dp_reset(struct exynos_dp_device *dp);  void exynos_dp_swreset(struct exynos_dp_device *dp);  void exynos_dp_config_interrupt(struct exynos_dp_device *dp); -u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); +enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);  void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);  void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,  				enum analog_power_block block, @@ -105,7 +105,7 @@ u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);  u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);  u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);  void exynos_dp_reset_macro(struct exynos_dp_device *dp); -int exynos_dp_init_video(struct exynos_dp_device *dp); +void exynos_dp_init_video(struct exynos_dp_device *dp);  void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,  				u32 color_depth, @@ -144,7 +144,7 @@ void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);  #define DPCD_ADDR_TRAINING_PATTERN_SET		0x0102  #define DPCD_ADDR_TRAINING_LANE0_SET		0x0103  #define DPCD_ADDR_LANE0_1_STATUS		0x0202 -#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED	0x0204 +#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED	0x0204  #define DPCD_ADDR_ADJUST_REQUEST_LANE0_1	0x0206  #define DPCD_ADDR_ADJUST_REQUEST_LANE2_3	0x0207  #define DPCD_ADDR_TEST_REQUEST			0x0218 diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c index 2db5b9aa250..3f5ca8a0d5e 100644 --- a/drivers/video/exynos/exynos_dp_reg.c +++ b/drivers/video/exynos/exynos_dp_reg.c @@ -77,7 +77,7 @@ void exynos_dp_init_analog_param(struct exynos_dp_device *dp)  	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);  	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | -		TX_CUR1_2X | TX_CUR_8_MA; +		TX_CUR1_2X | TX_CUR_16_MA;  	writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);  	reg = CH3_AMP_400_MV | CH2_AMP_400_MV | @@ -148,9 +148,6 @@ void exynos_dp_reset(struct exynos_dp_device *dp)  	writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);  	writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); - -	exynos_dp_init_analog_param(dp); -	exynos_dp_init_interrupt(dp);  }  void exynos_dp_swreset(struct exynos_dp_device *dp) @@ -179,7 +176,7 @@ void exynos_dp_config_interrupt(struct exynos_dp_device *dp)  	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);  } -u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp) +enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)  {  	u32 reg; @@ -401,6 +398,7 @@ int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)  {  	int reg;  	int retval = 0; +	int timeout_loop = 0;  	/* Enable AUX CH operation */  	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); @@ -409,8 +407,15 @@ int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)  	/* Is AUX CH command reply received? */  	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); -	while (!(reg & RPLY_RECEIV)) +	while (!(reg & RPLY_RECEIV)) { +		timeout_loop++; +		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { +			dev_err(dp->dev, "AUX CH command reply failed!\n"); +			return -ETIMEDOUT; +		}  		reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); +		usleep_range(10, 11); +	}  	/* Clear interrupt source for AUX CH command reply */  	writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA); @@ -471,7 +476,8 @@ int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,  		if (retval == 0)  			break;  		else -			dev_err(dp->dev, "Aux Transaction fail!\n"); +			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", +				__func__);  	}  	return retval; @@ -511,7 +517,8 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,  		if (retval == 0)  			break;  		else -			dev_err(dp->dev, "Aux Transaction fail!\n"); +			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", +				__func__);  	}  	/* Read data buffer */ @@ -575,7 +582,8 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,  			if (retval == 0)  				break;  			else -				dev_err(dp->dev, "Aux Transaction fail!\n"); +				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", +					__func__);  		}  		start_offset += cur_data_count; @@ -632,7 +640,8 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,  			if (retval == 0)  				break;  			else -				dev_err(dp->dev, "Aux Transaction fail!\n"); +				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", +					__func__);  		}  		for (cur_data_idx = 0; cur_data_idx < cur_data_count; @@ -677,7 +686,7 @@ int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,  	/* Start AUX transaction */  	retval = exynos_dp_start_aux_transaction(dp);  	if (retval != 0) -		dev_err(dp->dev, "Aux Transaction fail!\n"); +		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);  	return retval;  } @@ -717,7 +726,8 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,  		if (retval == 0)  			break;  		else -			dev_err(dp->dev, "Aux Transaction fail!\n"); +			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", +				__func__);  	}  	/* Read data */ @@ -777,7 +787,9 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,  				if (retval == 0)  					break;  				else -					dev_err(dp->dev, "Aux Transaction fail!\n"); +					dev_dbg(dp->dev, +						"%s: Aux Transaction fail!\n", +						__func__);  			}  			/* Check if Rx sends defer */  			reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM); @@ -883,7 +895,9 @@ void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)  {  	u32 reg; -	reg = level << PRE_EMPHASIS_SET_SHIFT; +	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); +	reg &= ~PRE_EMPHASIS_SET_MASK; +	reg |= level << PRE_EMPHASIS_SET_SHIFT;  	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);  } @@ -891,7 +905,9 @@ void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)  {  	u32 reg; -	reg = level << PRE_EMPHASIS_SET_SHIFT; +	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); +	reg &= ~PRE_EMPHASIS_SET_MASK; +	reg |= level << PRE_EMPHASIS_SET_SHIFT;  	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);  } @@ -899,7 +915,9 @@ void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)  {  	u32 reg; -	reg = level << PRE_EMPHASIS_SET_SHIFT; +	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); +	reg &= ~PRE_EMPHASIS_SET_MASK; +	reg |= level << PRE_EMPHASIS_SET_SHIFT;  	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);  } @@ -907,7 +925,9 @@ void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)  {  	u32 reg; -	reg = level << PRE_EMPHASIS_SET_SHIFT; +	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); +	reg &= ~PRE_EMPHASIS_SET_MASK; +	reg |= level << PRE_EMPHASIS_SET_SHIFT;  	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);  } @@ -994,7 +1014,7 @@ void exynos_dp_reset_macro(struct exynos_dp_device *dp)  	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);  } -int exynos_dp_init_video(struct exynos_dp_device *dp) +void exynos_dp_init_video(struct exynos_dp_device *dp)  {  	u32 reg; @@ -1012,8 +1032,6 @@ int exynos_dp_init_video(struct exynos_dp_device *dp)  	reg = VID_HRES_TH(2) | VID_VRES_TH(0);  	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8); - -	return 0;  }  void exynos_dp_set_video_color_format(struct exynos_dp_device *dp, diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h index 125b27cd57a..1f2f014cfe8 100644 --- a/drivers/video/exynos/exynos_dp_reg.h +++ b/drivers/video/exynos/exynos_dp_reg.h @@ -187,7 +187,7 @@  #define PD_RING_OSC				(0x1 << 6)  #define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)  #define TX_CUR1_2X				(0x1 << 2) -#define TX_CUR_8_MA				(0x2 << 0) +#define TX_CUR_16_MA				(0x3 << 0)  /* EXYNOS_DP_TX_AMP_TUNING_CTL */  #define CH3_AMP_400_MV				(0x0 << 24) @@ -285,6 +285,7 @@  #define SW_TRAINING_PATTERN_SET_NORMAL		(0x0 << 0)  /* EXYNOS_DP_LN0_LINK_TRAINING_CTL */ +#define PRE_EMPHASIS_SET_MASK			(0x3 << 3)  #define PRE_EMPHASIS_SET_SHIFT			(3)  /* EXYNOS_DP_DEBUG_CTL */ diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index 663c308d0e7..07d70a3a628 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -205,7 +205,8 @@ int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)  	return 0;  } -struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv) +static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device( +					struct mipi_dsim_lcd_driver *lcd_drv)  {  	struct mipi_dsim_ddi *dsim_ddi, *next;  	struct mipi_dsim_lcd_device *lcd_dev; @@ -265,7 +266,8 @@ int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)  } -struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim, +static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi( +						struct mipi_dsim_device *dsim,  						const char *name)  {  	struct mipi_dsim_ddi *dsim_ddi, *next; @@ -373,6 +375,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)  	dsim->clock = clk_get(&pdev->dev, "dsim0");  	if (IS_ERR(dsim->clock)) {  		dev_err(&pdev->dev, "failed to get dsim clock source\n"); +		ret = -ENODEV;  		goto err_clock_get;  	} @@ -381,6 +384,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) {  		dev_err(&pdev->dev, "failed to get io memory region\n"); +		ret = -ENODEV;  		goto err_platform_get;  	} @@ -405,6 +409,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)  	dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);  	if (!dsim_ddi) {  		dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n"); +		ret = -EINVAL;  		goto err_bind;  	} diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c index 47b533a183b..3cd29a4fc10 100644 --- a/drivers/video/exynos/exynos_mipi_dsi_common.c +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c @@ -79,11 +79,6 @@ irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)  	struct mipi_dsim_device *dsim = dev_id;  	unsigned int intsrc, intmsk; -	if (dsim == NULL) { -		dev_err(dsim->dev, "%s: wrong parameter\n", __func__); -		return IRQ_NONE; -	} -  	intsrc = exynos_mipi_dsi_read_interrupt(dsim);  	intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);  	intmsk = ~intmsk & intsrc; @@ -288,9 +283,6 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,  		mutex_unlock(&dsim->lock);  		return -EINVAL;  	} - -	mutex_unlock(&dsim->lock); -	return 0;  }  static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim, diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 458c00664ad..ede9e55413f 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -1501,8 +1501,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)  	unsigned int i;  	int ret; -	data = dma_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data), -				  &dma_addr, GFP_DMA | __GFP_ZERO); +	data = dmam_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data), +				   &dma_addr, GFP_DMA | __GFP_ZERO);  	if (!data)  		return -ENOMEM;  	data->dma_addr = dma_addr; @@ -1628,9 +1628,6 @@ error:  	iounmap(data->diu_reg); -	dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data, -			  data->dma_addr); -  	return ret;  } @@ -1648,9 +1645,6 @@ static int fsl_diu_remove(struct platform_device *pdev)  	iounmap(data->diu_reg); -	dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data, -			  data->dma_addr); -  	return 0;  } diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 05e2a8a99d8..3dad31975db 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -20,6 +20,7 @@  #include <linux/kernel.h>  #include <linux/mm.h>  #include <linux/module.h> +#include <linux/io.h>  #ifdef CONFIG_X86  #include <asm/mtrr.h> @@ -28,7 +29,6 @@  #include <asm/addrspace.h>  #endif  #include <asm/byteorder.h> -#include <asm/io.h>  #include <asm/tlbflush.h>  #include <video/gbe.h> @@ -1156,7 +1156,8 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)  		goto out_release_framebuffer;  	} -	gbe = (struct sgi_gbe *) ioremap(GBE_BASE, sizeof(struct sgi_gbe)); +	gbe = (struct sgi_gbe *) devm_ioremap(&p_dev->dev, GBE_BASE, +					      sizeof(struct sgi_gbe));  	if (!gbe) {  		printk(KERN_ERR "gbefb: couldn't map mmio region\n");  		ret = -ENXIO; @@ -1170,12 +1171,13 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)  	if (!gbe_tiles.cpu) {  		printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");  		ret = -ENOMEM; -		goto out_unmap; +		goto out_release_mem_region;  	}  	if (gbe_mem_phys) {  		/* memory was allocated at boot time */ -		gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size); +		gbe_mem = devm_ioremap_nocache(&p_dev->dev, gbe_mem_phys, +					       gbe_mem_size);  		if (!gbe_mem) {  			printk(KERN_ERR "gbefb: couldn't map framebuffer\n");  			ret = -ENOMEM; @@ -1241,13 +1243,9 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)  out_gbe_unmap:  	if (gbe_dma_addr)  		dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys); -	else -		iounmap(gbe_mem);  out_tiles_free:  	dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),  			  (void *)gbe_tiles.cpu, gbe_tiles.dma); -out_unmap: -	iounmap(gbe);  out_release_mem_region:  	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));  out_release_framebuffer: @@ -1264,12 +1262,9 @@ static int __devexit gbefb_remove(struct platform_device* p_dev)  	gbe_turn_off();  	if (gbe_dma_addr)  		dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys); -	else -		iounmap(gbe_mem);  	dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),  			  (void *)gbe_tiles.cpu, gbe_tiles.dma);  	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); -	iounmap(gbe);  	gbefb_remove_sysfs(&p_dev->dev);  	framebuffer_release(info); diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index ebf8495ff19..7324865f965 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -210,6 +210,7 @@ static int __devinit hpfb_init_one(unsigned long phys_base,  				   unsigned long virt_base)  {  	unsigned long fboff, fb_width, fb_height, fb_start; +	int ret;  	fb_regs = virt_base;  	fboff = (in_8(fb_regs + HPFB_FBOMSB) << 8) | in_8(fb_regs + HPFB_FBOLSB); @@ -290,19 +291,29 @@ static int __devinit hpfb_init_one(unsigned long phys_base,  	fb_info.var   = hpfb_defined;  	fb_info.screen_base = (char *)fb_start; -	fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0); +	ret = fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0); +	if (ret < 0) +		goto unmap_screen_base; -	if (register_framebuffer(&fb_info) < 0) { -		fb_dealloc_cmap(&fb_info.cmap); -		iounmap(fb_info.screen_base); -		fb_info.screen_base = NULL; -		return 1; -	} +	ret = register_framebuffer(&fb_info); +	if (ret < 0) +		goto dealloc_cmap;  	printk(KERN_INFO "fb%d: %s frame buffer device\n",  	       fb_info.node, fb_info.fix.id);  	return 0; + +dealloc_cmap: +	fb_dealloc_cmap(&fb_info.cmap); + +unmap_screen_base: +	if (fb_info.screen_base) { +		iounmap(fb_info.screen_base); +		fb_info.screen_base = NULL; +	} + +	return ret;  }  /*  @@ -345,6 +356,9 @@ static void __devexit hpfb_remove_one(struct dio_dev *d)  	if (d->scode >= DIOII_SCBASE)  		iounmap((void *)fb_regs);  	release_mem_region(d->resource.start, resource_size(&d->resource)); +	fb_dealloc_cmap(&fb_info.cmap); +	if (fb_info.screen_base) +		iounmap(fb_info.screen_base);  }  static struct dio_device_id hpfb_dio_tbl[] = { diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 53ffdfc82a7..cf2688de083 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -803,6 +803,7 @@ static int __init imxfb_probe(struct platform_device *pdev)  	fbi->regs = ioremap(res->start, resource_size(res));  	if (fbi->regs == NULL) {  		dev_err(&pdev->dev, "Cannot map frame buffer registers\n"); +		ret = -ENOMEM;  		goto failed_ioremap;  	} diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c index 3c63fc24bb1..4d25711b998 100644 --- a/drivers/video/jz4740_fb.c +++ b/drivers/video/jz4740_fb.c @@ -632,23 +632,10 @@ static int __devinit jzfb_probe(struct platform_device *pdev)  		return -ENXIO;  	} -	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!mem) { -		dev_err(&pdev->dev, "Failed to get register memory resource\n"); -		return -ENXIO; -	} - -	mem = request_mem_region(mem->start, resource_size(mem), pdev->name); -	if (!mem) { -		dev_err(&pdev->dev, "Failed to request register memory region\n"); -		return -EBUSY; -	} -  	fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);  	if (!fb) {  		dev_err(&pdev->dev, "Failed to allocate framebuffer device\n"); -		ret = -ENOMEM; -		goto err_release_mem_region; +		return -ENOMEM;  	}  	fb->fbops = &jzfb_ops; @@ -657,27 +644,26 @@ static int __devinit jzfb_probe(struct platform_device *pdev)  	jzfb = fb->par;  	jzfb->pdev = pdev;  	jzfb->pdata = pdata; -	jzfb->mem = mem; -	jzfb->ldclk = clk_get(&pdev->dev, "lcd"); +	jzfb->ldclk = devm_clk_get(&pdev->dev, "lcd");  	if (IS_ERR(jzfb->ldclk)) {  		ret = PTR_ERR(jzfb->ldclk);  		dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);  		goto err_framebuffer_release;  	} -	jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk"); +	jzfb->lpclk = devm_clk_get(&pdev->dev, "lcd_pclk");  	if (IS_ERR(jzfb->lpclk)) {  		ret = PTR_ERR(jzfb->lpclk);  		dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret); -		goto err_put_ldclk; +		goto err_framebuffer_release;  	} -	jzfb->base = ioremap(mem->start, resource_size(mem)); +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	jzfb->base = devm_request_and_ioremap(&pdev->dev, mem);  	if (!jzfb->base) { -		dev_err(&pdev->dev, "Failed to ioremap register memory region\n");  		ret = -EBUSY; -		goto err_put_lpclk; +		goto err_framebuffer_release;  	}  	platform_set_drvdata(pdev, jzfb); @@ -693,7 +679,7 @@ static int __devinit jzfb_probe(struct platform_device *pdev)  	ret = jzfb_alloc_devmem(jzfb);  	if (ret) {  		dev_err(&pdev->dev, "Failed to allocate video memory\n"); -		goto err_iounmap; +		goto err_framebuffer_release;  	}  	fb->fix = jzfb_fix; @@ -734,16 +720,8 @@ err_free_devmem:  	fb_dealloc_cmap(&fb->cmap);  	jzfb_free_devmem(jzfb); -err_iounmap: -	iounmap(jzfb->base); -err_put_lpclk: -	clk_put(jzfb->lpclk); -err_put_ldclk: -	clk_put(jzfb->ldclk);  err_framebuffer_release:  	framebuffer_release(fb); -err_release_mem_region: -	release_mem_region(mem->start, resource_size(mem));  	return ret;  } @@ -756,17 +734,11 @@ static int __devexit jzfb_remove(struct platform_device *pdev)  	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));  	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); -	iounmap(jzfb->base); -	release_mem_region(jzfb->mem->start, resource_size(jzfb->mem)); -  	fb_dealloc_cmap(&jzfb->fb->cmap);  	jzfb_free_devmem(jzfb);  	platform_set_drvdata(pdev, NULL); -	clk_put(jzfb->lpclk); -	clk_put(jzfb->ldclk); -  	framebuffer_release(jzfb->fb);  	return 0; diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index 57d940be5f3..d68e332aa21 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c @@ -1052,12 +1052,14 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,  		break;  	default:  		/* should never occur */ +		ret = -EIO;  		goto rel_reg;  	}  	par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);  	if (par->fb_base == NULL) {  		dev_err(dev, "Cannot map framebuffer\n"); +		ret = -EIO;  		goto rel_reg;  	} @@ -1073,11 +1075,13 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,  	dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",  		(unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len); -	if (mb862xx_pci_gdc_init(par)) +	ret = mb862xx_pci_gdc_init(par); +	if (ret)  		goto io_unmap; -	if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED, -			DRV_NAME, (void *)par)) { +	ret = request_irq(par->irq, mb862xx_intr, IRQF_SHARED, +			  DRV_NAME, (void *)par); +	if (ret) {  		dev_err(dev, "Cannot request irq\n");  		goto io_unmap;  	} diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index 85e4f44bfa6..6563e50413c 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c @@ -26,8 +26,7 @@  #include <linux/module.h>  #include <linux/platform_device.h>  #include <linux/uaccess.h> - -#include <asm/io.h> +#include <linux/io.h>  #include <video/mbxfb.h> @@ -939,8 +938,9 @@ static int __devinit mbxfb_probe(struct platform_device *dev)  	}  	mfbi->reg_phys_addr = mfbi->reg_res->start; -	mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr, -					      res_size(mfbi->reg_req)); +	mfbi->reg_virt_addr = devm_ioremap_nocache(&dev->dev, +						   mfbi->reg_phys_addr, +						   res_size(mfbi->reg_req));  	if (!mfbi->reg_virt_addr) {  		dev_err(&dev->dev, "failed to ioremap Marathon registers\n");  		ret = -EINVAL; @@ -948,12 +948,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev)  	}  	virt_base_2700 = mfbi->reg_virt_addr; -	mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, -					     res_size(mfbi->fb_req)); +	mfbi->fb_virt_addr = devm_ioremap_nocache(&dev->dev, mfbi->fb_phys_addr, +						  res_size(mfbi->fb_req));  	if (!mfbi->fb_virt_addr) {  		dev_err(&dev->dev, "failed to ioremap frame buffer\n");  		ret = -EINVAL; -		goto err4; +		goto err3;  	}  	fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); @@ -971,7 +971,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)  	if (ret < 0) {  		dev_err(&dev->dev, "fb_alloc_cmap failed\n");  		ret = -EINVAL; -		goto err5; +		goto err3;  	}  	platform_set_drvdata(dev, fbi); @@ -996,10 +996,6 @@ static int __devinit mbxfb_probe(struct platform_device *dev)  err6:  	fb_dealloc_cmap(&fbi->cmap); -err5: -	iounmap(mfbi->fb_virt_addr); -err4: -	iounmap(mfbi->reg_virt_addr);  err3:  	release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res));  err2: @@ -1026,10 +1022,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev)  			if (mfbi->platform_remove)  				mfbi->platform_remove(fbi); -			if (mfbi->fb_virt_addr) -				iounmap(mfbi->fb_virt_addr); -			if (mfbi->reg_virt_addr) -				iounmap(mfbi->reg_virt_addr); +  			if (mfbi->reg_req)  				release_mem_region(mfbi->reg_req->start,  						   res_size(mfbi->reg_req)); diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c index bf73f048006..35ac9e8bee6 100644 --- a/drivers/video/msm/mddi.c +++ b/drivers/video/msm/mddi.c @@ -26,9 +26,6 @@  #include <linux/clk.h>  #include <linux/io.h>  #include <linux/sched.h> -#include <mach/msm_iomap.h> -#include <mach/irqs.h> -#include <mach/board.h>  #include <linux/platform_data/video-msm_fb.h>  #include "mddi_hw.h" diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c index d7a5bf84fb2..f96df32e550 100644 --- a/drivers/video/msm/mddi_client_nt35399.c +++ b/drivers/video/msm/mddi_client_nt35399.c @@ -189,8 +189,9 @@ static int mddi_nt35399_probe(struct platform_device *pdev)  	int ret; -	struct panel_info *panel = kzalloc(sizeof(struct panel_info), -					   GFP_KERNEL); +	struct panel_info *panel = devm_kzalloc(&pdev->dev, +						sizeof(struct panel_info), +						GFP_KERNEL);  	printk(KERN_DEBUG "%s: enter.\n", __func__); @@ -233,7 +234,6 @@ static int mddi_nt35399_remove(struct platform_device *pdev)  	struct panel_info *panel = platform_get_drvdata(pdev);  	setup_vsync(panel, 0); -	kfree(panel);  	return 0;  } diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c index 2e0f3bab611..f2566c19e71 100644 --- a/drivers/video/msm/mdp.c +++ b/drivers/video/msm/mdp.c @@ -25,7 +25,6 @@  #include <linux/major.h>  #include <linux/slab.h> -#include <mach/msm_iomap.h>  #include <linux/platform_data/video-msm_fb.h>  #include <linux/platform_device.h>  #include <linux/export.h> diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h index a0bacf581b3..35848d74100 100644 --- a/drivers/video/msm/mdp_hw.h +++ b/drivers/video/msm/mdp_hw.h @@ -15,7 +15,6 @@  #ifndef _MDP_HW_H_  #define _MDP_HW_H_ -#include <mach/msm_iomap.h>  #include <linux/platform_data/video-msm_fb.h>  struct mdp_info { diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index d7381088a18..ce1d452464e 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -1568,7 +1568,8 @@ static int mx3fb_remove(struct platform_device *dev)  static struct platform_driver mx3fb_driver = {  	.driver = { -		   .name = MX3FB_NAME, +		.name = MX3FB_NAME, +		.owner = THIS_MODULE,  	},  	.probe = mx3fb_probe,  	.remove = mx3fb_remove, diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c index 93387555337..475dfee82c4 100644 --- a/drivers/video/nuc900fb.c +++ b/drivers/video/nuc900fb.c @@ -387,7 +387,7 @@ static int nuc900fb_init_registers(struct fb_info *info)   *    The buffer should be a non-cached, non-buffered, memory region   *    to allow palette and pixel writes without flushing the cache.   */ -static int __init nuc900fb_map_video_memory(struct fb_info *info) +static int __devinit nuc900fb_map_video_memory(struct fb_info *info)  {  	struct nuc900fb_info *fbi = info->par;  	dma_addr_t map_dma; diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index 9f1d23c319c..f349ee6f0ce 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c @@ -27,7 +27,6 @@  #include <linux/clk.h>  #include <linux/interrupt.h> -#include <plat/dma.h>  #include "omapfb.h"  #define HWA742_REV_CODE_REG       0x0 diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c index 88c31eb0cd6..ff4fb624b90 100644 --- a/drivers/video/omap/lcd_palmte.c +++ b/drivers/video/omap/lcd_palmte.c @@ -23,7 +23,6 @@  #include <linux/platform_device.h>  #include <linux/io.h> -#include <plat/fpga.h>  #include "omapfb.h"  static int palmte_panel_init(struct lcd_panel *panel, diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index f54b463709e..4351c438b76 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -131,15 +131,6 @@ static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)   * LCD controller and LCD DMA   * ---------------------------------------------------------------------------   */ -/* Lookup table to map elem size to elem type. */ -static const int dma_elem_type[] = { -	0, -	OMAP_DMA_DATA_TYPE_S8, -	OMAP_DMA_DATA_TYPE_S16, -	0, -	OMAP_DMA_DATA_TYPE_S32, -}; -  /*   * Allocate resources needed for LCD controller and LCD DMA operations. Video   * memory is allocated from system memory according to the virtual display diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c index eaeed4340e0..c835aa70f96 100644 --- a/drivers/video/omap2/displays/panel-acx565akm.c +++ b/drivers/video/omap2/displays/panel-acx565akm.c @@ -600,6 +600,9 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)  	mutex_lock(&md->mutex); +	omapdss_sdi_set_timings(dssdev, &dssdev->panel.timings); +	omapdss_sdi_set_datapairs(dssdev, dssdev->phy.sdi.datapairs); +  	r = omapdss_sdi_display_enable(dssdev);  	if (r) {  		pr_err("%s sdi enable failed\n", __func__); @@ -731,18 +734,9 @@ static int acx_panel_resume(struct omap_dss_device *dssdev)  static void acx_panel_set_timings(struct omap_dss_device *dssdev,  		struct omap_video_timings *timings)  { -	int r; - -	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) -		omapdss_sdi_display_disable(dssdev); +	omapdss_sdi_set_timings(dssdev, timings);  	dssdev->panel.timings = *timings; - -	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { -		r = omapdss_sdi_display_enable(dssdev); -		if (r) -			dev_err(&dssdev->dev, "%s enable failed\n", __func__); -	}  }  static int acx_panel_check_timings(struct omap_dss_device *dssdev, diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index bc5af2500eb..88295c52681 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c @@ -545,6 +545,8 @@ struct panel_drv_data {  	struct omap_dss_device *dssdev;  	struct panel_config *panel_config; + +	struct mutex lock;  };  static inline struct panel_generic_dpi_data @@ -563,6 +565,9 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)  	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)  		return 0; +	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings); +	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines); +  	r = omapdss_dpi_display_enable(dssdev);  	if (r)  		goto err0; @@ -634,6 +639,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)  	drv_data->dssdev = dssdev;  	drv_data->panel_config = panel_config; +	mutex_init(&drv_data->lock); +  	dev_set_drvdata(&dssdev->dev, drv_data);  	return 0; @@ -652,56 +659,108 @@ static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)  static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)  { -	int r = 0; +	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); +	int r; + +	mutex_lock(&drv_data->lock);  	r = generic_dpi_panel_power_on(dssdev);  	if (r) -		return r; +		goto err;  	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; +err: +	mutex_unlock(&drv_data->lock); -	return 0; +	return r;  }  static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)  { +	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&drv_data->lock); +  	generic_dpi_panel_power_off(dssdev);  	dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + +	mutex_unlock(&drv_data->lock);  }  static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)  { +	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&drv_data->lock); +  	generic_dpi_panel_power_off(dssdev);  	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; +	mutex_unlock(&drv_data->lock); +  	return 0;  }  static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)  { -	int r = 0; +	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); +	int r; + +	mutex_lock(&drv_data->lock);  	r = generic_dpi_panel_power_on(dssdev);  	if (r) -		return r; +		goto err;  	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; -	return 0; +err: +	mutex_unlock(&drv_data->lock); + +	return r;  }  static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,  		struct omap_video_timings *timings)  { -	dpi_set_timings(dssdev, timings); +	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&drv_data->lock); + +	omapdss_dpi_set_timings(dssdev, timings); + +	dssdev->panel.timings = *timings; + +	mutex_unlock(&drv_data->lock); +} + +static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings) +{ +	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); + +	mutex_lock(&drv_data->lock); + +	*timings = dssdev->panel.timings; + +	mutex_unlock(&drv_data->lock);  }  static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,  		struct omap_video_timings *timings)  { -	return dpi_check_timings(dssdev, timings); +	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); +	int r; + +	mutex_lock(&drv_data->lock); + +	r = dpi_check_timings(dssdev, timings); + +	mutex_unlock(&drv_data->lock); + +	return r;  }  static struct omap_dss_driver dpi_driver = { @@ -714,6 +773,7 @@ static struct omap_dss_driver dpi_driver = {  	.resume		= generic_dpi_panel_resume,  	.set_timings	= generic_dpi_panel_set_timings, +	.get_timings	= generic_dpi_panel_get_timings,  	.check_timings	= generic_dpi_panel_check_timings,  	.driver         = { diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c index 80280779884..90c1cabf244 100644 --- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c +++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c @@ -55,6 +55,9 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)  	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)  		return 0; +	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings); +	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines); +  	r = omapdss_dpi_display_enable(dssdev);  	if (r)  		goto err0; diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c index e6c115373c0..3fc5ad081a2 100644 --- a/drivers/video/omap2/displays/panel-n8x0.c +++ b/drivers/video/omap2/displays/panel-n8x0.c @@ -150,11 +150,17 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,  			BLIZZARD_SRC_WRITE_LCD :  			BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; -	omap_rfbi_configure(dssdev, 16, 8); +	omapdss_rfbi_set_pixel_size(dssdev, 16); +	omapdss_rfbi_set_data_lines(dssdev, 8); + +	omap_rfbi_configure(dssdev);  	blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); -	omap_rfbi_configure(dssdev, 16, 16); +	omapdss_rfbi_set_pixel_size(dssdev, 16); +	omapdss_rfbi_set_data_lines(dssdev, 16); + +	omap_rfbi_configure(dssdev);  }  static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf, @@ -297,6 +303,12 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)  			goto err_plat_en;  	} +	omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res, +		dssdev->panel.timings.y_res); +	omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size); +	omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines); +	omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings); +  	r = omapdss_rfbi_display_enable(dssdev);  	if (r)  		goto err_rfbi_en; @@ -477,6 +489,7 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)  	dssdev->panel.timings.y_res = 480;  	dssdev->ctrl.pixel_size = 16;  	dssdev->ctrl.rfbi_timings = n8x0_panel_timings; +	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;  	memset(&props, 0, sizeof(props));  	props.max_brightness = 127; @@ -625,17 +638,25 @@ 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); +	u16 dw, dh;  	dev_dbg(&dssdev->dev, "update\n"); +	dw = dssdev->panel.timings.x_res; +	dh = dssdev->panel.timings.y_res; + +	if (x != 0 || y != 0 || w != dw || h != dh) { +		dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n", +			x, y, w, h); +		return -EINVAL; +	} +  	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); +	omap_rfbi_update(dssdev, update_done, NULL);  	mutex_unlock(&ddata->lock); diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c index b122b0f31c4..908fd268f3d 100644 --- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c +++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c @@ -175,6 +175,9 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)  	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)  		return 0; +	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings); +	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines); +  	r = omapdss_dpi_display_enable(dssdev);  	if (r)  		goto err0; diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c index 2d35bd38886..9df87640ddd 100644 --- a/drivers/video/omap2/displays/panel-picodlp.c +++ b/drivers/video/omap2/displays/panel-picodlp.c @@ -377,6 +377,10 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)  	 * then only i2c commands can be successfully sent to dpp2600  	 */  	msleep(1000); + +	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings); +	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines); +  	r = omapdss_dpi_display_enable(dssdev);  	if (r) {  		dev_err(&dssdev->dev, "failed to enable DPI\n"); diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c index bd86ba9ccf7..1ec3b277ff1 100644 --- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c @@ -142,6 +142,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)  	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)  		return 0; +	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings); +	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines); +  	r = omapdss_dpi_display_enable(dssdev);  	if (r)  		goto err0; diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 6b5e6e0e202..f2f644680ca 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -121,6 +121,18 @@ struct taal_data {  	struct omap_dss_device *dssdev; +	/* panel specific HW info */ +	struct panel_config *panel_config; + +	/* panel HW configuration from DT or platform data */ +	int reset_gpio; +	int ext_te_gpio; + +	bool use_dsi_backlight; + +	struct omap_dsi_pin_config pin_config; + +	/* runtime variables */  	bool enabled;  	u8 rotate;  	bool mirror; @@ -145,16 +157,8 @@ struct taal_data {  	bool ulps_enabled;  	unsigned ulps_timeout;  	struct delayed_work ulps_work; - -	struct panel_config *panel_config;  }; -static inline struct nokia_dsi_panel_data -*get_panel_data(const struct omap_dss_device *dssdev) -{ -	return (struct nokia_dsi_panel_data *) dssdev->data; -} -  static void taal_esd_work(struct work_struct *work);  static void taal_ulps_work(struct work_struct *work); @@ -371,7 +375,6 @@ static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)  static int taal_enter_ulps(struct omap_dss_device *dssdev)  {  	struct taal_data *td = dev_get_drvdata(&dssdev->dev); -	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);  	int r;  	if (td->ulps_enabled) @@ -383,7 +386,8 @@ static int taal_enter_ulps(struct omap_dss_device *dssdev)  	if (r)  		goto err; -	disable_irq(gpio_to_irq(panel_data->ext_te_gpio)); +	if (gpio_is_valid(td->ext_te_gpio)) +		disable_irq(gpio_to_irq(td->ext_te_gpio));  	omapdss_dsi_display_disable(dssdev, false, true); @@ -405,7 +409,6 @@ err:  static int taal_exit_ulps(struct omap_dss_device *dssdev)  {  	struct taal_data *td = dev_get_drvdata(&dssdev->dev); -	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);  	int r;  	if (!td->ulps_enabled) @@ -425,7 +428,8 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)  		goto err2;  	} -	enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); +	if (gpio_is_valid(td->ext_te_gpio)) +		enable_irq(gpio_to_irq(td->ext_te_gpio));  	taal_queue_ulps_work(dssdev); @@ -438,7 +442,8 @@ err2:  	r = taal_panel_reset(dssdev);  	if (!r) { -		enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); +		if (gpio_is_valid(td->ext_te_gpio)) +			enable_irq(gpio_to_irq(td->ext_te_gpio));  		td->ulps_enabled = false;  	}  err1: @@ -835,94 +840,135 @@ static struct attribute_group taal_attr_group = {  static void taal_hw_reset(struct omap_dss_device *dssdev)  {  	struct taal_data *td = dev_get_drvdata(&dssdev->dev); -	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); -	if (panel_data->reset_gpio == -1) +	if (!gpio_is_valid(td->reset_gpio))  		return; -	gpio_set_value(panel_data->reset_gpio, 1); +	gpio_set_value(td->reset_gpio, 1);  	if (td->panel_config->reset_sequence.high)  		udelay(td->panel_config->reset_sequence.high);  	/* reset the panel */ -	gpio_set_value(panel_data->reset_gpio, 0); +	gpio_set_value(td->reset_gpio, 0);  	/* assert reset */  	if (td->panel_config->reset_sequence.low)  		udelay(td->panel_config->reset_sequence.low); -	gpio_set_value(panel_data->reset_gpio, 1); +	gpio_set_value(td->reset_gpio, 1);  	/* wait after releasing reset */  	if (td->panel_config->sleep.hw_reset)  		msleep(td->panel_config->sleep.hw_reset);  } +static void taal_probe_pdata(struct taal_data *td, +		const struct nokia_dsi_panel_data *pdata) +{ +	td->reset_gpio = pdata->reset_gpio; + +	if (pdata->use_ext_te) +		td->ext_te_gpio = pdata->ext_te_gpio; +	else +		td->ext_te_gpio = -1; + +	td->esd_interval = pdata->esd_interval; +	td->ulps_timeout = pdata->ulps_timeout; + +	td->use_dsi_backlight = pdata->use_dsi_backlight; + +	td->pin_config = pdata->pin_config; +} +  static int taal_probe(struct omap_dss_device *dssdev)  {  	struct backlight_properties props;  	struct taal_data *td;  	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; +	const char *panel_name;  	dev_dbg(&dssdev->dev, "probe\n"); -	if (!panel_data || !panel_data->name) { -		r = -EINVAL; -		goto err; +	td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL); +	if (!td) +		return -ENOMEM; + +	dev_set_drvdata(&dssdev->dev, td); +	td->dssdev = dssdev; + +	if (dssdev->data) { +		const struct nokia_dsi_panel_data *pdata = dssdev->data; + +		taal_probe_pdata(td, pdata); + +		panel_name = pdata->name; +	} else { +		return -ENODEV;  	} +	if (panel_name == NULL) +		return -EINVAL; +  	for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { -		if (strcmp(panel_data->name, panel_configs[i].name) == 0) { -			panel_config = &panel_configs[i]; +		if (strcmp(panel_name, panel_configs[i].name) == 0) { +			td->panel_config = &panel_configs[i];  			break;  		}  	} -	if (!panel_config) { -		r = -EINVAL; -		goto err; -	} +	if (!td->panel_config) +		return -EINVAL; -	dssdev->panel.timings = panel_config->timings; +	dssdev->panel.timings = td->panel_config->timings;  	dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; - -	td = kzalloc(sizeof(*td), GFP_KERNEL); -	if (!td) { -		r = -ENOMEM; -		goto err; -	} -	td->dssdev = dssdev; -	td->panel_config = panel_config; -	td->esd_interval = panel_data->esd_interval; -	td->ulps_enabled = false; -	td->ulps_timeout = panel_data->ulps_timeout; +	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | +		OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;  	mutex_init(&td->lock);  	atomic_set(&td->do_update, 0); -	td->workqueue = create_singlethread_workqueue("taal_esd"); -	if (td->workqueue == NULL) { -		dev_err(&dssdev->dev, "can't create ESD workqueue\n"); -		r = -ENOMEM; -		goto err_wq; +	if (gpio_is_valid(td->reset_gpio)) { +		r = devm_gpio_request_one(&dssdev->dev, td->reset_gpio, +				GPIOF_OUT_INIT_LOW, "taal rst"); +		if (r) { +			dev_err(&dssdev->dev, "failed to request reset gpio\n"); +			return r; +		}  	} -	INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work); -	INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work); -	dev_set_drvdata(&dssdev->dev, td); +	if (gpio_is_valid(td->ext_te_gpio)) { +		r = devm_gpio_request_one(&dssdev->dev, td->ext_te_gpio, +				GPIOF_IN, "taal irq"); +		if (r) { +			dev_err(&dssdev->dev, "GPIO request failed\n"); +			return r; +		} + +		r = devm_request_irq(&dssdev->dev, gpio_to_irq(td->ext_te_gpio), +				taal_te_isr, +				IRQF_TRIGGER_RISING, +				"taal vsync", dssdev); -	if (gpio_is_valid(panel_data->reset_gpio)) { -		r = gpio_request_one(panel_data->reset_gpio, GPIOF_OUT_INIT_LOW, -				"taal rst");  		if (r) { -			dev_err(&dssdev->dev, "failed to request reset gpio\n"); -			goto err_rst_gpio; +			dev_err(&dssdev->dev, "IRQ request failed\n"); +			return r;  		} + +		INIT_DEFERRABLE_WORK(&td->te_timeout_work, +					taal_te_timeout_work_callback); + +		dev_dbg(&dssdev->dev, "Using GPIO TE\n");  	} +	td->workqueue = create_singlethread_workqueue("taal_esd"); +	if (td->workqueue == NULL) { +		dev_err(&dssdev->dev, "can't create ESD workqueue\n"); +		return -ENOMEM; +	} +	INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work); +	INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work); +  	taal_hw_reset(dssdev); -	if (panel_data->use_dsi_backlight) { +	if (td->use_dsi_backlight) {  		memset(&props, 0, sizeof(struct backlight_properties));  		props.max_brightness = 255; @@ -943,31 +989,6 @@ static int taal_probe(struct omap_dss_device *dssdev)  		taal_bl_update_status(bldev);  	} -	if (panel_data->use_ext_te) { -		int gpio = panel_data->ext_te_gpio; - -		r = gpio_request_one(gpio, GPIOF_IN, "taal irq"); -		if (r) { -			dev_err(&dssdev->dev, "GPIO request failed\n"); -			goto err_gpio; -		} - -		r = request_irq(gpio_to_irq(gpio), taal_te_isr, -				IRQF_TRIGGER_RISING, -				"taal vsync", dssdev); - -		if (r) { -			dev_err(&dssdev->dev, "IRQ request failed\n"); -			gpio_free(gpio); -			goto err_irq; -		} - -		INIT_DEFERRABLE_WORK(&td->te_timeout_work, -				     taal_te_timeout_work_callback); - -		dev_dbg(&dssdev->dev, "Using GPIO TE\n"); -	} -  	r = omap_dsi_request_vc(dssdev, &td->channel);  	if (r) {  		dev_err(&dssdev->dev, "failed to get virtual channel\n"); @@ -991,29 +1012,16 @@ static int taal_probe(struct omap_dss_device *dssdev)  err_vc_id:  	omap_dsi_release_vc(dssdev, td->channel);  err_req_vc: -	if (panel_data->use_ext_te) -		free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); -err_irq: -	if (panel_data->use_ext_te) -		gpio_free(panel_data->ext_te_gpio); -err_gpio:  	if (bldev != NULL)  		backlight_device_unregister(bldev);  err_bl: -	if (gpio_is_valid(panel_data->reset_gpio)) -		gpio_free(panel_data->reset_gpio); -err_rst_gpio:  	destroy_workqueue(td->workqueue); -err_wq: -	kfree(td); -err:  	return r;  }  static void __exit taal_remove(struct omap_dss_device *dssdev)  {  	struct taal_data *td = dev_get_drvdata(&dssdev->dev); -	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);  	struct backlight_device *bldev;  	dev_dbg(&dssdev->dev, "remove\n"); @@ -1021,12 +1029,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)  	sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);  	omap_dsi_release_vc(dssdev, td->channel); -	if (panel_data->use_ext_te) { -		int gpio = panel_data->ext_te_gpio; -		free_irq(gpio_to_irq(gpio), dssdev); -		gpio_free(gpio); -	} -  	bldev = td->bldev;  	if (bldev != NULL) {  		bldev->props.power = FB_BLANK_POWERDOWN; @@ -1040,26 +1042,31 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)  	/* reset, to be sure that the panel is in a valid state */  	taal_hw_reset(dssdev); - -	if (gpio_is_valid(panel_data->reset_gpio)) -		gpio_free(panel_data->reset_gpio); - -	kfree(td);  }  static int taal_power_on(struct omap_dss_device *dssdev)  {  	struct taal_data *td = dev_get_drvdata(&dssdev->dev); -	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);  	u8 id1, id2, id3;  	int r; -	r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config); +	r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);  	if (r) {  		dev_err(&dssdev->dev, "failed to configure DSI pins\n");  		goto err0;  	}; +	omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res, +		dssdev->panel.timings.y_res); +	omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888); +	omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE); + +	r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000); +	if (r) { +		dev_err(&dssdev->dev, "failed to set HS and LP clocks\n"); +		goto err0; +	} +  	r = omapdss_dsi_display_enable(dssdev);  	if (r) {  		dev_err(&dssdev->dev, "failed to enable DSI\n"); @@ -1356,7 +1363,6 @@ static int taal_update(struct omap_dss_device *dssdev,  				    u16 x, u16 y, u16 w, u16 h)  {  	struct taal_data *td = dev_get_drvdata(&dssdev->dev); -	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);  	int r;  	dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); @@ -1380,7 +1386,7 @@ static int taal_update(struct omap_dss_device *dssdev,  	if (r)  		goto err; -	if (td->te_enabled && panel_data->use_ext_te) { +	if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {  		schedule_delayed_work(&td->te_timeout_work,  				msecs_to_jiffies(250));  		atomic_set(&td->do_update, 1); @@ -1419,7 +1425,6 @@ static int taal_sync(struct omap_dss_device *dssdev)  static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)  {  	struct taal_data *td = dev_get_drvdata(&dssdev->dev); -	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);  	int r;  	if (enable) @@ -1427,7 +1432,7 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)  	else  		r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF); -	if (!panel_data->use_ext_te) +	if (!gpio_is_valid(td->ext_te_gpio))  		omapdss_dsi_enable_te(dssdev, enable);  	if (td->panel_config->sleep.enable_te) @@ -1487,6 +1492,7 @@ static int taal_get_te(struct omap_dss_device *dssdev)  static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)  {  	struct taal_data *td = dev_get_drvdata(&dssdev->dev); +	u16 dw, dh;  	int r;  	dev_dbg(&dssdev->dev, "rotate %d\n", rotate); @@ -1508,6 +1514,16 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)  			goto err;  	} +	if (rotate == 0 || rotate == 2) { +		dw = dssdev->panel.timings.x_res; +		dh = dssdev->panel.timings.y_res; +	} else { +		dw = dssdev->panel.timings.y_res; +		dh = dssdev->panel.timings.x_res; +	} + +	omapdss_dsi_set_size(dssdev, dw, dh); +  	td->rotate = rotate;  	dsi_bus_unlock(dssdev); @@ -1726,7 +1742,6 @@ static void taal_esd_work(struct work_struct *work)  	struct taal_data *td = container_of(work, struct taal_data,  			esd_work.work);  	struct omap_dss_device *dssdev = td->dssdev; -	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);  	u8 state1, state2;  	int r; @@ -1773,7 +1788,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) { +	if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {  		r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);  		if (r)  			goto err; diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c index 40cc0cfa5d1..383811cf864 100644 --- a/drivers/video/omap2/displays/panel-tfp410.c +++ b/drivers/video/omap2/displays/panel-tfp410.c @@ -65,6 +65,9 @@ static int tfp410_power_on(struct omap_dss_device *dssdev)  	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)  		return 0; +	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings); +	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines); +  	r = omapdss_dpi_display_enable(dssdev);  	if (r)  		goto err0; @@ -116,8 +119,8 @@ static int tfp410_probe(struct omap_dss_device *dssdev)  	}  	if (gpio_is_valid(ddata->pd_gpio)) { -		r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW, -				"tfp410 pd"); +		r = devm_gpio_request_one(&dssdev->dev, ddata->pd_gpio, +				GPIOF_OUT_INIT_LOW, "tfp410 pd");  		if (r) {  			dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",  					ddata->pd_gpio); @@ -132,8 +135,7 @@ static int tfp410_probe(struct omap_dss_device *dssdev)  		if (!adapter) {  			dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",  					i2c_bus_num); -			r = -EINVAL; -			goto err_i2c; +			return -EINVAL;  		}  		ddata->i2c_adapter = adapter; @@ -142,10 +144,6 @@ static int tfp410_probe(struct omap_dss_device *dssdev)  	dev_set_drvdata(&dssdev->dev, ddata);  	return 0; -err_i2c: -	if (gpio_is_valid(ddata->pd_gpio)) -		gpio_free(ddata->pd_gpio); -	return r;  }  static void __exit tfp410_remove(struct omap_dss_device *dssdev) @@ -157,9 +155,6 @@ static void __exit tfp410_remove(struct omap_dss_device *dssdev)  	if (ddata->i2c_adapter)  		i2c_put_adapter(ddata->i2c_adapter); -	if (gpio_is_valid(ddata->pd_gpio)) -		gpio_free(ddata->pd_gpio); -  	dev_set_drvdata(&dssdev->dev, NULL);  	mutex_unlock(&ddata->lock); @@ -231,7 +226,8 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev,  	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);  	mutex_lock(&ddata->lock); -	dpi_set_timings(dssdev, timings); +	omapdss_dpi_set_timings(dssdev, timings); +	dssdev->panel.timings = *timings;  	mutex_unlock(&ddata->lock);  } diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c index fa7baa650ae..b5e6dbc59f0 100644 --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c @@ -337,6 +337,9 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)  	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)  		return 0; +	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings); +	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines); +  	r = omapdss_dpi_display_enable(dssdev);  	if (r)  		goto err0; @@ -480,7 +483,9 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)  static void tpo_td043_set_timings(struct omap_dss_device *dssdev,  		struct omap_video_timings *timings)  { -	dpi_set_timings(dssdev, timings); +	omapdss_dpi_set_timings(dssdev, timings); + +	dssdev->panel.timings = *timings;  }  static int tpo_td043_check_timings(struct omap_dss_device *dssdev, diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index b337a8469fd..80f5390aa13 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -84,7 +84,7 @@ config OMAP2_DSS_SDI  config OMAP2_DSS_DSI  	bool "DSI support" -	depends on ARCH_OMAP3 || ARCH_OMAP4 +	depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5          default n  	help  	  MIPI DSI (Display Serial Interface) support. diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 5c450b0f94d..4549869bfe1 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -1,9 +1,9 @@  obj-$(CONFIG_OMAP2_DSS) += omapdss.o  omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ -	manager.o overlay.o apply.o +	manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o  omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o  omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o -omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o +omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o  omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o  omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o  omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 0fefc68372b..19d66f471b4 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -111,9 +111,6 @@ static struct {  	struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];  	struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS]; -	bool fifo_merge_dirty; -	bool fifo_merge; -  	bool irq_enabled;  } dss_data; @@ -424,17 +421,25 @@ static void wait_pending_extra_info_updates(void)  int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)  {  	unsigned long timeout = msecs_to_jiffies(500); -	struct mgr_priv_data *mp; +	struct mgr_priv_data *mp = get_mgr_priv(mgr);  	u32 irq; +	unsigned long flags;  	int r;  	int i; -	struct omap_dss_device *dssdev = mgr->device; -	if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) +	spin_lock_irqsave(&data_lock, flags); + +	if (mgr_manual_update(mgr)) { +		spin_unlock_irqrestore(&data_lock, flags);  		return 0; +	} -	if (mgr_manual_update(mgr)) +	if (!mp->enabled) { +		spin_unlock_irqrestore(&data_lock, flags);  		return 0; +	} + +	spin_unlock_irqrestore(&data_lock, flags);  	r = dispc_runtime_get();  	if (r) @@ -442,10 +447,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)  	irq = dispc_mgr_get_vsync_irq(mgr->id); -	mp = get_mgr_priv(mgr);  	i = 0;  	while (1) { -		unsigned long flags;  		bool shadow_dirty, dirty;  		spin_lock_irqsave(&data_lock, flags); @@ -489,21 +492,30 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)  {  	unsigned long timeout = msecs_to_jiffies(500);  	struct ovl_priv_data *op; -	struct omap_dss_device *dssdev; +	struct mgr_priv_data *mp;  	u32 irq; +	unsigned long flags;  	int r;  	int i;  	if (!ovl->manager)  		return 0; -	dssdev = ovl->manager->device; +	mp = get_mgr_priv(ovl->manager); + +	spin_lock_irqsave(&data_lock, flags); -	if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) +	if (ovl_manual_update(ovl)) { +		spin_unlock_irqrestore(&data_lock, flags);  		return 0; +	} -	if (ovl_manual_update(ovl)) +	if (!mp->enabled) { +		spin_unlock_irqrestore(&data_lock, flags);  		return 0; +	} + +	spin_unlock_irqrestore(&data_lock, flags);  	r = dispc_runtime_get();  	if (r) @@ -514,7 +526,6 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)  	op = get_ovl_priv(ovl);  	i = 0;  	while (1) { -		unsigned long flags;  		bool shadow_dirty, dirty;  		spin_lock_irqsave(&data_lock, flags); @@ -573,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)  	replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode); -	r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings); +	r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);  	if (r) {  		/*  		 * We can't do much here, as this function can be called from @@ -677,40 +688,11 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)  		mp->shadow_extra_info_dirty = true;  } -static void dss_write_regs_common(void) -{ -	const int num_mgrs = omap_dss_get_num_overlay_managers(); -	int i; - -	if (!dss_data.fifo_merge_dirty) -		return; - -	for (i = 0; i < num_mgrs; ++i) { -		struct omap_overlay_manager *mgr; -		struct mgr_priv_data *mp; - -		mgr = omap_dss_get_overlay_manager(i); -		mp = get_mgr_priv(mgr); - -		if (mp->enabled) { -			if (dss_data.fifo_merge_dirty) { -				dispc_enable_fifomerge(dss_data.fifo_merge); -				dss_data.fifo_merge_dirty = false; -			} - -			if (mp->updating) -				mp->shadow_info_dirty = true; -		} -	} -} -  static void dss_write_regs(void)  {  	const int num_mgrs = omap_dss_get_num_overlay_managers();  	int i; -	dss_write_regs_common(); -  	for (i = 0; i < num_mgrs; ++i) {  		struct omap_overlay_manager *mgr;  		struct mgr_priv_data *mp; @@ -799,8 +781,6 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)  	dss_mgr_write_regs(mgr);  	dss_mgr_write_regs_extra(mgr); -	dss_write_regs_common(); -  	mp->updating = true;  	if (!dss_data.irq_enabled && need_isr()) @@ -984,20 +964,11 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,  	op->extra_info_dirty = true;  } -static void dss_apply_fifo_merge(bool use_fifo_merge) -{ -	if (dss_data.fifo_merge == use_fifo_merge) -		return; - -	dss_data.fifo_merge = use_fifo_merge; -	dss_data.fifo_merge_dirty = true; -} - -static void dss_ovl_setup_fifo(struct omap_overlay *ovl, -		bool use_fifo_merge) +static void dss_ovl_setup_fifo(struct omap_overlay *ovl)  {  	struct ovl_priv_data *op = get_ovl_priv(ovl);  	u32 fifo_low, fifo_high; +	bool use_fifo_merge = false;  	if (!op->enabled && !op->enabling)  		return; @@ -1008,8 +979,7 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl,  	dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);  } -static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr, -		bool use_fifo_merge) +static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)  {  	struct omap_overlay *ovl;  	struct mgr_priv_data *mp; @@ -1020,94 +990,19 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,  		return;  	list_for_each_entry(ovl, &mgr->overlays, list) -		dss_ovl_setup_fifo(ovl, use_fifo_merge); -} - -static void dss_setup_fifos(bool use_fifo_merge) -{ -	const int num_mgrs = omap_dss_get_num_overlay_managers(); -	struct omap_overlay_manager *mgr; -	int i; - -	for (i = 0; i < num_mgrs; ++i) { -		mgr = omap_dss_get_overlay_manager(i); -		dss_mgr_setup_fifos(mgr, use_fifo_merge); -	} +		dss_ovl_setup_fifo(ovl);  } -static int get_num_used_managers(void) +static void dss_setup_fifos(void)  {  	const int num_mgrs = omap_dss_get_num_overlay_managers();  	struct omap_overlay_manager *mgr; -	struct mgr_priv_data *mp;  	int i; -	int enabled_mgrs; - -	enabled_mgrs = 0;  	for (i = 0; i < num_mgrs; ++i) {  		mgr = omap_dss_get_overlay_manager(i); -		mp = get_mgr_priv(mgr); - -		if (!mp->enabled) -			continue; - -		enabled_mgrs++; +		dss_mgr_setup_fifos(mgr);  	} - -	return enabled_mgrs; -} - -static int get_num_used_overlays(void) -{ -	const int num_ovls = omap_dss_get_num_overlays(); -	struct omap_overlay *ovl; -	struct ovl_priv_data *op; -	struct mgr_priv_data *mp; -	int i; -	int enabled_ovls; - -	enabled_ovls = 0; - -	for (i = 0; i < num_ovls; ++i) { -		ovl = omap_dss_get_overlay(i); -		op = get_ovl_priv(ovl); - -		if (!op->enabled && !op->enabling) -			continue; - -		mp = get_mgr_priv(ovl->manager); - -		if (!mp->enabled) -			continue; - -		enabled_ovls++; -	} - -	return enabled_ovls; -} - -static bool get_use_fifo_merge(void) -{ -	int enabled_mgrs = get_num_used_managers(); -	int enabled_ovls = get_num_used_overlays(); - -	if (!dss_has_feature(FEAT_FIFO_MERGE)) -		return false; - -	/* -	 * In theory the only requirement for fifomerge is enabled_ovls <= 1. -	 * However, if we have two managers enabled and set/unset the fifomerge, -	 * we need to set the GO bits in particular sequence for the managers, -	 * and wait in between. -	 * -	 * This is rather difficult as new apply calls can happen at any time, -	 * so we simplify the problem by requiring also that enabled_mgrs <= 1. -	 * In practice this shouldn't matter, because when only one overlay is -	 * enabled, most likely only one output is enabled. -	 */ - -	return enabled_mgrs <= 1 && enabled_ovls <= 1;  }  int dss_mgr_enable(struct omap_overlay_manager *mgr) @@ -1115,7 +1010,6 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)  	struct mgr_priv_data *mp = get_mgr_priv(mgr);  	unsigned long flags;  	int r; -	bool fifo_merge;  	mutex_lock(&apply_lock); @@ -1133,23 +1027,11 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)  		goto err;  	} -	/* step 1: setup fifos/fifomerge before enabling the manager */ - -	fifo_merge = get_use_fifo_merge(); -	dss_setup_fifos(fifo_merge); -	dss_apply_fifo_merge(fifo_merge); +	dss_setup_fifos();  	dss_write_regs();  	dss_set_go_bits(); -	spin_unlock_irqrestore(&data_lock, flags); - -	/* wait until fifo config is in */ -	wait_pending_extra_info_updates(); - -	/* step 2: enable the manager */ -	spin_lock_irqsave(&data_lock, flags); -  	if (!mgr_manual_update(mgr))  		mp->updating = true; @@ -1174,7 +1056,6 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)  {  	struct mgr_priv_data *mp = get_mgr_priv(mgr);  	unsigned long flags; -	bool fifo_merge;  	mutex_lock(&apply_lock); @@ -1189,16 +1070,8 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)  	mp->updating = false;  	mp->enabled = false; -	fifo_merge = get_use_fifo_merge(); -	dss_setup_fifos(fifo_merge); -	dss_apply_fifo_merge(fifo_merge); - -	dss_write_regs(); -	dss_set_go_bits(); -  	spin_unlock_irqrestore(&data_lock, flags); -	wait_pending_extra_info_updates();  out:  	mutex_unlock(&apply_lock);  } @@ -1237,29 +1110,29 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,  	spin_unlock_irqrestore(&data_lock, flags);  } -int dss_mgr_set_device(struct omap_overlay_manager *mgr, -		struct omap_dss_device *dssdev) +int dss_mgr_set_output(struct omap_overlay_manager *mgr, +		struct omap_dss_output *output)  {  	int r;  	mutex_lock(&apply_lock); -	if (dssdev->manager) { -		DSSERR("display '%s' already has a manager '%s'\n", -			       dssdev->name, dssdev->manager->name); +	if (mgr->output) { +		DSSERR("manager %s is already connected to an output\n", +			mgr->name);  		r = -EINVAL;  		goto err;  	} -	if ((mgr->supported_displays & dssdev->type) == 0) { -		DSSERR("display '%s' does not support manager '%s'\n", -			       dssdev->name, mgr->name); +	if ((mgr->supported_outputs & output->id) == 0) { +		DSSERR("output does not support manager %s\n", +			mgr->name);  		r = -EINVAL;  		goto err;  	} -	dssdev->manager = mgr; -	mgr->device = dssdev; +	output->manager = mgr; +	mgr->output = output;  	mutex_unlock(&apply_lock); @@ -1269,40 +1142,46 @@ err:  	return r;  } -int dss_mgr_unset_device(struct omap_overlay_manager *mgr) +int dss_mgr_unset_output(struct omap_overlay_manager *mgr)  {  	int r; +	struct mgr_priv_data *mp = get_mgr_priv(mgr); +	unsigned long flags;  	mutex_lock(&apply_lock); -	if (!mgr->device) { -		DSSERR("failed to unset display, display not set.\n"); +	if (!mgr->output) { +		DSSERR("failed to unset output, output not set\n");  		r = -EINVAL;  		goto err;  	} -	/* -	 * Don't allow currently enabled displays to have the overlay manager -	 * pulled out from underneath them -	 */ -	if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) { +	spin_lock_irqsave(&data_lock, flags); + +	if (mp->enabled) { +		DSSERR("output can't be unset when manager is enabled\n");  		r = -EINVAL; -		goto err; +		goto err1;  	} -	mgr->device->manager = NULL; -	mgr->device = NULL; +	spin_unlock_irqrestore(&data_lock, flags); + +	mgr->output->manager = NULL; +	mgr->output = NULL;  	mutex_unlock(&apply_lock);  	return 0; +err1: +	spin_unlock_irqrestore(&data_lock, flags);  err:  	mutex_unlock(&apply_lock); +  	return r;  }  static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, -		struct omap_video_timings *timings) +		const struct omap_video_timings *timings)  {  	struct mgr_priv_data *mp = get_mgr_priv(mgr); @@ -1311,24 +1190,22 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,  }  void dss_mgr_set_timings(struct omap_overlay_manager *mgr, -		struct omap_video_timings *timings) +		const struct omap_video_timings *timings)  {  	unsigned long flags; - -	mutex_lock(&apply_lock); +	struct mgr_priv_data *mp = get_mgr_priv(mgr);  	spin_lock_irqsave(&data_lock, flags); -	dss_apply_mgr_timings(mgr, timings); - -	dss_write_regs(); -	dss_set_go_bits(); +	if (mp->updating) { +		DSSERR("cannot set timings for %s: manager needs to be disabled\n", +			mgr->name); +		goto out; +	} +	dss_apply_mgr_timings(mgr, timings); +out:  	spin_unlock_irqrestore(&data_lock, flags); - -	wait_pending_extra_info_updates(); - -	mutex_unlock(&apply_lock);  }  static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr, @@ -1346,7 +1223,7 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,  	unsigned long flags;  	struct mgr_priv_data *mp = get_mgr_priv(mgr); -	mutex_lock(&apply_lock); +	spin_lock_irqsave(&data_lock, flags);  	if (mp->enabled) {  		DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n", @@ -1354,19 +1231,9 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,  		goto out;  	} -	spin_lock_irqsave(&data_lock, flags); -  	dss_apply_mgr_lcd_config(mgr, config); - -	dss_write_regs(); -	dss_set_go_bits(); - -	spin_unlock_irqrestore(&data_lock, flags); - -	wait_pending_extra_info_updates(); -  out: -	mutex_unlock(&apply_lock); +	spin_unlock_irqrestore(&data_lock, flags);  }  int dss_ovl_set_info(struct omap_overlay *ovl, @@ -1483,6 +1350,13 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)  		goto err;  	} +	spin_unlock_irqrestore(&data_lock, flags); + +	/* wait for pending extra_info updates to ensure the ovl is disabled */ +	wait_pending_extra_info_updates(); + +	spin_lock_irqsave(&data_lock, flags); +  	op->channel = -1;  	ovl->manager = NULL; @@ -1517,7 +1391,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)  {  	struct ovl_priv_data *op = get_ovl_priv(ovl);  	unsigned long flags; -	bool fifo_merge;  	int r;  	mutex_lock(&apply_lock); @@ -1527,7 +1400,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)  		goto err1;  	} -	if (ovl->manager == NULL || ovl->manager->device == NULL) { +	if (ovl->manager == NULL || ovl->manager->output == NULL) {  		r = -EINVAL;  		goto err1;  	} @@ -1543,22 +1416,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)  		goto err2;  	} -	/* step 1: configure fifos/fifomerge for currently enabled ovls */ - -	fifo_merge = get_use_fifo_merge(); -	dss_setup_fifos(fifo_merge); -	dss_apply_fifo_merge(fifo_merge); - -	dss_write_regs(); -	dss_set_go_bits(); - -	spin_unlock_irqrestore(&data_lock, flags); - -	/* wait for fifo configs to go in */ -	wait_pending_extra_info_updates(); - -	/* step 2: enable the overlay */ -	spin_lock_irqsave(&data_lock, flags); +	dss_setup_fifos();  	op->enabling = false;  	dss_apply_ovl_enable(ovl, true); @@ -1568,9 +1426,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)  	spin_unlock_irqrestore(&data_lock, flags); -	/* wait for overlay to be enabled */ -	wait_pending_extra_info_updates(); -  	mutex_unlock(&apply_lock);  	return 0; @@ -1586,7 +1441,6 @@ int dss_ovl_disable(struct omap_overlay *ovl)  {  	struct ovl_priv_data *op = get_ovl_priv(ovl);  	unsigned long flags; -	bool fifo_merge;  	int r;  	mutex_lock(&apply_lock); @@ -1596,39 +1450,19 @@ int dss_ovl_disable(struct omap_overlay *ovl)  		goto err;  	} -	if (ovl->manager == NULL || ovl->manager->device == NULL) { +	if (ovl->manager == NULL || ovl->manager->output == NULL) {  		r = -EINVAL;  		goto err;  	} -	/* step 1: disable the overlay */  	spin_lock_irqsave(&data_lock, flags);  	dss_apply_ovl_enable(ovl, false); -  	dss_write_regs();  	dss_set_go_bits();  	spin_unlock_irqrestore(&data_lock, flags); -	/* wait for the overlay to be disabled */ -	wait_pending_extra_info_updates(); - -	/* step 2: configure fifos/fifomerge */ -	spin_lock_irqsave(&data_lock, flags); - -	fifo_merge = get_use_fifo_merge(); -	dss_setup_fifos(fifo_merge); -	dss_apply_fifo_merge(fifo_merge); - -	dss_write_regs(); -	dss_set_go_bits(); - -	spin_unlock_irqrestore(&data_lock, flags); - -	/* wait for fifo config to go in */ -	wait_pending_extra_info_updates(); -  	mutex_unlock(&apply_lock);  	return 0; diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 58bd9c27369..b2af72dc20b 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -33,6 +33,7 @@  #include <linux/device.h>  #include <linux/regulator/consumer.h>  #include <linux/suspend.h> +#include <linux/slab.h>  #include <video/omapdss.h> @@ -57,6 +58,11 @@ bool dss_debug;  module_param_named(debug, dss_debug, bool, 0644);  #endif +const char *dss_get_default_display_name(void) +{ +	return core.default_display_name; +} +  /* REGULATORS */  struct regulator *dss_get_vdds_dsi(void) @@ -347,17 +353,14 @@ static int dss_driver_probe(struct device *dev)  	int r;  	struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);  	struct omap_dss_device *dssdev = to_dss_device(dev); -	bool force;  	DSSDBG("driver_probe: dev %s/%s, drv %s\n",  				dev_name(dev), dssdev->driver_name,  				dssdrv->driver.name); -	dss_init_device(core.pdev, dssdev); - -	force = core.default_display_name && -		strcmp(core.default_display_name, dssdev->name) == 0; -	dss_recheck_connections(dssdev, force); +	r = dss_init_device(core.pdev, dssdev); +	if (r) +		return r;  	r = dssdrv->probe(dssdev); @@ -416,54 +419,44 @@ void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)  EXPORT_SYMBOL(omap_dss_unregister_driver);  /* DEVICE */ -static void reset_device(struct device *dev, int check) -{ -	u8 *dev_p = (u8 *)dev; -	u8 *dev_end = dev_p + sizeof(*dev); -	void *saved_pdata; - -	saved_pdata = dev->platform_data; -	if (check) { -		/* -		 * Check if there is any other setting than platform_data -		 * in struct device; warn that these will be reset by our -		 * init. -		 */ -		dev->platform_data = NULL; -		while (dev_p < dev_end) { -			if (*dev_p) { -				WARN("%s: struct device fields will be " -						"discarded\n", -				     __func__); -				break; -			} -			dev_p++; -		} -	} -	memset(dev, 0, sizeof(*dev)); -	dev->platform_data = saved_pdata; -} -  static void omap_dss_dev_release(struct device *dev)  { -	reset_device(dev, 0); +	struct omap_dss_device *dssdev = to_dss_device(dev); +	kfree(dssdev);  } -int omap_dss_register_device(struct omap_dss_device *dssdev, -		struct device *parent, int disp_num) +static int disp_num_counter; + +struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)  { -	WARN_ON(!dssdev->driver_name); +	struct omap_dss_device *dssdev; + +	dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL); +	if (!dssdev) +		return NULL; -	reset_device(&dssdev->dev, 1);  	dssdev->dev.bus = &dss_bus_type;  	dssdev->dev.parent = parent;  	dssdev->dev.release = omap_dss_dev_release; -	dev_set_name(&dssdev->dev, "display%d", disp_num); -	return device_register(&dssdev->dev); +	dev_set_name(&dssdev->dev, "display%d", disp_num_counter++); + +	device_initialize(&dssdev->dev); + +	return dssdev;  } -void omap_dss_unregister_device(struct omap_dss_device *dssdev) +int dss_add_device(struct omap_dss_device *dssdev) +{ +	return device_add(&dssdev->dev); +} + +void dss_put_device(struct omap_dss_device *dssdev) +{ +	put_device(&dssdev->dev); +} + +void dss_unregister_device(struct omap_dss_device *dssdev)  {  	device_unregister(&dssdev->dev);  } @@ -471,15 +464,25 @@ void omap_dss_unregister_device(struct omap_dss_device *dssdev)  static int dss_unregister_dss_dev(struct device *dev, void *data)  {  	struct omap_dss_device *dssdev = to_dss_device(dev); -	omap_dss_unregister_device(dssdev); +	dss_unregister_device(dssdev);  	return 0;  } -void omap_dss_unregister_child_devices(struct device *parent) +void dss_unregister_child_devices(struct device *parent)  {  	device_for_each_child(parent, NULL, dss_unregister_dss_dev);  } +void dss_copy_device_pdata(struct omap_dss_device *dst, +		const struct omap_dss_device *src) +{ +	u8 *d = (u8 *)dst; +	u8 *s = (u8 *)src; +	size_t dsize = sizeof(struct device); + +	memcpy(d + dsize, s + dsize, sizeof(struct omap_dss_device) - dsize); +} +  /* BUS */  static int __init omap_dss_bus_register(void)  { diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ee9e29639dc..b43477a5fae 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -38,7 +38,6 @@  #include <linux/pm_runtime.h>  #include <plat/cpu.h> -#include <plat/clock.h>  #include <video/omapdss.h> @@ -82,6 +81,30 @@ struct dispc_irq_stats {  	unsigned irqs[32];  }; +struct dispc_features { +	u8 sw_start; +	u8 fp_start; +	u8 bp_start; +	u16 sw_max; +	u16 vp_max; +	u16 hp_max; +	int (*calc_scaling) (enum omap_plane plane, +		const struct omap_video_timings *mgr_timings, +		u16 width, u16 height, u16 out_width, u16 out_height, +		enum omap_color_mode color_mode, bool *five_taps, +		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, +		u16 pos_x, unsigned long *core_clk, bool mem_to_mem); +	unsigned long (*calc_core_clk) (enum omap_plane plane, +		u16 width, u16 height, u16 out_width, u16 out_height, +		bool mem_to_mem); +	u8 num_fifos; + +	/* swap GFX & WB fifos */ +	bool gfx_fifo_workaround:1; +}; + +#define DISPC_MAX_NR_FIFOS 5 +  static struct {  	struct platform_device *pdev;  	void __iomem    *base; @@ -91,7 +114,9 @@ static struct {  	int irq;  	struct clk *dss_clk; -	u32	fifo_size[MAX_DSS_OVERLAYS]; +	u32 fifo_size[DISPC_MAX_NR_FIFOS]; +	/* maps which plane is using a fifo. fifo-id -> plane-id */ +	int fifo_assignment[DISPC_MAX_NR_FIFOS];  	spinlock_t irq_lock;  	u32 irq_error_mask; @@ -102,6 +127,8 @@ static struct {  	bool		ctx_valid;  	u32		ctx[DISPC_SZ_REGS / sizeof(u32)]; +	const struct dispc_features *feat; +  #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS  	spinlock_t irq_stats_lock;  	struct dispc_irq_stats irq_stats; @@ -211,7 +238,14 @@ static const struct {  	},  }; +struct color_conv_coef { +	int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; +	int full_range; +}; +  static void _omap_dispc_set_irqs(void); +static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); +static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);  static inline void dispc_write_reg(const u16 idx, u32 val)  { @@ -509,6 +543,11 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)  	return mgr_desc[channel].framedone_irq;  } +u32 dispc_wb_get_framedone_irq(void) +{ +	return DISPC_IRQ_FRAMEDONEWB; +} +  bool dispc_mgr_go_busy(enum omap_channel channel)  {  	return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; @@ -536,6 +575,30 @@ void dispc_mgr_go(enum omap_channel channel)  	mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);  } +bool dispc_wb_go_busy(void) +{ +	return REG_GET(DISPC_CONTROL2, 6, 6) == 1; +} + +void dispc_wb_go(void) +{ +	enum omap_plane plane = OMAP_DSS_WB; +	bool enable, go; + +	enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1; + +	if (!enable) +		return; + +	go = REG_GET(DISPC_CONTROL2, 6, 6) == 1; +	if (go) { +		DSSERR("GO bit not down for WB\n"); +		return; +	} + +	REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6); +} +  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); @@ -618,41 +681,41 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,  	}  } -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; -	}  ctbl_bt601_5 = { -		298,  409,    0,  298, -208, -100,  298,    0,  517, 0, -	}; - -	const struct color_conv_coef *ct; +static void dispc_ovl_write_color_conv_coef(enum omap_plane plane, +		const struct color_conv_coef *ct) +{  #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) -	ct = &ctbl_bt601_5; +	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry)); +	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy,  ct->rcb)); +	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr)); +	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by)); +	dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 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)); - -		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range, -			11, 11); -	} +	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);  #undef CVAL  } +static void dispc_setup_color_conv_coef(void) +{ +	int i; +	int num_ovl = dss_feat_get_num_ovls(); +	int num_wb = dss_feat_get_num_wbs(); +	const struct color_conv_coef ctbl_bt601_5_ovl = { +		298, 409, 0, 298, -208, -100, 298, 0, 517, 0, +	}; +	const struct color_conv_coef ctbl_bt601_5_wb = { +		66, 112, -38, 129, -94, -74, 25, -18, 112, 0, +	}; + +	for (i = 1; i < num_ovl; i++) +		dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl); + +	for (; i < num_wb; i++) +		dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb); +}  static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)  { @@ -674,24 +737,32 @@ 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_ovl_set_pos(enum omap_plane plane, int x, int y) +static void dispc_ovl_set_pos(enum omap_plane plane, +		enum omap_overlay_caps caps, int x, int y)  { -	u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); +	u32 val; + +	if ((caps & OMAP_DSS_OVL_CAP_POS) == 0) +		return; + +	val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);  	dispc_write_reg(DISPC_OVL_POSITION(plane), val);  } -static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height) +static void dispc_ovl_set_input_size(enum omap_plane plane, int width, +		int height)  {  	u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); -	if (plane == OMAP_DSS_GFX) +	if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB)  		dispc_write_reg(DISPC_OVL_SIZE(plane), val);  	else  		dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);  } -static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) +static void dispc_ovl_set_output_size(enum omap_plane plane, int width, +		int height)  {  	u32 val; @@ -699,14 +770,16 @@ static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)  	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); -	dispc_write_reg(DISPC_OVL_SIZE(plane), val); +	if (plane == OMAP_DSS_WB) +		dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); +	else +		dispc_write_reg(DISPC_OVL_SIZE(plane), val);  } -static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) +static void dispc_ovl_set_zorder(enum omap_plane plane, +		enum omap_overlay_caps caps, u8 zorder)  { -	struct omap_overlay *ovl = omap_dss_get_overlay(plane); - -	if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) +	if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)  		return;  	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); @@ -723,23 +796,22 @@ static void dispc_ovl_enable_zorder_planes(void)  		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);  } -static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) +static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, +		enum omap_overlay_caps caps, bool enable)  { -	struct omap_overlay *ovl = omap_dss_get_overlay(plane); - -	if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) +	if ((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_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha) +static void dispc_ovl_setup_global_alpha(enum omap_plane plane, +		enum omap_overlay_caps caps, u8 global_alpha)  {  	static const unsigned shifts[] = { 0, 8, 16, 24, };  	int shift; -	struct omap_overlay *ovl = omap_dss_get_overlay(plane); -	if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) +	if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)  		return;  	shift = shifts[plane]; @@ -947,10 +1019,17 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)  	return channel;  } +void dispc_wb_set_channel_in(enum dss_writeback_channel channel) +{ +	enum omap_plane plane = OMAP_DSS_WB; + +	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16); +} +  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, }; +	static const unsigned shifts[] = { 6, 14, 14, 14, 14, };  	int shift;  	shift = shifts[plane]; @@ -1027,11 +1106,15 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)  	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);  } -static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) +static void dispc_ovl_enable_replication(enum omap_plane plane, +		enum omap_overlay_caps caps, bool enable)  {  	static const unsigned shifts[] = { 5, 10, 10, 10 };  	int shift; +	if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0) +		return; +  	shift = shifts[plane];  	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);  } @@ -1045,10 +1128,10 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,  	dispc_write_reg(DISPC_SIZE_MGR(channel), val);  } -static void dispc_read_plane_fifo_sizes(void) +static void dispc_init_fifos(void)  {  	u32 size; -	int plane; +	int fifo;  	u8 start, end;  	u32 unit; @@ -1056,16 +1139,53 @@ static void dispc_read_plane_fifo_sizes(void)  	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); -	for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) { -		size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end); +	for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) { +		size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);  		size *= unit; -		dispc.fifo_size[plane] = size; +		dispc.fifo_size[fifo] = size; + +		/* +		 * By default fifos are mapped directly to overlays, fifo 0 to +		 * ovl 0, fifo 1 to ovl 1, etc. +		 */ +		dispc.fifo_assignment[fifo] = fifo; +	} + +	/* +	 * The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo +	 * causes problems with certain use cases, like using the tiler in 2D +	 * mode. The below hack swaps the fifos of GFX and WB planes, thus +	 * giving GFX plane a larger fifo. WB but should work fine with a +	 * smaller fifo. +	 */ +	if (dispc.feat->gfx_fifo_workaround) { +		u32 v; + +		v = dispc_read_reg(DISPC_GLOBAL_BUFFER); + +		v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */ +		v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */ +		v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */ +		v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */ + +		dispc_write_reg(DISPC_GLOBAL_BUFFER, v); + +		dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB; +		dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;  	}  }  static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)  { -	return dispc.fifo_size[plane]; +	int fifo; +	u32 size = 0; + +	for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) { +		if (dispc.fifo_assignment[fifo] == plane) +			size += dispc.fifo_size[fifo]; +	} + +	return size;  }  void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) @@ -1141,6 +1261,14 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,  	if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {  		*fifo_low = ovl_fifo_size - burst_size * 2;  		*fifo_high = total_fifo_size - burst_size; +	} else if (plane == OMAP_DSS_WB) { +		/* +		 * Most optimal configuration for writeback is to push out data +		 * to the interconnect the moment writeback pushes enough pixels +		 * in the FIFO to form a burst +		 */ +		*fifo_low = 0; +		*fifo_high = burst_size;  	} else {  		*fifo_low = ovl_fifo_size - burst_size;  		*fifo_high = total_fifo_size - buf_unit; @@ -1383,6 +1511,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,  {  	int scale_x = out_width != orig_width;  	int scale_y = out_height != orig_height; +	bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;  	if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))  		return; @@ -1390,7 +1519,8 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,  			color_mode != OMAP_DSS_COLOR_UYVY &&  			color_mode != OMAP_DSS_COLOR_NV12)) {  		/* reset chroma resampling for RGB formats  */ -		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); +		if (plane != OMAP_DSS_WB) +			REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);  		return;  	} @@ -1399,23 +1529,34 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,  	switch (color_mode) {  	case OMAP_DSS_COLOR_NV12: -		/* UV is subsampled by 2 vertically*/ -		orig_height >>= 1; -		/* UV is subsampled by 2 horz.*/ -		orig_width >>= 1; +		if (chroma_upscale) { +			/* UV is subsampled by 2 horizontally and vertically */ +			orig_height >>= 1; +			orig_width >>= 1; +		} else { +			/* UV is downsampled by 2 horizontally and vertically */ +			orig_height <<= 1; +			orig_width <<= 1; +		} +  		break;  	case OMAP_DSS_COLOR_YUV2:  	case OMAP_DSS_COLOR_UYVY: -		/*For YUV422 with 90/270 rotation, -		 *we don't upsample chroma -		 */ +		/* For YUV422 with 90/270 rotation, we don't upsample chroma */  		if (rotation == OMAP_DSS_ROT_0 || -			rotation == OMAP_DSS_ROT_180) -			/* UV is subsampled by 2 hrz*/ -			orig_width >>= 1; +				rotation == OMAP_DSS_ROT_180) { +			if (chroma_upscale) +				/* UV is subsampled by 2 horizontally */ +				orig_width >>= 1; +			else +				/* UV is downsampled by 2 horizontally */ +				orig_width <<= 1; +		} +  		/* must use FIR for YUV422 if rotated */  		if (rotation != OMAP_DSS_ROT_0)  			scale_x = scale_y = true; +  		break;  	default:  		BUG(); @@ -1431,8 +1572,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,  			out_width, out_height, five_taps,  				rotation, DISPC_COLOR_COMPONENT_UV); -	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), -		(scale_x || scale_y) ? 1 : 0, 8, 8); +	if (plane != OMAP_DSS_WB) +		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), +			(scale_x || scale_y) ? 1 : 0, 8, 8); +  	/* set H scaling */  	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);  	/* set V scaling */ @@ -1848,22 +1991,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,   * This function is used to avoid synclosts in OMAP3, because of some   * undocumented horizontal position and timing related limitations.   */ -static int check_horiz_timing_omap3(enum omap_channel channel, +static int check_horiz_timing_omap3(enum omap_plane plane,  		const struct omap_video_timings *t, u16 pos_x,  		u16 width, u16 height, u16 out_width, u16 out_height)  {  	int DS = DIV_ROUND_UP(height, out_height); -	unsigned long nonactive, lclk, pclk; +	unsigned long nonactive;  	static const u8 limits[3] = { 8, 10, 20 };  	u64 val, blank; +	unsigned long pclk = dispc_plane_pclk_rate(plane); +	unsigned long lclk = dispc_plane_lclk_rate(plane);  	int i;  	nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; -	pclk = dispc_mgr_pclk_rate(channel); -	if (dss_mgr_is_lcd(channel)) -		lclk = dispc_mgr_lclk_rate(channel); -	else -		lclk = dispc_fclk_rate();  	i = 0;  	if (out_height < height) @@ -1900,13 +2040,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel,  	return 0;  } -static unsigned long calc_core_clk_five_taps(enum omap_channel channel, +static unsigned long calc_core_clk_five_taps(enum omap_plane plane,  		const struct omap_video_timings *mgr_timings, u16 width,  		u16 height, u16 out_width, u16 out_height,  		enum omap_color_mode color_mode)  {  	u32 core_clk = 0; -	u64 tmp, pclk = dispc_mgr_pclk_rate(channel); +	u64 tmp; +	unsigned long pclk = dispc_plane_pclk_rate(plane);  	if (height <= out_height && width <= out_width)  		return (unsigned long) pclk; @@ -1940,11 +2081,22 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,  	return core_clk;  } -static unsigned long calc_core_clk(enum omap_channel channel, u16 width, -		u16 height, u16 out_width, u16 out_height) +static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width, +		u16 height, u16 out_width, u16 out_height, bool mem_to_mem) +{ +	unsigned long pclk = dispc_plane_pclk_rate(plane); + +	if (height > out_height && width > out_width) +		return pclk * 4; +	else +		return pclk * 2; +} + +static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width, +		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)  {  	unsigned int hf, vf; -	unsigned long pclk = dispc_mgr_pclk_rate(channel); +	unsigned long pclk = dispc_plane_pclk_rate(plane);  	/*  	 * FIXME how to determine the 'A' factor @@ -1959,51 +2111,207 @@ static unsigned long calc_core_clk(enum omap_channel channel, u16 width,  		hf = 2;  	else  		hf = 1; -  	if (height > out_height)  		vf = 2;  	else  		vf = 1; -	if (cpu_is_omap24xx()) { -		if (vf > 1 && hf > 1) -			return pclk * 4; -		else -			return pclk * 2; -	} else if (cpu_is_omap34xx()) { -		return pclk * vf * hf; -	} else { -		if (hf > 1) -			return DIV_ROUND_UP(pclk, out_width) * width; -		else -			return pclk; +	return pclk * vf * hf; +} + +static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width, +		u16 height, u16 out_width, u16 out_height, bool mem_to_mem) +{ +	unsigned long pclk; + +	/* +	 * If the overlay/writeback is in mem to mem mode, there are no +	 * downscaling limitations with respect to pixel clock, return 1 as +	 * required core clock to represent that we have sufficient enough +	 * core clock to do maximum downscaling +	 */ +	if (mem_to_mem) +		return 1; + +	pclk = dispc_plane_pclk_rate(plane); + +	if (width > out_width) +		return DIV_ROUND_UP(pclk, out_width) * width; +	else +		return pclk; +} + +static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane, +		const struct omap_video_timings *mgr_timings, +		u16 width, u16 height, u16 out_width, u16 out_height, +		enum omap_color_mode color_mode, bool *five_taps, +		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, +		u16 pos_x, unsigned long *core_clk, bool mem_to_mem) +{ +	int error; +	u16 in_width, in_height; +	int min_factor = min(*decim_x, *decim_y); +	const int maxsinglelinewidth = +			dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); + +	*five_taps = false; + +	do { +		in_height = DIV_ROUND_UP(height, *decim_y); +		in_width = DIV_ROUND_UP(width, *decim_x); +		*core_clk = dispc.feat->calc_core_clk(plane, in_width, +				in_height, out_width, out_height, mem_to_mem); +		error = (in_width > maxsinglelinewidth || !*core_clk || +			*core_clk > dispc_core_clk_rate()); +		if (error) { +			if (*decim_x == *decim_y) { +				*decim_x = min_factor; +				++*decim_y; +			} else { +				swap(*decim_x, *decim_y); +				if (*decim_x < *decim_y) +					++*decim_x; +			} +		} +	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); + +	if (in_width > maxsinglelinewidth) { +		DSSERR("Cannot scale max input width exceeded"); +		return -EINVAL;  	} +	return 0;  } -static int dispc_ovl_calc_scaling(enum omap_plane plane, -		enum omap_channel channel, +static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,  		const struct omap_video_timings *mgr_timings,  		u16 width, u16 height, u16 out_width, u16 out_height,  		enum omap_color_mode color_mode, bool *five_taps, -		int *x_predecim, int *y_predecim, u16 pos_x) +		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, +		u16 pos_x, unsigned long *core_clk, bool mem_to_mem)  { -	struct omap_overlay *ovl = omap_dss_get_overlay(plane); -	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); +	int error; +	u16 in_width, in_height; +	int min_factor = min(*decim_x, *decim_y); +	const int maxsinglelinewidth = +			dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); + +	do { +		in_height = DIV_ROUND_UP(height, *decim_y); +		in_width = DIV_ROUND_UP(width, *decim_x); +		*core_clk = calc_core_clk_five_taps(plane, mgr_timings, +			in_width, in_height, out_width, out_height, color_mode); + +		error = check_horiz_timing_omap3(plane, mgr_timings, +				pos_x, in_width, in_height, out_width, +				out_height); + +		if (in_width > maxsinglelinewidth) +			if (in_height > out_height && +						in_height < out_height * 2) +				*five_taps = false; +		if (!*five_taps) +			*core_clk = dispc.feat->calc_core_clk(plane, in_width, +					in_height, out_width, out_height, +					mem_to_mem); + +		error = (error || in_width > maxsinglelinewidth * 2 || +			(in_width > maxsinglelinewidth && *five_taps) || +			!*core_clk || *core_clk > dispc_core_clk_rate()); +		if (error) { +			if (*decim_x == *decim_y) { +				*decim_x = min_factor; +				++*decim_y; +			} else { +				swap(*decim_x, *decim_y); +				if (*decim_x < *decim_y) +					++*decim_x; +			} +		} +	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); + +	if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height, +		out_width, out_height)){ +			DSSERR("horizontal timing too tight\n"); +			return -EINVAL; +	} + +	if (in_width > (maxsinglelinewidth * 2)) { +		DSSERR("Cannot setup scaling"); +		DSSERR("width exceeds maximum width possible"); +		return -EINVAL; +	} + +	if (in_width > maxsinglelinewidth && *five_taps) { +		DSSERR("cannot setup scaling with five taps"); +		return -EINVAL; +	} +	return 0; +} + +static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, +		const struct omap_video_timings *mgr_timings, +		u16 width, u16 height, u16 out_width, u16 out_height, +		enum omap_color_mode color_mode, bool *five_taps, +		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, +		u16 pos_x, unsigned long *core_clk, bool mem_to_mem) +{ +	u16 in_width, in_width_max; +	int decim_x_min = *decim_x; +	u16 in_height = DIV_ROUND_UP(height, *decim_y);  	const int maxsinglelinewidth =  				dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); +	unsigned long pclk = dispc_plane_pclk_rate(plane); +	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); + +	if (mem_to_mem) +		in_width_max = DIV_ROUND_UP(out_width, maxdownscale); +	else +		in_width_max = dispc_core_clk_rate() / +					DIV_ROUND_UP(pclk, out_width); + +	*decim_x = DIV_ROUND_UP(width, in_width_max); + +	*decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min; +	if (*decim_x > *x_predecim) +		return -EINVAL; + +	do { +		in_width = DIV_ROUND_UP(width, *decim_x); +	} while (*decim_x <= *x_predecim && +			in_width > maxsinglelinewidth && ++*decim_x); + +	if (in_width > maxsinglelinewidth) { +		DSSERR("Cannot scale width exceeds max line width"); +		return -EINVAL; +	} + +	*core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height, +				out_width, out_height, mem_to_mem); +	return 0; +} + +static int dispc_ovl_calc_scaling(enum omap_plane plane, +		enum omap_overlay_caps caps, +		const struct omap_video_timings *mgr_timings, +		u16 width, u16 height, u16 out_width, u16 out_height, +		enum omap_color_mode color_mode, bool *five_taps, +		int *x_predecim, int *y_predecim, u16 pos_x, +		enum omap_dss_rotation_type rotation_type, bool mem_to_mem) +{ +	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);  	const int max_decim_limit = 16;  	unsigned long core_clk = 0; -	int decim_x, decim_y, error, min_factor; -	u16 in_width, in_height, in_width_max = 0; +	int decim_x, decim_y, ret;  	if (width == out_width && height == out_height)  		return 0; -	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) +	if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)  		return -EINVAL;  	*x_predecim = max_decim_limit; -	*y_predecim = max_decim_limit; +	*y_predecim = (rotation_type == OMAP_DSS_ROT_TILER && +			dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;  	if (color_mode == OMAP_DSS_COLOR_CLUT1 ||  	    color_mode == OMAP_DSS_COLOR_CLUT2 || @@ -2018,118 +2326,18 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,  	decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);  	decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); -	min_factor = min(decim_x, decim_y); -  	if (decim_x > *x_predecim || out_width > width * 8)  		return -EINVAL;  	if (decim_y > *y_predecim || out_height > height * 8)  		return -EINVAL; -	if (cpu_is_omap24xx()) { -		*five_taps = false; - -		do { -			in_height = DIV_ROUND_UP(height, decim_y); -			in_width = DIV_ROUND_UP(width, decim_x); -			core_clk = calc_core_clk(channel, in_width, in_height, -					out_width, out_height); -			error = (in_width > maxsinglelinewidth || !core_clk || -				core_clk > dispc_core_clk_rate()); -			if (error) { -				if (decim_x == decim_y) { -					decim_x = min_factor; -					decim_y++; -				} else { -					swap(decim_x, decim_y); -					if (decim_x < decim_y) -						decim_x++; -				} -			} -		} while (decim_x <= *x_predecim && decim_y <= *y_predecim && -				error); - -		if (in_width > maxsinglelinewidth) { -			DSSERR("Cannot scale max input width exceeded"); -			return -EINVAL; -		} -	} else if (cpu_is_omap34xx()) { - -		do { -			in_height = DIV_ROUND_UP(height, decim_y); -			in_width = DIV_ROUND_UP(width, decim_x); -			core_clk = calc_core_clk_five_taps(channel, mgr_timings, -				in_width, in_height, out_width, out_height, -				color_mode); - -			error = check_horiz_timing_omap3(channel, mgr_timings, -				pos_x, in_width, in_height, out_width, -				out_height); - -			if (in_width > maxsinglelinewidth) -				if (in_height > out_height && -					in_height < out_height * 2) -					*five_taps = false; -			if (!*five_taps) -				core_clk = calc_core_clk(channel, in_width, -					in_height, out_width, out_height); -			error = (error || in_width > maxsinglelinewidth * 2 || -				(in_width > maxsinglelinewidth && *five_taps) || -				!core_clk || core_clk > dispc_core_clk_rate()); -			if (error) { -				if (decim_x == decim_y) { -					decim_x = min_factor; -					decim_y++; -				} else { -					swap(decim_x, decim_y); -					if (decim_x < decim_y) -						decim_x++; -				} -			} -		} while (decim_x <= *x_predecim && decim_y <= *y_predecim -			&& error); - -		if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, -			height, out_width, out_height)){ -				DSSERR("horizontal timing too tight\n"); -				return -EINVAL; -		} - -		if (in_width > (maxsinglelinewidth * 2)) { -			DSSERR("Cannot setup scaling"); -			DSSERR("width exceeds maximum width possible"); -			return -EINVAL; -		} - -		if (in_width > maxsinglelinewidth && *five_taps) { -			DSSERR("cannot setup scaling with five taps"); -			return -EINVAL; -		} -	} else { -		int decim_x_min = decim_x; -		in_height = DIV_ROUND_UP(height, decim_y); -		in_width_max = dispc_core_clk_rate() / -				DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), -						out_width); -		decim_x = DIV_ROUND_UP(width, in_width_max); - -		decim_x = decim_x > decim_x_min ? decim_x : decim_x_min; -		if (decim_x > *x_predecim) -			return -EINVAL; - -		do { -			in_width = DIV_ROUND_UP(width, decim_x); -		} while (decim_x <= *x_predecim && -				in_width > maxsinglelinewidth && decim_x++); - -		if (in_width > maxsinglelinewidth) { -			DSSERR("Cannot scale width exceeds max line width"); -			return -EINVAL; -		} - -		core_clk = calc_core_clk(channel, in_width, in_height, -				out_width, out_height); -	} +	ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height, +		out_width, out_height, color_mode, five_taps, +		x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk, +		mem_to_mem); +	if (ret) +		return ret;  	DSSDBG("required core clk rate = %lu Hz\n", core_clk);  	DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); @@ -2147,69 +2355,64 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,  	return 0;  } -int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, -		bool replication, const struct omap_video_timings *mgr_timings) +static int dispc_ovl_setup_common(enum omap_plane plane, +		enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr, +		u16 screen_width, int pos_x, int pos_y, u16 width, u16 height, +		u16 out_width, u16 out_height, enum omap_color_mode color_mode, +		u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha, +		u8 global_alpha, enum omap_dss_rotation_type rotation_type, +		bool replication, const struct omap_video_timings *mgr_timings, +		bool mem_to_mem)  { -	struct omap_overlay *ovl = omap_dss_get_overlay(plane);  	bool five_taps = true;  	bool fieldmode = 0;  	int r, cconv = 0;  	unsigned offset0, offset1;  	s32 row_inc;  	s32 pix_inc; -	u16 frame_height = oi->height; +	u16 frame_height = height;  	unsigned int field_offset = 0; -	u16 in_height = oi->height; -	u16 in_width = oi->width; -	u16 out_width, out_height; -	enum omap_channel channel; +	u16 in_height = height; +	u16 in_width = width;  	int x_predecim = 1, y_predecim = 1;  	bool ilace = mgr_timings->interlace; -	channel = dispc_ovl_get_channel_out(plane); - -	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\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); - -	if (oi->paddr == 0) +	if (paddr == 0)  		return -EINVAL; -	out_width = oi->out_width == 0 ? oi->width : oi->out_width; -	out_height = oi->out_height == 0 ? oi->height : oi->out_height; +	out_width = out_width == 0 ? width : out_width; +	out_height = out_height == 0 ? height : out_height; -	if (ilace && oi->height == out_height) +	if (ilace && height == out_height)  		fieldmode = 1;  	if (ilace) {  		if (fieldmode)  			in_height /= 2; -		oi->pos_y /= 2; +		pos_y /= 2;  		out_height /= 2;  		DSSDBG("adjusting for ilace: height %d, pos_y %d, " -				"out_height %d\n", -				in_height, oi->pos_y, out_height); +			"out_height %d\n", in_height, pos_y, +			out_height);  	} -	if (!dss_feat_color_mode_supported(plane, oi->color_mode)) +	if (!dss_feat_color_mode_supported(plane, color_mode))  		return -EINVAL; -	r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width, -			in_height, out_width, out_height, oi->color_mode, -			&five_taps, &x_predecim, &y_predecim, oi->pos_x); +	r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width, +			in_height, out_width, out_height, color_mode, +			&five_taps, &x_predecim, &y_predecim, pos_x, +			rotation_type, mem_to_mem);  	if (r)  		return r;  	in_width = DIV_ROUND_UP(in_width, x_predecim);  	in_height = DIV_ROUND_UP(in_height, y_predecim); -	if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || -			oi->color_mode == OMAP_DSS_COLOR_UYVY || -			oi->color_mode == OMAP_DSS_COLOR_NV12) +	if (color_mode == OMAP_DSS_COLOR_YUV2 || +			color_mode == OMAP_DSS_COLOR_UYVY || +			color_mode == OMAP_DSS_COLOR_NV12)  		cconv = 1;  	if (ilace && !fieldmode) { @@ -2235,70 +2438,144 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,  	row_inc = 0;  	pix_inc = 0; -	if (oi->rotation_type == OMAP_DSS_ROT_TILER) -		calc_tiler_rotation_offset(oi->screen_width, in_width, -				oi->color_mode, fieldmode, field_offset, +	if (rotation_type == OMAP_DSS_ROT_TILER) +		calc_tiler_rotation_offset(screen_width, in_width, +				color_mode, fieldmode, field_offset,  				&offset0, &offset1, &row_inc, &pix_inc,  				x_predecim, y_predecim); -	else if (oi->rotation_type == OMAP_DSS_ROT_DMA) -		calc_dma_rotation_offset(oi->rotation, oi->mirror, -				oi->screen_width, in_width, frame_height, -				oi->color_mode, fieldmode, field_offset, +	else if (rotation_type == OMAP_DSS_ROT_DMA) +		calc_dma_rotation_offset(rotation, mirror, +				screen_width, in_width, frame_height, +				color_mode, fieldmode, field_offset,  				&offset0, &offset1, &row_inc, &pix_inc,  				x_predecim, y_predecim);  	else -		calc_vrfb_rotation_offset(oi->rotation, oi->mirror, -				oi->screen_width, in_width, frame_height, -				oi->color_mode, fieldmode, field_offset, +		calc_vrfb_rotation_offset(rotation, mirror, +				screen_width, in_width, frame_height, +				color_mode, fieldmode, field_offset,  				&offset0, &offset1, &row_inc, &pix_inc,  				x_predecim, y_predecim);  	DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",  			offset0, offset1, row_inc, pix_inc); -	dispc_ovl_set_color_mode(plane, oi->color_mode); +	dispc_ovl_set_color_mode(plane, color_mode); -	dispc_ovl_configure_burst_type(plane, oi->rotation_type); +	dispc_ovl_configure_burst_type(plane, rotation_type); -	dispc_ovl_set_ba0(plane, oi->paddr + offset0); -	dispc_ovl_set_ba1(plane, oi->paddr + offset1); +	dispc_ovl_set_ba0(plane, paddr + offset0); +	dispc_ovl_set_ba1(plane, paddr + 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); +	if (OMAP_DSS_COLOR_NV12 == color_mode) { +		dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0); +		dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);  	} -  	dispc_ovl_set_row_inc(plane, row_inc);  	dispc_ovl_set_pix_inc(plane, pix_inc); -	DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width, +	DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width,  			in_height, out_width, out_height); -	dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); +	dispc_ovl_set_pos(plane, caps, pos_x, pos_y); -	dispc_ovl_set_pic_size(plane, in_width, in_height); +	dispc_ovl_set_input_size(plane, in_width, in_height); -	if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { +	if (caps & OMAP_DSS_OVL_CAP_SCALE) {  		dispc_ovl_set_scaling(plane, in_width, in_height, out_width,  				   out_height, ilace, five_taps, fieldmode, -				   oi->color_mode, oi->rotation); -		dispc_ovl_set_vid_size(plane, out_width, out_height); +				   color_mode, rotation); +		dispc_ovl_set_output_size(plane, out_width, out_height);  		dispc_ovl_set_vid_color_conv(plane, cconv);  	} -	dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror, -			oi->color_mode); +	dispc_ovl_set_rotation_attrs(plane, rotation, mirror, 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_ovl_set_zorder(plane, caps, zorder); +	dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha); +	dispc_ovl_setup_global_alpha(plane, caps, global_alpha); -	dispc_ovl_enable_replication(plane, replication); +	dispc_ovl_enable_replication(plane, caps, replication);  	return 0;  } +int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, +		bool replication, const struct omap_video_timings *mgr_timings, +		bool mem_to_mem) +{ +	int r; +	struct omap_overlay *ovl = omap_dss_get_overlay(plane); +	enum omap_channel channel; + +	channel = dispc_ovl_get_channel_out(plane); + +	DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " +		"%dx%d, cmode %x, rot %d, mir %d, chan %d repl %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, channel, replication); + +	r = dispc_ovl_setup_common(plane, ovl->caps, 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, oi->zorder, oi->pre_mult_alpha, oi->global_alpha, +		oi->rotation_type, replication, mgr_timings, mem_to_mem); + +	return r; +} + +int dispc_wb_setup(const struct omap_dss_writeback_info *wi, +		bool mem_to_mem, const struct omap_video_timings *mgr_timings) +{ +	int r; +	u32 l; +	enum omap_plane plane = OMAP_DSS_WB; +	const int pos_x = 0, pos_y = 0; +	const u8 zorder = 0, global_alpha = 0; +	const bool replication = false; +	bool truncation; +	int in_width = mgr_timings->x_res; +	int in_height = mgr_timings->y_res; +	enum omap_overlay_caps caps = +		OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA; + +	DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, " +		"rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width, +		in_height, wi->width, wi->height, wi->color_mode, wi->rotation, +		wi->mirror); + +	r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr, +		wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width, +		wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder, +		wi->pre_mult_alpha, global_alpha, wi->rotation_type, +		replication, mgr_timings, mem_to_mem); + +	switch (wi->color_mode) { +	case OMAP_DSS_COLOR_RGB16: +	case OMAP_DSS_COLOR_RGB24P: +	case OMAP_DSS_COLOR_ARGB16: +	case OMAP_DSS_COLOR_RGBA16: +	case OMAP_DSS_COLOR_RGB12U: +	case OMAP_DSS_COLOR_ARGB16_1555: +	case OMAP_DSS_COLOR_XRGB16_1555: +	case OMAP_DSS_COLOR_RGBX16: +		truncation = true; +		break; +	default: +		truncation = false; +		break; +	} + +	/* setup extra DISPC_WB_ATTRIBUTES */ +	l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); +	l = FLD_MOD(l, truncation, 10, 10);	/* TRUNCATIONENABLE */ +	l = FLD_MOD(l, mem_to_mem, 19, 19);	/* WRITEBACKMODE */ +	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l); + +	return r; +} +  int dispc_ovl_enable(enum omap_plane plane, bool enable)  {  	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); @@ -2451,6 +2728,47 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable)  		BUG();  } +void dispc_wb_enable(bool enable) +{ +	enum omap_plane plane = OMAP_DSS_WB; +	struct completion frame_done_completion; +	bool is_on; +	int r; +	u32 irq; + +	is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); +	irq = DISPC_IRQ_FRAMEDONEWB; + +	if (!enable && is_on) { +		init_completion(&frame_done_completion); + +		r = omap_dispc_register_isr(dispc_disable_isr, +				&frame_done_completion, irq); +		if (r) +			DSSERR("failed to register FRAMEDONEWB isr\n"); +	} + +	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0); + +	if (!enable && is_on) { +		if (!wait_for_completion_timeout(&frame_done_completion, +					msecs_to_jiffies(100))) +			DSSERR("timeout waiting for FRAMEDONEWB\n"); + +		r = omap_dispc_unregister_isr(dispc_disable_isr, +				&frame_done_completion, irq); +		if (r) +			DSSERR("failed to unregister FRAMEDONEWB isr\n"); +	} +} + +bool dispc_wb_is_enabled(void) +{ +	enum omap_plane plane = OMAP_DSS_WB; + +	return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); +} +  void dispc_lcd_enable_signal_polarity(bool act_high)  {  	if (!dss_has_feature(FEAT_LCDENABLEPOL)) @@ -2605,24 +2923,13 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height)  static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,  		int vsw, int vfp, int vbp)  { -	if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { -		if (hsw < 1 || hsw > 64 || -				hfp < 1 || hfp > 256 || -				hbp < 1 || hbp > 256 || -				vsw < 1 || vsw > 64 || -				vfp < 0 || vfp > 255 || -				vbp < 0 || vbp > 255) -			return false; -	} else { -		if (hsw < 1 || hsw > 256 || -				hfp < 1 || hfp > 4096 || -				hbp < 1 || hbp > 4096 || -				vsw < 1 || vsw > 256 || -				vfp < 0 || vfp > 4095 || -				vbp < 0 || vbp > 4095) -			return false; -	} - +	if (hsw < 1 || hsw > dispc.feat->sw_max || +			hfp < 1 || hfp > dispc.feat->hp_max || +			hbp < 1 || hbp > dispc.feat->hp_max || +			vsw < 1 || vsw > dispc.feat->sw_max || +			vfp < 0 || vfp > dispc.feat->vp_max || +			vbp < 0 || vbp > dispc.feat->vp_max) +		return false;  	return true;  } @@ -2654,19 +2961,12 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,  	u32 timing_h, timing_v, l;  	bool onoff, rf, ipc; -	if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { -		timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | -			FLD_VAL(hbp-1, 27, 20); - -		timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | -			FLD_VAL(vbp, 27, 20); -	} else { -		timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) | -			FLD_VAL(hbp-1, 31, 20); - -		timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) | -			FLD_VAL(vbp, 31, 20); -	} +	timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) | +			FLD_VAL(hfp-1, dispc.feat->fp_start, 8) | +			FLD_VAL(hbp-1, dispc.feat->bp_start, 20); +	timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) | +			FLD_VAL(vfp, dispc.feat->fp_start, 8) | +			FLD_VAL(vbp, dispc.feat->bp_start, 20);  	dispc_write_reg(DISPC_TIMING_H(channel), timing_h);  	dispc_write_reg(DISPC_TIMING_V(channel), timing_v); @@ -2872,6 +3172,23 @@ unsigned long dispc_core_clk_rate(void)  	return fclk / lcd;  } +static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) +{ +	enum omap_channel channel = dispc_ovl_get_channel_out(plane); + +	return dispc_mgr_pclk_rate(channel); +} + +static unsigned long dispc_plane_lclk_rate(enum omap_plane plane) +{ +	enum omap_channel channel = dispc_ovl_get_channel_out(plane); + +	if (dss_mgr_is_lcd(channel)) +		return dispc_mgr_lclk_rate(channel); +	else +		return dispc_fclk_rate(); + +}  static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)  {  	int lcd, pcd; @@ -3492,7 +3809,7 @@ static void dispc_error_worker(struct work_struct *work)  					ovl->name);  			dispc_ovl_enable(ovl->id, false);  			dispc_mgr_go(ovl->manager->id); -			mdelay(50); +			msleep(50);  		}  	} @@ -3504,7 +3821,7 @@ static void dispc_error_worker(struct work_struct *work)  		bit = mgr_desc[i].sync_lost_irq;  		if (bit & errors) { -			struct omap_dss_device *dssdev = mgr->device; +			struct omap_dss_device *dssdev = mgr->get_device(mgr);  			bool enable;  			DSSERR("SYNC_LOST on channel %s, restarting the output " @@ -3524,7 +3841,7 @@ static void dispc_error_worker(struct work_struct *work)  			}  			dispc_mgr_go(mgr->id); -			mdelay(50); +			msleep(50);  			if (enable)  				dssdev->driver->enable(dssdev); @@ -3535,9 +3852,13 @@ static void dispc_error_worker(struct work_struct *work)  		DSSERR("OCP_ERR\n");  		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {  			struct omap_overlay_manager *mgr; +			struct omap_dss_device *dssdev; +  			mgr = omap_dss_get_overlay_manager(i); -			if (mgr->device && mgr->device->driver) -				mgr->device->driver->disable(mgr->device); +			dssdev = mgr->get_device(mgr); + +			if (dssdev && dssdev->driver) +				dssdev->driver->disable(dssdev);  		}  	} @@ -3661,17 +3982,98 @@ static void _omap_dispc_initial_config(void)  	if (dss_has_feature(FEAT_FUNCGATED))  		REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); -	_dispc_setup_color_conv_coef(); +	dispc_setup_color_conv_coef();  	dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); -	dispc_read_plane_fifo_sizes(); +	dispc_init_fifos();  	dispc_configure_burst_sizes();  	dispc_ovl_enable_zorder_planes();  } +static const struct dispc_features omap24xx_dispc_feats __initconst = { +	.sw_start		=	5, +	.fp_start		=	15, +	.bp_start		=	27, +	.sw_max			=	64, +	.vp_max			=	255, +	.hp_max			=	256, +	.calc_scaling		=	dispc_ovl_calc_scaling_24xx, +	.calc_core_clk		=	calc_core_clk_24xx, +	.num_fifos		=	3, +}; + +static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { +	.sw_start		=	5, +	.fp_start		=	15, +	.bp_start		=	27, +	.sw_max			=	64, +	.vp_max			=	255, +	.hp_max			=	256, +	.calc_scaling		=	dispc_ovl_calc_scaling_34xx, +	.calc_core_clk		=	calc_core_clk_34xx, +	.num_fifos		=	3, +}; + +static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { +	.sw_start		=	7, +	.fp_start		=	19, +	.bp_start		=	31, +	.sw_max			=	256, +	.vp_max			=	4095, +	.hp_max			=	4096, +	.calc_scaling		=	dispc_ovl_calc_scaling_34xx, +	.calc_core_clk		=	calc_core_clk_34xx, +	.num_fifos		=	3, +}; + +static const struct dispc_features omap44xx_dispc_feats __initconst = { +	.sw_start		=	7, +	.fp_start		=	19, +	.bp_start		=	31, +	.sw_max			=	256, +	.vp_max			=	4095, +	.hp_max			=	4096, +	.calc_scaling		=	dispc_ovl_calc_scaling_44xx, +	.calc_core_clk		=	calc_core_clk_44xx, +	.num_fifos		=	5, +	.gfx_fifo_workaround	=	true, +}; + +static int __init dispc_init_features(struct device *dev) +{ +	const struct dispc_features *src; +	struct dispc_features *dst; + +	dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL); +	if (!dst) { +		dev_err(dev, "Failed to allocate DISPC Features\n"); +		return -ENOMEM; +	} + +	if (cpu_is_omap24xx()) { +		src = &omap24xx_dispc_feats; +	} else if (cpu_is_omap34xx()) { +		if (omap_rev() < OMAP3430_REV_ES3_0) +			src = &omap34xx_rev1_0_dispc_feats; +		else +			src = &omap34xx_rev3_0_dispc_feats; +	} else if (cpu_is_omap44xx()) { +		src = &omap44xx_dispc_feats; +	} else if (soc_is_omap54xx()) { +		src = &omap44xx_dispc_feats; +	} else { +		return -ENODEV; +	} + +	memcpy(dst, src, sizeof(*dst)); +	dispc.feat = dst; + +	return 0; +} +  /* DISPC HW IP initialisation */  static int __init omap_dispchw_probe(struct platform_device *pdev)  { @@ -3682,6 +4084,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)  	dispc.pdev = pdev; +	r = dispc_init_features(&dispc.pdev->dev); +	if (r) +		return r; +  	spin_lock_init(&dispc.irq_lock);  #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h index 92d8a9be86f..222363c6e62 100644 --- a/drivers/video/omap2/dss/dispc.h +++ b/drivers/video/omap2/dss/dispc.h @@ -36,6 +36,7 @@  #define DISPC_CONTROL2			0x0238  #define DISPC_CONFIG2			0x0620  #define DISPC_DIVISOR			0x0804 +#define DISPC_GLOBAL_BUFFER		0x0800  #define DISPC_CONTROL3                  0x0848  #define DISPC_CONFIG3                   0x084C @@ -355,6 +356,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)  		return 0x014C;  	case OMAP_DSS_VIDEO3:  		return 0x0300; +	case OMAP_DSS_WB: +		return 0x0500;  	default:  		BUG();  		return 0; @@ -370,6 +373,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x0000;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0008;  	default:  		BUG(); @@ -385,6 +389,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x0004;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x000C;  	default:  		BUG(); @@ -404,6 +409,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)  		return 0x04BC;  	case OMAP_DSS_VIDEO3:  		return 0x0310; +	case OMAP_DSS_WB: +		return 0x0118;  	default:  		BUG();  		return 0; @@ -422,6 +429,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)  		return 0x04C0;  	case OMAP_DSS_VIDEO3:  		return 0x0314; +	case OMAP_DSS_WB: +		return 0x011C;  	default:  		BUG();  		return 0; @@ -451,6 +460,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x000C;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x00A8;  	default:  		BUG(); @@ -467,6 +477,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x0010;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0070;  	default:  		BUG(); @@ -486,6 +497,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)  		return 0x04DC;  	case OMAP_DSS_VIDEO3:  		return 0x032C; +	case OMAP_DSS_WB: +		return 0x0310;  	default:  		BUG();  		return 0; @@ -501,6 +514,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x0014;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x008C;  	default:  		BUG(); @@ -517,6 +531,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x0018;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0088;  	default:  		BUG(); @@ -533,6 +548,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x001C;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x00A4;  	default:  		BUG(); @@ -549,6 +565,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x0020;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0098;  	default:  		BUG(); @@ -598,6 +615,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x0024;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0090;  	default:  		BUG(); @@ -617,6 +635,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)  		return 0x055C;  	case OMAP_DSS_VIDEO3:  		return 0x0424; +	case OMAP_DSS_WB: +		return 0x290;  	default:  		BUG();  		return 0; @@ -633,6 +653,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x0028;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0094;  	default:  		BUG(); @@ -651,6 +672,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x002C;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0000;  	default:  		BUG(); @@ -670,6 +692,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)  		return 0x0560;  	case OMAP_DSS_VIDEO3:  		return 0x0428; +	case OMAP_DSS_WB: +		return 0x0294;  	default:  		BUG();  		return 0; @@ -686,6 +710,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)  	case OMAP_DSS_VIDEO2:  		return 0x0030;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0004;  	default:  		BUG(); @@ -705,6 +730,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)  		return 0x0564;  	case OMAP_DSS_VIDEO3:  		return 0x042C; +	case OMAP_DSS_WB: +		return 0x0298;  	default:  		BUG();  		return 0; @@ -722,6 +749,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)  	case OMAP_DSS_VIDEO2:  		return 0x0034 + i * 0x8;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0010 + i * 0x8;  	default:  		BUG(); @@ -742,6 +770,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)  		return 0x0568 + i * 0x8;  	case OMAP_DSS_VIDEO3:  		return 0x0430 + i * 0x8; +	case OMAP_DSS_WB: +		return 0x02A0 + i * 0x8;  	default:  		BUG();  		return 0; @@ -759,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)  	case OMAP_DSS_VIDEO2:  		return 0x0038 + i * 0x8;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0014 + i * 0x8;  	default:  		BUG(); @@ -779,6 +810,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)  		return 0x056C + i * 0x8;  	case OMAP_DSS_VIDEO3:  		return 0x0434 + i * 0x8; +	case OMAP_DSS_WB: +		return 0x02A4 + i * 0x8;  	default:  		BUG();  		return 0; @@ -795,6 +828,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)  	case OMAP_DSS_VIDEO1:  	case OMAP_DSS_VIDEO2:  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0074 + i * 0x4;  	default:  		BUG(); @@ -814,6 +848,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)  	case OMAP_DSS_VIDEO2:  		return 0x00B4 + i * 0x4;  	case OMAP_DSS_VIDEO3: +	case OMAP_DSS_WB:  		return 0x0050 + i * 0x4;  	default:  		BUG(); @@ -834,6 +869,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)  		return 0x05A8 + i * 0x4;  	case OMAP_DSS_VIDEO3:  		return 0x0470 + i * 0x4; +	case OMAP_DSS_WB: +		return 0x02E0 + i * 0x4;  	default:  		BUG();  		return 0; diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 5bd957e8550..ccf8550fafd 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -142,7 +142,11 @@ static ssize_t display_timings_store(struct device *dev,  	if (r)  		return r; +	dssdev->driver->disable(dssdev);  	dssdev->driver->set_timings(dssdev, &t); +	r = dssdev->driver->enable(dssdev); +	if (r) +		return r;  	return size;  } @@ -316,26 +320,117 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,  }  EXPORT_SYMBOL(omapdss_default_get_timings); -void dss_init_device(struct platform_device *pdev, +/* + * Connect dssdev to a manager if the manager is free or if force is specified. + * Connect all overlays to that manager if they are free or if force is + * specified. + */ +static int dss_init_connections(struct omap_dss_device *dssdev, bool force) +{ +	struct omap_dss_output *out; +	struct omap_overlay_manager *mgr; +	int i, r; + +	out = omapdss_get_output_from_dssdev(dssdev); + +	WARN_ON(dssdev->output); +	WARN_ON(out->device); + +	r = omapdss_output_set_device(out, dssdev); +	if (r) { +		DSSERR("failed to connect output to new device\n"); +		return r; +	} + +	mgr = omap_dss_get_overlay_manager(dssdev->channel); + +	if (mgr->output && !force) +		return 0; + +	if (mgr->output) +		mgr->unset_output(mgr); + +	r = mgr->set_output(mgr, out); +	if (r) { +		DSSERR("failed to connect manager to output of new device\n"); + +		/* remove the output-device connection we just made */ +		omapdss_output_unset_device(out); +		return r; +	} + +	for (i = 0; i < omap_dss_get_num_overlays(); ++i) { +		struct omap_overlay *ovl = omap_dss_get_overlay(i); + +		if (!ovl->manager || force) { +			if (ovl->manager) +				ovl->unset_manager(ovl); + +			r = ovl->set_manager(ovl, mgr); +			if (r) { +				DSSERR("failed to set initial overlay\n"); +				return r; +			} +		} +	} + +	return 0; +} + +static void dss_uninit_connections(struct omap_dss_device *dssdev) +{ +	if (dssdev->output) { +		struct omap_overlay_manager *mgr = dssdev->output->manager; + +		if (mgr) +			mgr->unset_output(mgr); + +		omapdss_output_unset_device(dssdev->output); +	} +} + +int dss_init_device(struct platform_device *pdev,  		struct omap_dss_device *dssdev)  {  	struct device_attribute *attr; -	int i; -	int r; +	int i, r; +	const char *def_disp_name = dss_get_default_display_name(); +	bool force; + +	force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0; +	dss_init_connections(dssdev, force);  	/* create device sysfs files */  	i = 0;  	while ((attr = display_sysfs_attrs[i++]) != NULL) {  		r = device_create_file(&dssdev->dev, attr); -		if (r) +		if (r) { +			for (i = i - 2; i >= 0; i--) { +				attr = display_sysfs_attrs[i]; +				device_remove_file(&dssdev->dev, attr); +			} + +			dss_uninit_connections(dssdev); +  			DSSERR("failed to create sysfs file\n"); +			return r; +		}  	}  	/* create display? sysfs links */  	r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,  			dev_name(&dssdev->dev)); -	if (r) +	if (r) { +		while ((attr = display_sysfs_attrs[i++]) != NULL) +			device_remove_file(&dssdev->dev, attr); + +		dss_uninit_connections(dssdev); +  		DSSERR("failed to create sysfs display link\n"); +		return r; +	} + +	return 0;  }  void dss_uninit_device(struct platform_device *pdev, @@ -349,8 +444,7 @@ void dss_uninit_device(struct platform_device *pdev,  	while ((attr = display_sysfs_attrs[i++]) != NULL)  		device_remove_file(&dssdev->dev, attr); -	if (dssdev->manager) -		dssdev->manager->unset_device(dssdev->manager); +	dss_uninit_connections(dssdev);  }  static int dss_suspend_device(struct device *dev, void *data) diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 3266be23fc0..56748cf8760 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -29,17 +29,24 @@  #include <linux/errno.h>  #include <linux/platform_device.h>  #include <linux/regulator/consumer.h> +#include <linux/string.h>  #include <video/omapdss.h> -#include <plat/cpu.h>  #include "dss.h" +#include "dss_features.h"  static struct {  	struct regulator *vdds_dsi_reg;  	struct platform_device *dsidev; +	struct mutex lock; + +	struct omap_video_timings timings;  	struct dss_lcd_mgr_config mgr_config; +	int data_lines; + +	struct omap_dss_output output;  } dpi;  static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) @@ -121,7 +128,8 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,  static int dpi_set_mode(struct omap_dss_device *dssdev)  { -	struct omap_video_timings *t = &dssdev->panel.timings; +	struct omap_video_timings *t = &dpi.timings; +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	int lck_div = 0, pck_div = 0;  	unsigned long fck = 0;  	unsigned long pck; @@ -146,37 +154,44 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)  		t->pixel_clock = pck;  	} -	dss_mgr_set_timings(dssdev->manager, t); +	dss_mgr_set_timings(mgr, t);  	return 0;  }  static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)  { +	struct omap_overlay_manager *mgr = dssdev->output->manager; +  	dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;  	dpi.mgr_config.stallmode = false;  	dpi.mgr_config.fifohandcheck = false; -	dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines; +	dpi.mgr_config.video_port_width = dpi.data_lines;  	dpi.mgr_config.lcden_sig_polarity = 0; -	dss_mgr_set_lcd_config(dssdev->manager, &dpi.mgr_config); +	dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);  }  int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)  { +	struct omap_dss_output *out = dssdev->output;  	int r; -	if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) { +	mutex_lock(&dpi.lock); + +	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {  		DSSERR("no VDSS_DSI regulator\n"); -		return -ENODEV; +		r = -ENODEV; +		goto err_no_reg;  	} -	if (dssdev->manager == NULL) { -		DSSERR("failed to enable display: no manager\n"); -		return -ENODEV; +	if (out == NULL || out->manager == NULL) { +		DSSERR("failed to enable display: no output/manager\n"); +		r = -ENODEV; +		goto err_no_out_mgr;  	}  	r = omap_dss_start_device(dssdev); @@ -185,7 +200,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)  		goto err_start_dev;  	} -	if (cpu_is_omap34xx()) { +	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {  		r = regulator_enable(dpi.vdds_dsi_reg);  		if (r)  			goto err_reg_enable; @@ -195,6 +210,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)  	if (r)  		goto err_get_dispc; +	r = dss_dpi_select_source(dssdev->channel); +	if (r) +		goto err_src_sel; +  	if (dpi_use_dsi_pll(dssdev)) {  		r = dsi_runtime_get(dpi.dsidev);  		if (r) @@ -213,10 +232,12 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)  	mdelay(2); -	r = dss_mgr_enable(dssdev->manager); +	r = dss_mgr_enable(out->manager);  	if (r)  		goto err_mgr_enable; +	mutex_unlock(&dpi.lock); +  	return 0;  err_mgr_enable: @@ -227,20 +248,28 @@ err_dsi_pll_init:  	if (dpi_use_dsi_pll(dssdev))  		dsi_runtime_put(dpi.dsidev);  err_get_dsi: +err_src_sel:  	dispc_runtime_put();  err_get_dispc: -	if (cpu_is_omap34xx()) +	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))  		regulator_disable(dpi.vdds_dsi_reg);  err_reg_enable:  	omap_dss_stop_device(dssdev);  err_start_dev: +err_no_out_mgr: +err_no_reg: +	mutex_unlock(&dpi.lock);  	return r;  }  EXPORT_SYMBOL(omapdss_dpi_display_enable);  void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)  { -	dss_mgr_disable(dssdev->manager); +	struct omap_overlay_manager *mgr = dssdev->output->manager; + +	mutex_lock(&dpi.lock); + +	dss_mgr_disable(mgr);  	if (dpi_use_dsi_pll(dssdev)) {  		dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); @@ -250,44 +279,39 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)  	dispc_runtime_put(); -	if (cpu_is_omap34xx()) +	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))  		regulator_disable(dpi.vdds_dsi_reg);  	omap_dss_stop_device(dssdev); + +	mutex_unlock(&dpi.lock);  }  EXPORT_SYMBOL(omapdss_dpi_display_disable); -void dpi_set_timings(struct omap_dss_device *dssdev, -			struct omap_video_timings *timings) +void omapdss_dpi_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings)  { -	int r; -  	DSSDBG("dpi_set_timings\n"); -	dssdev->panel.timings = *timings; -	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { -		r = dispc_runtime_get(); -		if (r) -			return; -		dpi_set_mode(dssdev); +	mutex_lock(&dpi.lock); -		dispc_runtime_put(); -	} else { -		dss_mgr_set_timings(dssdev->manager, timings); -	} +	dpi.timings = *timings; + +	mutex_unlock(&dpi.lock);  } -EXPORT_SYMBOL(dpi_set_timings); +EXPORT_SYMBOL(omapdss_dpi_set_timings);  int dpi_check_timings(struct omap_dss_device *dssdev,  			struct omap_video_timings *timings)  {  	int r; +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	int lck_div, pck_div;  	unsigned long fck;  	unsigned long pck;  	struct dispc_clock_info dispc_cinfo; -	if (dss_mgr_check_timings(dssdev->manager, timings)) +	if (dss_mgr_check_timings(mgr, timings))  		return -EINVAL;  	if (timings->pixel_clock == 0) @@ -325,11 +349,22 @@ int dpi_check_timings(struct omap_dss_device *dssdev,  }  EXPORT_SYMBOL(dpi_check_timings); +void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) +{ +	mutex_lock(&dpi.lock); + +	dpi.data_lines = data_lines; + +	mutex_unlock(&dpi.lock); +} +EXPORT_SYMBOL(omapdss_dpi_set_data_lines); +  static int __init dpi_init_display(struct omap_dss_device *dssdev)  {  	DSSDBG("init_display\n"); -	if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { +	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && +					dpi.vdds_dsi_reg == NULL) {  		struct regulator *vdds_dsi;  		vdds_dsi = dss_get_vdds_dsi(); @@ -351,10 +386,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)  	return 0;  } -static void __init dpi_probe_pdata(struct platform_device *pdev) +static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)  {  	struct omap_dss_board_info *pdata = pdev->dev.platform_data; -	int i, r; +	const char *def_disp_name = dss_get_default_display_name(); +	struct omap_dss_device *def_dssdev; +	int i; + +	def_dssdev = NULL;  	for (i = 0; i < pdata->num_devices; ++i) {  		struct omap_dss_device *dssdev = pdata->devices[i]; @@ -362,21 +401,75 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)  		if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)  			continue; -		r = dpi_init_display(dssdev); -		if (r) { -			DSSERR("device %s init failed: %d\n", dssdev->name, r); -			continue; +		if (def_dssdev == NULL) +			def_dssdev = dssdev; + +		if (def_disp_name != NULL && +				strcmp(dssdev->name, def_disp_name) == 0) { +			def_dssdev = dssdev; +			break;  		} +	} -		r = omap_dss_register_device(dssdev, &pdev->dev, i); -		if (r) -			DSSERR("device %s register failed: %d\n", -					dssdev->name, r); +	return def_dssdev; +} + +static void __init dpi_probe_pdata(struct platform_device *dpidev) +{ +	struct omap_dss_device *plat_dssdev; +	struct omap_dss_device *dssdev; +	int r; + +	plat_dssdev = dpi_find_dssdev(dpidev); + +	if (!plat_dssdev) +		return; + +	dssdev = dss_alloc_and_init_device(&dpidev->dev); +	if (!dssdev) +		return; + +	dss_copy_device_pdata(dssdev, plat_dssdev); + +	r = dpi_init_display(dssdev); +	if (r) { +		DSSERR("device %s init failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return; +	} + +	r = dss_add_device(dssdev); +	if (r) { +		DSSERR("device %s register failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return;  	}  } +static void __init dpi_init_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &dpi.output; + +	out->pdev = pdev; +	out->id = OMAP_DSS_OUTPUT_DPI; +	out->type = OMAP_DISPLAY_TYPE_DPI; + +	dss_register_output(out); +} + +static void __exit dpi_uninit_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &dpi.output; + +	dss_unregister_output(out); +} +  static int __init omap_dpi_probe(struct platform_device *pdev)  { +	mutex_init(&dpi.lock); + +	dpi_init_output(pdev); +  	dpi_probe_pdata(pdev);  	return 0; @@ -384,7 +477,9 @@ static int __init omap_dpi_probe(struct platform_device *pdev)  static int __exit omap_dpi_remove(struct platform_device *pdev)  { -	omap_dss_unregister_child_devices(&pdev->dev); +	dss_unregister_child_devices(&pdev->dev); + +	dpi_uninit_output(pdev);  	return 0;  } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 05ee04667af..d64ac384288 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -41,7 +41,6 @@  #include <video/omapdss.h>  #include <video/mipi_display.h> -#include <plat/clock.h>  #include "dss.h"  #include "dss_features.h" @@ -333,6 +332,12 @@ struct dsi_data {  	unsigned scp_clk_refcount;  	struct dss_lcd_mgr_config mgr_config; +	struct omap_video_timings timings; +	enum omap_dss_dsi_pixel_format pix_fmt; +	enum omap_dss_dsi_mode mode; +	struct omap_dss_dsi_videomode_timings vm_timings; + +	struct omap_dss_output output;  };  struct dsi_packet_sent_handler_data { @@ -340,8 +345,6 @@ struct dsi_packet_sent_handler_data {  	struct completion *completion;  }; -static struct platform_device *dsi_pdev_map[MAX_NUM_DSI]; -  #ifdef DEBUG  static bool dsi_perf;  module_param(dsi_perf, bool, 0644); @@ -354,12 +357,19 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside  static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)  { -	return dsi_pdev_map[dssdev->phy.dsi.module]; +	return dssdev->output->pdev;  }  struct platform_device *dsi_get_dsidev_from_id(int module)  { -	return dsi_pdev_map[module]; +	struct omap_dss_output *out; +	enum omap_dss_output_id	id; + +	id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + +	out = omap_dss_get_output(id); + +	return out->pdev;  }  static inline void dsi_write_reg(struct platform_device *dsidev, @@ -1450,6 +1460,148 @@ found:  	return 0;  } +static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev, +		unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct dsi_clock_info cur, best; + +	DSSDBG("dsi_pll_calc_ddrfreq\n"); + +	memset(&best, 0, sizeof(best)); +	memset(&cur, 0, sizeof(cur)); + +	cur.clkin = clk_get_rate(dsi->sys_clk); + +	for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { +		cur.fint = cur.clkin / cur.regn; + +		if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) +			continue; + +		/* DSIPHY(MHz) = (2 * regm / regn) * clkin */ +		for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { +			unsigned long a, b; + +			a = 2 * cur.regm * (cur.clkin/1000); +			b = cur.regn; +			cur.clkin4ddr = a / b * 1000; + +			if (cur.clkin4ddr > 1800 * 1000 * 1000) +				break; + +			if (abs(cur.clkin4ddr - req_clkin4ddr) < +					abs(best.clkin4ddr - req_clkin4ddr)) { +				best = cur; +				DSSDBG("best %ld\n", best.clkin4ddr); +			} + +			if (cur.clkin4ddr == req_clkin4ddr) +				goto found; +		} +	} +found: +	if (cinfo) +		*cinfo = best; + +	return 0; +} + +static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev, +		struct dsi_clock_info *cinfo) +{ +	unsigned long max_dsi_fck; + +	max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK); + +	cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck); +	cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi; +} + +static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev, +		unsigned long req_pck, struct dsi_clock_info *cinfo, +		struct dispc_clock_info *dispc_cinfo) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	unsigned regm_dispc, best_regm_dispc; +	unsigned long dispc_clk, best_dispc_clk; +	int min_fck_per_pck; +	unsigned long max_dss_fck; +	struct dispc_clock_info best_dispc; +	bool match; + +	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + +	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; + +	if (min_fck_per_pck && +			req_pck * min_fck_per_pck > max_dss_fck) { +		DSSERR("Requested pixel clock not possible with the current " +				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " +				"the constraint off.\n"); +		min_fck_per_pck = 0; +	} + +retry: +	best_regm_dispc = 0; +	best_dispc_clk = 0; +	memset(&best_dispc, 0, sizeof(best_dispc)); +	match = false; + +	for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) { +		struct dispc_clock_info cur_dispc; + +		dispc_clk = cinfo->clkin4ddr / regm_dispc; + +		/* this will narrow down the search a bit, +		 * but still give pixclocks below what was +		 * requested */ +		if (dispc_clk  < req_pck) +			break; + +		if (dispc_clk > max_dss_fck) +			continue; + +		if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck) +			continue; + +		match = true; + +		dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc); + +		if (abs(cur_dispc.pck - req_pck) < +				abs(best_dispc.pck - req_pck)) { +			best_regm_dispc = regm_dispc; +			best_dispc_clk = dispc_clk; +			best_dispc = cur_dispc; + +			if (cur_dispc.pck == req_pck) +				goto found; +		} +	} + +	if (!match) { +		if (min_fck_per_pck) { +			DSSERR("Could not find suitable clock settings.\n" +					"Turning FCK/PCK constraint off and" +					"trying again.\n"); +			min_fck_per_pck = 0; +			goto retry; +		} + +		DSSERR("Could not find suitable clock settings.\n"); + +		return -EINVAL; +	} +found: +	cinfo->regm_dispc = best_regm_dispc; +	cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk; + +	*dispc_cinfo = best_dispc; + +	return 0; +} +  int dsi_pll_set_clock_div(struct platform_device *dsidev,  		struct dsi_clock_info *cinfo)  { @@ -1526,21 +1678,27 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,  	BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); +	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); +  	if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {  		f = cinfo->fint < 1000000 ? 0x3 :  			cinfo->fint < 1250000 ? 0x4 :  			cinfo->fint < 1500000 ? 0x5 :  			cinfo->fint < 1750000 ? 0x6 :  			0x7; -	} -	l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2); - -	if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))  		l = FLD_MOD(l, f, 4, 1);	/* DSI_PLL_FREQSEL */ +	} else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) { +		f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4; + +		l = FLD_MOD(l, f, 4, 1);	/* PLL_SELFREQDCO */ +	} +  	l = FLD_MOD(l, 1, 13, 13);		/* DSI_PLL_REFEN */  	l = FLD_MOD(l, 0, 14, 14);		/* DSIPHY_CLKINEN */  	l = FLD_MOD(l, 1, 20, 20);		/* DSI_HSDIVBYPASS */ +	if (dss_has_feature(FEAT_DSI_PLL_REFSEL)) +		l = FLD_MOD(l, 3, 22, 21);	/* REF_SYSCLK = sysclk */  	dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);  	REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0);	/* DSI_PLL_GO */ @@ -2004,15 +2162,16 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)  		return 1194 * 3;	/* 1194x24 bits */  	case 6:  		return 1365 * 3;	/* 1365x24 bits */ +	case 7: +		return 1920 * 3;	/* 1920x24 bits */  	default:  		BUG();  		return 0;  	}  } -static int dsi_set_lane_config(struct omap_dss_device *dssdev) +static int dsi_set_lane_config(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	static const u8 offsets[] = { 0, 4, 8, 12, 16 };  	static const enum dsi_lane_function functions[] = { @@ -2136,9 +2295,16 @@ static void dsi_cio_timings(struct platform_device *dsidev)  	dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);  	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); -	r = FLD_MOD(r, tlpx_half, 22, 16); +	r = FLD_MOD(r, tlpx_half, 20, 16);  	r = FLD_MOD(r, tclk_trail, 15, 8);  	r = FLD_MOD(r, tclk_zero, 7, 0); + +	if (dss_has_feature(FEAT_DSI_PHY_DCC)) { +		r = FLD_MOD(r, 0, 21, 21);	/* DCCEN = disable */ +		r = FLD_MOD(r, 1, 22, 22);	/* CLKINP_DIVBY2EN = enable */ +		r = FLD_MOD(r, 1, 23, 23);	/* CLKINP_SEL = enable */ +	} +  	dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);  	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); @@ -2147,10 +2313,9 @@ static void dsi_cio_timings(struct platform_device *dsidev)  }  /* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */ -static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, +static void dsi_cio_enable_lane_override(struct platform_device *dsidev,  		unsigned mask_p, unsigned mask_n)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int i;  	u32 l; @@ -2197,9 +2362,8 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)  	REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);  } -static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) +static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int t, i;  	bool in_use[DSI_MAX_NR_LANES]; @@ -2247,9 +2411,8 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)  }  /* return bitmask of enabled lanes, lane0 being the lsb */ -static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) +static unsigned dsi_get_lane_mask(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	unsigned mask = 0;  	int i; @@ -2262,16 +2425,15 @@ static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)  	return mask;  } -static int dsi_cio_init(struct omap_dss_device *dssdev) +static int dsi_cio_init(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int r;  	u32 l;  	DSSDBGF(); -	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); +	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));  	if (r)  		return r; @@ -2288,7 +2450,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  		goto err_scp_clk_dom;  	} -	r = dsi_set_lane_config(dssdev); +	r = dsi_set_lane_config(dsidev);  	if (r)  		goto err_scp_clk_dom; @@ -2323,7 +2485,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  			mask_p |= 1 << i;  		} -		dsi_cio_enable_lane_override(dssdev, mask_p, 0); +		dsi_cio_enable_lane_override(dsidev, mask_p, 0);  	}  	r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); @@ -2340,7 +2502,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  	dsi_if_enable(dsidev, false);  	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ -	r = dsi_cio_wait_tx_clk_esc_reset(dssdev); +	r = dsi_cio_wait_tx_clk_esc_reset(dsidev);  	if (r)  		goto err_tx_clk_esc_rst; @@ -2360,10 +2522,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)  	dsi_cio_timings(dsidev); -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {  		/* DDR_CLK_ALWAYS_ON */  		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, -			dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); +			dsi->vm_timings.ddr_clk_always_on, 13, 13);  	}  	dsi->ulps_enabled = false; @@ -2381,13 +2543,12 @@ err_cio_pwr:  		dsi_cio_disable_lane_override(dsidev);  err_scp_clk_dom:  	dsi_disable_scp_clk(dsidev); -	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); +	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));  	return r;  } -static void dsi_cio_uninit(struct omap_dss_device *dssdev) +static void dsi_cio_uninit(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	/* DDR_CLK_ALWAYS_ON */ @@ -2395,7 +2556,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev)  	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);  	dsi_disable_scp_clk(dsidev); -	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); +	dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));  }  static void dsi_config_tx_fifo(struct platform_device *dsidev, @@ -2685,6 +2846,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,  		bool enable)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); @@ -2701,7 +2863,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,  	dsi_force_tx_stop_mode_io(dsidev);  	/* start the DDR clock by sending a NULL packet */ -	if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable) +	if (dsi->vm_timings.ddr_clk_always_on && enable)  		dsi_vc_send_null(dssdev, channel);  }  EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); @@ -2987,10 +3149,9 @@ int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)  }  EXPORT_SYMBOL(dsi_vc_send_null); -static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, +static int dsi_vc_write_nosync_common(struct platform_device *dsidev,  		int channel, u8 *data, int len, enum dss_dsi_content_type type)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r;  	if (len == 0) { @@ -3021,7 +3182,9 @@ static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,  int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,  		u8 *data, int len)  { -	return dsi_vc_write_nosync_common(dssdev, channel, data, len, +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + +	return dsi_vc_write_nosync_common(dsidev, channel, data, len,  			DSS_DSI_CONTENT_DCS);  }  EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); @@ -3029,7 +3192,9 @@ EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);  int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,  		u8 *data, int len)  { -	return dsi_vc_write_nosync_common(dssdev, channel, data, len, +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + +	return dsi_vc_write_nosync_common(dsidev, channel, data, len,  			DSS_DSI_CONTENT_GENERIC);  }  EXPORT_SYMBOL(dsi_vc_generic_write_nosync); @@ -3040,7 +3205,7 @@ static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r; -	r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type); +	r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type);  	if (r)  		goto err; @@ -3118,10 +3283,9 @@ int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,  }  EXPORT_SYMBOL(dsi_vc_generic_write_2); -static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, +static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,  		int channel, u8 dcs_cmd)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int r; @@ -3139,10 +3303,9 @@ static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,  	return 0;  } -static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, +static int dsi_vc_generic_send_read_request(struct platform_device *dsidev,  		int channel, u8 *reqdata, int reqlen)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	u16 data;  	u8 data_type; @@ -3291,7 +3454,7 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r; -	r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd); +	r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);  	if (r)  		goto err; @@ -3322,7 +3485,7 @@ static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	int r; -	r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); +	r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen);  	if (r)  		return r; @@ -3604,15 +3767,15 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,  			(total_ticks * 1000) / (fck / 1000 / 1000));  } -static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) +static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	int num_line_buffers; -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { -		int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { +		int bpp = dsi_get_pixel_size(dsi->pix_fmt);  		unsigned line_buf_size = dsi_get_line_buf_size(dsidev); -		struct omap_video_timings *timings = &dssdev->panel.timings; +		struct omap_video_timings *timings = &dsi->timings;  		/*  		 * Don't use line buffers if width is greater than the video  		 * port's line buffer size @@ -3630,11 +3793,11 @@ static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)  	REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);  } -static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) +static void dsi_config_vp_sync_events(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); -	bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; -	bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	bool vsync_end = dsi->vm_timings.vp_vsync_end; +	bool hsync_end = dsi->vm_timings.vp_hsync_end;  	u32 r;  	r = dsi_read_reg(dsidev, DSI_CTRL); @@ -3648,13 +3811,13 @@ static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)  	dsi_write_reg(dsidev, DSI_CTRL, r);  } -static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) +static void dsi_config_blanking_modes(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); -	int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode; -	int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode; -	int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode; -	int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode; +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	int blanking_mode = dsi->vm_timings.blanking_mode; +	int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode; +	int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode; +	int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;  	u32 r;  	/* @@ -3741,8 +3904,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)  	int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;  	int tclk_trail, ths_exit, exiths_clk;  	bool ddr_alwon; -	struct omap_video_timings *timings = &dssdev->panel.timings; -	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +	struct omap_video_timings *timings = &dsi->timings; +	int bpp = dsi_get_pixel_size(dsi->pix_fmt);  	int ndl = dsi->num_lanes_used - 1;  	int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;  	int hsa_interleave_hs = 0, hsa_interleave_lp = 0; @@ -3852,6 +4015,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)  static int dsi_proto_config(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	u32 r;  	int buswidth = 0; @@ -3871,7 +4035,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);  	dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); -	switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) { +	switch (dsi_get_pixel_size(dsi->pix_fmt)) {  	case 16:  		buswidth = 0;  		break; @@ -3903,11 +4067,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	dsi_write_reg(dsidev, DSI_CTRL, r); -	dsi_config_vp_num_line_buffers(dssdev); +	dsi_config_vp_num_line_buffers(dsidev); -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { -		dsi_config_vp_sync_events(dssdev); -		dsi_config_blanking_modes(dssdev); +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { +		dsi_config_vp_sync_events(dsidev); +		dsi_config_blanking_modes(dsidev);  		dsi_config_cmd_mode_interleaving(dssdev);  	} @@ -3919,9 +4083,8 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)  	return 0;  } -static void dsi_proto_timings(struct omap_dss_device *dssdev) +static void dsi_proto_timings(struct platform_device *dsidev)  { -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;  	unsigned tclk_pre, tclk_post; @@ -3941,7 +4104,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)  	ths_exit = FLD_GET(r, 7, 0);  	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); -	tlpx = FLD_GET(r, 22, 16) * 2; +	tlpx = FLD_GET(r, 20, 16) * 2;  	tclk_trail = FLD_GET(r, 15, 8);  	tclk_zero = FLD_GET(r, 7, 0); @@ -3984,18 +4147,18 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)  	DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",  			enter_hs_mode_lat, exit_hs_mode_lat); -	 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +	 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {  		/* TODO: Implement a video mode check_timings function */ -		int hsa = dssdev->panel.dsi_vm_data.hsa; -		int hfp = dssdev->panel.dsi_vm_data.hfp; -		int hbp = dssdev->panel.dsi_vm_data.hbp; -		int vsa = dssdev->panel.dsi_vm_data.vsa; -		int vfp = dssdev->panel.dsi_vm_data.vfp; -		int vbp = dssdev->panel.dsi_vm_data.vbp; -		int window_sync = dssdev->panel.dsi_vm_data.window_sync; -		bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; -		struct omap_video_timings *timings = &dssdev->panel.timings; -		int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +		int hsa = dsi->vm_timings.hsa; +		int hfp = dsi->vm_timings.hfp; +		int hbp = dsi->vm_timings.hbp; +		int vsa = dsi->vm_timings.vsa; +		int vfp = dsi->vm_timings.vfp; +		int vbp = dsi->vm_timings.vbp; +		int window_sync = dsi->vm_timings.window_sync; +		bool hsync_end = dsi->vm_timings.vp_hsync_end; +		struct omap_video_timings *timings = &dsi->timings; +		int bpp = dsi_get_pixel_size(dsi->pix_fmt);  		int tl, t_he, width_bytes;  		t_he = hsync_end ? @@ -4100,16 +4263,84 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,  }  EXPORT_SYMBOL(omapdss_dsi_configure_pins); -int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) +int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, +		unsigned long ddr_clk, unsigned long lp_clk)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct dsi_clock_info cinfo; +	struct dispc_clock_info dispc_cinfo; +	unsigned lp_clk_div; +	unsigned long dsi_fclk;  	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +	unsigned long pck; +	int r; + +	DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk); + +	mutex_lock(&dsi->lock); + +	/* Calculate PLL output clock */ +	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo); +	if (r) +		goto err; + +	/* Calculate PLL's DSI clock */ +	dsi_pll_calc_dsi_fck(dsidev, &cinfo); + +	/* Calculate PLL's DISPC clock and pck & lck divs */ +	pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp; +	DSSDBG("finding dispc dividers for pck %lu\n", pck); +	r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo); +	if (r) +		goto err; + +	/* Calculate LP clock */ +	dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk; +	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2); + +	dssdev->clocks.dsi.regn = cinfo.regn; +	dssdev->clocks.dsi.regm = cinfo.regm; +	dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc; +	dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi; + +	dssdev->clocks.dsi.lp_clk_div = lp_clk_div; + +	dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div; +	dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div; + +	dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK; + +	dssdev->clocks.dispc.channel.lcd_clk_src = +		dsi->module_id == 0 ? +		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : +		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC; + +	dssdev->clocks.dsi.dsi_fclk_src = +		dsi->module_id == 0 ? +		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : +		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI; + +	mutex_unlock(&dsi->lock); +	return 0; +err: +	mutex_unlock(&dsi->lock); +	return r; +} +EXPORT_SYMBOL(omapdss_dsi_set_clocks); + +int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager; +	int bpp = dsi_get_pixel_size(dsi->pix_fmt);  	u8 data_type;  	u16 word_count;  	int r; -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { -		switch (dssdev->panel.dsi_pix_fmt) { +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { +		switch (dsi->pix_fmt) {  		case OMAP_DSS_DSI_FMT_RGB888:  			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;  			break; @@ -4133,7 +4364,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)  		/* MODE, 1 = video mode */  		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); -		word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); +		word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);  		dsi_vc_write_long_header(dsidev, channel, data_type,  				word_count, 0); @@ -4142,9 +4373,9 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)  		dsi_if_enable(dsidev, true);  	} -	r = dss_mgr_enable(dssdev->manager); +	r = dss_mgr_enable(mgr);  	if (r) { -		if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +		if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {  			dsi_if_enable(dsidev, false);  			dsi_vc_enable(dsidev, channel, false);  		} @@ -4159,8 +4390,10 @@ EXPORT_SYMBOL(dsi_enable_video_output);  void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager; -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { +	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {  		dsi_if_enable(dsidev, false);  		dsi_vc_enable(dsidev, channel, false); @@ -4171,15 +4404,15 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)  		dsi_if_enable(dsidev, true);  	} -	dss_mgr_disable(dssdev->manager); +	dss_mgr_disable(mgr);  }  EXPORT_SYMBOL(dsi_disable_video_output); -static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, -		u16 w, u16 h) +static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	unsigned bytespp;  	unsigned bytespl;  	unsigned bytespf; @@ -4190,12 +4423,14 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,  	int r;  	const unsigned channel = dsi->update_channel;  	const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); +	u16 w = dsi->timings.x_res; +	u16 h = dsi->timings.y_res;  	DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);  	dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); -	bytespp	= dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; +	bytespp	= dsi_get_pixel_size(dsi->pix_fmt) / 8;  	bytespl = w * bytespp;  	bytespf = bytespl * h; @@ -4239,7 +4474,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,  		msecs_to_jiffies(250));  	BUG_ON(r == 0); -	dss_mgr_start_update(dssdev->manager); +	dss_mgr_set_timings(mgr, &dsi->timings); + +	dss_mgr_start_update(mgr);  	if (dsi->te_enabled) {  		/* disable LP_RX_TO, so that we can receive TE.  Time to wait @@ -4297,8 +4534,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)  static void dsi_framedone_irq_callback(void *data, u32 mask)  { -	struct omap_dss_device *dssdev = (struct omap_dss_device *) data; -	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct platform_device *dsidev = (struct platform_device *) data;  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);  	/* Note: We get FRAMEDONE when DISPC has finished sending pixels and @@ -4325,13 +4561,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,  	dsi->framedone_callback = callback;  	dsi->framedone_data = data; -	dssdev->driver->get_resolution(dssdev, &dw, &dh); +	dw = dsi->timings.x_res; +	dh = dsi->timings.y_res;  #ifdef DEBUG  	dsi->update_bytes = dw * dh * -		dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; +		dsi_get_pixel_size(dsi->pix_fmt) / 8;  #endif -	dsi_update_screen_dispc(dssdev, dw, dh); +	dsi_update_screen_dispc(dssdev);  	return 0;  } @@ -4367,28 +4604,22 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	struct omap_video_timings timings; +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	int r;  	u32 irq = 0; -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { -		u16 dw, dh; - -		dssdev->driver->get_resolution(dssdev, &dw, &dh); - -		timings.x_res = dw; -		timings.y_res = dh; -		timings.hsw = 1; -		timings.hfp = 1; -		timings.hbp = 1; -		timings.vsw = 1; -		timings.vfp = 0; -		timings.vbp = 0; +	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { +		dsi->timings.hsw = 1; +		dsi->timings.hfp = 1; +		dsi->timings.hbp = 1; +		dsi->timings.vsw = 1; +		dsi->timings.vfp = 0; +		dsi->timings.vbp = 0; -		irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); +		irq = dispc_mgr_get_framedone_irq(mgr->id);  		r = omap_dispc_register_isr(dsi_framedone_irq_callback, -			(void *) dssdev, irq); +			(void *) dsidev, irq);  		if (r) {  			DSSERR("can't get FRAMEDONE irq\n");  			goto err; @@ -4397,8 +4628,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  		dsi->mgr_config.stallmode = true;  		dsi->mgr_config.fifohandcheck = true;  	} else { -		timings = dssdev->panel.timings; -  		dsi->mgr_config.stallmode = false;  		dsi->mgr_config.fifohandcheck = false;  	} @@ -4407,14 +4636,14 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  	 * override interlace, logic level and edge related parameters in  	 * omap_video_timings with default values  	 */ -	timings.interlace = false; -	timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; -	timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; -	timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; -	timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; -	timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; +	dsi->timings.interlace = false; +	dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; +	dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; +	dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; +	dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; +	dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; -	dss_mgr_set_timings(dssdev->manager, &timings); +	dss_mgr_set_timings(mgr, &dsi->timings);  	r = dsi_configure_dispc_clocks(dssdev);  	if (r) @@ -4422,29 +4651,33 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)  	dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;  	dsi->mgr_config.video_port_width = -			dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); +			dsi_get_pixel_size(dsi->pix_fmt);  	dsi->mgr_config.lcden_sig_polarity = 0; -	dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config); +	dss_mgr_set_lcd_config(mgr, &dsi->mgr_config);  	return 0;  err1: -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) +	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)  		omap_dispc_unregister_isr(dsi_framedone_irq_callback, -			(void *) dssdev, irq); +			(void *) dsidev, irq);  err:  	return r;  }  static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)  { -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager; + +	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {  		u32 irq; -		irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); +		irq = dispc_mgr_get_framedone_irq(mgr->id);  		omap_dispc_unregister_isr(dsi_framedone_irq_callback, -			(void *) dssdev, irq); +			(void *) dsidev, irq);  	}  } @@ -4477,6 +4710,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	int r;  	r = dsi_pll_init(dsidev, true, true); @@ -4489,18 +4723,18 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)  	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);  	dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); -	dss_select_lcd_clk_source(dssdev->manager->id, +	dss_select_lcd_clk_source(mgr->id,  			dssdev->clocks.dispc.channel.lcd_clk_src);  	DSSDBG("PLL OK\n"); -	r = dsi_cio_init(dssdev); +	r = dsi_cio_init(dsidev);  	if (r)  		goto err2;  	_dsi_print_reset_status(dsidev); -	dsi_proto_timings(dssdev); +	dsi_proto_timings(dsidev);  	dsi_set_lp_clk_divisor(dssdev);  	if (1) @@ -4520,11 +4754,11 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)  	return 0;  err3: -	dsi_cio_uninit(dssdev); +	dsi_cio_uninit(dsidev);  err2:  	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);  	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); -	dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); +	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);  err1:  	dsi_pll_uninit(dsidev, true); @@ -4537,6 +4771,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	if (enter_ulps && !dsi->ulps_enabled)  		dsi_enter_ulps(dsidev); @@ -4550,8 +4785,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,  	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);  	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); -	dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); -	dsi_cio_uninit(dssdev); +	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); +	dsi_cio_uninit(dsidev);  	dsi_pll_uninit(dsidev, disconnect_lanes);  } @@ -4559,6 +4794,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_dss_output *out = dssdev->output;  	int r = 0;  	DSSDBG("dsi_display_enable\n"); @@ -4567,8 +4803,8 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)  	mutex_lock(&dsi->lock); -	if (dssdev->manager == NULL) { -		DSSERR("failed to enable display: no manager\n"); +	if (out == NULL || out->manager == NULL) { +		DSSERR("failed to enable display: no output/manager\n");  		r = -ENODEV;  		goto err_start_dev;  	} @@ -4653,17 +4889,83 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)  }  EXPORT_SYMBOL(omapdss_dsi_enable_te); -static int __init dsi_init_display(struct omap_dss_device *dssdev) +void omapdss_dsi_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings)  {  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);  	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	DSSDBG("DSI init\n"); +	mutex_lock(&dsi->lock); -	if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { -		dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | -			OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; -	} +	dsi->timings = *timings; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_timings); + +void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	mutex_lock(&dsi->lock); + +	dsi->timings.x_res = w; +	dsi->timings.y_res = h; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_size); + +void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev, +		enum omap_dss_dsi_pixel_format fmt) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	mutex_lock(&dsi->lock); + +	dsi->pix_fmt = fmt; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_pixel_format); + +void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev, +		enum omap_dss_dsi_mode mode) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	mutex_lock(&dsi->lock); + +	dsi->mode = mode; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_operation_mode); + +void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev, +		struct omap_dss_dsi_videomode_timings *timings) +{ +	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	mutex_lock(&dsi->lock); + +	dsi->vm_timings = *timings; + +	mutex_unlock(&dsi->lock); +} +EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings); + +static int __init dsi_init_display(struct omap_dss_device *dssdev) +{ +	struct platform_device *dsidev = +			dsi_get_dsidev_from_id(dssdev->phy.dsi.module); +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + +	DSSDBG("DSI init\n");  	if (dsi->vdds_dsi_reg == NULL) {  		struct regulator *vdds_dsi; @@ -4806,11 +5108,15 @@ static void dsi_put_clocks(struct platform_device *dsidev)  		clk_put(dsi->sys_clk);  } -static void __init dsi_probe_pdata(struct platform_device *dsidev) +static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)  { -	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); -	struct omap_dss_board_info *pdata = dsidev->dev.platform_data; -	int i, r; +	struct omap_dss_board_info *pdata = pdev->dev.platform_data; +	struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); +	const char *def_disp_name = dss_get_default_display_name(); +	struct omap_dss_device *def_dssdev; +	int i; + +	def_dssdev = NULL;  	for (i = 0; i < pdata->num_devices; ++i) {  		struct omap_dss_device *dssdev = pdata->devices[i]; @@ -4821,19 +5127,73 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)  		if (dssdev->phy.dsi.module != dsi->module_id)  			continue; -		r = dsi_init_display(dssdev); -		if (r) { -			DSSERR("device %s init failed: %d\n", dssdev->name, r); -			continue; +		if (def_dssdev == NULL) +			def_dssdev = dssdev; + +		if (def_disp_name != NULL && +				strcmp(dssdev->name, def_disp_name) == 0) { +			def_dssdev = dssdev; +			break;  		} +	} -		r = omap_dss_register_device(dssdev, &dsidev->dev, i); -		if (r) -			DSSERR("device %s register failed: %d\n", -					dssdev->name, r); +	return def_dssdev; +} + +static void __init dsi_probe_pdata(struct platform_device *dsidev) +{ +	struct omap_dss_device *plat_dssdev; +	struct omap_dss_device *dssdev; +	int r; + +	plat_dssdev = dsi_find_dssdev(dsidev); + +	if (!plat_dssdev) +		return; + +	dssdev = dss_alloc_and_init_device(&dsidev->dev); +	if (!dssdev) +		return; + +	dss_copy_device_pdata(dssdev, plat_dssdev); + +	r = dsi_init_display(dssdev); +	if (r) { +		DSSERR("device %s init failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return; +	} + +	r = dss_add_device(dssdev); +	if (r) { +		DSSERR("device %s register failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return;  	}  } +static void __init dsi_init_output(struct platform_device *dsidev) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_dss_output *out = &dsi->output; + +	out->pdev = dsidev; +	out->id = dsi->module_id == 0 ? +			OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + +	out->type = OMAP_DISPLAY_TYPE_DSI; + +	dss_register_output(out); +} + +static void __exit dsi_uninit_output(struct platform_device *dsidev) +{ +	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); +	struct omap_dss_output *out = &dsi->output; + +	dss_unregister_output(out); +} +  /* DSI1 HW IP initialisation */  static int __init omap_dsihw_probe(struct platform_device *dsidev)  { @@ -4848,7 +5208,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)  	dsi->module_id = dsidev->id;  	dsi->pdev = dsidev; -	dsi_pdev_map[dsi->module_id] = dsidev;  	dev_set_drvdata(&dsidev->dev, dsi);  	spin_lock_init(&dsi->irq_lock); @@ -4928,6 +5287,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)  	else  		dsi->num_lanes_supported = 3; +	dsi_init_output(dsidev); +  	dsi_probe_pdata(dsidev);  	dsi_runtime_put(dsidev); @@ -4957,7 +5318,9 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)  	WARN_ON(dsi->scp_clk_refcount > 0); -	omap_dss_unregister_child_devices(&dsidev->dev); +	dss_unregister_child_devices(&dsidev->dev); + +	dsi_uninit_output(dsidev);  	pm_runtime_disable(&dsidev->dev); diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 04b4586113e..2ab1c3e9655 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -31,11 +31,11 @@  #include <linux/clk.h>  #include <linux/platform_device.h>  #include <linux/pm_runtime.h> +#include <linux/gfp.h>  #include <video/omapdss.h>  #include <plat/cpu.h> -#include <plat/clock.h>  #include "dss.h"  #include "dss_features.h" @@ -65,6 +65,13 @@ struct dss_reg {  static int dss_runtime_get(void);  static void dss_runtime_put(void); +struct dss_features { +	u8 fck_div_max; +	u8 dss_fck_multiplier; +	const char *clk_name; +	int (*dpi_select_source)(enum omap_channel channel); +}; +  static struct {  	struct platform_device *pdev;  	void __iomem    *base; @@ -83,6 +90,8 @@ static struct {  	bool		ctx_valid;  	u32		ctx[DSS_SZ_REGS / sizeof(u32)]; + +	const struct dss_features *feat;  } dss;  static const char * const dss_generic_clk_source_names[] = { @@ -144,7 +153,7 @@ static void dss_restore_context(void)  #undef SR  #undef RR -void dss_sdi_init(u8 datapairs) +void dss_sdi_init(int datapairs)  {  	u32 l; @@ -236,7 +245,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)  	return dss_generic_clk_source_names[clk_src];  } -  void dss_dump_clocks(struct seq_file *s)  {  	unsigned long dpll4_ck_rate; @@ -259,18 +267,10 @@ void dss_dump_clocks(struct seq_file *s)  		seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); -		if (cpu_is_omap3630() || cpu_is_omap44xx()) -			seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n", -					fclk_name, fclk_real_name, -					dpll4_ck_rate, -					dpll4_ck_rate / dpll4_m4_ck_rate, -					fclk_rate); -		else -			seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n", -					fclk_name, fclk_real_name, -					dpll4_ck_rate, -					dpll4_ck_rate / dpll4_m4_ck_rate, -					fclk_rate); +		seq_printf(s, "%s (%s) = %lu / %lu * %d  = %lu\n", +				fclk_name, fclk_real_name, dpll4_ck_rate, +				dpll4_ck_rate / dpll4_m4_ck_rate, +				dss.feat->dss_fck_multiplier, fclk_rate);  	} else {  		seq_printf(s, "%s (%s) = %lu\n",  				fclk_name, fclk_real_name, @@ -431,31 +431,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)  	}  } -/* calculate clock rates using dividers in cinfo */ -int dss_calc_clock_rates(struct dss_clock_info *cinfo) -{ -	if (dss.dpll4_m4_ck) { -		unsigned long prate; -		u16 fck_div_max = 16; - -		if (cpu_is_omap3630() || cpu_is_omap44xx()) -			fck_div_max = 32; - -		if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0) -			return -EINVAL; - -		prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - -		cinfo->fck = prate / cinfo->fck_div; -	} else { -		if (cinfo->fck_div != 0) -			return -EINVAL; -		cinfo->fck = clk_get_rate(dss.dss_clk); -	} - -	return 0; -} -  int dss_set_clock_div(struct dss_clock_info *cinfo)  {  	if (dss.dpll4_m4_ck) { @@ -478,26 +453,6 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)  	return 0;  } -int dss_get_clock_div(struct dss_clock_info *cinfo) -{ -	cinfo->fck = clk_get_rate(dss.dss_clk); - -	if (dss.dpll4_m4_ck) { -		unsigned long prate; - -		prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - -		if (cpu_is_omap3630() || cpu_is_omap44xx()) -			cinfo->fck_div = prate / (cinfo->fck); -		else -			cinfo->fck_div = prate / (cinfo->fck / 2); -	} else { -		cinfo->fck_div = 0; -	} - -	return 0; -} -  unsigned long dss_get_dpll4_rate(void)  {  	if (dss.dpll4_m4_ck) @@ -515,7 +470,7 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,  	unsigned long fck, max_dss_fck; -	u16 fck_div, fck_div_max = 16; +	u16 fck_div;  	int match = 0;  	int min_fck_per_pck; @@ -525,9 +480,8 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,  	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);  	fck = clk_get_rate(dss.dss_clk); -	if (req_pck == dss.cache_req_pck && -			((cpu_is_omap34xx() && prate == dss.cache_prate) || -			 dss.cache_dss_cinfo.fck == fck)) { +	if (req_pck == dss.cache_req_pck && prate == dss.cache_prate && +		dss.cache_dss_cinfo.fck == fck) {  		DSSDBG("dispc clock info found from cache.\n");  		*dss_cinfo = dss.cache_dss_cinfo;  		*dispc_cinfo = dss.cache_dispc_cinfo; @@ -564,16 +518,10 @@ retry:  		goto found;  	} else { -		if (cpu_is_omap3630() || cpu_is_omap44xx()) -			fck_div_max = 32; - -		for (fck_div = fck_div_max; fck_div > 0; --fck_div) { +		for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {  			struct dispc_clock_info cur_dispc; -			if (fck_div_max == 32) -				fck = prate / fck_div; -			else -				fck = prate / fck_div * 2; +			fck = prate / fck_div * dss.feat->dss_fck_multiplier;  			if (fck > max_dss_fck)  				continue; @@ -648,9 +596,18 @@ void dss_set_dac_pwrdn_bgz(bool enable)  	REG_FLD_MOD(DSS_CONTROL, enable, 5, 5);	/* DAC Power-Down Control */  } -void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) +void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)  { -	REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15);	/* VENC_HDMI_SWITCH */ +	enum omap_display_type dp; +	dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT); + +	/* Complain about invalid selections */ +	WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC)); +	WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI)); + +	/* Select only if we have options */ +	if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI)) +		REG_FLD_MOD(DSS_CONTROL, src, 15, 15);	/* VENC_HDMI_SWITCH */  }  enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) @@ -661,9 +618,71 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)  	if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)  		return DSS_VENC_TV_CLK; +	if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0) +		return DSS_HDMI_M_PCLK; +  	return REG_GET(DSS_CONTROL, 15, 15);  } +static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel) +{ +	if (channel != OMAP_DSS_CHANNEL_LCD) +		return -EINVAL; + +	return 0; +} + +static int dss_dpi_select_source_omap4(enum omap_channel channel) +{ +	int val; + +	switch (channel) { +	case OMAP_DSS_CHANNEL_LCD2: +		val = 0; +		break; +	case OMAP_DSS_CHANNEL_DIGIT: +		val = 1; +		break; +	default: +		return -EINVAL; +	} + +	REG_FLD_MOD(DSS_CONTROL, val, 17, 17); + +	return 0; +} + +static int dss_dpi_select_source_omap5(enum omap_channel channel) +{ +	int val; + +	switch (channel) { +	case OMAP_DSS_CHANNEL_LCD: +		val = 1; +		break; +	case OMAP_DSS_CHANNEL_LCD2: +		val = 2; +		break; +	case OMAP_DSS_CHANNEL_LCD3: +		val = 3; +		break; +	case OMAP_DSS_CHANNEL_DIGIT: +		val = 0; +		break; +	default: +		return -EINVAL; +	} + +	REG_FLD_MOD(DSS_CONTROL, val, 17, 16); + +	return 0; +} + +int dss_dpi_select_source(enum omap_channel channel) +{ +	return dss.feat->dpi_select_source(channel); +} +  static int dss_get_clocks(void)  {  	struct clk *clk; @@ -678,22 +697,11 @@ static int dss_get_clocks(void)  	dss.dss_clk = clk; -	if (cpu_is_omap34xx()) { -		clk = clk_get(NULL, "dpll4_m4_ck"); -		if (IS_ERR(clk)) { -			DSSERR("Failed to get dpll4_m4_ck\n"); -			r = PTR_ERR(clk); -			goto err; -		} -	} else if (cpu_is_omap44xx()) { -		clk = clk_get(NULL, "dpll_per_m5x2_ck"); -		if (IS_ERR(clk)) { -			DSSERR("Failed to get dpll_per_m5x2_ck\n"); -			r = PTR_ERR(clk); -			goto err; -		} -	} else { /* omap24xx */ -		clk = NULL; +	clk = clk_get(NULL, dss.feat->clk_name); +	if (IS_ERR(clk)) { +		DSSERR("Failed to get %s\n", dss.feat->clk_name); +		r = PTR_ERR(clk); +		goto err;  	}  	dss.dpll4_m4_ck = clk; @@ -749,6 +757,71 @@ void dss_debug_dump_clocks(struct seq_file *s)  }  #endif +static const struct dss_features omap24xx_dss_feats __initconst = { +	.fck_div_max		=	16, +	.dss_fck_multiplier	=	2, +	.clk_name		=	NULL, +	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3, +}; + +static const struct dss_features omap34xx_dss_feats __initconst = { +	.fck_div_max		=	16, +	.dss_fck_multiplier	=	2, +	.clk_name		=	"dpll4_m4_ck", +	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3, +}; + +static const struct dss_features omap3630_dss_feats __initconst = { +	.fck_div_max		=	32, +	.dss_fck_multiplier	=	1, +	.clk_name		=	"dpll4_m4_ck", +	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3, +}; + +static const struct dss_features omap44xx_dss_feats __initconst = { +	.fck_div_max		=	32, +	.dss_fck_multiplier	=	1, +	.clk_name		=	"dpll_per_m5x2_ck", +	.dpi_select_source	=	&dss_dpi_select_source_omap4, +}; + +static const struct dss_features omap54xx_dss_feats __initconst = { +	.fck_div_max		=	64, +	.dss_fck_multiplier	=	1, +	.clk_name		=	"dpll_per_h12x2_ck", +	.dpi_select_source	=	&dss_dpi_select_source_omap5, +}; + +static int __init dss_init_features(struct device *dev) +{ +	const struct dss_features *src; +	struct dss_features *dst; + +	dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL); +	if (!dst) { +		dev_err(dev, "Failed to allocate local DSS Features\n"); +		return -ENOMEM; +	} + +	if (cpu_is_omap24xx()) +		src = &omap24xx_dss_feats; +	else if (cpu_is_omap34xx()) +		src = &omap34xx_dss_feats; +	else if (cpu_is_omap3630()) +		src = &omap3630_dss_feats; +	else if (cpu_is_omap44xx()) +		src = &omap44xx_dss_feats; +	else if (soc_is_omap54xx()) +		src = &omap54xx_dss_feats; +	else +		return -ENODEV; + +	memcpy(dst, src, sizeof(*dst)); +	dss.feat = dst; + +	return 0; +} +  /* DSS HW IP initialisation */  static int __init omap_dsshw_probe(struct platform_device *pdev)  { @@ -758,6 +831,10 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)  	dss.pdev = pdev; +	r = dss_init_features(&dss.pdev->dev); +	if (r) +		return r; +  	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);  	if (!dss_mem) {  		DSSERR("can't get IORESOURCE_MEM DSS\n"); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index f67afe76f21..6728892f9da 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -113,6 +113,17 @@ enum dss_dsi_content_type {  	DSS_DSI_CONTENT_GENERIC,  }; +enum dss_writeback_channel { +	DSS_WB_LCD1_MGR =	0, +	DSS_WB_LCD2_MGR =	1, +	DSS_WB_TV_MGR =		2, +	DSS_WB_OVL0 =		3, +	DSS_WB_OVL1 =		4, +	DSS_WB_OVL2 =		5, +	DSS_WB_OVL3 =		6, +	DSS_WB_LCD3_MGR =	7, +}; +  struct dss_clock_info {  	/* rates that we get with dividers below */  	unsigned long fck; @@ -175,6 +186,7 @@ struct seq_file;  struct platform_device;  /* core */ +const char *dss_get_default_display_name(void);  struct bus_type *dss_get_bus(void);  struct regulator *dss_get_vdds_dsi(void);  struct regulator *dss_get_vdds_sdi(void); @@ -184,10 +196,13 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);  int dss_set_min_bus_tput(struct device *dev, unsigned long tput);  int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); -int omap_dss_register_device(struct omap_dss_device *dssdev, -		struct device *parent, int disp_num); -void omap_dss_unregister_device(struct omap_dss_device *dssdev); -void omap_dss_unregister_child_devices(struct device *parent); +struct omap_dss_device *dss_alloc_and_init_device(struct device *parent); +int dss_add_device(struct omap_dss_device *dssdev); +void dss_unregister_device(struct omap_dss_device *dssdev); +void dss_unregister_child_devices(struct device *parent); +void dss_put_device(struct omap_dss_device *dssdev); +void dss_copy_device_pdata(struct omap_dss_device *dst, +		const struct omap_dss_device *src);  /* apply */  void dss_apply_init(void); @@ -205,8 +220,11 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,  int dss_mgr_set_device(struct omap_overlay_manager *mgr,  		struct omap_dss_device *dssdev);  int dss_mgr_unset_device(struct omap_overlay_manager *mgr); +int dss_mgr_set_output(struct omap_overlay_manager *mgr, +		struct omap_dss_output *output); +int dss_mgr_unset_output(struct omap_overlay_manager *mgr);  void dss_mgr_set_timings(struct omap_overlay_manager *mgr, -		struct omap_video_timings *timings); +		const struct omap_video_timings *timings);  void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,  		const struct dss_lcd_mgr_config *config);  const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr); @@ -222,12 +240,17 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,  		struct omap_overlay_manager *mgr);  int dss_ovl_unset_manager(struct omap_overlay *ovl); +/* output */ +void dss_register_output(struct omap_dss_output *out); +void dss_unregister_output(struct omap_dss_output *out); +struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev); +  /* display */  int dss_suspend_all_devices(void);  int dss_resume_all_devices(void);  void dss_disable_all_devices(void); -void dss_init_device(struct platform_device *pdev, +int dss_init_device(struct platform_device *pdev,  		struct omap_dss_device *dssdev);  void dss_uninit_device(struct platform_device *pdev,  		struct omap_dss_device *dssdev); @@ -254,22 +277,29 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id)  		return false;  } +int dss_manager_kobj_init(struct omap_overlay_manager *mgr, +		struct platform_device *pdev); +void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr); +  /* overlay */  void dss_init_overlays(struct platform_device *pdev);  void dss_uninit_overlays(struct platform_device *pdev);  void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); -void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);  int dss_ovl_simple_check(struct omap_overlay *ovl,  		const struct omap_overlay_info *info);  int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,  		const struct omap_video_timings *mgr_timings);  bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,  		enum omap_color_mode mode); +int dss_overlay_kobj_init(struct omap_overlay *ovl, +		struct platform_device *pdev); +void dss_overlay_kobj_uninit(struct omap_overlay *ovl);  /* DSS */  int dss_init_platform_driver(void) __init;  void dss_uninit_platform_driver(void); +int dss_dpi_select_source(enum omap_channel channel);  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); @@ -279,7 +309,7 @@ void dss_dump_clocks(struct seq_file *s);  void dss_debug_dump_clocks(struct seq_file *s);  #endif -void dss_sdi_init(u8 datapairs); +void dss_sdi_init(int datapairs);  int dss_sdi_enable(void);  void dss_sdi_disable(void); @@ -296,9 +326,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);  void dss_set_dac_pwrdn_bgz(bool enable);  unsigned long dss_get_dpll4_rate(void); -int dss_calc_clock_rates(struct dss_clock_info *cinfo);  int dss_set_clock_div(struct dss_clock_info *cinfo); -int dss_get_clock_div(struct dss_clock_info *cinfo);  int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,  		struct dispc_clock_info *dispc_cinfo); @@ -427,8 +455,9 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);  void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,  		u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,  		bool manual_update); -int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, -		bool replication, const struct omap_video_timings *mgr_timings); +int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, +		bool replication, const struct omap_video_timings *mgr_timings, +		bool mem_to_mem);  int dispc_ovl_enable(enum omap_plane plane, bool enable);  void dispc_ovl_set_channel_out(enum omap_plane plane,  		enum omap_channel channel); @@ -457,6 +486,15 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,  void dispc_mgr_setup(enum omap_channel channel,  		struct omap_overlay_manager_info *info); +u32 dispc_wb_get_framedone_irq(void); +bool dispc_wb_go_busy(void); +void dispc_wb_go(void); +void dispc_wb_enable(bool enable); +bool dispc_wb_is_enabled(void); +void dispc_wb_set_channel_in(enum dss_writeback_channel channel); +int dispc_wb_setup(const struct omap_dss_writeback_info *wi, +		bool mem_to_mem, const struct omap_video_timings *timings); +  /* VENC */  #ifdef CONFIG_OMAP2_DSS_VENC  int venc_init_platform_driver(void) __init; @@ -469,6 +507,20 @@ static inline unsigned long venc_get_pixel_clock(void)  	return 0;  }  #endif +int omapdss_venc_display_enable(struct omap_dss_device *dssdev); +void omapdss_venc_display_disable(struct omap_dss_device *dssdev); +void omapdss_venc_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings); +int omapdss_venc_check_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings); +u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev); +int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss); +void omapdss_venc_set_type(struct omap_dss_device *dssdev, +		enum omap_dss_venc_type type); +void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev, +		bool invert_polarity); +int venc_panel_init(void); +void venc_panel_exit(void);  /* HDMI */  #ifdef CONFIG_OMAP4_DSS_HDMI @@ -484,7 +536,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)  #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); +void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings);  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); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 938709724f0..acbc1e1efba 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -46,7 +46,9 @@ struct omap_dss_features {  	const int num_mgrs;  	const int num_ovls; +	const int num_wbs;  	const enum omap_display_type *supported_displays; +	const enum omap_dss_output_id *supported_outputs;  	const enum omap_color_mode *supported_color_modes;  	const enum omap_overlay_caps *overlay_caps;  	const char * const *clksrc_names; @@ -106,6 +108,21 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {  	[FEAT_REG_DSIPLL_REGM_DSI]		= { 30, 26 },  }; +static const struct dss_reg_field omap5_dss_reg_fields[] = { +	[FEAT_REG_FIRHINC]			= { 12, 0 }, +	[FEAT_REG_FIRVINC]			= { 28, 16 }, +	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 15, 0 }, +	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 31, 16 }, +	[FEAT_REG_FIFOSIZE]			= { 15, 0 }, +	[FEAT_REG_HORIZONTALACCU]		= { 10, 0 }, +	[FEAT_REG_VERTICALACCU]			= { 26, 16 }, +	[FEAT_REG_DISPC_CLK_SWITCH]		= { 9, 7 }, +	[FEAT_REG_DSIPLL_REGN]			= { 8, 1 }, +	[FEAT_REG_DSIPLL_REGM]			= { 20, 9 }, +	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 25, 21 }, +	[FEAT_REG_DSIPLL_REGM_DSI]		= { 30, 26 }, +}; +  static const enum omap_display_type omap2_dss_supported_displays[] = {  	/* OMAP_DSS_CHANNEL_LCD */  	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, @@ -144,6 +161,76 @@ static const enum omap_display_type omap4_dss_supported_displays[] = {  	OMAP_DISPLAY_TYPE_DSI,  }; +static const enum omap_display_type omap5_dss_supported_displays[] = { +	/* OMAP_DSS_CHANNEL_LCD */ +	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | +	OMAP_DISPLAY_TYPE_DSI, + +	/* OMAP_DSS_CHANNEL_DIGIT */ +	OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI, + +	/* OMAP_DSS_CHANNEL_LCD2 */ +	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | +	OMAP_DISPLAY_TYPE_DSI, +}; + +static const enum omap_dss_output_id omap2_dss_supported_outputs[] = { +	/* OMAP_DSS_CHANNEL_LCD */ +	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI, + +	/* OMAP_DSS_CHANNEL_DIGIT */ +	OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = { +	/* OMAP_DSS_CHANNEL_LCD */ +	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | +	OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1, + +	/* OMAP_DSS_CHANNEL_DIGIT */ +	OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = { +	/* OMAP_DSS_CHANNEL_LCD */ +	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | +	OMAP_DSS_OUTPUT_DSI1, + +	/* OMAP_DSS_CHANNEL_DIGIT */ +	OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id omap4_dss_supported_outputs[] = { +	/* OMAP_DSS_CHANNEL_LCD */ +	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | +	OMAP_DSS_OUTPUT_DSI1, + +	/* OMAP_DSS_CHANNEL_DIGIT */ +	OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI | +	OMAP_DSS_OUTPUT_DPI, + +	/* OMAP_DSS_CHANNEL_LCD2 */ +	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | +	OMAP_DSS_OUTPUT_DSI2, +}; + +static const enum omap_dss_output_id omap5_dss_supported_outputs[] = { +	/* OMAP_DSS_CHANNEL_LCD */ +	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | +	OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2, + +	/* OMAP_DSS_CHANNEL_DIGIT */ +	OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI, + +	/* OMAP_DSS_CHANNEL_LCD2 */ +	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | +	OMAP_DSS_OUTPUT_DSI1, + +	/* OMAP_DSS_CHANNEL_LCD3 */ +	OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | +	OMAP_DSS_OUTPUT_DSI2, +}; +  static const enum omap_color_mode omap2_dss_supported_color_modes[] = {  	/* OMAP_DSS_GFX */  	OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | @@ -224,58 +311,80 @@ 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_WB */ +	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_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,  	/* OMAP_DSS_VIDEO1 */ -	OMAP_DSS_OVL_CAP_SCALE, +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | +		OMAP_DSS_OVL_CAP_REPLICATION,  	/* OMAP_DSS_VIDEO2 */ -	OMAP_DSS_OVL_CAP_SCALE, +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | +		OMAP_DSS_OVL_CAP_REPLICATION,  };  static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {  	/* OMAP_DSS_GFX */ -	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, +	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS | +		OMAP_DSS_OVL_CAP_REPLICATION,  	/* OMAP_DSS_VIDEO1 */ -	OMAP_DSS_OVL_CAP_SCALE, +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | +		OMAP_DSS_OVL_CAP_REPLICATION,  	/* OMAP_DSS_VIDEO2 */ -	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | +		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,  };  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_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | +		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,  	/* OMAP_DSS_VIDEO1 */ -	OMAP_DSS_OVL_CAP_SCALE, +	OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | +		OMAP_DSS_OVL_CAP_REPLICATION,  	/* 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_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS | +		OMAP_DSS_OVL_CAP_REPLICATION,  };  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_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS | +		OMAP_DSS_OVL_CAP_REPLICATION,  	/* 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_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | +		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,  	/* 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_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | +		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,  	/* 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, +		OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | +		OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,  };  static const char * const omap2_dss_clk_source_names[] = { @@ -298,6 +407,14 @@ static const char * const omap4_dss_clk_source_names[] = {  	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "PLL2_CLK2",  }; +static const char * const omap5_dss_clk_source_names[] = { +	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DPLL_DSI1_A_CLK1", +	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DPLL_DSI1_A_CLK2", +	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_CLK", +	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "DPLL_DSI1_C_CLK1", +	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "DPLL_DSI1_C_CLK2", +}; +  static const struct dss_param_range omap2_dss_param_range[] = {  	[FEAT_PARAM_DSS_FCK]			= { 0, 173000000 },  	[FEAT_PARAM_DSS_PCD]			= { 2, 255 }, @@ -326,6 +443,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {  	[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_DSI_FCK]			= { 0, 173000000 },  	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },  	[FEAT_PARAM_LINEWIDTH]			= { 1, 1024 },  	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 }, @@ -341,6 +459,23 @@ static const struct dss_param_range omap4_dss_param_range[] = {  	[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_DSI_FCK]			= { 0, 170000000 }, +	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 }, +	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 }, +	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 }, +	[FEAT_PARAM_MGR_HEIGHT]			= { 1, 2048 }, +}; + +static const struct dss_param_range omap5_dss_param_range[] = { +	[FEAT_PARAM_DSS_FCK]			= { 0, 200000000 }, +	[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_DSI_FCK]			= { 0, 170000000 },  	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },  	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },  	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 }, @@ -373,6 +508,26 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {  	FEAT_ALPHA_FIXED_ZORDER,  	FEAT_FIFO_MERGE,  	FEAT_OMAP3_DSI_FIFO_BUG, +	FEAT_DPI_USES_VDDS_DSI, +}; + +static const enum dss_feat_id am35xx_dss_feat_list[] = { +	FEAT_LCDENABLEPOL, +	FEAT_LCDENABLESIGNAL, +	FEAT_PCKFREEENABLE, +	FEAT_FUNCGATED, +	FEAT_LINEBUFFERSPLIT, +	FEAT_ROWREPEATENABLE, +	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_ALPHA_FIXED_ZORDER, +	FEAT_FIFO_MERGE, +	FEAT_OMAP3_DSI_FIFO_BUG,  };  static const enum dss_feat_id omap3630_dss_feat_list[] = { @@ -447,6 +602,28 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {  	FEAT_BURST_2D,  }; +static const enum dss_feat_id omap5_dss_feat_list[] = { +	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_HDMI_AUDIO_USE_MCLK, +	FEAT_HANDLE_UV_SEPARATE, +	FEAT_ATTR2, +	FEAT_CPR, +	FEAT_PRELOAD, +	FEAT_FIR_COEF_V, +	FEAT_ALPHA_FREE_ZORDER, +	FEAT_FIFO_MERGE, +	FEAT_BURST_2D, +	FEAT_DSI_PLL_SELFREQDCO, +	FEAT_DSI_PLL_REFSEL, +	FEAT_DSI_PHY_DCC, +}; +  /* OMAP2 DSS Features */  static const struct omap_dss_features omap2_dss_features = {  	.reg_fields = omap2_dss_reg_fields, @@ -458,6 +635,7 @@ static const struct omap_dss_features omap2_dss_features = {  	.num_mgrs = 2,  	.num_ovls = 3,  	.supported_displays = omap2_dss_supported_displays, +	.supported_outputs = omap2_dss_supported_outputs,  	.supported_color_modes = omap2_dss_supported_color_modes,  	.overlay_caps = omap2_dss_overlay_caps,  	.clksrc_names = omap2_dss_clk_source_names, @@ -478,6 +656,31 @@ static const struct omap_dss_features omap3430_dss_features = {  	.num_mgrs = 2,  	.num_ovls = 3,  	.supported_displays = omap3430_dss_supported_displays, +	.supported_outputs = omap3430_dss_supported_outputs, +	.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, +	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, +	.buffer_size_unit = 1, +	.burst_size_unit = 8, +}; + +/* + * AM35xx DSS Features. This is basically OMAP3 DSS Features without the + * vdds_dsi regulator. + */ +static const struct omap_dss_features am35xx_dss_features = { +	.reg_fields = omap3_dss_reg_fields, +	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), + +	.features = am35xx_dss_feat_list, +	.num_features = ARRAY_SIZE(am35xx_dss_feat_list), + +	.num_mgrs = 2, +	.num_ovls = 3, +	.supported_displays = omap3430_dss_supported_displays, +	.supported_outputs = omap3430_dss_supported_outputs,  	.supported_color_modes = omap3_dss_supported_color_modes,  	.overlay_caps = omap3430_dss_overlay_caps,  	.clksrc_names = omap3_dss_clk_source_names, @@ -497,6 +700,7 @@ static const struct omap_dss_features omap3630_dss_features = {  	.num_mgrs = 2,  	.num_ovls = 3,  	.supported_displays = omap3630_dss_supported_displays, +	.supported_outputs = omap3630_dss_supported_outputs,  	.supported_color_modes = omap3_dss_supported_color_modes,  	.overlay_caps = omap3630_dss_overlay_caps,  	.clksrc_names = omap3_dss_clk_source_names, @@ -517,7 +721,9 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {  	.num_mgrs = 3,  	.num_ovls = 4, +	.num_wbs = 1,  	.supported_displays = omap4_dss_supported_displays, +	.supported_outputs = omap4_dss_supported_outputs,  	.supported_color_modes = omap4_dss_supported_color_modes,  	.overlay_caps = omap4_dss_overlay_caps,  	.clksrc_names = omap4_dss_clk_source_names, @@ -537,7 +743,9 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {  	.num_mgrs = 3,  	.num_ovls = 4, +	.num_wbs = 1,  	.supported_displays = omap4_dss_supported_displays, +	.supported_outputs = omap4_dss_supported_outputs,  	.supported_color_modes = omap4_dss_supported_color_modes,  	.overlay_caps = omap4_dss_overlay_caps,  	.clksrc_names = omap4_dss_clk_source_names, @@ -557,7 +765,9 @@ static const struct omap_dss_features omap4_dss_features = {  	.num_mgrs = 3,  	.num_ovls = 4, +	.num_wbs = 1,  	.supported_displays = omap4_dss_supported_displays, +	.supported_outputs = omap4_dss_supported_outputs,  	.supported_color_modes = omap4_dss_supported_color_modes,  	.overlay_caps = omap4_dss_overlay_caps,  	.clksrc_names = omap4_dss_clk_source_names, @@ -567,6 +777,27 @@ static const struct omap_dss_features omap4_dss_features = {  	.burst_size_unit = 16,  }; +/* OMAP5 DSS Features */ +static const struct omap_dss_features omap5_dss_features = { +	.reg_fields = omap5_dss_reg_fields, +	.num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields), + +	.features = omap5_dss_feat_list, +	.num_features = ARRAY_SIZE(omap5_dss_feat_list), + +	.num_mgrs = 3, +	.num_ovls = 4, +	.supported_displays = omap5_dss_supported_displays, +	.supported_outputs = omap5_dss_supported_outputs, +	.supported_color_modes = omap4_dss_supported_color_modes, +	.overlay_caps = omap4_dss_overlay_caps, +	.clksrc_names = omap5_dss_clk_source_names, +	.dss_params = omap5_dss_param_range, +	.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, +	.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 = { @@ -612,6 +843,11 @@ int dss_feat_get_num_ovls(void)  	return omap_current_dss_features->num_ovls;  } +int dss_feat_get_num_wbs(void) +{ +	return omap_current_dss_features->num_wbs; +} +  unsigned long dss_feat_get_param_min(enum dss_range_param param)  {  	return omap_current_dss_features->dss_params[param].min; @@ -627,6 +863,11 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel  	return omap_current_dss_features->supported_displays[channel];  } +enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel) +{ +	return omap_current_dss_features->supported_outputs[channel]; +} +  enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)  {  	return omap_current_dss_features->supported_color_modes[plane]; @@ -694,8 +935,13 @@ void dss_features_init(void)  		omap_current_dss_features = &omap2_dss_features;  	else if (cpu_is_omap3630())  		omap_current_dss_features = &omap3630_dss_features; -	else if (cpu_is_omap34xx()) -		omap_current_dss_features = &omap3430_dss_features; +	else if (cpu_is_omap34xx()) { +		if (soc_is_am35xx()) { +			omap_current_dss_features = &am35xx_dss_features; +		} else { +			omap_current_dss_features = &omap3430_dss_features; +		} +	}  	else if (omap_rev() == OMAP4430_REV_ES1_0)  		omap_current_dss_features = &omap4430_es1_0_dss_features;  	else if (omap_rev() == OMAP4430_REV_ES2_0 || @@ -704,6 +950,8 @@ void dss_features_init(void)  		omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;  	else if (cpu_is_omap44xx())  		omap_current_dss_features = &omap4_dss_features; +	else if (soc_is_omap54xx()) +		omap_current_dss_features = &omap5_dss_features;  	else  		DSSWARN("Unsupported OMAP version");  } diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 996ffcbfed5..9218113b5e8 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -50,6 +50,7 @@ enum dss_feat_id {  	FEAT_DSI_VC_OCP_WIDTH,  	FEAT_DSI_REVERSE_TXCLKESC,  	FEAT_DSI_GNQ, +	FEAT_DPI_USES_VDDS_DSI,  	FEAT_HDMI_CTS_SWMODE,  	FEAT_HDMI_AUDIO_USE_MCLK,  	FEAT_HANDLE_UV_SEPARATE, @@ -64,6 +65,9 @@ enum dss_feat_id {  	/* An unknown HW bug causing the normal FIFO thresholds not to work */  	FEAT_OMAP3_DSI_FIFO_BUG,  	FEAT_BURST_2D, +	FEAT_DSI_PLL_SELFREQDCO, +	FEAT_DSI_PLL_REFSEL, +	FEAT_DSI_PHY_DCC,  };  /* DSS register field id */ @@ -91,6 +95,7 @@ enum dss_range_param {  	FEAT_PARAM_DSIPLL_REGM_DSI,  	FEAT_PARAM_DSIPLL_FINT,  	FEAT_PARAM_DSIPLL_LPDIV, +	FEAT_PARAM_DSI_FCK,  	FEAT_PARAM_DOWNSCALE,  	FEAT_PARAM_LINEWIDTH,  	FEAT_PARAM_MGR_WIDTH, @@ -100,9 +105,11 @@ enum dss_range_param {  /* DSS Feature Functions */  int dss_feat_get_num_mgrs(void);  int dss_feat_get_num_ovls(void); +int dss_feat_get_num_wbs(void);  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_dss_output_id dss_feat_get_supported_outputs(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, diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 060216fdc57..a48a7dd75b3 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -32,6 +32,8 @@  #include <linux/platform_device.h>  #include <linux/pm_runtime.h>  #include <linux/clk.h> +#include <linux/gpio.h> +#include <linux/regulator/consumer.h>  #include <video/omapdss.h>  #include "ti_hdmi.h" @@ -61,6 +63,13 @@ static struct {  	struct hdmi_ip_data ip_data;  	struct clk *sys_clk; +	struct regulator *vdda_hdmi_dac_reg; + +	int ct_cp_hpd_gpio; +	int ls_oe_gpio; +	int hpd_gpio; + +	struct omap_dss_output output;  } hdmi;  /* @@ -314,12 +323,47 @@ static void hdmi_runtime_put(void)  static int __init hdmi_init_display(struct omap_dss_device *dssdev)  { +	int r; + +	struct gpio gpios[] = { +		{ hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" }, +		{ hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" }, +		{ hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" }, +	}; +  	DSSDBG("init_display\n");  	dss_init_hdmi_ip_ops(&hdmi.ip_data); + +	if (hdmi.vdda_hdmi_dac_reg == NULL) { +		struct regulator *reg; + +		reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); + +		if (IS_ERR(reg)) { +			DSSERR("can't get VDDA_HDMI_DAC regulator\n"); +			return PTR_ERR(reg); +		} + +		hdmi.vdda_hdmi_dac_reg = reg; +	} + +	r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); +	if (r) +		return r; +  	return 0;  } +static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev) +{ +	DSSDBG("uninit_display\n"); + +	gpio_free(hdmi.ct_cp_hpd_gpio); +	gpio_free(hdmi.ls_oe_gpio); +	gpio_free(hdmi.hpd_gpio); +} +  static const struct hdmi_config *hdmi_find_timing(  					const struct hdmi_config *timings_arr,  					int len) @@ -459,32 +503,30 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,  static int hdmi_power_on(struct omap_dss_device *dssdev)  {  	int r; -	const struct hdmi_config *timing;  	struct omap_video_timings *p; +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	unsigned long phy; +	gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); +	gpio_set_value(hdmi.ls_oe_gpio, 1); + +	/* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */ +	udelay(300); + +	r = regulator_enable(hdmi.vdda_hdmi_dac_reg); +	if (r) +		goto err_vdac_enable; +  	r = hdmi_runtime_get();  	if (r) -		return r; +		goto err_runtime_get; -	dss_mgr_disable(dssdev->manager); +	dss_mgr_disable(mgr); -	p = &dssdev->panel.timings; +	p = &hdmi.ip_data.cfg.timings; -	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", -		dssdev->panel.timings.x_res, -		dssdev->panel.timings.y_res); +	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); -	timing = hdmi_get_timings(); -	if (timing == NULL) { -		/* HDMI code 4 corresponds to 640 * 480 VGA */ -		hdmi.ip_data.cfg.cm.code = 4; -		/* DVI mode 1 corresponds to HDMI 0 to DVI */ -		hdmi.ip_data.cfg.cm.mode = HDMI_DVI; -		hdmi.ip_data.cfg = vesa_timings[0]; -	} else { -		hdmi.ip_data.cfg = *timing; -	}  	phy = p->pixel_clock;  	hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); @@ -495,13 +537,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)  	r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);  	if (r) {  		DSSDBG("Failed to lock PLL\n"); -		goto err; +		goto err_pll_enable;  	}  	r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);  	if (r) {  		DSSDBG("Failed to start PHY\n"); -		goto err; +		goto err_phy_enable;  	}  	hdmi.ip_data.ops->video_configure(&hdmi.ip_data); @@ -521,13 +563,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)  	dispc_enable_gamma_table(0);  	/* tv size */ -	dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); +	dss_mgr_set_timings(mgr, p);  	r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);  	if (r)  		goto err_vid_enable; -	r = dss_mgr_enable(dssdev->manager); +	r = dss_mgr_enable(mgr);  	if (r)  		goto err_mgr_enable; @@ -537,20 +579,33 @@ err_mgr_enable:  	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);  err_vid_enable:  	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); +err_phy_enable:  	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); -err: +err_pll_enable:  	hdmi_runtime_put(); +err_runtime_get: +	regulator_disable(hdmi.vdda_hdmi_dac_reg); +err_vdac_enable: +	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); +	gpio_set_value(hdmi.ls_oe_gpio, 0);  	return -EIO;  }  static void hdmi_power_off(struct omap_dss_device *dssdev)  { -	dss_mgr_disable(dssdev->manager); +	struct omap_overlay_manager *mgr = dssdev->output->manager; + +	dss_mgr_disable(mgr);  	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);  	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);  	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);  	hdmi_runtime_put(); + +	regulator_disable(hdmi.vdda_hdmi_dac_reg); + +	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); +	gpio_set_value(hdmi.ls_oe_gpio, 0);  }  int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, @@ -567,25 +622,22 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,  } -void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) +void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings)  {  	struct hdmi_cm cm; +	const struct hdmi_config *t; -	cm = hdmi_get_code(&dssdev->panel.timings); -	hdmi.ip_data.cfg.cm.code = cm.code; -	hdmi.ip_data.cfg.cm.mode = cm.mode; +	mutex_lock(&hdmi.lock); -	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { -		int r; +	cm = hdmi_get_code(timings); +	hdmi.ip_data.cfg.cm = cm; -		hdmi_power_off(dssdev); +	t = hdmi_get_timings(); +	if (t != NULL) +		hdmi.ip_data.cfg = *t; -		r = hdmi_power_on(dssdev); -		if (r) -			DSSERR("failed to power on device\n"); -	} else { -		dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); -	} +	mutex_unlock(&hdmi.lock);  }  static void hdmi_dump_regs(struct seq_file *s) @@ -640,20 +692,20 @@ bool omapdss_hdmi_detect(void)  int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)  { -	struct omap_dss_hdmi_data *priv = dssdev->data; +	struct omap_dss_output *out = dssdev->output;  	int r = 0;  	DSSDBG("ENTER hdmi_display_enable\n");  	mutex_lock(&hdmi.lock); -	if (dssdev->manager == NULL) { -		DSSERR("failed to enable display: no manager\n"); +	if (out == NULL || out->manager == NULL) { +		DSSERR("failed to enable display: no output/manager\n");  		r = -ENODEV;  		goto err0;  	} -	hdmi.ip_data.hpd_gpio = priv->hpd_gpio; +	hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;  	r = omap_dss_start_device(dssdev);  	if (r) { @@ -661,26 +713,15 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)  		goto err0;  	} -	if (dssdev->platform_enable) { -		r = dssdev->platform_enable(dssdev); -		if (r) { -			DSSERR("failed to enable GPIO's\n"); -			goto err1; -		} -	} -  	r = hdmi_power_on(dssdev);  	if (r) {  		DSSERR("failed to power on device\n"); -		goto err2; +		goto err1;  	}  	mutex_unlock(&hdmi.lock);  	return 0; -err2: -	if (dssdev->platform_disable) -		dssdev->platform_disable(dssdev);  err1:  	omap_dss_stop_device(dssdev);  err0: @@ -696,9 +737,6 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)  	hdmi_power_off(dssdev); -	if (dssdev->platform_disable) -		dssdev->platform_disable(dssdev); -  	omap_dss_stop_device(dssdev);  	mutex_unlock(&hdmi.lock); @@ -869,10 +907,14 @@ int hdmi_audio_config(struct omap_dss_audio *audio)  #endif -static void __init hdmi_probe_pdata(struct platform_device *pdev) +static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)  {  	struct omap_dss_board_info *pdata = pdev->dev.platform_data; -	int r, i; +	const char *def_disp_name = dss_get_default_display_name(); +	struct omap_dss_device *def_dssdev; +	int i; + +	def_dssdev = NULL;  	for (i = 0; i < pdata->num_devices; ++i) {  		struct omap_dss_device *dssdev = pdata->devices[i]; @@ -880,17 +922,76 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)  		if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)  			continue; -		r = hdmi_init_display(dssdev); -		if (r) { -			DSSERR("device %s init failed: %d\n", dssdev->name, r); -			continue; +		if (def_dssdev == NULL) +			def_dssdev = dssdev; + +		if (def_disp_name != NULL && +				strcmp(dssdev->name, def_disp_name) == 0) { +			def_dssdev = dssdev; +			break;  		} +	} -		r = omap_dss_register_device(dssdev, &pdev->dev, i); -		if (r) -			DSSERR("device %s register failed: %d\n", -					dssdev->name, r); +	return def_dssdev; +} + +static void __init hdmi_probe_pdata(struct platform_device *pdev) +{ +	struct omap_dss_device *plat_dssdev; +	struct omap_dss_device *dssdev; +	struct omap_dss_hdmi_data *priv; +	int r; + +	plat_dssdev = hdmi_find_dssdev(pdev); + +	if (!plat_dssdev) +		return; + +	dssdev = dss_alloc_and_init_device(&pdev->dev); +	if (!dssdev) +		return; + +	dss_copy_device_pdata(dssdev, plat_dssdev); + +	priv = dssdev->data; + +	hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio; +	hdmi.ls_oe_gpio = priv->ls_oe_gpio; +	hdmi.hpd_gpio = priv->hpd_gpio; + +	dssdev->channel = OMAP_DSS_CHANNEL_DIGIT; + +	r = hdmi_init_display(dssdev); +	if (r) { +		DSSERR("device %s init failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return;  	} + +	r = dss_add_device(dssdev); +	if (r) { +		DSSERR("device %s register failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return; +	} +} + +static void __init hdmi_init_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &hdmi.output; + +	out->pdev = pdev; +	out->id = OMAP_DSS_OUTPUT_HDMI; +	out->type = OMAP_DISPLAY_TYPE_HDMI; + +	dss_register_output(out); +} + +static void __exit hdmi_uninit_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &hdmi.output; + +	dss_unregister_output(out);  }  /* HDMI HW IP initialisation */ @@ -929,23 +1030,37 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)  	hdmi.ip_data.core_av_offset = HDMI_CORE_AV;  	hdmi.ip_data.pll_offset = HDMI_PLLCTRL;  	hdmi.ip_data.phy_offset = HDMI_PHY; +  	mutex_init(&hdmi.ip_data.lock);  	hdmi_panel_init();  	dss_debugfs_create_file("hdmi", hdmi_dump_regs); +	hdmi_init_output(pdev); +  	hdmi_probe_pdata(pdev);  	return 0;  } +static int __exit hdmi_remove_child(struct device *dev, void *data) +{ +	struct omap_dss_device *dssdev = to_dss_device(dev); +	hdmi_uninit_display(dssdev); +	return 0; +} +  static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)  { -	omap_dss_unregister_child_devices(&pdev->dev); +	device_for_each_child(&pdev->dev, NULL, hdmi_remove_child); + +	dss_unregister_child_devices(&pdev->dev);  	hdmi_panel_exit(); +	hdmi_uninit_output(pdev); +  	pm_runtime_disable(&pdev->dev);  	hdmi_put_clocks(); diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c index e10844faadf..69fb115bab3 100644 --- a/drivers/video/omap2/dss/hdmi_panel.c +++ b/drivers/video/omap2/dss/hdmi_panel.c @@ -41,17 +41,34 @@ static struct {  static int hdmi_panel_probe(struct omap_dss_device *dssdev)  { +	/* Initialize default timings to VGA in DVI mode */ +	const struct omap_video_timings default_timings = { +		.x_res		= 640, +		.y_res		= 480, +		.pixel_clock	= 25175, +		.hsw		= 96, +		.hfp		= 16, +		.hbp		= 48, +		.vsw		= 2, +		.vfp		= 11, +		.vbp		= 31, + +		.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW, +		.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW, + +		.interlace	= false, +	}; +  	DSSDBG("ENTER hdmi_panel_probe\n"); -	dssdev->panel.timings = (struct omap_video_timings) -			{ 640, 480, 25175, 96, 16, 48, 2, 11, 31, -				OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, -				false, -			}; +	dssdev->panel.timings = default_timings;  	DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",  		dssdev->panel.timings.x_res,  		dssdev->panel.timings.y_res); + +	omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings); +  	return 0;  } @@ -228,6 +245,8 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)  		goto err;  	} +	omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings); +  	r = omapdss_hdmi_display_enable(dssdev);  	if (r) {  		DSSERR("failed to power on\n"); @@ -336,8 +355,8 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,  	 */  	hdmi_panel_audio_disable(dssdev); +	omapdss_hdmi_display_set_timing(dssdev, timings);  	dssdev->panel.timings = *timings; -	omapdss_hdmi_display_set_timing(dssdev);  	mutex_unlock(&hdmi.lock);  } diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c new file mode 100644 index 00000000000..9a2fb59b6f8 --- /dev/null +++ b/drivers/video/omap2/dss/manager-sysfs.c @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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/>. + */ + +#define DSS_SUBSYS_NAME "MANAGER" + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/jiffies.h> + +#include <video/omapdss.h> + +#include "dss.h" +#include "dss_features.h" + +static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) +{ +	return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name); +} + +static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf) +{ +	struct omap_dss_device *dssdev = mgr->get_device(mgr); + +	return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ? +			dssdev->name : "<none>"); +} + +static ssize_t manager_display_store(struct omap_overlay_manager *mgr, +		const char *buf, size_t size) +{ +	int r = 0; +	size_t len = size; +	struct omap_dss_device *dssdev = NULL; + +	int match(struct omap_dss_device *dssdev, void *data) +	{ +		const char *str = data; +		return sysfs_streq(dssdev->name, str); +	} + +	if (buf[size-1] == '\n') +		--len; + +	if (len > 0) +		dssdev = omap_dss_find_device((void *)buf, match); + +	if (len > 0 && dssdev == NULL) +		return -EINVAL; + +	if (dssdev) +		DSSDBG("display %s found\n", dssdev->name); + +	if (mgr->output) { +		r = mgr->unset_output(mgr); +		if (r) { +			DSSERR("failed to unset current output\n"); +			goto put_device; +		} +	} + +	if (dssdev) { +		struct omap_dss_output *out = dssdev->output; + +		/* +		 * a registered device should have an output connected to it +		 * already +		 */ +		if (!out) { +			DSSERR("device has no output connected to it\n"); +			goto put_device; +		} + +		r = mgr->set_output(mgr, out); +		if (r) { +			DSSERR("failed to set manager output\n"); +			goto put_device; +		} + +		r = mgr->apply(mgr); +		if (r) { +			DSSERR("failed to apply dispc config\n"); +			goto put_device; +		} +	} + +put_device: +	if (dssdev) +		omap_dss_put_device(dssdev); + +	return r ? r : size; +} + +static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, +					  char *buf) +{ +	struct omap_overlay_manager_info info; + +	mgr->get_manager_info(mgr, &info); + +	return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color); +} + +static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, +					   const char *buf, size_t size) +{ +	struct omap_overlay_manager_info info; +	u32 color; +	int r; + +	r = kstrtouint(buf, 0, &color); +	if (r) +		return r; + +	mgr->get_manager_info(mgr, &info); + +	info.default_color = color; + +	r = mgr->set_manager_info(mgr, &info); +	if (r) +		return r; + +	r = mgr->apply(mgr); +	if (r) +		return r; + +	return size; +} + +static const char *trans_key_type_str[] = { +	"gfx-destination", +	"video-source", +}; + +static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr, +					   char *buf) +{ +	enum omap_dss_trans_key_type key_type; +	struct omap_overlay_manager_info info; + +	mgr->get_manager_info(mgr, &info); + +	key_type = info.trans_key_type; +	BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str)); + +	return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]); +} + +static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr, +					    const char *buf, size_t size) +{ +	enum omap_dss_trans_key_type key_type; +	struct omap_overlay_manager_info info; +	int r; + +	for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST; +			key_type < ARRAY_SIZE(trans_key_type_str); key_type++) { +		if (sysfs_streq(buf, trans_key_type_str[key_type])) +			break; +	} + +	if (key_type == ARRAY_SIZE(trans_key_type_str)) +		return -EINVAL; + +	mgr->get_manager_info(mgr, &info); + +	info.trans_key_type = key_type; + +	r = mgr->set_manager_info(mgr, &info); +	if (r) +		return r; + +	r = mgr->apply(mgr); +	if (r) +		return r; + +	return size; +} + +static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, +					    char *buf) +{ +	struct omap_overlay_manager_info info; + +	mgr->get_manager_info(mgr, &info); + +	return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key); +} + +static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, +					     const char *buf, size_t size) +{ +	struct omap_overlay_manager_info info; +	u32 key_value; +	int r; + +	r = kstrtouint(buf, 0, &key_value); +	if (r) +		return r; + +	mgr->get_manager_info(mgr, &info); + +	info.trans_key = key_value; + +	r = mgr->set_manager_info(mgr, &info); +	if (r) +		return r; + +	r = mgr->apply(mgr); +	if (r) +		return r; + +	return size; +} + +static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr, +					      char *buf) +{ +	struct omap_overlay_manager_info info; + +	mgr->get_manager_info(mgr, &info); + +	return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled); +} + +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; +	bool enable; +	int r; + +	r = strtobool(buf, &enable); +	if (r) +		return r; + +	mgr->get_manager_info(mgr, &info); + +	info.trans_enabled = enable; + +	r = mgr->set_manager_info(mgr, &info); +	if (r) +		return r; + +	r = mgr->apply(mgr); +	if (r) +		return r; + +	return size; +} + +static ssize_t manager_alpha_blending_enabled_show( +		struct omap_overlay_manager *mgr, char *buf) +{ +	struct omap_overlay_manager_info info; + +	mgr->get_manager_info(mgr, &info); + +	WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); + +	return snprintf(buf, PAGE_SIZE, "%d\n", +		info.partial_alpha_enabled); +} + +static ssize_t manager_alpha_blending_enabled_store( +		struct omap_overlay_manager *mgr, +		const char *buf, size_t size) +{ +	struct omap_overlay_manager_info info; +	bool enable; +	int r; + +	WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); + +	r = strtobool(buf, &enable); +	if (r) +		return r; + +	mgr->get_manager_info(mgr, &info); + +	info.partial_alpha_enabled = enable; + +	r = mgr->set_manager_info(mgr, &info); +	if (r) +		return r; + +	r = mgr->apply(mgr); +	if (r) +		return r; + +	return size; +} + +static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr, +		char *buf) +{ +	struct omap_overlay_manager_info info; + +	mgr->get_manager_info(mgr, &info); + +	return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable); +} + +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 r; +	bool enable; + +	if (!dss_has_feature(FEAT_CPR)) +		return -ENODEV; + +	r = strtobool(buf, &enable); +	if (r) +		return r; + +	mgr->get_manager_info(mgr, &info); + +	if (info.cpr_enable == enable) +		return size; + +	info.cpr_enable = enable; + +	r = mgr->set_manager_info(mgr, &info); +	if (r) +		return r; + +	r = mgr->apply(mgr); +	if (r) +		return r; + +	return size; +} + +static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr, +		char *buf) +{ +	struct omap_overlay_manager_info info; + +	mgr->get_manager_info(mgr, &info); + +	return snprintf(buf, PAGE_SIZE, +			"%d %d %d %d %d %d %d %d %d\n", +			info.cpr_coefs.rr, +			info.cpr_coefs.rg, +			info.cpr_coefs.rb, +			info.cpr_coefs.gr, +			info.cpr_coefs.gg, +			info.cpr_coefs.gb, +			info.cpr_coefs.br, +			info.cpr_coefs.bg, +			info.cpr_coefs.bb); +} + +static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr, +		const char *buf, size_t size) +{ +	struct omap_overlay_manager_info info; +	struct omap_dss_cpr_coefs coefs; +	int r, i; +	s16 *arr; + +	if (!dss_has_feature(FEAT_CPR)) +		return -ENODEV; + +	if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd", +				&coefs.rr, &coefs.rg, &coefs.rb, +				&coefs.gr, &coefs.gg, &coefs.gb, +				&coefs.br, &coefs.bg, &coefs.bb) != 9) +		return -EINVAL; + +	arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb, +		coefs.gr, coefs.gg, coefs.gb, +		coefs.br, coefs.bg, coefs.bb }; + +	for (i = 0; i < 9; ++i) { +		if (arr[i] < -512 || arr[i] > 511) +			return -EINVAL; +	} + +	mgr->get_manager_info(mgr, &info); + +	info.cpr_coefs = coefs; + +	r = mgr->set_manager_info(mgr, &info); +	if (r) +		return r; + +	r = mgr->apply(mgr); +	if (r) +		return r; + +	return size; +} + +struct manager_attribute { +	struct attribute attr; +	ssize_t (*show)(struct omap_overlay_manager *, char *); +	ssize_t	(*store)(struct omap_overlay_manager *, const char *, size_t); +}; + +#define MANAGER_ATTR(_name, _mode, _show, _store) \ +	struct manager_attribute manager_attr_##_name = \ +	__ATTR(_name, _mode, _show, _store) + +static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL); +static MANAGER_ATTR(display, S_IRUGO|S_IWUSR, +		manager_display_show, manager_display_store); +static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR, +		manager_default_color_show, manager_default_color_store); +static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR, +		manager_trans_key_type_show, manager_trans_key_type_store); +static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR, +		manager_trans_key_value_show, manager_trans_key_value_store); +static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, +		manager_trans_key_enabled_show, +		manager_trans_key_enabled_store); +static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, +		manager_alpha_blending_enabled_show, +		manager_alpha_blending_enabled_store); +static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR, +		manager_cpr_enable_show, +		manager_cpr_enable_store); +static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR, +		manager_cpr_coef_show, +		manager_cpr_coef_store); + + +static struct attribute *manager_sysfs_attrs[] = { +	&manager_attr_name.attr, +	&manager_attr_display.attr, +	&manager_attr_default_color.attr, +	&manager_attr_trans_key_type.attr, +	&manager_attr_trans_key_value.attr, +	&manager_attr_trans_key_enabled.attr, +	&manager_attr_alpha_blending_enabled.attr, +	&manager_attr_cpr_enable.attr, +	&manager_attr_cpr_coef.attr, +	NULL +}; + +static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, +		char *buf) +{ +	struct omap_overlay_manager *manager; +	struct manager_attribute *manager_attr; + +	manager = container_of(kobj, struct omap_overlay_manager, kobj); +	manager_attr = container_of(attr, struct manager_attribute, attr); + +	if (!manager_attr->show) +		return -ENOENT; + +	return manager_attr->show(manager, buf); +} + +static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, +		const char *buf, size_t size) +{ +	struct omap_overlay_manager *manager; +	struct manager_attribute *manager_attr; + +	manager = container_of(kobj, struct omap_overlay_manager, kobj); +	manager_attr = container_of(attr, struct manager_attribute, attr); + +	if (!manager_attr->store) +		return -ENOENT; + +	return manager_attr->store(manager, buf, size); +} + +static const struct sysfs_ops manager_sysfs_ops = { +	.show = manager_attr_show, +	.store = manager_attr_store, +}; + +static struct kobj_type manager_ktype = { +	.sysfs_ops = &manager_sysfs_ops, +	.default_attrs = manager_sysfs_attrs, +}; + +int dss_manager_kobj_init(struct omap_overlay_manager *mgr, +		struct platform_device *pdev) +{ +	return kobject_init_and_add(&mgr->kobj, &manager_ktype, +			&pdev->dev.kobj, "manager%d", mgr->id); +} + +void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr) +{ +	kobject_del(&mgr->kobj); +	kobject_put(&mgr->kobj); +} diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 53710fadc82..c54d2f620ce 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -36,463 +36,15 @@  static int num_managers;  static struct omap_overlay_manager *managers; -static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) +static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)  { -	return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name); +	return mgr->output ? mgr->output->device : NULL;  } -static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf) -{ -	return snprintf(buf, PAGE_SIZE, "%s\n", -			mgr->device ? mgr->device->name : "<none>"); -} - -static ssize_t manager_display_store(struct omap_overlay_manager *mgr, -		const char *buf, size_t size) -{ -	int r = 0; -	size_t len = size; -	struct omap_dss_device *dssdev = NULL; - -	int match(struct omap_dss_device *dssdev, void *data) -	{ -		const char *str = data; -		return sysfs_streq(dssdev->name, str); -	} - -	if (buf[size-1] == '\n') -		--len; - -	if (len > 0) -		dssdev = omap_dss_find_device((void *)buf, match); - -	if (len > 0 && dssdev == NULL) -		return -EINVAL; - -	if (dssdev) -		DSSDBG("display %s found\n", dssdev->name); - -	if (mgr->device) { -		r = mgr->unset_device(mgr); -		if (r) { -			DSSERR("failed to unset display\n"); -			goto put_device; -		} -	} - -	if (dssdev) { -		r = mgr->set_device(mgr, dssdev); -		if (r) { -			DSSERR("failed to set manager\n"); -			goto put_device; -		} - -		r = mgr->apply(mgr); -		if (r) { -			DSSERR("failed to apply dispc config\n"); -			goto put_device; -		} -	} - -put_device: -	if (dssdev) -		omap_dss_put_device(dssdev); - -	return r ? r : size; -} - -static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, -					  char *buf) -{ -	struct omap_overlay_manager_info info; - -	mgr->get_manager_info(mgr, &info); - -	return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color); -} - -static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, -					   const char *buf, size_t size) -{ -	struct omap_overlay_manager_info info; -	u32 color; -	int r; - -	r = kstrtouint(buf, 0, &color); -	if (r) -		return r; - -	mgr->get_manager_info(mgr, &info); - -	info.default_color = color; - -	r = mgr->set_manager_info(mgr, &info); -	if (r) -		return r; - -	r = mgr->apply(mgr); -	if (r) -		return r; - -	return size; -} - -static const char *trans_key_type_str[] = { -	"gfx-destination", -	"video-source", -}; - -static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr, -					   char *buf) -{ -	enum omap_dss_trans_key_type key_type; -	struct omap_overlay_manager_info info; - -	mgr->get_manager_info(mgr, &info); - -	key_type = info.trans_key_type; -	BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str)); - -	return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]); -} - -static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr, -					    const char *buf, size_t size) -{ -	enum omap_dss_trans_key_type key_type; -	struct omap_overlay_manager_info info; -	int r; - -	for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST; -			key_type < ARRAY_SIZE(trans_key_type_str); key_type++) { -		if (sysfs_streq(buf, trans_key_type_str[key_type])) -			break; -	} - -	if (key_type == ARRAY_SIZE(trans_key_type_str)) -		return -EINVAL; - -	mgr->get_manager_info(mgr, &info); - -	info.trans_key_type = key_type; - -	r = mgr->set_manager_info(mgr, &info); -	if (r) -		return r; - -	r = mgr->apply(mgr); -	if (r) -		return r; - -	return size; -} - -static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, -					    char *buf) -{ -	struct omap_overlay_manager_info info; - -	mgr->get_manager_info(mgr, &info); - -	return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key); -} - -static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, -					     const char *buf, size_t size) -{ -	struct omap_overlay_manager_info info; -	u32 key_value; -	int r; - -	r = kstrtouint(buf, 0, &key_value); -	if (r) -		return r; - -	mgr->get_manager_info(mgr, &info); - -	info.trans_key = key_value; - -	r = mgr->set_manager_info(mgr, &info); -	if (r) -		return r; - -	r = mgr->apply(mgr); -	if (r) -		return r; - -	return size; -} - -static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr, -					      char *buf) -{ -	struct omap_overlay_manager_info info; - -	mgr->get_manager_info(mgr, &info); - -	return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled); -} - -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; -	bool enable; -	int r; - -	r = strtobool(buf, &enable); -	if (r) -		return r; - -	mgr->get_manager_info(mgr, &info); - -	info.trans_enabled = enable; - -	r = mgr->set_manager_info(mgr, &info); -	if (r) -		return r; - -	r = mgr->apply(mgr); -	if (r) -		return r; - -	return size; -} - -static ssize_t manager_alpha_blending_enabled_show( -		struct omap_overlay_manager *mgr, char *buf) -{ -	struct omap_overlay_manager_info info; - -	mgr->get_manager_info(mgr, &info); - -	WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); - -	return snprintf(buf, PAGE_SIZE, "%d\n", -		info.partial_alpha_enabled); -} - -static ssize_t manager_alpha_blending_enabled_store( -		struct omap_overlay_manager *mgr, -		const char *buf, size_t size) -{ -	struct omap_overlay_manager_info info; -	bool enable; -	int r; - -	WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); - -	r = strtobool(buf, &enable); -	if (r) -		return r; - -	mgr->get_manager_info(mgr, &info); - -	info.partial_alpha_enabled = enable; - -	r = mgr->set_manager_info(mgr, &info); -	if (r) -		return r; - -	r = mgr->apply(mgr); -	if (r) -		return r; - -	return size; -} - -static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr, -		char *buf) -{ -	struct omap_overlay_manager_info info; - -	mgr->get_manager_info(mgr, &info); - -	return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable); -} - -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 r; -	bool enable; - -	if (!dss_has_feature(FEAT_CPR)) -		return -ENODEV; - -	r = strtobool(buf, &enable); -	if (r) -		return r; - -	mgr->get_manager_info(mgr, &info); - -	if (info.cpr_enable == enable) -		return size; - -	info.cpr_enable = enable; - -	r = mgr->set_manager_info(mgr, &info); -	if (r) -		return r; - -	r = mgr->apply(mgr); -	if (r) -		return r; - -	return size; -} - -static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr, -		char *buf) -{ -	struct omap_overlay_manager_info info; - -	mgr->get_manager_info(mgr, &info); - -	return snprintf(buf, PAGE_SIZE, -			"%d %d %d %d %d %d %d %d %d\n", -			info.cpr_coefs.rr, -			info.cpr_coefs.rg, -			info.cpr_coefs.rb, -			info.cpr_coefs.gr, -			info.cpr_coefs.gg, -			info.cpr_coefs.gb, -			info.cpr_coefs.br, -			info.cpr_coefs.bg, -			info.cpr_coefs.bb); -} - -static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr, -		const char *buf, size_t size) -{ -	struct omap_overlay_manager_info info; -	struct omap_dss_cpr_coefs coefs; -	int r, i; -	s16 *arr; - -	if (!dss_has_feature(FEAT_CPR)) -		return -ENODEV; - -	if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd", -				&coefs.rr, &coefs.rg, &coefs.rb, -				&coefs.gr, &coefs.gg, &coefs.gb, -				&coefs.br, &coefs.bg, &coefs.bb) != 9) -		return -EINVAL; - -	arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb, -		coefs.gr, coefs.gg, coefs.gb, -		coefs.br, coefs.bg, coefs.bb }; - -	for (i = 0; i < 9; ++i) { -		if (arr[i] < -512 || arr[i] > 511) -			return -EINVAL; -	} - -	mgr->get_manager_info(mgr, &info); - -	info.cpr_coefs = coefs; - -	r = mgr->set_manager_info(mgr, &info); -	if (r) -		return r; - -	r = mgr->apply(mgr); -	if (r) -		return r; - -	return size; -} - -struct manager_attribute { -	struct attribute attr; -	ssize_t (*show)(struct omap_overlay_manager *, char *); -	ssize_t	(*store)(struct omap_overlay_manager *, const char *, size_t); -}; - -#define MANAGER_ATTR(_name, _mode, _show, _store) \ -	struct manager_attribute manager_attr_##_name = \ -	__ATTR(_name, _mode, _show, _store) - -static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL); -static MANAGER_ATTR(display, S_IRUGO|S_IWUSR, -		manager_display_show, manager_display_store); -static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR, -		manager_default_color_show, manager_default_color_store); -static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR, -		manager_trans_key_type_show, manager_trans_key_type_store); -static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR, -		manager_trans_key_value_show, manager_trans_key_value_store); -static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, -		manager_trans_key_enabled_show, -		manager_trans_key_enabled_store); -static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, -		manager_alpha_blending_enabled_show, -		manager_alpha_blending_enabled_store); -static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR, -		manager_cpr_enable_show, -		manager_cpr_enable_store); -static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR, -		manager_cpr_coef_show, -		manager_cpr_coef_store); - - -static struct attribute *manager_sysfs_attrs[] = { -	&manager_attr_name.attr, -	&manager_attr_display.attr, -	&manager_attr_default_color.attr, -	&manager_attr_trans_key_type.attr, -	&manager_attr_trans_key_value.attr, -	&manager_attr_trans_key_enabled.attr, -	&manager_attr_alpha_blending_enabled.attr, -	&manager_attr_cpr_enable.attr, -	&manager_attr_cpr_coef.attr, -	NULL -}; - -static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, -		char *buf) -{ -	struct omap_overlay_manager *manager; -	struct manager_attribute *manager_attr; - -	manager = container_of(kobj, struct omap_overlay_manager, kobj); -	manager_attr = container_of(attr, struct manager_attribute, attr); - -	if (!manager_attr->show) -		return -ENOENT; - -	return manager_attr->show(manager, buf); -} - -static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, -		const char *buf, size_t size) -{ -	struct omap_overlay_manager *manager; -	struct manager_attribute *manager_attr; - -	manager = container_of(kobj, struct omap_overlay_manager, kobj); -	manager_attr = container_of(attr, struct manager_attribute, attr); - -	if (!manager_attr->store) -		return -ENOENT; - -	return manager_attr->store(manager, buf, size); -} - -static const struct sysfs_ops manager_sysfs_ops = { -	.show = manager_attr_show, -	.store = manager_attr_store, -}; - -static struct kobj_type manager_ktype = { -	.sysfs_ops = &manager_sysfs_ops, -	.default_attrs = manager_sysfs_attrs, -}; -  static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)  {  	unsigned long timeout = msecs_to_jiffies(500); +	struct omap_dss_device *dssdev = mgr->get_device(mgr);  	u32 irq;  	int r; @@ -500,9 +52,9 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)  	if (r)  		return r; -	if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) +	if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)  		irq = DISPC_IRQ_EVSYNC_ODD; -	else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) +	else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)  		irq = DISPC_IRQ_EVSYNC_EVEN;  	else  		irq = dispc_mgr_get_vsync_irq(mgr->id); @@ -547,23 +99,24 @@ int dss_init_overlay_managers(struct platform_device *pdev)  			break;  		} -		mgr->set_device = &dss_mgr_set_device; -		mgr->unset_device = &dss_mgr_unset_device; +		mgr->set_output = &dss_mgr_set_output; +		mgr->unset_output = &dss_mgr_unset_output;  		mgr->apply = &omap_dss_mgr_apply;  		mgr->set_manager_info = &dss_mgr_set_info;  		mgr->get_manager_info = &dss_mgr_get_info;  		mgr->wait_for_go = &dss_mgr_wait_for_go;  		mgr->wait_for_vsync = &dss_mgr_wait_for_vsync; +		mgr->get_device = &dss_mgr_get_device;  		mgr->caps = 0;  		mgr->supported_displays =  			dss_feat_get_supported_displays(mgr->id); +		mgr->supported_outputs = +			dss_feat_get_supported_outputs(mgr->id);  		INIT_LIST_HEAD(&mgr->overlays); -		r = kobject_init_and_add(&mgr->kobj, &manager_ktype, -				&pdev->dev.kobj, "manager%d", i); - +		r = dss_manager_kobj_init(mgr, pdev);  		if (r)  			DSSERR("failed to create sysfs file\n");  	} @@ -577,9 +130,7 @@ void dss_uninit_overlay_managers(struct platform_device *pdev)  	for (i = 0; i < num_managers; ++i) {  		struct omap_overlay_manager *mgr = &managers[i]; - -		kobject_del(&mgr->kobj); -		kobject_put(&mgr->kobj); +		dss_manager_kobj_uninit(mgr);  	}  	kfree(managers); diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c new file mode 100644 index 00000000000..813f26682b7 --- /dev/null +++ b/drivers/video/omap2/dss/output.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2012 Texas Instruments Ltd + * Author: Archit Taneja <archit@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/platform_device.h> +#include <linux/slab.h> + +#include <video/omapdss.h> + +#include "dss.h" + +static LIST_HEAD(output_list); +static DEFINE_MUTEX(output_lock); + +int omapdss_output_set_device(struct omap_dss_output *out, +		struct omap_dss_device *dssdev) +{ +	int r; + +	mutex_lock(&output_lock); + +	if (out->device) { +		DSSERR("output already has device %s connected to it\n", +			out->device->name); +		r = -EINVAL; +		goto err; +	} + +	if (out->type != dssdev->type) { +		DSSERR("output type and display type don't match\n"); +		r = -EINVAL; +		goto err; +	} + +	out->device = dssdev; +	dssdev->output = out; + +	mutex_unlock(&output_lock); + +	return 0; +err: +	mutex_unlock(&output_lock); + +	return r; +} +EXPORT_SYMBOL(omapdss_output_set_device); + +int omapdss_output_unset_device(struct omap_dss_output *out) +{ +	int r; + +	mutex_lock(&output_lock); + +	if (!out->device) { +		DSSERR("output doesn't have a device connected to it\n"); +		r = -EINVAL; +		goto err; +	} + +	if (out->device->state != OMAP_DSS_DISPLAY_DISABLED) { +		DSSERR("device %s is not disabled, cannot unset device\n", +				out->device->name); +		r = -EINVAL; +		goto err; +	} + +	out->device->output = NULL; +	out->device = NULL; + +	mutex_unlock(&output_lock); + +	return 0; +err: +	mutex_unlock(&output_lock); + +	return r; +} +EXPORT_SYMBOL(omapdss_output_unset_device); + +void dss_register_output(struct omap_dss_output *out) +{ +	list_add_tail(&out->list, &output_list); +} + +void dss_unregister_output(struct omap_dss_output *out) +{ +	list_del(&out->list); +} + +struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id) +{ +	struct omap_dss_output *out; + +	list_for_each_entry(out, &output_list, list) { +		if (out->id == id) +			return out; +	} + +	return NULL; +} + +struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev) +{ +	struct omap_dss_output *out = NULL; +	enum omap_dss_output_id id; + +	switch (dssdev->type) { +	case OMAP_DISPLAY_TYPE_DPI: +		out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI); +		break; +	case OMAP_DISPLAY_TYPE_DBI: +		out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI); +		break; +	case OMAP_DISPLAY_TYPE_SDI: +		out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI); +		break; +	case OMAP_DISPLAY_TYPE_VENC: +		out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC); +		break; +	case OMAP_DISPLAY_TYPE_HDMI: +		out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI); +		break; +	case OMAP_DISPLAY_TYPE_DSI: +		id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 : +					OMAP_DSS_OUTPUT_DSI2; +		out = omap_dss_get_output(id); +		break; +	default: +		break; +	} + +	return out; +} diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/omap2/dss/overlay-sysfs.c new file mode 100644 index 00000000000..4cc5ddebfb3 --- /dev/null +++ b/drivers/video/omap2/dss/overlay-sysfs.c @@ -0,0 +1,456 @@ +/* + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * 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/>. + */ + +#define DSS_SUBSYS_NAME "OVERLAY" + +#include <linux/module.h> +#include <linux/err.h> +#include <linux/sysfs.h> +#include <linux/kobject.h> +#include <linux/platform_device.h> + +#include <video/omapdss.h> + +#include "dss.h" +#include "dss_features.h" + +static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) +{ +	return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); +} + +static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf) +{ +	return snprintf(buf, PAGE_SIZE, "%s\n", +			ovl->manager ? ovl->manager->name : "<none>"); +} + +static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, +		size_t size) +{ +	int i, r; +	struct omap_overlay_manager *mgr = NULL; +	struct omap_overlay_manager *old_mgr; +	int len = size; + +	if (buf[size-1] == '\n') +		--len; + +	if (len > 0) { +		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { +			mgr = omap_dss_get_overlay_manager(i); + +			if (sysfs_streq(buf, mgr->name)) +				break; + +			mgr = NULL; +		} +	} + +	if (len > 0 && mgr == NULL) +		return -EINVAL; + +	if (mgr) +		DSSDBG("manager %s found\n", mgr->name); + +	if (mgr == ovl->manager) +		return size; + +	old_mgr = ovl->manager; + +	r = dispc_runtime_get(); +	if (r) +		return r; + +	/* detach old manager */ +	if (old_mgr) { +		r = ovl->unset_manager(ovl); +		if (r) { +			DSSERR("detach failed\n"); +			goto err; +		} + +		r = old_mgr->apply(old_mgr); +		if (r) +			goto err; +	} + +	if (mgr) { +		r = ovl->set_manager(ovl, mgr); +		if (r) { +			DSSERR("Failed to attach overlay\n"); +			goto err; +		} + +		r = mgr->apply(mgr); +		if (r) +			goto err; +	} + +	dispc_runtime_put(); + +	return size; + +err: +	dispc_runtime_put(); +	return r; +} + +static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) +{ +	struct omap_overlay_info info; + +	ovl->get_overlay_info(ovl, &info); + +	return snprintf(buf, PAGE_SIZE, "%d,%d\n", +			info.width, info.height); +} + +static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf) +{ +	struct omap_overlay_info info; + +	ovl->get_overlay_info(ovl, &info); + +	return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width); +} + +static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf) +{ +	struct omap_overlay_info info; + +	ovl->get_overlay_info(ovl, &info); + +	return snprintf(buf, PAGE_SIZE, "%d,%d\n", +			info.pos_x, info.pos_y); +} + +static ssize_t overlay_position_store(struct omap_overlay *ovl, +		const char *buf, size_t size) +{ +	int r; +	char *last; +	struct omap_overlay_info info; + +	ovl->get_overlay_info(ovl, &info); + +	info.pos_x = simple_strtoul(buf, &last, 10); +	++last; +	if (last - buf >= size) +		return -EINVAL; + +	info.pos_y = simple_strtoul(last, &last, 10); + +	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_output_size_show(struct omap_overlay *ovl, char *buf) +{ +	struct omap_overlay_info info; + +	ovl->get_overlay_info(ovl, &info); + +	return snprintf(buf, PAGE_SIZE, "%d,%d\n", +			info.out_width, info.out_height); +} + +static ssize_t overlay_output_size_store(struct omap_overlay *ovl, +		const char *buf, size_t size) +{ +	int r; +	char *last; +	struct omap_overlay_info info; + +	ovl->get_overlay_info(ovl, &info); + +	info.out_width = simple_strtoul(buf, &last, 10); +	++last; +	if (last - buf >= size) +		return -EINVAL; + +	info.out_height = simple_strtoul(last, &last, 10); + +	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_enabled_show(struct omap_overlay *ovl, char *buf) +{ +	return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl)); +} + +static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, +		size_t size) +{ +	int r; +	bool enable; + +	r = strtobool(buf, &enable); +	if (r) +		return r; + +	if (enable) +		r = ovl->enable(ovl); +	else +		r = ovl->disable(ovl); + +	if (r) +		return r; + +	return size; +} + +static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf) +{ +	struct omap_overlay_info info; + +	ovl->get_overlay_info(ovl, &info); + +	return snprintf(buf, PAGE_SIZE, "%d\n", +			info.global_alpha); +} + +static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, +		const char *buf, size_t size) +{ +	int r; +	u8 alpha; +	struct omap_overlay_info info; + +	if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) +		return -ENODEV; + +	r = kstrtou8(buf, 0, &alpha); +	if (r) +		return r; + +	ovl->get_overlay_info(ovl, &info); + +	info.global_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_pre_mult_alpha_show(struct omap_overlay *ovl, +		char *buf) +{ +	struct omap_overlay_info info; + +	ovl->get_overlay_info(ovl, &info); + +	return snprintf(buf, PAGE_SIZE, "%d\n", +			info.pre_mult_alpha); +} + +static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, +		const char *buf, size_t size) +{ +	int r; +	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); + +	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) +{ +	struct omap_overlay_info info; + +	ovl->get_overlay_info(ovl, &info); + +	return snprintf(buf, PAGE_SIZE, "%d\n", 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) +		return r; + +	if (ovl->manager) { +		r = ovl->manager->apply(ovl->manager); +		if (r) +			return r; +	} + +	return size; +} + +struct overlay_attribute { +	struct attribute attr; +	ssize_t (*show)(struct omap_overlay *, char *); +	ssize_t	(*store)(struct omap_overlay *, const char *, size_t); +}; + +#define OVERLAY_ATTR(_name, _mode, _show, _store) \ +	struct overlay_attribute overlay_attr_##_name = \ +	__ATTR(_name, _mode, _show, _store) + +static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL); +static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR, +		overlay_manager_show, overlay_manager_store); +static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL); +static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL); +static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR, +		overlay_position_show, overlay_position_store); +static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR, +		overlay_output_size_show, overlay_output_size_store); +static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, +		overlay_enabled_show, overlay_enabled_store); +static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, +		overlay_global_alpha_show, overlay_global_alpha_store); +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, +	&overlay_attr_manager.attr, +	&overlay_attr_input_size.attr, +	&overlay_attr_screen_width.attr, +	&overlay_attr_position.attr, +	&overlay_attr_output_size.attr, +	&overlay_attr_enabled.attr, +	&overlay_attr_global_alpha.attr, +	&overlay_attr_pre_mult_alpha.attr, +	&overlay_attr_zorder.attr, +	NULL +}; + +static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, +		char *buf) +{ +	struct omap_overlay *overlay; +	struct overlay_attribute *overlay_attr; + +	overlay = container_of(kobj, struct omap_overlay, kobj); +	overlay_attr = container_of(attr, struct overlay_attribute, attr); + +	if (!overlay_attr->show) +		return -ENOENT; + +	return overlay_attr->show(overlay, buf); +} + +static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, +		const char *buf, size_t size) +{ +	struct omap_overlay *overlay; +	struct overlay_attribute *overlay_attr; + +	overlay = container_of(kobj, struct omap_overlay, kobj); +	overlay_attr = container_of(attr, struct overlay_attribute, attr); + +	if (!overlay_attr->store) +		return -ENOENT; + +	return overlay_attr->store(overlay, buf, size); +} + +static const struct sysfs_ops overlay_sysfs_ops = { +	.show = overlay_attr_show, +	.store = overlay_attr_store, +}; + +static struct kobj_type overlay_ktype = { +	.sysfs_ops = &overlay_sysfs_ops, +	.default_attrs = overlay_sysfs_attrs, +}; + +int dss_overlay_kobj_init(struct omap_overlay *ovl, +		struct platform_device *pdev) +{ +	return kobject_init_and_add(&ovl->kobj, &overlay_ktype, +			&pdev->dev.kobj, "overlay%d", ovl->id); +} + +void dss_overlay_kobj_uninit(struct omap_overlay *ovl) +{ +	kobject_del(&ovl->kobj); +	kobject_put(&ovl->kobj); +} diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 952c6fad9a8..45f4994bc6b 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -26,13 +26,11 @@  #include <linux/module.h>  #include <linux/err.h>  #include <linux/sysfs.h> -#include <linux/kobject.h>  #include <linux/platform_device.h>  #include <linux/delay.h>  #include <linux/slab.h>  #include <video/omapdss.h> -#include <plat/cpu.h>  #include "dss.h"  #include "dss_features.h" @@ -40,417 +38,13 @@  static int num_overlays;  static struct omap_overlay *overlays; -static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) +static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)  { -	return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); +	return ovl->manager ? +		(ovl->manager->output ? ovl->manager->output->device : NULL) : +		NULL;  } -static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf) -{ -	return snprintf(buf, PAGE_SIZE, "%s\n", -			ovl->manager ? ovl->manager->name : "<none>"); -} - -static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, -		size_t size) -{ -	int i, r; -	struct omap_overlay_manager *mgr = NULL; -	struct omap_overlay_manager *old_mgr; -	int len = size; - -	if (buf[size-1] == '\n') -		--len; - -	if (len > 0) { -		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { -			mgr = omap_dss_get_overlay_manager(i); - -			if (sysfs_streq(buf, mgr->name)) -				break; - -			mgr = NULL; -		} -	} - -	if (len > 0 && mgr == NULL) -		return -EINVAL; - -	if (mgr) -		DSSDBG("manager %s found\n", mgr->name); - -	if (mgr == ovl->manager) -		return size; - -	old_mgr = ovl->manager; - -	r = dispc_runtime_get(); -	if (r) -		return r; - -	/* detach old manager */ -	if (old_mgr) { -		r = ovl->unset_manager(ovl); -		if (r) { -			DSSERR("detach failed\n"); -			goto err; -		} - -		r = old_mgr->apply(old_mgr); -		if (r) -			goto err; -	} - -	if (mgr) { -		r = ovl->set_manager(ovl, mgr); -		if (r) { -			DSSERR("Failed to attach overlay\n"); -			goto err; -		} - -		r = mgr->apply(mgr); -		if (r) -			goto err; -	} - -	dispc_runtime_put(); - -	return size; - -err: -	dispc_runtime_put(); -	return r; -} - -static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) -{ -	struct omap_overlay_info info; - -	ovl->get_overlay_info(ovl, &info); - -	return snprintf(buf, PAGE_SIZE, "%d,%d\n", -			info.width, info.height); -} - -static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf) -{ -	struct omap_overlay_info info; - -	ovl->get_overlay_info(ovl, &info); - -	return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width); -} - -static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf) -{ -	struct omap_overlay_info info; - -	ovl->get_overlay_info(ovl, &info); - -	return snprintf(buf, PAGE_SIZE, "%d,%d\n", -			info.pos_x, info.pos_y); -} - -static ssize_t overlay_position_store(struct omap_overlay *ovl, -		const char *buf, size_t size) -{ -	int r; -	char *last; -	struct omap_overlay_info info; - -	ovl->get_overlay_info(ovl, &info); - -	info.pos_x = simple_strtoul(buf, &last, 10); -	++last; -	if (last - buf >= size) -		return -EINVAL; - -	info.pos_y = simple_strtoul(last, &last, 10); - -	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_output_size_show(struct omap_overlay *ovl, char *buf) -{ -	struct omap_overlay_info info; - -	ovl->get_overlay_info(ovl, &info); - -	return snprintf(buf, PAGE_SIZE, "%d,%d\n", -			info.out_width, info.out_height); -} - -static ssize_t overlay_output_size_store(struct omap_overlay *ovl, -		const char *buf, size_t size) -{ -	int r; -	char *last; -	struct omap_overlay_info info; - -	ovl->get_overlay_info(ovl, &info); - -	info.out_width = simple_strtoul(buf, &last, 10); -	++last; -	if (last - buf >= size) -		return -EINVAL; - -	info.out_height = simple_strtoul(last, &last, 10); - -	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_enabled_show(struct omap_overlay *ovl, char *buf) -{ -	return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl)); -} - -static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, -		size_t size) -{ -	int r; -	bool enable; - -	r = strtobool(buf, &enable); -	if (r) -		return r; - -	if (enable) -		r = ovl->enable(ovl); -	else -		r = ovl->disable(ovl); - -	if (r) -		return r; - -	return size; -} - -static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf) -{ -	struct omap_overlay_info info; - -	ovl->get_overlay_info(ovl, &info); - -	return snprintf(buf, PAGE_SIZE, "%d\n", -			info.global_alpha); -} - -static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, -		const char *buf, size_t size) -{ -	int r; -	u8 alpha; -	struct omap_overlay_info info; - -	if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) -		return -ENODEV; - -	r = kstrtou8(buf, 0, &alpha); -	if (r) -		return r; - -	ovl->get_overlay_info(ovl, &info); - -	info.global_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_pre_mult_alpha_show(struct omap_overlay *ovl, -		char *buf) -{ -	struct omap_overlay_info info; - -	ovl->get_overlay_info(ovl, &info); - -	return snprintf(buf, PAGE_SIZE, "%d\n", -			info.pre_mult_alpha); -} - -static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, -		const char *buf, size_t size) -{ -	int r; -	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); - -	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) -{ -	struct omap_overlay_info info; - -	ovl->get_overlay_info(ovl, &info); - -	return snprintf(buf, PAGE_SIZE, "%d\n", 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) -		return r; - -	if (ovl->manager) { -		r = ovl->manager->apply(ovl->manager); -		if (r) -			return r; -	} - -	return size; -} - -struct overlay_attribute { -	struct attribute attr; -	ssize_t (*show)(struct omap_overlay *, char *); -	ssize_t	(*store)(struct omap_overlay *, const char *, size_t); -}; - -#define OVERLAY_ATTR(_name, _mode, _show, _store) \ -	struct overlay_attribute overlay_attr_##_name = \ -	__ATTR(_name, _mode, _show, _store) - -static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL); -static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR, -		overlay_manager_show, overlay_manager_store); -static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL); -static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL); -static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR, -		overlay_position_show, overlay_position_store); -static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR, -		overlay_output_size_show, overlay_output_size_store); -static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, -		overlay_enabled_show, overlay_enabled_store); -static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, -		overlay_global_alpha_show, overlay_global_alpha_store); -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, -	&overlay_attr_manager.attr, -	&overlay_attr_input_size.attr, -	&overlay_attr_screen_width.attr, -	&overlay_attr_position.attr, -	&overlay_attr_output_size.attr, -	&overlay_attr_enabled.attr, -	&overlay_attr_global_alpha.attr, -	&overlay_attr_pre_mult_alpha.attr, -	&overlay_attr_zorder.attr, -	NULL -}; - -static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, -		char *buf) -{ -	struct omap_overlay *overlay; -	struct overlay_attribute *overlay_attr; - -	overlay = container_of(kobj, struct omap_overlay, kobj); -	overlay_attr = container_of(attr, struct overlay_attribute, attr); - -	if (!overlay_attr->show) -		return -ENOENT; - -	return overlay_attr->show(overlay, buf); -} - -static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, -		const char *buf, size_t size) -{ -	struct omap_overlay *overlay; -	struct overlay_attribute *overlay_attr; - -	overlay = container_of(kobj, struct omap_overlay, kobj); -	overlay_attr = container_of(attr, struct overlay_attribute, attr); - -	if (!overlay_attr->store) -		return -ENOENT; - -	return overlay_attr->store(overlay, buf, size); -} - -static const struct sysfs_ops overlay_sysfs_ops = { -	.show = overlay_attr_show, -	.store = overlay_attr_store, -}; - -static struct kobj_type overlay_ktype = { -	.sysfs_ops = &overlay_sysfs_ops, -	.default_attrs = overlay_sysfs_attrs, -}; -  int omap_dss_get_num_overlays(void)  {  	return num_overlays; @@ -507,97 +101,25 @@ void dss_init_overlays(struct platform_device *pdev)  		ovl->set_overlay_info = &dss_ovl_set_info;  		ovl->get_overlay_info = &dss_ovl_get_info;  		ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; +		ovl->get_device = &dss_ovl_get_device;  		ovl->caps = dss_feat_get_overlay_caps(ovl->id);  		ovl->supported_modes =  			dss_feat_get_supported_color_modes(ovl->id); -		r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, -				&pdev->dev.kobj, "overlay%d", i); - +		r = dss_overlay_kobj_init(ovl, pdev);  		if (r)  			DSSERR("failed to create sysfs file\n");  	}  } -/* connect overlays to the new device, if not already connected. if force - * selected, connect always. */ -void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) -{ -	int i; -	struct omap_overlay_manager *lcd_mgr; -	struct omap_overlay_manager *tv_mgr; -	struct omap_overlay_manager *lcd2_mgr = NULL; -	struct omap_overlay_manager *lcd3_mgr = NULL; -	struct omap_overlay_manager *mgr = NULL; - -	lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD); -	tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_DIGIT); -	if (dss_has_feature(FEAT_MGR_LCD3)) -		lcd3_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD3); -	if (dss_has_feature(FEAT_MGR_LCD2)) -		lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD2); - -	if (dssdev->channel == OMAP_DSS_CHANNEL_LCD3) { -		if (!lcd3_mgr->device || force) { -			if (lcd3_mgr->device) -				lcd3_mgr->unset_device(lcd3_mgr); -			lcd3_mgr->set_device(lcd3_mgr, dssdev); -			mgr = lcd3_mgr; -		} -	} else if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) { -		if (!lcd2_mgr->device || force) { -			if (lcd2_mgr->device) -				lcd2_mgr->unset_device(lcd2_mgr); -			lcd2_mgr->set_device(lcd2_mgr, dssdev); -			mgr = lcd2_mgr; -		} -	} else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC -			&& dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { -		if (!lcd_mgr->device || force) { -			if (lcd_mgr->device) -				lcd_mgr->unset_device(lcd_mgr); -			lcd_mgr->set_device(lcd_mgr, dssdev); -			mgr = lcd_mgr; -		} -	} - -	if (dssdev->type == OMAP_DISPLAY_TYPE_VENC -			|| dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { -		if (!tv_mgr->device || force) { -			if (tv_mgr->device) -				tv_mgr->unset_device(tv_mgr); -			tv_mgr->set_device(tv_mgr, dssdev); -			mgr = tv_mgr; -		} -	} - -	if (mgr) { -		dispc_runtime_get(); - -		for (i = 0; i < dss_feat_get_num_ovls(); i++) { -			struct omap_overlay *ovl; -			ovl = omap_dss_get_overlay(i); -			if (!ovl->manager || force) { -				if (ovl->manager) -					ovl->unset_manager(ovl); -				ovl->set_manager(ovl, mgr); -			} -		} - -		dispc_runtime_put(); -	} -} -  void dss_uninit_overlays(struct platform_device *pdev)  {  	int i;  	for (i = 0; i < num_overlays; ++i) {  		struct omap_overlay *ovl = &overlays[i]; - -		kobject_del(&ovl->kobj); -		kobject_put(&ovl->kobj); +		dss_overlay_kobj_uninit(ovl);  	}  	kfree(overlays); diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 7c087424b63..7282e5af3e1 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -111,6 +111,13 @@ static struct {  	struct omap_dss_device *dssdev[2];  	struct semaphore bus_lock; + +	struct omap_video_timings timings; +	int pixel_size; +	int data_lines; +	struct rfbi_timings intf_timings; + +	struct omap_dss_output output;  } rfbi;  static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) @@ -300,30 +307,23 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,  }  EXPORT_SYMBOL(omap_rfbi_write_pixels); -static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, -		u16 height, void (*callback)(void *data), void *data) +static int rfbi_transfer_area(struct omap_dss_device *dssdev, +		void (*callback)(void *data), void *data)  {  	u32 l;  	int r; -	struct omap_video_timings timings = { -		.hsw		= 1, -		.hfp		= 1, -		.hbp		= 1, -		.vsw		= 1, -		.vfp		= 0, -		.vbp		= 0, -		.x_res		= width, -		.y_res		= height, -	}; +	struct omap_overlay_manager *mgr = dssdev->output->manager; +	u16 width = rfbi.timings.x_res; +	u16 height = rfbi.timings.y_res;  	/*BUG_ON(callback == 0);*/  	BUG_ON(rfbi.framedone_callback != NULL);  	DSSDBG("rfbi_transfer_area %dx%d\n", width, height); -	dss_mgr_set_timings(dssdev->manager, &timings); +	dss_mgr_set_timings(mgr, &rfbi.timings); -	r = dss_mgr_enable(dssdev->manager); +	r = dss_mgr_enable(mgr);  	if (r)  		return r; @@ -770,62 +770,45 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)  	return 0;  } -int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, -		int data_lines) +int omap_rfbi_configure(struct omap_dss_device *dssdev)  { -	return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines); +	return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size, +			rfbi.data_lines);  }  EXPORT_SYMBOL(omap_rfbi_configure); -int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, -		u16 *x, u16 *y, u16 *w, u16 *h) +int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *), +		void *data)  { -	u16 dw, dh; -	struct omap_video_timings timings = { -		.hsw		= 1, -		.hfp		= 1, -		.hbp		= 1, -		.vsw		= 1, -		.vfp		= 0, -		.vbp		= 0, -		.x_res		= *w, -		.y_res		= *h, -	}; - -	dssdev->driver->get_resolution(dssdev, &dw, &dh); - -	if  (*x > dw || *y > dh) -		return -EINVAL; - -	if (*x + *w > dw) -		return -EINVAL; - -	if (*y + *h > dh) -		return -EINVAL; - -	if (*w == 1) -		return -EINVAL; - -	if (*w == 0 || *h == 0) -		return -EINVAL; - -	dss_mgr_set_timings(dssdev->manager, &timings); +	return rfbi_transfer_area(dssdev, callback, data); +} +EXPORT_SYMBOL(omap_rfbi_update); -	return 0; +void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) +{ +	rfbi.timings.x_res = w; +	rfbi.timings.y_res = h;  } -EXPORT_SYMBOL(omap_rfbi_prepare_update); +EXPORT_SYMBOL(omapdss_rfbi_set_size); -int omap_rfbi_update(struct omap_dss_device *dssdev, -		u16 x, u16 y, u16 w, u16 h, -		void (*callback)(void *), void *data) +void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)  { -	int r; +	rfbi.pixel_size = pixel_size; +} +EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size); -	r = rfbi_transfer_area(dssdev, w, h, callback, data); +void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) +{ +	rfbi.data_lines = data_lines; +} +EXPORT_SYMBOL(omapdss_rfbi_set_data_lines); -	return r; +void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, +		struct rfbi_timings *timings) +{ +	rfbi.intf_timings = *timings;  } -EXPORT_SYMBOL(omap_rfbi_update); +EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);  static void rfbi_dump_regs(struct seq_file *s)  { @@ -869,6 +852,7 @@ static void rfbi_dump_regs(struct seq_file *s)  static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)  { +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	struct dss_lcd_mgr_config mgr_config;  	mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI; @@ -877,18 +861,40 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)  	/* Do we need fifohandcheck for RFBI? */  	mgr_config.fifohandcheck = false; -	mgr_config.video_port_width = dssdev->ctrl.pixel_size; +	mgr_config.video_port_width = rfbi.pixel_size;  	mgr_config.lcden_sig_polarity = 0; -	dss_mgr_set_lcd_config(dssdev->manager, &mgr_config); +	dss_mgr_set_lcd_config(mgr, &mgr_config); + +	/* +	 * Set rfbi.timings with default values, the x_res and y_res fields +	 * are expected to be already configured by the panel driver via +	 * omapdss_rfbi_set_size() +	 */ +	rfbi.timings.hsw = 1; +	rfbi.timings.hfp = 1; +	rfbi.timings.hbp = 1; +	rfbi.timings.vsw = 1; +	rfbi.timings.vfp = 0; +	rfbi.timings.vbp = 0; + +	rfbi.timings.interlace = false; +	rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; +	rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; +	rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; +	rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; +	rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; + +	dss_mgr_set_timings(mgr, &rfbi.timings);  }  int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)  { +	struct omap_dss_output *out = dssdev->output;  	int r; -	if (dssdev->manager == NULL) { -		DSSERR("failed to enable display: no manager\n"); +	if (out == NULL || out->manager == NULL) { +		DSSERR("failed to enable display: no output/manager\n");  		return -ENODEV;  	} @@ -911,13 +917,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)  	rfbi_config_lcd_manager(dssdev); -	rfbi_configure(dssdev->phy.rfbi.channel, -			       dssdev->ctrl.pixel_size, -			       dssdev->phy.rfbi.data_lines); - -	rfbi_set_timings(dssdev->phy.rfbi.channel, -			 &dssdev->ctrl.rfbi_timings); +	rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size, +			rfbi.data_lines); +	rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);  	return 0;  err1: @@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable);  static int __init rfbi_init_display(struct omap_dss_device *dssdev)  {  	rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; -	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;  	return 0;  } -static void __init rfbi_probe_pdata(struct platform_device *pdev) +static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)  {  	struct omap_dss_board_info *pdata = pdev->dev.platform_data; -	int i, r; +	const char *def_disp_name = dss_get_default_display_name(); +	struct omap_dss_device *def_dssdev; +	int i; + +	def_dssdev = NULL;  	for (i = 0; i < pdata->num_devices; ++i) {  		struct omap_dss_device *dssdev = pdata->devices[i]; @@ -956,17 +962,67 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)  		if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)  			continue; -		r = rfbi_init_display(dssdev); -		if (r) { -			DSSERR("device %s init failed: %d\n", dssdev->name, r); -			continue; +		if (def_dssdev == NULL) +			def_dssdev = dssdev; + +		if (def_disp_name != NULL && +				strcmp(dssdev->name, def_disp_name) == 0) { +			def_dssdev = dssdev; +			break;  		} +	} + +	return def_dssdev; +} + +static void __init rfbi_probe_pdata(struct platform_device *rfbidev) +{ +	struct omap_dss_device *plat_dssdev; +	struct omap_dss_device *dssdev; +	int r; + +	plat_dssdev = rfbi_find_dssdev(rfbidev); -		r = omap_dss_register_device(dssdev, &pdev->dev, i); -		if (r) -			DSSERR("device %s register failed: %d\n", -				dssdev->name, r); +	if (!plat_dssdev) +		return; + +	dssdev = dss_alloc_and_init_device(&rfbidev->dev); +	if (!dssdev) +		return; + +	dss_copy_device_pdata(dssdev, plat_dssdev); + +	r = rfbi_init_display(dssdev); +	if (r) { +		DSSERR("device %s init failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return;  	} + +	r = dss_add_device(dssdev); +	if (r) { +		DSSERR("device %s register failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return; +	} +} + +static void __init rfbi_init_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &rfbi.output; + +	out->pdev = pdev; +	out->id = OMAP_DSS_OUTPUT_DBI; +	out->type = OMAP_DISPLAY_TYPE_DBI; + +	dss_register_output(out); +} + +static void __exit rfbi_uninit_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &rfbi.output; + +	dss_unregister_output(out);  }  /* RFBI HW IP initialisation */ @@ -1020,6 +1076,8 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)  	dss_debugfs_create_file("rfbi", rfbi_dump_regs); +	rfbi_init_output(pdev); +  	rfbi_probe_pdata(pdev);  	return 0; @@ -1031,8 +1089,12 @@ err_runtime_get:  static int __exit omap_rfbihw_remove(struct platform_device *pdev)  { -	omap_dss_unregister_child_devices(&pdev->dev); +	dss_unregister_child_devices(&pdev->dev); + +	rfbi_uninit_output(pdev); +  	pm_runtime_disable(&pdev->dev); +  	return 0;  } diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index f43bfe17b3b..7760851f6e5 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -25,6 +25,7 @@  #include <linux/regulator/consumer.h>  #include <linux/export.h>  #include <linux/platform_device.h> +#include <linux/string.h>  #include <video/omapdss.h>  #include "dss.h" @@ -34,10 +35,16 @@ static struct {  	struct regulator *vdds_sdi_reg;  	struct dss_lcd_mgr_config mgr_config; +	struct omap_video_timings timings; +	int datapairs; + +	struct omap_dss_output output;  } sdi;  static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)  { +	struct omap_overlay_manager *mgr = dssdev->output->manager; +  	sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;  	sdi.mgr_config.stallmode = false; @@ -46,19 +53,20 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)  	sdi.mgr_config.video_port_width = 24;  	sdi.mgr_config.lcden_sig_polarity = 1; -	dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config); +	dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);  }  int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)  { -	struct omap_video_timings *t = &dssdev->panel.timings; +	struct omap_dss_output *out = dssdev->output; +	struct omap_video_timings *t = &sdi.timings;  	struct dss_clock_info dss_cinfo;  	struct dispc_clock_info dispc_cinfo;  	unsigned long pck;  	int r; -	if (dssdev->manager == NULL) { -		DSSERR("failed to enable display: no manager\n"); +	if (out == NULL || out->manager == NULL) { +		DSSERR("failed to enable display: no output/manager\n");  		return -ENODEV;  	} @@ -77,8 +85,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)  		goto err_get_dispc;  	/* 15.5.9.1.2 */ -	dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; -	dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; +	t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; +	t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;  	r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);  	if (r) @@ -97,7 +105,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)  	} -	dss_mgr_set_timings(dssdev->manager, t); +	dss_mgr_set_timings(out->manager, t);  	r = dss_set_clock_div(&dss_cinfo);  	if (r) @@ -116,16 +124,15 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)  	 * need to care about the shadow register mechanism for pck-free. The  	 * exact reason for this is unknown.  	 */ -	dispc_mgr_set_clock_div(dssdev->manager->id, -			&sdi.mgr_config.clock_info); +	dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info); -	dss_sdi_init(dssdev->phy.sdi.datapairs); +	dss_sdi_init(sdi.datapairs);  	r = dss_sdi_enable();  	if (r)  		goto err_sdi_enable;  	mdelay(2); -	r = dss_mgr_enable(dssdev->manager); +	r = dss_mgr_enable(out->manager);  	if (r)  		goto err_mgr_enable; @@ -148,7 +155,9 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);  void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)  { -	dss_mgr_disable(dssdev->manager); +	struct omap_overlay_manager *mgr = dssdev->output->manager; + +	dss_mgr_disable(mgr);  	dss_sdi_disable(); @@ -160,6 +169,19 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)  }  EXPORT_SYMBOL(omapdss_sdi_display_disable); +void omapdss_sdi_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings) +{ +	sdi.timings = *timings; +} +EXPORT_SYMBOL(omapdss_sdi_set_timings); + +void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs) +{ +	sdi.datapairs = datapairs; +} +EXPORT_SYMBOL(omapdss_sdi_set_datapairs); +  static int __init sdi_init_display(struct omap_dss_device *dssdev)  {  	DSSDBG("SDI init\n"); @@ -180,10 +202,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)  	return 0;  } -static void __init sdi_probe_pdata(struct platform_device *pdev) +static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)  {  	struct omap_dss_board_info *pdata = pdev->dev.platform_data; -	int i, r; +	const char *def_disp_name = dss_get_default_display_name(); +	struct omap_dss_device *def_dssdev; +	int i; + +	def_dssdev = NULL;  	for (i = 0; i < pdata->num_devices; ++i) {  		struct omap_dss_device *dssdev = pdata->devices[i]; @@ -191,21 +217,73 @@ static void __init sdi_probe_pdata(struct platform_device *pdev)  		if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)  			continue; -		r = sdi_init_display(dssdev); -		if (r) { -			DSSERR("device %s init failed: %d\n", dssdev->name, r); -			continue; +		if (def_dssdev == NULL) +			def_dssdev = dssdev; + +		if (def_disp_name != NULL && +				strcmp(dssdev->name, def_disp_name) == 0) { +			def_dssdev = dssdev; +			break;  		} +	} + +	return def_dssdev; +} + +static void __init sdi_probe_pdata(struct platform_device *sdidev) +{ +	struct omap_dss_device *plat_dssdev; +	struct omap_dss_device *dssdev; +	int r; + +	plat_dssdev = sdi_find_dssdev(sdidev); -		r = omap_dss_register_device(dssdev, &pdev->dev, i); -		if (r) -			DSSERR("device %s register failed: %d\n", -					dssdev->name, r); +	if (!plat_dssdev) +		return; + +	dssdev = dss_alloc_and_init_device(&sdidev->dev); +	if (!dssdev) +		return; + +	dss_copy_device_pdata(dssdev, plat_dssdev); + +	r = sdi_init_display(dssdev); +	if (r) { +		DSSERR("device %s init failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return;  	} + +	r = dss_add_device(dssdev); +	if (r) { +		DSSERR("device %s register failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return; +	} +} + +static void __init sdi_init_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &sdi.output; + +	out->pdev = pdev; +	out->id = OMAP_DSS_OUTPUT_SDI; +	out->type = OMAP_DISPLAY_TYPE_SDI; + +	dss_register_output(out); +} + +static void __exit sdi_uninit_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &sdi.output; + +	dss_unregister_output(out);  }  static int __init omap_sdi_probe(struct platform_device *pdev)  { +	sdi_init_output(pdev); +  	sdi_probe_pdata(pdev);  	return 0; @@ -213,7 +291,9 @@ static int __init omap_sdi_probe(struct platform_device *pdev)  static int __exit omap_sdi_remove(struct platform_device *pdev)  { -	omap_dss_unregister_child_devices(&pdev->dev); +	dss_unregister_child_devices(&pdev->dev); + +	sdi_uninit_output(pdev);  	return 0;  } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 3a220877461..56efa3bb465 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -36,7 +36,6 @@  #include <linux/pm_runtime.h>  #include <video/omapdss.h> -#include <plat/cpu.h>  #include "dss.h"  #include "dss_features.h" @@ -300,6 +299,12 @@ static struct {  	struct regulator *vdda_dac_reg;  	struct clk	*tv_dac_clk; + +	struct omap_video_timings timings; +	enum omap_dss_venc_type type; +	bool invert_polarity; + +	struct omap_dss_output output;  } venc;  static inline void venc_write_reg(int idx, u32 val) @@ -424,65 +429,67 @@ static const struct venc_config *venc_timings_to_config(  static int venc_power_on(struct omap_dss_device *dssdev)  { +	struct omap_overlay_manager *mgr = dssdev->output->manager;  	u32 l;  	int r; +	r = venc_runtime_get(); +	if (r) +		goto err0; +  	venc_reset(); -	venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); +	venc_write_config(venc_timings_to_config(&venc.timings)); -	dss_set_venc_output(dssdev->phy.venc.type); +	dss_set_venc_output(venc.type);  	dss_set_dac_pwrdn_bgz(1);  	l = 0; -	if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) +	if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)  		l |= 1 << 1;  	else /* S-Video */  		l |= (1 << 0) | (1 << 2); -	if (dssdev->phy.venc.invert_polarity == false) +	if (venc.invert_polarity == false)  		l |= 1 << 3;  	venc_write_reg(VENC_OUTPUT_CONTROL, l); -	dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); +	dss_mgr_set_timings(mgr, &venc.timings);  	r = regulator_enable(venc.vdda_dac_reg);  	if (r) -		goto err; - -	if (dssdev->platform_enable) -		dssdev->platform_enable(dssdev); +		goto err1; -	r = dss_mgr_enable(dssdev->manager); +	r = dss_mgr_enable(mgr);  	if (r) -		goto err; +		goto err2;  	return 0; -err: +err2: +	regulator_disable(venc.vdda_dac_reg); +err1:  	venc_write_reg(VENC_OUTPUT_CONTROL, 0);  	dss_set_dac_pwrdn_bgz(0); -	if (dssdev->platform_disable) -		dssdev->platform_disable(dssdev); - -	regulator_disable(venc.vdda_dac_reg); - +	venc_runtime_put(); +err0:  	return r;  }  static void venc_power_off(struct omap_dss_device *dssdev)  { +	struct omap_overlay_manager *mgr = dssdev->output->manager; +  	venc_write_reg(VENC_OUTPUT_CONTROL, 0);  	dss_set_dac_pwrdn_bgz(0); -	dss_mgr_disable(dssdev->manager); - -	if (dssdev->platform_disable) -		dssdev->platform_disable(dssdev); +	dss_mgr_disable(mgr);  	regulator_disable(venc.vdda_dac_reg); + +	venc_runtime_put();  }  unsigned long venc_get_pixel_clock(void) @@ -491,171 +498,83 @@ unsigned long venc_get_pixel_clock(void)  	return 13500000;  } -static ssize_t display_output_type_show(struct device *dev, -		struct device_attribute *attr, char *buf) +int omapdss_venc_display_enable(struct omap_dss_device *dssdev)  { -	struct omap_dss_device *dssdev = to_dss_device(dev); -	const char *ret; - -	switch (dssdev->phy.venc.type) { -	case OMAP_DSS_VENC_TYPE_COMPOSITE: -		ret = "composite"; -		break; -	case OMAP_DSS_VENC_TYPE_SVIDEO: -		ret = "svideo"; -		break; -	default: -		return -EINVAL; -	} - -	return snprintf(buf, PAGE_SIZE, "%s\n", ret); -} +	struct omap_dss_output *out = dssdev->output; +	int r; -static ssize_t display_output_type_store(struct device *dev, -		struct device_attribute *attr, const char *buf, size_t size) -{ -	struct omap_dss_device *dssdev = to_dss_device(dev); -	enum omap_dss_venc_type new_type; - -	if (sysfs_streq("composite", buf)) -		new_type = OMAP_DSS_VENC_TYPE_COMPOSITE; -	else if (sysfs_streq("svideo", buf)) -		new_type = OMAP_DSS_VENC_TYPE_SVIDEO; -	else -		return -EINVAL; +	DSSDBG("venc_display_enable\n");  	mutex_lock(&venc.venc_lock); -	if (dssdev->phy.venc.type != new_type) { -		dssdev->phy.venc.type = new_type; -		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { -			venc_power_off(dssdev); -			venc_power_on(dssdev); -		} +	if (out == NULL || out->manager == NULL) { +		DSSERR("Failed to enable display: no output/manager\n"); +		r = -ENODEV; +		goto err0;  	} -	mutex_unlock(&venc.venc_lock); - -	return size; -} - -static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR, -		display_output_type_show, display_output_type_store); - -/* driver */ -static int venc_panel_probe(struct omap_dss_device *dssdev) -{ -	dssdev->panel.timings = omap_dss_pal_timings; - -	return device_create_file(&dssdev->dev, &dev_attr_output_type); -} - -static void venc_panel_remove(struct omap_dss_device *dssdev) -{ -	device_remove_file(&dssdev->dev, &dev_attr_output_type); -} - -static int venc_panel_enable(struct omap_dss_device *dssdev) -{ -	int r = 0; - -	DSSDBG("venc_enable_display\n"); - -	mutex_lock(&venc.venc_lock); -  	r = omap_dss_start_device(dssdev);  	if (r) {  		DSSERR("failed to start device\n");  		goto err0;  	} -	if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { -		r = -EINVAL; -		goto err1; -	} +	if (dssdev->platform_enable) +		dssdev->platform_enable(dssdev); -	r = venc_runtime_get(); -	if (r) -		goto err1;  	r = venc_power_on(dssdev);  	if (r) -		goto err2; +		goto err1;  	venc.wss_data = 0; -	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; -  	mutex_unlock(&venc.venc_lock); +  	return 0; -err2: -	venc_runtime_put();  err1: +	if (dssdev->platform_disable) +		dssdev->platform_disable(dssdev);  	omap_dss_stop_device(dssdev);  err0:  	mutex_unlock(&venc.venc_lock); -  	return r;  } -static void venc_panel_disable(struct omap_dss_device *dssdev) +void omapdss_venc_display_disable(struct omap_dss_device *dssdev)  { -	DSSDBG("venc_disable_display\n"); +	DSSDBG("venc_display_disable\n");  	mutex_lock(&venc.venc_lock); -	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) -		goto end; - -	if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) { -		/* suspended is the same as disabled with venc */ -		dssdev->state = OMAP_DSS_DISPLAY_DISABLED; -		goto end; -	} -  	venc_power_off(dssdev); -	venc_runtime_put(); - -	dssdev->state = OMAP_DSS_DISPLAY_DISABLED; -  	omap_dss_stop_device(dssdev); -end: -	mutex_unlock(&venc.venc_lock); -} -static int venc_panel_suspend(struct omap_dss_device *dssdev) -{ -	venc_panel_disable(dssdev); -	return 0; -} +	if (dssdev->platform_disable) +		dssdev->platform_disable(dssdev); -static int venc_panel_resume(struct omap_dss_device *dssdev) -{ -	return venc_panel_enable(dssdev); +	mutex_unlock(&venc.venc_lock);  } -static void venc_set_timings(struct omap_dss_device *dssdev, -			struct omap_video_timings *timings) +void omapdss_venc_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings)  {  	DSSDBG("venc_set_timings\n"); +	mutex_lock(&venc.venc_lock); +  	/* Reset WSS data when the TV standard changes. */ -	if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings))) +	if (memcmp(&venc.timings, timings, sizeof(*timings)))  		venc.wss_data = 0; -	dssdev->panel.timings = *timings; -	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { -		/* turn the venc off and on to get new timings to use */ -		venc_panel_disable(dssdev); -		venc_panel_enable(dssdev); -	} else { -		dss_mgr_set_timings(dssdev->manager, timings); -	} +	venc.timings = *timings; + +	mutex_unlock(&venc.venc_lock);  } -static int venc_check_timings(struct omap_dss_device *dssdev, -			struct omap_video_timings *timings) +int omapdss_venc_check_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings)  {  	DSSDBG("venc_check_timings\n"); @@ -668,13 +587,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,  	return -EINVAL;  } -static u32 venc_get_wss(struct omap_dss_device *dssdev) +u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)  {  	/* Invert due to VENC_L21_WC_CTL:INV=1 */  	return (venc.wss_data >> 8) ^ 0xfffff;  } -static int venc_set_wss(struct omap_dss_device *dssdev,	u32 wss) +int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)  {  	const struct venc_config *config;  	int r; @@ -683,7 +602,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev,	u32 wss)  	mutex_lock(&venc.venc_lock); -	config = venc_timings_to_config(&dssdev->panel.timings); +	config = venc_timings_to_config(&venc.timings);  	/* Invert due to VENC_L21_WC_CTL:INV=1 */  	venc.wss_data = (wss ^ 0xfffff) << 8; @@ -703,30 +622,25 @@ err:  	return r;  } -static struct omap_dss_driver venc_driver = { -	.probe		= venc_panel_probe, -	.remove		= venc_panel_remove, +void omapdss_venc_set_type(struct omap_dss_device *dssdev, +		enum omap_dss_venc_type type) +{ +	mutex_lock(&venc.venc_lock); -	.enable		= venc_panel_enable, -	.disable	= venc_panel_disable, -	.suspend	= venc_panel_suspend, -	.resume		= venc_panel_resume, +	venc.type = type; -	.get_resolution	= omapdss_default_get_resolution, -	.get_recommended_bpp = omapdss_default_get_recommended_bpp, +	mutex_unlock(&venc.venc_lock); +} -	.set_timings	= venc_set_timings, -	.check_timings	= venc_check_timings, +void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev, +		bool invert_polarity) +{ +	mutex_lock(&venc.venc_lock); -	.get_wss	= venc_get_wss, -	.set_wss	= venc_set_wss, +	venc.invert_polarity = invert_polarity; -	.driver         = { -		.name   = "venc", -		.owner  = THIS_MODULE, -	}, -}; -/* driver end */ +	mutex_unlock(&venc.venc_lock); +}  static int __init venc_init_display(struct omap_dss_device *dssdev)  { @@ -752,11 +666,6 @@ static void venc_dump_regs(struct seq_file *s)  {  #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) -	if (cpu_is_omap44xx()) { -		seq_printf(s, "VENC currently disabled on OMAP44xx\n"); -		return; -	} -  	if (venc_runtime_get())  		return; @@ -832,10 +741,14 @@ static void venc_put_clocks(void)  		clk_put(venc.tv_dac_clk);  } -static void __init venc_probe_pdata(struct platform_device *pdev) +static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)  {  	struct omap_dss_board_info *pdata = pdev->dev.platform_data; -	int r, i; +	const char *def_disp_name = dss_get_default_display_name(); +	struct omap_dss_device *def_dssdev; +	int i; + +	def_dssdev = NULL;  	for (i = 0; i < pdata->num_devices; ++i) {  		struct omap_dss_device *dssdev = pdata->devices[i]; @@ -843,17 +756,69 @@ static void __init venc_probe_pdata(struct platform_device *pdev)  		if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)  			continue; -		r = venc_init_display(dssdev); -		if (r) { -			DSSERR("device %s init failed: %d\n", dssdev->name, r); -			continue; +		if (def_dssdev == NULL) +			def_dssdev = dssdev; + +		if (def_disp_name != NULL && +				strcmp(dssdev->name, def_disp_name) == 0) { +			def_dssdev = dssdev; +			break;  		} +	} + +	return def_dssdev; +} + +static void __init venc_probe_pdata(struct platform_device *vencdev) +{ +	struct omap_dss_device *plat_dssdev; +	struct omap_dss_device *dssdev; +	int r; + +	plat_dssdev = venc_find_dssdev(vencdev); -		r = omap_dss_register_device(dssdev, &pdev->dev, i); -		if (r) -			DSSERR("device %s register failed: %d\n", -					dssdev->name, r); +	if (!plat_dssdev) +		return; + +	dssdev = dss_alloc_and_init_device(&vencdev->dev); +	if (!dssdev) +		return; + +	dss_copy_device_pdata(dssdev, plat_dssdev); + +	dssdev->channel = OMAP_DSS_CHANNEL_DIGIT; + +	r = venc_init_display(dssdev); +	if (r) { +		DSSERR("device %s init failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return;  	} + +	r = dss_add_device(dssdev); +	if (r) { +		DSSERR("device %s register failed: %d\n", dssdev->name, r); +		dss_put_device(dssdev); +		return; +	} +} + +static void __init venc_init_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &venc.output; + +	out->pdev = pdev; +	out->id = OMAP_DSS_OUTPUT_VENC; +	out->type = OMAP_DISPLAY_TYPE_VENC; + +	dss_register_output(out); +} + +static void __exit venc_uninit_output(struct platform_device *pdev) +{ +	struct omap_dss_output *out = &venc.output; + +	dss_unregister_output(out);  }  /* VENC HW IP initialisation */ @@ -897,17 +862,19 @@ static int __init omap_venchw_probe(struct platform_device *pdev)  	venc_runtime_put(); -	r = omap_dss_register_driver(&venc_driver); +	r = venc_panel_init();  	if (r) -		goto err_reg_panel_driver; +		goto err_panel_init;  	dss_debugfs_create_file("venc", venc_dump_regs); +	venc_init_output(pdev); +  	venc_probe_pdata(pdev);  	return 0; -err_reg_panel_driver: +err_panel_init:  err_runtime_get:  	pm_runtime_disable(&pdev->dev);  	venc_put_clocks(); @@ -916,14 +883,16 @@ err_runtime_get:  static int __exit omap_venchw_remove(struct platform_device *pdev)  { -	omap_dss_unregister_child_devices(&pdev->dev); +	dss_unregister_child_devices(&pdev->dev);  	if (venc.vdda_dac_reg != NULL) {  		regulator_put(venc.vdda_dac_reg);  		venc.vdda_dac_reg = NULL;  	} -	omap_dss_unregister_driver(&venc_driver); +	venc_panel_exit(); + +	venc_uninit_output(pdev);  	pm_runtime_disable(&pdev->dev);  	venc_put_clocks(); @@ -971,16 +940,10 @@ static struct platform_driver omap_venchw_driver = {  int __init venc_init_platform_driver(void)  { -	if (cpu_is_omap44xx()) -		return 0; -  	return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);  }  void __exit venc_uninit_platform_driver(void)  { -	if (cpu_is_omap44xx()) -		return; -  	platform_driver_unregister(&omap_venchw_driver);  } diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c new file mode 100644 index 00000000000..d55b8784ecf --- /dev/null +++ b/drivers/video/omap2/dss/venc_panel.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> + * + * VENC panel driver + * + * 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/err.h> +#include <linux/io.h> +#include <linux/mutex.h> +#include <linux/module.h> + +#include <video/omapdss.h> + +#include "dss.h" + +static struct { +	struct mutex lock; +} venc_panel; + +static ssize_t display_output_type_show(struct device *dev, +		struct device_attribute *attr, char *buf) +{ +	struct omap_dss_device *dssdev = to_dss_device(dev); +	const char *ret; + +	switch (dssdev->phy.venc.type) { +	case OMAP_DSS_VENC_TYPE_COMPOSITE: +		ret = "composite"; +		break; +	case OMAP_DSS_VENC_TYPE_SVIDEO: +		ret = "svideo"; +		break; +	default: +		return -EINVAL; +	} + +	return snprintf(buf, PAGE_SIZE, "%s\n", ret); +} + +static ssize_t display_output_type_store(struct device *dev, +		struct device_attribute *attr, const char *buf, size_t size) +{ +	struct omap_dss_device *dssdev = to_dss_device(dev); +	enum omap_dss_venc_type new_type; + +	if (sysfs_streq("composite", buf)) +		new_type = OMAP_DSS_VENC_TYPE_COMPOSITE; +	else if (sysfs_streq("svideo", buf)) +		new_type = OMAP_DSS_VENC_TYPE_SVIDEO; +	else +		return -EINVAL; + +	mutex_lock(&venc_panel.lock); + +	if (dssdev->phy.venc.type != new_type) { +		dssdev->phy.venc.type = new_type; +		omapdss_venc_set_type(dssdev, new_type); +		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { +			omapdss_venc_display_disable(dssdev); +			omapdss_venc_display_enable(dssdev); +		} +	} + +	mutex_unlock(&venc_panel.lock); + +	return size; +} + +static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR, +		display_output_type_show, display_output_type_store); + +static int venc_panel_probe(struct omap_dss_device *dssdev) +{ +	/* set default timings to PAL */ +	const struct omap_video_timings default_timings = { +		.x_res		= 720, +		.y_res		= 574, +		.pixel_clock	= 13500, +		.hsw		= 64, +		.hfp		= 12, +		.hbp		= 68, +		.vsw		= 5, +		.vfp		= 5, +		.vbp		= 41, + +		.vsync_level	= OMAPDSS_SIG_ACTIVE_HIGH, +		.hsync_level	= OMAPDSS_SIG_ACTIVE_HIGH, + +		.interlace	= true, +	}; + +	mutex_init(&venc_panel.lock); + +	dssdev->panel.timings = default_timings; + +	return device_create_file(&dssdev->dev, &dev_attr_output_type); +} + +static void venc_panel_remove(struct omap_dss_device *dssdev) +{ +	device_remove_file(&dssdev->dev, &dev_attr_output_type); +} + +static int venc_panel_enable(struct omap_dss_device *dssdev) +{ +	int r; + +	dev_dbg(&dssdev->dev, "venc_panel_enable\n"); + +	mutex_lock(&venc_panel.lock); + +	if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { +		r = -EINVAL; +		goto err; +	} + +	omapdss_venc_set_timings(dssdev, &dssdev->panel.timings); +	omapdss_venc_set_type(dssdev, dssdev->phy.venc.type); +	omapdss_venc_invert_vid_out_polarity(dssdev, +		dssdev->phy.venc.invert_polarity); + +	r = omapdss_venc_display_enable(dssdev); +	if (r) +		goto err; + +	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +	mutex_unlock(&venc_panel.lock); + +	return 0; +err: +	mutex_unlock(&venc_panel.lock); + +	return r; +} + +static void venc_panel_disable(struct omap_dss_device *dssdev) +{ +	dev_dbg(&dssdev->dev, "venc_panel_disable\n"); + +	mutex_lock(&venc_panel.lock); + +	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) +		goto end; + +	if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) { +		/* suspended is the same as disabled with venc */ +		dssdev->state = OMAP_DSS_DISPLAY_DISABLED; +		goto end; +	} + +	omapdss_venc_display_disable(dssdev); + +	dssdev->state = OMAP_DSS_DISPLAY_DISABLED; +end: +	mutex_unlock(&venc_panel.lock); +} + +static int venc_panel_suspend(struct omap_dss_device *dssdev) +{ +	venc_panel_disable(dssdev); +	return 0; +} + +static int venc_panel_resume(struct omap_dss_device *dssdev) +{ +	return venc_panel_enable(dssdev); +} + +static void venc_panel_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings) +{ +	dev_dbg(&dssdev->dev, "venc_panel_set_timings\n"); + +	mutex_lock(&venc_panel.lock); + +	omapdss_venc_set_timings(dssdev, timings); +	dssdev->panel.timings = *timings; + +	mutex_unlock(&venc_panel.lock); +} + +static int venc_panel_check_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings) +{ +	dev_dbg(&dssdev->dev, "venc_panel_check_timings\n"); + +	return omapdss_venc_check_timings(dssdev, timings); +} + +static u32 venc_panel_get_wss(struct omap_dss_device *dssdev) +{ +	dev_dbg(&dssdev->dev, "venc_panel_get_wss\n"); + +	return omapdss_venc_get_wss(dssdev); +} + +static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss) +{ +	dev_dbg(&dssdev->dev, "venc_panel_set_wss\n"); + +	return omapdss_venc_set_wss(dssdev, wss); +} + +static struct omap_dss_driver venc_driver = { +	.probe		= venc_panel_probe, +	.remove		= venc_panel_remove, + +	.enable		= venc_panel_enable, +	.disable	= venc_panel_disable, +	.suspend	= venc_panel_suspend, +	.resume		= venc_panel_resume, + +	.get_resolution	= omapdss_default_get_resolution, +	.get_recommended_bpp = omapdss_default_get_recommended_bpp, + +	.set_timings	= venc_panel_set_timings, +	.check_timings	= venc_panel_check_timings, + +	.get_wss	= venc_panel_get_wss, +	.set_wss	= venc_panel_set_wss, + +	.driver         = { +		.name   = "venc", +		.owner  = THIS_MODULE, +	}, +}; + +int venc_panel_init(void) +{ +	return omap_dss_register_driver(&venc_driver); +} + +void venc_panel_exit(void) +{ +	omap_dss_unregister_driver(&venc_driver); +} diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index c6cf372d22c..606b89f1235 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -599,6 +599,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)  	struct omapfb_info *ofbi = FB2OFB(fbi);  	struct omapfb2_device *fbdev = ofbi->fbdev;  	struct omap_dss_device *display = fb2display(fbi); +	struct omap_overlay_manager *mgr;  	union {  		struct omapfb_update_window_old	uwnd_o; @@ -786,12 +787,14 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)  	case OMAPFB_WAITFORVSYNC:  		DBG("ioctl WAITFORVSYNC\n"); -		if (!display) { +		if (!display && !display->output && !display->output->manager) {  			r = -EINVAL;  			break;  		} -		r = display->manager->wait_for_vsync(display->manager); +		mgr = display->output->manager; + +		r = mgr->wait_for_vsync(mgr);  		break;  	case OMAPFB_WAITFORGO: diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 15373f4aee1..16db1589bd9 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -1593,6 +1593,20 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)  	return 0;  } +static void omapfb_clear_fb(struct fb_info *fbi) +{ +	const struct fb_fillrect rect = { +		.dx = 0, +		.dy = 0, +		.width = fbi->var.xres_virtual, +		.height = fbi->var.yres_virtual, +		.color = 0, +		.rop = ROP_COPY, +	}; + +	cfb_fillrect(fbi, &rect); +} +  int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)  {  	struct omapfb_info *ofbi = FB2OFB(fbi); @@ -1662,6 +1676,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)  			goto err;  	} +	omapfb_clear_fb(fbi); +  	return 0;  err:  	omapfb_free_fbmem(fbi); @@ -1946,6 +1962,16 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)  		}  	} +	for (i = 0; i < fbdev->num_fbs; i++) { +		struct fb_info *fbi = fbdev->fbs[i]; +		struct omapfb_info *ofbi = FB2OFB(fbi); + +		if (ofbi->region->size == 0) +			continue; + +		omapfb_clear_fb(fbi); +	} +  	DBG("fb_infos initialized\n");  	for (i = 0; i < fbdev->num_fbs; i++) { @@ -2354,6 +2380,7 @@ static int __init omapfb_probe(struct platform_device *pdev)  	struct omap_overlay *ovl;  	struct omap_dss_device *def_display;  	struct omap_dss_device *dssdev; +	struct omap_dss_device *ovl_device;  	DBG("omapfb_probe\n"); @@ -2427,8 +2454,9 @@ static int __init omapfb_probe(struct platform_device *pdev)  	/* 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; +	ovl_device = ovl->get_device(ovl); +	if (ovl_device) { +		def_display = ovl_device;  	} else {  		dev_warn(&pdev->dev, "cannot find default display\n");  		def_display = NULL; diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index 30361a09aec..5ced9b334d3 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h @@ -148,8 +148,9 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)  	/* XXX: returns the display connected to first attached overlay */  	for (i = 0; i < ofbi->num_overlays; i++) { -		if (ofbi->overlays[i]->manager) -			return ofbi->overlays[i]->manager->device; +		struct omap_overlay *ovl = ofbi->overlays[i]; + +		return ovl->get_device(ovl);  	}  	return NULL; diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c index 87e421e25af..f2b15c4a75b 100644 --- a/drivers/video/omap2/vram.c +++ b/drivers/video/omap2/vram.c @@ -34,7 +34,6 @@  #include <asm/setup.h>  #include <plat/vram.h> -#include <plat/dma.h>  #ifdef DEBUG  #define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__) @@ -250,59 +249,6 @@ int omap_vram_reserve(unsigned long paddr, size_t size)  }  EXPORT_SYMBOL(omap_vram_reserve); -static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data) -{ -	struct completion *compl = data; -	complete(compl); -} - -static int _omap_vram_clear(u32 paddr, unsigned pages) -{ -	struct completion compl; -	unsigned elem_count; -	unsigned frame_count; -	int r; -	int lch; - -	init_completion(&compl); - -	r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA", -			_omap_vram_dma_cb, -			&compl, &lch); -	if (r) { -		pr_err("VRAM: request_dma failed for memory clear\n"); -		return -EBUSY; -	} - -	elem_count = pages * PAGE_SIZE / 4; -	frame_count = 1; - -	omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32, -			elem_count, frame_count, -			OMAP_DMA_SYNC_ELEMENT, -			0, 0); - -	omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC, -			paddr, 0, 0); - -	omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000); - -	omap_start_dma(lch); - -	if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) { -		omap_stop_dma(lch); -		pr_err("VRAM: dma timeout while clearing memory\n"); -		r = -EIO; -		goto err; -	} - -	r = 0; -err: -	omap_free_dma(lch); - -	return r; -} -  static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)  {  	struct vram_region *rm; @@ -337,8 +283,6 @@ found:  		*paddr = start; -		_omap_vram_clear(start, pages); -  		return 0;  	} diff --git a/drivers/video/pnx4008/Makefile b/drivers/video/pnx4008/Makefile deleted file mode 100644 index 636aaccf01f..00000000000 --- a/drivers/video/pnx4008/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for the new PNX4008 framebuffer device driver -# - -obj-$(CONFIG_FB_PNX4008_DUM) += sdum.o -obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnxrgbfb.o - diff --git a/drivers/video/pnx4008/dum.h b/drivers/video/pnx4008/dum.h deleted file mode 100644 index 1234d4375d9..00000000000 --- a/drivers/video/pnx4008/dum.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * linux/drivers/video/pnx4008/dum.h - * - * Internal header for SDUM - * - * 2005 (c) Koninklijke Philips N.V. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifndef __PNX008_DUM_H__ -#define __PNX008_DUM_H__ - -#include <mach/platform.h> - -#define PNX4008_DUMCONF_VA_BASE		IO_ADDRESS(PNX4008_DUMCONF_BASE) -#define PNX4008_DUM_MAIN_VA_BASE	IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE) - -/* DUM CFG ADDRESSES */ -#define DUM_CH_BASE_ADR		(PNX4008_DUMCONF_VA_BASE + 0x00) -#define DUM_CH_MIN_ADR		(PNX4008_DUMCONF_VA_BASE + 0x00) -#define DUM_CH_MAX_ADR		(PNX4008_DUMCONF_VA_BASE + 0x04) -#define DUM_CH_CONF_ADR		(PNX4008_DUMCONF_VA_BASE + 0x08) -#define DUM_CH_STAT_ADR		(PNX4008_DUMCONF_VA_BASE + 0x0C) -#define DUM_CH_CTRL_ADR		(PNX4008_DUMCONF_VA_BASE + 0x10) - -#define CH_MARG		(0x100 / sizeof(u32)) -#define DUM_CH_MIN(i)	(*((volatile u32 *)DUM_CH_MIN_ADR + (i) * CH_MARG)) -#define DUM_CH_MAX(i)	(*((volatile u32 *)DUM_CH_MAX_ADR + (i) * CH_MARG)) -#define DUM_CH_CONF(i)	(*((volatile u32 *)DUM_CH_CONF_ADR + (i) * CH_MARG)) -#define DUM_CH_STAT(i)	(*((volatile u32 *)DUM_CH_STAT_ADR + (i) * CH_MARG)) -#define DUM_CH_CTRL(i)	(*((volatile u32 *)DUM_CH_CTRL_ADR + (i) * CH_MARG)) - -#define DUM_CONF_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x00) -#define DUM_CTRL_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x04) -#define DUM_STAT_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x08) -#define DUM_DECODE_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x0C) -#define DUM_COM_BASE_ADR      (PNX4008_DUM_MAIN_VA_BASE + 0x10) -#define DUM_SYNC_C_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x14) -#define DUM_CLK_DIV_ADR       (PNX4008_DUM_MAIN_VA_BASE + 0x18) -#define DUM_DIRTY_LOW_ADR     (PNX4008_DUM_MAIN_VA_BASE + 0x20) -#define DUM_DIRTY_HIGH_ADR    (PNX4008_DUM_MAIN_VA_BASE + 0x24) -#define DUM_FORMAT_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x28) -#define DUM_WTCFG1_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x30) -#define DUM_RTCFG1_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x34) -#define DUM_WTCFG2_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x38) -#define DUM_RTCFG2_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x3C) -#define DUM_TCFG_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x40) -#define DUM_OUTP_FORMAT1_ADR  (PNX4008_DUM_MAIN_VA_BASE + 0x44) -#define DUM_OUTP_FORMAT2_ADR  (PNX4008_DUM_MAIN_VA_BASE + 0x48) -#define DUM_SYNC_MODE_ADR     (PNX4008_DUM_MAIN_VA_BASE + 0x4C) -#define DUM_SYNC_OUT_C_ADR    (PNX4008_DUM_MAIN_VA_BASE + 0x50) - -#define DUM_CONF              (*(volatile u32 *)(DUM_CONF_ADR)) -#define DUM_CTRL              (*(volatile u32 *)(DUM_CTRL_ADR)) -#define DUM_STAT              (*(volatile u32 *)(DUM_STAT_ADR)) -#define DUM_DECODE            (*(volatile u32 *)(DUM_DECODE_ADR)) -#define DUM_COM_BASE          (*(volatile u32 *)(DUM_COM_BASE_ADR)) -#define DUM_SYNC_C            (*(volatile u32 *)(DUM_SYNC_C_ADR)) -#define DUM_CLK_DIV           (*(volatile u32 *)(DUM_CLK_DIV_ADR)) -#define DUM_DIRTY_LOW         (*(volatile u32 *)(DUM_DIRTY_LOW_ADR)) -#define DUM_DIRTY_HIGH        (*(volatile u32 *)(DUM_DIRTY_HIGH_ADR)) -#define DUM_FORMAT            (*(volatile u32 *)(DUM_FORMAT_ADR)) -#define DUM_WTCFG1            (*(volatile u32 *)(DUM_WTCFG1_ADR)) -#define DUM_RTCFG1            (*(volatile u32 *)(DUM_RTCFG1_ADR)) -#define DUM_WTCFG2            (*(volatile u32 *)(DUM_WTCFG2_ADR)) -#define DUM_RTCFG2            (*(volatile u32 *)(DUM_RTCFG2_ADR)) -#define DUM_TCFG              (*(volatile u32 *)(DUM_TCFG_ADR)) -#define DUM_OUTP_FORMAT1      (*(volatile u32 *)(DUM_OUTP_FORMAT1_ADR)) -#define DUM_OUTP_FORMAT2      (*(volatile u32 *)(DUM_OUTP_FORMAT2_ADR)) -#define DUM_SYNC_MODE         (*(volatile u32 *)(DUM_SYNC_MODE_ADR)) -#define DUM_SYNC_OUT_C        (*(volatile u32 *)(DUM_SYNC_OUT_C_ADR)) - -/* DUM SLAVE ADDRESSES */ -#define DUM_SLAVE_WRITE_ADR      (PNX4008_DUM_MAINCFG_BASE + 0x0000000) -#define DUM_SLAVE_READ1_I_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x1000000) -#define DUM_SLAVE_READ1_R_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x1000004) -#define DUM_SLAVE_READ2_I_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x1000008) -#define DUM_SLAVE_READ2_R_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x100000C) - -#define DUM_SLAVE_WRITE_W  ((volatile u32 *)(DUM_SLAVE_WRITE_ADR)) -#define DUM_SLAVE_WRITE_HW ((volatile u16 *)(DUM_SLAVE_WRITE_ADR)) -#define DUM_SLAVE_READ1_I  ((volatile u8 *)(DUM_SLAVE_READ1_I_ADR)) -#define DUM_SLAVE_READ1_R  ((volatile u16 *)(DUM_SLAVE_READ1_R_ADR)) -#define DUM_SLAVE_READ2_I  ((volatile u8 *)(DUM_SLAVE_READ2_I_ADR)) -#define DUM_SLAVE_READ2_R  ((volatile u16 *)(DUM_SLAVE_READ2_R_ADR)) - -/* Sony display register addresses */ -#define DISP_0_REG            (0x00) -#define DISP_1_REG            (0x01) -#define DISP_CAL_REG          (0x20) -#define DISP_ID_REG           (0x2A) -#define DISP_XMIN_L_REG       (0x30) -#define DISP_XMIN_H_REG       (0x31) -#define DISP_YMIN_REG         (0x32) -#define DISP_XMAX_L_REG       (0x34) -#define DISP_XMAX_H_REG       (0x35) -#define DISP_YMAX_REG         (0x36) -#define DISP_SYNC_EN_REG      (0x38) -#define DISP_SYNC_RISE_L_REG  (0x3C) -#define DISP_SYNC_RISE_H_REG  (0x3D) -#define DISP_SYNC_FALL_L_REG  (0x3E) -#define DISP_SYNC_FALL_H_REG  (0x3F) -#define DISP_PIXEL_REG        (0x0B) -#define DISP_DUMMY1_REG       (0x28) -#define DISP_DUMMY2_REG       (0x29) -#define DISP_TIMING_REG       (0x98) -#define DISP_DUMP_REG         (0x99) - -/* Sony display constants */ -#define SONY_ID1              (0x22) -#define SONY_ID2              (0x23) - -/* Philips display register addresses */ -#define PH_DISP_ORIENT_REG    (0x003) -#define PH_DISP_YPOINT_REG    (0x200) -#define PH_DISP_XPOINT_REG    (0x201) -#define PH_DISP_PIXEL_REG     (0x202) -#define PH_DISP_YMIN_REG      (0x406) -#define PH_DISP_YMAX_REG      (0x407) -#define PH_DISP_XMIN_REG      (0x408) -#define PH_DISP_XMAX_REG      (0x409) - -/* Misc constants */ -#define NO_VALID_DISPLAY_FOUND      (0) -#define DISPLAY2_IS_NOT_CONNECTED   (0) - -/* register values */ -#define V_BAC_ENABLE		(BIT(0)) -#define V_BAC_DISABLE_IDLE	(BIT(1)) -#define V_BAC_DISABLE_TRIG	(BIT(2)) -#define V_DUM_RESET		(BIT(3)) -#define V_MUX_RESET		(BIT(4)) -#define BAC_ENABLED		(BIT(0)) -#define BAC_DISABLED		0 - -/* Sony LCD commands */ -#define V_LCD_STANDBY_OFF	((BIT(25)) | (0 << 16) | DISP_0_REG) -#define V_LCD_USE_9BIT_BUS	((BIT(25)) | (2 << 16) | DISP_1_REG) -#define V_LCD_SYNC_RISE_L	((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_L_REG) -#define V_LCD_SYNC_RISE_H	((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_H_REG) -#define V_LCD_SYNC_FALL_L	((BIT(25)) | (160 << 16) | DISP_SYNC_FALL_L_REG) -#define V_LCD_SYNC_FALL_H	((BIT(25)) | (0 << 16) | DISP_SYNC_FALL_H_REG) -#define V_LCD_SYNC_ENABLE	((BIT(25)) | (128 << 16) | DISP_SYNC_EN_REG) -#define V_LCD_DISPLAY_ON	((BIT(25)) | (64 << 16) | DISP_0_REG) - -enum { -	PAD_NONE, -	PAD_512, -	PAD_1024 -}; - -enum { -	RGB888, -	RGB666, -	RGB565, -	BGR565, -	ARGB1555, -	ABGR1555, -	ARGB4444, -	ABGR4444 -}; - -struct dum_setup { -	int sync_neg_edge; -	int round_robin; -	int mux_int; -	int synced_dirty_flag_int; -	int dirty_flag_int; -	int error_int; -	int pf_empty_int; -	int sf_empty_int; -	int bac_dis_int; -	u32 dirty_base_adr; -	u32 command_base_adr; -	u32 sync_clk_div; -	int sync_output; -	u32 sync_restart_val; -	u32 set_sync_high; -	u32 set_sync_low; -}; - -struct dum_ch_setup { -	int disp_no; -	u32 xmin; -	u32 ymin; -	u32 xmax; -	u32 ymax; -	int xmirror; -	int ymirror; -	int rotate; -	u32 minadr; -	u32 maxadr; -	u32 dirtybuffer; -	int pad; -	int format; -	int hwdirty; -	int slave_trans; -}; - -struct disp_window { -	u32 xmin_l; -	u32 xmin_h; -	u32 ymin; -	u32 xmax_l; -	u32 xmax_h; -	u32 ymax; -}; - -#endif				/* #ifndef __PNX008_DUM_H__ */ diff --git a/drivers/video/pnx4008/fbcommon.h b/drivers/video/pnx4008/fbcommon.h deleted file mode 100644 index 4ebc87dafaf..00000000000 --- a/drivers/video/pnx4008/fbcommon.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2005 Philips Semiconductors - * - * 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, 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; see the file COPYING.  If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html -*/ - -#define QCIF_W  (176) -#define QCIF_H  (144) - -#define CIF_W   (352) -#define CIF_H   (288) - -#define LCD_X_RES	208 -#define LCD_Y_RES	320 -#define LCD_X_PAD	256 -#define LCD_BBP		4	/* Bytes Per Pixel */ - -#define DISP_MAX_X_SIZE     (320) -#define DISP_MAX_Y_SIZE     (208) - -#define RETURNVAL_BASE (0x400) - -enum fb_ioctl_returntype { -	ENORESOURCESLEFT = RETURNVAL_BASE, -	ERESOURCESNOTFREED, -	EPROCNOTOWNER, -	EFBNOTOWNER, -	ECOPYFAILED, -	EIOREMAPFAILED, -}; diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c deleted file mode 100644 index 6d30428e9cf..00000000000 --- a/drivers/video/pnx4008/pnxrgbfb.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * drivers/video/pnx4008/pnxrgbfb.c - * - * PNX4008's framebuffer support - * - * Author: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com> - * Based on Philips Semiconductors's code - * - * Copyrght (c) 2005 MontaVista Software, Inc. - * Copyright (c) 2005 Philips Semiconductors - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/platform_device.h> - -#include "sdum.h" -#include "fbcommon.h" - -static u32 colreg[16]; - -static struct fb_var_screeninfo rgbfb_var __initdata = { -	.xres = LCD_X_RES, -	.yres = LCD_Y_RES, -	.xres_virtual = LCD_X_RES, -	.yres_virtual = LCD_Y_RES, -	.bits_per_pixel = 32, -	.red.offset = 16, -	.red.length = 8, -	.green.offset = 8, -	.green.length = 8, -	.blue.offset = 0, -	.blue.length = 8, -	.left_margin = 0, -	.right_margin = 0, -	.upper_margin = 0, -	.lower_margin = 0, -	.vmode = FB_VMODE_NONINTERLACED, -}; -static struct fb_fix_screeninfo rgbfb_fix __initdata = { -	.id = "RGBFB", -	.line_length = LCD_X_RES * LCD_BBP, -	.type = FB_TYPE_PACKED_PIXELS, -	.visual = FB_VISUAL_TRUECOLOR, -	.xpanstep = 0, -	.ypanstep = 0, -	.ywrapstep = 0, -	.accel = FB_ACCEL_NONE, -}; - -static int channel_owned; - -static int no_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ -	return 0; -} - -static int rgbfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, -			   u_int transp, struct fb_info *info) -{ -	if (regno > 15) -		return 1; - -	colreg[regno] = ((red & 0xff00) << 8) | (green & 0xff00) | -	    ((blue & 0xff00) >> 8); -	return 0; -} - -static int rgbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ -	return pnx4008_sdum_mmap(info, vma, NULL); -} - -static struct fb_ops rgbfb_ops = { -	.fb_mmap = rgbfb_mmap, -	.fb_setcolreg = rgbfb_setcolreg, -	.fb_fillrect = cfb_fillrect, -	.fb_copyarea = cfb_copyarea, -	.fb_imageblit = cfb_imageblit, -}; - -static int rgbfb_remove(struct platform_device *pdev) -{ -	struct fb_info *info = platform_get_drvdata(pdev); - -	if (info) { -		unregister_framebuffer(info); -		fb_dealloc_cmap(&info->cmap); -		framebuffer_release(info); -		platform_set_drvdata(pdev, NULL); -	} - -	pnx4008_free_dum_channel(channel_owned, pdev->id); -	pnx4008_set_dum_exit_notification(pdev->id); - -	return 0; -} - -static int __devinit rgbfb_probe(struct platform_device *pdev) -{ -	struct fb_info *info; -	struct dumchannel_uf chan_uf; -	int ret; -	char *option; - -	info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev); -	if (!info) { -		ret = -ENOMEM; -		goto err; -	} - -	pnx4008_get_fb_addresses(FB_TYPE_RGB, (void **)&info->screen_base, -				 (dma_addr_t *) &rgbfb_fix.smem_start, -				 &rgbfb_fix.smem_len); - -	if ((ret = pnx4008_alloc_dum_channel(pdev->id)) < 0) -		goto err0; -	else { -		channel_owned = ret; -		chan_uf.channelnr = channel_owned; -		chan_uf.dirty = (u32 *) NULL; -		chan_uf.source = (u32 *) rgbfb_fix.smem_start; -		chan_uf.x_offset = 0; -		chan_uf.y_offset = 0; -		chan_uf.width = LCD_X_RES; -		chan_uf.height = LCD_Y_RES; - -		if ((ret = pnx4008_put_dum_channel_uf(chan_uf, pdev->id))< 0) -			goto err1; - -		if ((ret = -		     pnx4008_set_dum_channel_sync(channel_owned, CONF_SYNC_ON, -						  pdev->id)) < 0) -			goto err1; - -		if ((ret = -		     pnx4008_set_dum_channel_dirty_detect(channel_owned, -							 CONF_DIRTYDETECTION_ON, -							 pdev->id)) < 0) -			goto err1; -	} - -	if (!fb_get_options("pnxrgbfb", &option) && option && -			!strcmp(option, "nocursor")) -		rgbfb_ops.fb_cursor = no_cursor; - -	info->node = -1; -	info->flags = FBINFO_FLAG_DEFAULT; -	info->fbops = &rgbfb_ops; -	info->fix = rgbfb_fix; -	info->var = rgbfb_var; -	info->screen_size = rgbfb_fix.smem_len; -	info->pseudo_palette = info->par; -	info->par = NULL; - -	ret = fb_alloc_cmap(&info->cmap, 256, 0); -	if (ret < 0) -		goto err1; - -	ret = register_framebuffer(info); -	if (ret < 0) -		goto err2; -	platform_set_drvdata(pdev, info); - -	return 0; - -err2: -	fb_dealloc_cmap(&info->cmap); -err1: -	pnx4008_free_dum_channel(channel_owned, pdev->id); -err0: -	framebuffer_release(info); -err: -	return ret; -} - -static struct platform_driver rgbfb_driver = { -	.driver = { -		.name = "pnx4008-rgbfb", -	}, -	.probe = rgbfb_probe, -	.remove = rgbfb_remove, -}; - -module_platform_driver(rgbfb_driver); - -MODULE_LICENSE("GPL"); diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c deleted file mode 100644 index c5c741452ca..00000000000 --- a/drivers/video/pnx4008/sdum.c +++ /dev/null @@ -1,861 +0,0 @@ -/* - * drivers/video/pnx4008/sdum.c - * - * Display Update Master support - * - * Authors: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com> - *          Vitaly Wool <vitalywool@gmail.com> - * Based on Philips Semiconductors's code - * - * Copyrght (c) 2005-2006 MontaVista Software, Inc. - * Copyright (c) 2005 Philips Semiconductors - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/vmalloc.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/dma-mapping.h> -#include <linux/clk.h> -#include <linux/gfp.h> -#include <asm/uaccess.h> -#include <asm/gpio.h> - -#include "sdum.h" -#include "fbcommon.h" -#include "dum.h" - -/* Framebuffers we have */ - -static struct pnx4008_fb_addr { -	int fb_type; -	long addr_offset; -	long fb_length; -} fb_addr[] = { -	[0] = { -		FB_TYPE_YUV, 0, 0xB0000 -	}, -	[1] = { -		FB_TYPE_RGB, 0xB0000, 0x50000 -	}, -}; - -static struct dum_data { -	u32 lcd_phys_start; -	u32 lcd_virt_start; -	u32 slave_phys_base; -	u32 *slave_virt_base; -	int fb_owning_channel[MAX_DUM_CHANNELS]; -	struct dumchannel_uf chan_uf_store[MAX_DUM_CHANNELS]; -} dum_data; - -/* Different local helper functions */ - -static u32 nof_pixels_dx(struct dum_ch_setup *ch_setup) -{ -	return (ch_setup->xmax - ch_setup->xmin + 1); -} - -static u32 nof_pixels_dy(struct dum_ch_setup *ch_setup) -{ -	return (ch_setup->ymax - ch_setup->ymin + 1); -} - -static u32 nof_pixels_dxy(struct dum_ch_setup *ch_setup) -{ -	return (nof_pixels_dx(ch_setup) * nof_pixels_dy(ch_setup)); -} - -static u32 nof_bytes(struct dum_ch_setup *ch_setup) -{ -	u32 r = nof_pixels_dxy(ch_setup); -	switch (ch_setup->format) { -	case RGB888: -	case RGB666: -		r *= 4; -		break; - -	default: -		r *= 2; -		break; -	} -	return r; -} - -static u32 build_command(int disp_no, u32 reg, u32 val) -{ -	return ((disp_no << 26) | BIT(25) | (val << 16) | (disp_no << 10) | -		(reg << 0)); -} - -static u32 build_double_index(int disp_no, u32 val) -{ -	return ((disp_no << 26) | (val << 16) | (disp_no << 10) | (val << 0)); -} - -static void build_disp_window(struct dum_ch_setup * ch_setup, struct disp_window * dw) -{ -	dw->ymin = ch_setup->ymin; -	dw->ymax = ch_setup->ymax; -	dw->xmin_l = ch_setup->xmin & 0xFF; -	dw->xmin_h = (ch_setup->xmin & BIT(8)) >> 8; -	dw->xmax_l = ch_setup->xmax & 0xFF; -	dw->xmax_h = (ch_setup->xmax & BIT(8)) >> 8; -} - -static int put_channel(struct dumchannel chan) -{ -	int i = chan.channelnr; - -	if (i < 0 || i > MAX_DUM_CHANNELS) -		return -EINVAL; -	else { -		DUM_CH_MIN(i) = chan.dum_ch_min; -		DUM_CH_MAX(i) = chan.dum_ch_max; -		DUM_CH_CONF(i) = chan.dum_ch_conf; -		DUM_CH_CTRL(i) = chan.dum_ch_ctrl; -	} - -	return 0; -} - -static void clear_channel(int channr) -{ -	struct dumchannel chan; - -	chan.channelnr = channr; -	chan.dum_ch_min = 0; -	chan.dum_ch_max = 0; -	chan.dum_ch_conf = 0; -	chan.dum_ch_ctrl = 0; - -	put_channel(chan); -} - -static int put_cmd_string(struct cmdstring cmds) -{ -	u16 *cmd_str_virtaddr; -	u32 *cmd_ptr0_virtaddr; -	u32 cmd_str_physaddr; - -	int i = cmds.channelnr; - -	if (i < 0 || i > MAX_DUM_CHANNELS) -		return -EINVAL; -	else if ((cmd_ptr0_virtaddr = -		  (int *)ioremap_nocache(DUM_COM_BASE, -					 sizeof(int) * MAX_DUM_CHANNELS)) == -		 NULL) -		return -EIOREMAPFAILED; -	else { -		cmd_str_physaddr = ioread32(&cmd_ptr0_virtaddr[cmds.channelnr]); -		if ((cmd_str_virtaddr = -		     (u16 *) ioremap_nocache(cmd_str_physaddr, -					     sizeof(cmds))) == NULL) { -			iounmap(cmd_ptr0_virtaddr); -			return -EIOREMAPFAILED; -		} else { -			int t; -			for (t = 0; t < 8; t++) -				iowrite16(*((u16 *)&cmds.prestringlen + t), -					  cmd_str_virtaddr + t); - -			for (t = 0; t < cmds.prestringlen / 2; t++) -				 iowrite16(*((u16 *)&cmds.precmd + t), -					   cmd_str_virtaddr + t + 8); - -			for (t = 0; t < cmds.poststringlen / 2; t++) -				iowrite16(*((u16 *)&cmds.postcmd + t), -					  cmd_str_virtaddr + t + 8 + -					  	cmds.prestringlen / 2); - -			iounmap(cmd_ptr0_virtaddr); -			iounmap(cmd_str_virtaddr); -		} -	} - -	return 0; -} - -static u32 dum_ch_setup(int ch_no, struct dum_ch_setup * ch_setup) -{ -	struct cmdstring cmds_c; -	struct cmdstring *cmds = &cmds_c; -	struct disp_window dw; -	int standard; -	u32 orientation = 0; -	struct dumchannel chan = { 0 }; -	int ret; - -	if ((ch_setup->xmirror) || (ch_setup->ymirror) || (ch_setup->rotate)) { -		standard = 0; - -		orientation = BIT(1);	/* always set 9-bit-bus */ -		if (ch_setup->xmirror) -			orientation |= BIT(4); -		if (ch_setup->ymirror) -			orientation |= BIT(3); -		if (ch_setup->rotate) -			orientation |= BIT(0); -	} else -		standard = 1; - -	cmds->channelnr = ch_no; - -	/* build command string header */ -	if (standard) { -		cmds->prestringlen = 32; -		cmds->poststringlen = 0; -	} else { -		cmds->prestringlen = 48; -		cmds->poststringlen = 16; -	} - -	cmds->format = -	    (u16) ((ch_setup->disp_no << 4) | (BIT(3)) | (ch_setup->format)); -	cmds->reserved = 0x0; -	cmds->startaddr_low = (ch_setup->minadr & 0xFFFF); -	cmds->startaddr_high = (ch_setup->minadr >> 16); - -	if ((ch_setup->minadr == 0) && (ch_setup->maxadr == 0) -	    && (ch_setup->xmin == 0) -	    && (ch_setup->ymin == 0) && (ch_setup->xmax == 0) -	    && (ch_setup->ymax == 0)) { -		cmds->pixdatlen_low = 0; -		cmds->pixdatlen_high = 0; -	} else { -		u32 nbytes = nof_bytes(ch_setup); -		cmds->pixdatlen_low = (nbytes & 0xFFFF); -		cmds->pixdatlen_high = (nbytes >> 16); -	} - -	if (ch_setup->slave_trans) -		cmds->pixdatlen_high |= BIT(15); - -	/* build pre-string */ -	build_disp_window(ch_setup, &dw); - -	if (standard) { -		cmds->precmd[0] = -		    build_command(ch_setup->disp_no, DISP_XMIN_L_REG, 0x99); -		cmds->precmd[1] = -		    build_command(ch_setup->disp_no, DISP_XMIN_L_REG, -				  dw.xmin_l); -		cmds->precmd[2] = -		    build_command(ch_setup->disp_no, DISP_XMIN_H_REG, -				  dw.xmin_h); -		cmds->precmd[3] = -		    build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin); -		cmds->precmd[4] = -		    build_command(ch_setup->disp_no, DISP_XMAX_L_REG, -				  dw.xmax_l); -		cmds->precmd[5] = -		    build_command(ch_setup->disp_no, DISP_XMAX_H_REG, -				  dw.xmax_h); -		cmds->precmd[6] = -		    build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax); -		cmds->precmd[7] = -		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); -	} else { -		if (dw.xmin_l == ch_no) -			cmds->precmd[0] = -			    build_command(ch_setup->disp_no, DISP_XMIN_L_REG, -					  0x99); -		else -			cmds->precmd[0] = -			    build_command(ch_setup->disp_no, DISP_XMIN_L_REG, -					  ch_no); - -		cmds->precmd[1] = -		    build_command(ch_setup->disp_no, DISP_XMIN_L_REG, -				  dw.xmin_l); -		cmds->precmd[2] = -		    build_command(ch_setup->disp_no, DISP_XMIN_H_REG, -				  dw.xmin_h); -		cmds->precmd[3] = -		    build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin); -		cmds->precmd[4] = -		    build_command(ch_setup->disp_no, DISP_XMAX_L_REG, -				  dw.xmax_l); -		cmds->precmd[5] = -		    build_command(ch_setup->disp_no, DISP_XMAX_H_REG, -				  dw.xmax_h); -		cmds->precmd[6] = -		    build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax); -		cmds->precmd[7] = -		    build_command(ch_setup->disp_no, DISP_1_REG, orientation); -		cmds->precmd[8] = -		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); -		cmds->precmd[9] = -		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); -		cmds->precmd[0xA] = -		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); -		cmds->precmd[0xB] = -		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); -		cmds->postcmd[0] = -		    build_command(ch_setup->disp_no, DISP_1_REG, BIT(1)); -		cmds->postcmd[1] = -		    build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 1); -		cmds->postcmd[2] = -		    build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 2); -		cmds->postcmd[3] = -		    build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 3); -	} - -	if ((ret = put_cmd_string(cmds_c)) != 0) { -		return ret; -	} - -	chan.channelnr = cmds->channelnr; -	chan.dum_ch_min = ch_setup->dirtybuffer + ch_setup->minadr; -	chan.dum_ch_max = ch_setup->dirtybuffer + ch_setup->maxadr; -	chan.dum_ch_conf = 0x002; -	chan.dum_ch_ctrl = 0x04; - -	put_channel(chan); - -	return 0; -} - -static u32 display_open(int ch_no, int auto_update, u32 * dirty_buffer, -			u32 * frame_buffer, u32 xpos, u32 ypos, u32 w, u32 h) -{ - -	struct dum_ch_setup k; -	int ret; - -	/* keep width & height within display area */ -	if ((xpos + w) > DISP_MAX_X_SIZE) -		w = DISP_MAX_X_SIZE - xpos; - -	if ((ypos + h) > DISP_MAX_Y_SIZE) -		h = DISP_MAX_Y_SIZE - ypos; - -	/* assume 1 display only */ -	k.disp_no = 0; -	k.xmin = xpos; -	k.ymin = ypos; -	k.xmax = xpos + (w - 1); -	k.ymax = ypos + (h - 1); - -	/* adjust min and max values if necessary */ -	if (k.xmin > DISP_MAX_X_SIZE - 1) -		k.xmin = DISP_MAX_X_SIZE - 1; -	if (k.ymin > DISP_MAX_Y_SIZE - 1) -		k.ymin = DISP_MAX_Y_SIZE - 1; - -	if (k.xmax > DISP_MAX_X_SIZE - 1) -		k.xmax = DISP_MAX_X_SIZE - 1; -	if (k.ymax > DISP_MAX_Y_SIZE - 1) -		k.ymax = DISP_MAX_Y_SIZE - 1; - -	k.xmirror = 0; -	k.ymirror = 0; -	k.rotate = 0; -	k.minadr = (u32) frame_buffer; -	k.maxadr = (u32) frame_buffer + (((w - 1) << 10) | ((h << 2) - 2)); -	k.pad = PAD_1024; -	k.dirtybuffer = (u32) dirty_buffer; -	k.format = RGB888; -	k.hwdirty = 0; -	k.slave_trans = 0; - -	ret = dum_ch_setup(ch_no, &k); - -	return ret; -} - -static void lcd_reset(void) -{ -	u32 *dum_pio_base = (u32 *)IO_ADDRESS(PNX4008_PIO_BASE); - -	udelay(1); -	iowrite32(BIT(19), &dum_pio_base[2]); -	udelay(1); -	iowrite32(BIT(19), &dum_pio_base[1]); -	udelay(1); -} - -static int dum_init(struct platform_device *pdev) -{ -	struct clk *clk; - -	/* enable DUM clock */ -	clk = clk_get(&pdev->dev, "dum_ck"); -	if (IS_ERR(clk)) { -		printk(KERN_ERR "pnx4008_dum: Unable to access DUM clock\n"); -		return PTR_ERR(clk); -	} - -	clk_set_rate(clk, 1); -	clk_put(clk); - -	DUM_CTRL = V_DUM_RESET; - -	/* set priority to "round-robin". All other params to "false" */ -	DUM_CONF = BIT(9); - -	/* Display 1 */ -	DUM_WTCFG1 = PNX4008_DUM_WT_CFG; -	DUM_RTCFG1 = PNX4008_DUM_RT_CFG; -	DUM_TCFG = PNX4008_DUM_T_CFG; - -	return 0; -} - -static void dum_chan_init(void) -{ -	int i = 0, ch = 0; -	u32 *cmdptrs; -	u32 *cmdstrings; - -	DUM_COM_BASE = -		CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS; - -	if ((cmdptrs = -	     (u32 *) ioremap_nocache(DUM_COM_BASE, -				     sizeof(u32) * NR_OF_CMDSTRINGS)) == NULL) -		return; - -	for (ch = 0; ch < NR_OF_CMDSTRINGS; ch++) -		iowrite32(CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * ch, -			  cmdptrs + ch); - -	for (ch = 0; ch < MAX_DUM_CHANNELS; ch++) -		clear_channel(ch); - -	/* Clear the cmdstrings */ -	cmdstrings = -	    (u32 *)ioremap_nocache(*cmdptrs, -				   BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS); - -	if (!cmdstrings) -		goto out; - -	for (i = 0; i < NR_OF_CMDSTRINGS * BYTES_PER_CMDSTRING / sizeof(u32); -	     i++) -		iowrite32(0, cmdstrings + i); - -	iounmap((u32 *)cmdstrings); - -out: -	iounmap((u32 *)cmdptrs); -} - -static void lcd_init(void) -{ -	lcd_reset(); - -	DUM_OUTP_FORMAT1 = 0; /* RGB666 */ - -	udelay(1); -	iowrite32(V_LCD_STANDBY_OFF, dum_data.slave_virt_base); -	udelay(1); -	iowrite32(V_LCD_USE_9BIT_BUS, dum_data.slave_virt_base); -	udelay(1); -	iowrite32(V_LCD_SYNC_RISE_L, dum_data.slave_virt_base); -	udelay(1); -	iowrite32(V_LCD_SYNC_RISE_H, dum_data.slave_virt_base); -	udelay(1); -	iowrite32(V_LCD_SYNC_FALL_L, dum_data.slave_virt_base); -	udelay(1); -	iowrite32(V_LCD_SYNC_FALL_H, dum_data.slave_virt_base); -	udelay(1); -	iowrite32(V_LCD_SYNC_ENABLE, dum_data.slave_virt_base); -	udelay(1); -	iowrite32(V_LCD_DISPLAY_ON, dum_data.slave_virt_base); -	udelay(1); -} - -/* Interface exported to framebuffer drivers */ - -int pnx4008_get_fb_addresses(int fb_type, void **virt_addr, -			     dma_addr_t *phys_addr, int *fb_length) -{ -	int i; -	int ret = -1; -	for (i = 0; i < ARRAY_SIZE(fb_addr); i++) -		if (fb_addr[i].fb_type == fb_type) { -			*virt_addr = (void *)(dum_data.lcd_virt_start + -					fb_addr[i].addr_offset); -			*phys_addr = -			    dum_data.lcd_phys_start + fb_addr[i].addr_offset; -			*fb_length = fb_addr[i].fb_length; -			ret = 0; -			break; -		} - -	return ret; -} - -EXPORT_SYMBOL(pnx4008_get_fb_addresses); - -int pnx4008_alloc_dum_channel(int dev_id) -{ -	int i = 0; - -	while ((i < MAX_DUM_CHANNELS) && (dum_data.fb_owning_channel[i] != -1)) -		i++; - -	if (i == MAX_DUM_CHANNELS) -		return -ENORESOURCESLEFT; -	else { -		dum_data.fb_owning_channel[i] = dev_id; -		return i; -	} -} - -EXPORT_SYMBOL(pnx4008_alloc_dum_channel); - -int pnx4008_free_dum_channel(int channr, int dev_id) -{ -	if (channr < 0 || channr > MAX_DUM_CHANNELS) -		return -EINVAL; -	else if (dum_data.fb_owning_channel[channr] != dev_id) -		return -EFBNOTOWNER; -	else { -		clear_channel(channr); -		dum_data.fb_owning_channel[channr] = -1; -	} - -	return 0; -} - -EXPORT_SYMBOL(pnx4008_free_dum_channel); - -int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id) -{ -	int i = chan_uf.channelnr; -	int ret; - -	if (i < 0 || i > MAX_DUM_CHANNELS) -		return -EINVAL; -	else if (dum_data.fb_owning_channel[i] != dev_id) -		return -EFBNOTOWNER; -	else if ((ret = -		  display_open(chan_uf.channelnr, 0, chan_uf.dirty, -			       chan_uf.source, chan_uf.y_offset, -			       chan_uf.x_offset, chan_uf.height, -			       chan_uf.width)) != 0) -		return ret; -	else { -		dum_data.chan_uf_store[i].dirty = chan_uf.dirty; -		dum_data.chan_uf_store[i].source = chan_uf.source; -		dum_data.chan_uf_store[i].x_offset = chan_uf.x_offset; -		dum_data.chan_uf_store[i].y_offset = chan_uf.y_offset; -		dum_data.chan_uf_store[i].width = chan_uf.width; -		dum_data.chan_uf_store[i].height = chan_uf.height; -	} - -	return 0; -} - -EXPORT_SYMBOL(pnx4008_put_dum_channel_uf); - -int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id) -{ -	if (channr < 0 || channr > MAX_DUM_CHANNELS) -		return -EINVAL; -	else if (dum_data.fb_owning_channel[channr] != dev_id) -		return -EFBNOTOWNER; -	else { -		if (val == CONF_SYNC_ON) { -			DUM_CH_CONF(channr) |= CONF_SYNCENABLE; -			DUM_CH_CONF(channr) |= DUM_CHANNEL_CFG_SYNC_MASK | -				DUM_CHANNEL_CFG_SYNC_MASK_SET; -		} else if (val == CONF_SYNC_OFF) -			DUM_CH_CONF(channr) &= ~CONF_SYNCENABLE; -		else -			return -EINVAL; -	} - -	return 0; -} - -EXPORT_SYMBOL(pnx4008_set_dum_channel_sync); - -int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id) -{ -	if (channr < 0 || channr > MAX_DUM_CHANNELS) -		return -EINVAL; -	else if (dum_data.fb_owning_channel[channr] != dev_id) -		return -EFBNOTOWNER; -	else { -		if (val == CONF_DIRTYDETECTION_ON) -			DUM_CH_CONF(channr) |= CONF_DIRTYENABLE; -		else if (val == CONF_DIRTYDETECTION_OFF) -			DUM_CH_CONF(channr) &= ~CONF_DIRTYENABLE; -		else -			return -EINVAL; -	} - -	return 0; -} - -EXPORT_SYMBOL(pnx4008_set_dum_channel_dirty_detect); - -#if 0 /* Functions not used currently, but likely to be used in future */ - -static int get_channel(struct dumchannel *p_chan) -{ -	int i = p_chan->channelnr; - -	if (i < 0 || i > MAX_DUM_CHANNELS) -		return -EINVAL; -	else { -		p_chan->dum_ch_min = DUM_CH_MIN(i); -		p_chan->dum_ch_max = DUM_CH_MAX(i); -		p_chan->dum_ch_conf = DUM_CH_CONF(i); -		p_chan->dum_ch_stat = DUM_CH_STAT(i); -		p_chan->dum_ch_ctrl = 0;	/* WriteOnly control register */ -	} - -	return 0; -} - -int pnx4008_get_dum_channel_uf(struct dumchannel_uf *p_chan_uf, int dev_id) -{ -	int i = p_chan_uf->channelnr; - -	if (i < 0 || i > MAX_DUM_CHANNELS) -		return -EINVAL; -	else if (dum_data.fb_owning_channel[i] != dev_id) -		return -EFBNOTOWNER; -	else { -		p_chan_uf->dirty = dum_data.chan_uf_store[i].dirty; -		p_chan_uf->source = dum_data.chan_uf_store[i].source; -		p_chan_uf->x_offset = dum_data.chan_uf_store[i].x_offset; -		p_chan_uf->y_offset = dum_data.chan_uf_store[i].y_offset; -		p_chan_uf->width = dum_data.chan_uf_store[i].width; -		p_chan_uf->height = dum_data.chan_uf_store[i].height; -	} - -	return 0; -} - -EXPORT_SYMBOL(pnx4008_get_dum_channel_uf); - -int pnx4008_get_dum_channel_config(int channr, int dev_id) -{ -	int ret; -	struct dumchannel chan; - -	if (channr < 0 || channr > MAX_DUM_CHANNELS) -		return -EINVAL; -	else if (dum_data.fb_owning_channel[channr] != dev_id) -		return -EFBNOTOWNER; -	else { -		chan.channelnr = channr; -		if ((ret = get_channel(&chan)) != 0) -			return ret; -	} - -	return (chan.dum_ch_conf & DUM_CHANNEL_CFG_MASK); -} - -EXPORT_SYMBOL(pnx4008_get_dum_channel_config); - -int pnx4008_force_update_dum_channel(int channr, int dev_id) -{ -	if (channr < 0 || channr > MAX_DUM_CHANNELS) -		return -EINVAL; - -	else if (dum_data.fb_owning_channel[channr] != dev_id) -		return -EFBNOTOWNER; -	else -		DUM_CH_CTRL(channr) = CTRL_SETDIRTY; - -	return 0; -} - -EXPORT_SYMBOL(pnx4008_force_update_dum_channel); - -#endif - -int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, -		      struct device *dev) -{ -	unsigned long off = vma->vm_pgoff << PAGE_SHIFT; - -	if (off < info->fix.smem_len) { -		vma->vm_pgoff += 1; -		return dma_mmap_writecombine(dev, vma, -				(void *)dum_data.lcd_virt_start, -				dum_data.lcd_phys_start, -				FB_DMA_SIZE); -	} -	return -EINVAL; -} - -EXPORT_SYMBOL(pnx4008_sdum_mmap); - -int pnx4008_set_dum_exit_notification(int dev_id) -{ -	int i; - -	for (i = 0; i < MAX_DUM_CHANNELS; i++) -		if (dum_data.fb_owning_channel[i] == dev_id) -			return -ERESOURCESNOTFREED; - -	return 0; -} - -EXPORT_SYMBOL(pnx4008_set_dum_exit_notification); - -/* Platform device driver for DUM */ - -static int sdum_suspend(struct platform_device *pdev, pm_message_t state) -{ -	int retval = 0; -	struct clk *clk; - -	clk = clk_get(0, "dum_ck"); -	if (!IS_ERR(clk)) { -		clk_set_rate(clk, 0); -		clk_put(clk); -	} else -		retval = PTR_ERR(clk); - -	/* disable BAC */ -	DUM_CTRL = V_BAC_DISABLE_IDLE; - -	/* LCD standby & turn off display */ -	lcd_reset(); - -	return retval; -} - -static int sdum_resume(struct platform_device *pdev) -{ -	int retval = 0; -	struct clk *clk; - -	clk = clk_get(0, "dum_ck"); -	if (!IS_ERR(clk)) { -		clk_set_rate(clk, 1); -		clk_put(clk); -	} else -		retval = PTR_ERR(clk); - -	/* wait for BAC disable */ -	DUM_CTRL = V_BAC_DISABLE_TRIG; - -	while (DUM_CTRL & BAC_ENABLED) -		udelay(10); - -	/* re-init LCD */ -	lcd_init(); - -	/* enable BAC and reset MUX */ -	DUM_CTRL = V_BAC_ENABLE; -	udelay(1); -	DUM_CTRL = V_MUX_RESET; -	return 0; -} - -static int __devinit sdum_probe(struct platform_device *pdev) -{ -	int ret = 0, i = 0; - -	/* map frame buffer */ -	dum_data.lcd_virt_start = (u32) dma_alloc_writecombine(&pdev->dev, -						       FB_DMA_SIZE, -						       &dum_data.lcd_phys_start, -						       GFP_KERNEL); - -	if (!dum_data.lcd_virt_start) { -		ret = -ENOMEM; -		goto out_3; -	} - -	/* map slave registers */ -	dum_data.slave_phys_base = PNX4008_DUM_SLAVE_BASE; -	dum_data.slave_virt_base = -	    (u32 *) ioremap_nocache(dum_data.slave_phys_base, sizeof(u32)); - -	if (dum_data.slave_virt_base == NULL) { -		ret = -ENOMEM; -		goto out_2; -	} - -	/* initialize DUM and LCD display */ -	ret = dum_init(pdev); -	if (ret) -		goto out_1; - -	dum_chan_init(); -	lcd_init(); - -	DUM_CTRL = V_BAC_ENABLE; -	udelay(1); -	DUM_CTRL = V_MUX_RESET; - -	/* set decode address and sync clock divider */ -	DUM_DECODE = dum_data.lcd_phys_start & DUM_DECODE_MASK; -	DUM_CLK_DIV = PNX4008_DUM_CLK_DIV; - -	for (i = 0; i < MAX_DUM_CHANNELS; i++) -		dum_data.fb_owning_channel[i] = -1; - -	/*setup wakeup interrupt */ -	start_int_set_rising_edge(SE_DISP_SYNC_INT); -	start_int_ack(SE_DISP_SYNC_INT); -	start_int_umask(SE_DISP_SYNC_INT); - -	return 0; - -out_1: -	iounmap((void *)dum_data.slave_virt_base); -out_2: -	dma_free_writecombine(&pdev->dev, FB_DMA_SIZE, -			(void *)dum_data.lcd_virt_start, -			dum_data.lcd_phys_start); -out_3: -	return ret; -} - -static int sdum_remove(struct platform_device *pdev) -{ -	struct clk *clk; - -	start_int_mask(SE_DISP_SYNC_INT); - -	clk = clk_get(0, "dum_ck"); -	if (!IS_ERR(clk)) { -		clk_set_rate(clk, 0); -		clk_put(clk); -	} - -	iounmap((void *)dum_data.slave_virt_base); - -	dma_free_writecombine(&pdev->dev, FB_DMA_SIZE, -			(void *)dum_data.lcd_virt_start, -			dum_data.lcd_phys_start); - -	return 0; -} - -static struct platform_driver sdum_driver = { -	.driver = { -		.name = "pnx4008-sdum", -	}, -	.probe = sdum_probe, -	.remove = sdum_remove, -	.suspend = sdum_suspend, -	.resume = sdum_resume, -}; - -module_platform_driver(sdum_driver); - -MODULE_LICENSE("GPL"); diff --git a/drivers/video/pnx4008/sdum.h b/drivers/video/pnx4008/sdum.h deleted file mode 100644 index 189c3d64138..00000000000 --- a/drivers/video/pnx4008/sdum.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2005 Philips Semiconductors - * - * 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, 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; see the file COPYING.  If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html -*/ - -#define MAX_DUM_CHANNELS	64 - -#define RGB_MEM_WINDOW(x) (0x10000000 + (x)*0x00100000) - -#define QCIF_OFFSET(x) (((x) == 0) ? 0x00000: ((x) == 1) ? 0x30000: -1) -#define CIF_OFFSET(x)  (((x) == 0) ? 0x00000: ((x) == 1) ? 0x60000: -1) - -#define CTRL_SETDIRTY	 	(0x00000001) -#define CONF_DIRTYENABLE	(0x00000020) -#define CONF_SYNCENABLE		(0x00000004) - -#define DIRTY_ENABLED(conf)	((conf) & 0x0020) -#define SYNC_ENABLED(conf) 	((conf) & 0x0004) - -/* Display 1 & 2 Write Timing Configuration */ -#define PNX4008_DUM_WT_CFG		0x00372000 - -/* Display 1 & 2 Read Timing Configuration */ -#define PNX4008_DUM_RT_CFG		0x00003A47 - -/* DUM Transit State Timing Configuration */ -#define PNX4008_DUM_T_CFG		0x1D	/* 29 HCLK cycles */ - -/* DUM Sync count clock divider */ -#define PNX4008_DUM_CLK_DIV		0x02DD - -/* Memory size for framebuffer, allocated through dma_alloc_writecombine(). - * Must be PAGE aligned - */ -#define FB_DMA_SIZE (PAGE_ALIGN(SZ_1M + PAGE_SIZE)) - -#define OFFSET_RGBBUFFER (0xB0000) -#define OFFSET_YUVBUFFER (0x00000) - -#define YUVBUFFER (lcd_video_start + OFFSET_YUVBUFFER) -#define RGBBUFFER (lcd_video_start + OFFSET_RGBBUFFER) - -#define CMDSTRING_BASEADDR	(0x00C000)	/* iram */ -#define BYTES_PER_CMDSTRING	(0x80) -#define NR_OF_CMDSTRINGS	(64) - -#define MAX_NR_PRESTRINGS (0x40) -#define MAX_NR_POSTSTRINGS (0x40) - -/* various mask definitions */ -#define DUM_CLK_ENABLE 0x01 -#define DUM_CLK_DISABLE 0 -#define DUM_DECODE_MASK 0x1FFFFFFF -#define DUM_CHANNEL_CFG_MASK 0x01FF -#define DUM_CHANNEL_CFG_SYNC_MASK 0xFFFE00FF -#define DUM_CHANNEL_CFG_SYNC_MASK_SET 0x0CA00 - -#define SDUM_RETURNVAL_BASE (0x500) - -#define CONF_SYNC_OFF		(0x602) -#define CONF_SYNC_ON		(0x603) - -#define CONF_DIRTYDETECTION_OFF	(0x600) -#define CONF_DIRTYDETECTION_ON	(0x601) - -struct dumchannel_uf { -	int channelnr; -	u32 *dirty; -	u32 *source; -	u32 x_offset; -	u32 y_offset; -	u32 width; -	u32 height; -}; - -enum { -	FB_TYPE_YUV, -	FB_TYPE_RGB -}; - -struct cmdstring { -	int channelnr; -	uint16_t prestringlen; -	uint16_t poststringlen; -	uint16_t format; -	uint16_t reserved; -	uint16_t startaddr_low; -	uint16_t startaddr_high; -	uint16_t pixdatlen_low; -	uint16_t pixdatlen_high; -	u32 precmd[MAX_NR_PRESTRINGS]; -	u32 postcmd[MAX_NR_POSTSTRINGS]; - -}; - -struct dumchannel { -	int channelnr; -	int dum_ch_min; -	int dum_ch_max; -	int dum_ch_conf; -	int dum_ch_stat; -	int dum_ch_ctrl; -}; - -int pnx4008_alloc_dum_channel(int dev_id); -int pnx4008_free_dum_channel(int channr, int dev_id); - -int pnx4008_get_dum_channel_uf(struct dumchannel_uf *pChan_uf, int dev_id); -int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id); - -int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id); -int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id); - -int pnx4008_force_dum_update_channel(int channr, int dev_id); - -int pnx4008_get_dum_channel_config(int channr, int dev_id); - -int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, struct device *dev); -int pnx4008_set_dum_exit_notification(int dev_id); - -int pnx4008_get_fb_addresses(int fb_type, void **virt_addr, -			     dma_addr_t * phys_addr, int *fb_length); diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 4e292f29bf5..0b340d6ff8a 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c @@ -1034,6 +1034,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)  	if (status) {  		dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",  			__func__, status); +		retval = -ENOMEM;  		goto err_close_device;  	}  	dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar); @@ -1046,6 +1047,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)  		dev_err(&dev->core,  			"%s: lv1_gpu_context_allocate failed: %d\n", __func__,  			status); +		retval = -ENOMEM;  		goto err_gpu_memory_free;  	} @@ -1053,6 +1055,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)  	dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);  	if (!dinfo) {  		dev_err(&dev->core, "%s: ioremap failed\n", __func__); +		retval = -ENOMEM;  		goto err_gpu_context_free;  	} @@ -1121,8 +1124,10 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)  	}  	info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core); -	if (!info) +	if (!info) { +		retval = -ENOMEM;  		goto err_context_fb_close; +	}  	par = info->par;  	par->mode_id = ~ps3fb_mode;	/* != ps3fb_mode, to trigger change */ diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 69bf9d07c23..2ed7b633bbd 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -25,8 +25,8 @@  #include <linux/interrupt.h>  #include <linux/pm_runtime.h> +#include <video/samsung_fimd.h>  #include <mach/map.h> -#include <plat/regs-fb-v4.h>  #include <plat/fb.h>  /* This driver will export a number of framebuffer interfaces depending @@ -1398,35 +1398,28 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)  	spin_lock_init(&sfb->slock); -	sfb->bus_clk = clk_get(dev, "lcd"); +	sfb->bus_clk = devm_clk_get(dev, "lcd");  	if (IS_ERR(sfb->bus_clk)) {  		dev_err(dev, "failed to get bus clock\n"); -		ret = PTR_ERR(sfb->bus_clk); -		goto err_sfb; +		return PTR_ERR(sfb->bus_clk);  	} -	clk_enable(sfb->bus_clk); +	clk_prepare_enable(sfb->bus_clk);  	if (!sfb->variant.has_clksel) { -		sfb->lcd_clk = clk_get(dev, "sclk_fimd"); +		sfb->lcd_clk = devm_clk_get(dev, "sclk_fimd");  		if (IS_ERR(sfb->lcd_clk)) {  			dev_err(dev, "failed to get lcd clock\n");  			ret = PTR_ERR(sfb->lcd_clk);  			goto err_bus_clk;  		} -		clk_enable(sfb->lcd_clk); +		clk_prepare_enable(sfb->lcd_clk);  	}  	pm_runtime_enable(sfb->dev);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(dev, "failed to find registers\n"); -		ret = -ENOENT; -		goto err_lcd_clk; -	} -  	sfb->regs = devm_request_and_ioremap(dev, res);  	if (!sfb->regs) {  		dev_err(dev, "failed to map registers\n"); @@ -1510,16 +1503,12 @@ err_pm_runtime:  err_lcd_clk:  	pm_runtime_disable(sfb->dev); -	if (!sfb->variant.has_clksel) { -		clk_disable(sfb->lcd_clk); -		clk_put(sfb->lcd_clk); -	} +	if (!sfb->variant.has_clksel) +		clk_disable_unprepare(sfb->lcd_clk);  err_bus_clk: -	clk_disable(sfb->bus_clk); -	clk_put(sfb->bus_clk); +	clk_disable_unprepare(sfb->bus_clk); -err_sfb:  	return ret;  } @@ -1541,13 +1530,10 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)  		if (sfb->windows[win])  			s3c_fb_release_win(sfb, sfb->windows[win]); -	if (!sfb->variant.has_clksel) { -		clk_disable(sfb->lcd_clk); -		clk_put(sfb->lcd_clk); -	} +	if (!sfb->variant.has_clksel) +		clk_disable_unprepare(sfb->lcd_clk); -	clk_disable(sfb->bus_clk); -	clk_put(sfb->bus_clk); +	clk_disable_unprepare(sfb->bus_clk);  	pm_runtime_put_sync(sfb->dev);  	pm_runtime_disable(sfb->dev); @@ -1575,9 +1561,9 @@ static int s3c_fb_suspend(struct device *dev)  	}  	if (!sfb->variant.has_clksel) -		clk_disable(sfb->lcd_clk); +		clk_disable_unprepare(sfb->lcd_clk); -	clk_disable(sfb->bus_clk); +	clk_disable_unprepare(sfb->bus_clk);  	pm_runtime_put_sync(sfb->dev); @@ -1595,10 +1581,10 @@ static int s3c_fb_resume(struct device *dev)  	pm_runtime_get_sync(sfb->dev); -	clk_enable(sfb->bus_clk); +	clk_prepare_enable(sfb->bus_clk);  	if (!sfb->variant.has_clksel) -		clk_enable(sfb->lcd_clk); +		clk_prepare_enable(sfb->lcd_clk);  	/* setup gpio and output polarity controls */  	pd->setup_gpio(); @@ -1654,9 +1640,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)  	struct s3c_fb *sfb = platform_get_drvdata(pdev);  	if (!sfb->variant.has_clksel) -		clk_disable(sfb->lcd_clk); +		clk_disable_unprepare(sfb->lcd_clk); -	clk_disable(sfb->bus_clk); +	clk_disable_unprepare(sfb->bus_clk);  	return 0;  } @@ -1667,10 +1653,10 @@ static int s3c_fb_runtime_resume(struct device *dev)  	struct s3c_fb *sfb = platform_get_drvdata(pdev);  	struct s3c_fb_platdata *pd = sfb->pdata; -	clk_enable(sfb->bus_clk); +	clk_prepare_enable(sfb->bus_clk);  	if (!sfb->variant.has_clksel) -		clk_enable(sfb->lcd_clk); +		clk_prepare_enable(sfb->lcd_clk);  	/* setup gpio and output polarity controls */  	pd->setup_gpio(); diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 77f34c614c8..1083bb9469e 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -11,6 +11,8 @@   * Driver based on skeletonfb.c, sa1100fb.c and others.  */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/err.h> @@ -48,7 +50,11 @@ static int debug	= 1;  static int debug;  #endif -#define dprintk(msg...)	if (debug) printk(KERN_DEBUG "s3c2410fb: " msg); +#define dprintk(msg...) \ +do { \ +	if (debug) \ +		pr_debug(msg); \ +} while (0)  /* useful functions */ @@ -598,11 +604,11 @@ static int s3c2410fb_debug_store(struct device *dev,  	if (strnicmp(buf, "on", 2) == 0 ||  	    strnicmp(buf, "1", 1) == 0) {  		debug = 1; -		printk(KERN_DEBUG "s3c2410fb: Debug On"); +		dev_dbg(dev, "s3c2410fb: Debug On");  	} else if (strnicmp(buf, "off", 3) == 0 ||  		   strnicmp(buf, "0", 1) == 0) {  		debug = 0; -		printk(KERN_DEBUG "s3c2410fb: Debug Off"); +		dev_dbg(dev, "s3c2410fb: Debug Off");  	} else {  		return -EINVAL;  	} @@ -921,7 +927,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,  	info->clk = clk_get(NULL, "lcd");  	if (IS_ERR(info->clk)) { -		printk(KERN_ERR "failed to get lcd clock source\n"); +		dev_err(&pdev->dev, "failed to get lcd clock source\n");  		ret = PTR_ERR(info->clk);  		goto release_irq;  	} @@ -929,7 +935,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,  	clk_enable(info->clk);  	dprintk("got and enabled clock\n"); -	usleep_range(1000, 1000); +	usleep_range(1000, 1100);  	info->clk_rate = clk_get_rate(info->clk); @@ -947,7 +953,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,  	/* Initialize video memory */  	ret = s3c2410fb_map_video_memory(fbinfo);  	if (ret) { -		printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret); +		dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);  		ret = -ENOMEM;  		goto release_clock;  	} @@ -970,7 +976,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,  	ret = register_framebuffer(fbinfo);  	if (ret < 0) { -		printk(KERN_ERR "Failed to register framebuffer device: %d\n", +		dev_err(&pdev->dev, "Failed to register framebuffer device: %d\n",  			ret);  		goto free_cpufreq;  	} @@ -978,9 +984,9 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,  	/* create device files */  	ret = device_create_file(&pdev->dev, &dev_attr_debug);  	if (ret) -		printk(KERN_ERR "failed to add debug attribute\n"); +		dev_err(&pdev->dev, "failed to add debug attribute\n"); -	printk(KERN_INFO "fb%d: %s frame buffer device\n", +	dev_info(&pdev->dev, "fb%d: %s frame buffer device\n",  		fbinfo->node, fbinfo->fix.id);  	return 0; @@ -1028,7 +1034,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev)  	s3c2410fb_cpufreq_deregister(info);  	s3c2410fb_lcd_enable(info, 0); -	usleep_range(1000, 1000); +	usleep_range(1000, 1100);  	s3c2410fb_unmap_video_memory(fbinfo); @@ -1065,7 +1071,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)  	 * the LCD DMA engine is not going to get back on the bus  	 * before the clock goes off again (bjd) */ -	usleep_range(1000, 1000); +	usleep_range(1000, 1100);  	clk_disable(info->clk);  	return 0; @@ -1077,7 +1083,7 @@ static int s3c2410fb_resume(struct platform_device *dev)  	struct s3c2410fb_info *info = fbinfo->par;  	clk_enable(info->clk); -	usleep_range(1000, 1000); +	usleep_range(1000, 1100);  	s3c2410fb_init_registers(fbinfo); @@ -1134,8 +1140,8 @@ static void __exit s3c2410fb_cleanup(void)  module_init(s3c2410fb_init);  module_exit(s3c2410fb_cleanup); -MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, " -	      "Ben Dooks <ben-linux@fluff.org>"); +MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); +MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");  MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");  MODULE_LICENSE("GPL");  MODULE_ALIAS("platform:s3c2410-lcd"); diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 0d0f52c18fd..f4f53b082d0 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -2266,8 +2266,10 @@ static int __devinit savagefb_probe(struct pci_dev* dev,  	lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);  	info->var.yres_virtual = info->fix.smem_len/lpitch; -	if (info->var.yres_virtual < info->var.yres) +	if (info->var.yres_virtual < info->var.yres) { +		err = -ENOMEM;  		goto failed; +	}  #if defined(CONFIG_FB_SAVAGE_ACCEL)  	/* diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c index 9dec64da401..3ab18f5a375 100644 --- a/drivers/video/sis/initextlfb.c +++ b/drivers/video/sis/initextlfb.c @@ -65,7 +65,7 @@ sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,      }  #endif -    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {; +    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {         printk(KERN_ERR "Could not find mode %x\n", ModeNo);         return 65000;      } diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c index b7f27acaf81..729a50722bd 100644 --- a/drivers/video/sunxvr1000.c +++ b/drivers/video/sunxvr1000.c @@ -141,8 +141,10 @@ static int __devinit gfb_probe(struct platform_device *op)  	gp->fb_base = of_ioremap(&op->resource[6], 0,  				 gp->fb_size, "gfb fb"); -	if (!gp->fb_base) +	if (!gp->fb_base) { +		err = -ENOMEM;  		goto err_release_fb; +	}  	err = gfb_set_fbinfo(gp);  	if (err) diff --git a/drivers/video/sunxvr2500.c b/drivers/video/sunxvr2500.c index 5848436c19d..7fbcba86d1a 100644 --- a/drivers/video/sunxvr2500.c +++ b/drivers/video/sunxvr2500.c @@ -181,8 +181,10 @@ static int __devinit s3d_pci_register(struct pci_dev *pdev,  	sp->fb_size = info->fix.line_length * sp->height;  	sp->fb_base = ioremap(sp->fb_base_phys, sp->fb_size); -	if (!sp->fb_base) +	if (!sp->fb_base) { +		err = -ENOMEM;  		goto err_release_pci; +	}  	err = s3d_set_fbinfo(sp);  	if (err) diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c index eb931b8626f..6c71b1b4447 100644 --- a/drivers/video/sunxvr500.c +++ b/drivers/video/sunxvr500.c @@ -298,8 +298,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,  		goto err_release_fb;  	}  	ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000); -	if (!ep->ramdac) +	if (!ep->ramdac) { +		err = -ENOMEM;  		goto err_release_pci1; +	}  	ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0);  	ep->fb8_0_off -= ep->fb_base_reg; @@ -343,8 +345,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,  	ep->fb_size = info->fix.line_length * ep->height;  	ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size); -	if (!ep->fb_base) +	if (!ep->fb_base) { +		err = -ENOMEM;  		goto err_release_pci0; +	}  	err = e3d_set_fbinfo(ep);  	if (err) diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index f45eba3d615..86d449ea316 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -646,7 +646,7 @@ static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,  	result = fb_sys_write(info, buf, count, ppos);  	if (result > 0) { -		int start = max((int)(offset / info->fix.line_length) - 1, 0); +		int start = max((int)(offset / info->fix.line_length), 0);  		int lines = min((u32)((result / info->fix.line_length) + 1),  				(u32)info->var.yres); diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index b0e2a4261af..2f8f82d874a 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -659,6 +659,8 @@ static int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task,  	task->t.flags = TF_BUF_RET | TF_BUF_ESDI;  	task->t.buf_len = EDID_LENGTH;  	task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL); +	if (!task->buf) +		return -ENOMEM;  	err = uvesafb_exec(task); diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c index 89aef343e29..4709edc3cb7 100644 --- a/drivers/video/vermilion/vermilion.c +++ b/drivers/video/vermilion/vermilion.c @@ -1167,8 +1167,7 @@ void vmlfb_unregister_subsys(struct vml_sys *sys)  	list_for_each_entry_safe(entry, next, &global_has_mode, head) {  		printk(KERN_DEBUG MODULE_NAME ": subsys disable pipe\n");  		vmlfb_disable_pipe(entry); -		list_del(&entry->head); -		list_add_tail(&entry->head, &global_no_mode); +		list_move_tail(&entry->head, &global_no_mode);  	}  	mutex_unlock(&vml_mutex);  } diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c index af8f26b643c..db1e39277e3 100644 --- a/drivers/video/via/via_clock.c +++ b/drivers/video/via/via_clock.c @@ -25,6 +25,7 @@  #include <linux/kernel.h>  #include <linux/via-core.h> +#include <asm/olpc.h>  #include "via_clock.h"  #include "global.h"  #include "debug.h" @@ -289,6 +290,10 @@ static void dummy_set_pll(struct via_pll_config config)  	printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);  } +static void noop_set_clock_state(u8 state) +{ +} +  void via_clock_init(struct via_clock *clock, int gfx_chip)  {  	switch (gfx_chip) { @@ -346,4 +351,18 @@ void via_clock_init(struct via_clock *clock, int gfx_chip)  		break;  	} + +	if (machine_is_olpc()) { +		/* The OLPC XO-1.5 cannot suspend/resume reliably if the +		 * IGA1/IGA2 clocks are set as on or off (memory rot +		 * occasionally happens during suspend under such +		 * configurations). +		 * +		 * The only known stable scenario is to leave this bits as-is, +		 * which in their default states are documented to enable the +		 * clock only when it is needed. +		 */ +		clock->set_primary_clock_state = noop_set_clock_state; +		clock->set_secondary_clock_state = noop_set_clock_state; +	}  } diff --git a/include/video/omapdss.h b/include/video/omapdss.h index a6267a2d292..3729173b7fb 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -48,10 +48,10 @@  #define DISPC_IRQ_FRAMEDONEWB		(1 << 23)  #define DISPC_IRQ_FRAMEDONETV		(1 << 24)  #define DISPC_IRQ_WBBUFFEROVERFLOW	(1 << 25) -#define DISPC_IRQ_FRAMEDONE3		(1 << 26) -#define DISPC_IRQ_VSYNC3		(1 << 27) -#define DISPC_IRQ_ACBIAS_COUNT_STAT3	(1 << 28) -#define DISPC_IRQ_SYNC_LOST3		(1 << 29) +#define DISPC_IRQ_SYNC_LOST3		(1 << 27) +#define DISPC_IRQ_VSYNC3		(1 << 28) +#define DISPC_IRQ_ACBIAS_COUNT_STAT3	(1 << 29) +#define DISPC_IRQ_FRAMEDONE3		(1 << 30)  struct omap_dss_device;  struct omap_overlay_manager; @@ -73,6 +73,7 @@ enum omap_plane {  	OMAP_DSS_VIDEO1	= 1,  	OMAP_DSS_VIDEO2	= 2,  	OMAP_DSS_VIDEO3	= 3, +	OMAP_DSS_WB	= 4,  };  enum omap_channel { @@ -186,6 +187,8 @@ enum omap_overlay_caps {  	OMAP_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1,  	OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2,  	OMAP_DSS_OVL_CAP_ZORDER = 1 << 3, +	OMAP_DSS_OVL_CAP_POS = 1 << 4, +	OMAP_DSS_OVL_CAP_REPLICATION = 1 << 5,  };  enum omap_overlay_manager_caps { @@ -207,6 +210,16 @@ enum omap_hdmi_flags {  	OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0,  }; +enum omap_dss_output_id { +	OMAP_DSS_OUTPUT_DPI	= 1 << 0, +	OMAP_DSS_OUTPUT_DBI	= 1 << 1, +	OMAP_DSS_OUTPUT_SDI	= 1 << 2, +	OMAP_DSS_OUTPUT_DSI1	= 1 << 3, +	OMAP_DSS_OUTPUT_DSI2	= 1 << 4, +	OMAP_DSS_OUTPUT_VENC	= 1 << 5, +	OMAP_DSS_OUTPUT_HDMI	= 1 << 6, +}; +  /* RFBI */  struct rfbi_timings { @@ -243,7 +256,7 @@ void rfbi_bus_unlock(void);  /* DSI */ -struct omap_dss_dsi_videomode_data { +struct omap_dss_dsi_videomode_timings {  	/* DSI video mode blanking data */  	/* Unit: byte clock cycles */  	u16 hsa; @@ -424,6 +437,8 @@ struct omap_overlay {  			struct omap_overlay_info *info);  	int (*wait_for_go)(struct omap_overlay *ovl); + +	struct omap_dss_device *(*get_device)(struct omap_overlay *ovl);  };  struct omap_overlay_manager_info { @@ -448,9 +463,10 @@ struct omap_overlay_manager {  	enum omap_overlay_manager_caps caps;  	struct list_head overlays;  	enum omap_display_type supported_displays; +	enum omap_dss_output_id supported_outputs;  	/* dynamic fields */ -	struct omap_dss_device *device; +	struct omap_dss_output *output;  	/*  	 * The following functions do not block: @@ -463,9 +479,9 @@ struct omap_overlay_manager {  	 * interrupt context  	 */ -	int (*set_device)(struct omap_overlay_manager *mgr, -		struct omap_dss_device *dssdev); -	int (*unset_device)(struct omap_overlay_manager *mgr); +	int (*set_output)(struct omap_overlay_manager *mgr, +		struct omap_dss_output *output); +	int (*unset_output)(struct omap_overlay_manager *mgr);  	int (*set_manager_info)(struct omap_overlay_manager *mgr,  			struct omap_overlay_manager_info *info); @@ -475,6 +491,8 @@ struct omap_overlay_manager {  	int (*apply)(struct omap_overlay_manager *mgr);  	int (*wait_for_go)(struct omap_overlay_manager *mgr);  	int (*wait_for_vsync)(struct omap_overlay_manager *mgr); + +	struct omap_dss_device *(*get_device)(struct omap_overlay_manager *mgr);  };  /* 22 pins means 1 clk lane and 10 data lanes */ @@ -492,6 +510,37 @@ struct omap_dsi_pin_config {  	int pins[OMAP_DSS_MAX_DSI_PINS];  }; +struct omap_dss_writeback_info { +	u32 paddr; +	u32 p_uv_addr; +	u16 buf_width; +	u16 width; +	u16 height; +	enum omap_color_mode color_mode; +	u8 rotation; +	enum omap_dss_rotation_type rotation_type; +	bool mirror; +	u8 pre_mult_alpha; +}; + +struct omap_dss_output { +	struct list_head list; + +	/* display type supported by the output */ +	enum omap_display_type type; + +	/* output instance */ +	enum omap_dss_output_id id; + +	/* output's platform device pointer */ +	struct platform_device *pdev; + +	/* dynamic fields */ +	struct omap_overlay_manager *manager; + +	struct omap_dss_device *device; +}; +  struct omap_dss_device {  	struct device dev; @@ -564,7 +613,7 @@ struct omap_dss_device {  		enum omap_dss_dsi_pixel_format dsi_pix_fmt;  		enum omap_dss_dsi_mode dsi_mode; -		struct omap_dss_dsi_videomode_data dsi_vm_data; +		struct omap_dss_dsi_videomode_timings dsi_vm_timings;  	} panel;  	struct { @@ -590,7 +639,7 @@ struct omap_dss_device {  	enum omap_display_caps caps; -	struct omap_overlay_manager *manager; +	struct omap_dss_output *output;  	enum omap_dss_display_state state; @@ -605,6 +654,8 @@ struct omap_dss_device {  struct omap_dss_hdmi_data  { +	int ct_cp_hpd_gpio; +	int ls_oe_gpio;  	int hpd_gpio;  }; @@ -699,6 +750,11 @@ struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);  int omap_dss_get_num_overlays(void);  struct omap_overlay *omap_dss_get_overlay(int num); +struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id); +int omapdss_output_set_device(struct omap_dss_output *out, +		struct omap_dss_device *dssdev); +int omapdss_output_unset_device(struct omap_dss_output *out); +  void omapdss_default_get_resolution(struct omap_dss_device *dssdev,  		u16 *xres, u16 *yres);  int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev); @@ -719,6 +775,15 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,  void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,  		bool enable);  int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable); +void omapdss_dsi_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings); +void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h); +void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev, +		enum omap_dss_dsi_pixel_format fmt); +void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev, +		enum omap_dss_dsi_mode mode); +void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev, +		struct omap_dss_dsi_videomode_timings *timings);  int omap_dsi_update(struct omap_dss_device *dssdev, int channel,  		void (*callback)(int, void *), void *data); @@ -727,6 +792,8 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);  void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);  int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,  		const struct omap_dsi_pin_config *pin_cfg); +int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, +		unsigned long ddr_clk, unsigned long lp_clk);  int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);  void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, @@ -734,22 +801,29 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,  int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);  void omapdss_dpi_display_disable(struct omap_dss_device *dssdev); -void dpi_set_timings(struct omap_dss_device *dssdev, -			struct omap_video_timings *timings); +void omapdss_dpi_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings);  int dpi_check_timings(struct omap_dss_device *dssdev,  			struct omap_video_timings *timings); +void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines);  int omapdss_sdi_display_enable(struct omap_dss_device *dssdev);  void omapdss_sdi_display_disable(struct omap_dss_device *dssdev); +void omapdss_sdi_set_timings(struct omap_dss_device *dssdev, +		struct omap_video_timings *timings); +void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs);  int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev);  void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev); -int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, -		u16 *x, u16 *y, u16 *w, u16 *h); -int omap_rfbi_update(struct omap_dss_device *dssdev, -		u16 x, u16 y, u16 w, u16 h, -		void (*callback)(void *), void *data); -int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, +int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *), +		void *data); +int omap_rfbi_configure(struct omap_dss_device *dssdev); +void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h); +void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, +		int pixel_size); +void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,  		int data_lines); +void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, +		struct rfbi_timings *timings);  #endif diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/include/video/samsung_fimd.h index 9a78012d6f4..7ae6c07f2ef 100644 --- a/arch/arm/plat-samsung/include/plat/regs-fb.h +++ b/include/video/samsung_fimd.h @@ -1,13 +1,13 @@ -/* arch/arm/plat-samsung/include/plat/regs-fb.h +/* include/video/samsung_fimd.h   *   * Copyright 2008 Openmoko, Inc.   * Copyright 2008 Simtec Electronics   *      http://armlinux.simtec.co.uk/   *      Ben Dooks <ben@simtec.co.uk>   * - * S3C Platform - new-style framebuffer register definitions + * S3C Platform - new-style fimd and framebuffer register definitions   * - * This is the register set for the new style framebuffer interface + * This is the register set for the fimd and new style framebuffer interface   * found from the S3C2443 onwards into the S3C2416, S3C2450 and the   * S3C64XX series such as the S3C6400 and S3C6410.   * @@ -15,19 +15,11 @@   * whichever architecture is selected, it only contains the core of the   * register set. See <mach/regs-fb.h> to get the specifics.   * - * Note, we changed to using regs-fb.h as it avoids any clashes with - * the original regs-lcd.h so out of the way of regs-lcd.h as well as - * indicating the newer block is much more than just an LCD interface. - *   * 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.  */ -/* Please do not include this file directly, use <mach/regs-fb.h> to - * ensure all the localised SoC support is included as necessary. -*/ -  /* VIDCON0 */  #define VIDCON0					(0x00) @@ -401,3 +393,141 @@  #define BLENDCON_NEW_8BIT_ALPHA_VALUE		(1 << 0)  #define BLENDCON_NEW_4BIT_ALPHA_VALUE		(0 << 0) +#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */ +#define VIDCON1_FSTATUS_EVEN	(1 << 15) + +/* Video timing controls */ +#define VIDTCON0				(0x10) +#define VIDTCON1				(0x14) +#define VIDTCON2				(0x18) + +/* Window position controls */ + +#define WINCON(_win)				(0x20 + ((_win) * 4)) + +/* OSD1 and OSD4 do not have register D */ + +#define VIDOSD_BASE				(0x40) + +#define VIDINTCON0				(0x130) + +/* WINCONx */ + +#define WINCONx_CSCWIDTH_MASK			(0x3 << 26) +#define WINCONx_CSCWIDTH_SHIFT			(26) +#define WINCONx_CSCWIDTH_WIDE			(0x0 << 26) +#define WINCONx_CSCWIDTH_NARROW			(0x3 << 26) + +#define WINCONx_ENLOCAL				(1 << 22) +#define WINCONx_BUFSTATUS			(1 << 21) +#define WINCONx_BUFSEL				(1 << 20) +#define WINCONx_BUFAUTOEN			(1 << 19) +#define WINCONx_YCbCr				(1 << 13) + +#define WINCON1_LOCALSEL_CAMIF			(1 << 23) + +#define WINCON2_LOCALSEL_CAMIF			(1 << 23) +#define WINCON2_BLD_PIX				(1 << 6) + +#define WINCON2_ALPHA_SEL			(1 << 1) +#define WINCON2_BPPMODE_MASK			(0xf << 2) +#define WINCON2_BPPMODE_SHIFT			(2) +#define WINCON2_BPPMODE_1BPP			(0x0 << 2) +#define WINCON2_BPPMODE_2BPP			(0x1 << 2) +#define WINCON2_BPPMODE_4BPP			(0x2 << 2) +#define WINCON2_BPPMODE_8BPP_1232		(0x4 << 2) +#define WINCON2_BPPMODE_16BPP_565		(0x5 << 2) +#define WINCON2_BPPMODE_16BPP_A1555		(0x6 << 2) +#define WINCON2_BPPMODE_16BPP_I1555		(0x7 << 2) +#define WINCON2_BPPMODE_18BPP_666		(0x8 << 2) +#define WINCON2_BPPMODE_18BPP_A1665		(0x9 << 2) +#define WINCON2_BPPMODE_19BPP_A1666		(0xa << 2) +#define WINCON2_BPPMODE_24BPP_888		(0xb << 2) +#define WINCON2_BPPMODE_24BPP_A1887		(0xc << 2) +#define WINCON2_BPPMODE_25BPP_A1888		(0xd << 2) +#define WINCON2_BPPMODE_28BPP_A4888		(0xd << 2) + +#define WINCON3_BLD_PIX				(1 << 6) + +#define WINCON3_ALPHA_SEL			(1 << 1) +#define WINCON3_BPPMODE_MASK			(0xf << 2) +#define WINCON3_BPPMODE_SHIFT			(2) +#define WINCON3_BPPMODE_1BPP			(0x0 << 2) +#define WINCON3_BPPMODE_2BPP			(0x1 << 2) +#define WINCON3_BPPMODE_4BPP			(0x2 << 2) +#define WINCON3_BPPMODE_16BPP_565		(0x5 << 2) +#define WINCON3_BPPMODE_16BPP_A1555		(0x6 << 2) +#define WINCON3_BPPMODE_16BPP_I1555		(0x7 << 2) +#define WINCON3_BPPMODE_18BPP_666		(0x8 << 2) +#define WINCON3_BPPMODE_18BPP_A1665		(0x9 << 2) +#define WINCON3_BPPMODE_19BPP_A1666		(0xa << 2) +#define WINCON3_BPPMODE_24BPP_888		(0xb << 2) +#define WINCON3_BPPMODE_24BPP_A1887		(0xc << 2) +#define WINCON3_BPPMODE_25BPP_A1888		(0xd << 2) +#define WINCON3_BPPMODE_28BPP_A4888		(0xd << 2) + +#define VIDINTCON0_FIFIOSEL_WINDOW2		(0x10 << 5) +#define VIDINTCON0_FIFIOSEL_WINDOW3		(0x20 << 5) +#define VIDINTCON0_FIFIOSEL_WINDOW4		(0x40 << 5) + +#define DITHMODE				(0x170) +#define WINxMAP(_win)				(0x180 + ((_win) * 4)) + + +#define DITHMODE_R_POS_MASK			(0x3 << 5) +#define DITHMODE_R_POS_SHIFT			(5) +#define DITHMODE_R_POS_8BIT			(0x0 << 5) +#define DITHMODE_R_POS_6BIT			(0x1 << 5) +#define DITHMODE_R_POS_5BIT			(0x2 << 5) + +#define DITHMODE_G_POS_MASK			(0x3 << 3) +#define DITHMODE_G_POS_SHIFT			(3) +#define DITHMODE_G_POS_8BIT			(0x0 << 3) +#define DITHMODE_G_POS_6BIT			(0x1 << 3) +#define DITHMODE_G_POS_5BIT			(0x2 << 3) + +#define DITHMODE_B_POS_MASK			(0x3 << 1) +#define DITHMODE_B_POS_SHIFT			(1) +#define DITHMODE_B_POS_8BIT			(0x0 << 1) +#define DITHMODE_B_POS_6BIT			(0x1 << 1) +#define DITHMODE_B_POS_5BIT			(0x2 << 1) + +#define DITHMODE_DITH_EN			(1 << 0) + +#define WPALCON					(0x1A0) + +/* Palette control */ +/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L), + * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */ +#define WPALCON_W4PAL_16BPP_A555		(1 << 8) +#define WPALCON_W3PAL_16BPP_A555		(1 << 7) +#define WPALCON_W2PAL_16BPP_A555		(1 << 6) + + +/* Notes on per-window bpp settings + * + * Value	Win0	 Win1	  Win2	   Win3	    Win 4 + * 0000		1(P)	 1(P)	  1(P)	   1(P)	    1(P) + * 0001		2(P)	 2(P)     2(P)	   2(P)	    2(P) + * 0010		4(P)	 4(P)     4(P)	   4(P)     -none- + * 0011		8(P)	 8(P)     -none-   -none-   -none- + * 0100		-none-	 8(A232)  8(A232)  -none-   -none- + * 0101		16(565)	 16(565)  16(565)  16(565)   16(565) + * 0110		-none-	 16(A555) 16(A555) 16(A555)  16(A555) + * 0111		16(I555) 16(I565) 16(I555) 16(I555)  16(I555) + * 1000		18(666)	 18(666)  18(666)  18(666)   18(666) + * 1001		-none-	 18(A665) 18(A665) 18(A665)  16(A665) + * 1010		-none-	 19(A666) 19(A666) 19(A666)  19(A666) + * 1011		24(888)	 24(888)  24(888)  24(888)   24(888) + * 1100		-none-	 24(A887) 24(A887) 24(A887)  24(A887) + * 1101		-none-	 25(A888) 25(A888) 25(A888)  25(A888) + * 1110		-none-	 -none-	  -none-   -none-    -none- + * 1111		-none-	 -none-   -none-   -none-    -none- +*/ + +/* FIMD Version 8 register offset definitions */ +#define FIMD_V8_VIDTCON0	(0x20010) +#define FIMD_V8_VIDTCON1	(0x20014) +#define FIMD_V8_VIDTCON2	(0x20018) +#define FIMD_V8_VIDTCON3	(0x2001C) +#define FIMD_V8_VIDCON1		(0x20004)  |