diff options
Diffstat (limited to 'arch')
-rwxr-xr-x | arch/arm/configs/mop500_power_defconfig | 4 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-mcde.c | 449 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/board-mop500.c | 491 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/include/mach/prcmu-fw-api.h | 1 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/include/mach/prcmu-regs.h | 26 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/prcmu-fw.c | 85 |
7 files changed, 595 insertions, 462 deletions
diff --git a/arch/arm/configs/mop500_power_defconfig b/arch/arm/configs/mop500_power_defconfig index f98e650934f..a427cb63fc0 100755 --- a/arch/arm/configs/mop500_power_defconfig +++ b/arch/arm/configs/mop500_power_defconfig @@ -1309,8 +1309,8 @@ CONFIG_FB_B2R2=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_DUMMY_CONSOLE is not set +# CONFIG_FRAMEBUFFER_CONSOLE is not set # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FONTS is not set diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index e7bbb54e48c..3e3d7ad581c 100755 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o mop500-sdi.o obj-$(CONFIG_UX500_SOC_DB5500) += db5500-devices.o cpu-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += db8500-devices.o hsi.o mcde.o \ cpu-db8500.o prcmu-fw.o +obj-$(CONFIG_FB_MCDE) += board-mop500-mcde.o obj-$(CONFIG_MACH_U8500_SIMULATOR) += board-mop500.o mop500-sdi.o obj-$(CONFIG_MACH_U5500_SIMULATOR) += board-u5500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o diff --git a/arch/arm/mach-ux500/board-mop500-mcde.c b/arch/arm/mach-ux500/board-mop500-mcde.c new file mode 100644 index 00000000000..7fbb35caf22 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-mcde.c @@ -0,0 +1,449 @@ +/* + * Copyright (C) ST-Ericsson AB 2010 + * + * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ +#include <linux/platform_device.h> +#include <mach/tc35892.h> +#include <mach/ab8500_denc.h> +#include <video/av8100.h> +#include <video/mcde_display.h> +#include <video/mcde_display-generic_dsi.h> +#include <video/mcde_display-av8100.h> +#include <video/mcde_display-ab8500.h> +#include <video/mcde_fb.h> +#include <video/mcde_dss.h> + +#define DSI_UNIT_INTERVAL_0 0xA +#define DSI_UNIT_INTERVAL_1 0xA +#define DSI_UNIT_INTERVAL_2 0x6 + +static bool rotate_main = true; +static bool display_initialize_during_boot; + +static int __init startup_graphics_setup(char *str) +{ + if (!str) + return 1; + + switch (*str) { + case '0': + pr_info("No Startup graphics support\n"); + display_initialize_during_boot = false; + break; + case '1': + pr_info("Startup graphics supported\n"); + display_initialize_during_boot = true; + break; + default: + display_initialize_during_boot = false; + break; + }; + + return 1; +} +__setup("startup_graphics=", startup_graphics_setup); + +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY +static struct mcde_port port0 = { + .type = MCDE_PORTTYPE_DSI, + .mode = MCDE_PORTMODE_CMD, + .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, + .ifc = 1, + .link = 0, + .sync_src = MCDE_SYNCSRC_BTA, + .update_auto_trig = false, + .phy = { + .dsi = { + .virt_id = 0, + .num_data_lanes = 2, + .ui = DSI_UNIT_INTERVAL_0, + }, + }, +}; + +struct mcde_display_generic_platform_data generic_display0_pdata = { + .reset_gpio = EGPIO_PIN_15, + .reset_delay = 1, +#ifdef CONFIG_REGULATOR + .regulator_id = "v-display", + .min_supply_voltage = 2500000, /* 2.5V */ + .max_supply_voltage = 2700000 /* 2.7V */ +#endif +}; + +struct mcde_display_device generic_display0 = { + .name = "mcde_disp_generic", + .id = 0, + .port = &port0, + .chnl_id = MCDE_CHNL_A, + .fifo = MCDE_FIFO_C0, + .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, + .native_x_res = 864, + .native_y_res = 480, + .synchronized_update = false, + /* TODO: Remove rotation buffers once ESRAM driver is completed */ + .rotbuf1 = U8500_ESRAM_BASE + 0x20000 * 4, + .rotbuf2 = U8500_ESRAM_BASE + 0x20000 * 4 + 0x10000, + .dev = { + .platform_data = &generic_display0_pdata, + }, +}; +#endif /* CONFIG_DISPLAY_GENERIC_DSI_PRIMARY */ + +#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY +static struct mcde_port subdisplay_port = { + .type = MCDE_PORTTYPE_DSI, + .mode = MCDE_PORTMODE_CMD, + .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, + .ifc = 1, + .link = 1, + .sync_src = MCDE_SYNCSRC_BTA, + .update_auto_trig = false, + .phy = { + .dsi = { + .virt_id = 0, + .num_data_lanes = 2, + .ui = DSI_UNIT_INTERVAL_1, + }, + }, + +}; + +static struct mcde_display_generic_platform_data generic_subdisplay_pdata = { + .reset_gpio = EGPIO_PIN_14, + .reset_delay = 1, +#ifdef CONFIG_REGULATOR + .regulator_id = "v-display", + .min_supply_voltage = 2500000, /* 2.5V */ + .max_supply_voltage = 2700000 /* 2.7V */ +#endif +}; + +static struct mcde_display_device generic_subdisplay = { + .name = "mcde_disp_generic_subdisplay", + .id = 1, + .port = &subdisplay_port, + .chnl_id = MCDE_CHNL_C1, + .fifo = MCDE_FIFO_C1, + .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, + .native_x_res = 864, + .native_y_res = 480, + .synchronized_update = false, + .dev = { + .platform_data = &generic_subdisplay_pdata, + }, +}; +#endif /* CONFIG_DISPLAY_GENERIC_DSI_SECONDARY */ + + +#ifdef CONFIG_DISPLAY_AB8500_TERTIARY +static struct mcde_port port_tvout1 = { + .type = MCDE_PORTTYPE_DPI, + .pixel_format = MCDE_PORTPIXFMT_DPI_24BPP, + .ifc = 0, + .link = 1, + .sync_src = MCDE_SYNCSRC_OFF, + .update_auto_trig = true, + .phy = { + .dpi = { + .num_data_lanes = 4, /* DDR mode */ + }, + }, +}; + +static struct ab8500_display_platform_data ab8500_display_pdata = { + /* REVIEW use "#ifdef CONFIG_REGULATOR" as with other displays */ + /* TODO use this ID as soon as we switch to newer kernel with support or + * ab8500 TVout regulator + .regulator_id = "v-tvout", + */ + /* REVIEW change name: use transform instead of convert? */ + .rgb_2_yCbCr_convert = { + .matrix = { + {0x42, 0x81, 0x19}, + {0xffda, 0xffb6, 0x70}, + {0x70, 0xffa2, 0xffee}, + }, + .offset = {0x80, 0x10, 0x80}, + } +}; + +static int ab8500_platform_enable(struct mcde_display_device *ddev) +{ + int res = 0; + /* probe checks for pdata */ + struct ab8500_display_platform_data *pdata = ddev->dev.platform_data; + + dev_info(&ddev->dev, "%s\n", __func__); + res = stm_gpio_altfuncenable(GPIO_ALT_LCD_PANELB); + if (res != 0) + goto alt_func_failed; + + if (pdata->regulator) { + res = regulator_enable(pdata->regulator); + if (res != 0) + goto regu_failed; + } + + return res; + +regu_failed: + (void) stm_gpio_altfuncdisable(GPIO_ALT_LCD_PANELB); +alt_func_failed: + dev_warn(&ddev->dev, "Failure during %s\n", __func__); + return res; +} + +static int ab8500_platform_disable(struct mcde_display_device *ddev) +{ + int res; + /* probe checks for pdata */ + struct ab8500_display_platform_data *pdata = ddev->dev.platform_data; + + dev_info(&ddev->dev, "%s\n", __func__); + + res = stm_gpio_altfuncdisable(GPIO_ALT_LCD_PANELB); + if (res != 0) + goto alt_func_failed; + + if (pdata->regulator) { + res = regulator_disable(pdata->regulator); + if (res != 0) + goto regu_failed; + } + + return res; +regu_failed: + (void) stm_gpio_altfuncenable(GPIO_ALT_LCD_PANELB); +alt_func_failed: + dev_warn(&ddev->dev, "Failure during %s\n", __func__); + return res; + +} + +static struct mcde_display_device tvout_ab8500_display = { + .name = "mcde_tv_ab8500", + .id = 2, + .port = &port_tvout1, + .chnl_id = MCDE_CHNL_B, + .fifo = MCDE_FIFO_B, + .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, + .native_x_res = 720, + .native_y_res = 576, + .synchronized_update = true, + .dev = { + .platform_data = &ab8500_display_pdata, + }, + + /* + * We might need to describe the std here: + * - there are different PAL / NTSC formats (do they require MCDE + * settings?) + */ + .platform_enable = ab8500_platform_enable, + .platform_disable = ab8500_platform_disable, +}; + +static struct ab8500_denc_platform_data ab8500_denc_pdata = { + .ddr_enable = true, + .ddr_little_endian = false, +}; + +static struct platform_device ab8500_denc = { + .name = "ab8500_denc", + .id = -1, + .dev = { + .platform_data = &ab8500_denc_pdata, + }, +}; +#endif /* CONFIG_DISPLAY_AB8500_TERTIARY */ + +#ifdef CONFIG_DISPLAY_AV8100_TERTIARY +static struct mcde_port port2 = { + .type = MCDE_PORTTYPE_DSI, + .mode = MCDE_PORTMODE_CMD, + .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, + .ifc = 1, + .link = 2, +#ifdef AV8100_HW_TE_I2SDAT3 + .sync_src = MCDE_SYNCSRC_TE1, +#else + .sync_src = MCDE_SYNCSRC_TE0, +#endif /* AV8100_HW_TE_I2SDAT3 */ + .update_auto_trig = true, + .phy = { + .dsi = { + .virt_id = 0, + .num_data_lanes = 2, + .ui = DSI_UNIT_INTERVAL_2, + }, + }, +}; + +struct mcde_display_hdmi_platform_data av8100_hdmi_pdata = { + .reset_gpio = 0, + .reset_delay = 1, + .regulator_id = NULL, /* TODO: "display_main" */ + .ddb_id = 1, + .rgb_2_yCbCr_convert = { + .matrix = { + {0x42, 0x81, 0x19}, + {0xffda, 0xffb6, 0x70}, + {0x70, 0xffa2, 0xffee}, + }, + .offset = {0x80, 0x10, 0x80}, + } +}; + +static int av8100_platform_enable(struct mcde_display_device *dev) +{ + int ret = 0; + struct mcde_display_hdmi_platform_data *pdata = + dev->dev.platform_data; + + ret = stm_gpio_altfuncenable(GPIO_ALT_LCD_PANELA); + if (ret != 0) + goto alt_func_failed; + + if (pdata->reset_gpio) + gpio_set_value(pdata->reset_gpio, pdata->reset_high); + if (pdata->regulator) + ret = regulator_enable(pdata->regulator); +alt_func_failed: + return ret; +} + +static int av8100_platform_disable(struct mcde_display_device *dev) +{ + int ret = 0; + struct mcde_display_hdmi_platform_data *pdata = + dev->dev.platform_data; + + ret = stm_gpio_altfuncdisable(GPIO_ALT_LCD_PANELA); + if (ret != 0) + goto alt_func_failed; + if (pdata->reset_gpio) + gpio_set_value(pdata->reset_gpio, !pdata->reset_high); + if (pdata->regulator) + ret = regulator_disable(pdata->regulator); +alt_func_failed: + return ret; +} + +static struct mcde_display_device av8100_hdmi = { + .name = "av8100_hdmi", + .id = 2, + .port = &port2, + .chnl_id = MCDE_CHNL_B, + .fifo = MCDE_FIFO_B, + .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, +#ifdef CONFIG_AV8100_SDTV + .native_x_res = 720, + .native_y_res = 576, +#else + .native_x_res = 1280, + .native_y_res = 720, +#endif + .synchronized_update = true, + .dev = { + .platform_data = &av8100_hdmi_pdata, + }, + .platform_enable = av8100_platform_enable, + .platform_disable = av8100_platform_disable, +}; +#endif /* CONFIG_DISPLAY_AV8100_TERTIARY */ + +static struct fb_info *fbs[3] = { NULL, NULL, NULL }; +static struct mcde_display_device *displays[3] = { NULL, NULL, NULL }; + +static int display_registered_callback(struct notifier_block *nb, + unsigned long event, void *dev) +{ + struct mcde_display_device *ddev = dev; + u16 width, height; + bool rotate; + bool display_initialized; + + if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED) + return 0; + + if (ddev->id < 0 || ddev->id >= ARRAY_SIZE(fbs)) + return 0; + + mcde_dss_get_native_resolution(ddev, &width, &height); + + display_initialized = (ddev->id == 0 && display_initialize_during_boot); + rotate = (ddev->id == 0 && rotate_main); + if (rotate) { + u16 tmp = height; + height = width; + width = tmp; + } + + /* Create frame buffer */ + fbs[ddev->id] = mcde_fb_create(ddev, + width, height, + width, height * 2, + ddev->default_pixel_format, + rotate ? FB_ROTATE_CW : FB_ROTATE_UR, + display_initialized); + if (IS_ERR(fbs[ddev->id])) + pr_warning("Failed to create fb for display %s\n", ddev->name); + else + pr_info("Framebuffer created (%s)\n", ddev->name); + + return 0; +} + +static struct notifier_block display_nb = { + .notifier_call = display_registered_callback, +}; + +int __init init_display_devices(void) +{ + int ret; + + ret = mcde_dss_register_notifier(&display_nb); + if (ret) + pr_warning("Failed to register dss notifier\n"); + +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY + ret = mcde_display_device_register(&generic_display0); + if (ret) + pr_warning("Failed to register generic display device 0\n"); + displays[0] = &generic_display0; +#endif + +#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY + ret = mcde_display_device_register(&generic_subdisplay); + if (ret) + pr_warning("Failed to register generic sub display device\n"); + displays[1] = &generic_subdisplay; +#endif + +#ifdef CONFIG_DISPLAY_AV8100_TERTIARY + ret = mcde_display_device_register(&av8100_hdmi); + if (ret) + pr_warning("Failed to register av8100_hdmi\n"); + displays[2] = &av8100_hdmi; +#endif +#ifdef CONFIG_DISPLAY_AB8500_TERTIARY + ret = platform_device_register(&ab8500_denc); + if (ret) + pr_warning("Failed to register ab8500_denc device\n"); + else { + ret = mcde_display_device_register(&tvout_ab8500_display); + if (ret) + pr_warning("Failed to register ab8500 tvout device\n"); + displays[2] = &tvout_ab8500_display; + } +#endif + + return ret; +} + +module_init(init_display_devices); diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index b4dace33e87..782a9801aa2 100755 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -40,30 +40,16 @@ #include <mach/setup.h> #include <mach/i2c.h> #include <mach/tc35893-keypad.h> - -#include <video/mcde_display.h> -#include <video/mcde_display-generic_dsi.h> -#include <video/mcde_display-av8100.h> -#include <video/mcde_display-ab8500.h> -#include <video/mcde_fb.h> -#include <video/mcde_dss.h> #include <video/av8100.h> -#include <mach/ab8500_denc.h> #define IRQ_KP 1 /*To DO*/ int href_v1_board; -extern int platform_id; #define MOP500_PLATFORM_ID 0 #define HREF_PLATFORM_ID 1 -#define AV8100_CUT_1_0 - -/* - * This is only non-static because MCDE accesses it directly. Make this static - * once MCDE is fixed to not depend on these variables. - */ +/*#define AV8100_HW_TE_I2SDAT3*/ /* REVIEW/TODO: remove? */ int platform_id = MOP500_PLATFORM_ID; /* we have equally similar boards with very minimal @@ -123,14 +109,20 @@ static struct gpio_altfun_data gpio_altfun_table[] = { __GPIO_ALT(GPIO_ALT_SDIO, 208, 214, 0, NMK_GPIO_ALT_A, "sdio"), __GPIO_ALT(GPIO_ALT_TRACE, 70, 74, 0, NMK_GPIO_ALT_C, "stm"), __GPIO_ALT(GPIO_ALT_SDMMC2, 128, 138, 0, NMK_GPIO_ALT_A, "mmc2"), - __GPIO_ALT(GPIO_ALT_LCD_PANELB, 78, 81, 1, NMK_GPIO_ALT_A, "mcde tvout"), - __GPIO_ALT(GPIO_ALT_LCD_PANELB, 150, 150, 0, NMK_GPIO_ALT_B, "mcde tvout"), - __GPIO_ALT(GPIO_ALT_LCD_PANELA, 68, 68, 0, NMK_GPIO_ALT_A, "mcde tvout"), - __GPIO_ALT(GPIO_ALT_MMIO_INIT_BOARD, 141, 142, 0, NMK_GPIO_ALT_B, "mmio"), + __GPIO_ALT(GPIO_ALT_LCD_PANELB, 78, 81, 1, NMK_GPIO_ALT_A, + "mcde tvout"), + __GPIO_ALT(GPIO_ALT_LCD_PANELB, 150, 150, 0, NMK_GPIO_ALT_B, + "mcde tvout"), + __GPIO_ALT(GPIO_ALT_LCD_PANELA, 68, 68, 0, NMK_GPIO_ALT_A, + "mcde tvout"), + __GPIO_ALT(GPIO_ALT_MMIO_INIT_BOARD, 141, 142, 0, NMK_GPIO_ALT_B, + "mmio"), __GPIO_ALT(GPIO_ALT_MMIO_CAM_SET_I2C, 8, 9, 0, NMK_GPIO_ALT_A, "mmio"), - __GPIO_ALT(GPIO_ALT_MMIO_CAM_SET_EXT_CLK, 227, 228, 0, NMK_GPIO_ALT_A, "mmio"), + __GPIO_ALT(GPIO_ALT_MMIO_CAM_SET_EXT_CLK, 227, 228, 0, NMK_GPIO_ALT_A, + "mmio"), #ifndef CONFIG_U8500_TSC_EXT_CLK_SHARE - __GPIO_ALT(GPIO_ALT_TP_SET_EXT_CLK, 228, 228, 0, NMK_GPIO_ALT_A, "u8500_tp"), + __GPIO_ALT(GPIO_ALT_TP_SET_EXT_CLK, 228, 228, 0, NMK_GPIO_ALT_A, + "u8500_tp"), #endif }; @@ -497,10 +489,12 @@ static int bu21013_gpio_board_init(int reset_pin) if (!config_set) { retval = stm_gpio_altfuncenable(GPIO_ALT_TP_SET_EXT_CLK); if (retval < 0) { - printk(KERN_ERR "%s: gpio alternate failed\n", __func__); + printk(KERN_ERR "%s: gpio alternate failed\n", + __func__); return retval; } - clk_base = (void __iomem *)IO_ADDRESS(U8500_PRCMU_BASE + PRCMU_CLOCK_OCR); + clk_base = (void __iomem *)IO_ADDRESS(U8500_PRCMU_BASE + + PRCMU_CLOCK_OCR); clk_value = readl(clk_base); writel(TSC_EXT_CLOCK_9_6MHZ, clk_base); } @@ -520,7 +514,8 @@ static int bu21013_gpio_board_init(int reset_pin) } retval = gpio_direction_output(reset_pin, 1); if (retval < 0) { - printk(KERN_ERR "%s: gpio direction failed\n", __func__); + printk(KERN_ERR "%s: gpio direction failed\n", + __func__); return retval; } gpio_set_value(reset_pin, 1); @@ -546,7 +541,8 @@ static int bu21013_gpio_board_exit(int reset_pin) if (!config_disable_set) { retval = gpio_direction_output(reset_pin, 0); if (retval < 0) { - printk(KERN_ERR "%s: gpio direction failed\n", __func__); + printk(KERN_ERR "%s: gpio direction failed\n", + __func__); return retval; } gpio_set_value(reset_pin, 0); @@ -576,11 +572,14 @@ static int bu21013_init_irq(void (*callback)(void *parameter), void *data) retval = tc35892_set_callback(EGPIO_PIN_12, callback, (void *)data); if (retval < 0) - printk(KERN_ERR "%s: set callback failed\n", __func__); + printk(KERN_ERR "%s: set callback failed\n", + __func__); retval = tc35892_set_gpio_intr_conf(EGPIO_PIN_12, - EDGE_SENSITIVE, TC35892_FALLING_EDGE_OR_LOWLEVEL); + EDGE_SENSITIVE, + TC35892_FALLING_EDGE_OR_LOWLEVEL); if (retval < 0) - printk(KERN_ERR "%s: config failed\n", __func__); + printk(KERN_ERR "%s: config failed\n", + __func__); } } return retval; @@ -597,12 +596,14 @@ static int bu21013_exit_irq(void) if (platform_id == MOP500_PLATFORM_ID) { retval = stmpe2401_remove_callback(EGPIO_PIN_3); if (retval < 0) - printk(KERN_ERR "%s: remove callback failed\n", __func__); + pr_err("%s: remove callback failed\n", + __func__); } else if (platform_id == HREF_PLATFORM_ID) { if (!href_v1_board) { retval = tc35892_remove_callback(EGPIO_PIN_12); if (retval < 0) - printk(KERN_ERR "%s: remove calllback failed\n", __func__); + pr_err("%s: remove calllback failed\n", + __func__); } } return retval; @@ -1163,436 +1164,6 @@ struct platform_device sensors1p_device = { }; #endif -#ifdef CONFIG_FB_MCDE -#define DSI_UNIT_INTERVAL_0 0xA -#define DSI_UNIT_INTERVAL_1 0xA -#define DSI_UNIT_INTERVAL_2 0x6 - -static bool rotate_main = true; -static bool display_initialize_during_boot; - -#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY -static struct mcde_port port0 = { - .type = MCDE_PORTTYPE_DSI, - .mode = MCDE_PORTMODE_CMD, - .ifc = 1, - .link = 0, - .sync_src = MCDE_SYNCSRC_BTA, - .update_auto_trig = false, - .phy = { - .dsi = { - .virt_id = 0, - .num_data_lanes = 2, - .ui = DSI_UNIT_INTERVAL_0, - }, - }, -}; - -struct mcde_display_generic_platform_data generic_display0_pdata = { - .reset_gpio = EGPIO_PIN_15, - .reset_delay = 1, -#ifdef CONFIG_REGULATOR - .regulator_id = "v-display", - .min_supply_voltage = 2500000, /* 2.5V */ - .max_supply_voltage = 2700000 /* 2.7V */ -#endif -}; - -struct mcde_display_device generic_display0 = { - .name = "mcde_disp_generic", - .id = 0, - .port = &port0, - .chnl_id = MCDE_CHNL_A, - .fifo = MCDE_FIFO_C0, - .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, - .port_pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, - .native_x_res = 864, - .native_y_res = 480, - .synchronized_update = false, - /* TODO: Remove rotation buffers once ESRAM driver is completed */ - .rotbuf1 = U8500_ESRAM_BASE + 0x20000 * 4, - .rotbuf2 = U8500_ESRAM_BASE + 0x20000 * 4 + 0x10000, - .dev = { - .platform_data = &generic_display0_pdata, - }, -}; -#endif /* CONFIG_DISPLAY_GENERIC_DSI_PRIMARY */ - -#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY -static struct mcde_port subdisplay_port = { - .type = MCDE_PORTTYPE_DSI, - .mode = MCDE_PORTMODE_CMD, - .ifc = 1, - .link = 1, - .sync_src = MCDE_SYNCSRC_BTA, - .update_auto_trig = false, - .phy = { - .dsi = { - .virt_id = 0, - .num_data_lanes = 2, - .ui = DSI_UNIT_INTERVAL_1, - }, - }, -}; - -static struct mcde_display_generic_platform_data generic_subdisplay_pdata = { - .reset_gpio = EGPIO_PIN_14, - .reset_delay = 1, -#ifdef CONFIG_REGULATOR - .regulator_id = "v-display", - .min_supply_voltage = 2500000, /* 2.5V */ - .max_supply_voltage = 2700000 /* 2.7V */ -#endif -}; - -static struct mcde_display_device generic_subdisplay = { - .name = "mcde_disp_generic_subdisplay", - .id = 1, - .port = &subdisplay_port, - .chnl_id = MCDE_CHNL_C1, - .fifo = MCDE_FIFO_C1, - .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, - .port_pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, - .native_x_res = 864, - .native_y_res = 480, - .synchronized_update = false, - .dev = { - .platform_data = &generic_subdisplay_pdata, - }, -}; -#endif /* CONFIG_DISPLAY_GENERIC_DSI_SECONDARY */ - - -#ifdef CONFIG_DISPLAY_AB8500_TERTIARY -static struct mcde_port port_tvout1 = { - .type = MCDE_PORTTYPE_DPI, - .ifc = 0, - .link = 1, - .sync_src = MCDE_SYNCSRC_OFF, - .update_auto_trig = true, - .phy = { - .dpi = { - .num_data_lanes = 4, /* DDR mode */ - }, - }, -}; - -static struct ab8500_display_platform_data ab8500_display_pdata = { - /* TODO use this ID as soon as we switch to newer kernel with support or - * ab8500 TVout regulator - .regulator_id = "v-tvout", - */ -}; - -static int ab8500_platform_enable(struct mcde_display_device *ddev) -{ - int res = 0; - /* probe checks for pdata */ - struct ab8500_display_platform_data *pdata = ddev->dev.platform_data; - - pr_info("%s\n", __func__); - res = stm_gpio_altfuncenable(GPIO_ALT_LCD_PANELB); - if (res != 0) - goto alt_func_failed; - - if (pdata->regulator) { - res = regulator_enable(pdata->regulator); - if (res != 0) - goto regu_failed; - } - -out: - return res; - -regu_failed: - (void) stm_gpio_altfuncdisable(GPIO_ALT_LCD_PANELB); -alt_func_failed: - dev_warn(&ddev->dev, "Failure during %s\n", __func__); - goto out; -} - -static int ab8500_platform_disable(struct mcde_display_device *ddev) -{ - int res; - /* probe checks for pdata */ - struct ab8500_display_platform_data *pdata = ddev->dev.platform_data; - - dev_info(&ddev->dev, "%s\n", __func__); - - res = stm_gpio_altfuncdisable(GPIO_ALT_LCD_PANELB); - if (res != 0) - goto alt_func_failed; - - if (pdata->regulator) { - res = regulator_disable(pdata->regulator); - if (res != 0) - goto regu_failed; - } - -out: - return res; -regu_failed: - (void) stm_gpio_altfuncenable(GPIO_ALT_LCD_PANELB); -alt_func_failed: - dev_warn(&ddev->dev, "Failure during %s\n", __func__); - goto out; - -} - -static struct mcde_display_device tvout_ab8500_display = { - .name = "mcde_tv_ab8500", - .id = 2, - .port = &port_tvout1, - .chnl_id = MCDE_CHNL_B, - .fifo = MCDE_FIFO_B, - .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, - .port_pixel_format = MCDE_PORTPIXFMT_DPI_24BPP, - .native_x_res = 720, - .native_y_res = 576, - .synchronized_update = true, - .video_mode = { - .xres = 720, - .yres = 576, - }, - .dev = { - .platform_data = &ab8500_display_pdata, - }, - - /* We might need to describe the std here: - * - there are different PAL / NTSC formats (do they require MCDE - * settings?) - */ - .platform_enable = ab8500_platform_enable, - .platform_disable = ab8500_platform_disable, -}; - -static struct ab8500_denc_platform_data ab8500_denc_pdata = { - .ddr_enable = true, - .ddr_little_endian = false, -}; - -static struct platform_device ab8500_denc = { - .name = "ab8500_denc", - .id = -1, - .dev = { - .platform_data = &ab8500_denc_pdata, - }, -}; -#endif /* CONFIG_DISPLAY_AB8500_TERTIARY */ - -#ifdef CONFIG_DISPLAY_AV8100_TERTIARY -static struct mcde_port port2 = { - .type = MCDE_PORTTYPE_DSI, - .mode = MCDE_PORTMODE_CMD, - .ifc = 1, - .link = 2, - .sync_src = MCDE_SYNCSRC_TE0, - .update_auto_trig = true, - .phy = { - .dsi = { - .virt_id = 0, - .num_data_lanes = 2, - .ui = DSI_UNIT_INTERVAL_2, - }, - }, -}; - -struct mcde_display_generic_platform_data av8100_hdmi_pdata = { - .reset_gpio = 0, - .reset_delay = 1, - .regulator_id = NULL, /* TODO: "display_main" */ - .ddb_id = 1, -}; - -static int av8100_platform_enable(struct mcde_display_device *dev) -{ -#define GPIO1B_AFSLA_REG_OFFSET 0x20 -#define GPIO1B_AFSLB_REG_OFFSET 0x24 - - int ret = 0; - struct mcde_display_hdmi_platform_data *pdata = - dev->dev.platform_data; - -#ifdef AV8100_CUT_1_0 - volatile u32 __iomem *gpio_68_remap; -#endif -#ifdef AV8100_CUT_2_1 - volatile u32 __iomem *gpio_69_remap; -#endif - - /* HW trig begin */ -#ifdef AV8100_CUT_1_0 - gpio_68_remap = (u32 *) ioremap( - U8500_GPIO1_BASE + GPIO1B_AFSLB_REG_OFFSET, - (U8500_GPIO1_BASE + GPIO1B_AFSLB_REG_OFFSET + 3) - - (U8500_GPIO1_BASE + GPIO1B_AFSLB_REG_OFFSET) + 1); - - *gpio_68_remap &= 0xffffffef; - iounmap(gpio_68_remap); - - gpio_68_remap = (u32 *) ioremap( - U8500_GPIO1_BASE + GPIO1B_AFSLA_REG_OFFSET, - (U8500_GPIO1_BASE + GPIO1B_AFSLA_REG_OFFSET + 3) - - (U8500_GPIO1_BASE + GPIO1B_AFSLA_REG_OFFSET) + 1); - *gpio_68_remap |= 0x10; - iounmap(gpio_68_remap); -#endif - -#ifdef AV8100_CUT_2_1 - gpio_69_remap = (u32 *) ioremap( - U8500_GPIO1_BASE + GPIO1B_AFSLB_REG_OFFSET, - (U8500_GPIO1_BASE + GPIO1B_AFSLB_REG_OFFSET + 3) - - (U8500_GPIO1_BASE + GPIO1B_AFSLB_REG_OFFSET) + 1); - - *gpio_69_remap &= 0xffffffdf; - iounmap(gpio_69_remap); - - gpio_69_remap = (u32 *) ioremap( - U8500_GPIO1_BASE + GPIO1B_AFSLA_REG_OFFSET, - (U8500_GPIO1_BASE + GPIO1B_AFSLA_REG_OFFSET + 3) - - (U8500_GPIO1_BASE + GPIO1B_AFSLA_REG_OFFSET) + 1); - *gpio_69_remap |= 0x20; - iounmap(gpio_69_remap); -#endif - /* HW trig end */ - - if (pdata->reset_gpio) - gpio_set_value(pdata->reset_gpio, pdata->reset_high); - if (pdata->regulator) - ret = regulator_enable(pdata->regulator); - return ret; -} - -static int av8100_platform_disable(struct mcde_display_device *dev) -{ - int ret = 0; - struct mcde_display_hdmi_platform_data *pdata = - dev->dev.platform_data; - - if (pdata->reset_gpio) - gpio_set_value(pdata->reset_gpio, !pdata->reset_high); - if (pdata->regulator) - ret = regulator_disable(pdata->regulator); - - return ret; -} - -static struct mcde_display_device av8100_hdmi = { - .name = "av8100_hdmi", - .id = 2, - .port = &port2, - .chnl_id = MCDE_CHNL_B, - .fifo = MCDE_FIFO_B, - .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, - .port_pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, -#ifdef CONFIG_AV8100_SDTV - .native_x_res = 720, - .native_y_res = 576, -#else - .native_x_res = 1280, - .native_y_res = 720, -#endif - .synchronized_update = true, - .dev = { - .platform_data = &av8100_hdmi_pdata, - }, - .platform_enable = av8100_platform_enable, - .platform_disable = av8100_platform_disable, -}; -#endif /* CONFIG_DISPLAY_AV8100_TERTIARY */ - -static struct fb_info *fbs[3] = { NULL, NULL, NULL }; -static struct mcde_display_device *displays[3] = { NULL, NULL, NULL }; - -static int display_registered_callback(struct notifier_block *nb, - unsigned long event, void *dev) -{ - struct mcde_display_device *ddev = dev; - u16 width, height; - bool rotate; - bool display_initialized; - - if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED) - return 0; - - if (ddev->id < 0 || ddev->id >= ARRAY_SIZE(fbs)) - return 0; - - mcde_dss_get_native_resolution(ddev, &width, &height); - - display_initialized = (ddev->id == 0 && display_initialize_during_boot); - rotate = (ddev->id == 0 && rotate_main); - if (rotate) { - u16 tmp = height; - height = width; - width = tmp; - } - - /* Create frame buffer */ - fbs[ddev->id] = mcde_fb_create(ddev, - width, height, - width, height * 2, - ddev->default_pixel_format, - rotate ? FB_ROTATE_CW : FB_ROTATE_UR, - display_initialized); - if (IS_ERR(fbs[ddev->id])) - pr_warning("Failed to create fb for display %s\n", ddev->name); - else - pr_info("Framebuffer created (%s)\n", ddev->name); - - return 0; -} - -static struct notifier_block display_nb = { - .notifier_call = display_registered_callback, -}; - -int __init init_display_devices(void) -{ - int ret; - - ret = mcde_dss_register_notifier(&display_nb); - if (ret) - pr_warning("Failed to register dss notifier\n"); - -#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY - ret = mcde_display_device_register(&generic_display0); - if (ret) - pr_warning("Failed to register generic display device 0\n"); - displays[0] = &generic_display0; -#endif - -#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY - ret = mcde_display_device_register(&generic_subdisplay); - if (ret) - pr_warning("Failed to register generic sub display device\n"); - displays[1] = &generic_subdisplay; -#endif - -#ifdef CONFIG_DISPLAY_AV8100_TERTIARY - ret = mcde_display_device_register(&av8100_hdmi); - if (ret) - pr_warning("Failed to register av8100_hdmi\n"); - displays[2] = &av8100_hdmi; -#endif -#ifdef CONFIG_DISPLAY_AB8500_TERTIARY - ret = platform_device_register(&ab8500_denc); - if (ret) - pr_warning("Failed to register ab8500_denc device\n"); - else { - ret = mcde_display_device_register(&tvout_ab8500_display); - if (ret) - pr_warning("Failed to register ab8500 tvout device\n"); - displays[2] = &tvout_ab8500_display; - } -#endif - - return ret; -} - -module_init(init_display_devices); -#endif /* CONFIG_FB_MCDE */ - static struct i2s_board_info stm_i2s_board_info[] __initdata = { { .modalias = "i2s_device.0", diff --git a/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h b/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h index 3be7c5cfa33..e9491d1378c 100755 --- a/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h +++ b/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h @@ -118,5 +118,6 @@ void prcmu_set_callback_modem_reset_request(void (*func)(void)); void prcmu_system_reset(void); int prcmu_is_ca_wake_req_pending(void); int prcmu_read_ack_mb7(void); +int prcmu_enable_mcde(void); #endif /* __MACH_PRCMU_FW_API_V1_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h index b852663a270..0972342dfb5 100755 --- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h +++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h @@ -67,4 +67,30 @@ /* System reset register */ #define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228) +/* Level shifter and clamp control registers */ +#define PRCM_MMIP_LS_CLAMP_SET (_PRCMU_BASE + 0x420) +#define PRCM_MMIP_LS_CLAMP_CLR (_PRCMU_BASE + 0x424) + +/* PRCMU clock/PLL/reset registers */ +#define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500) +#define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504) +#define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044) +#define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064) +#define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058) +#define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07c) +#define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530) +#define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C) +#define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4) +#define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8) + +/* ePOD and memory power signal control registers */ +#define PRCM_EPOD_C_SET (_PRCMU_BASE + 0x410) +#define PRCM_SRAM_LS_SLEEP (_PRCMU_BASE + 0x304) + +/* Debug power control unit registers */ +#define PRCM_POWER_STATE_SET (_PRCMU_BASE + 0x254) + +/* Miscellaneous unit registers */ +#define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324) + #endif /* __MACH_PRCMU__REGS_H */ diff --git a/arch/arm/mach-ux500/prcmu-fw.c b/arch/arm/mach-ux500/prcmu-fw.c index 8772a145406..8c98f2fa587 100755 --- a/arch/arm/mach-ux500/prcmu-fw.c +++ b/arch/arm/mach-ux500/prcmu-fw.c @@ -80,6 +80,91 @@ static void (*prcmu_modem_reset_shrm)(void); static int prcmu_set_hwacc_st(enum hw_acc_t hw_acc, enum hw_accst_t hw_accst); + +/* +* Used by MCDE to setup all necessary PRCMU registers +*/ +#define PRCMU_CLAMP_DSS_DSIPLL 0x00600C00 +#define PRCMU_RESET_DSS 0x0000000C +#define PRCMU_ENABLE_DSS_MEM 0x00200000 +#define PRCMU_ENABLE_DSS_LOGIC 0x00100000 +#define PRCMU_DSS_SLEEP_OUTPUT_MASK 0x400 +#define PRCMU_UNCLAMP_DSS_DSIPLL 0x00600C00 +#define PRCMU_POWER_ON_DSI 0x00008000 + +#define PRCMU_DSI_CLOCK_SETTING 0x00000145 +#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000141 +#define PRCMU_PLLDSI_FREQ_SETTING 0x0004012B + +#define PRCMU_ENABLE_PLLDSI 0x00000001 +#define PRCMU_RELEASE_RESET_DSS 0x0000400C +#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000202 +#define PRCMU_ENABLE_ESCAPE_CLOCK 0x07031717 +#define PRCMU_DSI_RESET_SW 0x00000007 + +#define PRCMU_MCDE_DELAY 10 + +int prcmu_enable_mcde(void) +{ +#ifndef CONFIG_REGULATOR /* Only for V10 */ + u32 temp; +#endif + /* Clamp DSS out, DSIPLL in/out, (why not DSS input?) */ + writel(PRCMU_CLAMP_DSS_DSIPLL, PRCM_MMIP_LS_CLAMP_SET); + mdelay(PRCMU_MCDE_DELAY); + /* Enable DSS_M_INITN, DSS_L_RESETN, DSIPLL_RESETN resets */ + writel(PRCMU_RESET_DSS, PRCM_APE_RESETN_CLR); + mdelay(PRCMU_MCDE_DELAY); +#ifndef CONFIG_REGULATOR /* Only for V10 */ + /* Power on DSS mem */ + writel(PRCMU_ENABLE_DSS_MEM, PRCM_EPOD_C_SET); + mdelay(PRCMU_MCDE_DELAY); + /* Power on DSS logic */ + writel(PRCMU_ENABLE_DSS_LOGIC, PRCM_EPOD_C_SET); + mdelay(PRCMU_MCDE_DELAY); + /* Release DSS_SLEEP */ + temp = readl(PRCM_SRAM_LS_SLEEP); + writel(temp & ~PRCMU_DSS_SLEEP_OUTPUT_MASK, PRCM_SRAM_LS_SLEEP); + mdelay(PRCMU_MCDE_DELAY); +#endif + /* Unclamp DSS out, DSIPLL in/out, (why not DSS input?) */ + writel(PRCMU_UNCLAMP_DSS_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); + mdelay(PRCMU_MCDE_DELAY); +#ifndef CONFIG_REGULATOR /* Only for V10 */ + /* Power on CSI_DSI */ + writel(PRCMU_POWER_ON_DSI, PRCM_POWER_STATE_SET); + mdelay(PRCMU_MCDE_DELAY); +#endif + /* HDMI and TVCLK Should be handled somewhere else */ + /* PLLDIV=5, PLLSW=2, CLKEN=1 */ + writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT); + mdelay(PRCMU_MCDE_DELAY); + /* PLLDIV=14, PLLSW=2, CLKEN=1 */ + writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); + mdelay(PRCMU_MCDE_DELAY); + + /* D=43, N=1, R=4, SELDIV2=0 */ + writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ); + mdelay(PRCMU_MCDE_DELAY); + /* Start DSI PLL */ + writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE); + mdelay(PRCMU_MCDE_DELAY); + /* Release DSS_M_INITN, DSS_L_RESETN, DSIPLL_RESETN */ + writel(PRCMU_RELEASE_RESET_DSS, PRCM_APE_RESETN_SET); + mdelay(PRCMU_MCDE_DELAY); + /* DSI0=phi/2, DSI1=phi/2 */ + writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); + mdelay(PRCMU_MCDE_DELAY); + /* Enable ESC clk 0/1/2, div2=3, div1=0x17, div0=0x17 */ + writel(PRCMU_ENABLE_ESCAPE_CLOCK, PRCM_DSITVCLK_DIV); + mdelay(PRCMU_MCDE_DELAY); + /* Release DSI reset 0/1/2 */ + writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET); + mdelay(PRCMU_MCDE_DELAY); + return 0; +} + + /* Internal functions */ /** |