diff options
Diffstat (limited to 'drivers/video/omap')
25 files changed, 2319 insertions, 136 deletions
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 44408850e2e..551e3e9c4cb 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -7,6 +7,69 @@ config FB_OMAP help Frame buffer driver for OMAP based boards. +config FB_OMAP_LCD_VGA + bool "Use LCD in VGA mode" + depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP + +choice + depends on FB_OMAP && MACH_OVERO + prompt "Screen resolution" + default FB_OMAP_079M3R + help + Selected desired screen resolution + +config FB_OMAP_031M3R + boolean "640 x 480 @ 60 Hz Reduced blanking" + +config FB_OMAP_048M3R + boolean "800 x 600 @ 60 Hz Reduced blanking" + +config FB_OMAP_079M3R + boolean "1024 x 768 @ 60 Hz Reduced blanking" + +config FB_OMAP_092M9R + boolean "1280 x 720 @ 60 Hz Reduced blanking" + +endchoice + +config FB_OMAP_LCDC_EXTERNAL + bool "External LCD controller support" + depends on FB_OMAP + help + Say Y here, if you want to have support for boards with an + external LCD controller connected to the SoSSI/RFBI interface. + +config FB_OMAP_LCDC_HWA742 + bool "Epson HWA742 LCD controller support" + depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL + help + Say Y here if you want to have support for the external + Epson HWA742 LCD controller. + +config FB_OMAP_LCDC_BLIZZARD + bool "Epson Blizzard LCD controller support" + depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL + help + Say Y here if you want to have support for the external + Epson Blizzard LCD controller. + +config FB_OMAP_MANUAL_UPDATE + bool "Default to manual update mode" + depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL + help + Say Y here, if your user-space applications are capable of + notifying the frame buffer driver when a change has occured in + the frame buffer content and thus a reload of the image data to + the external frame buffer is required. If unsure, say N. + +config FB_OMAP_LCD_MIPID + bool "MIPI DBI-C/DCS compatible LCD support" + depends on FB_OMAP && SPI_MASTER + help + Say Y here if you want to have support for LCDs compatible with + the Mobile Industry Processor Interface DBI-C/DCS + specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3) + config FB_OMAP_BOOTLOADER_INIT bool "Check bootloader initialization" depends on FB_OMAP @@ -36,23 +99,4 @@ config FB_OMAP_DMA_TUNE answer yes. Answer no if you have a dedicated video memory, or don't use any of the accelerated features. -config FB_OMAP_LCDC_EXTERNAL - bool "External LCD controller support" - depends on FB_OMAP - help - Say Y here, if you want to have support for boards with an - external LCD controller connected to the SoSSI/RFBI interface. - -config FB_OMAP_LCDC_HWA742 - bool "Epson HWA742 LCD controller support" - depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL - help - Say Y here if you want to have support for the external - Epson HWA742 LCD controller. -config FB_OMAP_LCDC_BLIZZARD - bool "Epson Blizzard LCD controller support" - depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL - help - Say Y here if you want to have support for the external - Epson Blizzard LCD controller. diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index ed13889c116..b63b198d1f0 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile @@ -8,6 +8,7 @@ objs-yy := omapfb_main.o objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o objs-y$(CONFIG_ARCH_OMAP2) += dispc.o +objs-y$(CONFIG_ARCH_OMAP3) += dispc.o objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o @@ -15,6 +16,7 @@ objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o +objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o @@ -24,5 +26,15 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o +objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o +objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o +objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o +objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o +objs-y$(CONFIG_MACH_OMAP2EVM) += lcd_omap2evm.o +objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o +objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o +objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o +objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o + omapfb-objs := $(objs-yy) diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c index 9dfcf39d336..70dadf9d233 100644 --- a/drivers/video/omap/blizzard.c +++ b/drivers/video/omap/blizzard.c @@ -44,6 +44,7 @@ #define BLIZZARD_CLK_SRC 0x0e #define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 #define BLIZZARD_MEM_BANK0_STATUS 0x14 +#define BLIZZARD_PANEL_CONFIGURATION 0x28 #define BLIZZARD_HDISP 0x2a #define BLIZZARD_HNDP 0x2c #define BLIZZARD_VDISP0 0x2e @@ -92,7 +93,7 @@ struct blizzard_reg_list { }; /* These need to be saved / restored separately from the rest. */ -static struct blizzard_reg_list blizzard_pll_regs[] = { +static const struct blizzard_reg_list blizzard_pll_regs[] = { { .start = 0x04, /* Don't save PLL ctrl (0x0C) */ .end = 0x0a, @@ -103,7 +104,7 @@ static struct blizzard_reg_list blizzard_pll_regs[] = { }, }; -static struct blizzard_reg_list blizzard_gen_regs[] = { +static const struct blizzard_reg_list blizzard_gen_regs[] = { { .start = 0x18, /* SDRAM control */ .end = 0x20, @@ -162,6 +163,10 @@ struct blizzard_struct { int vid_scaled; int last_color_mode; int zoom_on; + int zoom_area_gx1; + int zoom_area_gx2; + int zoom_area_gy1; + int zoom_area_gy2; int screen_width; int screen_height; unsigned te_connected:1; @@ -186,7 +191,7 @@ struct blizzard_struct { struct omapfb_device *fbdev; struct lcd_ctrl_extif *extif; - struct lcd_ctrl *int_ctrl; + const struct lcd_ctrl *int_ctrl; void (*power_up)(struct device *dev); void (*power_down)(struct device *dev); @@ -513,6 +518,13 @@ static int do_full_screen_update(struct blizzard_request *req) return REQ_PENDING; } +static int check_1d_intersect(int a1, int a2, int b1, int b2) +{ + if (a2 <= b1 || b2 <= a1) + return 0; + return 1; +} + /* Setup all planes with an overlapping area with the update window. */ static int do_partial_update(struct blizzard_request *req, int plane, int x, int y, int w, int h, @@ -525,6 +537,7 @@ static int do_partial_update(struct blizzard_request *req, int plane, int color_mode; int flags; int zoom_off; + int have_zoom_for_this_update = 0; /* Global coordinates, relative to pixel 0,0 of the LCD */ gx1 = x + blizzard.plane[plane].pos_x; @@ -544,10 +557,6 @@ static int do_partial_update(struct blizzard_request *req, int plane, gx2_out = gx1_out + w_out; gy2_out = gy1_out + h_out; } - zoom_off = blizzard.zoom_on && gx1 == 0 && gy1 == 0 && - w == blizzard.screen_width && h == blizzard.screen_height; - blizzard.zoom_on = (!zoom_off && blizzard.zoom_on) || - (w < w_out || h < h_out); for (i = 0; i < OMAPFB_PLANE_NUM; i++) { struct plane_info *p = &blizzard.plane[i]; @@ -653,8 +662,49 @@ static int do_partial_update(struct blizzard_request *req, int plane, else disable_tearsync(); + if ((gx2_out - gx1_out) != (gx2 - gx1) || + (gy2_out - gy1_out) != (gy2 - gy1)) + have_zoom_for_this_update = 1; + + /* 'background' type of screen update (as opposed to 'destructive') + can be used to disable scaling if scaling is active */ + zoom_off = blizzard.zoom_on && !have_zoom_for_this_update && + (gx1_out == 0) && (gx2_out == blizzard.screen_width) && + (gy1_out == 0) && (gy2_out == blizzard.screen_height) && + (gx1 == 0) && (gy1 == 0); + + if (blizzard.zoom_on && !have_zoom_for_this_update && !zoom_off && + check_1d_intersect(blizzard.zoom_area_gx1, blizzard.zoom_area_gx2, + gx1_out, gx2_out) && + check_1d_intersect(blizzard.zoom_area_gy1, blizzard.zoom_area_gy2, + gy1_out, gy2_out)) { + /* Previous screen update was using scaling, current update + * is not using it. Additionally, current screen update is + * going to overlap with the scaled area. Scaling needs to be + * disabled in order to avoid 'magnifying glass' effect. + * Dummy setup of background window can be used for this. + */ + set_window_regs(0, 0, blizzard.screen_width, + blizzard.screen_height, + 0, 0, blizzard.screen_width, + blizzard.screen_height, + BLIZZARD_COLOR_RGB565, 1, flags); + blizzard.zoom_on = 0; + } + + /* remember scaling settings if we have scaled update */ + if (have_zoom_for_this_update) { + blizzard.zoom_on = 1; + blizzard.zoom_area_gx1 = gx1_out; + blizzard.zoom_area_gx2 = gx2_out; + blizzard.zoom_area_gy1 = gy1_out; + blizzard.zoom_area_gy2 = gy2_out; + } + set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out, color_mode, zoom_off, flags); + if (zoom_off) + blizzard.zoom_on = 0; blizzard.extif->set_bits_per_cycle(16); /* set_window_regs has left the register index at the right @@ -908,6 +958,35 @@ static int blizzard_set_scale(int plane, int orig_w, int orig_h, return 0; } +static int blizzard_set_rotate(int angle) +{ + u32 l; + + l = blizzard_read_reg(BLIZZARD_PANEL_CONFIGURATION); + l &= ~0x03; + + switch (angle) { + case 0: + l = l | 0x00; + break; + case 90: + l = l | 0x03; + break; + case 180: + l = l | 0x02; + break; + case 270: + l = l | 0x01; + break; + default: + return -EINVAL; + } + + blizzard_write_reg(BLIZZARD_PANEL_CONFIGURATION, l); + + return 0; +} + static int blizzard_enable_plane(int plane, int enable) { if (enable) @@ -1285,14 +1364,15 @@ static void blizzard_get_caps(int plane, struct omapfb_caps *caps) caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE | OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE | OMAPFB_CAPS_WINDOW_SCALE | - OMAPFB_CAPS_WINDOW_OVERLAY; + OMAPFB_CAPS_WINDOW_OVERLAY | + OMAPFB_CAPS_WINDOW_ROTATE; if (blizzard.te_connected) caps->ctrl |= OMAPFB_CAPS_TEARSYNC; caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) | (1 << OMAPFB_COLOR_YUV420); } -static void _save_regs(struct blizzard_reg_list *list, int cnt) +static void _save_regs(const struct blizzard_reg_list *list, int cnt) { int i; @@ -1303,7 +1383,7 @@ static void _save_regs(struct blizzard_reg_list *list, int cnt) } } -static void _restore_regs(struct blizzard_reg_list *list, int cnt) +static void _restore_regs(const struct blizzard_reg_list *list, int cnt) { int i; @@ -1560,6 +1640,7 @@ struct lcd_ctrl blizzard_ctrl = { .setup_plane = blizzard_setup_plane, .set_scale = blizzard_set_scale, .enable_plane = blizzard_enable_plane, + .set_rotate = blizzard_set_rotate, .update_window = blizzard_update_window_async, .sync = blizzard_sync, .suspend = blizzard_suspend, diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index 915439dc05a..f16e4215422 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c @@ -155,6 +155,8 @@ struct resmap { unsigned long *map; }; +#define MAX_IRQ_HANDLERS 4 + static struct { void __iomem *base; @@ -167,9 +169,11 @@ static struct { int ext_mode; - unsigned long enabled_irqs; - void (*irq_callback)(void *); - void *irq_callback_data; + struct { + u32 irq_mask; + void (*callback)(void *); + void *data; + } irq_handlers[MAX_IRQ_HANDLERS]; struct completion frame_done; int fir_hinc[OMAPFB_PLANE_NUM]; @@ -286,7 +290,7 @@ static void setup_plane_fifo(int plane, int ext_mode) BUG_ON(plane > 2); l = dispc_read_reg(fsz_reg[plane]); - l &= FLD_MASK(0, 9); + l &= FLD_MASK(0, 11); if (ext_mode) { low = l * 3 / 4; high = l; @@ -294,7 +298,7 @@ static void setup_plane_fifo(int plane, int ext_mode) low = l / 4; high = l * 3 / 4; } - MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9), + MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 12) | FLD_MASK(0, 12), (high << 16) | low); } @@ -809,57 +813,74 @@ static void set_lcd_timings(void) panel->pixel_clock = fck / lck_div / pck_div / 1000; } -int omap_dispc_request_irq(void (*callback)(void *data), void *data) +static void recalc_irq_mask(void) { - int r = 0; + int i; + unsigned long irq_mask = DISPC_IRQ_MASK_ERROR; - BUG_ON(callback == NULL); + for (i = 0; i < MAX_IRQ_HANDLERS; i++) { + if (!dispc.irq_handlers[i].callback) + continue; - if (dispc.irq_callback) - r = -EBUSY; - else { - dispc.irq_callback = callback; - dispc.irq_callback_data = data; + irq_mask |= dispc.irq_handlers[i].irq_mask; } - return r; -} -EXPORT_SYMBOL(omap_dispc_request_irq); - -void omap_dispc_enable_irqs(int irq_mask) -{ enable_lcd_clocks(1); - dispc.enabled_irqs = irq_mask; - irq_mask |= DISPC_IRQ_MASK_ERROR; MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); enable_lcd_clocks(0); } -EXPORT_SYMBOL(omap_dispc_enable_irqs); -void omap_dispc_disable_irqs(int irq_mask) +int omap_dispc_request_irq(unsigned long irq_mask, void (*callback)(void *data), + void *data) { - enable_lcd_clocks(1); - dispc.enabled_irqs &= ~irq_mask; - irq_mask &= ~DISPC_IRQ_MASK_ERROR; - MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); - enable_lcd_clocks(0); + int i; + + BUG_ON(callback == NULL); + + for (i = 0; i < MAX_IRQ_HANDLERS; i++) { + if (dispc.irq_handlers[i].callback) + continue; + + dispc.irq_handlers[i].irq_mask = irq_mask; + dispc.irq_handlers[i].callback = callback; + dispc.irq_handlers[i].data = data; + recalc_irq_mask(); + + return 0; + } + + return -EBUSY; } -EXPORT_SYMBOL(omap_dispc_disable_irqs); +EXPORT_SYMBOL(omap_dispc_request_irq); -void omap_dispc_free_irq(void) +void omap_dispc_free_irq(unsigned long irq_mask, void (*callback)(void *data), + void *data) { - enable_lcd_clocks(1); - omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL); - dispc.irq_callback = NULL; - dispc.irq_callback_data = NULL; - enable_lcd_clocks(0); + int i; + + for (i = 0; i < MAX_IRQ_HANDLERS; i++) { + if (dispc.irq_handlers[i].callback == callback && + dispc.irq_handlers[i].data == data) { + dispc.irq_handlers[i].irq_mask = 0; + dispc.irq_handlers[i].callback = NULL; + dispc.irq_handlers[i].data = NULL; + recalc_irq_mask(); + return; + } + } + + BUG(); } EXPORT_SYMBOL(omap_dispc_free_irq); static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) { - u32 stat = dispc_read_reg(DISPC_IRQSTATUS); + u32 stat; + int i = 0; + + enable_lcd_clocks(1); + stat = dispc_read_reg(DISPC_IRQSTATUS); if (stat & DISPC_IRQ_FRAMEMASK) complete(&dispc.frame_done); @@ -870,11 +891,17 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) } } - if ((stat & dispc.enabled_irqs) && dispc.irq_callback) - dispc.irq_callback(dispc.irq_callback_data); + for (i = 0; i < MAX_IRQ_HANDLERS; i++) { + if (unlikely(dispc.irq_handlers[i].callback && + (stat & dispc.irq_handlers[i].irq_mask))) + dispc.irq_handlers[i].callback( + dispc.irq_handlers[i].data); + } dispc_write_reg(DISPC_IRQSTATUS, stat); + enable_lcd_clocks(0); + return IRQ_HANDLED; } @@ -913,18 +940,13 @@ static void put_dss_clocks(void) static void enable_lcd_clocks(int enable) { - if (enable) + if (enable) { + clk_enable(dispc.dss_ick); clk_enable(dispc.dss1_fck); - else + } else { clk_disable(dispc.dss1_fck); -} - -static void enable_interface_clocks(int enable) -{ - if (enable) - clk_enable(dispc.dss_ick); - else clk_disable(dispc.dss_ick); + } } static void enable_digit_clocks(int enable) @@ -1013,7 +1035,7 @@ static void mmap_user_close(struct vm_area_struct *vma) atomic_dec(&dispc.map_count[plane]); } -static struct vm_operations_struct mmap_user_ops = { +static const struct vm_operations_struct mmap_user_ops = { .open = mmap_user_open, .close = mmap_user_close, }; @@ -1365,7 +1387,6 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, if ((r = get_dss_clocks()) < 0) goto fail0; - enable_interface_clocks(1); enable_lcd_clocks(1); #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT @@ -1396,10 +1417,10 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, enable_digit_clocks(0); } - /* Enable smart idle and autoidle */ - l = dispc_read_reg(DISPC_CONTROL); + /* Enable smart standby/idle, autoidle and wakeup */ + l = dispc_read_reg(DISPC_SYSCONFIG); l &= ~((3 << 12) | (3 << 3)); - l |= (2 << 12) | (2 << 3) | (1 << 0); + l |= (2 << 12) | (2 << 3) | (1 << 2) | (1 << 0); dispc_write_reg(DISPC_SYSCONFIG, l); omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG); @@ -1409,10 +1430,9 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, dispc_write_reg(DISPC_CONFIG, l); l = dispc_read_reg(DISPC_IRQSTATUS); - dispc_write_reg(l, DISPC_IRQSTATUS); + dispc_write_reg(DISPC_IRQSTATUS, l); - /* Enable those that we handle always */ - omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK); + recalc_irq_mask(); if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler, 0, MODULE_NAME, fbdev)) < 0) { @@ -1469,7 +1489,6 @@ fail2: free_irq(INT_24XX_DSS_IRQ, fbdev); fail1: enable_lcd_clocks(0); - enable_interface_clocks(0); put_dss_clocks(); fail0: iounmap(dispc.base); @@ -1487,7 +1506,6 @@ static void omap_dispc_cleanup(void) cleanup_fbmem(); free_palette_ram(); free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); - enable_interface_clocks(0); put_dss_clocks(); iounmap(dispc.base); } diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h index ef720a78f6d..c15ea77f060 100644 --- a/drivers/video/omap/dispc.h +++ b/drivers/video/omap/dispc.h @@ -37,9 +37,10 @@ extern void omap_dispc_set_lcd_size(int width, int height); extern void omap_dispc_enable_lcd_out(int enable); extern void omap_dispc_enable_digit_out(int enable); -extern int omap_dispc_request_irq(void (*callback)(void *data), void *data); -extern void omap_dispc_free_irq(void); +extern int omap_dispc_request_irq(unsigned long irq_mask, + void (*callback)(void *data), void *data); +extern void omap_dispc_free_irq(unsigned long irq_mask, + void (*callback)(void *data), void *data); extern const struct lcd_ctrl omap2_int_ctrl; - #endif diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index 5d4f34887a2..ca51583ec98 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c @@ -131,7 +131,7 @@ struct { struct omapfb_device *fbdev; struct lcd_ctrl_extif *extif; - struct lcd_ctrl *int_ctrl; + const struct lcd_ctrl *int_ctrl; struct clk *sys_ck; } hwa742; diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c new file mode 100644 index 00000000000..393712b6f36 --- /dev/null +++ b/drivers/video/omap/lcd_2430sdp.c @@ -0,0 +1,202 @@ +/* + * LCD panel support for the TI 2430SDP board + * + * Copyright (C) 2007 MontaVista + * Author: Hunyue Yau <hyau@mvista.com> + * + * Derived from drivers/video/omap/lcd-apollon.c + * + * 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. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/i2c/twl4030.h> + +#include <mach/mux.h> +#include <mach/omapfb.h> +#include <asm/mach-types.h> + +#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 +#define SDP2430_LCD_PANEL_ENABLE_GPIO 154 +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24 +#define SDP3430_LCD_PANEL_ENABLE_GPIO 28 + +static unsigned backlight_gpio; +static unsigned enable_gpio; + +#define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */ +#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER +#define ENABLE_VAUX2_DEDICATED 0x09 +#define ENABLE_VAUX2_DEV_GRP 0x20 +#define ENABLE_VAUX3_DEDICATED 0x03 +#define ENABLE_VAUX3_DEV_GRP 0x20 + +#define ENABLE_VPLL2_DEDICATED 0x05 +#define ENABLE_VPLL2_DEV_GRP 0xE0 +#define TWL4030_VPLL2_DEV_GRP 0x33 +#define TWL4030_VPLL2_DEDICATED 0x36 + +#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v) + + +static int sdp2430_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + if (machine_is_omap_3430sdp()) { + enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; + backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; + } else { + enable_gpio = SDP2430_LCD_PANEL_ENABLE_GPIO; + backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO; + } + + gpio_request(enable_gpio, "LCD enable"); /* LCD panel */ + gpio_request(backlight_gpio, "LCD bl"); /* LCD backlight */ + gpio_direction_output(enable_gpio, 0); + gpio_direction_output(backlight_gpio, 0); + + return 0; +} + +static void sdp2430_panel_cleanup(struct lcd_panel *panel) +{ + gpio_free(backlight_gpio); + gpio_free(enable_gpio); +} + +static int sdp2430_panel_enable(struct lcd_panel *panel) +{ + u8 ded_val, ded_reg; + u8 grp_val, grp_reg; + + if (machine_is_omap_3430sdp()) { + ded_reg = TWL4030_VAUX3_DEDICATED; + ded_val = ENABLE_VAUX3_DEDICATED; + grp_reg = TWL4030_VAUX3_DEV_GRP; + grp_val = ENABLE_VAUX3_DEV_GRP; + + if (omap_rev() > OMAP3430_REV_ES1_0) { + t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED, + TWL4030_VPLL2_DEDICATED); + t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP, + TWL4030_VPLL2_DEV_GRP); + } + } else { + ded_reg = TWL4030_VAUX2_DEDICATED; + ded_val = ENABLE_VAUX2_DEDICATED; + grp_reg = TWL4030_VAUX2_DEV_GRP; + grp_val = ENABLE_VAUX2_DEV_GRP; + } + + gpio_set_value(enable_gpio, 1); + gpio_set_value(backlight_gpio, 1); + + if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg)) + return -EIO; + if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg)) + return -EIO; + + return 0; +} + +static void sdp2430_panel_disable(struct lcd_panel *panel) +{ + gpio_set_value(enable_gpio, 0); + gpio_set_value(backlight_gpio, 0); + if (omap_rev() > OMAP3430_REV_ES1_0) { + t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED); + t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP); + msleep(4); + } +} + +static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +struct lcd_panel sdp2430_panel = { + .name = "sdp2430", + .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | + OMAP_LCDC_INV_HSYNC, + + .bpp = 16, + .data_lines = 16, + .x_res = 240, + .y_res = 320, + .hsw = 3, /* hsync_len (4) - 1 */ + .hfp = 3, /* right_margin (4) - 1 */ + .hbp = 39, /* left_margin (40) - 1 */ + .vsw = 1, /* vsync_len (2) - 1 */ + .vfp = 2, /* lower_margin */ + .vbp = 7, /* upper_margin (8) - 1 */ + + .pixel_clock = LCD_PIXCLOCK_MAX, + + .init = sdp2430_panel_init, + .cleanup = sdp2430_panel_cleanup, + .enable = sdp2430_panel_enable, + .disable = sdp2430_panel_disable, + .get_caps = sdp2430_panel_get_caps, +}; + +static int sdp2430_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&sdp2430_panel); + return 0; +} + +static int sdp2430_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int sdp2430_panel_suspend(struct platform_device *pdev, + pm_message_t mesg) +{ + return 0; +} + +static int sdp2430_panel_resume(struct platform_device *pdev) +{ + return 0; +} + +struct platform_driver sdp2430_panel_driver = { + .probe = sdp2430_panel_probe, + .remove = sdp2430_panel_remove, + .suspend = sdp2430_panel_suspend, + .resume = sdp2430_panel_resume, + .driver = { + .name = "sdp2430_lcd", + .owner = THIS_MODULE, + }, +}; + +static int __init sdp2430_panel_drv_init(void) +{ + return platform_driver_register(&sdp2430_panel_driver); +} + +static void __exit sdp2430_panel_drv_exit(void) +{ + platform_driver_unregister(&sdp2430_panel_driver); +} + +module_init(sdp2430_panel_drv_init); +module_exit(sdp2430_panel_drv_exit); diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c new file mode 100644 index 00000000000..1f7439955e0 --- /dev/null +++ b/drivers/video/omap/lcd_ams_delta.c @@ -0,0 +1,137 @@ +/* + * Based on drivers/video/omap/lcd_inn1510.c + * + * LCD panel support for the Amstrad E3 (Delta) videophone. + * + * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li> + * + * 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. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/delay.h> + +#include <mach/board-ams-delta.h> +#include <mach/hardware.h> +#include <mach/omapfb.h> + +#define AMS_DELTA_DEFAULT_CONTRAST 112 + +static int ams_delta_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + return 0; +} + +static void ams_delta_panel_cleanup(struct lcd_panel *panel) +{ +} + +static int ams_delta_panel_enable(struct lcd_panel *panel) +{ + ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP, + AMS_DELTA_LATCH2_LCD_NDISP); + ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN, + AMS_DELTA_LATCH2_LCD_VBLEN); + + omap_writeb(1, OMAP_PWL_CLK_ENABLE); + omap_writeb(AMS_DELTA_DEFAULT_CONTRAST, OMAP_PWL_ENABLE); + + return 0; +} + +static void ams_delta_panel_disable(struct lcd_panel *panel) +{ + ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN, 0); + ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP, 0); +} + +static unsigned long ams_delta_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +static struct lcd_panel ams_delta_panel = { + .name = "ams-delta", + .config = 0, + + .bpp = 12, + .data_lines = 16, + .x_res = 480, + .y_res = 320, + .pixel_clock = 4687, + .hsw = 3, + .hfp = 1, + .hbp = 1, + .vsw = 1, + .vfp = 0, + .vbp = 0, + .pcd = 0, + .acb = 37, + + .init = ams_delta_panel_init, + .cleanup = ams_delta_panel_cleanup, + .enable = ams_delta_panel_enable, + .disable = ams_delta_panel_disable, + .get_caps = ams_delta_panel_get_caps, +}; + +static int ams_delta_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&ams_delta_panel); + return 0; +} + +static int ams_delta_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int ams_delta_panel_suspend(struct platform_device *pdev, |