summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Zabel <philipp.zabel@gmail.com>2008-04-09 19:27:10 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-04-19 11:29:07 +0100
commite07ff8d8091eff8e208fe1e406c15e5de0fffd63 (patch)
tree06a646e77f14f5d50fccdaa1d79186fb62df3546
parent350d115d1eaa29e64324847badf27c93159ba8e0 (diff)
[ARM] 4952/1: magician: add LCD detection, LCD power switching, update pxafb settings
All magician devices I've encountered so far have featured the Toppoly TD028STEB1 display, so the Samsung LTP280QV support is untested. The power-on sequence is not correct because pxafb doesn't yet support enabling the LCD controller in the middle of the it. Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-pxa/magician.c121
-rw-r--r--include/asm-arm/arch-pxa/magician.h2
2 files changed, 116 insertions, 7 deletions
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index d152a086e73..7de3bfe543b 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/mfd/htc-egpio.h>
@@ -144,7 +145,7 @@ static struct platform_device egpio = {
};
/*
- * LCD - Toppoly TD028STEB1
+ * LCD - Toppoly TD028STEB1 or Samsung LTP280QV
*/
static struct pxafb_mode_info toppoly_modes[] = {
@@ -163,12 +164,99 @@ static struct pxafb_mode_info toppoly_modes[] = {
},
};
+static struct pxafb_mode_info samsung_modes[] = {
+ {
+ .pixclock = 96153,
+ .bpp = 16,
+ .xres = 240,
+ .yres = 320,
+ .hsync_len = 8,
+ .vsync_len = 4,
+ .left_margin = 9,
+ .upper_margin = 4,
+ .right_margin = 9,
+ .lower_margin = 4,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ },
+};
+
+static void toppoly_lcd_power(int on, struct fb_var_screeninfo *si)
+{
+ pr_debug("Toppoly LCD power\n");
+
+ if (on) {
+ pr_debug("on\n");
+ gpio_set_value(EGPIO_MAGICIAN_TOPPOLY_POWER, 1);
+ gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1);
+ udelay(2000);
+ gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1);
+ udelay(2000);
+ /* FIXME: enable LCDC here */
+ udelay(2000);
+ gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1);
+ udelay(2000);
+ gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1);
+ } else {
+ pr_debug("off\n");
+ msleep(15);
+ gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0);
+ udelay(500);
+ gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0);
+ udelay(1000);
+ gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0);
+ gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0);
+ }
+}
+
+static void samsung_lcd_power(int on, struct fb_var_screeninfo *si)
+{
+ pr_debug("Samsung LCD power\n");
+
+ if (on) {
+ pr_debug("on\n");
+ if (system_rev < 3)
+ gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 1);
+ else
+ gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1);
+ mdelay(10);
+ gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1);
+ mdelay(10);
+ gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1);
+ mdelay(30);
+ gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1);
+ mdelay(10);
+ } else {
+ pr_debug("off\n");
+ mdelay(10);
+ gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0);
+ mdelay(30);
+ gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0);
+ mdelay(10);
+ gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0);
+ mdelay(10);
+ if (system_rev < 3)
+ gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);
+ else
+ gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0);
+ }
+}
+
static struct pxafb_mach_info toppoly_info = {
- .modes = toppoly_modes,
- .num_modes = 1,
- .fixed_modes = 1,
- .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- .lccr3 = LCCR3_PixRsEdg,
+ .modes = toppoly_modes,
+ .num_modes = 1,
+ .fixed_modes = 1,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_PixRsEdg,
+ .pxafb_lcd_power = toppoly_lcd_power,
+};
+
+static struct pxafb_mach_info samsung_info = {
+ .modes = samsung_modes,
+ .num_modes = 1,
+ .fixed_modes = 1,
+ .lccr0 = LCCR0_LDDALT | LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = LCCR3_PixFlEdg,
+ .pxafb_lcd_power = samsung_lcd_power,
};
/*
@@ -358,12 +446,31 @@ static struct platform_device *devices[] __initdata = {
static void __init magician_init(void)
{
+ void __iomem *cpld;
+ int lcd_select;
+
platform_add_devices(devices, ARRAY_SIZE(devices));
pxa_set_i2c_info(NULL);
pxa_set_mci_info(&magician_mci_info);
pxa_set_ohci_info(&magician_ohci_info);
pxa_set_ficp_info(&magician_ficp_info);
- set_pxa_fb_info(&toppoly_info);
+
+ /* Check LCD type we have */
+ cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000);
+ if (cpld) {
+ u8 board_id = __raw_readb(cpld+0x14);
+ system_rev = board_id & 0x7;
+ lcd_select = board_id & 0x8;
+ iounmap(cpld);
+ pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");
+ if (lcd_select && (system_rev < 3))
+ pxa_gpio_mode(GPIO75_MAGICIAN_SAMSUNG_POWER_MD);
+ pxa_gpio_mode(GPIO104_MAGICIAN_LCD_POWER_1_MD);
+ pxa_gpio_mode(GPIO105_MAGICIAN_LCD_POWER_2_MD);
+ pxa_gpio_mode(GPIO106_MAGICIAN_LCD_POWER_3_MD);
+ set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
+ } else
+ pr_err("LCD detection: CPLD mapping failed\n");
}
diff --git a/include/asm-arm/arch-pxa/magician.h b/include/asm-arm/arch-pxa/magician.h
index 216921db9d6..b34fd5683e2 100644
--- a/include/asm-arm/arch-pxa/magician.h
+++ b/include/asm-arm/arch-pxa/magician.h
@@ -35,6 +35,7 @@
#define GPIO48_MAGICIAN_UNKNOWN 48
#define GPIO56_MAGICIAN_UNKNOWN 56
#define GPIO57_MAGICIAN_CAM_RESET 57
+#define GPIO75_MAGICIAN_SAMSUNG_POWER 75
#define GPIO83_MAGICIAN_nIR_EN 83
#define GPIO86_MAGICIAN_GSM_RESET 86
#define GPIO87_MAGICIAN_GSM_SELECT 87
@@ -82,6 +83,7 @@
#define GPIO48_MAGICIAN_UNKNOWN_MD (48 | GPIO_OUT)
#define GPIO56_MAGICIAN_UNKNOWN_MD (56 | GPIO_OUT)
#define GPIO57_MAGICIAN_CAM_RESET_MD (57 | GPIO_OUT)
+#define GPIO75_MAGICIAN_SAMSUNG_POWER_MD (75 | GPIO_OUT)
#define GPIO83_MAGICIAN_nIR_EN_MD (83 | GPIO_OUT)
#define GPIO86_MAGICIAN_GSM_RESET_MD (86 | GPIO_OUT)
#define GPIO87_MAGICIAN_GSM_SELECT_MD (87 | GPIO_OUT)