Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Philipp Zabel and committed by
Russell King
e07ff8d8 350d115d

+116 -7
+114 -7
arch/arm/mach-pxa/magician.c
··· 16 16 #include <linux/kernel.h> 17 17 #include <linux/init.h> 18 18 #include <linux/platform_device.h> 19 + #include <linux/delay.h> 19 20 #include <linux/gpio_keys.h> 20 21 #include <linux/input.h> 21 22 #include <linux/mfd/htc-egpio.h> ··· 145 144 }; 146 145 147 146 /* 148 - * LCD - Toppoly TD028STEB1 147 + * LCD - Toppoly TD028STEB1 or Samsung LTP280QV 149 148 */ 150 149 151 150 static struct pxafb_mode_info toppoly_modes[] = { ··· 164 163 }, 165 164 }; 166 165 166 + static struct pxafb_mode_info samsung_modes[] = { 167 + { 168 + .pixclock = 96153, 169 + .bpp = 16, 170 + .xres = 240, 171 + .yres = 320, 172 + .hsync_len = 8, 173 + .vsync_len = 4, 174 + .left_margin = 9, 175 + .upper_margin = 4, 176 + .right_margin = 9, 177 + .lower_margin = 4, 178 + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 179 + }, 180 + }; 181 + 182 + static void toppoly_lcd_power(int on, struct fb_var_screeninfo *si) 183 + { 184 + pr_debug("Toppoly LCD power\n"); 185 + 186 + if (on) { 187 + pr_debug("on\n"); 188 + gpio_set_value(EGPIO_MAGICIAN_TOPPOLY_POWER, 1); 189 + gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1); 190 + udelay(2000); 191 + gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1); 192 + udelay(2000); 193 + /* FIXME: enable LCDC here */ 194 + udelay(2000); 195 + gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1); 196 + udelay(2000); 197 + gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1); 198 + } else { 199 + pr_debug("off\n"); 200 + msleep(15); 201 + gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0); 202 + udelay(500); 203 + gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0); 204 + udelay(1000); 205 + gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0); 206 + gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0); 207 + } 208 + } 209 + 210 + static void samsung_lcd_power(int on, struct fb_var_screeninfo *si) 211 + { 212 + pr_debug("Samsung LCD power\n"); 213 + 214 + if (on) { 215 + pr_debug("on\n"); 216 + if (system_rev < 3) 217 + gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 1); 218 + else 219 + gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1); 220 + mdelay(10); 221 + gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1); 222 + mdelay(10); 223 + gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1); 224 + mdelay(30); 225 + gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1); 226 + mdelay(10); 227 + } else { 228 + pr_debug("off\n"); 229 + mdelay(10); 230 + gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0); 231 + mdelay(30); 232 + gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0); 233 + mdelay(10); 234 + gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0); 235 + mdelay(10); 236 + if (system_rev < 3) 237 + gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 0); 238 + else 239 + gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0); 240 + } 241 + } 242 + 167 243 static struct pxafb_mach_info toppoly_info = { 168 - .modes = toppoly_modes, 169 - .num_modes = 1, 170 - .fixed_modes = 1, 171 - .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 172 - .lccr3 = LCCR3_PixRsEdg, 244 + .modes = toppoly_modes, 245 + .num_modes = 1, 246 + .fixed_modes = 1, 247 + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 248 + .lccr3 = LCCR3_PixRsEdg, 249 + .pxafb_lcd_power = toppoly_lcd_power, 250 + }; 251 + 252 + static struct pxafb_mach_info samsung_info = { 253 + .modes = samsung_modes, 254 + .num_modes = 1, 255 + .fixed_modes = 1, 256 + .lccr0 = LCCR0_LDDALT | LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 257 + .lccr3 = LCCR3_PixFlEdg, 258 + .pxafb_lcd_power = samsung_lcd_power, 173 259 }; 174 260 175 261 /* ··· 446 358 447 359 static void __init magician_init(void) 448 360 { 361 + void __iomem *cpld; 362 + int lcd_select; 363 + 449 364 platform_add_devices(devices, ARRAY_SIZE(devices)); 450 365 pxa_set_i2c_info(NULL); 451 366 pxa_set_mci_info(&magician_mci_info); 452 367 pxa_set_ohci_info(&magician_ohci_info); 453 368 pxa_set_ficp_info(&magician_ficp_info); 454 - set_pxa_fb_info(&toppoly_info); 369 + 370 + /* Check LCD type we have */ 371 + cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000); 372 + if (cpld) { 373 + u8 board_id = __raw_readb(cpld+0x14); 374 + system_rev = board_id & 0x7; 375 + lcd_select = board_id & 0x8; 376 + iounmap(cpld); 377 + pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly"); 378 + if (lcd_select && (system_rev < 3)) 379 + pxa_gpio_mode(GPIO75_MAGICIAN_SAMSUNG_POWER_MD); 380 + pxa_gpio_mode(GPIO104_MAGICIAN_LCD_POWER_1_MD); 381 + pxa_gpio_mode(GPIO105_MAGICIAN_LCD_POWER_2_MD); 382 + pxa_gpio_mode(GPIO106_MAGICIAN_LCD_POWER_3_MD); 383 + set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info); 384 + } else 385 + pr_err("LCD detection: CPLD mapping failed\n"); 455 386 } 456 387 457 388
+2
include/asm-arm/arch-pxa/magician.h
··· 35 35 #define GPIO48_MAGICIAN_UNKNOWN 48 36 36 #define GPIO56_MAGICIAN_UNKNOWN 56 37 37 #define GPIO57_MAGICIAN_CAM_RESET 57 38 + #define GPIO75_MAGICIAN_SAMSUNG_POWER 75 38 39 #define GPIO83_MAGICIAN_nIR_EN 83 39 40 #define GPIO86_MAGICIAN_GSM_RESET 86 40 41 #define GPIO87_MAGICIAN_GSM_SELECT 87 ··· 83 82 #define GPIO48_MAGICIAN_UNKNOWN_MD (48 | GPIO_OUT) 84 83 #define GPIO56_MAGICIAN_UNKNOWN_MD (56 | GPIO_OUT) 85 84 #define GPIO57_MAGICIAN_CAM_RESET_MD (57 | GPIO_OUT) 85 + #define GPIO75_MAGICIAN_SAMSUNG_POWER_MD (75 | GPIO_OUT) 86 86 #define GPIO83_MAGICIAN_nIR_EN_MD (83 | GPIO_OUT) 87 87 #define GPIO86_MAGICIAN_GSM_RESET_MD (86 | GPIO_OUT) 88 88 #define GPIO87_MAGICIAN_GSM_SELECT_MD (87 | GPIO_OUT)