diff options
Diffstat (limited to 'arch/arm/plat-omap')
25 files changed, 1878 insertions, 492 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index f332d454651a..e7ac4f7b9688 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -27,6 +27,7 @@ config ARCH_OMAP4 bool "TI OMAP4" select CPU_V7 select ARM_GIC + select COMMON_CLKDEV endchoice diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index a83279523958..cfc0967df153 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -4,7 +4,7 @@ # Common support obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \ - usb.o fb.o io.o + usb.o fb.o vram.o vrfb.o io.o obj-m := obj-n := obj- := diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index e8c327a45a55..972694b217fe 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -40,36 +40,10 @@ static struct clk_functions *arch_clock; * clock framework is not up , it is defined here to avoid rework in * every driver. Also dummy prcm reset function is added */ -/* Dummy hooks only for OMAP4.For rest OMAPs, common clkdev is used */ -#if defined(CONFIG_ARCH_OMAP4) -struct clk *clk_get(struct device *dev, const char *id) -{ - return NULL; -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); - -void omap2_clk_prepare_for_reboot(void) -{ -} -EXPORT_SYMBOL(omap2_clk_prepare_for_reboot); - -void omap_prcm_arch_reset(char mode) -{ -} -EXPORT_SYMBOL(omap_prcm_arch_reset); -#endif int clk_enable(struct clk *clk) { unsigned long flags; int ret = 0; - if (cpu_is_omap44xx()) - /* OMAP4 clk framework not supported yet */ - return 0; if (clk == NULL || IS_ERR(clk)) return -EINVAL; diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index ebcf006406f9..a2d5298f656c 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -372,6 +372,7 @@ static struct omap_globals omap4_globals = { .ctrl = OMAP2_IO_ADDRESS(OMAP443X_CTRL_BASE), .prm = OMAP2_IO_ADDRESS(OMAP4430_PRM_BASE), .cm = OMAP2_IO_ADDRESS(OMAP4430_CM_BASE), + .cm2 = OMAP2_IO_ADDRESS(OMAP4430_CM2_BASE), }; void __init omap2_set_globals_443x(void) diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index afba7af9da90..04f43d5ee8cb 100755 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -384,6 +384,31 @@ static void omap_init_rng(void) static inline void omap_init_rng(void) {} #endif +#if defined(CONFIG_VIDEO_OMAP_VIDEOOUT) || \ + defined(CONFIG_VIDEO_OMAP_VIDEOOUT_MODULE) +#ifdef CONFIG_FB_OMAP2 +static struct resource sdp4430_vout_resource[3 - CONFIG_FB_OMAP2_NUM_FBS] = { +}; +#else +static struct resource sdp4430_vout_resource[2] = { +}; +#endif + +static struct platform_device sdp4430_vout_device = { + .name = "omap_vout", + .num_resources = ARRAY_SIZE(sdp4430_vout_resource), + .resource = &sdp4430_vout_resource[0], + .id = -1, +}; + +static void omap_init_vout(void) +{ + (void) platform_device_register(&sdp4430_vout_device); +} +#else +static inline void omap_init_vout(void) {} +#endif + /* * This gets called after board-specific INIT_MACHINE, and initializes most * on-chip peripherals accessible on this board (except for few like USB): @@ -414,6 +439,7 @@ static int __init omap_init_devices(void) omap_init_uwire(); omap_init_wdt(); omap_init_rng(); + omap_init_vout(); return 0; } arch_initcall(omap_init_devices); diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index 3746222bed10..1dc34154d794 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c @@ -28,13 +28,13 @@ #include <linux/platform_device.h> #include <linux/bootmem.h> #include <linux/io.h> +#include <linux/omapfb.h> #include <mach/hardware.h> #include <asm/mach/map.h> #include <mach/board.h> #include <mach/sram.h> -#include <mach/omapfb.h> #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) @@ -327,6 +327,34 @@ static inline int omap_init_fb(void) arch_initcall(omap_init_fb); +#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) + +static u64 omap_fb_dma_mask = ~(u32)0; +static struct omapfb_platform_data omapfb_config; + +static struct platform_device omap_fb_device = { + .name = "omapfb", + .id = -1, + .dev = { + .dma_mask = &omap_fb_dma_mask, + .coherent_dma_mask = ~(u32)0, + .platform_data = &omapfb_config, + }, + .num_resources = 0, +}; + +void omapfb_set_platform_data(struct omapfb_platform_data *data) +{ + omapfb_config = *data; +} + +static inline int omap_init_fb(void) +{ + return platform_device_register(&omap_fb_device); +} + +arch_initcall(omap_init_fb); + #else void omapfb_reserve_sdram(void) {} diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 26b387c12423..bec76cf618df 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -115,28 +115,65 @@ #define OMAP24XX_GPIO_REVISION 0x0000 #define OMAP24XX_GPIO_SYSCONFIG 0x0010 -#define OMAP24XX_GPIO_SYSSTATUS 0x0014 -#define OMAP24XX_GPIO_IRQSTATUS1 0x0018 -#define OMAP24XX_GPIO_IRQSTATUS2 0x0028 -#define OMAP24XX_GPIO_IRQENABLE2 0x002c -#define OMAP24XX_GPIO_IRQENABLE1 0x001c -#define OMAP24XX_GPIO_WAKE_EN 0x0020 -#define OMAP24XX_GPIO_CTRL 0x0030 -#define OMAP24XX_GPIO_OE 0x0034 -#define OMAP24XX_GPIO_DATAIN 0x0038 -#define OMAP24XX_GPIO_DATAOUT 0x003c -#define OMAP24XX_GPIO_LEVELDETECT0 0x0040 -#define OMAP24XX_GPIO_LEVELDETECT1 0x0044 -#define OMAP24XX_GPIO_RISINGDETECT 0x0048 -#define OMAP24XX_GPIO_FALLINGDETECT 0x004c -#define OMAP24XX_GPIO_DEBOUNCE_EN 0x0050 -#define OMAP24XX_GPIO_DEBOUNCE_VAL 0x0054 -#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060 -#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064 -#define OMAP24XX_GPIO_CLEARWKUENA 0x0080 -#define OMAP24XX_GPIO_SETWKUENA 0x0084 -#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090 -#define OMAP24XX_GPIO_SETDATAOUT 0x0094 + +#ifdef CONFIG_ARCH_OMAP4 +#define OMAP24XX_GPIO_SYSSTATUS 0x0114 +#define OMAP24XX_GPIO_IRQSTATUS1 0x0118 +#define OMAP24XX_GPIO_IRQSTATUS2 0x0128 +#define OMAP24XX_GPIO_IRQENABLE2 0x012c +#define OMAP24XX_GPIO_IRQENABLE1 0x011c +#define OMAP24XX_GPIO_WAKE_EN 0x0120 +#define OMAP24XX_GPIO_CTRL 0x0130 +#define OMAP24XX_GPIO_OE 0x0134 +#define OMAP24XX_GPIO_DATAIN 0x0138 +#define OMAP24XX_GPIO_DATAOUT 0x013c +#define OMAP24XX_GPIO_LEVELDETECT0 0x0140 +#define OMAP24XX_GPIO_LEVELDETECT1 0x0144 +#define OMAP24XX_GPIO_RISINGDETECT 0x0148 +#define OMAP24XX_GPIO_FALLINGDETECT 0x014c +#define OMAP24XX_GPIO_DEBOUNCE_EN 0x0150 +#define OMAP24XX_GPIO_DEBOUNCE_VAL 0x0154 +#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0160 +#define OMAP24XX_GPIO_SETIRQENABLE1 0x0164 +#define OMAP24XX_GPIO_CLEARWKUENA 0x0180 +#define OMAP24XX_GPIO_SETWKUENA 0x0184 +#define OMAP24XX_GPIO_CLEARDATAOUT 0x0190 +#define OMAP24XX_GPIO_SETDATAOUT 0x0194 +#define OMAP24XX_GPIO_STATUS_RAW_0 0x0024 +#define OMAP24XX_GPIO_STATUS_RAW_1 0x0028 +#define OMAP24XX_GPIO_IRQ_STATUS_0 0x002C +#define OMAP24XX_GPIO_IRQ_STATUS_1 0x0030 +#define OMAP24XX_GPIO_IRQ_STATUS_SET_0 0x0034 +#define OMAP24XX_GPIO_IRQ_STATUS_SET_1 0x0038 +#define OMAP24XX_GPIO_IRQ_STATUS_CLR_0 0x003C +#define OMAP24XX_GPIO_IRQ_STATUS_CLR_1 0x0040 +#define OMAP24XX_GPIO_IRQ_WAKE_ENABLE_0 0x0044 +#define OMAP24XX_GPIO_IRQ_WAKE_ENABLE_1 0x0048 + +#else +#define OMAP24XX_GPIO_SYSSTATUS 0x0014 +#define OMAP24XX_GPIO_IRQSTATUS1 0x0018 +#define OMAP24XX_GPIO_IRQSTATUS2 0x0028 +#define OMAP24XX_GPIO_IRQENABLE2 0x002c +#define OMAP24XX_GPIO_IRQENABLE1 0x001c +#define OMAP24XX_GPIO_WAKE_EN 0x0020 +#define OMAP24XX_GPIO_CTRL 0x0030 +#define OMAP24XX_GPIO_OE 0x0034 +#define OMAP24XX_GPIO_DATAIN 0x0038 +#define OMAP24XX_GPIO_DATAOUT 0x003c +#define OMAP24XX_GPIO_LEVELDETECT0 0x0040 +#define OMAP24XX_GPIO_LEVELDETECT1 0x0044 +#define OMAP24XX_GPIO_RISINGDETECT 0x0048 +#define OMAP24XX_GPIO_FALLINGDETECT 0x004c +#define OMAP24XX_GPIO_DEBOUNCE_EN 0x0050 +#define OMAP24XX_GPIO_DEBOUNCE_VAL 0x0054 +#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060 +#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064 +#define OMAP24XX_GPIO_CLEARWKUENA 0x0080 +#define OMAP24XX_GPIO_SETWKUENA 0x0084 +#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090 +#define OMAP24XX_GPIO_SETDATAOUT 0x0094 +#endif /* * omap34xx specific GPIO registers @@ -784,11 +821,16 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) break; #endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: + #ifdef CONFIG_ARCH_OMAP4 + reg += OMAP24XX_GPIO_IRQ_STATUS_0; + #else reg += OMAP24XX_GPIO_IRQSTATUS1; + #endif break; #endif + default: WARN_ON(1); return; @@ -796,14 +838,20 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) __raw_writel(gpio_mask, reg); /* Workaround for clearing DSP GPIO interrupts to allow retention */ -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ +defined(CONFIG_ARCH_OMAP4) +#ifdef CONFIG_ARCH_OMAP4 + reg = bank->base + OMAP24XX_GPIO_IRQ_STATUS_1; +#else reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) +#endif + if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) __raw_writel(gpio_mask, reg); /* Flush posted write for the irq status to avoid spurious interrupts */ __raw_readl(reg); #endif + } static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) @@ -856,7 +904,11 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: +#ifdef CONFIG_ARCH_OMAP4 + reg += OMAP24XX_GPIO_IRQ_STATUS_SET_0; +#else reg += OMAP24XX_GPIO_IRQENABLE1; +#endif mask = 0xffffffff; break; #endif @@ -1115,7 +1167,11 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ defined(CONFIG_ARCH_OMAP4) if (bank->method == METHOD_GPIO_24XX) + #ifdef CONFIG_ARCH_OMAP4 + isr_reg = bank->base + OMAP24XX_GPIO_IRQ_STATUS_0; + #else isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; + #endif #endif while(1) { u32 isr_saved, level_mask = 0; @@ -1464,14 +1520,21 @@ static int __init _omap_gpio_init(void) #endif #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) + /* + * FIX-ME: Replace with correct clk node when clk + * framework is available + */ if (cpu_is_omap34xx() || cpu_is_omap44xx()) { - for (i = 0; i < OMAP34XX_NR_GPIOS; i++) { - sprintf(clk_name, "gpio%d_ick", i + 1); - gpio_iclks[i] = clk_get(NULL, clk_name); - if (IS_ERR(gpio_iclks[i])) - printk(KERN_ERR "Could not get %s\n", clk_name); - else - clk_enable(gpio_iclks[i]); + if (!cpu_is_omap44xx()) { + for (i = 0; i < OMAP34XX_NR_GPIOS; i++) { + sprintf(clk_name, "gpio%d_ick", i + 1); + gpio_iclks[i] = clk_get(NULL, clk_name); + if (IS_ERR(gpio_iclks[i])) + printk(KERN_ERR "Could not get %s\n", + clk_name); + else + clk_enable(gpio_iclks[i]); + } } } #endif @@ -1581,9 +1644,17 @@ static int __init _omap_gpio_init(void) static const u32 non_wakeup_gpios[] = { 0xe203ffc0, 0x08700040 }; - - __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1); - __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1); +#ifdef CONFIG_ARCH_OMAP4 + __raw_writel(0x00000000, bank->base + + OMAP24XX_GPIO_IRQ_STATUS_CLR_0); + __raw_writel(0xffffffff, bank->base + + OMAP24XX_GPIO_IRQ_STATUS_0); +#else + __raw_writel(0x00000000, bank->base + + OMAP24XX_GPIO_IRQENABLE1); + __raw_writel(0xffffffff, bank->base + + OMAP24XX_GPIO_IRQSTATUS1); +#endif __raw_writew(0x0015, bank->base + OMAP24XX_GPIO_SYSCONFIG); __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_DEBOUNCE_EN); @@ -1633,12 +1704,18 @@ static int __init _omap_gpio_init(void) } set_irq_chained_handler(bank->irq, gpio_irq_handler); set_irq_data(bank->irq, bank); - + /* + * FIX-ME: Replace with correct clk node when clk + * framework is available + */ if (cpu_is_omap34xx() || cpu_is_omap44xx()) { - sprintf(clk_name, "gpio%d_dbck", i + 1); - bank->dbck = clk_get(NULL, clk_name); - if (IS_ERR(bank->dbck)) - printk(KERN_ERR "Could not get %s\n", clk_name); + if (!cpu_is_omap44xx()) { + sprintf(clk_name, "gpio%d_dbck", i + 1); + bank->dbck = clk_get(NULL, clk_name); + if (IS_ERR(bank->dbck)) + printk(KERN_ERR "Could not get %s\n", + clk_name); + } } } diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 8b848391f0c8..778e591f6112 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -53,9 +53,15 @@ static struct resource i2c_resources[][2] = { #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, INT_24XX_I2C2_IRQ) }, #endif +#if defined(CONFIG_ARCH_OMAP4) + { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, INT_44XX_I2C2_IRQ) }, +#endif #if defined(CONFIG_ARCH_OMAP34XX) { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, INT_34XX_I2C3_IRQ) }, #endif +#if defined(CONFIG_ARCH_OMAP4) + { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, INT_44XX_I2C3_IRQ) }, +#endif }; #define I2C_DEV_BUILDER(bus_id, res, data) \ @@ -72,10 +78,11 @@ static struct resource i2c_resources[][2] = { static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_rate[0]), -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ +defined(CONFIG_ARCH_OMAP4) I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_rate[1]), #endif -#if defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4) I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_rate[2]), #endif }; @@ -88,7 +95,7 @@ static const int omap24xx_pins[][2] = { #else static const int omap24xx_pins[][2] = {}; #endif -#if defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4) static const int omap34xx_pins[][2] = { { K21_34XX_I2C1_SCL, J21_34XX_I2C1_SDA}, { AF15_34XX_I2C2_SCL, AE15_34XX_I2C2_SDA}, @@ -110,7 +117,7 @@ static void __init omap_i2c_mux_pins(int bus) } else if (cpu_is_omap24xx()) { scl = omap24xx_pins[bus][0]; sda = omap24xx_pins[bus][1]; - } else if (cpu_is_omap34xx()) { + } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) { scl = omap34xx_pins[bus][0]; sda = omap34xx_pins[bus][1]; } else { @@ -129,7 +136,7 @@ static int __init omap_i2c_nr_ports(void) ports = 1; else if (cpu_is_omap24xx()) ports = 2; - else if (cpu_is_omap34xx()) + else if (cpu_is_omap34xx() || cpu_is_omap44xx()) ports = 3; return ports; @@ -151,6 +158,10 @@ static int __init omap_i2c_add_bus(int bus_id) base = OMAP2_I2C_BASE1; irq = INT_24XX_I2C1_IRQ; } + if (cpu_is_omap44xx()) { + base = OMAP2_I2C_BASE1; + irq = INT_44XX_I2C1_IRQ; + } res[0].start = base; res[0].end = base + OMAP_I2C_SIZE; res[1].start = irq; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index f9f65e1ba3f1..e0cac22fd4cc 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -63,6 +63,10 @@ struct dpll_data { u8 recal_en_bit; u8 recal_st_bit; # endif + +#if defined(CONFIG_ARCH_OMAP4) + struct clk *clk_hsd_bypass; +#endif }; #endif @@ -154,6 +158,7 @@ extern const struct clkops clkops_null; #define RATE_IN_243X (1 << 2) #define RATE_IN_343X (1 << 3) /* rates common to all 343X */ #define RATE_IN_3430ES2 (1 << 4) /* 3430ES2 rates only */ +#define RATE_IN_443X (1 << 5) #define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X) diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h index fdeab421b4dc..878c4f96c2d3 100644 --- a/arch/arm/plat-omap/include/mach/common.h +++ b/arch/arm/plat-omap/include/mach/common.h @@ -55,6 +55,7 @@ struct omap_globals { void __iomem *ctrl; /* System Control Module */ void __iomem *prm; /* Power and Reset Management */ void __iomem *cm; /* Clock Management */ + void __iomem *cm2; }; void omap2_set_globals_242x(void); diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h index 8140dbccb7bc..e97a15c95ea8 100644 --- a/arch/arm/plat-omap/include/mach/control.h +++ b/arch/arm/plat-omap/include/mach/control.h @@ -25,10 +25,13 @@ IO_ADDRESS(OMAP243X_CTRL_BASE + (reg)) #define OMAP343X_CTRL_REGADDR(reg) \ IO_ADDRESS(OMAP343X_CTRL_BASE + (reg)) +#define OMAP44XX_CTRL_REGADDR(reg) \ + IO_ADDRESS(OMAP44XX_CTRL_BASE + (reg)) #else #define OMAP242X_CTRL_REGADDR(reg) IO_ADDRESS(OMAP242X_CTRL_BASE + (reg)) #define OMAP243X_CTRL_REGADDR(reg) IO_ADDRESS(OMAP243X_CTRL_BASE + (reg)) #define OMAP343X_CTRL_REGADDR(reg) IO_ADDRESS(OMAP343X_CTRL_BASE + (reg)) +#define OMAP44XX_CTRL_REGADDR(reg) IO_ADDRESS(OMAP44XX_CTRL_BASE + (reg)) #endif /* __ASSEMBLY__ */ /* diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h new file mode 100644 index 000000000000..70fa053d8fd6 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/display.h @@ -0,0 +1,541 @@ +/* + * linux/include/asm-arm/arch-omap/display.h + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __ASM_ARCH_OMAP_DISPLAY_H +#define __ASM_ARCH_OMAP_DISPLAY_H + +#include <linux/list.h> +#include <linux/kobject.h> +#include <linux/device.h> +#include <asm/atomic.h> + +#define DISPC_IRQ_FRAMEDONE (1 << 0) +#define DISPC_IRQ_VSYNC (1 << 1) +#define DISPC_IRQ_EVSYNC_EVEN (1 << 2) +#define DISPC_IRQ_EVSYNC_ODD (1 << 3) +#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4) +#define DISPC_IRQ_PROG_LINE_NUM (1 << 5) +#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6) +#define DISPC_IRQ_GFX_END_WIN (1 << 7) +#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8) +#define DISPC_IRQ_OCP_ERR (1 << 9) +#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10) +#define DISPC_IRQ_VID1_END_WIN (1 << 11) +#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12) +#define DISPC_IRQ_VID2_END_WIN (1 << 13) +#define DISPC_IRQ_SYNC_LOST (1 << 14) +#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15) +#define DISPC_IRQ_WAKEUP (1 << 16) + +struct omap_dss_device; +struct omap_overlay_manager; + +enum omap_display_type { + OMAP_DISPLAY_TYPE_NONE = 0, + OMAP_DISPLAY_TYPE_DPI = 1 << 0, + OMAP_DISPLAY_TYPE_DBI = 1 << 1, + OMAP_DISPLAY_TYPE_SDI = 1 << 2, + OMAP_DISPLAY_TYPE_DSI = 1 << 3, + OMAP_DISPLAY_TYPE_VENC = 1 << 4, +}; + +enum omap_plane { + OMAP_DSS_GFX = 0, + OMAP_DSS_VIDEO1 = 1, + OMAP_DSS_VIDEO2 = 2 +}; + +enum omap_channel { + OMAP_DSS_CHANNEL_LCD = 0, + OMAP_DSS_CHANNEL_DIGIT = 1, +}; + +enum omap_color_mode { + OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */ + OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */ + OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */ + OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */ + OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */ + OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */ + OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */ + OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */ + OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */ + OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */ + OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */ + OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */ + OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */ + OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */ + + OMAP_DSS_COLOR_GFX_OMAP3 = + OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | + OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 | + OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | + OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | + OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | + OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, + + OMAP_DSS_COLOR_VID_OMAP3 = + OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | + OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | + OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | + OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 | + OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY, +}; + +enum omap_lcd_display_type { + OMAP_DSS_LCD_DISPLAY_STN, + OMAP_DSS_LCD_DISPLAY_TFT, +}; + +enum omap_dss_load_mode { + OMAP_DSS_LOAD_CLUT_AND_FRAME = 0, + OMAP_DSS_LOAD_CLUT_ONLY = 1, + OMAP_DSS_LOAD_FRAME_ONLY = 2, + OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3, +}; + +enum omap_dss_trans_key_type { + OMAP_DSS_COLOR_KEY_GFX_DST = 0, + OMAP_DSS_COLOR_KEY_VID_SRC = 1, +}; + +enum omap_rfbi_te_mode { + OMAP_DSS_RFBI_TE_MODE_1 = 1, + OMAP_DSS_RFBI_TE_MODE_2 = 2, +}; + +enum omap_panel_config { + OMAP_DSS_LCD_IVS = 1<<0, + OMAP_DSS_LCD_IHS = 1<<1, + OMAP_DSS_LCD_IPC = 1<<2, + OMAP_DSS_LCD_IEO = 1<<3, + OMAP_DSS_LCD_RF = 1<<4, + OMAP_DSS_LCD_ONOFF = 1<<5, + + OMAP_DSS_LCD_TFT = 1<<20, +}; + +enum omap_dss_venc_type { + OMAP_DSS_VENC_TYPE_COMPOSITE, + OMAP_DSS_VENC_TYPE_SVIDEO, +}; + +enum omap_display_caps { + OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0, +}; + +enum omap_dss_update_mode { + OMAP_DSS_UPDATE_DISABLED = 0, + OMAP_DSS_UPDATE_AUTO, + OMAP_DSS_UPDATE_MANUAL, +}; + +enum omap_dss_display_state { + OMAP_DSS_DISPLAY_DISABLED = 0, + OMAP_DSS_DISPLAY_ACTIVE, + OMAP_DSS_DISPLAY_SUSPENDED, +}; + +/* XXX perhaps this should be removed */ +enum omap_dss_overlay_managers { + OMAP_DSS_OVL_MGR_LCD, + OMAP_DSS_OVL_MGR_TV, +}; + +enum omap_dss_rotation_type { + OMAP_DSS_ROT_DMA = 0, + OMAP_DSS_ROT_VRFB = 1, +}; + +enum omap_overlay_caps { + OMAP_DSS_OVL_CAP_SCALE = 1 << 0, + OMAP_DSS_OVL_CAP_DISPC = 1 << 1, +}; + +enum omap_overlay_manager_caps { + OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0, +}; + +/* RFBI */ + +struct rfbi_timings { + int cs_on_time; + int cs_off_time; + int we_on_time; + int we_off_time; + int re_on_time; + int re_off_time; + int we_cycle_time; + int re_cycle_time; + int cs_pulse_width; + int access_time; + + int clk_div; + + u32 tim[5]; /* set by rfbi_convert_timings() */ + + int converted; +}; + +void omap_rfbi_write_command(const void *buf, u32 len); +void omap_rfbi_read_data(void *buf, u32 len); +void omap_rfbi_write_data(const void *buf, u32 len); +void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, + u16 x, u16 y, + u16 w, u16 h); +int omap_rfbi_enable_te(bool enable, unsigned line); +int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, + unsigned hs_pulse_time, unsigned vs_pulse_time, + int hs_pol_inv, int vs_pol_inv, int extif_div); + +/* DSI */ +void dsi_bus_lock(void); +void dsi_bus_unlock(void); +int dsi_vc_dcs_write(int channel, u8 *data, int len); +int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len); +int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen); +int dsi_vc_set_max_rx_packet_size(int channel, u16 len); +int dsi_vc_send_null(int channel); + +/* Board specific data */ +struct omap_dss_board_info { + int (*get_last_off_on_transaction_id)(struct device *dev); + int num_devices; + struct omap_dss_device **devices; + struct omap_dss_device *default_device; +}; + +struct omap_video_timings { + /* Unit: pixels */ + u16 x_res; + /* Unit: pixels */ + u16 y_res; + /* Unit: KHz */ + u32 pixel_clock; + /* Unit: pixel clocks */ + u16 hsw; /* Horizontal synchronization pulse width */ + /* Unit: pixel clocks */ + u16 hfp; /* Horizontal front porch */ + /* Unit: pixel clocks */ + u16 hbp; /* Horizontal back porch */ + /* Unit: line clocks */ + u16 vsw; /* Vertical synchronization pulse width */ + /* Unit: line clocks */ + u16 vfp; /* Vertical front porch */ + /* Unit: line clocks */ + u16 vbp; /* Vertical back porch */ +}; + +#ifdef CONFIG_OMAP2_DSS_VENC +/* Hardcoded timings for tv modes. Venc only uses these to + * identify the mode, and does not actually use the configs + * itself. However, the configs should be something that + * a normal monitor can also show */ +const extern struct omap_video_timings omap_dss_pal_timings; +const extern struct omap_video_timings omap_dss_ntsc_timings; +#endif + +struct omap_overlay_info { + bool enabled; + + u32 paddr; + void __iomem *vaddr; + u16 screen_width; + u16 width; + u16 height; + enum omap_color_mode color_mode; + u8 rotation; + enum omap_dss_rotation_type rotation_type; + bool mirror; + + u16 pos_x; + u16 pos_y; + u16 out_width; /* if 0, out_width == width */ + u16 out_height; /* if 0, out_height == height */ + u8 global_alpha; +}; + +struct omap_overlay { + struct kobject kobj; + struct list_head list; + + /* static fields */ + const char *name; + int id; + enum omap_color_mode supported_modes; + enum omap_overlay_caps caps; + + /* dynamic fields */ + struct omap_overlay_manager *manager; + struct omap_overlay_info info; + + /* if true, info has been changed, but not applied() yet */ + bool info_dirty; + + int (*set_manager)(struct omap_overlay *ovl, + struct omap_overlay_manager *mgr); + int (*unset_manager)(struct omap_overlay *ovl); + + int (*set_overlay_info)(struct omap_overlay *ovl, + struct omap_overlay_info *info); + void (*get_overlay_info)(struct omap_overlay *ovl, + struct omap_overlay_info *info); + + int (*wait_for_go)(struct omap_overlay *ovl); +}; + +struct omap_overlay_manager_info { + u32 default_color; + + enum omap_dss_trans_key_type trans_key_type; + u32 trans_key; + bool trans_enabled; + + bool alpha_enabled; +}; + +struct omap_overlay_manager { + struct kobject kobj; + struct list_head list; + + /* static fields */ + const char *name; + int id; + enum omap_overlay_manager_caps caps; + int num_overlays; + struct omap_overlay **overlays; + enum omap_display_type supported_displays; + + /* dynamic fields */ + struct omap_dss_device *device; + struct omap_overlay_manager_info info; + + bool device_changed; + /* if true, info has been changed but not applied() yet */ + bool info_dirty; + + int (*set_device)(struct omap_overlay_manager *mgr, + struct omap_dss_device *dssdev); + int (*unset_device)(struct omap_overlay_manager *mgr); + + int (*set_manager_info)(struct omap_overlay_manager *mgr, + struct omap_overlay_manager_info *info); + void (*get_manager_info)(struct omap_overlay_manager *mgr, + struct omap_overlay_manager_info *info); + + int (*apply)(struct omap_overlay_manager *mgr); + int (*wait_for_go)(struct omap_overlay_manager *mgr); +}; + +struct omap_dss_device { + struct device dev; + + enum omap_display_type type; + + union { + struct { + u8 data_lines; + } dpi; + + struct { + u8 channel; + u8 data_lines; + } rfbi; + + struct { + u8 datapairs; + unsigned pad_off_pe:1; /* pull pads if disabled */ + unsigned pad_off_pu:1; /* pull up */ + } sdi; + + struct { + u8 clk_lane; + u8 clk_pol; + u8 data1_lane; + u8 data1_pol; + u8 data2_lane; + u8 data2_pol; + unsigned long lp_clk_hz; + unsigned long ddr_clk_hz; + + bool ext_te; + u8 ext_te_gpio; + } dsi; + + struct { + enum omap_dss_venc_type type; + } venc; + } phy; + + struct { + struct omap_video_timings timings; + + int acbi; /* ac-bias pin transitions per interrupt */ + /* Unit: line clocks */ + int acb; /* ac-bias pin frequency */ + + enum omap_panel_config config; + + u8 recommended_bpp; + + struct omap_dss_device *ctrl; + } panel; + + struct { + u8 pixel_size; + struct rfbi_timings rfbi_timings; + struct omap_dss_device *panel; + } ctrl; + + int reset_gpio; + + int max_backlight_level; + + const char *name; + + /* used to match device to driver */ + const char *driver_name; + + void *data; + + struct omap_dss_driver *driver; + + /* helper variable for driver suspend/resume */ + bool activate_after_resume; + + enum omap_display_caps caps; + + struct omap_overlay_manager *manager; + + enum omap_dss_display_state state; + + int (*enable)(struct omap_dss_device *dssdev); + void (*disable)(struct omap_dss_device *dssdev); + + int (*suspend)(struct omap_dss_device *dssdev); + int (*resume)(struct omap_dss_device *dssdev); + + void (*get_resolution)(struct omap_dss_device *dssdev, + u16 *xres, u16 *yres); + int (*get_recommended_bpp)(struct omap_dss_device *dssdev); + + int (*check_timings)(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); + void (*set_timings)(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); + void (*get_timings)(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); + int (*update)(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h); + int (*sync)(struct omap_dss_device *dssdev); + int (*wait_vsync)(struct omap_dss_device *dssdev); + + int (*set_update_mode)(struct omap_dss_device *dssdev, + enum omap_dss_update_mode); + enum omap_dss_update_mode (*get_update_mode) + (struct omap_dss_device *dssdev); + + int (*enable_te)(struct omap_dss_device *dssdev, bool enable); + int (*get_te)(struct omap_dss_device *dssdev); + int (*wait_for_te)(struct omap_dss_device *dssdev); + + u8 (*get_rotate)(struct omap_dss_device *dssdev); + int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate); + + bool (*get_mirror)(struct omap_dss_device *dssdev); + int (*set_mirror)(struct omap_dss_device *dssdev, bool enable); + + int (*run_test)(struct omap_dss_device *dssdev, int test); + int (*memory_read)(struct omap_dss_device *dssdev, + void *buf, size_t size, + u16 x, u16 y, u16 w, u16 h); + + int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); + u32 (*get_wss)(struct omap_dss_device *dssdev); + + /* platform specific */ + int (*platform_enable)(struct omap_dss_device *dssdev); + void (*platform_disable)(struct omap_dss_device *dssdev); + int (*set_backlight)(struct omap_dss_device *dssdev, int level); + int (*get_backlight)(struct omap_dss_device *dssdev); +}; + +struct omap_dss_driver { + struct device_driver driver; + + int (*probe)(struct omap_dss_device *); + void (*remove)(struct omap_dss_device *); + + int (*enable)(struct omap_dss_device *display); + void (*disable)(struct omap_dss_device *display); + int (*suspend)(struct omap_dss_device *display); + int (*resume)(struct omap_dss_device *display); + int (*run_test)(struct omap_dss_device *display, int test); + + void (*setup_update)(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h); + + int (*enable_te)(struct omap_dss_device *dssdev, bool enable); + int (*wait_for_te)(struct omap_dss_device *dssdev); + + u8 (*get_rotate)(struct omap_dss_device *dssdev); + int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate); + + bool (*get_mirror)(struct omap_dss_device *dssdev); + int (*set_mirror)(struct omap_dss_device *dssdev, bool enable); + + int (*memory_read)(struct omap_dss_device *dssdev, + void *buf, size_t size, + u16 x, u16 y, u16 w, u16 h); +}; + +int omap_dss_register_driver(struct omap_dss_driver *); +void omap_dss_unregister_driver(struct omap_dss_driver *); + +int omap_dss_register_device(struct omap_dss_device *); +void omap_dss_unregister_device(struct omap_dss_device *); + +void omap_dss_get_device(struct omap_dss_device *dssdev); +void omap_dss_put_device(struct omap_dss_device *dssdev); +#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL) +struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from); +struct omap_dss_device *omap_dss_find_device(void *data, + int (*match)(struct omap_dss_device *dssdev, void *data)); + +int omap_dss_start_device(struct omap_dss_device *dssdev); +void omap_dss_stop_device(struct omap_dss_device *dssdev); + +int omap_dss_get_num_overlay_managers(void); +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); + +typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); +int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); +int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); + +int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout); +int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, + unsigned long timeout); + +#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver) +#define to_dss_device(x) container_of((x), struct omap_dss_device, dev) + +#endif diff --git a/arch/arm/plat-omap/include/mach/dma.h b/arch/arm/plat-omap/include/mach/dma.h index 923cf213f316..866e37eb8474 100755 --- a/arch/arm/plat-omap/include/mach/dma.h +++ b/arch/arm/plat-omap/include/mach/dma.h @@ -335,6 +335,7 @@ #define OMAP44XX_DMA_UART4_DMA_TX 55 /* S_DMA_54 */ #define OMAP44XX_DMA_UART4_DMA_RX 56 /* S_DMA_55 */ #define OMAP44XX_DMA_MMC4_DMA_TX 57 /* S_DMA_56 */ +#define OMAP44XX_DMA_MMC4_DMA_RX 58 /* S_DMA_57 */ #define OMAP44XX_DMA_MMC5_DMA_TX 59 /* S_DMA_58 */ #define OMAP44XX_DMA_MMC5_DMA_RX 60 /* S_DMA_59 */ #define OMAP44XX_DMA_MCPDM_UP 65 /* S_DMA_64 */ diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h index 34b6d09c1413..8725136695c5 100644 --- a/arch/arm/plat-omap/include/mach/irqs.h +++ b/arch/arm/plat-omap/include/mach/irqs.h @@ -503,6 +503,7 @@ #define INT_44XX_FPKA_READY_IRQ (50 + IRQ_GIC_START) #define INT_44XX_SHA1MD51_IRQ (51 + IRQ_GIC_START) #define INT_44XX_RNG_IRQ (52 + IRQ_GIC_START) +#define INT_44XX_MMC5_IRQ (59 + IRQ_GIC_START) #define INT_44XX_I2C3_IRQ (61 + IRQ_GIC_START) #define INT_44XX_FPKA_ERROR_IRQ (64 + IRQ_GIC_START) #define INT_44XX_PBIAS_IRQ (75 + IRQ_GIC_START) @@ -511,6 +512,9 @@ #define INT_44XX_TLL_IRQ (78 + IRQ_GIC_START) #define INT_44XX_PARTHASH_IRQ (79 + IRQ_GIC_START) #define INT_44XX_MMC3_IRQ (94 + IRQ_GIC_START) +#define INT_44XX_MMC4_IRQ (96 + IRQ_GIC_START) +#define INT_44XX_MCPDM_IRQ (112 + IRQ_GIC_START) +#define INT_44XX_SYS_NIRQ2 (119 + IRQ_GIC_START) #define INT_44XX_DUCATI_MMU_IRQ (100 + IRQ_GIC_START) /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730/850) and @@ -551,8 +555,20 @@ #endif #define TWL4030_GPIO_IRQ_END (TWL4030_GPIO_IRQ_BASE + TWL4030_GPIO_NR_IRQS) +#define TWL6030_IRQ_BASE (OMAP_FPGA_IRQ_END) +#ifdef CONFIG_TWL6030_CORE +#define TWL6030_BASE_NR_IRQS 20 +#else +#define TWL6030_BASE_NR_IRQS 0 +#endif +#define TWL6030_IRQ_END (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS) + /* Total number of interrupts depends on the enabled blocks above */ +#ifdef CONFIG_TWL4030_CORE #define NR_IRQS TWL4030_GPIO_IRQ_END +#else +#define NR_IRQS TWL6030_IRQ_END +#endif #define OMAP_IRQ_BIT(irq) (1 << ((irq) % 32)) diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index bb154ea76769..ec6f81e06d39 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -53,6 +53,11 @@ #define OMAP34XX_MCBSP4_BASE 0x49026000 #define OMAP34XX_MCBSP5_BASE 0x48096000 +#define OMAP44XX_MCBSP1_BASE 0x49022000 +#define OMAP44XX_MCBSP2_BASE 0x49024000 +#define OMAP44XX_MCBSP3_BASE 0x49026000 +#define OMAP44XX_MCBSP4_BASE 0x48074000 + #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730) #define OMAP_MCBSP_REG_DRR2 0x00 @@ -98,7 +103,8 @@ #define AUDIO_DMA_TX OMAP_DMA_MCBSP1_TX #define AUDIO_DMA_RX OMAP_DMA_MCBSP1_RX -#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) #define OMAP_MCBSP_REG_DRR2 0x00 #define OMAP_MCBSP_REG_DRR1 0x04 diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 81d5b36534b3..2dfb4734f4b4 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -25,11 +25,19 @@ #define OMAP24XX_NR_MMC 2 #define OMAP34XX_NR_MMC 3 +#define OMAP44XX_NR_MMC 5 #define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE #define HSMMC_SIZE 0x200 #define OMAP2_MMC1_BASE 0x4809c000 #define OMAP2_MMC2_BASE 0x480b4000 #define OMAP3_MMC3_BASE 0x480ad000 +#define OMAP4_MMC1_BASE 0x4809c100 +#define OMAP4_MMC2_BASE 0x480b4100 +#define OMAP4_MMC3_BASE 0x480ad100 +#define OMAP4_MMC4_BASE 0x480d1100 +#define OMAP4_MMC5_BASE 0x480d5100 +#define HSMMC5 (1 << 4) +#define HSMMC4 (1 << 3) #define HSMMC3 (1 << 2) #define HSMMC2 (1 << 1) #define HSMMC1 (1 << 0) diff --git a/arch/arm/plat-omap/include/mach/mux.h b/arch/arm/plat-omap/include/mach/mux.h index 85a621705766..fc82f7b15f6b 100644 --- a/arch/arm/plat-omap/include/mach/mux.h +++ b/arch/arm/plat-omap/include/mach/mux.h @@ -208,7 +208,7 @@ struct pin_config { const unsigned int mux_reg; unsigned char debug; -#if defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4) u16 mux_val; /* Wake-up, off mode, pull, mux mode */ #endif @@ -855,6 +855,89 @@ enum omap34xx_index { J25_34XX_GPIO170, }; +enum omap44xx_index { + + AA3_4430_McSPI1_CLK, + Y2_4430_McSPI1_SIMO, + Y3_4430_McSPI1_SOMI, + Y4_4430_McSPI1_CS0, + Y4_4430_McSPI1_CS1, + Y4_4430_McSPI1_CS2, + Y4_4430_McSPI1_CS3, + + AA3_4430_McBSP1_CLK, + Y2_4430_McBSP1_DX, + Y3_4430_McBSP1_DR, + Y4_4430_McBSP1_FSX, + + PAD0_4430_UNIPRO_TX0, + PAD1_4430_UNIPRO_TY0, + PAD0_4430_UNIPRO_TX1, + PAD1_4430_UNIPRO_TY1, + PAD0_4430_UNIPRO_TX2, + PAD1_4430_UNIPRO_TY2, + PAD0_4430_UNIPRO_RX0, + PAD1_4430_UNIPRO_RY0, + PAD0_4430_UNIPRO_RX1, + PAD1_4430_UNIPRO_RY1, + PAD0_4430_UNIPRO_RX2, + PAD1_4430_UNIPRO_RY2, + + PAD1_4430_SYS_NIRQ1, + PAD0_4430_SYS_NIRQ2, + + A1_4430_MMC1_CLK, + C1_4430_MMC1_CMD, + D0_4430_MMC1_DAT0, + D1_4430_MMC1_DAT1, + D2_4430_MMC1_DAT2, + D3_4430_MMC1_DAT3, + D4_4430_MMC1_DAT4, + D5_4430_MMC1_DAT5, + D6_4430_MMC1_DAT6, + D7_4430_MMC1_DAT7, + + A1_4430_MMC2_CLK, + C1_4430_MMC2_CMD, + D0_4430_MMC2_DAT0, + D1_4430_MMC2_DAT1, + D2_4430_MMC2_DAT2, + D3_4430_MMC2_DAT3, + D4_4430_MMC2_DAT4, + D5_4430_MMC2_DAT5, + D6_4430_MMC2_DAT6, + D7_4430_MMC2_DAT7, + + A1_4430_MMC3_CLK, + C1_4430_MMC3_CMD, + D0_4430_MMC3_DAT0, + D1_4430_MMC3_DAT1, + D2_4430_MMC3_DAT2, + D3_4430_MMC3_DAT3, + + A1_4430_MMC4_CLK, + C1_4430_MMC4_CMD, + D0_4430_MMC4_DAT0, + D1_4430_MMC4_DAT1, + D2_4430_MMC4_DAT2, + D3_4430_MMC4_DAT3, + + A1_4430_MMC5_CLK, + C1_4430_MMC5_CMD, + D0_4430_MMC5_DAT0, + D1_4430_MMC5_DAT1, + D2_4430_MMC5_DAT2, + D3_4430_MMC5_DAT3, + + AG25_4430_ABE_PDM_UL_DATA, + AF25_4430_ABE_PDM_DL_DATA, + AE25_4430_ABE_PDM_FRAME, + AF26_4430_ABE_PDM_LB_CLK, + AH26_4430_ABE_PDM_CLKS, + AA27_4430_GPIO_127, + +}; + struct omap_mux_cfg { struct pin_config *pins; unsigned long size; diff --git a/arch/arm/plat-omap/include/mach/omap44xx.h b/arch/arm/plat-omap/include/mach/omap44xx.h index 6a545d33dee0..1ddffeb1fb98 100644 --- a/arch/arm/plat-omap/include/mach/omap44xx.h +++ b/arch/arm/plat-omap/include/mach/omap44xx.h @@ -25,11 +25,13 @@ #define L3_ABE_44XX_BASE 0x49000000 #define OMAP4430_32KSYNCT_BASE 0x4a304000 -#define OMAP4430_CM_BASE 0x4a004000 -#define OMAP4430_PRM_BASE 0x48306000 +#define OMAP4430_CM1_BASE 0x4A30A000 +#define OMAP4430_CM_BASE OMAP4430_CM1_BASE +#define OMAP4430_CM2_BASE 0x4A008000 +#define OMAP4430_PRM_BASE 0x4A306000 #define OMAP44XX_GPMC_BASE 0x50000000 #define OMAP443X_SCM_BASE 0x4a002000 -#define OMAP443X_CTRL_BASE OMAP443X_SCM_BASE +#define OMAP443X_CTRL_BASE 0x4A100000 #define OMAP44XX_IC_BASE 0x48200000 #define OMAP44XX_IVA_INTC_BASE 0x40000000 #define IRQ_SIR_IRQ 0x0040 diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h deleted file mode 100644 index 7b74d1255e0b..000000000000 --- a/arch/arm/plat-omap/include/mach/omapfb.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - * File: arch/arm/plat-omap/include/mach/omapfb.h - * - * Framebuffer driver for TI OMAP boards - * - * Copyright (C) 2004 Nokia Corporation - * Author: Imre Deak <imre.deak@nokia.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __OMAPFB_H -#define __OMAPFB_H - -#include <asm/ioctl.h> -#include <asm/types.h> - -/* IOCTL commands. */ - -#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) -#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) -#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) -#define OMAP_IO(num) _IO('O', num) - -#define OMAPFB_MIRROR OMAP_IOW(31, int) -#define OMAPFB_SYNC_GFX OMAP_IO(37) -#define OMAPFB_VSYNC OMAP_IO(38) -#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) -#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) -#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) -#define OMAPFB_LCD_TEST OMAP_IOW(45, int) -#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) -#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) -#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) -#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) -#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) -#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) -#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) -#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) -#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) - -#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff -#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 -#define OMAPFB_CAPS_PANEL_MASK 0xff000000 - -#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 -#define OMAPFB_CAPS_TEARSYNC 0x00002000 -#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 -#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 -#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 -#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 -#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 -#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 -#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 - -/* Values from DSP must map to lower 16-bits */ -#define OMAPFB_FORMAT_MASK 0x00ff -#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 -#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 -#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 -#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 -#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 - -#define OMAPFB_EVENT_READY 1 -#define OMAPFB_EVENT_DISABLED 2 - -#define OMAPFB_MEMTYPE_SDRAM 0 -#define OMAPFB_MEMTYPE_SRAM 1 -#define OMAPFB_MEMTYPE_MAX 1 - -enum omapfb_color_format { - OMAPFB_COLOR_RGB565 = 0, - OMAPFB_COLOR_YUV422, - OMAPFB_COLOR_YUV420, - OMAPFB_COLOR_CLUT_8BPP, - OMAPFB_COLOR_CLUT_4BPP, - OMAPFB_COLOR_CLUT_2BPP, - OMAPFB_COLOR_CLUT_1BPP, - OMAPFB_COLOR_RGB444, - OMAPFB_COLOR_YUY422, -}; - -struct omapfb_update_window { - __u32 x, y; - __u32 width, height; - __u32 format; - __u32 out_x, out_y; - __u32 out_width, out_height; - __u32 reserved[8]; -}; - -struct omapfb_update_window_old { - __u32 x, y; - __u32 width, height; - __u32 format; -}; - -enum omapfb_plane { - OMAPFB_PLANE_GFX = 0, - OMAPFB_PLANE_VID1, - OMAPFB_PLANE_VID2, -}; - -enum omapfb_channel_out { - OMAPFB_CHANNEL_OUT_LCD = 0, - OMAPFB_CHANNEL_OUT_DIGIT, -}; - -struct omapfb_plane_info { - __u32 pos_x; - __u32 pos_y; - __u8 enabled; - __u8 channel_out; - __u8 mirror; - __u8 reserved1; - __u32 out_width; - __u32 out_height; - __u32 reserved2[12]; -}; - -struct omapfb_mem_info { - __u32 size; - __u8 type; - __u8 reserved[3]; -}; - -struct omapfb_caps { - __u32 ctrl; - __u32 plane_color; - __u32 wnd_color; -}; - -enum omapfb_color_key_type { - OMAPFB_COLOR_KEY_DISABLED = 0, - OMAPFB_COLOR_KEY_GFX_DST, - OMAPFB_COLOR_KEY_VID_SRC, -}; - -struct omapfb_color_key { - __u8 channel_out; - __u32 background; - __u32 trans_key; - __u8 key_type; -}; - -enum omapfb_update_mode { - OMAPFB_UPDATE_DISABLED = 0, - OMAPFB_AUTO_UPDATE, - OMAPFB_MANUAL_UPDATE -}; - -#ifdef __KERNEL__ - -#include <linux/completion.h> -#include <linux/interrupt.h> -#include <linux/fb.h> -#include <linux/mutex.h> - -#include <mach/board.h> - -#define OMAP_LCDC_INV_VSYNC 0x0001 -#define OMAP_LCDC_INV_HSYNC 0x0002 -#define OMAP_LCDC_INV_PIX_CLOCK 0x0004 -#define OMAP_LCDC_INV_OUTPUT_EN 0x0008 -#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010 -#define OMAP_LCDC_HSVS_OPPOSITE 0x0020 - -#define OMAP_LCDC_SIGNAL_MASK 0x003f - -#define OMAP_LCDC_PANEL_TFT 0x0100 - -#define OMAPFB_PLANE_XRES_MIN 8 -#define OMAPFB_PLANE_YRES_MIN 8 - -#ifdef CONFIG_ARCH_OMAP1 -#define OMAPFB_PLANE_NUM 1 -#else -#define OMAPFB_PLANE_NUM 3 -#endif - -struct omapfb_device; - -struct lcd_panel { - const char *name; - int config; /* TFT/STN, signal inversion */ - int bpp; /* Pixel format in fb mem */ - int data_lines; /* Lines on LCD HW interface */ - - int x_res, y_res; - int pixel_clock; /* In kHz */ - int hsw; /* Horizontal synchronization - pulse width */ - int hfp; /* Horizontal front porch */ - int hbp; /* Horizontal back porch */ - int vsw; /* Vertical synchronization - pulse width */ - int vfp; /* Vertical front porch */ - int vbp; /* Vertical back porch */ - int acb; /* ac-bias pin frequency */ - int pcd; /* pixel clock divider. - Obsolete use pixel_clock instead */ - - int (*init) (struct lcd_panel *panel, - struct omapfb_device *fbdev); - void (*cleanup) (struct lcd_panel *panel); - int (*enable) (struct lcd_panel *panel); - void (*disable) (struct lcd_panel *panel); - unsigned long (*get_caps) (struct lcd_panel *panel); - int (*set_bklight_level)(struct lcd_panel *panel, - unsigned int level); - unsigned int (*get_bklight_level)(struct lcd_panel *panel); - unsigned int (*get_bklight_max) (struct lcd_panel *panel); - int (*run_test) (struct lcd_panel *panel, int test_num); -}; - -struct extif_timings { - int cs_on_time; - int cs_off_time; - int we_on_time; - int we_off_time; - int re_on_time; - int re_off_time; - int we_cycle_time; - int re_cycle_time; - int cs_pulse_width; - int access_time; - - int clk_div; - - u32 tim[5]; /* set by extif->convert_timings */ - - int converted; -}; - -struct lcd_ctrl_extif { - int (*init) (struct omapfb_device *fbdev); - void (*cleanup) (void); - void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div); - unsigned long (*get_max_tx_rate)(void); - int (*convert_timings) (struct extif_timings *timings); - void (*set_timings) (const struct extif_timings *timings); - void (*set_bits_per_cycle)(int bpc); - void (*write_command) (const void *buf, unsigned int len); - void (*read_data) (void *buf, unsigned int len); - void (*write_data) (const void *buf, unsigned int len); - void (*transfer_area) (int width, int height, - void (callback)(void * data), void *data); - int (*setup_tearsync) (unsigned pin_cnt, - unsigned hs_pulse_time, unsigned vs_pulse_time, - int hs_pol_inv, int vs_pol_inv, int div); - int (*enable_tearsync) (int enable, unsigned line); - - unsigned long max_transmit_size; -}; - -struct omapfb_notifier_block { - struct notifier_block nb; - void *data; - int plane_idx; -}; - -typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, - unsigned long event, - void *fbi); - -struct omapfb_mem_region { - dma_addr_t paddr; - void *vaddr; - unsigned long size; - u8 type; /* OMAPFB_PLANE_MEM_* */ - unsigned alloc:1; /* allocated by the driver */ - unsigned map:1; /* kernel mapped by the driver */ -}; - -struct omapfb_mem_desc { - int region_cnt; - struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; -}; - -struct lcd_ctrl { - const char *name; - void *data; - - int (*init) (struct omapfb_device *fbdev, - int ext_mode, - struct omapfb_mem_desc *req_md); - void (*cleanup) (void); - void (*bind_client) (struct omapfb_notifier_block *nb); - void (*get_caps) (int plane, struct omapfb_caps *caps); - int (*set_update_mode)(enum omapfb_update_mode mode); - enum omapfb_update_mode (*get_update_mode)(void); - int (*setup_plane) (int plane, int channel_out, - unsigned long offset, - int screen_width, - int pos_x, int pos_y, int width, - int height, int color_mode); - int (*set_rotate) (int angle); - int (*setup_mem) (int plane, size_t size, - int mem_type, unsigned long *paddr); - int (*mmap) (struct fb_info *info, - struct vm_area_struct *vma); - int (*set_scale) (int plane, - int orig_width, int orig_height, - int out_width, int out_height); - int (*enable_plane) (int plane, int enable); - int (*update_window) (struct fb_info *fbi, - struct omapfb_update_window *win, - void (*callback)(void *), - void *callback_data); - void (*sync) (void); - void (*suspend) (void); - void (*resume) (void); - int (*run_test) (int test_num); - int (*setcolreg) (u_int regno, u16 red, u16 green, - u16 blue, u16 transp, - int update_hw_mem); - int (*set_color_key) (struct omapfb_color_key *ck); - int (*get_color_key) (struct omapfb_color_key *ck); -}; - -enum omapfb_state { - OMAPFB_DISABLED = 0, - OMAPFB_SUSPENDED= 99, - OMAPFB_ACTIVE = 100 -}; - -struct omapfb_plane_struct { - int idx; - struct omapfb_plane_info info; - enum omapfb_color_format color_mode; - struct omapfb_device *fbdev; -}; - -struct omapfb_device { - int state; - int ext_lcdc; /* Using external - LCD controller */ - struct mutex rqueue_mutex; - - int palette_size; - u32 pseudo_palette[17]; - - struct lcd_panel *panel; /* LCD panel */ - const struct lcd_ctrl *ctrl; /* LCD controller */ - const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ - struct lcd_ctrl_extif *ext_if; /* LCD ctrl external - interface */ - struct device *dev; - struct fb_var_screeninfo new_var; /* for mode changes */ - - struct omapfb_mem_desc mem_desc; - struct fb_info *fb_info[OMAPFB_PLANE_NUM]; -}; - -struct omapfb_platform_data { - struct omap_lcd_config lcd; - struct omapfb_mem_desc mem_desc; - void *ctrl_platform_data; -}; - -#ifdef CONFIG_ARCH_OMAP1 -extern struct lcd_ctrl omap1_lcd_ctrl; -#else -extern struct lcd_ctrl omap2_disp_ctrl; -#endif - -extern void omapfb_reserve_sdram(void); -extern void omapfb_register_panel(struct lcd_panel *panel); -extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); -extern void omapfb_notify_clients(struct omapfb_device *fbdev, - unsigned long event); -extern int omapfb_register_client(struct omapfb_notifier_block *nb, - omapfb_notifier_callback_t callback, - void *callback_data); -extern int omapfb_unregister_client(struct omapfb_notifier_block *nb); -extern int omapfb_update_window_async(struct fb_info *fbi, - struct omapfb_update_window *win, - void (*callback)(void *), - void *callback_data); - -/* in arch/arm/plat-omap/fb.c */ -extern void omapfb_set_ctrl_platform_data(void *pdata); - -#endif /* __KERNEL__ */ - -#endif /* __OMAPFB_H */ diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h new file mode 100644 index 000000000000..8639e08c5efa --- /dev/null +++ b/arch/arm/plat-omap/include/mach/vram.h @@ -0,0 +1,34 @@ +/* + * File: arch/arm/plat-omap/include/mach/vram.h + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __OMAPVRAM_H +#define __OMAPVRAM_H + +#include <asm/types.h> + +extern int omap_vram_add_region(unsigned long paddr, size_t size); +extern int omap_vram_free(unsigned long paddr, size_t size); +extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr); +extern int omap_vram_reserve(unsigned long paddr, size_t size); +extern void omap2_set_sdram_vram(u32 size, u32 start); +extern void omap2_set_sram_vram(u32 size, u32 start); + +#endif diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h new file mode 100644 index 000000000000..9647d82c1cdd --- /dev/null +++ b/arch/arm/plat-omap/include/mach/vrfb.h @@ -0,0 +1,51 @@ +/* + * File: arch/arm/plat-omap/include/mach/vrfb.h + * + * VRFB + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __VRFB_H +#define __VRFB_H + +#include <mach/display.h> +#define OMAP_VRFB_LINE_LEN 2048 + +struct vrfb +{ + u8 context; + void __iomem *vaddr[4]; + unsigned long paddr[4]; + u16 xoffset; + u16 yoffset; + u8 bytespp; +}; + +extern int omap_vrfb_request_ctx(struct vrfb *vrfb); +extern void omap_vrfb_release_ctx(struct vrfb *vrfb); +extern void omap_vrfb_suspend_ctx(struct vrfb *vrfb); +extern void omap_vrfb_resume_ctx(struct vrfb *vrfb); +extern void omap_vrfb_adjust_size(u16 *width, u16 *height, + u8 bytespp); +extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, + u16 width, u16 height, + enum omap_color_mode color_mode); +extern void omap_vrfb_restore_context(void); + +#endif /* __VRFB_H */ diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index efa0e0111f38..39e594f05dfe 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -934,21 +934,25 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) mcbsp->rx_irq = pdata->rx_irq; mcbsp->dma_rx_sync = pdata->dma_rx_sync; mcbsp->dma_tx_sync = pdata->dma_tx_sync; + /* + * FIX-ME: Replace with correct clk node when clk + * framework is available + */ + if (!cpu_is_omap44xx()) { + mcbsp->iclk = clk_get(&pdev->dev, "ick"); + if (IS_ERR(mcbsp->iclk)) { + ret = PTR_ERR(mcbsp->iclk); + dev_err(&pdev->dev, "unable to get ick: %d\n", ret); + goto err_iclk; + } - mcbsp->iclk = clk_get(&pdev->dev, "ick"); - if (IS_ERR(mcbsp->iclk)) { - ret = PTR_ERR(mcbsp->iclk); - dev_err(&pdev->dev, "unable to get ick: %d\n", ret); - goto err_iclk; - } - - mcbsp->fclk = clk_get(&pdev->dev, "fck"); - if (IS_ERR(mcbsp->fclk)) { - ret = PTR_ERR(mcbsp->fclk); - dev_err(&pdev->dev, "unable to get fck: %d\n", ret); - goto err_fclk; + mcbsp->fclk = clk_get(&pdev->dev, "fck"); + if (IS_ERR(mcbsp->fclk)) { + ret = PTR_ERR(mcbsp->fclk); + dev_err(&pdev->dev, "unable to get fck: %d\n", ret); + goto err_fclk; + } } - mcbsp->pdata = pdata; mcbsp->dev = &pdev->dev; mcbsp_ptr[id] = mcbsp; diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c index 8d329fb20740..80b040fd5ca7 100644 --- a/arch/arm/plat-omap/mux.c +++ b/arch/arm/plat-omap/mux.c @@ -54,9 +54,6 @@ int __init_or_module omap_cfg_reg(const unsigned long index) { struct pin_config *reg; - if (cpu_is_omap44xx()) - return 0; - if (mux_cfg == NULL) { printk(KERN_ERR "Pin mux table not initialized\n"); return -ENODEV; diff --git a/arch/arm/plat-omap/vram.c b/arch/arm/plat-omap/vram.c new file mode 100644 index 000000000000..93be46a9f3fd --- /dev/null +++ b/arch/arm/plat-omap/vram.c @@ -0,0 +1,632 @@ +/* + * linux/arch/arm/plat-omap/vram.c + * + * Copyright (C) 2008 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 DEBUG*/ + +#include <linux/vmalloc.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/list.h> +#include <linux/dma-mapping.h> +#include <linux/seq_file.h> +#include <linux/bootmem.h> +#include <linux/omapfb.h> +#include <linux/completion.h> +#include <linux/debugfs.h> + +#include <asm/setup.h> + +#include <mach/sram.h> +#include <mach/vram.h> +#include <mach/dma.h> + +#ifdef DEBUG +#define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +#define OMAP2_SRAM_START 0x40200000 +/* Maximum size, in reality this is smaller if SRAM is partially locked. */ +#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */ + +#define REG_MAP_SIZE(_page_cnt) \ + ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8) +#define REG_MAP_PTR(_rg, _page_nr) \ + (((_rg)->map) + (_page_nr) / (sizeof(unsigned long) * 8)) +#define REG_MAP_MASK(_page_nr) \ + (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1))) + +/* #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) */ + +/* postponed regions are used to temporarily store region information at boot + * time when we cannot yet allocate the region list */ +#define MAX_POSTPONED_REGIONS 10 + +static bool vram_initialized; +static int postponed_cnt; +static struct { + unsigned long paddr; + size_t size; +} postponed_regions[MAX_POSTPONED_REGIONS]; + +struct vram_alloc { + struct list_head list; + unsigned long paddr; + unsigned pages; +}; + +struct vram_region { + struct list_head list; + struct list_head alloc_list; + unsigned long paddr; + unsigned pages; +}; + +static DEFINE_MUTEX(region_mutex); +static LIST_HEAD(region_list); + +static inline int region_mem_type(unsigned long paddr) +{ + if (paddr >= OMAP2_SRAM_START && + paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE) + return OMAPFB_MEMTYPE_SRAM; + else + return OMAPFB_MEMTYPE_SDRAM; +} + +static struct vram_region *omap_vram_create_region(unsigned long paddr, + unsigned pages) +{ + struct vram_region *rm; + + rm = kzalloc(sizeof(*rm), GFP_KERNEL); + + if (rm) { + INIT_LIST_HEAD(&rm->alloc_list); + rm->paddr = paddr; + rm->pages = pages; + } + + return rm; +} + +#if 0 +static void omap_vram_free_region(struct vram_region *vr) +{ + list_del(&vr->list); + kfree(vr); +} +#endif + +static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr, + unsigned long paddr, unsigned pages) +{ + struct vram_alloc *va; + struct vram_alloc *new; + + new = kzalloc(sizeof(*va), GFP_KERNEL); + + if (!new) + return NULL; + + new->paddr = paddr; + new->pages = pages; + + list_for_each_entry(va, &vr->alloc_list, list) { + if (va->paddr > new->paddr) + break; + } + + list_add_tail(&new->list, &va->list); + + return new; +} + +static void omap_vram_free_allocation(struct vram_alloc *va) +{ + list_del(&va->list); + kfree(va); +} + +int omap_vram_add_region(unsigned long paddr, size_t size) +{ + struct vram_region *rm; + unsigned pages; + + if (vram_initialized) { + DBG("adding region paddr %08lx size %d\n", + paddr, size); + + size &= PAGE_MASK; + pages = size >> PAGE_SHIFT; + + rm = omap_vram_create_region(paddr, pages); + if (rm == NULL) + return -ENOMEM; + + list_add(&rm->list, ®ion_list); + } else { + if (postponed_cnt == MAX_POSTPONED_REGIONS) + return -ENOMEM; + + postponed_regions[postponed_cnt].paddr = paddr; + postponed_regions[postponed_cnt].size = size; + + ++postponed_cnt; + } + return 0; +} + +int omap_vram_free(unsigned long paddr, size_t size) +{ + struct vram_region *rm; + struct vram_alloc *alloc; + unsigned start, end; + + DBG("free mem paddr %08lx size %d\n", paddr, size); + + size = PAGE_ALIGN(size); + + mutex_lock(®ion_mutex); + + list_for_each_entry(rm, ®ion_list, list) { + list_for_each_entry(alloc, &rm->alloc_list, list) { + start = alloc->paddr; + end = alloc->paddr + (alloc->pages >> PAGE_SHIFT); + + if (start >= paddr && end < paddr + size) + goto found; + } + } + + mutex_unlock(®ion_mutex); + return -EINVAL; + +found: + omap_vram_free_allocation(alloc); + + mutex_unlock(®ion_mutex); + return 0; +} +EXPORT_SYMBOL(omap_vram_free); + +static int _omap_vram_reserve(unsigned long paddr, unsigned pages) +{ + struct vram_region *rm; + struct vram_alloc *alloc; + size_t size; + + size = pages << PAGE_SHIFT; + + list_for_each_entry(rm, ®ion_list, list) { + unsigned long start, end; + + DBG("checking region %lx %d\n", rm->paddr, rm->pages); + + if (region_mem_type(rm->paddr) != region_mem_type(paddr)) + continue; + + start = rm->paddr; + end = start + (rm->pages << PAGE_SHIFT) - 1; + if (start > paddr || end < paddr + size - 1) + continue; + + DBG("block ok, checking allocs\n"); + + list_for_each_entry(alloc, &rm->alloc_list, list) { + end = alloc->paddr - 1; + + if (start <= paddr && end >= paddr + size - 1) + goto found; + + start = alloc->paddr + (alloc->pages << PAGE_SHIFT); + } + + end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1; + + if (!(start <= paddr && end >= paddr + size - 1)) + continue; +found: + DBG("FOUND area start %lx, end %lx\n", start, end); + + if (omap_vram_create_allocation(rm, paddr, pages) == NULL) + return -ENOMEM; + + return 0; + } + + return -ENOMEM; +} + +int omap_vram_reserve(unsigned long paddr, size_t size) +{ + unsigned pages; + int r; + + DBG("reserve mem paddr %08lx size %d\n", paddr, size); + + size = PAGE_ALIGN(size); + pages = size >> PAGE_SHIFT; + + mutex_lock(®ion_mutex); + + r = _omap_vram_reserve(paddr, pages); + + mutex_unlock(®ion_mutex); + + return r; +} +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(int mtype, unsigned pages, unsigned long *paddr) +{ + struct vram_region *rm; + struct vram_alloc *alloc; + + list_for_each_entry(rm, ®ion_list, list) { + unsigned long start, end; + + DBG("checking region %lx %d\n", rm->paddr, rm->pages); + + if (region_mem_type(rm->paddr) != mtype) + continue; + + start = rm->paddr; + + list_for_each_entry(alloc, &rm->alloc_list, list) { + end = alloc->paddr; + + if (end - start >= pages << PAGE_SHIFT) + goto found; + + start = alloc->paddr + (alloc->pages << PAGE_SHIFT); + } + + end = rm->paddr + (rm->pages << PAGE_SHIFT); +found: + if (end - start < pages << PAGE_SHIFT) + continue; + + DBG("FOUND %lx, end %lx\n", start, end); + + alloc = omap_vram_create_allocation(rm, start, pages); + if (alloc == NULL) + return -ENOMEM; + + *paddr = start; + + _omap_vram_clear(start, pages); + + return 0; + } + + return -ENOMEM; +} + +int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr) +{ + unsigned pages; + int r; + + BUG_ON(mtype > OMAPFB_MEMTYPE_MAX || !size); + + DBG("alloc mem type %d size %d\n", mtype, size); + + size = PAGE_ALIGN(size); + pages = size >> PAGE_SHIFT; + + mutex_lock(®ion_mutex); + + r = _omap_vram_alloc(mtype, pages, paddr); + + mutex_unlock(®ion_mutex); + + return r; +} +EXPORT_SYMBOL(omap_vram_alloc); + +#if defined(CONFIG_DEBUG_FS) +static int vram_debug_show(struct seq_file *s, void *unused) +{ + struct vram_region *vr; + struct vram_alloc *va; + unsigned size; + + mutex_lock(®ion_mutex); + + list_for_each_entry(vr, ®ion_list, list) { + size = vr->pages << PAGE_SHIFT; + seq_printf(s, "%08lx-%08lx (%d bytes)\n", + vr->paddr, vr->paddr + size - 1, + size); + + list_for_each_entry(va, &vr->alloc_list, list) { + size = va->pages << PAGE_SHIFT; + seq_printf(s, " %08lx-%08lx (%d bytes)\n", + va->paddr, va->paddr + size - 1, + size); + } + } + + mutex_unlock(®ion_mutex); + + return 0; +} + +static int vram_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, vram_debug_show, inode->i_private); +} + +static const struct file_operations vram_debug_fops = { + .open = vram_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init omap_vram_create_debugfs(void) +{ + struct dentry *d; + + d = debugfs_create_file("vram", S_IRUGO, NULL, + NULL, &vram_debug_fops); + if (IS_ERR(d)) + return PTR_ERR(d); + + return 0; +} +#endif + +static __init int omap_vram_init(void) +{ + int i; + + vram_initialized = 1; + + for (i = 0; i < postponed_cnt; i++) + omap_vram_add_region(postponed_regions[i].paddr, + postponed_regions[i].size); + +#ifdef CONFIG_DEBUG_FS + if (omap_vram_create_debugfs()) + pr_err("VRAM: Failed to create debugfs file\n"); +#endif + + return 0; +} + +arch_initcall(omap_vram_init); + +/* boottime vram alloc stuff */ + +/* set from board file */ +static u32 omapfb_sram_vram_start __initdata; +static u32 omapfb_sram_vram_size __initdata; + +/* set from board file */ +static u32 omapfb_sdram_vram_start __initdata; +static u32 omapfb_sdram_vram_size __initdata; + +/* set from kernel cmdline */ +static u32 omapfb_def_sdram_vram_size __initdata; +static u32 omapfb_def_sdram_vram_start __initdata; + +static void __init omapfb_early_vram(char **p) +{ + omapfb_def_sdram_vram_size = memparse(*p, p); + if (**p == ',') + omapfb_def_sdram_vram_start = simple_strtoul((*p) + 1, p, 16); +} +__early_param("vram=", omapfb_early_vram); + +/* + * Called from map_io. We need to call to this early enough so that we + * can reserve the fixed SDRAM regions before VM could get hold of them. + */ +void __init omapfb_reserve_sdram(void) +{ + struct bootmem_data *bdata; + unsigned long sdram_start, sdram_size; + u32 paddr; + u32 size = 0; + + /* cmdline arg overrides the board file definition */ + if (omapfb_def_sdram_vram_size) { + size = omapfb_def_sdram_vram_size; + paddr = omapfb_def_sdram_vram_start; + } + + if (!size) { + size = omapfb_sdram_vram_size; + paddr = omapfb_sdram_vram_start; + } + +#ifdef CONFIG_OMAP2_DSS_VRAM_SIZE + if (!size) { + size = CONFIG_OMAP2_DSS_VRAM_SIZE * 1024 * 1024; + paddr = 0; + } +#endif + + if (!size) + return; + + size = PAGE_ALIGN(size); + + bdata = NODE_DATA(0)->bdata; + sdram_start = bdata->node_min_pfn << PAGE_SHIFT; + sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; + + if (paddr) { + if ((paddr & ~PAGE_MASK) || paddr < sdram_start || + paddr + size > sdram_start + sdram_size) { + printk(KERN_ERR "Illegal SDRAM region for VRAM\n"); + return; + } + + if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) { + pr_err("FB: failed to reserve VRAM\n"); + return; + } + } else { + if (size > sdram_size) { + printk(KERN_ERR "Illegal SDRAM size for VRAM\n"); + return; + } + + paddr = virt_to_phys(alloc_bootmem_pages(size)); + BUG_ON(paddr & ~PAGE_MASK); + } + + omap_vram_add_region(paddr, size); + + pr_info("Reserving %u bytes SDRAM for VRAM\n", size); +} + +/* + * Called at sram init time, before anything is pushed to the SRAM stack. + * Because of the stack scheme, we will allocate everything from the + * start of the lowest address region to the end of SRAM. This will also + * include padding for page alignment and possible holes between regions. + * + * As opposed to the SDRAM case, we'll also do any dynamic allocations at + * this point, since the driver built as a module would have problem with + * freeing / reallocating the regions. + */ +unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart, + unsigned long sram_vstart, + unsigned long sram_size, + unsigned long pstart_avail, + unsigned long size_avail) +{ + unsigned long pend_avail; + unsigned long reserved; + u32 paddr; + u32 size; + + paddr = omapfb_sram_vram_start; + size = omapfb_sram_vram_size; + + if (!size) + return 0; + + reserved = 0; + pend_avail = pstart_avail + size_avail; + + if (!paddr) { + /* Dynamic allocation */ + if ((size_avail & PAGE_MASK) < size) { + printk(KERN_ERR "Not enough SRAM for VRAM\n"); + return 0; + } + size_avail = (size_avail - size) & PAGE_MASK; + paddr = pstart_avail + size_avail; + } + + if (paddr < sram_pstart || + paddr + size > sram_pstart + sram_size) { + printk(KERN_ERR "Illegal SRAM region for VRAM\n"); + return 0; + } + + /* Reserve everything above the start of the region. */ + if (pend_avail - paddr > reserved) + reserved = pend_avail - paddr; + size_avail = pend_avail - reserved - pstart_avail; + + omap_vram_add_region(paddr, size); + + if (reserved) + pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved); + + return reserved; +} + +void __init omap2_set_sdram_vram(u32 size, u32 start) +{ + omapfb_sdram_vram_start = start; + omapfb_sdram_vram_size = size; +} + +void __init omap2_set_sram_vram(u32 size, u32 start) +{ + omapfb_sram_vram_start = start; + omapfb_sram_vram_size = size; +} + +/* #endif */ + diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c new file mode 100644 index 000000000000..201640ad1301 --- /dev/null +++ b/arch/arm/plat-omap/vrfb.c @@ -0,0 +1,282 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/bitops.h> +#include <linux/mutex.h> + +#include <mach/io.h> +#include <mach/vrfb.h> +/*#define DEBUG*/ + +#ifdef DEBUG +#define DBG(format, ...) printk(KERN_DEBUG "VRFB: " format, ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +#define SMS_ROT_VIRT_BASE(context, rot) \ + (((context >= 4) ? 0xD0000000 : 0x70000000) \ + + (0x4000000 * (context)) \ + + (0x1000000 * (rot))) + +#define OMAP_VRFB_SIZE (2048 * 2048 * 4) + +#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */ +#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */ +#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP) +#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP) +#define SMS_IMAGEHEIGHT_OFFSET 16 +#define SMS_IMAGEWIDTH_OFFSET 0 +#define SMS_PH_OFFSET 8 +#define SMS_PW_OFFSET 4 +#define SMS_PS_OFFSET 0 + +#define OMAP_SMS_BASE 0x6C000000 +#define SMS_ROT_CONTROL(context) (OMAP_SMS_BASE + 0x180 + 0x10 * context) +#define SMS_ROT_SIZE(context) (OMAP_SMS_BASE + 0x184 + 0x10 * context) +#define SMS_ROT_PHYSICAL_BA(context) (OMAP_SMS_BASE + 0x188 + 0x10 * context) + +#define VRFB_NUM_CTXS 12 +/* bitmap of reserved contexts */ +static unsigned long ctx_map; +/* bitmap of contexts for which we have to keep the HW context valid */ +static unsigned long ctx_map_active; + +static DEFINE_MUTEX(ctx_lock); + +/* + * Access to this happens from client drivers or the PM core after wake-up. + * For the first case we require locking at the driver level, for the second + * we don't need locking, since no drivers will run until after the wake-up + * has finished. + */ +static struct { + u32 physical_ba; + u32 control; + u32 size; +} vrfb_hw_context[VRFB_NUM_CTXS]; + +static inline void restore_hw_context(int ctx) +{ + omap_writel(vrfb_hw_context[ctx].control, SMS_ROT_CONTROL(ctx)); + omap_writel(vrfb_hw_context[ctx].size, SMS_ROT_SIZE(ctx)); + omap_writel(vrfb_hw_context[ctx].physical_ba, SMS_ROT_PHYSICAL_BA(ctx)); +} + +void omap_vrfb_restore_context(void) +{ + int i; + unsigned long map = ctx_map_active; + + for (i = ffs(map); i; i = ffs(map)) { + /* i=1..32 */ + i--; + map &= ~(1 << i); + restore_hw_context(i); + } +} + +void omap_vrfb_adjust_size(u16 *width, u16 *height, + u8 bytespp) +{ + *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp; + *height = ALIGN(*height, VRFB_PAGE_HEIGHT); +} +EXPORT_SYMBOL(omap_vrfb_adjust_size); + +void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, + u16 width, u16 height, + enum omap_color_mode color_mode) +{ + unsigned pixel_size_exp; + u16 vrfb_width; + u16 vrfb_height; + u8 ctx = vrfb->context; + u8 bytespp; + u32 size; + u32 control; + + DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr, + width, height, color_mode); + + switch (color_mode) { + case OMAP_DSS_COLOR_RGB16: + case OMAP_DSS_COLOR_ARGB16: + bytespp = 2; + break; + + case OMAP_DSS_COLOR_RGB24P: + bytespp = 3; + break; + + case OMAP_DSS_COLOR_RGB24U: + case OMAP_DSS_COLOR_ARGB32: + case OMAP_DSS_COLOR_RGBA32: + case OMAP_DSS_COLOR_RGBX32: + case OMAP_DSS_COLOR_YUV2: + case OMAP_DSS_COLOR_UYVY: + bytespp = 4; + break; + + default: + BUG(); + } + + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + width >>= 1; + + if (bytespp == 4) + pixel_size_exp = 2; + else if (bytespp == 2) + pixel_size_exp = 1; + else + BUG(); + + vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp; + vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT); + + DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp); + + size = vrfb_width << SMS_IMAGEWIDTH_OFFSET; + size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET; + + control = pixel_size_exp << SMS_PS_OFFSET; + control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET; + control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET; + + vrfb_hw_context[ctx].physical_ba = paddr; + vrfb_hw_context[ctx].size = size; + vrfb_hw_context[ctx].control = control; + + omap_writel(paddr, SMS_ROT_PHYSICAL_BA(ctx)); + omap_writel(size, SMS_ROT_SIZE(ctx)); + omap_writel(control, SMS_ROT_CONTROL(ctx)); + + DBG("vrfb offset pixels %d, %d\n", + vrfb_width - width, vrfb_height - height); + + vrfb->xoffset = vrfb_width - width; + vrfb->yoffset = vrfb_height - height; + vrfb->bytespp = bytespp; +} +EXPORT_SYMBOL(omap_vrfb_setup); + +void omap_vrfb_release_ctx(struct vrfb *vrfb) +{ + int rot; + int ctx = vrfb->context; + + if (ctx == 0xff) + return; + + DBG("release ctx %d\n", ctx); + + mutex_lock(&ctx_lock); + + BUG_ON(!(ctx_map & (1 << ctx))); + + clear_bit(ctx, &ctx_map_active); + clear_bit(ctx, &ctx_map); + + for (rot = 0; rot < 4; ++rot) { + if (vrfb->paddr[rot]) { + release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE); + vrfb->paddr[rot] = 0; + } + } + + vrfb->context = 0xff; + + mutex_unlock(&ctx_lock); +} +EXPORT_SYMBOL(omap_vrfb_release_ctx); + +int omap_vrfb_request_ctx(struct vrfb *vrfb) +{ + int rot; + u32 paddr; + u8 ctx; + int r; + + DBG("request ctx\n"); + + mutex_lock(&ctx_lock); + + for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx) + if ((ctx_map & (1 << ctx)) == 0) + break; + + if (ctx == VRFB_NUM_CTXS) { + printk(KERN_ERR "vrfb: no free contexts\n"); + r = -EBUSY; + goto out; + } + + DBG("found free ctx %d\n", ctx); + + set_bit(ctx, &ctx_map); + WARN_ON(ctx_map_active & (1 << ctx)); + set_bit(ctx, &ctx_map_active); + + memset(vrfb, 0, sizeof(*vrfb)); + + vrfb->context = ctx; + + for (rot = 0; rot < 4; ++rot) { + paddr = SMS_ROT_VIRT_BASE(ctx, rot); + if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) { + printk(KERN_ERR "vrfb: failed to reserve VRFB " + "area for ctx %d, rotation %d\n", + ctx, rot * 90); + omap_vrfb_release_ctx(vrfb); + r = -ENOMEM; + goto out; + } + + vrfb->paddr[rot] = paddr; + + DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]); + } + + r = 0; +out: + mutex_unlock(&ctx_lock); + return r; +} +EXPORT_SYMBOL(omap_vrfb_request_ctx); + +void omap_vrfb_suspend_ctx(struct vrfb *vrfb) +{ + DBG("suspend ctx %d\n", vrfb->context); + mutex_lock(&ctx_lock); + + BUG_ON(vrfb->context >= VRFB_NUM_CTXS); + BUG_ON(!((1 << vrfb->context) & ctx_map_active)); + + clear_bit(vrfb->context, &ctx_map_active); + mutex_unlock(&ctx_lock); +} +EXPORT_SYMBOL(omap_vrfb_suspend_ctx); + +void omap_vrfb_resume_ctx(struct vrfb *vrfb) +{ + DBG("resume ctx %d\n", vrfb->context); + mutex_lock(&ctx_lock); + + BUG_ON(vrfb->context >= VRFB_NUM_CTXS); + BUG_ON((1 << vrfb->context) & ctx_map_active); + + /* + * omap_vrfb_restore_context is normally called by the core domain + * save / restore logic, but since this VRFB context was suspended + * those calls didn't actually restore the context and now we might + * have an invalid context. Do an explicit restore here. + */ + restore_hw_context(vrfb->context); + set_bit(vrfb->context, &ctx_map_active); + mutex_unlock(&ctx_lock); +} +EXPORT_SYMBOL(omap_vrfb_resume_ctx); + |