diff options
Diffstat (limited to 'drivers/video/omap')
| -rw-r--r-- | drivers/video/omap/Kconfig | 79 | ||||
| -rw-r--r-- | drivers/video/omap/Makefile | 32 | ||||
| -rw-r--r-- | drivers/video/omap/blizzard.c | 1648 | ||||
| -rw-r--r-- | drivers/video/omap/dispc.c | 1547 | ||||
| -rw-r--r-- | drivers/video/omap/dispc.h | 46 | ||||
| -rw-r--r-- | drivers/video/omap/hwa742.c | 1071 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_ams_delta.c | 212 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_h3.c | 127 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_htcherald.c | 118 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_inn1510.c | 112 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_inn1610.c | 136 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_mipid.c | 627 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_osk.c | 130 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_palmte.c | 111 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_palmtt.c | 116 | ||||
| -rw-r--r-- | drivers/video/omap/lcd_palmz71.c | 112 | ||||
| -rw-r--r-- | drivers/video/omap/lcdc.c | 856 | ||||
| -rw-r--r-- | drivers/video/omap/lcdc.h | 9 | ||||
| -rw-r--r-- | drivers/video/omap/omapfb.h | 229 | ||||
| -rw-r--r-- | drivers/video/omap/omapfb_main.c | 2004 | ||||
| -rw-r--r-- | drivers/video/omap/rfbi.c | 598 | ||||
| -rw-r--r-- | drivers/video/omap/sossi.c | 693 |
22 files changed, 0 insertions, 10613 deletions
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig deleted file mode 100644 index 84ff23208c2..00000000000 --- a/drivers/video/omap/Kconfig +++ /dev/null @@ -1,79 +0,0 @@ -config FB_OMAP - tristate "OMAP frame buffer support (EXPERIMENTAL)" - depends on FB && (OMAP2_DSS = "n") - depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select TWL4030_CORE if MACH_OMAP_2430SDP - help - Frame buffer driver for OMAP based boards. - -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 occurred 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 || FB_OMAP2 - help - Say Y here if you want to enable checking if the bootloader has - already initialized the display controller. In this case the - driver will skip the initialization. - -config FB_OMAP_CONSISTENT_DMA_SIZE - int "Consistent DMA memory size (MB)" - depends on FB_OMAP - range 1 14 - default 2 - help - Increase the DMA consistent memory size according to your video - memory needs, for example if you want to use multiple planes. - The size must be 2MB aligned. - If unsure say 1. - -config FB_OMAP_DMA_TUNE - bool "Set DMA SDRAM access priority high" - depends on FB_OMAP && ARCH_OMAP1 - help - On systems in which video memory is in system memory - (SDRAM) this will speed up graphics DMA operations. - If you have such a system and want to use rotation - answer yes. Answer no if you have a dedicated video - memory, or don't use any of the accelerated features. - - diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile deleted file mode 100644 index ef78550917f..00000000000 --- a/drivers/video/omap/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -# Makefile for the new OMAP framebuffer device driver -# - -obj-$(CONFIG_FB_OMAP) += omapfb.o - -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 - -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_H3) += lcd_h3.o -objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o -objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o -objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o -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_FB_OMAP_LCD_MIPID) += lcd_mipid.o -objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o - -omapfb-objs := $(objs-yy) - diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c deleted file mode 100644 index c0504a8a507..00000000000 --- a/drivers/video/omap/blizzard.c +++ /dev/null @@ -1,1648 +0,0 @@ -/* - * Epson Blizzard LCD controller driver - * - * Copyright (C) 2004-2005 Nokia Corporation - * Authors: Juha Yrjola <juha.yrjola@nokia.com> - * Imre Deak <imre.deak@nokia.com> - * YUV support: Jussi Laako <jussi.laako@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. - */ -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/fb.h> -#include <linux/delay.h> -#include <linux/clk.h> - -#include <plat/dma.h> -#include <plat/blizzard.h> - -#include "omapfb.h" -#include "dispc.h" - -#define MODULE_NAME "blizzard" - -#define BLIZZARD_REV_CODE 0x00 -#define BLIZZARD_CONFIG 0x02 -#define BLIZZARD_PLL_DIV 0x04 -#define BLIZZARD_PLL_LOCK_RANGE 0x06 -#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08 -#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a -#define BLIZZARD_PLL_MODE 0x0c -#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 -#define BLIZZARD_VDISP1 0x30 -#define BLIZZARD_VNDP 0x32 -#define BLIZZARD_HSW 0x34 -#define BLIZZARD_VSW 0x38 -#define BLIZZARD_DISPLAY_MODE 0x68 -#define BLIZZARD_INPUT_WIN_X_START_0 0x6c -#define BLIZZARD_DATA_SOURCE_SELECT 0x8e -#define BLIZZARD_DISP_MEM_DATA_PORT 0x90 -#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92 -#define BLIZZARD_POWER_SAVE 0xE6 -#define BLIZZARD_NDISP_CTRL_STATUS 0xE8 - -/* Data source select */ -/* For S1D13745 */ -#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00 -#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01 -#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04 -#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05 -/* For S1D13744 */ -#define BLIZZARD_SRC_WRITE_LCD 0x00 -#define BLIZZARD_SRC_BLT_LCD 0x06 - -#define BLIZZARD_COLOR_RGB565 0x01 -#define BLIZZARD_COLOR_YUV420 0x09 - -#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */ -#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */ - -#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20) - -/* Reserve 4 request slots for requests in irq context */ -#define REQ_POOL_SIZE 24 -#define IRQ_REQ_POOL_SIZE 4 - -#define REQ_FROM_IRQ_POOL 0x01 - -#define REQ_COMPLETE 0 -#define REQ_PENDING 1 - -struct blizzard_reg_list { - int start; - int end; -}; - -/* These need to be saved / restored separately from the rest. */ -static const struct blizzard_reg_list blizzard_pll_regs[] = { - { - .start = 0x04, /* Don't save PLL ctrl (0x0C) */ - .end = 0x0a, - }, - { - .start = 0x0e, /* Clock configuration */ - .end = 0x0e, - }, -}; - -static const struct blizzard_reg_list blizzard_gen_regs[] = { - { - .start = 0x18, /* SDRAM control */ - .end = 0x20, - }, - { - .start = 0x28, /* LCD Panel configuration */ - .end = 0x5a, /* HSSI interface, TV configuration */ - }, -}; - -static u8 blizzard_reg_cache[0x5a / 2]; - -struct update_param { - int plane; - int x, y, width, height; - int out_x, out_y; - int out_width, out_height; - int color_mode; - int bpp; - int flags; -}; - -struct blizzard_request { - struct list_head entry; - unsigned int flags; - - int (*handler)(struct blizzard_request *req); - void (*complete)(void *data); - void *complete_data; - - union { - struct update_param update; - struct completion *sync; - } par; -}; - -struct plane_info { - unsigned long offset; - int pos_x, pos_y; - int width, height; - int out_width, out_height; - int scr_width; - int color_mode; - int bpp; -}; - -struct blizzard_struct { - enum omapfb_update_mode update_mode; - enum omapfb_update_mode update_mode_before_suspend; - - struct timer_list auto_update_timer; - int stop_auto_update; - struct omapfb_update_window auto_update_window; - int enabled_planes; - int vid_nonstd_color; - 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; - unsigned vsync_only:1; - - struct plane_info plane[OMAPFB_PLANE_NUM]; - - struct blizzard_request req_pool[REQ_POOL_SIZE]; - struct list_head pending_req_list; - struct list_head free_req_list; - struct semaphore req_sema; - spinlock_t req_lock; - - unsigned long sys_ck_rate; - struct extif_timings reg_timings, lut_timings; - - u32 max_transmit_size; - u32 extif_clk_period; - int extif_clk_div; - unsigned long pix_tx_time; - unsigned long line_upd_time; - - struct omapfb_device *fbdev; - struct lcd_ctrl_extif *extif; - const struct lcd_ctrl *int_ctrl; - - void (*power_up)(struct device *dev); - void (*power_down)(struct device *dev); - - int version; -} blizzard; - -struct lcd_ctrl blizzard_ctrl; - -static u8 blizzard_read_reg(u8 reg) -{ - u8 data; - - blizzard.extif->set_bits_per_cycle(8); - blizzard.extif->write_command(®, 1); - blizzard.extif->read_data(&data, 1); - - return data; -} - -static void blizzard_write_reg(u8 reg, u8 val) -{ - blizzard.extif->set_bits_per_cycle(8); - blizzard.extif->write_command(®, 1); - blizzard.extif->write_data(&val, 1); -} - -static void blizzard_restart_sdram(void) -{ - unsigned long tmo; - - blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0); - udelay(50); - blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1); - tmo = jiffies + msecs_to_jiffies(200); - while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) { - if (time_after(jiffies, tmo)) { - dev_err(blizzard.fbdev->dev, - "s1d1374x: SDRAM not ready\n"); - break; - } - msleep(1); - } -} - -static void blizzard_stop_sdram(void) -{ - blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0); -} - -/* Wait until the last window was completely written into the controllers - * SDRAM and we can start transferring the next window. - */ -static void blizzard_wait_line_buffer(void) -{ - unsigned long tmo = jiffies + msecs_to_jiffies(30); - - while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) { - if (time_after(jiffies, tmo)) { - if (printk_ratelimit()) - dev_err(blizzard.fbdev->dev, - "s1d1374x: line buffer not ready\n"); - break; - } - } -} - -/* Wait until the YYC color space converter is idle. */ -static void blizzard_wait_yyc(void) -{ - unsigned long tmo = jiffies + msecs_to_jiffies(30); - - while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) { - if (time_after(jiffies, tmo)) { - if (printk_ratelimit()) - dev_err(blizzard.fbdev->dev, - "s1d1374x: YYC not ready\n"); - break; - } - } -} - -static void disable_overlay(void) -{ - blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT, - BLIZZARD_SRC_DISABLE_OVERLAY); -} - -static void set_window_regs(int x_start, int y_start, int x_end, int y_end, - int x_out_start, int y_out_start, - int x_out_end, int y_out_end, int color_mode, - int zoom_off, int flags) -{ - u8 tmp[18]; - u8 cmd; - - x_end--; - y_end--; - tmp[0] = x_start; - tmp[1] = x_start >> 8; - tmp[2] = y_start; - tmp[3] = y_start >> 8; - tmp[4] = x_end; - tmp[5] = x_end >> 8; - tmp[6] = y_end; - tmp[7] = y_end >> 8; - - x_out_end--; - y_out_end--; - tmp[8] = x_out_start; - tmp[9] = x_out_start >> 8; - tmp[10] = y_out_start; - tmp[11] = y_out_start >> 8; - tmp[12] = x_out_end; - tmp[13] = x_out_end >> 8; - tmp[14] = y_out_end; - tmp[15] = y_out_end >> 8; - - tmp[16] = color_mode; - if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745) - tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND; - else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY) - tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE; - else - tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ? - BLIZZARD_SRC_WRITE_LCD : - BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; - - blizzard.extif->set_bits_per_cycle(8); - cmd = BLIZZARD_INPUT_WIN_X_START_0; - blizzard.extif->write_command(&cmd, 1); - blizzard.extif->write_data(tmp, 18); -} - -static void enable_tearsync(int y, int width, int height, int screen_height, - int out_height, int force_vsync) -{ - u8 b; - - b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); - b |= 1 << 3; - blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b); - - if (likely(blizzard.vsync_only || force_vsync)) { - blizzard.extif->enable_tearsync(1, 0); - return; - } - - if (width * blizzard.pix_tx_time < blizzard.line_upd_time) { - blizzard.extif->enable_tearsync(1, 0); - return; - } - - if ((width * blizzard.pix_tx_time / 1000) * height < - (y + out_height) * (blizzard.line_upd_time / 1000)) { - blizzard.extif->enable_tearsync(1, 0); - return; - } - - blizzard.extif->enable_tearsync(1, y + 1); -} - -static void disable_tearsync(void) -{ - u8 b; - - blizzard.extif->enable_tearsync(0, 0); - b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); - b &= ~(1 << 3); - blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b); - b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); -} - -static inline void set_extif_timings(const struct extif_timings *t); - -static inline struct blizzard_request *alloc_req(void) -{ - unsigned long flags; - struct blizzard_request *req; - int req_flags = 0; - - if (!in_interrupt()) - down(&blizzard.req_sema); - else - req_flags = REQ_FROM_IRQ_POOL; - - spin_lock_irqsave(&blizzard.req_lock, flags); - BUG_ON(list_empty(&blizzard.free_req_list)); - req = list_entry(blizzard.free_req_list.next, - struct blizzard_request, entry); - list_del(&req->entry); - spin_unlock_irqrestore(&blizzard.req_lock, flags); - - INIT_LIST_HEAD(&req->entry); - req->flags = req_flags; - - return req; -} - -static inline void free_req(struct blizzard_request *req) -{ - unsigned long flags; - - spin_lock_irqsave(&blizzard.req_lock, flags); - - list_move(&req->entry, &blizzard.free_req_list); - if (!(req->flags & REQ_FROM_IRQ_POOL)) - up(&blizzard.req_sema); - - spin_unlock_irqrestore(&blizzard.req_lock, flags); -} - -static void process_pending_requests(void) -{ - unsigned long flags; - - spin_lock_irqsave(&blizzard.req_lock, flags); - - while (!list_empty(&blizzard.pending_req_list)) { - struct blizzard_request *req; - void (*complete)(void *); - void *complete_data; - - req = list_entry(blizzard.pending_req_list.next, - struct blizzard_request, entry); - spin_unlock_irqrestore(&blizzard.req_lock, flags); - - if (req->handler(req) == REQ_PENDING) - return; - - complete = req->complete; - complete_data = req->complete_data; - free_req(req); - - if (complete) - complete(complete_data); - - spin_lock_irqsave(&blizzard.req_lock, flags); - } - - spin_unlock_irqrestore(&blizzard.req_lock, flags); -} - -static void submit_req_list(struct list_head *head) -{ - unsigned long flags; - int process = 1; - - spin_lock_irqsave(&blizzard.req_lock, flags); - if (likely(!list_empty(&blizzard.pending_req_list))) - process = 0; - list_splice_init(head, blizzard.pending_req_list.prev); - spin_unlock_irqrestore(&blizzard.req_lock, flags); - - if (process) - process_pending_requests(); -} - -static void request_complete(void *data) -{ - struct blizzard_request *req = (struct blizzard_request *)data; - void (*complete)(void *); - void *complete_data; - - complete = req->complete; - complete_data = req->complete_data; - - free_req(req); - - if (complete) - complete(complete_data); - - process_pending_requests(); -} - - -static int do_full_screen_update(struct blizzard_request *req) -{ - int i; - int flags; - - for (i = 0; i < 3; i++) { - struct plane_info *p = &blizzard.plane[i]; - if (!(blizzard.enabled_planes & (1 << i))) { - blizzard.int_ctrl->enable_plane(i, 0); - continue; - } - dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n", - p->width, p->height); - blizzard.int_ctrl->setup_plane(i, - OMAPFB_CHANNEL_OUT_LCD, p->offset, - p->scr_width, p->pos_x, p->pos_y, - p->width, p->height, - p->color_mode); - blizzard.int_ctrl->enable_plane(i, 1); - } - - dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n", - blizzard.screen_width, blizzard.screen_height); - blizzard_wait_line_buffer(); - flags = req->par.update.flags; - if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC) - enable_tearsync(0, blizzard.screen_width, - blizzard.screen_height, - blizzard.screen_height, - blizzard.screen_height, - flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC); - else - disable_tearsync(); - - set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height, - 0, 0, blizzard.screen_width, blizzard.screen_height, - BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags); - blizzard.zoom_on = 0; - - blizzard.extif->set_bits_per_cycle(16); - /* set_window_regs has left the register index at the right - * place, so no need to set it here. - */ - blizzard.extif->transfer_area(blizzard.screen_width, - blizzard.screen_height, - request_complete, 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, - int x_out, int y_out, int w_out, int h_out, - int wnd_color_mode, int bpp) -{ - int i; - int gx1, gy1, gx2, gy2; - int gx1_out, gy1_out, gx2_out, gy2_out; - 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; - gy1 = y + blizzard.plane[plane].pos_y; - gx2 = gx1 + w; - gy2 = gy1 + h; - - flags = req->par.update.flags; - if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) { - gx1_out = gx1; - gy1_out = gy1; - gx2_out = gx1 + w * 2; - gy2_out = gy1 + h * 2; - } else { - gx1_out = x_out + blizzard.plane[plane].pos_x; - gy1_out = y_out + blizzard.plane[plane].pos_y; - gx2_out = gx1_out + w_out; - gy2_out = gy1_out + h_out; - } - - for (i = 0; i < OMAPFB_PLANE_NUM; i++) { - struct plane_info *p = &blizzard.plane[i]; - int px1, py1; - int px2, py2; - int pw, ph; - int pposx, pposy; - unsigned long offset; - - if (!(blizzard.enabled_planes & (1 << i)) || - (wnd_color_mode && i != plane)) { - blizzard.int_ctrl->enable_plane(i, 0); - continue; - } - /* Plane coordinates */ - if (i == plane) { - /* Plane in which we are doing the update. - * Local coordinates are the one in the update - * request. - */ - px1 = x; - py1 = y; - px2 = x + w; - py2 = y + h; - pposx = 0; - pposy = 0; - } else { - /* Check if this plane has an overlapping part */ - px1 = gx1 - p->pos_x; - py1 = gy1 - p->pos_y; - px2 = gx2 - p->pos_x; - py2 = gy2 - p->pos_y; - if (px1 >= p->width || py1 >= p->height || - px2 <= 0 || py2 <= 0) { - blizzard.int_ctrl->enable_plane(i, 0); - continue; - } - /* Calculate the coordinates for the overlapping - * part in the plane's local coordinates. - */ - pposx = -px1; - pposy = -py1; - if (px1 < 0) - px1 = 0; - if (py1 < 0) - py1 = 0; - if (px2 > p->width) - px2 = p->width; - if (py2 > p->height) - py2 = p->height; - if (pposx < 0) - pposx = 0; - if (pposy < 0) - pposy = 0; - } - pw = px2 - px1; - ph = py2 - py1; - offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8; - if (wnd_color_mode) - /* Window embedded in the plane with a differing - * color mode / bpp. Calculate the number of DMA - * transfer elements in terms of the plane's bpp. - */ - pw = (pw + 1) * bpp / p->bpp; -#ifdef VERBOSE - dev_dbg(blizzard.fbdev->dev, - "plane %d offset %#08lx pposx %d pposy %d " - "px1 %d py1 %d pw %d ph %d\n", - i, offset, pposx, pposy, px1, py1, pw, ph); -#endif - blizzard.int_ctrl->setup_plane(i, - OMAPFB_CHANNEL_OUT_LCD, offset, - p->scr_width, - pposx, pposy, pw, ph, - p->color_mode); - - blizzard.int_ctrl->enable_plane(i, 1); - } - - switch (wnd_color_mode) { - case OMAPFB_COLOR_YUV420: - color_mode = BLIZZARD_COLOR_YUV420; - /* Currently only the 16 bits/pixel cycle format is - * supported on the external interface. Adjust the number - * of transfer elements per line for 12bpp format. - */ - w = (w + 1) * 3 / 4; - break; - default: - color_mode = BLIZZARD_COLOR_RGB565; - break; - } - - blizzard_wait_line_buffer(); - if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420) - blizzard_wait_yyc(); - blizzard.last_color_mode = color_mode; - if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC) - enable_tearsync(gy1, w, h, - blizzard.screen_height, - h_out, - flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC); - 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 - * place, so no need to set it here. - */ - blizzard.extif->transfer_area(w, h, request_complete, req); - - return REQ_PENDING; -} - -static int send_frame_handler(struct blizzard_request *req) -{ - struct update_param *par = &req->par.update; - int plane = par->plane; - -#ifdef VERBOSE - dev_dbg(blizzard.fbdev->dev, - "send_frame: x %d y %d w %d h %d " - "x_out %d y_out %d w_out %d h_out %d " - "color_mode %04x flags %04x planes %01x\n", - par->x, par->y, par->width, par->height, - par->out_x, par->out_y, par->out_width, par->out_height, - par->color_mode, par->flags, blizzard.enabled_planes); -#endif - if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY) - disable_overlay(); - - if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) || - (blizzard.enabled_planes & blizzard.vid_scaled)) - return do_full_screen_update(req); - - return do_partial_update(req, plane, par->x, par->y, - par->width, par->height, - par->out_x, par->out_y, - par->out_width, par->out_height, - par->color_mode, par->bpp); -} - -static void send_frame_complete(void *data) -{ -} - -#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do { \ - req = alloc_req(); \ - req->handler = send_frame_handler; \ - req->complete = send_frame_complete; \ - req->par.update.plane = plane_idx; \ - req->par.update.x = _x; \ - req->par.update.y = _y; \ - req->par.update.width = _w; \ - req->par.update.height = _h; \ - req->par.update.out_x = _x_out; \ - req->par.update.out_y = _y_out; \ - req->par.update.out_width = _w_out; \ - req->par.update.out_height = _h_out; \ - req->par.update.bpp = bpp; \ - req->par.update.color_mode = color_mode;\ - req->par.update.flags = flags; \ - list_add_tail(&req->entry, req_head); \ -} while(0) - -static void create_req_list(int plane_idx, - struct omapfb_update_window *win, - struct list_head *req_head) -{ - struct blizzard_request *req; - int x = win->x; - int y = win->y; - int width = win->width; - int height = win->height; - int x_out = win->out_x; - int y_out = win->out_y; - int width_out = win->out_width; - int height_out = win->out_height; - int color_mode; - int bpp; - int flags; - unsigned int ystart = y; - unsigned int yspan = height; - unsigned int ystart_out = y_out; - unsigned int yspan_out = height_out; - - flags = win->format & ~OMAPFB_FORMAT_MASK; - color_mode = win->format & OMAPFB_FORMAT_MASK; - switch (color_mode) { - case OMAPFB_COLOR_YUV420: - /* Embedded window with different color mode */ - bpp = 12; - /* X, Y, height must be aligned at 2, width at 4 pixels */ - x &= ~1; - y &= ~1; - height = yspan = height & ~1; - width = width & ~3; - break; - default: - /* Same as the plane color mode */ - bpp = blizzard.plane[plane_idx].bpp; - break; - } - if (width * height * bpp / 8 > blizzard.max_transmit_size) { - yspan = blizzard.max_transmit_size / (width * bpp / 8); - yspan_out = yspan * height_out / height; - ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out, - width_out, yspan_out); - ystart += yspan; - ystart_out += yspan_out; - yspan = height - yspan; - yspan_out = height_out - yspan_out; - flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; - } - - ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out, - width_out, yspan_out); -} - -static void auto_update_complete(void *data) -{ - if (!blizzard.stop_auto_update) - mod_timer(&blizzard.auto_update_timer, - jiffies + BLIZZARD_AUTO_UPDATE_TIME); -} - -static void blizzard_update_window_auto(unsigned long arg) -{ - LIST_HEAD(req_list); - struct blizzard_request *last; - struct omapfb_plane_struct *plane; - - plane = blizzard.fbdev->fb_info[0]->par; - create_req_list(plane->idx, - &blizzard.auto_update_window, &req_list); - last = list_entry(req_list.prev, struct blizzard_request, entry); - - last->complete = auto_update_complete; - last->complete_data = NULL; - - submit_req_list(&req_list); -} - -int blizzard_update_window_async(struct fb_info *fbi, - struct omapfb_update_window *win, - void (*complete_callback)(void *arg), - void *complete_callback_data) -{ - LIST_HEAD(req_list); - struct blizzard_request *last; - struct omapfb_plane_struct *plane = fbi->par; - - if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE)) - return -EINVAL; - if (unlikely(!blizzard.te_connected && - (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC))) - return -EINVAL; - - create_req_list(plane->idx, win, &req_list); - last = list_entry(req_list.prev, struct blizzard_request, entry); - - last->complete = complete_callback; - last->complete_data = (void *)complete_callback_data; - - submit_req_list(&req_list); - - return 0; -} -EXPORT_SYMBOL(blizzard_update_window_async); - -static int update_full_screen(void) -{ - return blizzard_update_window_async(blizzard.fbdev->fb_info[0], - &blizzard.auto_update_window, NULL, NULL); - -} - -static int blizzard_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) -{ - struct plane_info *p; - -#ifdef VERBOSE - dev_dbg(blizzard.fbdev->dev, - "plane %d ch_out %d offset %#08lx scr_width %d " - "pos_x %d pos_y %d width %d height %d color_mode %d\n", - plane, channel_out, offset, screen_width, - pos_x, pos_y, width, height, color_mode); -#endif - if ((unsigned)plane > OMAPFB_PLANE_NUM) - return -EINVAL; - p = &blizzard.plane[plane]; - - switch (color_mode) { - case OMAPFB_COLOR_YUV422: - case OMAPFB_COLOR_YUY422: - p->bpp = 16; - blizzard.vid_nonstd_color &= ~(1 << plane); - break; - case OMAPFB_COLOR_YUV420: - p->bpp = 12; - blizzard.vid_nonstd_color |= 1 << plane; - break; - case OMAPFB_COLOR_RGB565: - p->bpp = 16; - blizzard.vid_nonstd_color &= ~(1 << plane); - break; - default: - return -EINVAL; - } - - p->offset = offset; - p->pos_x = pos_x; - p->pos_y = pos_y; - p->width = width; - p->height = height; - p->scr_width = screen_width; - if (!p->out_width) - p->out_width = width; - if (!p->out_height) - p->out_height = height; - - p->color_mode = color_mode; - - return 0; -} - -static int blizzard_set_scale(int plane, int orig_w, int orig_h, - int out_w, int out_h) -{ - struct plane_info *p = &blizzard.plane[plane]; - int r; - - dev_dbg(blizzard.fbdev->dev, - "plane %d orig_w %d orig_h %d out_w %d out_h %d\n", - plane, orig_w, orig_h, out_w, out_h); - if ((unsigned)plane > OMAPFB_PLANE_NUM) - return -ENODEV; - - r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h); - if (r < 0) - return r; - - p->width = orig_w; - p->height = orig_h; - p->out_width = out_w; - p->out_height = out_h; - if (orig_w == out_w && orig_h == out_h) - blizzard.vid_scaled &= ~(1 << plane); - else - blizzard.vid_scaled |= 1 << plane; - - 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) - blizzard.enabled_planes |= 1 << plane; - else - blizzard.enabled_planes &= ~(1 << plane); - - return 0; -} - -static int sync_handler(struct blizzard_request *req) -{ - complete(req->par.sync); - return REQ_COMPLETE; -} - -static void blizzard_sync(void) -{ - LIST_HEAD(req_list); - struct blizzard_request *req; - struct completion comp; - - req = alloc_req(); - - req->handler = sync_handler; - req->complete = NULL; - init_completion(&comp); - req->par.sync = ∁ - - list_add(&req->entry, &req_list); - submit_req_list(&req_list); - - wait_for_completion(&comp); -} - - -static void blizzard_bind_client(struct omapfb_notifier_block *nb) -{ - if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) { - omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY); - } -} - -static int blizzard_set_update_mode(enum omapfb_update_mode mode) -{ - if (unlikely(mode != OMAPFB_MANUAL_UPDATE && - mode != OMAPFB_AUTO_UPDATE && - mode != OMAPFB_UPDATE_DISABLED)) - return -EINVAL; - - if (mode == blizzard.update_mode) - return 0; - - dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n", - mode == OMAPFB_UPDATE_DISABLED ? "disabled" : - (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual")); - - switch (blizzard.update_mode) { - case OMAPFB_MANUAL_UPDATE: - omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED); - break; - case OMAPFB_AUTO_UPDATE: - blizzard.stop_auto_update = 1; - del_timer_sync(&blizzard.auto_update_timer); - break; - case OMAPFB_UPDATE_DISABLED: - break; - } - - blizzard.update_mode = mode; - blizzard_sync(); - blizzard.stop_auto_update = 0; - - switch (mode) { - case OMAPFB_MANUAL_UPDATE: - omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY); - break; - case OMAPFB_AUTO_UPDATE: - blizzard_update_window_auto(0); - break; - case OMAPFB_UPDATE_DISABLED: - break; - } - - return 0; -} - -static enum omapfb_update_mode blizzard_get_update_mode(void) -{ - return blizzard.update_mode; -} - -static inline void set_extif_timings(const struct extif_timings *t) -{ - blizzard.extif->set_timings(t); -} - -static inline unsigned long round_to_extif_ticks(unsigned long ps, int div) -{ - int bus_tick = blizzard.extif_clk_period * div; - return (ps + bus_tick - 1) / bus_tick * bus_tick; -} - -static int calc_reg_timing(unsigned long sysclk, int div) -{ - struct extif_timings *t; - unsigned long systim; - - /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, - * AccessTime 2 ns + 12.2 ns (regs), - * WEOffTime = WEOnTime + 1 ns, - * REOffTime = REOnTime + 12 ns (regs), - * CSOffTime = REOffTime + 1 ns - * ReadCycle = 2ns + 2*SYSCLK (regs), - * WriteCycle = 2*SYSCLK + 2 ns, - * CSPulseWidth = 10 ns */ - - systim = 1000000000 / (sysclk / 1000); - dev_dbg(blizzard.fbdev->dev, - "Blizzard systim %lu ps extif_clk_period %u div %d\n", - systim, blizzard.extif_clk_period, div); - - t = &blizzard.reg_timings; - memset(t, 0, sizeof(*t)); - - t->clk_div = div; - - t->cs_on_time = 0; - t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div); - t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); - t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div); - t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); - t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); - if (t->we_cycle_time < t->we_off_time) - t->we_cycle_time = t->we_off_time; - t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); - if (t->re_cycle_time < t->re_off_time) - t->re_cycle_time = t->re_off_time; - t->cs_pulse_width = 0; - - dev_dbg(blizzard.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n", - t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); - dev_dbg(blizzard.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n", - t->we_on_time, t->we_off_time, t->re_cycle_time, - t->we_cycle_time); - dev_dbg(blizzard.fbdev->dev, "[reg]rdaccess %d cspulse %d\n", - t->access_time, t->cs_pulse_width); - - return blizzard.extif->convert_timings(t); -} - -static int calc_lut_timing(unsigned long sysclk, int div) -{ - struct extif_timings *t; - unsigned long systim; - - /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, - * AccessTime 2 ns + 4 * SYSCLK + 26 (lut), - * WEOffTime = WEOnTime + 1 ns, - * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut), - * CSOffTime = REOffTime + 1 ns - * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut), - * WriteCycle = 2*SYSCLK + 2 ns, - * CSPulseWidth = 10 ns */ - - systim = 1000000000 / (sysclk / 1000); - dev_dbg(blizzard.fbdev->dev, - "Blizzard systim %lu ps extif_clk_period %u div %d\n", - systim, blizzard.extif_clk_period, div); - - t = &blizzard.lut_timings; - memset(t, 0, sizeof(*t)); - - t->clk_div = div; - - t->cs_on_time = 0; - t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim + - 26000, div); - t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); - t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim + - 26000, div); - t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); - t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); - if (t->we_cycle_time < t->we_off_time) - t->we_cycle_time = t->we_off_time; - t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div); - if (t->re_cycle_time < t->re_off_time) - t->re_cycle_time = t->re_off_time; - t->cs_pulse_width = 0; - - dev_dbg(blizzard.fbdev->dev, - "[lut]cson %d csoff %d reon %d reoff %d\n", - t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); - dev_dbg(blizzard.fbdev->dev, - "[lut]weon %d weoff %d recyc %d wecyc %d\n", - t->we_on_time, t->we_off_time, t->re_cycle_time, - t->we_cycle_time); - dev_dbg(blizzard.fbdev->dev, "[lut]rdaccess %d cspulse %d\n", - t->access_time, t->cs_pulse_width); - - return blizzard.extif->convert_timings(t); -} - -static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div) -{ - int max_clk_div; - int div; - - blizzard.extif->get_clk_info(&blizzard.extif_clk_period, &max_clk_div); - for (div = 1; div <= max_clk_div; div++) { - if (calc_reg_timing(sysclk, div) == 0) - break; - } - if (div > max_clk_div) { - dev_dbg(blizzard.fbdev->dev, "reg timing failed\n"); - goto err; - } - *extif_mem_div = div; - - for (div = 1; div <= max_clk_div; div++) { - if (calc_lut_timing(sysclk, div) == 0) - break; - } - - if (div > max_clk_div) - goto err; - - blizzard.extif_clk_div = div; - - return 0; -err: - dev_err(blizzard.fbdev->dev, "can't setup timings\n"); - return -1; -} - -static void calc_blizzard_clk_rates(unsigned long ext_clk, - unsigned long *sys_clk, unsigned long *pix_clk) -{ - int pix_clk_src; - int sys_div = 0, sys_mul = 0; - int pix_div; - - pix_clk_src = blizzard_read_reg(BLIZZARD_CLK_SRC); - pix_div = ((pix_clk_src >> 3) & 0x1f) + 1; - if ((pix_clk_src & (0x3 << 1)) == 0) { - /* Source is the PLL */ - sys_div = (blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x3f) + 1; - sys_mul = blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_0); - sys_mul |= ((blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_1) - & 0x0f) << 11); - *sys_clk = ext_clk * sys_mul / sys_div; - } else /* else source is ext clk, or oscillator */ - *sys_clk = ext_clk; - - *pix_clk = *sys_clk / pix_div; /* HZ */ - dev_dbg(blizzard.fbdev->dev, - "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n", - ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul); - dev_dbg(blizzard.fbdev->dev, "sys_clk %ld pix_clk %ld\n", - *sys_clk, *pix_clk); -} - -static int setup_tearsync(unsigned long pix_clk, int extif_div) -{ - int hdisp, vdisp; - int hndp, vndp; - int hsw, vsw; - int hs, vs; - int hs_pol_inv, vs_pol_inv; - int use_hsvs, use_ndp; - u8 b; - - hsw = blizzard_read_reg(BLIZZARD_HSW); - vsw = blizzard_read_reg(BLIZZARD_VSW); - hs_pol_inv = !(hsw & 0x80); - vs_pol_inv = !(vsw & 0x80); - hsw = hsw & 0x7f; - vsw = vsw & 0x3f; - - hdisp = blizzard_read_reg(BLIZZARD_HDISP) * 8; - vdisp = blizzard_read_reg(BLIZZARD_VDISP0) + - ((blizzard_read_reg(BLIZZARD_VDISP1) & 0x3) << 8); - - hndp = blizzard_read_reg(BLIZZARD_HNDP) & 0x3f; - vndp = blizzard_read_reg(BLIZZARD_VNDP); - - /* time to transfer one pixel (16bpp) in ps */ - blizzard.pix_tx_time = blizzard.reg_timings.we_cycle_time; - if (blizzard.extif->get_max_tx_rate != NULL) { - /* The external interface might have a rate limitation, - * if so, we have to maximize our transfer rate. - */ - unsigned long min_tx_time; - unsigned long max_tx_rate = blizzard.extif->get_max_tx_rate(); - - dev_dbg(blizzard.fbdev->dev, "max_tx_rate %ld HZ\n", - max_tx_rate); - min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */ - if (blizzard.pix_tx_time < min_tx_time) - blizzard.pix_tx_time = min_tx_time; - } - - /* time to update one line in ps */ - blizzard.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000); - blizzard.line_upd_time *= 1000; - if (hdisp * blizzard.pix_tx_time > blizzard.line_upd_time) - /* transfer speed too low, we might have to use both - * HS and VS */ - use_hsvs = 1; - else - /* decent transfer speed, we'll always use only VS */ - use_hsvs = 0; - - if (use_hsvs && (hs_pol_inv || vs_pol_inv)) { - /* HS or'ed with VS doesn't work, use the active high - * TE signal based on HNDP / VNDP */ - use_ndp = 1; - hs_pol_inv = 0; - vs_pol_inv = 0; - hs = hndp; - vs = vndp; - } else { - /* Use HS or'ed with VS as a TE signal if both are needed - * or VNDP if only vsync is needed. */ - use_ndp = 0; - hs = hsw; - vs = vsw; - if (!use_hsvs) { - hs_pol_inv = 0; - vs_pol_inv = 0; - } - } - - hs = hs * 1000000 / (pix_clk / 1000); /* ps */ - hs *= 1000; - - vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */ - vs *= 1000; - - if (vs <= hs) - return -EDOM; - /* set VS to 120% of HS to minimize VS detection time */ - vs = hs * 12 / 10; - /* minimize HS too */ - if (hs > 10000) - hs = 10000; - - b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS); - b &= ~0x3; - b |= use_hsvs ? 1 : 0; - b |= (use_ndp && use_hsvs) ? 0 : 2; - blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b); - - blizzard.vsync_only = !use_hsvs; - - dev_dbg(blizzard.fbdev->dev, - "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n", - pix_clk, blizzard.pix_tx_time, blizzard.line_upd_time); - dev_dbg(blizzard.fbdev->dev, - "hs %d ps vs %d ps mode %d vsync_only %d\n", - hs, vs, b & 0x3, !use_hsvs); - - return blizzard.extif->setup_tearsync(1, hs, vs, - hs_pol_inv, vs_pol_inv, - extif_div); -} - -static void blizzard_get_caps(int plane, struct omapfb_caps *caps) -{ - blizzard.int_ctrl->get_caps(plane, caps); - caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE | - OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE | - OMAPFB_CAPS_WINDOW_SCALE | - 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(const struct blizzard_reg_list *list, int cnt) -{ - int i; - - for (i = 0; i < cnt; i++, list++) { - int reg; - for (reg = list->start; reg <= list->end; reg += 2) - blizzard_reg_cache[reg / 2] = blizzard_read_reg(reg); - } -} - -static void _restore_regs(const struct blizzard_reg_list *list, int cnt) -{ - int i; - - for (i = 0; i < cnt; i++, list++) { - int reg; - for (reg = list->start; reg <= list->end; reg += 2) - blizzard_write_reg(reg, blizzard_reg_cache[reg / 2]); - } -} - -static void blizzard_save_all_regs(void) -{ - _save_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs)); - _save_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs)); -} - -static void blizzard_restore_pll_regs(void) -{ - _restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs)); -} - -static void blizzard_restore_gen_regs(void) -{ - _restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs)); -} - -static void blizzard_suspend(void) -{ - u32 l; - unsigned long tmo; - - if (blizzard.last_color_mode) { - update_full_screen(); - blizzard_sync(); - } - blizzard.update_mode_before_suspend = blizzard.update_mode; - /* the following will disable clocks as well */ - blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED); - - blizzard_save_all_regs(); - - blizzard_stop_sdram(); - - l = blizzard_read_reg(BLIZZARD_POWER_SAVE); - /* Standby, Sleep. We assume we use an external clock. */ - l |= 0x03; - blizzard_write_reg(BLIZZARD_POWER_SAVE, l); - - tmo = jiffies + msecs_to_jiffies(100); - while (!(blizzard_read_reg(BLIZZARD_PLL_MODE) & (1 << 1))) { - if (time_after(jiffies, tmo)) { - dev_err(blizzard.fbdev->dev, - "s1d1374x: sleep timeout, stopping PLL manually\n"); - l = blizzard_read_reg(BLIZZARD_PLL_MODE); - l &= ~0x03; - /* Disable PLL, counter function */ - l |= 0x2; - blizzard_write_reg(BLIZZARD_PLL_MODE, l); - break; - } - msleep(1); - } - - if (blizzard.power_down != NULL) - blizzard.power_down(blizzard.fbdev->dev); -} - -static void blizzard_resume(void) -{ - u32 l; - - if (blizzard.power_up != NULL) - blizzard.power_up(blizzard.fbdev->dev); - - l = blizzard_read_reg(BLIZZARD_POWER_SAVE); - /* Standby, Sleep */ - l &= ~0x03; - blizzard_write_reg(BLIZZARD_POWER_SAVE, l); - - blizzard_restore_pll_regs(); - l = blizzard_read_reg(BLIZZARD_PLL_MODE); - l &= ~0x03; - /* Enable PLL, counter function */ - l |= 0x1; - blizzard_write_reg(BLIZZARD_PLL_MODE, l); - - while (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & (1 << 7))) - msleep(1); - - blizzard_restart_sdram(); - - blizzard_restore_gen_regs(); - - /* Enable display */ - blizzard_write_reg(BLIZZARD_DISPLAY_MODE, 0x01); - - /* the following will enable clocks as necessary */ - blizzard_set_update_mode(blizzard.update_mode_before_suspend); - - /* Force a background update */ - blizzard.zoom_on = 1; - update_full_screen(); - blizzard_sync(); -} - -static int blizzard_init(struct omapfb_device *fbdev, int ext_mode, - struct omapfb_mem_desc *req_vram) -{ - int r = 0, i; - u8 rev, conf; - unsigned long ext_clk; - int extif_div; - unsigned long sys_clk, pix_clk; - struct omapfb_platform_data *omapfb_conf; - struct blizzard_platform_data *ctrl_conf; - - blizzard.fbdev = fbdev; - - BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl); - - blizzard.fbdev = fbdev; - blizzard.extif = fbdev->ext_if; - blizzard.int_ctrl = fbdev->int_ctrl; - - omapfb_conf = fbdev->dev->platform_data; - ctrl_conf = omapfb_conf->ctrl_platform_data; - if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) { - dev_err(fbdev->dev, "s1d1374x: missing platform data\n"); - r = -ENOENT; - goto err1; - } - - blizzard.power_down = ctrl_conf->power_down; - blizzard.power_up = ctrl_conf->power_up; - - spin_lock_init(&blizzard.req_lock); - - if ((r = blizzard.int_ctrl->init(fbdev, 1, req_vram)) < 0) - goto err1; - - if ((r = blizzard.extif->init(fbdev)) < 0) - goto err2; - - blizzard_ctrl.set_color_key = blizzard.int_ctrl->set_color_key; - blizzard_ctrl.get_color_key = blizzard.int_ctrl->get_color_key; - blizzard_ctrl.setup_mem = blizzard.int_ctrl->setup_mem; - blizzard_ctrl.mmap = blizzard.int_ctrl->mmap; - - ext_clk = ctrl_conf->get_clock_rate(fbdev->dev); - if ((r = calc_extif_timings(ext_clk, &extif_div)) < 0) - goto err3; - - set_extif_timings(&blizzard.reg_timings); - - if (blizzard.power_up != NULL) - blizzard.power_up(fbdev->dev); - - calc_blizzard_clk_rates(ext_clk, &sys_clk, &pix_clk); - - if ((r = calc_extif_timings(sys_clk, &extif_div)) < 0) - goto err3; - set_extif_timings(&blizzard.reg_timings); - - if (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x80)) { - dev_err(fbdev->dev, - "controller not initialized by the bootloader\n"); - r = -ENODEV; - goto err3; - } - - if (ctrl_conf->te_connected) { - if ((r = setup_tearsync(pix_clk, extif_div)) < 0) - goto err3; - blizzard.te_connected = 1; - } - - rev = blizzard_read_reg(BLIZZARD_REV_CODE); - conf = blizzard_read_reg(BLIZZARD_CONFIG); - - switch (rev & 0xfc) { - case 0x9c: - blizzard.version = BLIZZARD_VERSION_S1D13744; - pr_info("omapfb: s1d13744 LCD controller rev %d " - "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); - break; - case 0xa4: - blizzard.version = BLIZZARD_VERSION_S1D13745; - pr_info("omapfb: s1d13745 LCD controller rev %d " - "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); - break; - default: - dev_err(fbdev->dev, "invalid s1d1374x revision %02x\n", - rev); - r = -ENODEV; - goto err3; - } - - blizzard.max_transmit_size = blizzard.extif->max_transmit_size; - - blizzard.update_mode = OMAPFB_UPDATE_DISABLED; - - blizzard.auto_update_window.x = 0; - blizzard.auto_update_window.y = 0; - blizzard.auto_update_window.width = fbdev->panel->x_res; - blizzard.auto_update_window.height = fbdev->panel->y_res; - blizzard.auto_update_window.out_x = 0; - blizzard.auto_update_window.out_y = 0; - blizzard.auto_update_window.out_width = fbdev->panel->x_res; - blizzard.auto_update_window.out_height = fbdev->panel->y_res; - blizzard.auto_update_window.format = 0; - - blizzard.screen_width = fbdev->panel->x_res; - blizzard.screen_height = fbdev->panel->y_res; - - init_timer(&blizzard.auto_update_timer); - blizzard.auto_update_timer.function = blizzard_update_window_auto; - blizzard.auto_update_timer.data = 0; - - INIT_LIST_HEAD(&blizzard.free_req_list); - INIT_LIST_HEAD(&blizzard.pending_req_list); - for (i = 0; i < ARRAY_SIZE(blizzard.req_pool); i++) - list_add(&blizzard.req_pool[i].entry, &blizzard.free_req_list); - BUG_ON(i <= IRQ_REQ_POOL_SIZE); - sema_init(&blizzard.req_sema, i - IRQ_REQ_POOL_SIZE); - - return 0; -err3: - if (blizzard.power_down != NULL) - blizzard.power_down(fbdev->dev); - blizzard.extif->cleanup(); -err2: - blizzard.int_ctrl->cleanup(); -err1: - return r; -} - -static void blizzard_cleanup(void) -{ - blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED); - blizzard.extif->cleanup(); - blizzard.int_ctrl->cleanup(); - if (blizzard.power_down != NULL) - blizzard.power_down(blizzard.fbdev->dev); -} - -struct lcd_ctrl blizzard_ctrl = { - .name = "blizzard", - .init = blizzard_init, - .cleanup = blizzard_cleanup, - .bind_client = blizzard_bind_client, - .get_caps = blizzard_get_caps, - .set_update_mode = blizzard_set_update_mode, - .get_update_mode = blizzard_get_update_mode, - .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, - .resume = blizzard_resume, -}; - diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c deleted file mode 100644 index 6f61e781f15..00000000000 --- a/drivers/video/omap/dispc.c +++ /dev/null @@ -1,1547 +0,0 @@ -/* - * OMAP2 display controller support - * - * Copyright (C) 2005 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. - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/dma-mapping.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/slab.h> - -#include <plat/sram.h> -#include <plat/board.h> - -#include "omapfb.h" -#include "dispc.h" - -#define MODULE_NAME "dispc" - -#define DSS_BASE 0x48050000 -#define DSS_SYSCONFIG 0x0010 - -#define DISPC_BASE 0x48050400 - -/* DISPC common */ -#define DISPC_REVISION 0x0000 -#define DISPC_SYSCONFIG 0x0010 -#define DISPC_SYSSTATUS 0x0014 -#define DISPC_IRQSTATUS 0x0018 -#define DISPC_IRQENABLE 0x001C -#define DISPC_CONTROL 0x0040 -#define DISPC_CONFIG 0x0044 -#define DISPC_CAPABLE 0x0048 -#define DISPC_DEFAULT_COLOR0 0x004C -#define DISPC_DEFAULT_COLOR1 0x0050 -#define DISPC_TRANS_COLOR0 0x0054 -#define DISPC_TRANS_COLOR1 0x0058 -#define DISPC_LINE_STATUS 0x005C -#define DISPC_LINE_NUMBER 0x0060 -#define DISPC_TIMING_H 0x0064 -#define DISPC_TIMING_V 0x0068 -#define DISPC_POL_FREQ 0x006C -#define DISPC_DIVISOR 0x0070 -#define DISPC_SIZE_DIG 0x0078 -#define DISPC_SIZE_LCD 0x007C - -#define DISPC_DATA_CYCLE1 0x01D4 -#define DISPC_DATA_CYCLE2 0x01D8 -#define DISPC_DATA_CYCLE3 0x01DC - -/* DISPC GFX plane */ -#define DISPC_GFX_BA0 0x0080 -#define DISPC_GFX_BA1 0x0084 -#define DISPC_GFX_POSITION 0x0088 -#define DISPC_GFX_SIZE 0x008C -#define DISPC_GFX_ATTRIBUTES 0x00A0 -#define DISPC_GFX_FIFO_THRESHOLD 0x00A4 -#define DISPC_GFX_FIFO_SIZE_STATUS 0x00A8 -#define DISPC_GFX_ROW_INC 0x00AC -#define DISPC_GFX_PIXEL_INC 0x00B0 -#define DISPC_GFX_WINDOW_SKIP 0x00B4 -#define DISPC_GFX_TABLE_BA 0x00B8 - -/* DISPC Video plane 1/2 */ -#define DISPC_VID1_BASE 0x00BC -#define DISPC_VID2_BASE 0x014C - -/* Offsets into DISPC_VID1/2_BASE */ -#define DISPC_VID_BA0 0x0000 -#define DISPC_VID_BA1 0x0004 -#define DISPC_VID_POSITION 0x0008 -#define DISPC_VID_SIZE 0x000C -#define DISPC_VID_ATTRIBUTES 0x0010 -#define DISPC_VID_FIFO_THRESHOLD 0x0014 -#define DISPC_VID_FIFO_SIZE_STATUS 0x0018 -#define DISPC_VID_ROW_INC 0x001C -#define DISPC_VID_PIXEL_INC 0x0020 -#define DISPC_VID_FIR 0x0024 -#define DISPC_VID_PICTURE_SIZE 0x0028 -#define DISPC_VID_ACCU0 0x002C -#define DISPC_VID_ACCU1 0x0030 - -/* 8 elements in 8 byte increments */ -#define DISPC_VID_FIR_COEF_H0 0x0034 -/* 8 elements in 8 byte increments */ -#define DISPC_VID_FIR_COEF_HV0 0x0038 -/* 5 elements in 4 byte increments */ -#define DISPC_VID_CONV_COEF0 0x0074 - -#define DISPC_IRQ_FRAMEMASK 0x0001 -#define DISPC_IRQ_VSYNC 0x0002 -#define DISPC_IRQ_EVSYNC_EVEN 0x0004 -#define DISPC_IRQ_EVSYNC_ODD 0x0008 -#define DISPC_IRQ_ACBIAS_COUNT_STAT 0x0010 -#define DISPC_IRQ_PROG_LINE_NUM 0x0020 -#define DISPC_IRQ_GFX_FIFO_UNDERFLOW 0x0040 -#define DISPC_IRQ_GFX_END_WIN 0x0080 -#define DISPC_IRQ_PAL_GAMMA_MASK 0x0100 -#define DISPC_IRQ_OCP_ERR 0x0200 -#define DISPC_IRQ_VID1_FIFO_UNDERFLOW 0x0400 -#define DISPC_IRQ_VID1_END_WIN 0x0800 -#define DISPC_IRQ_VID2_FIFO_UNDERFLOW 0x1000 -#define DISPC_IRQ_VID2_END_WIN 0x2000 -#define DISPC_IRQ_SYNC_LOST 0x4000 - -#define DISPC_IRQ_MASK_ALL 0x7fff - -#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ - DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ - DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ - DISPC_IRQ_SYNC_LOST) - -#define RFBI_CONTROL 0x48050040 - -#define MAX_PALETTE_SIZE (256 * 16) - -#define FLD_MASK(pos, len) (((1 << len) - 1) << pos) - -#define MOD_REG_FLD(reg, mask, val) \ - dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val)); - -#define OMAP2_SRAM_START 0x40200000 -/* Maximum size, in reality this is smaller if SRAM is partially locked. */ -#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */ - -/* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */ -#define DISPC_MEMTYPE_NUM 2 - -#define RESMAP_SIZE(_page_cnt) \ - ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8) -#define RESMAP_PTR(_res_map, _page_nr) \ - (((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8)) -#define RESMAP_MASK(_page_nr) \ - (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1))) - -struct resmap { - unsigned long start; - unsigned page_cnt; - unsigned long *map; -}; - -#define MAX_IRQ_HANDLERS 4 - -static struct { - void __iomem *base; - - struct omapfb_mem_desc mem_desc; - struct resmap *res_map[DISPC_MEMTYPE_NUM]; - atomic_t map_count[OMAPFB_PLANE_NUM]; - - dma_addr_t palette_paddr; - void *palette_vaddr; - - int ext_mode; - - struct { - u32 irq_mask; - void (*callback)(void *); - void *data; - } irq_handlers[MAX_IRQ_HANDLERS]; - struct completion frame_done; - - int fir_hinc[OMAPFB_PLANE_NUM]; - int fir_vinc[OMAPFB_PLANE_NUM]; - - struct clk *dss_ick, *dss1_fck; - struct clk *dss_54m_fck; - - enum omapfb_update_mode update_mode; - struct omapfb_device *fbdev; - - struct omapfb_color_key color_key; -} dispc; - -static void enable_lcd_clocks(int enable); - -static void inline dispc_write_reg(int idx, u32 val) -{ - __raw_writel(val, dispc.base + idx); -} - -static u32 inline dispc_read_reg(int idx) -{ - u32 l = __raw_readl(dispc.base + idx); - return l; -} - -/* Select RFBI or bypass mode */ -static void enable_rfbi_mode(int enable) -{ - void __iomem *rfbi_control; - u32 l; - - l = dispc_read_reg(DISPC_CONTROL); - /* Enable RFBI, GPIO0/1 */ - l &= ~((1 << 11) | (1 << 15) | (1 << 16)); - l |= enable ? (1 << 11) : 0; - /* RFBI En: GPIO0/1=10 RFBI Dis: GPIO0/1=11 */ - l |= 1 << 15; - l |= enable ? 0 : (1 << 16); - dispc_write_reg(DISPC_CONTROL, l); - - /* Set bypass mode in RFBI module */ - rfbi_control = ioremap(RFBI_CONTROL, SZ_1K); - if (!rfbi_control) { - pr_err("Unable to ioremap rfbi_control\n"); - return; - } - l = __raw_readl(rfbi_control); - l |= enable ? 0 : (1 << 1); - __raw_writel(l, rfbi_control); - iounmap(rfbi_control); -} - -static void set_lcd_data_lines(int data_lines) -{ - u32 l; - int code = 0; - - switch (data_lines) { - case 12: - code = 0; - break; - case 16: - code = 1; - break; - case 18: - code = 2; - break; - case 24: - code = 3; - break; - default: - BUG(); - } - - l = dispc_read_reg(DISPC_CONTROL); - l &= ~(0x03 << 8); - l |= code << 8; - dispc_write_reg(DISPC_CONTROL, l); -} - -static void set_load_mode(int mode) -{ - BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY | - DISPC_LOAD_CLUT_ONCE_FRAME)); - MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1); -} - -void omap_dispc_set_lcd_size(int x, int y) -{ - BUG_ON((x > (1 << 11)) || (y > (1 << 11))); - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11), - ((y - 1) << 16) | (x - 1)); - enable_lcd_clocks(0); -} -EXPORT_SYMBOL(omap_dispc_set_lcd_size); - -void omap_dispc_set_digit_size(int x, int y) -{ - BUG_ON((x > (1 << 11)) || (y > (1 << 11))); - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11), - ((y - 1) << 16) | (x - 1)); - enable_lcd_clocks(0); -} -EXPORT_SYMBOL(omap_dispc_set_digit_size); - -static void setup_plane_fifo(int plane, int ext_mode) -{ - const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, - DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD, - DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD }; - const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, - DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS, - DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS }; - int low, high; - u32 l; - - BUG_ON(plane > 2); - - l = dispc_read_reg(fsz_reg[plane]); - l &= FLD_MASK(0, 11); - if (ext_mode) { - low = l * 3 / 4; - high = l; - } else { - low = l / 4; - high = l * 3 / 4; - } - MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 12) | FLD_MASK(0, 12), - (high << 16) | low); -} - -void omap_dispc_enable_lcd_out(int enable) -{ - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0); - enable_lcd_clocks(0); -} -EXPORT_SYMBOL(omap_dispc_enable_lcd_out); - -void omap_dispc_enable_digit_out(int enable) -{ - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0); - enable_lcd_clocks(0); -} -EXPORT_SYMBOL(omap_dispc_enable_digit_out); - -static inline int _setup_plane(int plane, int channel_out, - u32 paddr, int screen_width, - int pos_x, int pos_y, int width, int height, - int color_mode) -{ - const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES, - DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES, - DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES }; - const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0, - DISPC_VID2_BASE + DISPC_VID_BA0 }; - const u32 ps_reg[] = { DISPC_GFX_POSITION, - DISPC_VID1_BASE + DISPC_VID_POSITION, - DISPC_VID2_BASE + DISPC_VID_POSITION }; - const u32 sz_reg[] = { DISPC_GFX_SIZE, - DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE, - DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE }; - const u32 ri_reg[] = { DISPC_GFX_ROW_INC, - DISPC_VID1_BASE + DISPC_VID_ROW_INC, - DISPC_VID2_BASE + DISPC_VID_ROW_INC }; - const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE, - DISPC_VID2_BASE + DISPC_VID_SIZE }; - - int chout_shift, burst_shift; - int chout_val; - int color_code; - int bpp; - int cconv_en; - int set_vsize; - u32 l; - -#ifdef VERBOSE - dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d" - " pos_x %d pos_y %d width %d height %d color_mode %d\n", - plane, channel_out, paddr, screen_width, pos_x, pos_y, - width, height, color_mode); -#endif - - set_vsize = 0; - switch (plane) { - case OMAPFB_PLANE_GFX: - burst_shift = 6; - chout_shift = 8; - break; - case OMAPFB_PLANE_VID1: - case OMAPFB_PLANE_VID2: - burst_shift = 14; - chout_shift = 16; - set_vsize = 1; - break; - default: - return -EINVAL; - } - - switch (channel_out) { - case OMAPFB_CHANNEL_OUT_LCD: - chout_val = 0; - break; - case OMAPFB_CHANNEL_OUT_DIGIT: - chout_val = 1; - break; - default: - return -EINVAL; - } - - cconv_en = 0; - switch (color_mode) { - case OMAPFB_COLOR_RGB565: - color_code = DISPC_RGB_16_BPP; - bpp = 16; - break; - case OMAPFB_COLOR_YUV422: - if (plane == 0) - return -EINVAL; - color_code = DISPC_UYVY_422; - cconv_en = 1; - bpp = 16; - break; - case OMAPFB_COLOR_YUY422: - if (plane == 0) - return -EINVAL; - color_code = DISPC_YUV2_422; - cconv_en = 1; - bpp = 16; - break; - default: - return -EINVAL; - } - - l = dispc_read_reg(at_reg[plane]); - - l &= ~(0x0f << 1); - l |= color_code << 1; - l &= ~(1 << 9); - l |= cconv_en << 9; - - l &= ~(0x03 << burst_shift); - l |= DISPC_BURST_8x32 << burst_shift; - - l &= ~(1 << chout_shift); - l |= chout_val << chout_shift; - - dispc_write_reg(at_reg[plane], l); - - dispc_write_reg(ba_reg[plane], paddr); - MOD_REG_FLD(ps_reg[plane], - FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x); - - MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11), - ((height - 1) << 16) | (width - 1)); - - if (set_vsize) { - /* Set video size if set_scale hasn't set it */ - if (!dispc.fir_vinc[plane]) - MOD_REG_FLD(vs_reg[plane], - FLD_MASK(16, 11), (height - 1) << 16); - if (!dispc.fir_hinc[plane]) - MOD_REG_FLD(vs_reg[plane], - FLD_MASK(0, 11), width - 1); - } - - dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1); - - return height * screen_width * bpp / 8; -} - -static int omap_dispc_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) -{ - u32 paddr; - int r; - - if ((unsigned)plane > dispc.mem_desc.region_cnt) - return -EINVAL; - paddr = dispc.mem_desc.region[plane].paddr + offset; - enable_lcd_clocks(1); - r = _setup_plane(plane, channel_out, paddr, - screen_width, - pos_x, pos_y, width, height, color_mode); - enable_lcd_clocks(0); - return r; -} - -static void write_firh_reg(int plane, int reg, u32 value) -{ - u32 base; - - if (plane == 1) - base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0; - else - base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0; - dispc_write_reg(base + reg * 8, value); -} - -static void write_firhv_reg(int plane, int reg, u32 value) -{ - u32 base; - - if (plane == 1) - base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0; - else - base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0; - dispc_write_reg(base + reg * 8, value); -} - -static void set_upsampling_coef_table(int plane) -{ - const u32 coef[][2] = { - { 0x00800000, 0x00800000 }, - { 0x0D7CF800, 0x037B02FF }, - { 0x1E70F5FF, 0x0C6F05FE }, - { 0x335FF5FE, 0x205907FB }, - { 0xF74949F7, 0x00404000 }, - { 0xF55F33FB, 0x075920FE }, - { 0xF5701EFE, 0x056F0CFF }, - { 0xF87C0DFF, 0x027B0300 }, - }; - int i; - - for (i = 0; i < 8; i++) { - write_firh_reg(plane, i, coef[i][0]); - write_firhv_reg(plane, i, coef[i][1]); - } -} - -static int omap_dispc_set_scale(int plane, - int orig_width, int orig_height, - int out_width, int out_height) -{ - const u32 at_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES, - DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES }; - const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE, - DISPC_VID2_BASE + DISPC_VID_SIZE }; - const u32 fir_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_FIR, - DISPC_VID2_BASE + DISPC_VID_FIR }; - - u32 l; - int fir_hinc; - int fir_vinc; - - if ((unsigned)plane > OMAPFB_PLANE_NUM) - return -ENODEV; - - if (plane == OMAPFB_PLANE_GFX && - (out_width != orig_width || out_height != orig_height)) - return -EINVAL; - - enable_lcd_clocks(1); - if (orig_width < out_width) { - /* - * Upsampling. - * Currently you can only scale both dimensions in one way. - */ - if (orig_height > out_height || - orig_width * 8 < out_width || - orig_height * 8 < out_height) { - enable_lcd_clocks(0); - return -EINVAL; - } - set_upsampling_coef_table(plane); - } else if (orig_width > out_width) { - /* Downsampling not yet supported - */ - - enable_lcd_clocks(0); - return -EINVAL; - } - if (!orig_width || orig_width == out_width) - fir_hinc = 0; - else - fir_hinc = 1024 * orig_width / out_width; - if (!orig_height || orig_height == out_height) - fir_vinc = 0; - else - fir_vinc = 1024 * orig_height / out_height; - dispc.fir_hinc[plane] = fir_hinc; - dispc.fir_vinc[plane] = fir_vinc; - - MOD_REG_FLD(fir_reg[plane], - FLD_MASK(16, 12) | FLD_MASK(0, 12), - ((fir_vinc & 4095) << 16) | - (fir_hinc & 4095)); - - dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d " - "orig_height %d fir_hinc %d fir_vinc %d\n", - out_width, out_height, orig_width, orig_height, - fir_hinc, fir_vinc); - - MOD_REG_FLD(vs_reg[plane], - FLD_MASK(16, 11) | FLD_MASK(0, 11), - ((out_height - 1) << 16) | (out_width - 1)); - - l = dispc_read_reg(at_reg[plane]); - l &= ~(0x03 << 5); - l |= fir_hinc ? (1 << 5) : 0; - l |= fir_vinc ? (1 << 6) : 0; - dispc_write_reg(at_reg[plane], l); - - enable_lcd_clocks(0); - return 0; -} - -static int omap_dispc_enable_plane(int plane, int enable) -{ - const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES, - DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES, - DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES }; - if ((unsigned int)plane > dispc.mem_desc.region_cnt) - return -EINVAL; - - enable_lcd_clocks(1); - MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0); - enable_lcd_clocks(0); - - return 0; -} - -static int omap_dispc_set_color_key(struct omapfb_color_key *ck) -{ - u32 df_reg, tr_reg; - int shift, val; - - switch (ck->channel_out) { - case OMAPFB_CHANNEL_OUT_LCD: - df_reg = DISPC_DEFAULT_COLOR0; - tr_reg = DISPC_TRANS_COLOR0; - shift = 10; - break; - case OMAPFB_CHANNEL_OUT_DIGIT: - df_reg = DISPC_DEFAULT_COLOR1; - tr_reg = DISPC_TRANS_COLOR1; - shift = 12; - break; - default: - return -EINVAL; - } - switch (ck->key_type) { - case OMAPFB_COLOR_KEY_DISABLED: - val = 0; - break; - case OMAPFB_COLOR_KEY_GFX_DST: - val = 1; - break; - case OMAPFB_COLOR_KEY_VID_SRC: - val = 3; - break; - default: - return -EINVAL; - } - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift); - - if (val != 0) - dispc_write_reg(tr_reg, ck->trans_key); - dispc_write_reg(df_reg, ck->background); - enable_lcd_clocks(0); - - dispc.color_key = *ck; - - return 0; -} - -static int omap_dispc_get_color_key(struct omapfb_color_key *ck) -{ - *ck = dispc.color_key; - return 0; -} - -static void load_palette(void) -{ -} - -static int omap_dispc_set_update_mode(enum omapfb_update_mode mode) -{ - int r = 0; - - if (mode != dispc.update_mode) { - switch (mode) { - case OMAPFB_AUTO_UPDATE: - case OMAPFB_MANUAL_UPDATE: - enable_lcd_clocks(1); - omap_dispc_enable_lcd_out(1); - dispc.update_mode = mode; - break; - case OMAPFB_UPDATE_DISABLED: - init_completion(&dispc.frame_done); - omap_dispc_enable_lcd_out(0); - if (!wait_for_completion_timeout(&dispc.frame_done, - msecs_to_jiffies(500))) { - dev_err(dispc.fbdev->dev, - "timeout waiting for FRAME DONE\n"); - } - dispc.update_mode = mode; - enable_lcd_clocks(0); - break; - default: - r = -EINVAL; - } - } - - return r; -} - -static void omap_dispc_get_caps(int plane, struct omapfb_caps *caps) -{ - caps->ctrl |= OMAPFB_CAPS_PLANE_RELOCATE_MEM; - if (plane > 0) - caps->ctrl |= OMAPFB_CAPS_PLANE_SCALE; - caps->plane_color |= (1 << OMAPFB_COLOR_RGB565) | - (1 << OMAPFB_COLOR_YUV422) | - (1 << OMAPFB_COLOR_YUY422); - if (plane == 0) - caps->plane_color |= (1 << OMAPFB_COLOR_CLUT_8BPP) | - (1 << OMAPFB_COLOR_CLUT_4BPP) | - (1 << OMAPFB_COLOR_CLUT_2BPP) | - (1 << OMAPFB_COLOR_CLUT_1BPP) | - (1 << OMAPFB_COLOR_RGB444); -} - -static enum omapfb_update_mode omap_dispc_get_update_mode(void) -{ - return dispc.update_mode; -} - -static void setup_color_conv_coef(void) -{ - u32 mask = FLD_MASK(16, 11) | FLD_MASK(0, 11); - int cf1_reg = DISPC_VID1_BASE + DISPC_VID_CONV_COEF0; - int cf2_reg = DISPC_VID2_BASE + DISPC_VID_CONV_COEF0; - int at1_reg = DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES; - int at2_reg = DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES; - const struct color_conv_coef { - int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; - int full_range; - } ctbl_bt601_5 = { - 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, - }; - const struct color_conv_coef *ct; -#define CVAL(x, y) (((x & 2047) << 16) | (y & 2047)) - - ct = &ctbl_bt601_5; - - MOD_REG_FLD(cf1_reg, mask, CVAL(ct->rcr, ct->ry)); - MOD_REG_FLD(cf1_reg + 4, mask, CVAL(ct->gy, ct->rcb)); - MOD_REG_FLD(cf1_reg + 8, mask, CVAL(ct->gcb, ct->gcr)); - MOD_REG_FLD(cf1_reg + 12, mask, CVAL(ct->bcr, ct->by)); - MOD_REG_FLD(cf1_reg + 16, mask, CVAL(0, ct->bcb)); - - MOD_REG_FLD(cf2_reg, mask, CVAL(ct->rcr, ct->ry)); - MOD_REG_FLD(cf2_reg + 4, mask, CVAL(ct->gy, ct->rcb)); - MOD_REG_FLD(cf2_reg + 8, mask, CVAL(ct->gcb, ct->gcr)); - MOD_REG_FLD(cf2_reg + 12, mask, CVAL(ct->bcr, ct->by)); - MOD_REG_FLD(cf2_reg + 16, mask, CVAL(0, ct->bcb)); -#undef CVAL - - MOD_REG_FLD(at1_reg, (1 << 11), ct->full_range); - MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range); -} - -static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div) -{ - unsigned long fck, lck; - - *lck_div = 1; - pck = max(1, pck); - fck = clk_get_rate(dispc.dss1_fck); - lck = fck; - *pck_div = (lck + pck - 1) / pck; - if (is_tft) - *pck_div = max(2, *pck_div); - else - *pck_div = max(3, *pck_div); - if (*pck_div > 255) { - *pck_div = 255; - lck = pck * *pck_div; - *lck_div = fck / lck; - BUG_ON(*lck_div < 1); - if (*lck_div > 255) { - *lck_div = 255; - dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n", - pck / 1000); - } - } -} - -static void set_lcd_tft_mode(int enable) -{ - u32 mask; - - mask = 1 << 3; - MOD_REG_FLD(DISPC_CONTROL, mask, enable ? mask : 0); -} - -static void set_lcd_timings(void) -{ - u32 l; - int lck_div, pck_div; - struct lcd_panel *panel = dispc.fbdev->panel; - int is_tft = panel->config & OMAP_LCDC_PANEL_TFT; - unsigned long fck; - - l = dispc_read_reg(DISPC_TIMING_H); - l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8)); - l |= ( max(1, (min(64, panel->hsw))) - 1 ) << 0; - l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8; - l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20; - dispc_write_reg(DISPC_TIMING_H, l); - - l = dispc_read_reg(DISPC_TIMING_V); - l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8)); - l |= ( max(1, (min(64, panel->vsw))) - 1 ) << 0; - l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8; - l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20; - dispc_write_reg(DISPC_TIMING_V, l); - - l = dispc_read_reg(DISPC_POL_FREQ); - l &= ~FLD_MASK(12, 6); - l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12; - l |= panel->acb & 0xff; - dispc_write_reg(DISPC_POL_FREQ, l); - - calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div); - - l = dispc_read_reg(DISPC_DIVISOR); - l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8)); - l |= (lck_div << 16) | (pck_div << 0); - dispc_write_reg(DISPC_DIVISOR, l); - - /* update panel info with the exact clock */ - fck = clk_get_rate(dispc.dss1_fck); - panel->pixel_clock = fck / lck_div / pck_div / 1000; -} - -static void recalc_irq_mask(void) -{ - int i; - unsigned long irq_mask = DISPC_IRQ_MASK_ERROR; - - for (i = 0; i < MAX_IRQ_HANDLERS; i++) { - if (!dispc.irq_handlers[i].callback) - continue; - - irq_mask |= dispc.irq_handlers[i].irq_mask; - } - - enable_lcd_clocks(1); - MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); - enable_lcd_clocks(0); -} - -int omap_dispc_request_irq(unsigned long irq_mask, void (*callback)(void *data), - void *data) -{ - 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_request_irq); - -void omap_dispc_free_irq(unsigned long irq_mask, void (*callback)(void *data), - void *data) -{ - 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; - int i = 0; - - enable_lcd_clocks(1); - - stat = dispc_read_reg(DISPC_IRQSTATUS); - if (stat & DISPC_IRQ_FRAMEMASK) - complete(&dispc.frame_done); - - if (stat & DISPC_IRQ_MASK_ERROR) { - if (printk_ratelimit()) { - dev_err(dispc.fbdev->dev, "irq error status %04x\n", - stat & 0x7fff); - } - } - - 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; -} - -static int get_dss_clocks(void) -{ - dispc.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick"); - if (IS_ERR(dispc.dss_ick)) { - dev_err(dispc.fbdev->dev, "can't get ick\n"); - return PTR_ERR(dispc.dss_ick); - } - - dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "fck"); - if (IS_ERR(dispc.dss1_fck)) { - dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); - clk_put(dispc.dss_ick); - return PTR_ERR(dispc.dss1_fck); - } - - dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_clk"); - if (IS_ERR(dispc.dss_54m_fck)) { - dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); - clk_put(dispc.dss_ick); - clk_put(dispc.dss1_fck); - return PTR_ERR(dispc.dss_54m_fck); - } - - return 0; -} - -static void put_dss_clocks(void) -{ - clk_put(dispc.dss_54m_fck); - clk_put(dispc.dss1_fck); - clk_put(dispc.dss_ick); -} - -static void enable_lcd_clocks(int enable) -{ - if (enable) { - clk_enable(dispc.dss_ick); - clk_enable(dispc.dss1_fck); - } else { - clk_disable(dispc.dss1_fck); - clk_disable(dispc.dss_ick); - } -} - -static void enable_digit_clocks(int enable) -{ - if (enable) - clk_enable(dispc.dss_54m_fck); - else - clk_disable(dispc.dss_54m_fck); -} - -static void omap_dispc_suspend(void) -{ - if (dispc.update_mode == OMAPFB_AUTO_UPDATE) { - init_completion(&dispc.frame_done); - omap_dispc_enable_lcd_out(0); - if (!wait_for_completion_timeout(&dispc.frame_done, - msecs_to_jiffies(500))) { - dev_err(dispc.fbdev->dev, - "timeout waiting for FRAME DONE\n"); - } - enable_lcd_clocks(0); - } -} - -static void omap_dispc_resume(void) -{ - if (dispc.update_mode == OMAPFB_AUTO_UPDATE) { - enable_lcd_clocks(1); - if (!dispc.ext_mode) { - set_lcd_timings(); - load_palette(); - } - omap_dispc_enable_lcd_out(1); - } -} - - -static int omap_dispc_update_window(struct fb_info *fbi, - struct omapfb_update_window *win, - void (*complete_callback)(void *arg), - void *complete_callback_data) -{ - return dispc.update_mode == OMAPFB_UPDATE_DISABLED ? -ENODEV : 0; -} - -static int mmap_kern(struct omapfb_mem_region *region) -{ - struct vm_struct *kvma; - struct vm_area_struct vma; - pgprot_t pgprot; - unsigned long vaddr; - - kvma = get_vm_area(region->size, VM_IOREMAP); - if (kvma == NULL) { - dev_err(dispc.fbdev->dev, "can't get kernel vm area\n"); - return -ENOMEM; - } - vma.vm_mm = &init_mm; - - vaddr = (unsigned long)kvma->addr; - - pgprot = pgprot_writecombine(pgprot_kernel); - vma.vm_start = vaddr; - vma.vm_end = vaddr + region->size; - if (io_remap_pfn_range(&vma, vaddr, region->paddr >> PAGE_SHIFT, - region->size, pgprot) < 0) { - dev_err(dispc.fbdev->dev, "kernel mmap for FBMEM failed\n"); - return -EAGAIN; - } - region->vaddr = (void *)vaddr; - - return 0; -} - -static void mmap_user_open(struct vm_area_struct *vma) -{ - int plane = (int)vma->vm_private_data; - - atomic_inc(&dispc.map_count[plane]); -} - -static void mmap_user_close(struct vm_area_struct *vma) -{ - int plane = (int)vma->vm_private_data; - - atomic_dec(&dispc.map_count[plane]); -} - -static const struct vm_operations_struct mmap_user_ops = { - .open = mmap_user_open, - .close = mmap_user_close, -}; - -static int omap_dispc_mmap_user(struct fb_info *info, - struct vm_area_struct *vma) -{ - struct omapfb_plane_struct *plane = info->par; - unsigned long off; - unsigned long start; - u32 len; - - if (vma->vm_end - vma->vm_start == 0) - return 0; - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) - return -EINVAL; - off = vma->vm_pgoff << PAGE_SHIFT; - - start = info->fix.smem_start; - len = info->fix.smem_len; - if (off >= len) - return -EINVAL; - if ((vma->vm_end - vma->vm_start + off) > len) - return -EINVAL; - off += start; - vma->vm_pgoff = off >> PAGE_SHIFT; - vma->vm_flags |= VM_IO | VM_RESERVED; - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - vma->vm_ops = &mmap_user_ops; - vma->vm_private_data = (void *)plane->idx; - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) - return -EAGAIN; - /* vm_ops.open won't be called for mmap itself. */ - atomic_inc(&dispc.map_count[plane->idx]); - return 0; -} - -static void unmap_kern(struct omapfb_mem_region *region) -{ - vunmap(region->vaddr); -} - -static int alloc_palette_ram(void) -{ - dispc.palette_vaddr = dma_alloc_writecombine(dispc.fbdev->dev, - MAX_PALETTE_SIZE, &dispc.palette_paddr, GFP_KERNEL); - if (dispc.palette_vaddr == NULL) { - dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n"); - return -ENOMEM; - } - - return 0; -} - -static void free_palette_ram(void) -{ - dma_free_writecombine(dispc.fbdev->dev, MAX_PALETTE_SIZE, - dispc.palette_vaddr, dispc.palette_paddr); -} - -static int alloc_fbmem(struct omapfb_mem_region *region) -{ - region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev, - region->size, ®ion->paddr, GFP_KERNEL); - - if (region->vaddr == NULL) { - dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n"); - return -ENOMEM; - } - - return 0; -} - -static void free_fbmem(struct omapfb_mem_region *region) -{ - dma_free_writecombine(dispc.fbdev->dev, region->size, - region->vaddr, region->paddr); -} - -static struct resmap *init_resmap(unsigned long start, size_t size) -{ - unsigned page_cnt; - struct resmap *res_map; - - page_cnt = PAGE_ALIGN(size) / PAGE_SIZE; - res_map = - kzalloc(sizeof(struct resmap) + RESMAP_SIZE(page_cnt), GFP_KERNEL); - if (res_map == NULL) - return NULL; - res_map->start = start; - res_map->page_cnt = page_cnt; - res_map->map = (unsigned long *)(res_map + 1); - return res_map; -} - -static void cleanup_resmap(struct resmap *res_map) -{ - kfree(res_map); -} - -static inline int resmap_mem_type(unsigned long start) -{ - if (start >= OMAP2_SRAM_START && - start < OMAP2_SRAM_START + OMAP2_SRAM_SIZE) - return OMAPFB_MEMTYPE_SRAM; - else - return OMAPFB_MEMTYPE_SDRAM; -} - -static inline int resmap_page_reserved(struct resmap *res_map, unsigned page_nr) -{ - return *RESMAP_PTR(res_map, page_nr) & RESMAP_MASK(page_nr) ? 1 : 0; -} - -static inline void resmap_reserve_page(struct resmap *res_map, unsigned page_nr) -{ - BUG_ON(resmap_page_reserved(res_map, page_nr)); - *RESMAP_PTR(res_map, page_nr) |= RESMAP_MASK(page_nr); -} - -static inline void resmap_free_page(struct resmap *res_map, unsigned page_nr) -{ - BUG_ON(!resmap_page_reserved(res_map, page_nr)); - *RESMAP_PTR(res_map, page_nr) &= ~RESMAP_MASK(page_nr); -} - -static void resmap_reserve_region(unsigned long start, size_t size) -{ - - struct resmap *res_map; - unsigned start_page; - unsigned end_page; - int mtype; - unsigned i; - - mtype = resmap_mem_type(start); - res_map = dispc.res_map[mtype]; - dev_dbg(dispc.fbdev->dev, "reserve mem type %d start %08lx size %d\n", - mtype, start, size); - start_page = (start - res_map->start) / PAGE_SIZE; - end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE; - for (i = start_page; i < end_page; i++) - resmap_reserve_page(res_map, i); -} - -static void resmap_free_region(unsigned long start, size_t size) -{ - struct resmap *res_map; - unsigned start_page; - unsigned end_page; - unsigned i; - int mtype; - - mtype = resmap_mem_type(start); - res_map = dispc.res_map[mtype]; - dev_dbg(dispc.fbdev->dev, "free mem type %d start %08lx size %d\n", - mtype, start, size); - start_page = (start - res_map->start) / PAGE_SIZE; - end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE; - for (i = start_page; i < end_page; i++) - resmap_free_page(res_map, i); -} - -static unsigned long resmap_alloc_region(int mtype, size_t size) -{ - unsigned i; - unsigned total; - unsigned start_page; - unsigned long start; - struct resmap *res_map = dispc.res_map[mtype]; - - BUG_ON(mtype >= DISPC_MEMTYPE_NUM || res_map == NULL || !size); - - size = PAGE_ALIGN(size) / PAGE_SIZE; - start_page = 0; - total = 0; - for (i = 0; i < res_map->page_cnt; i++) { - if (resmap_page_reserved(res_map, i)) { - start_page = i + 1; - total = 0; - } else if (++total == size) - break; - } - if (total < size) - return 0; - - start = res_map->start + start_page * PAGE_SIZE; - resmap_reserve_region(start, size * PAGE_SIZE); - - return start; -} - -/* Note that this will only work for user mappings, we don't deal with - * kernel mappings here, so fbcon will keep using the old region. - */ -static int omap_dispc_setup_mem(int plane, size_t size, int mem_type, - unsigned long *paddr) -{ - struct omapfb_mem_region *rg; - unsigned long new_addr = 0; - - if ((unsigned)plane > dispc.mem_desc.region_cnt) - return -EINVAL; - if (mem_type >= DISPC_MEMTYPE_NUM) - return -EINVAL; - if (dispc.res_map[mem_type] == NULL) - return -ENOMEM; - rg = &dispc.mem_desc.region[plane]; - if (size == rg->size && mem_type == rg->type) - return 0; - if (atomic_read(&dispc.map_count[plane])) - return -EBUSY; - if (rg->size != 0) - resmap_free_region(rg->paddr, rg->size); - if (size != 0) { - new_addr = resmap_alloc_region(mem_type, size); - if (!new_addr) { - /* Reallocate old region. */ - resmap_reserve_region(rg->paddr, rg->size); - return -ENOMEM; - } - } - rg->paddr = new_addr; - rg->size = size; - rg->type = mem_type; - - *paddr = new_addr; - - return 0; -} - -static int setup_fbmem(struct omapfb_mem_desc *req_md) -{ - struct omapfb_mem_region *rg; - int i; - int r; - unsigned long mem_start[DISPC_MEMTYPE_NUM]; - unsigned long mem_end[DISPC_MEMTYPE_NUM]; - - if (!req_md->region_cnt) { - dev_err(dispc.fbdev->dev, "no memory regions defined\n"); - return -ENOENT; - } - - rg = &req_md->region[0]; - memset(mem_start, 0xff, sizeof(mem_start)); - memset(mem_end, 0, sizeof(mem_end)); - - for (i = 0; i < req_md->region_cnt; i++, rg++) { - int mtype; - if (rg->paddr) { - rg->alloc = 0; - if (rg->vaddr == NULL) { - rg->map = 1; - if ((r = mmap_kern(rg)) < 0) - return r; - } - } else { - if (rg->type != OMAPFB_MEMTYPE_SDRAM) { - dev_err(dispc.fbdev->dev, - "unsupported memory type\n"); - return -EINVAL; - } - rg->alloc = rg->map = 1; - if ((r = alloc_fbmem(rg)) < 0) - return r; - } - mtype = rg->type; - - if (rg->paddr < mem_start[mtype]) - mem_start[mtype] = rg->paddr; - if (rg->paddr + rg->size > mem_end[mtype]) - mem_end[mtype] = rg->paddr + rg->size; - } - - for (i = 0; i < DISPC_MEMTYPE_NUM; i++) { - unsigned long start; - size_t size; - if (mem_end[i] == 0) - continue; - start = mem_start[i]; - size = mem_end[i] - start; - dispc.res_map[i] = init_resmap(start, size); - r = -ENOMEM; - if (dispc.res_map[i] == NULL) - goto fail; - /* Initial state is that everything is reserved. This - * includes possible holes as well, which will never be - * freed. - */ - resmap_reserve_region(start, size); - } - - dispc.mem_desc = *req_md; - - return 0; -fail: - for (i = 0; i < DISPC_MEMTYPE_NUM; i++) { - if (dispc.res_map[i] != NULL) - cleanup_resmap(dispc.res_map[i]); - } - return r; -} - -static void cleanup_fbmem(void) -{ - struct omapfb_mem_region *rg; - int i; - - for (i = 0; i < DISPC_MEMTYPE_NUM; i++) { - if (dispc.res_map[i] != NULL) - cleanup_resmap(dispc.res_map[i]); - } - rg = &dispc.mem_desc.region[0]; - for (i = 0; i < dispc.mem_desc.region_cnt; i++, rg++) { - if (rg->alloc) - free_fbmem(rg); - else { - if (rg->map) - unmap_kern(rg); - } - } -} - -static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, - struct omapfb_mem_desc *req_vram) -{ - int r; - u32 l; - struct lcd_panel *panel = fbdev->panel; - void __iomem *ram_fw_base; - int tmo = 10000; - int skip_init = 0; - int i; - - memset(&dispc, 0, sizeof(dispc)); - - dispc.base = ioremap(DISPC_BASE, SZ_1K); - if (!dispc.base) { - dev_err(fbdev->dev, "can't ioremap DISPC\n"); - return -ENOMEM; - } - - dispc.fbdev = fbdev; - dispc.ext_mode = ext_mode; - - init_completion(&dispc.frame_done); - - if ((r = get_dss_clocks()) < 0) - goto fail0; - - enable_lcd_clocks(1); - -#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT - l = dispc_read_reg(DISPC_CONTROL); - /* LCD enabled ? */ - if (l & 1) { - pr_info("omapfb: skipping hardware initialization\n"); - skip_init = 1; - } -#endif - - if (!skip_init) { - /* Reset monitoring works only w/ the 54M clk */ - enable_digit_clocks(1); - - /* Soft reset */ - MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1); - - while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) { - if (!--tmo) { - dev_err(dispc.fbdev->dev, "soft reset failed\n"); - r = -ENODEV; - enable_digit_clocks(0); - goto fail1; - } - } - - enable_digit_clocks(0); - } - - /* Enable smart standby/idle, autoidle and wakeup */ - l = dispc_read_reg(DISPC_SYSCONFIG); - l &= ~((3 << 12) | (3 << 3)); - l |= (2 << 12) | (2 << 3) | (1 << 2) | (1 << 0); - dispc_write_reg(DISPC_SYSCONFIG, l); - omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG); - - /* Set functional clock autogating */ - l = dispc_read_reg(DISPC_CONFIG); - l |= 1 << 9; - dispc_write_reg(DISPC_CONFIG, l); - - l = dispc_read_reg(DISPC_IRQSTATUS); - dispc_write_reg(DISPC_IRQSTATUS, l); - - recalc_irq_mask(); - - if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler, - 0, MODULE_NAME, fbdev)) < 0) { - dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n"); - goto fail1; - } - - /* L3 firewall setting: enable access to OCM RAM */ - ram_fw_base = ioremap(0x68005000, SZ_1K); - if (!ram_fw_base) { - dev_err(dispc.fbdev->dev, "Cannot ioremap to enable OCM RAM\n"); - goto fail1; - } - __raw_writel(0x402000b0, ram_fw_base + 0xa0); - iounmap(ram_fw_base); - - if ((r = alloc_palette_ram()) < 0) - goto fail2; - - if ((r = setup_fbmem(req_vram)) < 0) - goto fail3; - - if (!skip_init) { - for (i = 0; i < dispc.mem_desc.region_cnt; i++) { - memset(dispc.mem_desc.region[i].vaddr, 0, - dispc.mem_desc.region[i].size); - } - - /* Set logic clock to fck, pixel clock to fck/2 for now */ - MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1 << 16); - MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(0, 8), 2 << 0); - - setup_plane_fifo(0, ext_mode); - setup_plane_fifo(1, ext_mode); - setup_plane_fifo(2, ext_mode); - - setup_color_conv_coef(); - - set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT); - set_load_mode(DISPC_LOAD_FRAME_ONLY); - - if (!ext_mode) { - set_lcd_data_lines(panel->data_lines); - omap_dispc_set_lcd_size(panel->x_res, panel->y_res); - set_lcd_timings(); - } else - set_lcd_data_lines(panel->bpp); - enable_rfbi_mode(ext_mode); - } - - l = dispc_read_reg(DISPC_REVISION); - pr_info("omapfb: DISPC version %d.%d initialized\n", - l >> 4 & 0x0f, l & 0x0f); - enable_lcd_clocks(0); - - return 0; -fail3: - free_palette_ram(); -fail2: - free_irq(INT_24XX_DSS_IRQ, fbdev); -fail1: - enable_lcd_clocks(0); - put_dss_clocks(); -fail0: - iounmap(dispc.base); - return r; -} - -static void omap_dispc_cleanup(void) -{ - int i; - - omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED); - /* This will also disable clocks that are on */ - for (i = 0; i < dispc.mem_desc.region_cnt; i++) - omap_dispc_enable_plane(i, 0); - cleanup_fbmem(); - free_palette_ram(); - free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); - put_dss_clocks(); - iounmap(dispc.base); -} - -const struct lcd_ctrl omap2_int_ctrl = { - .name = "internal", - .init = omap_dispc_init, - .cleanup = omap_dispc_cleanup, - .get_caps = omap_dispc_get_caps, - .set_update_mode = omap_dispc_set_update_mode, - .get_update_mode = omap_dispc_get_update_mode, - .update_window = omap_dispc_update_window, - .suspend = omap_dispc_suspend, - .resume = omap_dispc_resume, - .setup_plane = omap_dispc_setup_plane, - .setup_mem = omap_dispc_setup_mem, - .set_scale = omap_dispc_set_scale, - .enable_plane = omap_dispc_enable_plane, - .set_color_key = omap_dispc_set_color_key, - .get_color_key = omap_dispc_get_color_key, - .mmap = omap_dispc_mmap_user, -}; diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h deleted file mode 100644 index c15ea77f060..00000000000 --- a/drivers/video/omap/dispc.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _DISPC_H -#define _DISPC_H - -#include <linux/interrupt.h> - -#define DISPC_PLANE_GFX 0 -#define DISPC_PLANE_VID1 1 -#define DISPC_PLANE_VID2 2 - -#define DISPC_RGB_1_BPP 0x00 -#define DISPC_RGB_2_BPP 0x01 -#define DISPC_RGB_4_BPP 0x02 -#define DISPC_RGB_8_BPP 0x03 -#define DISPC_RGB_12_BPP 0x04 -#define DISPC_RGB_16_BPP 0x06 -#define DISPC_RGB_24_BPP 0x08 -#define DISPC_RGB_24_BPP_UNPACK_32 0x09 -#define DISPC_YUV2_422 0x0a -#define DISPC_UYVY_422 0x0b - -#define DISPC_BURST_4x32 0 -#define DISPC_BURST_8x32 1 -#define DISPC_BURST_16x32 2 - -#define DISPC_LOAD_CLUT_AND_FRAME 0x00 -#define DISPC_LOAD_CLUT_ONLY 0x01 -#define DISPC_LOAD_FRAME_ONLY 0x02 -#define DISPC_LOAD_CLUT_ONCE_FRAME 0x03 - -#define DISPC_TFT_DATA_LINES_12 0 -#define DISPC_TFT_DATA_LINES_16 1 -#define DISPC_TFT_DATA_LINES_18 2 -#define DISPC_TFT_DATA_LINES_24 3 - -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(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 deleted file mode 100644 index 084aa0ac562..00000000000 --- a/drivers/video/omap/hwa742.c +++ /dev/null @@ -1,1071 +0,0 @@ -/* - * Epson HWA742 LCD controller driver - * - * Copyright (C) 2004-2005 Nokia Corporation - * Authors: Juha Yrjölä <juha.yrjola@nokia.com> - * Imre Deak <imre.deak@nokia.com> - * YUV support: Jussi Laako <jussi.laako@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. - */ -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/fb.h> -#include <linux/delay.h> -#include <linux/clk.h> -#include <linux/interrupt.h> - -#include <plat/dma.h> -#include <plat/hwa742.h> -#include "omapfb.h" - -#define HWA742_REV_CODE_REG 0x0 -#define HWA742_CONFIG_REG 0x2 -#define HWA742_PLL_DIV_REG 0x4 -#define HWA742_PLL_0_REG 0x6 -#define HWA742_PLL_1_REG 0x8 -#define HWA742_PLL_2_REG 0xa -#define HWA742_PLL_3_REG 0xc -#define HWA742_PLL_4_REG 0xe -#define HWA742_CLK_SRC_REG 0x12 -#define HWA742_PANEL_TYPE_REG 0x14 -#define HWA742_H_DISP_REG 0x16 -#define HWA742_H_NDP_REG 0x18 -#define HWA742_V_DISP_1_REG 0x1a -#define HWA742_V_DISP_2_REG 0x1c -#define HWA742_V_NDP_REG 0x1e -#define HWA742_HS_W_REG 0x20 -#define HWA742_HP_S_REG 0x22 -#define HWA742_VS_W_REG 0x24 -#define HWA742_VP_S_REG 0x26 -#define HWA742_PCLK_POL_REG 0x28 -#define HWA742_INPUT_MODE_REG 0x2a -#define HWA742_TRANSL_MODE_REG1 0x2e -#define HWA742_DISP_MODE_REG 0x34 -#define HWA742_WINDOW_TYPE 0x36 -#define HWA742_WINDOW_X_START_0 0x38 -#define HWA742_WINDOW_X_START_1 0x3a -#define HWA742_WINDOW_Y_START_0 0x3c -#define HWA742_WINDOW_Y_START_1 0x3e -#define HWA742_WINDOW_X_END_0 0x40 -#define HWA742_WINDOW_X_END_1 0x42 -#define HWA742_WINDOW_Y_END_0 0x44 -#define HWA742_WINDOW_Y_END_1 0x46 -#define HWA742_MEMORY_WRITE_LSB 0x48 -#define HWA742_MEMORY_WRITE_MSB 0x49 -#define HWA742_MEMORY_READ_0 0x4a -#define HWA742_MEMORY_READ_1 0x4c -#define HWA742_MEMORY_READ_2 0x4e -#define HWA742_POWER_SAVE 0x56 -#define HWA742_NDP_CTRL 0x58 - -#define HWA742_AUTO_UPDATE_TIME (HZ / 20) - -/* Reserve 4 request slots for requests in irq context */ -#define REQ_POOL_SIZE 24 -#define IRQ_REQ_POOL_SIZE 4 - -#define REQ_FROM_IRQ_POOL 0x01 - -#define REQ_COMPLETE 0 -#define REQ_PENDING 1 - -struct update_param { - int x, y, width, height; - int color_mode; - int flags; -}; - -struct hwa742_request { - struct list_head entry; - unsigned int flags; - - int (*handler)(struct hwa742_request *req); - void (*complete)(void *data); - void *complete_data; - - union { - struct update_param update; - struct completion *sync; - } par; -}; - -struct { - enum omapfb_update_mode update_mode; - enum omapfb_update_mode update_mode_before_suspend; - - struct timer_list auto_update_timer; - int stop_auto_update; - struct omapfb_update_window auto_update_window; - unsigned te_connected:1; - unsigned vsync_only:1; - - struct hwa742_request req_pool[REQ_POOL_SIZE]; - struct list_head pending_req_list; - struct list_head free_req_list; - struct semaphore req_sema; - spinlock_t req_lock; - - struct extif_timings reg_timings, lut_timings; - - int prev_color_mode; - int prev_flags; - int window_type; - - u32 max_transmit_size; - u32 extif_clk_period; - unsigned long pix_tx_time; - unsigned long line_upd_time; - - - struct omapfb_device *fbdev; - struct lcd_ctrl_extif *extif; - const struct lcd_ctrl *int_ctrl; - - struct clk *sys_ck; -} hwa742; - -struct lcd_ctrl hwa742_ctrl; - -static u8 hwa742_read_reg(u8 reg) -{ - u8 data; - - hwa742.extif->set_bits_per_cycle(8); - hwa742.extif->write_command(®, 1); - hwa742.extif->read_data(&data, 1); - - return data; -} - -static void hwa742_write_reg(u8 reg, u8 data) -{ - hwa742.extif->set_bits_per_cycle(8); - hwa742.extif->write_command(®, 1); - hwa742.extif->write_data(&data, 1); -} - -static void set_window_regs(int x_start, int y_start, int x_end, int y_end) -{ - u8 tmp[8]; - u8 cmd; - - x_end--; - y_end--; - tmp[0] = x_start; - tmp[1] = x_start >> 8; - tmp[2] = y_start; - tmp[3] = y_start >> 8; - tmp[4] = x_end; - tmp[5] = x_end >> 8; - tmp[6] = y_end; - tmp[7] = y_end >> 8; - - hwa742.extif->set_bits_per_cycle(8); - cmd = HWA742_WINDOW_X_START_0; - - hwa742.extif->write_command(&cmd, 1); - - hwa742.extif->write_data(tmp, 8); -} - -static void set_format_regs(int conv, int transl, int flags) -{ - if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) { - hwa742.window_type = ((hwa742.window_type & 0xfc) | 0x01); -#ifdef VERBOSE - dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n"); -#endif - } else { - hwa742.window_type = (hwa742.window_type & 0xfc); -#ifdef VERBOSE - dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n"); -#endif - } - - hwa742_write_reg(HWA742_INPUT_MODE_REG, conv); - hwa742_write_reg(HWA742_TRANSL_MODE_REG1, transl); - hwa742_write_reg(HWA742_WINDOW_TYPE, hwa742.window_type); -} - -static void enable_tearsync(int y, int width, int height, int screen_height, - int force_vsync) -{ - u8 b; - - b = hwa742_read_reg(HWA742_NDP_CTRL); - b |= 1 << 2; - hwa742_write_reg(HWA742_NDP_CTRL, b); - - if (likely(hwa742.vsync_only || force_vsync)) { - hwa742.extif->enable_tearsync(1, 0); - return; - } - - if (width * hwa742.pix_tx_time < hwa742.line_upd_time) { - hwa742.extif->enable_tearsync(1, 0); - return; - } - - if ((width * hwa742.pix_tx_time / 1000) * height < - (y + height) * (hwa742.line_upd_time / 1000)) { - hwa742.extif->enable_tearsync(1, 0); - return; - } - - hwa742.extif->enable_tearsync(1, y + 1); -} - -static void disable_tearsync(void) -{ - u8 b; - - hwa742.extif->enable_tearsync(0, 0); - - b = hwa742_read_reg(HWA742_NDP_CTRL); - b &= ~(1 << 2); - hwa742_write_reg(HWA742_NDP_CTRL, b); -} - -static inline struct hwa742_request *alloc_req(void) -{ - unsigned long flags; - struct hwa742_request *req; - int req_flags = 0; - - if (!in_interrupt()) - down(&hwa742.req_sema); - else - req_flags = REQ_FROM_IRQ_POOL; - - spin_lock_irqsave(&hwa742.req_lock, flags); - BUG_ON(list_empty(&hwa742.free_req_list)); - req = list_entry(hwa742.free_req_list.next, - struct hwa742_request, entry); - list_del(&req->entry); - spin_unlock_irqrestore(&hwa742.req_lock, flags); - - INIT_LIST_HEAD(&req->entry); - req->flags = req_flags; - - return req; -} - -static inline void free_req(struct hwa742_request *req) -{ - unsigned long flags; - - spin_lock_irqsave(&hwa742.req_lock, flags); - - list_move(&req->entry, &hwa742.free_req_list); - if (!(req->flags & REQ_FROM_IRQ_POOL)) - up(&hwa742.req_sema); - - spin_unlock_irqrestore(&hwa742.req_lock, flags); -} - -static void process_pending_requests(void) -{ - unsigned long flags; - - spin_lock_irqsave(&hwa742.req_lock, flags); - - while (!list_empty(&hwa742.pending_req_list)) { - struct hwa742_request *req; - void (*complete)(void *); - void *complete_data; - - req = list_entry(hwa742.pending_req_list.next, - struct hwa742_request, entry); - spin_unlock_irqrestore(&hwa742.req_lock, flags); - - if (req->handler(req) == REQ_PENDING) - return; - - complete = req->complete; - complete_data = req->complete_data; - free_req(req); - - if (complete) - complete(complete_data); - - spin_lock_irqsave(&hwa742.req_lock, flags); - } - - spin_unlock_irqrestore(&hwa742.req_lock, flags); -} - -static void submit_req_list(struct list_head *head) -{ - unsigned long flags; - int process = 1; - - spin_lock_irqsave(&hwa742.req_lock, flags); - if (likely(!list_empty(&hwa742.pending_req_list))) - process = 0; - list_splice_init(head, hwa742.pending_req_list.prev); - spin_unlock_irqrestore(&hwa742.req_lock, flags); - - if (process) - process_pending_requests(); -} - -static void request_complete(void *data) -{ - struct hwa742_request *req = (struct hwa742_request *)data; - void (*complete)(void *); - void *complete_data; - - complete = req->complete; - complete_data = req->complete_data; - - free_req(req); - - if (complete) - complete(complete_data); - - process_pending_requests(); -} - -static int send_frame_handler(struct hwa742_request *req) -{ - struct update_param *par = &req->par.update; - int x = par->x; - int y = par->y; - int w = par->width; - int h = par->height; - int bpp; - int conv, transl; - unsigned long offset; - int color_mode = par->color_mode; - int flags = par->flags; - int scr_width = hwa742.fbdev->panel->x_res; - int scr_height = hwa742.fbdev->panel->y_res; - -#ifdef VERBOSE - dev_dbg(hwa742.fbdev->dev, "x %d y %d w %d h %d scr_width %d " - "color_mode %d flags %d\n", - x, y, w, h, scr_width, color_mode, flags); -#endif - - switch (color_mode) { - case OMAPFB_COLOR_YUV422: - bpp = 16; - conv = 0x08; - transl = 0x25; - break; - case OMAPFB_COLOR_YUV420: - bpp = 12; - conv = 0x09; - transl = 0x25; - break; - case OMAPFB_COLOR_RGB565: - bpp = 16; - conv = 0x01; - transl = 0x05; - break; - default: - return -EINVAL; - } - - if (hwa742.prev_flags != flags || - hwa742.prev_color_mode != color_mode) { - set_format_regs(conv, transl, flags); - hwa742.prev_color_mode = color_mode; - hwa742.prev_flags = flags; - } - flags = req->par.update.flags; - if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC) - enable_tearsync(y, scr_width, h, scr_height, - flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC); - else - disable_tearsync(); - - set_window_regs(x, y, x + w, y + h); - - offset = (scr_width * y + x) * bpp / 8; - - hwa742.int_ctrl->setup_plane(OMAPFB_PLANE_GFX, - OMAPFB_CHANNEL_OUT_LCD, offset, scr_width, 0, 0, w, h, - color_mode); - - hwa742.extif->set_bits_per_cycle(16); - - hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 1); - hwa742.extif->transfer_area(w, h, request_complete, req); - - return REQ_PENDING; -} - -static void send_frame_complete(void *data) -{ - hwa742.int_ctrl->enable_plane(OMAPFB_PLANE_GFX, 0); -} - -#define ADD_PREQ(_x, _y, _w, _h) do { \ - req = alloc_req(); \ - req->handler = send_frame_handler; \ - req->complete = send_frame_complete; \ - req->par.update.x = _x; \ - req->par.update.y = _y; \ - req->par.update.width = _w; \ - req->par.update.height = _h; \ - req->par.update.color_mode = color_mode;\ - req->par.update.flags = flags; \ - list_add_tail(&req->entry, req_head); \ -} while(0) - -static void create_req_list(struct omapfb_update_window *win, - struct list_head *req_head) -{ - struct hwa742_request *req; - int x = win->x; - int y = win->y; - int width = win->width; - int height = win->height; - int color_mode; - int flags; - - flags = win->format & ~OMAPFB_FORMAT_MASK; - color_mode = win->format & OMAPFB_FORMAT_MASK; - - if (x & 1) { - ADD_PREQ(x, y, 1, height); - width--; - x++; - flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; - } - if (width & ~1) { - unsigned int xspan = width & ~1; - unsigned int ystart = y; - unsigned int yspan = height; - - if (xspan * height * 2 > hwa742.max_transmit_size) { - yspan = hwa742.max_transmit_size / (xspan * 2); - ADD_PREQ(x, ystart, xspan, yspan); - ystart += yspan; - yspan = height - yspan; - flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; - } - - ADD_PREQ(x, ystart, xspan, yspan); - x += xspan; - width -= xspan; - flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC; - } - if (width) - ADD_PREQ(x, y, 1, height); -} - -static void auto_update_complete(void *data) -{ - if (!hwa742.stop_auto_update) - mod_timer(&hwa742.auto_update_timer, - jiffies + HWA742_AUTO_UPDATE_TIME); -} - -static void hwa742_update_window_auto(unsigned long arg) -{ - LIST_HEAD(req_list); - struct hwa742_request *last; - - create_req_list(&hwa742.auto_update_window, &req_list); - last = list_entry(req_list.prev, struct hwa742_request, entry); - - last->complete = auto_update_complete; - last->complete_data = NULL; - - submit_req_list(&req_list); -} - -int hwa742_update_window_async(struct fb_info *fbi, - struct omapfb_update_window *win, - void (*complete_callback)(void *arg), - void *complete_callback_data) -{ - LIST_HEAD(req_list); - struct hwa742_request *last; - int r = 0; - - if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) { - dev_dbg(hwa742.fbdev->dev, "invalid update mode\n"); - r = -EINVAL; - goto out; - } - if (unlikely(win->format & - ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE | - OMAPFB_FORMAT_FLAG_TEARSYNC | OMAPFB_FORMAT_FLAG_FORCE_VSYNC))) { - dev_dbg(hwa742.fbdev->dev, "invalid window flag\n"); - r = -EINVAL; - goto out; - } - - create_req_list(win, &req_list); - last = list_entry(req_list.prev, struct hwa742_request, entry); - - last->complete = complete_callback; - last->complete_data = (void *)complete_callback_data; - - submit_req_list(&req_list); - -out: - return r; -} -EXPORT_SYMBOL(hwa742_update_window_async); - -static int hwa742_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) -{ - if (plane != OMAPFB_PLANE_GFX || - channel_out != OMAPFB_CHANNEL_OUT_LCD) - return -EINVAL; - - return 0; -} - -static int hwa742_enable_plane(int plane, int enable) -{ - if (plane != 0) - return -EINVAL; - - hwa742.int_ctrl->enable_plane(plane, enable); - - return 0; -} - -static int sync_handler(struct hwa742_request *req) -{ - complete(req->par.sync); - return REQ_COMPLETE; -} - -static void hwa742_sync(void) -{ - LIST_HEAD(req_list); - struct hwa742_request *req; - struct completion comp; - - req = alloc_req(); - - req->handler = sync_handler; - req->complete = NULL; - init_completion(&comp); - req->par.sync = ∁ - - list_add(&req->entry, &req_list); - submit_req_list(&req_list); - - wait_for_completion(&comp); -} - -static void hwa742_bind_client(struct omapfb_notifier_block *nb) -{ - dev_dbg(hwa742.fbdev->dev, "update_mode %d\n", hwa742.update_mode); - if (hwa742.update_mode == OMAPFB_MANUAL_UPDATE) { - omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY); - } -} - -static int hwa742_set_update_mode(enum omapfb_update_mode mode) -{ - if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE && - mode != OMAPFB_UPDATE_DISABLED) - return -EINVAL; - - if (mode == hwa742.update_mode) - return 0; - - dev_info(hwa742.fbdev->dev, "HWA742: setting update mode to %s\n", - mode == OMAPFB_UPDATE_DISABLED ? "disabled" : - (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual")); - - switch (hwa742.update_mode) { - case OMAPFB_MANUAL_UPDATE: - omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_DISABLED); - break; - case OMAPFB_AUTO_UPDATE: - hwa742.stop_auto_update = 1; - del_timer_sync(&hwa742.auto_update_timer); - break; - case OMAPFB_UPDATE_DISABLED: - break; - } - - hwa742.update_mode = mode; - hwa742_sync(); - hwa742.stop_auto_update = 0; - - switch (mode) { - case OMAPFB_MANUAL_UPDATE: - omapfb_notify_clients(hwa742.fbdev, OMAPFB_EVENT_READY); - break; - case OMAPFB_AUTO_UPDATE: - hwa742_update_window_auto(0); - break; - case OMAPFB_UPDATE_DISABLED: - break; - } - - return 0; -} - -static enum omapfb_update_mode hwa742_get_update_mode(void) -{ - return hwa742.update_mode; -} - -static unsigned long round_to_extif_ticks(unsigned long ps, int div) -{ - int bus_tick = hwa742.extif_clk_period * div; - return (ps + bus_tick - 1) / bus_tick * bus_tick; -} - -static int calc_reg_timing(unsigned long sysclk, int div) -{ - struct extif_timings *t; - unsigned long systim; - - /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, - * AccessTime 2 ns + 12.2 ns (regs), - * WEOffTime = WEOnTime + 1 ns, - * REOffTime = REOnTime + 16 ns (regs), - * CSOffTime = REOffTime + 1 ns - * ReadCycle = 2ns + 2*SYSCLK (regs), - * WriteCycle = 2*SYSCLK + 2 ns, - * CSPulseWidth = 10 ns */ - systim = 1000000000 / (sysclk / 1000); - dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps" - "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div); - - t = &hwa742.reg_timings; - memset(t, 0, sizeof(*t)); - t->clk_div = div; - t->cs_on_time = 0; - t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div); - t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); - t->re_off_time = round_to_extif_ticks(t->re_on_time + 16000, div); - t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); - t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); - if (t->we_cycle_time < t->we_off_time) - t->we_cycle_time = t->we_off_time; - t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); - if (t->re_cycle_time < t->re_off_time) - t->re_cycle_time = t->re_off_time; - t->cs_pulse_width = 0; - - dev_dbg(hwa742.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n", - t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); - dev_dbg(hwa742.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n", - t->we_on_time, t->we_off_time, t->re_cycle_time, - t->we_cycle_time); - dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n", - t->access_time, t->cs_pulse_width); - - return hwa742.extif->convert_timings(t); -} - -static int calc_lut_timing(unsigned long sysclk, int div) -{ - struct extif_timings *t; - unsigned long systim; - - /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns, - * AccessTime 2 ns + 4 * SYSCLK + 26 (lut), - * WEOffTime = WEOnTime + 1 ns, - * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut), - * CSOffTime = REOffTime + 1 ns - * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut), - * WriteCycle = 2*SYSCLK + 2 ns, - * CSPulseWidth = 10 ns - */ - systim = 1000000000 / (sysclk / 1000); - dev_dbg(hwa742.fbdev->dev, "HWA742 systim %lu ps extif_clk_period %u ps" - "extif_clk_div %d\n", systim, hwa742.extif_clk_period, div); - - t = &hwa742.lut_timings; - memset(t, 0, sizeof(*t)); - - t->clk_div = div; - - t->cs_on_time = 0; - t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div); - t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim + - 26000, div); - t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div); - t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim + - 26000, div); - t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div); - t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div); - if (t->we_cycle_time < t->we_off_time) - t->we_cycle_time = t->we_off_time; - t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div); - if (t->re_cycle_time < t->re_off_time) - t->re_cycle_time = t->re_off_time; - t->cs_pulse_width = 0; - - dev_dbg(hwa742.fbdev->dev, "[lut]cson %d csoff %d reon %d reoff %d\n", - t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); - dev_dbg(hwa742.fbdev->dev, "[lut]weon %d weoff %d recyc %d wecyc %d\n", - t->we_on_time, t->we_off_time, t->re_cycle_time, - t->we_cycle_time); - dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n", - t->access_time, t->cs_pulse_width); - - return hwa742.extif->convert_timings(t); -} - -static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div) -{ - int max_clk_div; - int div; - - hwa742.extif->get_clk_info(&hwa742.extif_clk_period, &max_clk_div); - for (div = 1; div < max_clk_div; div++) { - if (calc_reg_timing(sysclk, div) == 0) - break; - } - if (div >= max_clk_div) - goto err; - - *extif_mem_div = div; - - for (div = 1; div < max_clk_div; div++) { - if (calc_lut_timing(sysclk, div) == 0) - break; - } - - if (div >= max_clk_div) - goto err; - - return 0; - -err: - dev_err(hwa742.fbdev->dev, "can't setup timings\n"); - return -1; -} - -static void calc_hwa742_clk_rates(unsigned long ext_clk, - unsigned long *sys_clk, unsigned long *pix_clk) -{ - int pix_clk_src; - int sys_div = 0, sys_mul = 0; - int pix_div; - - pix_clk_src = hwa742_read_reg(HWA742_CLK_SRC_REG); - pix_div = ((pix_clk_src >> 3) & 0x1f) + 1; - if ((pix_clk_src & (0x3 << 1)) == 0) { - /* Source is the PLL */ - sys_div = (hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x3f) + 1; - sys_mul = (hwa742_read_reg(HWA742_PLL_4_REG) & 0x7f) + 1; - *sys_clk = ext_clk * sys_mul / sys_div; - } else /* else source is ext clk, or oscillator */ - *sys_clk = ext_clk; - - *pix_clk = *sys_clk / pix_div; /* HZ */ - dev_dbg(hwa742.fbdev->dev, - "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n", - ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul); - dev_dbg(hwa742.fbdev->dev, "sys_clk %ld pix_clk %ld\n", - *sys_clk, *pix_clk); -} - - -static int setup_tearsync(unsigned long pix_clk, int extif_div) -{ - int hdisp, vdisp; - int hndp, vndp; - int hsw, vsw; - int hs, vs; - int hs_pol_inv, vs_pol_inv; - int use_hsvs, use_ndp; - u8 b; - - hsw = hwa742_read_reg(HWA742_HS_W_REG); - vsw = hwa742_read_reg(HWA742_VS_W_REG); - hs_pol_inv = !(hsw & 0x80); - vs_pol_inv = !(vsw & 0x80); - hsw = hsw & 0x7f; - vsw = vsw & 0x3f; - - hdisp = (hwa742_read_reg(HWA742_H_DISP_REG) & 0x7f) * 8; - vdisp = hwa742_read_reg(HWA742_V_DISP_1_REG) + - ((hwa742_read_reg(HWA742_V_DISP_2_REG) & 0x3) << 8); - - hndp = hwa742_read_reg(HWA742_H_NDP_REG) & 0x7f; - vndp = hwa742_read_reg(HWA742_V_NDP_REG); - - /* time to transfer one pixel (16bpp) in ps */ - hwa742.pix_tx_time = hwa742.reg_timings.we_cycle_time; - if (hwa742.extif->get_max_tx_rate != NULL) { - /* - * The external interface might have a rate limitation, - * if so, we have to maximize our transfer rate. - */ - unsigned long min_tx_time; - unsigned long max_tx_rate = hwa742.extif->get_max_tx_rate(); - - dev_dbg(hwa742.fbdev->dev, "max_tx_rate %ld HZ\n", - max_tx_rate); - min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */ - if (hwa742.pix_tx_time < min_tx_time) - hwa742.pix_tx_time = min_tx_time; - } - - /* time to update one line in ps */ - hwa742.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000); - hwa742.line_upd_time *= 1000; - if (hdisp * hwa742.pix_tx_time > hwa742.line_upd_time) - /* - * transfer speed too low, we might have to use both - * HS and VS - */ - use_hsvs = 1; - else - /* decent transfer speed, we'll always use only VS */ - use_hsvs = 0; - - if (use_hsvs && (hs_pol_inv || vs_pol_inv)) { - /* - * HS or'ed with VS doesn't work, use the active high - * TE signal based on HNDP / VNDP - */ - use_ndp = 1; - hs_pol_inv = 0; - vs_pol_inv = 0; - hs = hndp; - vs = vndp; - } else { - /* - * Use HS or'ed with VS as a TE signal if both are needed - * or VNDP if only vsync is needed. - */ - use_ndp = 0; - hs = hsw; - vs = vsw; - if (!use_hsvs) { - hs_pol_inv = 0; - vs_pol_inv = 0; - } - } - - hs = hs * 1000000 / (pix_clk / 1000); /* ps */ - hs *= 1000; - - vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */ - vs *= 1000; - - if (vs <= hs) - return -EDOM; - /* set VS to 120% of HS to minimize VS detection time */ - vs = hs * 12 / 10; - /* minimize HS too */ - hs = 10000; - - b = hwa742_read_reg(HWA742_NDP_CTRL); - b &= ~0x3; - b |= use_hsvs ? 1 : 0; - b |= (use_ndp && use_hsvs) ? 0 : 2; - hwa742_write_reg(HWA742_NDP_CTRL, b); - - hwa742.vsync_only = !use_hsvs; - - dev_dbg(hwa742.fbdev->dev, - "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n", - pix_clk, hwa742.pix_tx_time, hwa742.line_upd_time); - dev_dbg(hwa742.fbdev->dev, - "hs %d ps vs %d ps mode %d vsync_only %d\n", - hs, vs, (b & 0x3), !use_hsvs); - - return hwa742.extif->setup_tearsync(1, hs, vs, - hs_pol_inv, vs_pol_inv, extif_div); -} - -static void hwa742_get_caps(int plane, struct omapfb_caps *caps) -{ - hwa742.int_ctrl->get_caps(plane, caps); - caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE | - OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE; - if (hwa742.te_connected) - caps->ctrl |= OMAPFB_CAPS_TEARSYNC; - caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) | - (1 << OMAPFB_COLOR_YUV420); -} - -static void hwa742_suspend(void) -{ - hwa742.update_mode_before_suspend = hwa742.update_mode; - hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); - /* Enable sleep mode */ - hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1); - clk_disable(hwa742.sys_ck); -} - -static void hwa742_resume(void) -{ - clk_enable(hwa742.sys_ck); - - /* Disable sleep mode */ - hwa742_write_reg(HWA742_POWER_SAVE, 0); - while (1) { - /* Loop until PLL output is stabilized */ - if (hwa742_read_reg(HWA742_PLL_DIV_REG) & (1 << 7)) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(5)); - } - hwa742_set_update_mode(hwa742.update_mode_before_suspend); -} - -static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, - struct omapfb_mem_desc *req_vram) -{ - int r = 0, i; - u8 rev, conf; - unsigned long ext_clk; - unsigned long sys_clk, pix_clk; - int extif_mem_div; - struct omapfb_platform_data *omapfb_conf; - struct hwa742_platform_data *ctrl_conf; - - BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl); - - hwa742.fbdev = fbdev; - hwa742.extif = fbdev->ext_if; - hwa742.int_ctrl = fbdev->int_ctrl; - - omapfb_conf = fbdev->dev->platform_data; - ctrl_conf = omapfb_conf->ctrl_platform_data; - - if (ctrl_conf == NULL) { - dev_err(fbdev->dev, "HWA742: missing platform data\n"); - r = -ENOENT; - goto err1; - } - - hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck"); - - spin_lock_init(&hwa742.req_lock); - - if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0) - goto err1; - - if ((r = hwa742.extif->init(fbdev)) < 0) - goto err2; - - ext_clk = clk_get_rate(hwa742.sys_ck); - if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0) - goto err3; - hwa742.extif->set_timings(&hwa742.reg_timings); - clk_enable(hwa742.sys_ck); - - calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk); - if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0) - goto err4; - hwa742.extif->set_timings(&hwa742.reg_timings); - - rev = hwa742_read_reg(HWA742_REV_CODE_REG); - if ((rev & 0xfc) != 0x80) { - dev_err(fbdev->dev, "HWA742: invalid revision %02x\n", rev); - r = -ENODEV; - goto err4; - } - - - if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) { - dev_err(fbdev->dev, - "HWA742: controller not initialized by the bootloader\n"); - r = -ENODEV; - goto err4; - } - - if (ctrl_conf->te_connected) { - if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) { - dev_err(hwa742.fbdev->dev, - "HWA742: can't setup tearing synchronization\n"); - goto err4; - } - hwa742.te_connected = 1; - } - - hwa742.max_transmit_size = hwa742.extif->max_transmit_size; - - hwa742.update_mode = OMAPFB_UPDATE_DISABLED; - - hwa742.auto_update_window.x = 0; - hwa742.auto_update_window.y = 0; - hwa742.auto_update_window.width = fbdev->panel->x_res; - hwa742.auto_update_window.height = fbdev->panel->y_res; - hwa742.auto_update_window.format = 0; - - init_timer(&hwa742.auto_update_timer); - hwa742.auto_update_timer.function = hwa742_update_window_auto; - hwa742.auto_update_timer.data = 0; - - hwa742.prev_color_mode = -1; - hwa742.prev_flags = 0; - - hwa742.fbdev = fbdev; - - INIT_LIST_HEAD(&hwa742.free_req_list); - INIT_LIST_HEAD(&hwa742.pending_req_list); - for (i = 0; i < ARRAY_SIZE(hwa742.req_pool); i++) - list_add(&hwa742.req_pool[i].entry, &hwa742.free_req_list); - BUG_ON(i <= IRQ_REQ_POOL_SIZE); - sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE); - - conf = hwa742_read_reg(HWA742_CONFIG_REG); - dev_info(fbdev->dev, ": Epson HWA742 LCD controller rev %d " - "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); - - return 0; -err4: - clk_disable(hwa742.sys_ck); -err3: - hwa742.extif->cleanup(); -err2: - hwa742.int_ctrl->cleanup(); -err1: - return r; -} - -static void hwa742_cleanup(void) -{ - hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); - hwa742.extif->cleanup(); - hwa742.int_ctrl->cleanup(); - clk_disable(hwa742.sys_ck); -} - -struct lcd_ctrl hwa742_ctrl = { - .name = "hwa742", - .init = hwa742_init, - .cleanup = hwa742_cleanup, - .bind_client = hwa742_bind_client, - .get_caps = hwa742_get_caps, - .set_update_mode = hwa742_set_update_mode, - .get_update_mode = hwa742_get_update_mode, - .setup_plane = hwa742_setup_plane, - .enable_plane = hwa742_enable_plane, - .update_window = hwa742_update_window_async, - .sync = hwa742_sync, - .suspend = hwa742_suspend, - .resume = hwa742_resume, -}; - diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c deleted file mode 100644 index 0fdd6f6873b..00000000000 --- a/drivers/video/omap/lcd_ams_delta.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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 <linux/lcd.h> - -#include <plat/board-ams-delta.h> -#include <mach/hardware.h> - -#include "omapfb.h" - -#define AMS_DELTA_DEFAULT_CONTRAST 112 - -#define AMS_DELTA_MAX_CONTRAST 0x00FF -#define AMS_DELTA_LCD_POWER 0x0100 - - -/* LCD class device section */ - -static int ams_delta_lcd; - -static int ams_delta_lcd_set_power(struct lcd_device *dev, int power) -{ - if (power == FB_BLANK_UNBLANK) { - if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER)) { - omap_writeb(ams_delta_lcd & AMS_DELTA_MAX_CONTRAST, - OMAP_PWL_ENABLE); - omap_writeb(1, OMAP_PWL_CLK_ENABLE); - ams_delta_lcd |= AMS_DELTA_LCD_POWER; - } - } else { - if (ams_delta_lcd & AMS_DELTA_LCD_POWER) { - omap_writeb(0, OMAP_PWL_ENABLE); - omap_writeb(0, OMAP_PWL_CLK_ENABLE); - ams_delta_lcd &= ~AMS_DELTA_LCD_POWER; - } - } - return 0; -} - -static int ams_delta_lcd_set_contrast(struct lcd_device *dev, int value) -{ - if ((value >= 0) && (value <= AMS_DELTA_MAX_CONTRAST)) { - omap_writeb(value, OMAP_PWL_ENABLE); - ams_delta_lcd &= ~AMS_DELTA_MAX_CONTRAST; - ams_delta_lcd |= value; - } - return 0; -} - -#ifdef CONFIG_LCD_CLASS_DEVICE -static int ams_delta_lcd_get_power(struct lcd_device *dev) -{ - if (ams_delta_lcd & AMS_DELTA_LCD_POWER) - return FB_BLANK_UNBLANK; - else - return FB_BLANK_POWERDOWN; -} - -static int ams_delta_lcd_get_contrast(struct lcd_device *dev) -{ - if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER)) - return 0; - - return ams_delta_lcd & AMS_DELTA_MAX_CONTRAST; -} - -static struct lcd_ops ams_delta_lcd_ops = { - .get_power = ams_delta_lcd_get_power, - .set_power = ams_delta_lcd_set_power, - .get_contrast = ams_delta_lcd_get_contrast, - .set_contrast = ams_delta_lcd_set_contrast, -}; -#endif - - -/* omapfb panel section */ - -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); - 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, -}; - - -/* platform driver section */ - -static int ams_delta_panel_probe(struct platform_device *pdev) -{ - struct lcd_device *lcd_device = NULL; -#ifdef CONFIG_LCD_CLASS_DEVICE - int ret; - - lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL, - &ams_delta_lcd_ops); - - if (IS_ERR(lcd_device)) { - ret = PTR_ERR(lcd_device); - dev_err(&pdev->dev, "failed to register device\n"); - return ret; - } - - platform_set_drvdata(pdev, lcd_device); - lcd_device->props.max_contrast = AMS_DELTA_MAX_CONTRAST; -#endif - - ams_delta_lcd_set_contrast(lcd_device, AMS_DELTA_DEFAULT_CONTRAST); - ams_delta_lcd_set_power(lcd_device, FB_BLANK_UNBLANK); - - 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, - pm_message_t mesg) -{ - return 0; -} - -static int ams_delta_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver ams_delta_panel_driver = { - .probe = ams_delta_panel_probe, - .remove = ams_delta_panel_remove, - .suspend = ams_delta_panel_suspend, - .resume = ams_delta_panel_resume, - .driver = { - .name = "lcd_ams_delta", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(ams_delta_panel_driver); diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c deleted file mode 100644 index 49bdeca81e5..00000000000 --- a/drivers/video/omap/lcd_h3.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * LCD panel support for the TI OMAP H3 board - * - * 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. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/i2c/tps65010.h> - -#include <asm/gpio.h> -#include "omapfb.h" - -#define MODULE_NAME "omapfb-lcd_h3" - -static int h3_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) -{ - return 0; -} - -static void h3_panel_cleanup(struct lcd_panel *panel) -{ -} - -static int h3_panel_enable(struct lcd_panel *panel) -{ - int r = 0; - - /* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */ - r = tps65010_set_gpio_out_value(GPIO1, HIGH); - if (!r) - r = tps65010_set_gpio_out_value(GPIO2, HIGH); - if (r) - pr_err(MODULE_NAME ": Unable to turn on LCD panel\n"); - - return r; -} - -static void h3_panel_disable(struct lcd_panel *panel) -{ - int r = 0; - - /* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */ - r = tps65010_set_gpio_out_value(GPIO1, LOW); - if (!r) - tps65010_set_gpio_out_value(GPIO2, LOW); - if (r) - pr_err(MODULE_NAME ": Unable to turn off LCD panel\n"); -} - -static unsigned long h3_panel_get_caps(struct lcd_panel *panel) -{ - return 0; -} - -struct lcd_panel h3_panel = { - .name = "h3", - .config = OMAP_LCDC_PANEL_TFT, - - .data_lines = 16, - .bpp = 16, - .x_res = 240, - .y_res = 320, - .pixel_clock = 12000, - .hsw = 12, - .hfp = 14, - .hbp = 72 - 12, - .vsw = 1, - .vfp = 1, - .vbp = 0, - .pcd = 0, - - .init = h3_panel_init, - .cleanup = h3_panel_cleanup, - .enable = h3_panel_enable, - .disable = h3_panel_disable, - .get_caps = h3_panel_get_caps, -}; - -static int h3_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&h3_panel); - return 0; -} - -static int h3_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int h3_panel_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - return 0; -} - -static int h3_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver h3_panel_driver = { - .probe = h3_panel_probe, - .remove = h3_panel_remove, - .suspend = h3_panel_suspend, - .resume = h3_panel_resume, - .driver = { - .name = "lcd_h3", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(h3_panel_driver); diff --git a/drivers/video/omap/lcd_htcherald.c b/drivers/video/omap/lcd_htcherald.c deleted file mode 100644 index 20f477851d5..00000000000 --- a/drivers/video/omap/lcd_htcherald.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * File: drivers/video/omap/lcd-htcherald.c - * - * LCD panel support for the HTC Herald - * - * Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com> - * Copyright (C) 2009 Wing Linux - * - * Based on the lcd_htcwizard.c file from the linwizard project: - * Copyright (C) linwizard.sourceforge.net - * Author: Angelo Arrifano <miknix@gmail.com> - * Based on lcd_h4 by 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. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> - -#include "omapfb.h" - -static int htcherald_panel_init(struct lcd_panel *panel, - struct omapfb_device *fbdev) -{ - return 0; -} - -static void htcherald_panel_cleanup(struct lcd_panel *panel) -{ -} - -static int htcherald_panel_enable(struct lcd_panel *panel) -{ - return 0; -} - -static void htcherald_panel_disable(struct lcd_panel *panel) -{ -} - -static unsigned long htcherald_panel_get_caps(struct lcd_panel *panel) -{ - return 0; -} - -/* Found on WIZ200 (miknix) and some HERA110 models (darkstar62) */ -struct lcd_panel htcherald_panel_1 = { - .name = "lcd_herald", - .config = OMAP_LCDC_PANEL_TFT | - OMAP_LCDC_INV_HSYNC | - OMAP_LCDC_INV_VSYNC | - OMAP_LCDC_INV_PIX_CLOCK, - .bpp = 16, - .data_lines = 16, - .x_res = 240, - .y_res = 320, - .pixel_clock = 6093, - .pcd = 0, /* 15 */ - .hsw = 10, - .hfp = 10, - .hbp = 20, - .vsw = 3, - .vfp = 2, - .vbp = 2, - - .init = htcherald_panel_init, - .cleanup = htcherald_panel_cleanup, - .enable = htcherald_panel_enable, - .disable = htcherald_panel_disable, - .get_caps = htcherald_panel_get_caps, -}; - -static int htcherald_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&htcherald_panel_1); - return 0; -} - -static int htcherald_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int htcherald_panel_suspend(struct platform_device *pdev, - pm_message_t mesg) -{ - return 0; -} - -static int htcherald_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver htcherald_panel_driver = { - .probe = htcherald_panel_probe, - .remove = htcherald_panel_remove, - .suspend = htcherald_panel_suspend, - .resume = htcherald_panel_resume, - .driver = { - .name = "lcd_htcherald", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(htcherald_panel_driver); diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c deleted file mode 100644 index b38b1dd15ce..00000000000 --- a/drivers/video/omap/lcd_inn1510.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * LCD panel support for the TI OMAP1510 Innovator board - * - * 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. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/io.h> - -#include <plat/fpga.h> -#include "omapfb.h" - -static int innovator1510_panel_init(struct lcd_panel *panel, - struct omapfb_device *fbdev) -{ - return 0; -} - -static void innovator1510_panel_cleanup(struct lcd_panel *panel) -{ -} - -static int innovator1510_panel_enable(struct lcd_panel *panel) -{ - fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL); - return 0; -} - -static void innovator1510_panel_disable(struct lcd_panel *panel) -{ - fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL); -} - -static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel) -{ - return 0; -} - -struct lcd_panel innovator1510_panel = { - .name = "inn1510", - .config = OMAP_LCDC_PANEL_TFT, - - .bpp = 16, - .data_lines = 16, - .x_res = 240, - .y_res = 320, - .pixel_clock = 12500, - .hsw = 40, - .hfp = 40, - .hbp = 72, - .vsw = 1, - .vfp = 1, - .vbp = 0, - .pcd = 12, - - .init = innovator1510_panel_init, - .cleanup = innovator1510_panel_cleanup, - .enable = innovator1510_panel_enable, - .disable = innovator1510_panel_disable, - .get_caps = innovator1510_panel_get_caps, -}; - -static int innovator1510_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&innovator1510_panel); - return 0; -} - -static int innovator1510_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int innovator1510_panel_suspend(struct platform_device *pdev, - pm_message_t mesg) -{ - return 0; -} - -static int innovator1510_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver innovator1510_panel_driver = { - .probe = innovator1510_panel_probe, - .remove = innovator1510_panel_remove, - .suspend = innovator1510_panel_suspend, - .resume = innovator1510_panel_resume, - .driver = { - .name = "lcd_inn1510", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(innovator1510_panel_driver); diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c deleted file mode 100644 index 7e8bd8e08a9..00000000000 --- a/drivers/video/omap/lcd_inn1610.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * LCD panel support for the TI OMAP1610 Innovator board - * - * 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. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> - -#include <asm/gpio.h> -#include "omapfb.h" - -#define MODULE_NAME "omapfb-lcd_h3" - -static int innovator1610_panel_init(struct lcd_panel *panel, - struct omapfb_device *fbdev) -{ - int r = 0; - - if (gpio_request(14, "lcd_en0")) { - pr_err(MODULE_NAME ": can't request GPIO 14\n"); - r = -1; - goto exit; - } - if (gpio_request(15, "lcd_en1")) { - pr_err(MODULE_NAME ": can't request GPIO 15\n"); - gpio_free(14); - r = -1; - goto exit; - } - /* configure GPIO(14, 15) as outputs */ - gpio_direction_output(14, 0); - gpio_direction_output(15, 0); -exit: - return r; -} - -static void innovator1610_panel_cleanup(struct lcd_panel *panel) -{ - gpio_free(15); - gpio_free(14); -} - -static int innovator1610_panel_enable(struct lcd_panel *panel) -{ - /* set GPIO14 and GPIO15 high */ - gpio_set_value(14, 1); - gpio_set_value(15, 1); - return 0; -} - -static void innovator1610_panel_disable(struct lcd_panel *panel) -{ - /* set GPIO13, GPIO14 and GPIO15 low */ - gpio_set_value(14, 0); - gpio_set_value(15, 0); -} - -static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel) -{ - return 0; -} - -struct lcd_panel innovator1610_panel = { - .name = "inn1610", - .config = OMAP_LCDC_PANEL_TFT, - - .bpp = 16, - .data_lines = 16, - .x_res = 320, - .y_res = 240, - .pixel_clock = 12500, - .hsw = 40, - .hfp = 40, - .hbp = 72, - .vsw = 1, - .vfp = 1, - .vbp = 0, - .pcd = 12, - - .init = innovator1610_panel_init, - .cleanup = innovator1610_panel_cleanup, - .enable = innovator1610_panel_enable, - .disable = innovator1610_panel_disable, - .get_caps = innovator1610_panel_get_caps, -}; - -static int innovator1610_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&innovator1610_panel); - return 0; -} - -static int innovator1610_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int innovator1610_panel_suspend(struct platform_device *pdev, - pm_message_t mesg) -{ - return 0; -} - -static int innovator1610_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver innovator1610_panel_driver = { - .probe = innovator1610_panel_probe, - .remove = innovator1610_panel_remove, - .suspend = innovator1610_panel_suspend, - .resume = innovator1610_panel_resume, - .driver = { - .name = "lcd_inn1610", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(innovator1610_panel_driver); diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c deleted file mode 100644 index 8d546dd55e8..00000000000 --- a/drivers/video/omap/lcd_mipid.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * LCD driver for MIPI DBI-C / DCS compatible LCDs - * - * Copyright (C) 2006 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. - */ -#include <linux/device.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/workqueue.h> -#include <linux/spi/spi.h> -#include <linux/module.h> - -#include <plat/lcd_mipid.h> - -#include "omapfb.h" - -#define MIPID_MODULE_NAME "lcd_mipid" - -#define MIPID_CMD_READ_DISP_ID 0x04 -#define MIPID_CMD_READ_RED 0x06 -#define MIPID_CMD_READ_GREEN 0x07 -#define MIPID_CMD_READ_BLUE 0x08 -#define MIPID_CMD_READ_DISP_STATUS 0x09 -#define MIPID_CMD_RDDSDR 0x0F -#define MIPID_CMD_SLEEP_IN 0x10 -#define MIPID_CMD_SLEEP_OUT 0x11 -#define MIPID_CMD_DISP_OFF 0x28 -#define MIPID_CMD_DISP_ON 0x29 - -#define MIPID_ESD_CHECK_PERIOD msecs_to_jiffies(5000) - -#define to_mipid_device(p) container_of(p, struct mipid_device, \ - panel) -struct mipid_device { - int enabled; - int revision; - unsigned int saved_bklight_level; - unsigned long hw_guard_end; /* next value of jiffies - when we can issue the - next sleep in/out command */ - unsigned long hw_guard_wait; /* max guard time in jiffies */ - - struct omapfb_device *fbdev; - struct spi_device *spi; - struct mutex mutex; - struct lcd_panel panel; - - struct workqueue_struct *esd_wq; - struct delayed_work esd_work; - void (*esd_check)(struct mipid_device *m); -}; - -static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf, - int wlen, u8 *rbuf, int rlen) -{ - struct spi_message m; - struct spi_transfer *x, xfer[4]; - u16 w; - int r; - - BUG_ON(md->spi == NULL); - - spi_message_init(&m); - - memset(xfer, 0, sizeof(xfer)); - x = &xfer[0]; - - cmd &= 0xff; - x->tx_buf = &cmd; - x->bits_per_word = 9; - x->len = 2; - spi_message_add_tail(x, &m); - - if (wlen) { - x++; - x->tx_buf = wbuf; - x->len = wlen; - x->bits_per_word = 9; - spi_message_add_tail(x, &m); - } - - if (rlen) { - x++; - x->rx_buf = &w; - x->len = 1; - spi_message_add_tail(x, &m); - - if (rlen > 1) { - /* Arrange for the extra clock before the first - * data bit. - */ - x->bits_per_word = 9; - x->len = 2; - - x++; - x->rx_buf = &rbuf[1]; - x->len = rlen - 1; - spi_message_add_tail(x, &m); - } - } - - r = spi_sync(md->spi, &m); - if (r < 0) - dev_dbg(&md->spi->dev, "spi_sync %d\n", r); - - if (rlen) - rbuf[0] = w & 0xff; -} - -static inline void mipid_cmd(struct mipid_device *md, int cmd) -{ - mipid_transfer(md, cmd, NULL, 0, NULL, 0); -} - -static inline void mipid_write(struct mipid_device *md, - int reg, const u8 *buf, int len) -{ - mipid_transfer(md, reg, buf, len, NULL, 0); -} - -static inline void mipid_read(struct mipid_device *md, - int reg, u8 *buf, int len) -{ - mipid_transfer(md, reg, NULL, 0, buf, len); -} - -static void set_data_lines(struct mipid_device *md, int data_lines) -{ - u16 par; - - switch (data_lines) { - case 16: - par = 0x150; - break; - case 18: - par = 0x160; - break; - case 24: - par = 0x170; - break; - } - mipid_write(md, 0x3a, (u8 *)&par, 2); -} - -static void send_init_string(struct mipid_device *md) -{ - u16 initpar[] = { 0x0102, 0x0100, 0x0100 }; - - mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar)); - set_data_lines(md, md->panel.data_lines); -} - -static void hw_guard_start(struct mipid_device *md, int guard_msec) -{ - md->hw_guard_wait = msecs_to_jiffies(guard_msec); - md->hw_guard_end = jiffies + md->hw_guard_wait; -} - -static void hw_guard_wait(struct mipid_device *md) -{ - unsigned long wait = md->hw_guard_end - jiffies; - - if ((long)wait > 0 && wait <= md->hw_guard_wait) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(wait); - } -} - -static void set_sleep_mode(struct mipid_device *md, int on) -{ - int cmd, sleep_time = 50; - - if (on) - cmd = MIPID_CMD_SLEEP_IN; - else - cmd = MIPID_CMD_SLEEP_OUT; - hw_guard_wait(md); - mipid_cmd(md, cmd); - hw_guard_start(md, 120); - /* - * When we enable the panel, it seems we _have_ to sleep - * 120 ms before sending the init string. When disabling the - * panel we'll sleep for the duration of 2 frames, so that the - * controller can still provide the PCLK,HS,VS signals. - */ - if (!on) - sleep_time = 120; - msleep(sleep_time); -} - -static void set_display_state(struct mipid_device *md, int enabled) -{ - int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF; - - mipid_cmd(md, cmd); -} - -static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level) -{ - struct mipid_device *md = to_mipid_device(panel); - struct mipid_platform_data *pd = md->spi->dev.platform_data; - - if (pd->get_bklight_max == NULL || pd->set_bklight_level == NULL) - return -ENODEV; - if (level > pd->get_bklight_max(pd)) - return -EINVAL; - if (!md->enabled) { - md->saved_bklight_level = level; - return 0; - } - pd->set_bklight_level(pd, level); - - return 0; -} - -static unsigned int mipid_get_bklight_level(struct lcd_panel *panel) -{ - struct mipid_device *md = to_mipid_device(panel); - struct mipid_platform_data *pd = md->spi->dev.platform_data; - - if (pd->get_bklight_level == NULL) - return -ENODEV; - return pd->get_bklight_level(pd); -} - -static unsigned int mipid_get_bklight_max(struct lcd_panel *panel) -{ - struct mipid_device *md = to_mipid_device(panel); - struct mipid_platform_data *pd = md->spi->dev.platform_data; - - if (pd->get_bklight_max == NULL) - return -ENODEV; - - return pd->get_bklight_max(pd); -} - -static unsigned long mipid_get_caps(struct lcd_panel *panel) -{ - return OMAPFB_CAPS_SET_BACKLIGHT; -} - -static u16 read_first_pixel(struct mipid_device *md) -{ - u16 pixel; - u8 red, green, blue; - - mutex_lock(&md->mutex); - mipid_read(md, MIPID_CMD_READ_RED, &red, 1); - mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1); - mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1); - mutex_unlock(&md->mutex); - - switch (md->panel.data_lines) { - case 16: - pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1); - break; - case 24: - /* 24 bit -> 16 bit */ - pixel = ((red >> 3) << 11) | ((green >> 2) << 5) | - (blue >> 3); - break; - default: - pixel = 0; - BUG(); - } - - return pixel; -} - -static int mipid_run_test(struct lcd_panel *panel, int test_num) -{ - struct mipid_device *md = to_mipid_device(panel); - static const u16 test_values[4] = { - 0x0000, 0xffff, 0xaaaa, 0x5555, - }; - int i; - - if (test_num != MIPID_TEST_RGB_LINES) - return MIPID_TEST_INVALID; - - for (i = 0; i < ARRAY_SIZE(test_values); i++) { - int delay; - unsigned long tmo; - - omapfb_write_first_pixel(md->fbdev, test_values[i]); - tmo = jiffies + msecs_to_jiffies(100); - delay = 25; - while (1) { - u16 pixel; - - msleep(delay); - pixel = read_first_pixel(md); - if (pixel == test_values[i]) - break; - if (time_after(jiffies, tmo)) { - dev_err(&md->spi->dev, - "MIPI LCD RGB I/F test failed: " - "expecting %04x, got %04x\n", - test_values[i], pixel); - return MIPID_TEST_FAILED; - } - delay = 10; - } - } - - return 0; -} - -static void ls041y3_esd_recover(struct mipid_device *md) -{ - dev_err(&md->spi->dev, "performing LCD ESD recovery\n"); - set_sleep_mode(md, 1); - set_sleep_mode(md, 0); -} - -static void ls041y3_esd_check_mode1(struct mipid_device *md) -{ - u8 state1, state2; - - mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1); - set_sleep_mode(md, 0); - mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1); - dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n", - state1, state2); - /* Each sleep out command will trigger a self diagnostic and flip - * Bit6 if the test passes. - */ - if (!((state1 ^ state2) & (1 << 6))) - ls041y3_esd_recover(md); -} - -static void ls041y3_esd_check_mode2(struct mipid_device *md) -{ - int i; - u8 rbuf[2]; - static const struct { - int cmd; - int wlen; - u16 wbuf[3]; - } *rd, rd_ctrl[7] = { - { 0xb0, 4, { 0x0101, 0x01fe, } }, - { 0xb1, 4, { 0x01de, 0x0121, } }, - { 0xc2, 4, { 0x0100, 0x0100, } }, - { 0xbd, 2, { 0x0100, } }, - { 0xc2, 4, { 0x01fc, 0x0103, } }, - { 0xb4, 0, }, - { 0x00, 0, }, - }; - - rd = rd_ctrl; - for (i = 0; i < 3; i++, rd++) - mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen); - - udelay(10); - mipid_read(md, rd->cmd, rbuf, 2); - rd++; - - for (i = 0; i < 3; i++, rd++) { - udelay(10); - mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen); - } - - dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]); - if (rbuf[1] == 0x00) - ls041y3_esd_recover(md); -} - -static void ls041y3_esd_check(struct mipid_device *md) -{ - ls041y3_esd_check_mode1(md); - if (md->revision >= 0x88) - ls041y3_esd_check_mode2(md); -} - -static void mipid_esd_start_check(struct mipid_device *md) -{ - if (md->esd_check != NULL) - queue_delayed_work(md->esd_wq, &md->esd_work, - MIPID_ESD_CHECK_PERIOD); -} - -static void mipid_esd_stop_check(struct mipid_device *md) -{ - if (md->esd_check != NULL) - cancel_delayed_work_sync(&md->esd_work); -} - -static void mipid_esd_work(struct work_struct *work) -{ - struct mipid_device *md = container_of(work, struct mipid_device, - esd_work.work); - - mutex_lock(&md->mutex); - md->esd_check(md); - mutex_unlock(&md->mutex); - mipid_esd_start_check(md); -} - -static int mipid_enable(struct lcd_panel *panel) -{ - struct mipid_device *md = to_mipid_device(panel); - - mutex_lock(&md->mutex); - - if (md->enabled) { - mutex_unlock(&md->mutex); - return 0; - } - set_sleep_mode(md, 0); - md->enabled = 1; - send_init_string(md); - set_display_state(md, 1); - mipid_set_bklight_level(panel, md->saved_bklight_level); - mipid_esd_start_check(md); - - mutex_unlock(&md->mutex); - return 0; -} - -static void mipid_disable(struct lcd_panel *panel) -{ - struct mipid_device *md = to_mipid_device(panel); - - /* - * A final ESD work might be called before returning, - * so do this without holding the lock. - */ - mipid_esd_stop_check(md); - mutex_lock(&md->mutex); - - if (!md->enabled) { - mutex_unlock(&md->mutex); - return; - } - md->saved_bklight_level = mipid_get_bklight_level(panel); - mipid_set_bklight_level(panel, 0); - set_display_state(md, 0); - set_sleep_mode(md, 1); - md->enabled = 0; - - mutex_unlock(&md->mutex); -} - -static int panel_enabled(struct mipid_device *md) -{ - u32 disp_status; - int enabled; - - mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4); - disp_status = __be32_to_cpu(disp_status); - enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10)); - dev_dbg(&md->spi->dev, - "LCD panel %senabled by bootloader (status 0x%04x)\n", - enabled ? "" : "not ", disp_status); - return enabled; -} - -static int mipid_init(struct lcd_panel *panel, - struct omapfb_device *fbdev) -{ - struct mipid_device *md = to_mipid_device(panel); - - md->fbdev = fbdev; - md->esd_wq = create_singlethread_workqueue("mipid_esd"); - if (md->esd_wq == NULL) { - dev_err(&md->spi->dev, "can't create ESD workqueue\n"); - return -ENOMEM; - } - INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work); - mutex_init(&md->mutex); - - md->enabled = panel_enabled(md); - - if (md->enabled) - mipid_esd_start_check(md); - else - md->saved_bklight_level = mipid_get_bklight_level(panel); - - return 0; -} - -static void mipid_cleanup(struct lcd_panel *panel) -{ - struct mipid_device *md = to_mipid_device(panel); - - if (md->enabled) - mipid_esd_stop_check(md); - destroy_workqueue(md->esd_wq); -} - -static struct lcd_panel mipid_panel = { - .config = OMAP_LCDC_PANEL_TFT, - - .bpp = 16, - .x_res = 800, - .y_res = 480, - .pixel_clock = 21940, - .hsw = 50, - .hfp = 20, - .hbp = 15, - .vsw = 2, - .vfp = 1, - .vbp = 3, - - .init = mipid_init, - .cleanup = mipid_cleanup, - .enable = mipid_enable, - .disable = mipid_disable, - .get_caps = mipid_get_caps, - .set_bklight_level = mipid_set_bklight_level, - .get_bklight_level = mipid_get_bklight_level, - .get_bklight_max = mipid_get_bklight_max, - .run_test = mipid_run_test, -}; - -static int mipid_detect(struct mipid_device *md) -{ - struct mipid_platform_data *pdata; - u8 display_id[3]; - - pdata = md->spi->dev.platform_data; - if (pdata == NULL) { - dev_err(&md->spi->dev, "missing platform data\n"); - return -ENOENT; - } - - mipid_read(md, MIPID_CMD_READ_DISP_ID, display_id, 3); - dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n", - display_id[0], display_id[1], display_id[2]); - - switch (display_id[0]) { - case 0x45: - md->panel.name = "lph8923"; - break; - case 0x83: - md->panel.name = "ls041y3"; - md->esd_check = ls041y3_esd_check; - break; - default: - md->panel.name = "unknown"; - dev_err(&md->spi->dev, "invalid display ID\n"); - return -ENODEV; - } - - md->revision = display_id[1]; - md->panel.data_lines = pdata->data_lines; - pr_info("omapfb: %s rev %02x LCD detected, %d data lines\n", - md->panel.name, md->revision, md->panel.data_lines); - - return 0; -} - -static int mipid_spi_probe(struct spi_device *spi) -{ - struct mipid_device *md; - int r; - - md = kzalloc(sizeof(*md), GFP_KERNEL); - if (md == NULL) { - dev_err(&spi->dev, "out of memory\n"); - return -ENOMEM; - } - - spi->mode = SPI_MODE_0; - md->spi = spi; - dev_set_drvdata(&spi->dev, md); - md->panel = mipid_panel; - - r = mipid_detect(md); - if (r < 0) - return r; - - omapfb_register_panel(&md->panel); - - return 0; -} - -static int mipid_spi_remove(struct spi_device *spi) -{ - struct mipid_device *md = dev_get_drvdata(&spi->dev); - - mipid_disable(&md->panel); - kfree(md); - - return 0; -} - -static struct spi_driver mipid_spi_driver = { - .driver = { - .name = MIPID_MODULE_NAME, - .owner = THIS_MODULE, - }, - .probe = mipid_spi_probe, - .remove = __devexit_p(mipid_spi_remove), -}; - -static int __init mipid_drv_init(void) -{ - spi_register_driver(&mipid_spi_driver); - - return 0; -} -module_init(mipid_drv_init); - -static void __exit mipid_drv_cleanup(void) -{ - spi_unregister_driver(&mipid_spi_driver); -} -module_exit(mipid_drv_cleanup); - -MODULE_DESCRIPTION("MIPI display driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c deleted file mode 100644 index 5914220dfa9..00000000000 --- a/drivers/video/omap/lcd_osk.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * LCD panel support for the TI OMAP OSK board - * - * Copyright (C) 2004 Nokia Corporation - * Author: Imre Deak <imre.deak@nokia.com> - * Adapted for OSK by <dirk.behme@de.bosch.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. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> - -#include <asm/gpio.h> -#include <plat/mux.h> -#include "omapfb.h" - -static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) -{ - /* gpio2 was allocated in board init */ - return 0; -} - -static void osk_panel_cleanup(struct lcd_panel *panel) -{ -} - -static int osk_panel_enable(struct lcd_panel *panel) -{ - /* configure PWL pin */ - omap_cfg_reg(PWL); - - /* Enable PWL unit */ - omap_writeb(0x01, OMAP_PWL_CLK_ENABLE); - - /* Set PWL level */ - omap_writeb(0xFF, OMAP_PWL_ENABLE); - - /* set GPIO2 high (lcd power enabled) */ - gpio_set_value(2, 1); - - return 0; -} - -static void osk_panel_disable(struct lcd_panel *panel) -{ - /* Set PWL level to zero */ - omap_writeb(0x00, OMAP_PWL_ENABLE); - - /* Disable PWL unit */ - omap_writeb(0x00, OMAP_PWL_CLK_ENABLE); - - /* set GPIO2 low */ - gpio_set_value(2, 0); -} - -static unsigned long osk_panel_get_caps(struct lcd_panel *panel) -{ - return 0; -} - -struct lcd_panel osk_panel = { - .name = "osk", - .config = OMAP_LCDC_PANEL_TFT, - - .bpp = 16, - .data_lines = 16, - .x_res = 240, - .y_res = 320, - .pixel_clock = 12500, - .hsw = 40, - .hfp = 40, - .hbp = 72, - .vsw = 1, - .vfp = 1, - .vbp = 0, - .pcd = 12, - - .init = osk_panel_init, - .cleanup = osk_panel_cleanup, - .enable = osk_panel_enable, - .disable = osk_panel_disable, - .get_caps = osk_panel_get_caps, -}; - -static int osk_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&osk_panel); - return 0; -} - -static int osk_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int osk_panel_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - return 0; -} - -static int osk_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver osk_panel_driver = { - .probe = osk_panel_probe, - .remove = osk_panel_remove, - .suspend = osk_panel_suspend, - .resume = osk_panel_resume, - .driver = { - .name = "lcd_osk", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(osk_panel_driver); diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c deleted file mode 100644 index 88c31eb0cd6..00000000000 --- a/drivers/video/omap/lcd_palmte.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * LCD panel support for the Palm Tungsten E - * - * Original version : Romain Goyet <r.goyet@gmail.com> - * Current version : Laurent Gonzalez <palmte.linux@free.fr> - * - * 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 <plat/fpga.h> -#include "omapfb.h" - -static int palmte_panel_init(struct lcd_panel *panel, - struct omapfb_device *fbdev) -{ - return 0; -} - -static void palmte_panel_cleanup(struct lcd_panel *panel) -{ -} - -static int palmte_panel_enable(struct lcd_panel *panel) -{ - return 0; -} - -static void palmte_panel_disable(struct lcd_panel *panel) -{ -} - -static unsigned long palmte_panel_get_caps(struct lcd_panel *panel) -{ - return 0; -} - -struct lcd_panel palmte_panel = { - .name = "palmte", - .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | - OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE | - OMAP_LCDC_HSVS_OPPOSITE, - - .data_lines = 16, - .bpp = 8, - .pixel_clock = 12000, - .x_res = 320, - .y_res = 320, - .hsw = 4, - .hfp = 8, - .hbp = 28, - .vsw = 1, - .vfp = 8, - .vbp = 7, - .pcd = 0, - - .init = palmte_panel_init, - .cleanup = palmte_panel_cleanup, - .enable = palmte_panel_enable, - .disable = palmte_panel_disable, - .get_caps = palmte_panel_get_caps, -}; - -static int palmte_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&palmte_panel); - return 0; -} - -static int palmte_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int palmte_panel_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - return 0; -} - -static int palmte_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver palmte_panel_driver = { - .probe = palmte_panel_probe, - .remove = palmte_panel_remove, - .suspend = palmte_panel_suspend, - .resume = palmte_panel_resume, - .driver = { - .name = "lcd_palmte", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(palmte_panel_driver); diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c deleted file mode 100644 index aaf3c8ba124..00000000000 --- a/drivers/video/omap/lcd_palmtt.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * LCD panel support for Palm Tungsten|T - * Current version : Marek Vasut <marek.vasut@gmail.com> - * - * Modified from lcd_inn1510.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. - */ - -/* -GPIO11 - backlight -GPIO12 - screen blanking -GPIO13 - screen blanking -*/ - -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/io.h> - -#include <asm/gpio.h> -#include "omapfb.h" - -static int palmtt_panel_init(struct lcd_panel *panel, - struct omapfb_device *fbdev) -{ - return 0; -} - -static void palmtt_panel_cleanup(struct lcd_panel *panel) -{ -} - -static int palmtt_panel_enable(struct lcd_panel *panel) -{ - return 0; -} - -static void palmtt_panel_disable(struct lcd_panel *panel) -{ -} - -static unsigned long palmtt_panel_get_caps(struct lcd_panel *panel) -{ - return OMAPFB_CAPS_SET_BACKLIGHT; -} - -struct lcd_panel palmtt_panel = { - .name = "palmtt", - .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | - OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE | - OMAP_LCDC_HSVS_OPPOSITE, - .bpp = 16, - .data_lines = 16, - .x_res = 320, - .y_res = 320, - .pixel_clock = 10000, - .hsw = 4, - .hfp = 8, - .hbp = 28, - .vsw = 1, - .vfp = 8, - .vbp = 7, - .pcd = 0, - - .init = palmtt_panel_init, - .cleanup = palmtt_panel_cleanup, - .enable = palmtt_panel_enable, - .disable = palmtt_panel_disable, - .get_caps = palmtt_panel_get_caps, -}; - -static int palmtt_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&palmtt_panel); - return 0; -} - -static int palmtt_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int palmtt_panel_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - return 0; -} - -static int palmtt_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver palmtt_panel_driver = { - .probe = palmtt_panel_probe, - .remove = palmtt_panel_remove, - .suspend = palmtt_panel_suspend, - .resume = palmtt_panel_resume, - .driver = { - .name = "lcd_palmtt", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(palmtt_panel_driver); diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c deleted file mode 100644 index 3b7d8aa1cf3..00000000000 --- a/drivers/video/omap/lcd_palmz71.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * LCD panel support for the Palm Zire71 - * - * Original version : Romain Goyet - * Current version : Laurent Gonzalez - * Modified for zire71 : Marek Vasut - * - * 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 "omapfb.h" - -static int palmz71_panel_init(struct lcd_panel *panel, - struct omapfb_device *fbdev) -{ - return 0; -} - -static void palmz71_panel_cleanup(struct lcd_panel *panel) -{ - -} - -static int palmz71_panel_enable(struct lcd_panel *panel) -{ - return 0; -} - -static void palmz71_panel_disable(struct lcd_panel *panel) -{ -} - -static unsigned long palmz71_panel_get_caps(struct lcd_panel *panel) -{ - return OMAPFB_CAPS_SET_BACKLIGHT; -} - -struct lcd_panel palmz71_panel = { - .name = "palmz71", - .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | - OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE | - OMAP_LCDC_HSVS_OPPOSITE, - .data_lines = 16, - .bpp = 16, - .pixel_clock = 24000, - .x_res = 320, - .y_res = 320, - .hsw = 4, - .hfp = 8, - .hbp = 28, - .vsw = 1, - .vfp = 8, - .vbp = 7, - .pcd = 0, - - .init = palmz71_panel_init, - .cleanup = palmz71_panel_cleanup, - .enable = palmz71_panel_enable, - .disable = palmz71_panel_disable, - .get_caps = palmz71_panel_get_caps, -}; - -static int palmz71_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&palmz71_panel); - return 0; -} - -static int palmz71_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int palmz71_panel_suspend(struct platform_device *pdev, - pm_message_t mesg) -{ - return 0; -} - -static int palmz71_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver palmz71_panel_driver = { - .probe = palmz71_panel_probe, - .remove = palmz71_panel_remove, - .suspend = palmz71_panel_suspend, - .resume = palmz71_panel_resume, - .driver = { - .name = "lcd_palmz71", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(palmz71_panel_driver); diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c deleted file mode 100644 index 7767338f8b1..00000000000 --- a/drivers/video/omap/lcdc.c +++ /dev/null @@ -1,856 +0,0 @@ -/* - * OMAP1 internal LCD controller - * - * 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. - */ -#include <linux/module.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/err.h> -#include <linux/mm.h> -#include <linux/fb.h> -#include <linux/dma-mapping.h> -#include <linux/vmalloc.h> -#include <linux/clk.h> -#include <linux/gfp.h> - -#include <mach/lcdc.h> -#include <plat/dma.h> - -#include <asm/mach-types.h> - -#include "omapfb.h" - -#include "lcdc.h" - -#define MODULE_NAME "lcdc" - -#define MAX_PALETTE_SIZE PAGE_SIZE - -enum lcdc_load_mode { - OMAP_LCDC_LOAD_PALETTE, - OMAP_LCDC_LOAD_FRAME, - OMAP_LCDC_LOAD_PALETTE_AND_FRAME -}; - -static struct omap_lcd_controller { - enum omapfb_update_mode update_mode; - int ext_mode; - - unsigned long frame_offset; - int screen_width; - int xres; - int yres; - - enum omapfb_color_format color_mode; - int bpp; - void *palette_virt; - dma_addr_t palette_phys; - int palette_code; - int palette_size; - - unsigned int irq_mask; - struct completion last_frame_complete; - struct completion palette_load_complete; - struct clk *lcd_ck; - struct omapfb_device *fbdev; - - void (*dma_callback)(void *data); - void *dma_callback_data; - - int fbmem_allocated; - dma_addr_t vram_phys; - void *vram_virt; - unsigned long vram_size; -} lcdc; - -static void inline enable_irqs(int mask) -{ - lcdc.irq_mask |= mask; -} - -static void inline disable_irqs(int mask) -{ - lcdc.irq_mask &= ~mask; -} - -static void set_load_mode(enum lcdc_load_mode mode) -{ - u32 l; - - l = omap_readl(OMAP_LCDC_CONTROL); - l &= ~(3 << 20); - switch (mode) { - case OMAP_LCDC_LOAD_PALETTE: - l |= 1 << 20; - break; - case OMAP_LCDC_LOAD_FRAME: - l |= 2 << 20; - break; - case OMAP_LCDC_LOAD_PALETTE_AND_FRAME: - break; - default: - BUG(); - } - omap_writel(l, OMAP_LCDC_CONTROL); -} - -static void enable_controller(void) -{ - u32 l; - - l = omap_readl(OMAP_LCDC_CONTROL); - l |= OMAP_LCDC_CTRL_LCD_EN; - l &= ~OMAP_LCDC_IRQ_MASK; - l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE; /* enabled IRQs */ - omap_writel(l, OMAP_LCDC_CONTROL); -} - -static void disable_controller_async(void) -{ - u32 l; - u32 mask; - - l = omap_readl(OMAP_LCDC_CONTROL); - mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK; - /* - * Preserve the DONE mask, since we still want to get the - * final DONE irq. It will be disabled in the IRQ handler. - */ - mask &= ~OMAP_LCDC_IRQ_DONE; - l &= ~mask; - omap_writel(l, OMAP_LCDC_CONTROL); -} - -static void disable_controller(void) -{ - init_completion(&lcdc.last_frame_complete); - disable_controller_async(); - if (!wait_for_completion_timeout(&lcdc.last_frame_complete, - msecs_to_jiffies(500))) - dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n"); -} - -static void reset_controller(u32 status) -{ - static unsigned long reset_count; - static unsigned long last_jiffies; - - disable_controller_async(); - reset_count++; - if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) { - dev_err(lcdc.fbdev->dev, - "resetting (status %#010x,reset count %lu)\n", - status, reset_count); - last_jiffies = jiffies; - } - if (reset_count < 100) { - enable_controller(); - } else { - reset_count = 0; - dev_err(lcdc.fbdev->dev, - "too many reset attempts, giving up.\n"); - } -} - -/* - * Configure the LCD DMA according to the current mode specified by parameters - * in lcdc.fbdev and fbdev->var. - */ -static void setup_lcd_dma(void) -{ - static const int dma_elem_type[] = { - 0, - OMAP_DMA_DATA_TYPE_S8, - OMAP_DMA_DATA_TYPE_S16, - 0, - OMAP_DMA_DATA_TYPE_S32, - }; - struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par; - struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var; - unsigned long src; - int esize, xelem, yelem; - - src = lcdc.vram_phys + lcdc.frame_offset; - - switch (var->rotate) { - case 0: - if (plane->info.mirror || (src & 3) || - lcdc.color_mode == OMAPFB_COLOR_YUV420 || - (lcdc.xres & 1)) - esize = 2; - else - esize = 4; - xelem = lcdc.xres * lcdc.bpp / 8 / esize; - yelem = lcdc.yres; - break; - case 90: - case 180: - case 270: - if (cpu_is_omap15xx()) { - BUG(); - } - esize = 2; - xelem = lcdc.yres * lcdc.bpp / 16; - yelem = lcdc.xres; - break; - default: - BUG(); - return; - } -#ifdef VERBOSE - dev_dbg(lcdc.fbdev->dev, - "setup_dma: src %#010lx esize %d xelem %d yelem %d\n", - src, esize, xelem, yelem); -#endif - omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]); - if (!cpu_is_omap15xx()) { - int bpp = lcdc.bpp; - - /* - * YUV support is only for external mode when we have the - * YUV window embedded in a 16bpp frame buffer. - */ - if (lcdc.color_mode == OMAPFB_COLOR_YUV420) - bpp = 16; - /* Set virtual xres elem size */ - omap_set_lcd_dma_b1_vxres( - lcdc.screen_width * bpp / 8 / esize); - /* Setup transformations */ - omap_set_lcd_dma_b1_rotation(var->rotate); - omap_set_lcd_dma_b1_mirror(plane->info.mirror); - } - omap_setup_lcd_dma(); -} - -static irqreturn_t lcdc_irq_handler(int irq, void *dev_id) -{ - u32 status; - - status = omap_readl(OMAP_LCDC_STATUS); - - if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST)) - reset_controller(status); - else { - if (status & OMAP_LCDC_STAT_DONE) { - u32 l; - - /* - * Disable IRQ_DONE. The status bit will be cleared - * only when the controller is reenabled and we don't - * want to get more interrupts. - */ - l = omap_readl(OMAP_LCDC_CONTROL); - l &= ~OMAP_LCDC_IRQ_DONE; - omap_writel(l, OMAP_LCDC_CONTROL); - complete(&lcdc.last_frame_complete); - } - if (status & OMAP_LCDC_STAT_LOADED_PALETTE) { - disable_controller_async(); - complete(&lcdc.palette_load_complete); - } - } - - /* - * Clear these interrupt status bits. - * Sync_lost, FUF bits were cleared by disabling the LCD controller - * LOADED_PALETTE can be cleared this way only in palette only - * load mode. In other load modes it's cleared by disabling the - * controller. - */ - status &= ~(OMAP_LCDC_STAT_VSYNC | - OMAP_LCDC_STAT_LOADED_PALETTE | - OMAP_LCDC_STAT_ABC | - OMAP_LCDC_STAT_LINE_INT); - omap_writel(status, OMAP_LCDC_STATUS); - return IRQ_HANDLED; -} - -/* - * Change to a new video mode. We defer this to a later time to avoid any - * flicker and not to mess up the current LCD DMA context. For this we disable - * the LCD controller, which will generate a DONE irq after the last frame has - * been transferred. Then it'll be safe to reconfigure both the LCD controller - * as well as the LCD DMA. - */ -static int omap_lcdc_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) -{ - struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var; - struct lcd_panel *panel = lcdc.fbdev->panel; - int rot_x, rot_y; - - if (var->rotate == 0) { - rot_x = panel->x_res; - rot_y = panel->y_res; - } else { - rot_x = panel->y_res; - rot_y = panel->x_res; - } - if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 || - width > rot_x || height > rot_y) { -#ifdef VERBOSE - dev_dbg(lcdc.fbdev->dev, - "invalid plane params plane %d pos_x %d pos_y %d " - "w %d h %d\n", plane, pos_x, pos_y, width, height); -#endif - return -EINVAL; - } - - lcdc.frame_offset = offset; - lcdc.xres = width; - lcdc.yres = height; - lcdc.screen_width = screen_width; - lcdc.color_mode = color_mode; - - switch (color_mode) { - case OMAPFB_COLOR_CLUT_8BPP: - lcdc.bpp = 8; - lcdc.palette_code = 0x3000; - lcdc.palette_size = 512; - break; - case OMAPFB_COLOR_RGB565: - lcdc.bpp = 16; - lcdc.palette_code = 0x4000; - lcdc.palette_size = 32; - break; - case OMAPFB_COLOR_RGB444: - lcdc.bpp = 16; - lcdc.palette_code = 0x4000; - lcdc.palette_size = 32; - break; - case OMAPFB_COLOR_YUV420: - if (lcdc.ext_mode) { - lcdc.bpp = 12; - break; - } - /* fallthrough */ - case OMAPFB_COLOR_YUV422: - if (lcdc.ext_mode) { - lcdc.bpp = 16; - break; - } - /* fallthrough */ - default: - /* FIXME: other BPPs. - * bpp1: code 0, size 256 - * bpp2: code 0x1000 size 256 - * bpp4: code 0x2000 size 256 - * bpp12: code 0x4000 size 32 - */ - dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode); - BUG(); - return -1; - } - - if (lcdc.ext_mode) { - setup_lcd_dma(); - return 0; - } - - if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) { - disable_controller(); - omap_stop_lcd_dma(); - setup_lcd_dma(); - enable_controller(); - } - - return 0; -} - -static int omap_lcdc_enable_plane(int plane, int enable) -{ - dev_dbg(lcdc.fbdev->dev, - "plane %d enable %d update_mode %d ext_mode %d\n", - plane, enable, lcdc.update_mode, lcdc.ext_mode); - if (plane != OMAPFB_PLANE_GFX) - return -EINVAL; - - return 0; -} - -/* - * Configure the LCD DMA for a palette load operation and do the palette - * downloading synchronously. We don't use the frame+palette load mode of - * the controller, since the palette can always be downloaded separately. - */ -static void load_palette(void) -{ - u16 *palette; - - palette = (u16 *)lcdc.palette_virt; - - *(u16 *)palette &= 0x0fff; - *(u16 *)palette |= lcdc.palette_code; - - omap_set_lcd_dma_b1(lcdc.palette_phys, - lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32); - - omap_set_lcd_dma_single_transfer(1); - omap_setup_lcd_dma(); - - init_completion(&lcdc.palette_load_complete); - enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE); - set_load_mode(OMAP_LCDC_LOAD_PALETTE); - enable_controller(); - if (!wait_for_completion_timeout(&lcdc.palette_load_complete, - msecs_to_jiffies(500))) - dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n"); - /* The controller gets disabled in the irq handler */ - disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE); - omap_stop_lcd_dma(); - - omap_set_lcd_dma_single_transfer(lcdc.ext_mode); -} - -/* Used only in internal controller mode */ -static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue, - u16 transp, int update_hw_pal) -{ - u16 *palette; - - if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255) - return -EINVAL; - - palette = (u16 *)lcdc.palette_virt; - - palette[regno] &= ~0x0fff; - palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) | - (blue >> 12); - - if (update_hw_pal) { - disable_controller(); - omap_stop_lcd_dma(); - load_palette(); - setup_lcd_dma(); - set_load_mode(OMAP_LCDC_LOAD_FRAME); - enable_controller(); - } - - return 0; -} - -static void calc_ck_div(int is_tft, int pck, int *pck_div) -{ - unsigned long lck; - - pck = max(1, pck); - lck = clk_get_rate(lcdc.lcd_ck); - *pck_div = (lck + pck - 1) / pck; - if (is_tft) - *pck_div = max(2, *pck_div); - else - *pck_div = max(3, *pck_div); - if (*pck_div > 255) { - /* FIXME: try to adjust logic clock divider as well */ - *pck_div = 255; - dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n", - pck / 1000); - } -} - -static void inline setup_regs(void) -{ - u32 l; - struct lcd_panel *panel = lcdc.fbdev->panel; - int is_tft = panel->config & OMAP_LCDC_PANEL_TFT; - unsigned long lck; - int pcd; - - l = omap_readl(OMAP_LCDC_CONTROL); - l &= ~OMAP_LCDC_CTRL_LCD_TFT; - l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0; -#ifdef CONFIG_MACH_OMAP_PALMTE -/* FIXME:if (machine_is_omap_palmte()) { */ - /* PalmTE uses alternate TFT setting in 8BPP mode */ - l |= (is_tft && panel->bpp == 8) ? 0x810000 : 0; -/* } */ -#endif - omap_writel(l, OMAP_LCDC_CONTROL); - - l = omap_readl(OMAP_LCDC_TIMING2); - l &= ~(((1 << 6) - 1) << 20); - l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20; - omap_writel(l, OMAP_LCDC_TIMING2); - - l = panel->x_res - 1; - l |= (panel->hsw - 1) << 10; - l |= (panel->hfp - 1) << 16; - l |= (panel->hbp - 1) << 24; - omap_writel(l, OMAP_LCDC_TIMING0); - - l = panel->y_res - 1; - l |= (panel->vsw - 1) << 10; - l |= panel->vfp << 16; - l |= panel->vbp << 24; - omap_writel(l, OMAP_LCDC_TIMING1); - - l = omap_readl(OMAP_LCDC_TIMING2); - l &= ~0xff; - - lck = clk_get_rate(lcdc.lcd_ck); - - if (!panel->pcd) - calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd); - else { - dev_warn(lcdc.fbdev->dev, - "Pixel clock divider value is obsolete.\n" - "Try to set pixel_clock to %lu and pcd to 0 " - "in drivers/video/omap/lcd_%s.c and submit a patch.\n", - lck / panel->pcd / 1000, panel->name); - - pcd = panel->pcd; - } - l |= pcd & 0xff; - l |= panel->acb << 8; - omap_writel(l, OMAP_LCDC_TIMING2); - - /* update panel info with the exact clock */ - panel->pixel_clock = lck / pcd / 1000; -} - -/* - * Configure the LCD controller, download the color palette and start a looped - * DMA transfer of the frame image data. Called only in internal - * controller mode. - */ -static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode) -{ - int r = 0; - - if (mode != lcdc.update_mode) { - switch (mode) { - case OMAPFB_AUTO_UPDATE: - setup_regs(); - load_palette(); - - /* Setup and start LCD DMA */ - setup_lcd_dma(); - - set_load_mode(OMAP_LCDC_LOAD_FRAME); - enable_irqs(OMAP_LCDC_IRQ_DONE); - /* This will start the actual DMA transfer */ - enable_controller(); - lcdc.update_mode = mode; - break; - case OMAPFB_UPDATE_DISABLED: - disable_controller(); - omap_stop_lcd_dma(); - lcdc.update_mode = mode; - break; - default: - r = -EINVAL; - } - } - - return r; -} - -static enum omapfb_update_mode omap_lcdc_get_update_mode(void) -{ - return lcdc.update_mode; -} - -/* PM code called only in internal controller mode */ -static void omap_lcdc_suspend(void) -{ - omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED); -} - -static void omap_lcdc_resume(void) -{ - omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE); -} - -static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps) -{ - return; -} - -int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data) -{ - BUG_ON(callback == NULL); - - if (lcdc.dma_callback) - return -EBUSY; - else { - lcdc.dma_callback = callback; - lcdc.dma_callback_data = data; - } - return 0; -} -EXPORT_SYMBOL(omap_lcdc_set_dma_callback); - -void omap_lcdc_free_dma_callback(void) -{ - lcdc.dma_callback = NULL; -} -EXPORT_SYMBOL(omap_lcdc_free_dma_callback); - -static void lcdc_dma_handler(u16 status, void *data) -{ - if (lcdc.dma_callback) - lcdc.dma_callback(lcdc.dma_callback_data); -} - -static int mmap_kern(void) -{ - struct vm_struct *kvma; - struct vm_area_struct vma; - pgprot_t pgprot; - unsigned long vaddr; - - kvma = get_vm_area(lcdc.vram_size, VM_IOREMAP); - if (kvma == NULL) { - dev_err(lcdc.fbdev->dev, "can't get kernel vm area\n"); - return -ENOMEM; - } - vma.vm_mm = &init_mm; - - vaddr = (unsigned long)kvma->addr; - vma.vm_start = vaddr; - vma.vm_end = vaddr + lcdc.vram_size; - - pgprot = pgprot_writecombine(pgprot_kernel); - if (io_remap_pfn_range(&vma, vaddr, - lcdc.vram_phys >> PAGE_SHIFT, - lcdc.vram_size, pgprot) < 0) { - dev_err(lcdc.fbdev->dev, "kernel mmap for FB memory failed\n"); - return -EAGAIN; - } - - lcdc.vram_virt = (void *)vaddr; - - return 0; -} - -static void unmap_kern(void) -{ - vunmap(lcdc.vram_virt); -} - -static int alloc_palette_ram(void) -{ - lcdc.palette_virt = dma_alloc_writecombine(lcdc.fbdev->dev, - MAX_PALETTE_SIZE, &lcdc.palette_phys, GFP_KERNEL); - if (lcdc.palette_virt == NULL) { - dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n"); - return -ENOMEM; - } - memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE); - - return 0; -} - -static void free_palette_ram(void) -{ - dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE, - lcdc.palette_virt, lcdc.palette_phys); -} - -static int alloc_fbmem(struct omapfb_mem_region *region) -{ - int bpp; - int frame_size; - struct lcd_panel *panel = lcdc.fbdev->panel; - - bpp = panel->bpp; - if (bpp == 12) - bpp = 16; - frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res); - if (region->size > frame_size) - frame_size = region->size; - lcdc.vram_size = frame_size; - lcdc.vram_virt = dma_alloc_writecombine(lcdc.fbdev->dev, - lcdc.vram_size, &lcdc.vram_phys, GFP_KERNEL); - if (lcdc.vram_virt == NULL) { - dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n"); - return -ENOMEM; - } - region->size = frame_size; - region->paddr = lcdc.vram_phys; - region->vaddr = lcdc.vram_virt; - region->alloc = 1; - - memset(lcdc.vram_virt, 0, lcdc.vram_size); - - return 0; -} - -static void free_fbmem(void) -{ - dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size, - lcdc.vram_virt, lcdc.vram_phys); -} - -static int setup_fbmem(struct omapfb_mem_desc *req_md) -{ - int r; - - if (!req_md->region_cnt) { - dev_err(lcdc.fbdev->dev, "no memory regions defined\n"); - return -EINVAL; - } - - if (req_md->region_cnt > 1) { - dev_err(lcdc.fbdev->dev, "only one plane is supported\n"); - req_md->region_cnt = 1; - } - - if (req_md->region[0].paddr == 0) { - lcdc.fbmem_allocated = 1; - if ((r = alloc_fbmem(&req_md->region[0])) < 0) - return r; - return 0; - } - - lcdc.vram_phys = req_md->region[0].paddr; - lcdc.vram_size = req_md->region[0].size; - - if ((r = mmap_kern()) < 0) - return r; - - dev_dbg(lcdc.fbdev->dev, "vram at %08x size %08lx mapped to 0x%p\n", - lcdc.vram_phys, lcdc.vram_size, lcdc.vram_virt); - - return 0; -} - -static void cleanup_fbmem(void) -{ - if (lcdc.fbmem_allocated) - free_fbmem(); - else - unmap_kern(); -} - -static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode, - struct omapfb_mem_desc *req_vram) -{ - int r; - u32 l; - int rate; - struct clk *tc_ck; - - lcdc.irq_mask = 0; - - lcdc.fbdev = fbdev; - lcdc.ext_mode = ext_mode; - - l = 0; - omap_writel(l, OMAP_LCDC_CONTROL); - - /* FIXME: - * According to errata some platforms have a clock rate limitiation - */ - lcdc.lcd_ck = clk_get(fbdev->dev, "lcd_ck"); - if (IS_ERR(lcdc.lcd_ck)) { - dev_err(fbdev->dev, "unable to access LCD clock\n"); - r = PTR_ERR(lcdc.lcd_ck); - goto fail0; - } - - tc_ck = clk_get(fbdev->dev, "tc_ck"); - if (IS_ERR(tc_ck)) { - dev_err(fbdev->dev, "unable to access TC clock\n"); - r = PTR_ERR(tc_ck); - goto fail1; - } - - rate = clk_get_rate(tc_ck); - clk_put(tc_ck); - - if (machine_is_ams_delta()) - rate /= 4; - if (machine_is_omap_h3()) - rate /= 3; - r = clk_set_rate(lcdc.lcd_ck, rate); - if (r) { - dev_err(fbdev->dev, "failed to adjust LCD rate\n"); - goto fail1; - } - clk_enable(lcdc.lcd_ck); - - r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev); - if (r) { - dev_err(fbdev->dev, "unable to get IRQ\n"); - goto fail2; - } - - r = omap_request_lcd_dma(lcdc_dma_handler, NULL); - if (r) { - dev_err(fbdev->dev, "unable to get LCD DMA\n"); - goto fail3; - } - - omap_set_lcd_dma_single_transfer(ext_mode); - omap_set_lcd_dma_ext_controller(ext_mode); - - if (!ext_mode) - if ((r = alloc_palette_ram()) < 0) - goto fail4; - - if ((r = setup_fbmem(req_vram)) < 0) - goto fail5; - - pr_info("omapfb: LCDC initialized\n"); - - return 0; -fail5: - if (!ext_mode) - free_palette_ram(); -fail4: - omap_free_lcd_dma(); -fail3: - free_irq(OMAP_LCDC_IRQ, lcdc.fbdev); -fail2: - clk_disable(lcdc.lcd_ck); -fail1: - clk_put(lcdc.lcd_ck); -fail0: - return r; -} - -static void omap_lcdc_cleanup(void) -{ - if (!lcdc.ext_mode) - free_palette_ram(); - cleanup_fbmem(); - omap_free_lcd_dma(); - free_irq(OMAP_LCDC_IRQ, lcdc.fbdev); - clk_disable(lcdc.lcd_ck); - clk_put(lcdc.lcd_ck); -} - -const struct lcd_ctrl omap1_int_ctrl = { - .name = "internal", - .init = omap_lcdc_init, - .cleanup = omap_lcdc_cleanup, - .get_caps = omap_lcdc_get_caps, - .set_update_mode = omap_lcdc_set_update_mode, - .get_update_mode = omap_lcdc_get_update_mode, - .update_window = NULL, - .suspend = omap_lcdc_suspend, - .resume = omap_lcdc_resume, - .setup_plane = omap_lcdc_setup_plane, - .enable_plane = omap_lcdc_enable_plane, - .setcolreg = omap_lcdc_setcolreg, -}; diff --git a/drivers/video/omap/lcdc.h b/drivers/video/omap/lcdc.h deleted file mode 100644 index 845222270db..00000000000 --- a/drivers/video/omap/lcdc.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef LCDC_H -#define LCDC_H - -int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data); -void omap_lcdc_free_dma_callback(void); - -extern const struct lcd_ctrl omap1_int_ctrl; - -#endif diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h deleted file mode 100644 index af3c9e571ec..00000000000 --- a/drivers/video/omap/omapfb.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * File: drivers/video/omap/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 <linux/fb.h> -#include <linux/mutex.h> -#include <linux/omapfb.h> - -#define OMAPFB_EVENT_READY 1 -#define OMAPFB_EVENT_DISABLED 2 - -#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 - -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 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 platform_device *dssdev; /* dummy dev for clocks */ -}; - -#ifdef CONFIG_ARCH_OMAP1 -extern struct lcd_ctrl omap1_lcd_ctrl; -#else -extern struct lcd_ctrl omap2_disp_ctrl; -#endif - -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); - -#endif /* __OMAPFB_H */ diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c deleted file mode 100644 index b291bfaac80..00000000000 --- a/drivers/video/omap/omapfb_main.c +++ /dev/null @@ -1,2004 +0,0 @@ -/* - * Framebuffer driver for TI OMAP boards - * - * Copyright (C) 2004 Nokia Corporation - * Author: Imre Deak <imre.deak@nokia.com> - * - * Acknowledgements: - * Alex McMains <aam@ridgerun.com> - Original driver - * Juha Yrjola <juha.yrjola@nokia.com> - Original driver and improvements - * Dirk Behme <dirk.behme@de.bosch.com> - changes for 2.6 kernel API - * Texas Instruments - H3 support - * - * 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/platform_device.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/uaccess.h> -#include <linux/module.h> - -#include <plat/dma.h> - -#include "omapfb.h" -#include "lcdc.h" -#include "dispc.h" - -#define MODULE_NAME "omapfb" - -static unsigned int def_accel; -static unsigned long def_vram[OMAPFB_PLANE_NUM]; -static unsigned int def_vram_cnt; -static unsigned long def_vxres; -static unsigned long def_vyres; -static unsigned int def_rotate; -static unsigned int def_mirror; - -#ifdef CONFIG_FB_OMAP_MANUAL_UPDATE -static bool manual_update = 1; -#else -static bool manual_update; -#endif - -static struct platform_device *fbdev_pdev; -static struct lcd_panel *fbdev_panel; -static struct omapfb_device *omapfb_dev; - -struct caps_table_struct { - unsigned long flag; - const char *name; -}; - -static struct caps_table_struct ctrl_caps[] = { - { OMAPFB_CAPS_MANUAL_UPDATE, "manual update" }, - { OMAPFB_CAPS_TEARSYNC, "tearing synchronization" }, - { OMAPFB_CAPS_PLANE_RELOCATE_MEM, "relocate plane memory" }, - { OMAPFB_CAPS_PLANE_SCALE, "scale plane" }, - { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" }, - { OMAPFB_CAPS_WINDOW_SCALE, "scale window" }, - { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" }, - { OMAPFB_CAPS_WINDOW_ROTATE, "rotate window" }, - { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" }, -}; - -static struct caps_table_struct color_caps[] = { - { 1 << OMAPFB_COLOR_RGB565, "RGB565", }, - { 1 << OMAPFB_COLOR_YUV422, "YUV422", }, - { 1 << OMAPFB_COLOR_YUV420, "YUV420", }, - { 1 << OMAPFB_COLOR_CLUT_8BPP, "CLUT8", }, - { 1 << OMAPFB_COLOR_CLUT_4BPP, "CLUT4", }, - { 1 << OMAPFB_COLOR_CLUT_2BPP, "CLUT2", }, - { 1 << OMAPFB_COLOR_CLUT_1BPP, "CLUT1", }, - { 1 << OMAPFB_COLOR_RGB444, "RGB444", }, - { 1 << OMAPFB_COLOR_YUY422, "YUY422", }, -}; - -static void omapdss_release(struct device *dev) -{ -} - -/* dummy device for clocks */ -static struct platform_device omapdss_device = { - .name = "omapdss_dss", - .id = -1, - .dev = { - .release = omapdss_release, - }, -}; - -/* - * --------------------------------------------------------------------------- - * LCD panel - * --------------------------------------------------------------------------- - */ -extern struct lcd_ctrl hwa742_ctrl; -extern struct lcd_ctrl blizzard_ctrl; - -static const struct lcd_ctrl *ctrls[] = { -#ifdef CONFIG_ARCH_OMAP1 - &omap1_int_ctrl, -#else - &omap2_int_ctrl, -#endif - -#ifdef CONFIG_FB_OMAP_LCDC_HWA742 - &hwa742_ctrl, -#endif -#ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD - &blizzard_ctrl, -#endif -}; - -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL -#ifdef CONFIG_ARCH_OMAP1 -extern struct lcd_ctrl_extif omap1_ext_if; -#else -extern struct lcd_ctrl_extif omap2_ext_if; -#endif -#endif - -static void omapfb_rqueue_lock(struct omapfb_device *fbdev) -{ - mutex_lock(&fbdev->rqueue_mutex); -} - -static void omapfb_rqueue_unlock(struct omapfb_device *fbdev) -{ - mutex_unlock(&fbdev->rqueue_mutex); -} - -/* - * --------------------------------------------------------------------------- - * LCD controller and LCD DMA - * --------------------------------------------------------------------------- - */ -/* Lookup table to map elem size to elem type. */ -static const int dma_elem_type[] = { - 0, - OMAP_DMA_DATA_TYPE_S8, - OMAP_DMA_DATA_TYPE_S16, - 0, - OMAP_DMA_DATA_TYPE_S32, -}; - -/* - * Allocate resources needed for LCD controller and LCD DMA operations. Video - * memory is allocated from system memory according to the virtual display - * size, except if a bigger memory size is specified explicitly as a kernel - * parameter. - */ -static int ctrl_init(struct omapfb_device *fbdev) -{ - int r; - int i; - - /* kernel/module vram parameters override boot tags/board config */ - if (def_vram_cnt) { - for (i = 0; i < def_vram_cnt; i++) - fbdev->mem_desc.region[i].size = - PAGE_ALIGN(def_vram[i]); - fbdev->mem_desc.region_cnt = i; - } else { - struct omapfb_platform_data *conf; - - conf = fbdev->dev->platform_data; - fbdev->mem_desc = conf->mem_desc; - } - - if (!fbdev->mem_desc.region_cnt) { - struct lcd_panel *panel = fbdev->panel; - int def_size; - int bpp = panel->bpp; - - /* 12 bpp is packed in 16 bits */ - if (bpp == 12) - bpp = 16; - def_size = def_vxres * def_vyres * bpp / 8; - fbdev->mem_desc.region_cnt = 1; - fbdev->mem_desc.region[0].size = PAGE_ALIGN(def_size); - } - r = fbdev->ctrl->init(fbdev, 0, &fbdev->mem_desc); - if (r < 0) { - dev_err(fbdev->dev, "controller initialization failed (%d)\n", - r); - return r; - } - -#ifdef DEBUG - for (i = 0; i < fbdev->mem_desc.region_cnt; i++) { - dev_dbg(fbdev->dev, "region%d phys %08x virt %p size=%lu\n", - i, - fbdev->mem_desc.region[i].paddr, - fbdev->mem_desc.region[i].vaddr, - fbdev->mem_desc.region[i].size); - } -#endif - return 0; -} - -static void ctrl_cleanup(struct omapfb_device *fbdev) -{ - fbdev->ctrl->cleanup(); -} - -/* Must be called with fbdev->rqueue_mutex held. */ -static int ctrl_change_mode(struct fb_info *fbi) -{ - int r; - unsigned long offset; - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - struct fb_var_screeninfo *var = &fbi->var; - - offset = var->yoffset * fbi->fix.line_length + - var->xoffset * var->bits_per_pixel / 8; - - if (fbdev->ctrl->sync) - fbdev->ctrl->sync(); - r = fbdev->ctrl->setup_plane(plane->idx, plane->info.channel_out, - offset, var->xres_virtual, - plane->info.pos_x, plane->info.pos_y, - var->xres, var->yres, plane->color_mode); - if (r < 0) - return r; - - if (fbdev->ctrl->set_rotate != NULL) { - r = fbdev->ctrl->set_rotate(var->rotate); - if (r < 0) - return r; - } - - if (fbdev->ctrl->set_scale != NULL) - r = fbdev->ctrl->set_scale(plane->idx, - var->xres, var->yres, - plane->info.out_width, - plane->info.out_height); - - return r; -} - -/* - * --------------------------------------------------------------------------- - * fbdev framework callbacks and the ioctl interface - * --------------------------------------------------------------------------- - */ -/* Called each time the omapfb device is opened */ -static int omapfb_open(struct fb_info *info, int user) -{ - return 0; -} - -static void omapfb_sync(struct fb_info *info); - -/* Called when the omapfb device is closed. We make sure that any pending - * gfx DMA operations are ended, before we return. */ -static int omapfb_release(struct fb_info *info, int user) -{ - omapfb_sync(info); - return 0; -} - -/* Store a single color palette entry into a pseudo palette or the hardware - * palette if one is available. For now we support only 16bpp and thus store - * the entry only to the pseudo palette. - */ -static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green, - u_int blue, u_int transp, int update_hw_pal) -{ - struct omapfb_plane_struct *plane = info->par; - struct omapfb_device *fbdev = plane->fbdev; - struct fb_var_screeninfo *var = &info->var; - int r = 0; - - switch (plane->color_mode) { - case OMAPFB_COLOR_YUV422: - case OMAPFB_COLOR_YUV420: - case OMAPFB_COLOR_YUY422: - r = -EINVAL; - break; - case OMAPFB_COLOR_CLUT_8BPP: - case OMAPFB_COLOR_CLUT_4BPP: - case OMAPFB_COLOR_CLUT_2BPP: - case OMAPFB_COLOR_CLUT_1BPP: - if (fbdev->ctrl->setcolreg) - r = fbdev->ctrl->setcolreg(regno, red, green, blue, - transp, update_hw_pal); - /* Fallthrough */ - case OMAPFB_COLOR_RGB565: - case OMAPFB_COLOR_RGB444: - if (r != 0) - break; - - if (regno < 0) { - r = -EINVAL; - break; - } - - if (regno < 16) { - u16 pal; - pal = ((red >> (16 - var->red.length)) << - var->red.offset) | - ((green >> (16 - var->green.length)) << - var->green.offset) | - (blue >> (16 - var->blue.length)); - ((u32 *)(info->pseudo_palette))[regno] = pal; - } - break; - default: - BUG(); - } - return r; -} - -static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info) -{ - return _setcolreg(info, regno, red, green, blue, transp, 1); -} - -static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) -{ - int count, index, r; - u16 *red, *green, *blue, *transp; - u16 trans = 0xffff; - - red = cmap->red; - green = cmap->green; - blue = cmap->blue; - transp = cmap->transp; - index = cmap->start; - - for (count = 0; count < cmap->len; count++) { - if (transp) - trans = *transp++; - r = _setcolreg(info, index++, *red++, *green++, *blue++, trans, - count == cmap->len - 1); - if (r != 0) - return r; - } - - return 0; -} - -static int omapfb_update_full_screen(struct fb_info *fbi); - -static int omapfb_blank(int blank, struct fb_info *fbi) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - int do_update = 0; - int r = 0; - - omapfb_rqueue_lock(fbdev); - switch (blank) { - case FB_BLANK_UNBLANK: - if (fbdev->state == OMAPFB_SUSPENDED) { - if (fbdev->ctrl->resume) - fbdev->ctrl->resume(); - fbdev->panel->enable(fbdev->panel); - fbdev->state = OMAPFB_ACTIVE; - if (fbdev->ctrl->get_update_mode() == - OMAPFB_MANUAL_UPDATE) - do_update = 1; - } - break; - case FB_BLANK_POWERDOWN: - if (fbdev->state == OMAPFB_ACTIVE) { - fbdev->panel->disable(fbdev->panel); - if (fbdev->ctrl->suspend) - fbdev->ctrl->suspend(); - fbdev->state = OMAPFB_SUSPENDED; - } - break; - default: - r = -EINVAL; - } - omapfb_rqueue_unlock(fbdev); - - if (r == 0 && do_update) - r = omapfb_update_full_screen(fbi); - - return r; -} - -static void omapfb_sync(struct fb_info *fbi) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - - omapfb_rqueue_lock(fbdev); - if (fbdev->ctrl->sync) - fbdev->ctrl->sync(); - omapfb_rqueue_unlock(fbdev); -} - -/* - * Set fb_info.fix fields and also updates fbdev. - * When calling this fb_info.var must be set up already. - */ -static void set_fb_fix(struct fb_info *fbi, int from_init) -{ - struct fb_fix_screeninfo *fix = &fbi->fix; - struct fb_var_screeninfo *var = &fbi->var; - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_mem_region *rg; - int bpp; - - rg = &plane->fbdev->mem_desc.region[plane->idx]; - fbi->screen_base = rg->vaddr; - - if (!from_init) { - mutex_lock(&fbi->mm_lock); - fix->smem_start = rg->paddr; - fix->smem_len = rg->size; - mutex_unlock(&fbi->mm_lock); - } else { - fix->smem_start = rg->paddr; - fix->smem_len = rg->size; - } - - fix->type = FB_TYPE_PACKED_PIXELS; - bpp = var->bits_per_pixel; - if (var->nonstd) - fix->visual = FB_VISUAL_PSEUDOCOLOR; - else switch (var->bits_per_pixel) { - case 16: - case 12: - fix->visual = FB_VISUAL_TRUECOLOR; - /* 12bpp is stored in 16 bits */ - bpp = 16; - break; - case 1: - case 2: - case 4: - case 8: - fix->visual = FB_VISUAL_PSEUDOCOLOR; - break; - } - fix->accel = FB_ACCEL_OMAP1610; - fix->line_length = var->xres_virtual * bpp / 8; -} - -static int set_color_mode(struct omapfb_plane_struct *plane, - struct fb_var_screeninfo *var) -{ - switch (var->nonstd) { - case 0: - break; - case OMAPFB_COLOR_YUV422: - var->bits_per_pixel = 16; - plane->color_mode = var->nonstd; - return 0; - case OMAPFB_COLOR_YUV420: - var->bits_per_pixel = 12; - plane->color_mode = var->nonstd; - return 0; - case OMAPFB_COLOR_YUY422: - var->bits_per_pixel = 16; - plane->color_mode = var->nonstd; - return 0; - default: - return -EINVAL; - } - - switch (var->bits_per_pixel) { - case 1: - plane->color_mode = OMAPFB_COLOR_CLUT_1BPP; - return 0; - case 2: - plane->color_mode = OMAPFB_COLOR_CLUT_2BPP; - return 0; - case 4: - plane->color_mode = OMAPFB_COLOR_CLUT_4BPP; - return 0; - case 8: - plane->color_mode = OMAPFB_COLOR_CLUT_8BPP; - return 0; - case 12: - var->bits_per_pixel = 16; - case 16: - if (plane->fbdev->panel->bpp == 12) - plane->color_mode = OMAPFB_COLOR_RGB444; - else - plane->color_mode = OMAPFB_COLOR_RGB565; - return 0; - default: - return -EINVAL; - } -} - -/* - * Check the values in var against our capabilities and in case of out of - * bound values try to adjust them. - */ -static int set_fb_var(struct fb_info *fbi, - struct fb_var_screeninfo *var) -{ - int bpp; - unsigned long max_frame_size; - unsigned long line_size; - int xres_min, xres_max; - int yres_min, yres_max; - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - struct lcd_panel *panel = fbdev->panel; - - if (set_color_mode(plane, var) < 0) - return -EINVAL; - - bpp = var->bits_per_pixel; - if (plane->color_mode == OMAPFB_COLOR_RGB444) - bpp = 16; - - switch (var->rotate) { - case 0: - case 180: - xres_min = OMAPFB_PLANE_XRES_MIN; - xres_max = panel->x_res; - yres_min = OMAPFB_PLANE_YRES_MIN; - yres_max = panel->y_res; - if (cpu_is_omap15xx()) { - var->xres = panel->x_res; - var->yres = panel->y_res; - } - break; - case 90: - case 270: - xres_min = OMAPFB_PLANE_YRES_MIN; - xres_max = panel->y_res; - yres_min = OMAPFB_PLANE_XRES_MIN; - yres_max = panel->x_res; - if (cpu_is_omap15xx()) { - var->xres = panel->y_res; - var->yres = panel->x_res; - } - break; - default: - return -EINVAL; - } - - if (var->xres < xres_min) - var->xres = xres_min; - if (var->yres < yres_min) - var->yres = yres_min; - if (var->xres > xres_max) - var->xres = xres_max; - if (var->yres > yres_max) - var->yres = yres_max; - - if (var->xres_virtual < var->xres) - var->xres_virtual = var->xres; - if (var->yres_virtual < var->yres) - var->yres_virtual = var->yres; - max_frame_size = fbdev->mem_desc.region[plane->idx].size; - line_size = var->xres_virtual * bpp / 8; - if (line_size * var->yres_virtual > max_frame_size) { - /* Try to keep yres_virtual first */ - line_size = max_frame_size / var->yres_virtual; - var->xres_virtual = line_size * 8 / bpp; - if (var->xres_virtual < var->xres) { - /* Still doesn't fit. Shrink yres_virtual too */ - var->xres_virtual = var->xres; - line_size = var->xres * bpp / 8; - var->yres_virtual = max_frame_size / line_size; - } - /* Recheck this, as the virtual size changed. */ - if (var->xres_virtual < var->xres) - var->xres = var->xres_virtual; - if (var->yres_virtual < var->yres) - var->yres = var->yres_virtual; - if (var->xres < xres_min || var->yres < yres_min) - return -EINVAL; - } - if (var->xres + var->xoffset > var->xres_virtual) - var->xoffset = var->xres_virtual - var->xres; - if (var->yres + var->yoffset > var->yres_virtual) - var->yoffset = var->yres_virtual - var->yres; - - if (plane->color_mode == OMAPFB_COLOR_RGB444) { - var->red.offset = 8; var->red.length = 4; - var->red.msb_right = 0; - var->green.offset = 4; var->green.length = 4; - var->green.msb_right = 0; - var->blue.offset = 0; var->blue.length = 4; - var->blue.msb_right = 0; - } else { - var->red.offset = 11; var->red.length = 5; - var->red.msb_right = 0; - var->green.offset = 5; var->green.length = 6; - var->green.msb_right = 0; - var->blue.offset = 0; var->blue.length = 5; - var->blue.msb_right = 0; - } - - var->height = -1; - var->width = -1; - var->grayscale = 0; - - /* pixclock in ps, the rest in pixclock */ - var->pixclock = 10000000 / (panel->pixel_clock / 100); - var->left_margin = panel->hfp; - var->right_margin = panel->hbp; - var->upper_margin = panel->vfp; - var->lower_margin = panel->vbp; - var->hsync_len = panel->hsw; - var->vsync_len = panel->vsw; - - /* TODO: get these from panel->config */ - var->vmode = FB_VMODE_NONINTERLACED; - var->sync = 0; - - return 0; -} - - -/* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */ -static void omapfb_rotate(struct fb_info *fbi, int rotate) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - - omapfb_rqueue_lock(fbdev); - if (rotate != fbi->var.rotate) { - struct fb_var_screeninfo *new_var = &fbdev->new_var; - - memcpy(new_var, &fbi->var, sizeof(*new_var)); - new_var->rotate = rotate; - if (set_fb_var(fbi, new_var) == 0 && - memcmp(new_var, &fbi->var, sizeof(*new_var))) { - memcpy(&fbi->var, new_var, sizeof(*new_var)); - ctrl_change_mode(fbi); - } - } - omapfb_rqueue_unlock(fbdev); -} - -/* - * Set new x,y offsets in the virtual display for the visible area and switch - * to the new mode. - */ -static int omapfb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *fbi) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - int r = 0; - - omapfb_rqueue_lock(fbdev); - if (var->xoffset != fbi->var.xoffset || - var->yoffset != fbi->var.yoffset) { - struct fb_var_screeninfo *new_var = &fbdev->new_var; - - memcpy(new_var, &fbi->var, sizeof(*new_var)); - new_var->xoffset = var->xoffset; - new_var->yoffset = var->yoffset; - if (set_fb_var(fbi, new_var)) - r = -EINVAL; - else { - memcpy(&fbi->var, new_var, sizeof(*new_var)); - ctrl_change_mode(fbi); - } - } - omapfb_rqueue_unlock(fbdev); - - return r; -} - -/* Set mirror to vertical axis and switch to the new mode. */ -static int omapfb_mirror(struct fb_info *fbi, int mirror) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - int r = 0; - - omapfb_rqueue_lock(fbdev); - mirror = mirror ? 1 : 0; - if (cpu_is_omap15xx()) - r = -EINVAL; - else if (mirror != plane->info.mirror) { - plane->info.mirror = mirror; - r = ctrl_change_mode(fbi); - } - omapfb_rqueue_unlock(fbdev); - - return r; -} - -/* - * Check values in var, try to adjust them in case of out of bound values if - * possible, or return error. - */ -static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - int r; - - omapfb_rqueue_lock(fbdev); - if (fbdev->ctrl->sync != NULL) - fbdev->ctrl->sync(); - r = set_fb_var(fbi, var); - omapfb_rqueue_unlock(fbdev); - - return r; -} - -/* - * Switch to a new mode. The parameters for it has been check already by - * omapfb_check_var. - */ -static int omapfb_set_par(struct fb_info *fbi) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - int r = 0; - - omapfb_rqueue_lock(fbdev); - set_fb_fix(fbi, 0); - r = ctrl_change_mode(fbi); - omapfb_rqueue_unlock(fbdev); - - return r; -} - -int omapfb_update_window_async(struct fb_info *fbi, - struct omapfb_update_window *win, - void (*callback)(void *), - void *callback_data) -{ - int xres, yres; - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - struct fb_var_screeninfo *var = &fbi->var; - - switch (var->rotate) { - case 0: - case 180: - xres = fbdev->panel->x_res; - yres = fbdev->panel->y_res; - break; - case 90: - case 270: - xres = fbdev->panel->y_res; - yres = fbdev->panel->x_res; - break; - default: - return -EINVAL; - } - - if (win->x >= xres || win->y >= yres || - win->out_x > xres || win->out_y > yres) - return -EINVAL; - - if (!fbdev->ctrl->update_window || - fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE) - return -ENODEV; - - if (win->x + win->width > xres) - win->width = xres - win->x; - if (win->y + win->height > yres) - win->height = yres - win->y; - if (win->out_x + win->out_width > xres) - win->out_width = xres - win->out_x; - if (win->out_y + win->out_height > yres) - win->out_height = yres - win->out_y; - if (!win->width || !win->height || !win->out_width || !win->out_height) - return 0; - - return fbdev->ctrl->update_window(fbi, win, callback, callback_data); -} -EXPORT_SYMBOL(omapfb_update_window_async); - -static int omapfb_update_win(struct fb_info *fbi, - struct omapfb_update_window *win) -{ - struct omapfb_plane_struct *plane = fbi->par; - int ret; - - omapfb_rqueue_lock(plane->fbdev); - ret = omapfb_update_window_async(fbi, win, NULL, NULL); - omapfb_rqueue_unlock(plane->fbdev); - - return ret; -} - -static int omapfb_update_full_screen(struct fb_info *fbi) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - struct omapfb_update_window win; - int r; - - if (!fbdev->ctrl->update_window || - fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE) - return -ENODEV; - - win.x = 0; - win.y = 0; - win.width = fbi->var.xres; - win.height = fbi->var.yres; - win.out_x = 0; - win.out_y = 0; - win.out_width = fbi->var.xres; - win.out_height = fbi->var.yres; - win.format = 0; - - omapfb_rqueue_lock(fbdev); - r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL); - omapfb_rqueue_unlock(fbdev); - - return r; -} - -static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - struct lcd_panel *panel = fbdev->panel; - struct omapfb_plane_info old_info; - int r = 0; - - if (pi->pos_x + pi->out_width > panel->x_res || - pi->pos_y + pi->out_height > panel->y_res) - return -EINVAL; - - omapfb_rqueue_lock(fbdev); - if (pi->enabled && !fbdev->mem_desc.region[plane->idx].size) { - /* - * This plane's memory was freed, can't enable it - * until it's reallocated. - */ - r = -EINVAL; - goto out; - } - old_info = plane->info; - plane->info = *pi; - if (pi->enabled) { - r = ctrl_change_mode(fbi); - if (r < 0) { - plane->info = old_info; - goto out; - } - } - r = fbdev->ctrl->enable_plane(plane->idx, pi->enabled); - if (r < 0) { - plane->info = old_info; - goto out; - } -out: - omapfb_rqueue_unlock(fbdev); - return r; -} - -static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) -{ - struct omapfb_plane_struct *plane = fbi->par; - - *pi = plane->info; - return 0; -} - -static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - struct omapfb_mem_region *rg = &fbdev->mem_desc.region[plane->idx]; - size_t size; - int r = 0; - - if (fbdev->ctrl->setup_mem == NULL) - return -ENODEV; - if (mi->type > OMAPFB_MEMTYPE_MAX) - return -EINVAL; - - size = PAGE_ALIGN(mi->size); - omapfb_rqueue_lock(fbdev); - if (plane->info.enabled) { - r = -EBUSY; - goto out; - } - if (rg->size != size || rg->type != mi->type) { - struct fb_var_screeninfo *new_var = &fbdev->new_var; - unsigned long old_size = rg->size; - u8 old_type = rg->type; - unsigned long paddr; - - rg->size = size; - rg->type = mi->type; - /* - * size == 0 is a special case, for which we - * don't check / adjust the screen parameters. - * This isn't a problem since the plane can't - * be reenabled unless its size is > 0. - */ - if (old_size != size && size) { - if (size) { - memcpy(new_var, &fbi->var, sizeof(*new_var)); - r = set_fb_var(fbi, new_var); - if (r < 0) - goto out; - } - } - - if (fbdev->ctrl->sync) - fbdev->ctrl->sync(); - r = fbdev->ctrl->setup_mem(plane->idx, size, mi->type, &paddr); - if (r < 0) { - /* Revert changes. */ - rg->size = old_size; - rg->type = old_type; - goto out; - } - rg->paddr = paddr; - - if (old_size != size) { - if (size) { - memcpy(&fbi->var, new_var, sizeof(fbi->var)); - set_fb_fix(fbi, 0); - } else { - /* - * Set these explicitly to indicate that the - * plane memory is dealloce'd, the other - * screen parameters in var / fix are invalid. - */ - mutex_lock(&fbi->mm_lock); - fbi->fix.smem_start = 0; - fbi->fix.smem_len = 0; - mutex_unlock(&fbi->mm_lock); - } - } - } -out: - omapfb_rqueue_unlock(fbdev); - - return r; -} - -static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - struct omapfb_mem_region *rg; - - rg = &fbdev->mem_desc.region[plane->idx]; - memset(mi, 0, sizeof(*mi)); - mi->size = rg->size; - mi->type = rg->type; - - return 0; -} - -static int omapfb_set_color_key(struct omapfb_device *fbdev, - struct omapfb_color_key *ck) -{ - int r; - - if (!fbdev->ctrl->set_color_key) - return -ENODEV; - - omapfb_rqueue_lock(fbdev); - r = fbdev->ctrl->set_color_key(ck); - omapfb_rqueue_unlock(fbdev); - - return r; -} - -static int omapfb_get_color_key(struct omapfb_device *fbdev, - struct omapfb_color_key *ck) -{ - int r; - - if (!fbdev->ctrl->get_color_key) - return -ENODEV; - - omapfb_rqueue_lock(fbdev); - r = fbdev->ctrl->get_color_key(ck); - omapfb_rqueue_unlock(fbdev); - - return r; -} - -static struct blocking_notifier_head omapfb_client_list[OMAPFB_PLANE_NUM]; -static int notifier_inited; - -static void omapfb_init_notifier(void) -{ - int i; - - for (i = 0; i < OMAPFB_PLANE_NUM; i++) - BLOCKING_INIT_NOTIFIER_HEAD(&omapfb_client_list[i]); -} - -int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb, - omapfb_notifier_callback_t callback, - void *callback_data) -{ - int r; - - if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM) - return -EINVAL; - - if (!notifier_inited) { - omapfb_init_notifier(); - notifier_inited = 1; - } - - omapfb_nb->nb.notifier_call = (int (*)(struct notifier_block *, - unsigned long, void *))callback; - omapfb_nb->data = callback_data; - r = blocking_notifier_chain_register( - &omapfb_client_list[omapfb_nb->plane_idx], - &omapfb_nb->nb); - if (r) - return r; - if (omapfb_dev != NULL && - omapfb_dev->ctrl && omapfb_dev->ctrl->bind_client) { - omapfb_dev->ctrl->bind_client(omapfb_nb); - } - - return 0; -} -EXPORT_SYMBOL(omapfb_register_client); - -int omapfb_unregister_client(struct omapfb_notifier_block *omapfb_nb) -{ - return blocking_notifier_chain_unregister( - &omapfb_client_list[omapfb_nb->plane_idx], &omapfb_nb->nb); -} -EXPORT_SYMBOL(omapfb_unregister_client); - -void omapfb_notify_clients(struct omapfb_device *fbdev, unsigned long event) -{ - int i; - - if (!notifier_inited) - /* no client registered yet */ - return; - - for (i = 0; i < OMAPFB_PLANE_NUM; i++) - blocking_notifier_call_chain(&omapfb_client_list[i], event, - fbdev->fb_info[i]); -} -EXPORT_SYMBOL(omapfb_notify_clients); - -static int omapfb_set_update_mode(struct omapfb_device *fbdev, - enum omapfb_update_mode mode) -{ - int r; - - omapfb_rqueue_lock(fbdev); - r = fbdev->ctrl->set_update_mode(mode); - omapfb_rqueue_unlock(fbdev); - - return r; -} - -static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev) -{ - int r; - - omapfb_rqueue_lock(fbdev); - r = fbdev->ctrl->get_update_mode(); - omapfb_rqueue_unlock(fbdev); - - return r; -} - -static void omapfb_get_caps(struct omapfb_device *fbdev, int plane, - struct omapfb_caps *caps) -{ - memset(caps, 0, sizeof(*caps)); - fbdev->ctrl->get_caps(plane, caps); - caps->ctrl |= fbdev->panel->get_caps(fbdev->panel); -} - -/* For lcd testing */ -void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval) -{ - omapfb_rqueue_lock(fbdev); - *(u16 *)fbdev->mem_desc.region[0].vaddr = pixval; - if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) { - struct omapfb_update_window win; - - memset(&win, 0, sizeof(win)); - win.width = 2; - win.height = 2; - win.out_width = 2; - win.out_height = 2; - fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, NULL); - } - omapfb_rqueue_unlock(fbdev); -} -EXPORT_SYMBOL(omapfb_write_first_pixel); - -/* - * Ioctl interface. Part of the kernel mode frame buffer API is duplicated - * here to be accessible by user mode code. - */ -static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, - unsigned long arg) -{ - struct omapfb_plane_struct *plane = fbi->par; - struct omapfb_device *fbdev = plane->fbdev; - struct fb_ops *ops = fbi->fbops; - union { - struct omapfb_update_window update_window; - struct omapfb_plane_info plane_info; - struct omapfb_mem_info mem_info; - struct omapfb_color_key color_key; - enum omapfb_update_mode update_mode; - struct omapfb_caps caps; - unsigned int mirror; - int plane_out; - int enable_plane; - } p; - int r = 0; - - BUG_ON(!ops); - switch (cmd) { - case OMAPFB_MIRROR: - if (get_user(p.mirror, (int __user *)arg)) - r = -EFAULT; - else - omapfb_mirror(fbi, p.mirror); - break; - case OMAPFB_SYNC_GFX: - omapfb_sync(fbi); - break; - case OMAPFB_VSYNC: - break; - case OMAPFB_SET_UPDATE_MODE: - if (get_user(p.update_mode, (int __user *)arg)) - r = -EFAULT; - else - r = omapfb_set_update_mode(fbdev, p.update_mode); - break; - case OMAPFB_GET_UPDATE_MODE: - p.update_mode = omapfb_get_update_mode(fbdev); - if (put_user(p.update_mode, - (enum omapfb_update_mode __user *)arg)) - r = -EFAULT; - break; - case OMAPFB_UPDATE_WINDOW_OLD: - if (copy_from_user(&p.update_window, (void __user *)arg, - sizeof(struct omapfb_update_window_old))) - r = -EFAULT; - else { - struct omapfb_update_window *u = &p.update_window; - u->out_x = u->x; - u->out_y = u->y; - u->out_width = u->width; - u->out_height = u->height; - memset(u->reserved, 0, sizeof(u->reserved)); - r = omapfb_update_win(fbi, u); - } - break; - case OMAPFB_UPDATE_WINDOW: - if (copy_from_user(&p.update_window, (void __user *)arg, - sizeof(p.update_window))) - r = -EFAULT; - else - r = omapfb_update_win(fbi, &p.update_window); - break; - case OMAPFB_SETUP_PLANE: - if (copy_from_user(&p.plane_info, (void __user *)arg, - sizeof(p.plane_info))) - r = -EFAULT; - else - r = omapfb_setup_plane(fbi, &p.plane_info); - break; - case OMAPFB_QUERY_PLANE: - if ((r = omapfb_query_plane(fbi, &p.plane_info)) < 0) - break; - if (copy_to_user((void __user *)arg, &p.plane_info, - sizeof(p.plane_info))) - r = -EFAULT; - break; - case OMAPFB_SETUP_MEM: - if (copy_from_user(&p.mem_info, (void __user *)arg, - sizeof(p.mem_info))) - r = -EFAULT; - else - r = omapfb_setup_mem(fbi, &p.mem_info); - break; - case OMAPFB_QUERY_MEM: - if ((r = omapfb_query_mem(fbi, &p.mem_info)) < 0) - break; - if (copy_to_user((void __user *)arg, &p.mem_info, - sizeof(p.mem_info))) - r = -EFAULT; - break; - case OMAPFB_SET_COLOR_KEY: - if (copy_from_user(&p.color_key, (void __user *)arg, - sizeof(p.color_key))) - r = -EFAULT; - else - r = omapfb_set_color_key(fbdev, &p.color_key); - break; - case OMAPFB_GET_COLOR_KEY: - if ((r = omapfb_get_color_key(fbdev, &p.color_key)) < 0) - break; - if (copy_to_user((void __user *)arg, &p.color_key, - sizeof(p.color_key))) - r = -EFAULT; - break; - case OMAPFB_GET_CAPS: - omapfb_get_caps(fbdev, plane->idx, &p.caps); - if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps))) - r = -EFAULT; - break; - case OMAPFB_LCD_TEST: - { - int test_num; - - if (get_user(test_num, (int __user *)arg)) { - r = -EFAULT; - break; - } - if (!fbdev->panel->run_test) { - r = -EINVAL; - break; - } - r = fbdev->panel->run_test(fbdev->panel, test_num); - break; - } - case OMAPFB_CTRL_TEST: - { - int test_num; - - if (get_user(test_num, (int __user *)arg)) { - r = -EFAULT; - break; - } - if (!fbdev->ctrl->run_test) { - r = -EINVAL; - break; - } - r = fbdev->ctrl->run_test(test_num); - break; - } - default: - r = -EINVAL; - } - - return r; -} - -static int omapfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - struct omapfb_plane_struct *plane = info->par; - struct omapfb_device *fbdev = plane->fbdev; - int r; - - omapfb_rqueue_lock(fbdev); - r = fbdev->ctrl->mmap(info, vma); - omapfb_rqueue_unlock(fbdev); - - return r; -} - -/* - * Callback table for the frame buffer framework. Some of these pointers - * will be changed according to the current setting of fb_info->accel_flags. - */ -static struct fb_ops omapfb_ops = { - .owner = THIS_MODULE, - .fb_open = omapfb_open, - .fb_release = omapfb_release, - .fb_setcolreg = omapfb_setcolreg, - .fb_setcmap = omapfb_setcmap, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_blank = omapfb_blank, - .fb_ioctl = omapfb_ioctl, - .fb_check_var = omapfb_check_var, - .fb_set_par = omapfb_set_par, - .fb_rotate = omapfb_rotate, - .fb_pan_display = omapfb_pan_display, -}; - -/* - * --------------------------------------------------------------------------- - * Sysfs interface - * --------------------------------------------------------------------------- - */ -/* omapfbX sysfs entries */ -static ssize_t omapfb_show_caps_num(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct omapfb_device *fbdev = dev_get_drvdata(dev); - int plane; - size_t size; - struct omapfb_caps caps; - - plane = 0; - size = 0; - while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) { - omapfb_get_caps(fbdev, plane, &caps); - size += snprintf(&buf[size], PAGE_SIZE - size, - "plane#%d %#010x %#010x %#010x\n", - plane, caps.ctrl, caps.plane_color, caps.wnd_color); - plane++; - } - return size; -} - -static ssize_t omapfb_show_caps_text(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct omapfb_device *fbdev = dev_get_drvdata(dev); - int i; - struct omapfb_caps caps; - int plane; - size_t size; - - plane = 0; - size = 0; - while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) { - omapfb_get_caps(fbdev, plane, &caps); - size += snprintf(&buf[size], PAGE_SIZE - size, - "plane#%d:\n", plane); - for (i = 0; i < ARRAY_SIZE(ctrl_caps) && - size < PAGE_SIZE; i++) { - if (ctrl_caps[i].flag & caps.ctrl) - size += snprintf(&buf[size], PAGE_SIZE - size, - " %s\n", ctrl_caps[i].name); - } - size += snprintf(&buf[size], PAGE_SIZE - size, - " plane colors:\n"); - for (i = 0; i < ARRAY_SIZE(color_caps) && - size < PAGE_SIZE; i++) { - if (color_caps[i].flag & caps.plane_color) - size += snprintf(&buf[size], PAGE_SIZE - size, - " %s\n", color_caps[i].name); - } - size += snprintf(&buf[size], PAGE_SIZE - size, - " window colors:\n"); - for (i = 0; i < ARRAY_SIZE(color_caps) && - size < PAGE_SIZE; i++) { - if (color_caps[i].flag & caps.wnd_color) - size += snprintf(&buf[size], PAGE_SIZE - size, - " %s\n", color_caps[i].name); - } - - plane++; - } - return size; -} - -static DEVICE_ATTR(caps_num, 0444, omapfb_show_caps_num, NULL); -static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL); - -/* panel sysfs entries */ -static ssize_t omapfb_show_panel_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct omapfb_device *fbdev = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name); -} - -static ssize_t omapfb_show_bklight_level(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct omapfb_device *fbdev = dev_get_drvdata(dev); - int r; - - if (fbdev->panel->get_bklight_level) { - r = snprintf(buf, PAGE_SIZE, "%d\n", - fbdev->panel->get_bklight_level(fbdev->panel)); - } else - r = -ENODEV; - return r; -} - -static ssize_t omapfb_store_bklight_level(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct omapfb_device *fbdev = dev_get_drvdata(dev); - int r; - - if (fbdev->panel->set_bklight_level) { - unsigned int level; - - if (sscanf(buf, "%10d", &level) == 1) { - r = fbdev->panel->set_bklight_level(fbdev->panel, - level); - } else - r = -EINVAL; - } else - r = -ENODEV; - return r ? r : size; -} - -static ssize_t omapfb_show_bklight_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct omapfb_device *fbdev = dev_get_drvdata(dev); - int r; - - if (fbdev->panel->get_bklight_level) { - r = snprintf(buf, PAGE_SIZE, "%d\n", - fbdev->panel->get_bklight_max(fbdev->panel)); - } else - r = -ENODEV; - return r; -} - -static struct device_attribute dev_attr_panel_name = - __ATTR(name, 0444, omapfb_show_panel_name, NULL); -static DEVICE_ATTR(backlight_level, 0664, - omapfb_show_bklight_level, omapfb_store_bklight_level); -static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max, NULL); - -static struct attribute *panel_attrs[] = { - &dev_attr_panel_name.attr, - &dev_attr_backlight_level.attr, - &dev_attr_backlight_max.attr, - NULL, -}; - -static struct attribute_group panel_attr_grp = { - .name = "panel", - .attrs = panel_attrs, -}; - -/* ctrl sysfs entries */ -static ssize_t omapfb_show_ctrl_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct omapfb_device *fbdev = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name); -} - -static struct device_attribute dev_attr_ctrl_name = - __ATTR(name, 0444, omapfb_show_ctrl_name, NULL); - -static struct attribute *ctrl_attrs[] = { - &dev_attr_ctrl_name.attr, - NULL, -}; - -static struct attribute_group ctrl_attr_grp = { - .name = "ctrl", - .attrs = ctrl_attrs, -}; - -static int omapfb_register_sysfs(struct omapfb_device *fbdev) -{ - int r; - - if ((r = device_create_file(fbdev->dev, &dev_attr_caps_num))) - goto fail0; - - if ((r = device_create_file(fbdev->dev, &dev_attr_caps_text))) - goto fail1; - - if ((r = sysfs_create_group(&fbdev->dev->kobj, &panel_attr_grp))) - goto fail2; - - if ((r = sysfs_create_group(&fbdev->dev->kobj, &ctrl_attr_grp))) - goto fail3; - - return 0; -fail3: - sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp); -fail2: - device_remove_file(fbdev->dev, &dev_attr_caps_text); -fail1: - device_remove_file(fbdev->dev, &dev_attr_caps_num); -fail0: - dev_err(fbdev->dev, "unable to register sysfs interface\n"); - return r; -} - -static void omapfb_unregister_sysfs(struct omapfb_device *fbdev) -{ - sysfs_remove_group(&fbdev->dev->kobj, &ctrl_attr_grp); - sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp); - device_remove_file(fbdev->dev, &dev_attr_caps_num); - device_remove_file(fbdev->dev, &dev_attr_caps_text); -} - -/* - * --------------------------------------------------------------------------- - * LDM callbacks - * --------------------------------------------------------------------------- - */ -/* Initialize system fb_info object and set the default video mode. - * The frame buffer memory already allocated by lcddma_init - */ -static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info) -{ - struct fb_var_screeninfo *var = &info->var; - struct fb_fix_screeninfo *fix = &info->fix; - int r = 0; - - info->fbops = &omapfb_ops; - info->flags = FBINFO_FLAG_DEFAULT; - - strncpy(fix->id, MODULE_NAME, sizeof(fix->id)); - - info->pseudo_palette = fbdev->pseudo_palette; - - var->accel_flags = def_accel ? FB_ACCELF_TEXT : 0; - var->xres = def_vxres; - var->yres = def_vyres; - var->xres_virtual = def_vxres; - var->yres_virtual = def_vyres; - var->rotate = def_rotate; - var->bits_per_pixel = fbdev->panel->bpp; - - set_fb_var(info, var); - set_fb_fix(info, 1); - - r = fb_alloc_cmap(&info->cmap, 16, 0); - if (r != 0) - dev_err(fbdev->dev, "unable to allocate color map memory\n"); - - return r; -} - -/* Release the fb_info object */ -static void fbinfo_cleanup(struct omapfb_device *fbdev, struct fb_info *fbi) -{ - fb_dealloc_cmap(&fbi->cmap); -} - -static void planes_cleanup(struct omapfb_device *fbdev) -{ - int i; - - for (i = 0; i < fbdev->mem_desc.region_cnt; i++) { - if (fbdev->fb_info[i] == NULL) - break; - fbinfo_cleanup(fbdev, fbdev->fb_info[i]); - framebuffer_release(fbdev->fb_info[i]); - } -} - -static int planes_init(struct omapfb_device *fbdev) -{ - struct fb_info *fbi; - int i; - int r; - - for (i = 0; i < fbdev->mem_desc.region_cnt; i++) { - struct omapfb_plane_struct *plane; - fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct), - fbdev->dev); - if (fbi == NULL) { - dev_err(fbdev->dev, - "unable to allocate memory for plane info\n"); - planes_cleanup(fbdev); - return -ENOMEM; - } - plane = fbi->par; - plane->idx = i; - plane->fbdev = fbdev; - plane->info.mirror = def_mirror; - fbdev->fb_info[i] = fbi; - - if ((r = fbinfo_init(fbdev, fbi)) < 0) { - framebuffer_release(fbi); - planes_cleanup(fbdev); - return r; - } - plane->info.out_width = fbi->var.xres; - plane->info.out_height = fbi->var.yres; - } - return 0; -} - -/* - * Free driver resources. Can be called to rollback an aborted initialization - * sequence. - */ -static void omapfb_free_resources(struct omapfb_device *fbdev, int state) -{ - int i; - - switch (state) { - case OMAPFB_ACTIVE: - for (i = 0; i < fbdev->mem_desc.region_cnt; i++) - unregister_framebuffer(fbdev->fb_info[i]); - case 7: - omapfb_unregister_sysfs(fbdev); - case 6: - fbdev->panel->disable(fbdev->panel); - case 5: - omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED); - case 4: - planes_cleanup(fbdev); - case 3: - ctrl_cleanup(fbdev); - case 2: - fbdev->panel->cleanup(fbdev->panel); - case 1: - dev_set_drvdata(fbdev->dev, NULL); - kfree(fbdev); - case 0: - /* nothing to free */ - break; - default: - BUG(); - } -} - -static int omapfb_find_ctrl(struct omapfb_device *fbdev) -{ - struct omapfb_platform_data *conf; - char name[17]; - int i; - - conf = fbdev->dev->platform_data; - - fbdev->ctrl = NULL; - - strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1); - name[sizeof(name) - 1] = '\0'; - - if (strcmp(name, "internal") == 0) { - fbdev->ctrl = fbdev->int_ctrl; - return 0; - } - - for (i = 0; i < ARRAY_SIZE(ctrls); i++) { - dev_dbg(fbdev->dev, "ctrl %s\n", ctrls[i]->name); - if (strcmp(ctrls[i]->name, name) == 0) { - fbdev->ctrl = ctrls[i]; - break; - } - } - - if (fbdev->ctrl == NULL) { - dev_dbg(fbdev->dev, "ctrl %s not supported\n", name); - return -1; - } - - return 0; -} - -static void check_required_callbacks(struct omapfb_device *fbdev) -{ -#define _C(x) (fbdev->ctrl->x != NULL) -#define _P(x) (fbdev->panel->x != NULL) - BUG_ON(fbdev->ctrl == NULL || fbdev->panel == NULL); - BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) && - _C(set_update_mode) && _C(setup_plane) && _C(enable_plane) && - _P(init) && _P(cleanup) && _P(enable) && _P(disable) && - _P(get_caps))); -#undef _P -#undef _C -} - -/* - * Called by LDM binding to probe and attach a new device. - * Initialization sequence: - * 1. allocate system omapfb_device structure - * 2. select controller type according to platform configuration - * init LCD panel - * 3. init LCD controller and LCD DMA - * 4. init system fb_info structure for all planes - * 5. setup video mode for first plane and enable it - * 6. enable LCD panel - * 7. register sysfs attributes - * OMAPFB_ACTIVE: register system fb_info structure for all planes - */ -static int omapfb_do_probe(struct platform_device *pdev, - struct lcd_panel *panel) -{ - struct omapfb_device *fbdev = NULL; - int init_state; - unsigned long phz, hhz, vhz; - unsigned long vram; - int i; - int r = 0; - - init_state = 0; - - if (pdev->num_resources != 0) { - dev_err(&pdev->dev, "probed for an unknown device\n"); - r = -ENODEV; - goto cleanup; - } - - if (pdev->dev.platform_data == NULL) { - dev_err(&pdev->dev, "missing platform data\n"); - r = -ENOENT; - goto cleanup; - } - - fbdev = kzalloc(sizeof(struct omapfb_device), GFP_KERNEL); - if (fbdev == NULL) { - dev_err(&pdev->dev, - "unable to allocate memory for device info\n"); - r = -ENOMEM; - goto cleanup; - } - init_state++; - - fbdev->dev = &pdev->dev; - fbdev->panel = panel; - fbdev->dssdev = &omapdss_device; - platform_set_drvdata(pdev, fbdev); - - mutex_init(&fbdev->rqueue_mutex); - -#ifdef CONFIG_ARCH_OMAP1 - fbdev->int_ctrl = &omap1_int_ctrl; -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL - fbdev->ext_if = &omap1_ext_if; -#endif -#else /* OMAP2 */ - fbdev->int_ctrl = &omap2_int_ctrl; -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL - fbdev->ext_if = &omap2_ext_if; -#endif -#endif - if (omapfb_find_ctrl(fbdev) < 0) { - dev_err(fbdev->dev, - "LCD controller not found, board not supported\n"); - r = -ENODEV; - goto cleanup; - } - - r = fbdev->panel->init(fbdev->panel, fbdev); - if (r) - goto cleanup; - - pr_info("omapfb: configured for panel %s\n", fbdev->panel->name); - - def_vxres = def_vxres ? def_vxres : fbdev->panel->x_res; - def_vyres = def_vyres ? def_vyres : fbdev->panel->y_res; - - init_state++; - - r = ctrl_init(fbdev); - if (r) - goto cleanup; - if (fbdev->ctrl->mmap != NULL) - omapfb_ops.fb_mmap = omapfb_mmap; - init_state++; - - check_required_callbacks(fbdev); - - r = planes_init(fbdev); - if (r) - goto cleanup; - init_state++; - -#ifdef CONFIG_FB_OMAP_DMA_TUNE - /* Set DMA priority for EMIFF access to highest */ - if (cpu_class_is_omap1()) - omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15); -#endif - - r = ctrl_change_mode(fbdev->fb_info[0]); - if (r) { - dev_err(fbdev->dev, "mode setting failed\n"); - goto cleanup; - } - - /* GFX plane is enabled by default */ - r = fbdev->ctrl->enable_plane(OMAPFB_PLANE_GFX, 1); - if (r) - goto cleanup; - - omapfb_set_update_mode(fbdev, manual_update ? - OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE); - init_state++; - - r = fbdev->panel->enable(fbdev->panel); - if (r) - goto cleanup; - init_state++; - - r = omapfb_register_sysfs(fbdev); - if (r) - goto cleanup; - init_state++; - - vram = 0; - for (i = 0; i < fbdev->mem_desc.region_cnt; i++) { - r = register_framebuffer(fbdev->fb_info[i]); - if (r != 0) { - dev_err(fbdev->dev, - "registering framebuffer %d failed\n", i); - goto cleanup; - } - vram += fbdev->mem_desc.region[i].size; - } - - fbdev->state = OMAPFB_ACTIVE; - - panel = fbdev->panel; - phz = panel->pixel_clock * 1000; - hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw); - vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw); - - omapfb_dev = fbdev; - - pr_info("omapfb: Framebuffer initialized. Total vram %lu planes %d\n", - vram, fbdev->mem_desc.region_cnt); - pr_info("omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz " - "vfreq %lu.%lu Hz\n", - phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10); - - return 0; - -cleanup: - omapfb_free_resources(fbdev, init_state); - - return r; -} - -static int omapfb_probe(struct platform_device *pdev) -{ - int r; - - BUG_ON(fbdev_pdev != NULL); - - r = platform_device_register(&omapdss_device); - if (r) { - dev_err(&pdev->dev, "can't register omapdss device\n"); - return r; - } - - /* Delay actual initialization until the LCD is registered */ - fbdev_pdev = pdev; - if (fbdev_panel != NULL) - omapfb_do_probe(fbdev_pdev, fbdev_panel); - return 0; -} - -void omapfb_register_panel(struct lcd_panel *panel) -{ - BUG_ON(fbdev_panel != NULL); - - fbdev_panel = panel; - if (fbdev_pdev != NULL) - omapfb_do_probe(fbdev_pdev, fbdev_panel); -} - -/* Called when the device is being detached from the driver */ -static int omapfb_remove(struct platform_device *pdev) -{ - struct omapfb_device *fbdev = platform_get_drvdata(pdev); - enum omapfb_state saved_state = fbdev->state; - - /* FIXME: wait till completion of pending events */ - - fbdev->state = OMAPFB_DISABLED; - omapfb_free_resources(fbdev, saved_state); - - platform_device_unregister(&omapdss_device); - fbdev->dssdev = NULL; - - return 0; -} - -/* PM suspend */ -static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - struct omapfb_device *fbdev = platform_get_drvdata(pdev); - - if (fbdev != NULL) - omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]); - return 0; -} - -/* PM resume */ -static int omapfb_resume(struct platform_device *pdev) -{ - struct omapfb_device *fbdev = platform_get_drvdata(pdev); - - if (fbdev != NULL) - omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]); - return 0; -} - -static struct platform_driver omapfb_driver = { - .probe = omapfb_probe, - .remove = omapfb_remove, - .suspend = omapfb_suspend, - .resume = omapfb_resume, - .driver = { - .name = MODULE_NAME, - .owner = THIS_MODULE, - }, -}; - -#ifndef MODULE - -/* Process kernel command line parameters */ -static int __init omapfb_setup(char *options) -{ - char *this_opt = NULL; - int r = 0; - - pr_debug("omapfb: options %s\n", options); - - if (!options || !*options) - return 0; - - while (!r && (this_opt = strsep(&options, ",")) != NULL) { - if (!strncmp(this_opt, "accel", 5)) - def_accel = 1; - else if (!strncmp(this_opt, "vram:", 5)) { - char *suffix; - unsigned long vram; - vram = (simple_strtoul(this_opt + 5, &suffix, 0)); - switch (suffix[0]) { - case '\0': - break; - case 'm': - case 'M': - vram *= 1024; - /* Fall through */ - case 'k': - case 'K': - vram *= 1024; - break; - default: - pr_debug("omapfb: invalid vram suffix %c\n", - suffix[0]); - r = -1; - } - def_vram[def_vram_cnt++] = vram; - } - else if (!strncmp(this_opt, "vxres:", 6)) - def_vxres = simple_strtoul(this_opt + 6, NULL, 0); - else if (!strncmp(this_opt, "vyres:", 6)) - def_vyres = simple_strtoul(this_opt + 6, NULL, 0); - else if (!strncmp(this_opt, "rotate:", 7)) - def_rotate = (simple_strtoul(this_opt + 7, NULL, 0)); - else if (!strncmp(this_opt, "mirror:", 7)) - def_mirror = (simple_strtoul(this_opt + 7, NULL, 0)); - else if (!strncmp(this_opt, "manual_update", 13)) - manual_update = 1; - else { - pr_debug("omapfb: invalid option\n"); - r = -1; - } - } - - return r; -} - -#endif - -/* Register both the driver and the device */ -static int __init omapfb_init(void) -{ -#ifndef MODULE - char *option; - - if (fb_get_options("omapfb", &option)) - return -ENODEV; - omapfb_setup(option); -#endif - /* Register the driver with LDM */ - if (platform_driver_register(&omapfb_driver)) { - pr_debug("failed to register omapfb driver\n"); - return -ENODEV; - } - - return 0; -} - -static void __exit omapfb_cleanup(void) -{ - platform_driver_unregister(&omapfb_driver); -} - -module_param_named(accel, def_accel, uint, 0664); -module_param_array_named(vram, def_vram, ulong, &def_vram_cnt, 0664); -module_param_named(vxres, def_vxres, long, 0664); -module_param_named(vyres, def_vyres, long, 0664); -module_param_named(rotate, def_rotate, uint, 0664); -module_param_named(mirror, def_mirror, uint, 0664); -module_param_named(manual_update, manual_update, bool, 0664); - -module_init(omapfb_init); -module_exit(omapfb_cleanup); - -MODULE_DESCRIPTION("TI OMAP framebuffer driver"); -MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c deleted file mode 100644 index 2c1a3402bef..00000000000 --- a/drivers/video/omap/rfbi.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - * OMAP2 Remote Frame Buffer Interface support - * - * Copyright (C) 2005 Nokia Corporation - * Author: Juha Yrjölä <juha.yrjola@nokia.com> - * 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. - */ -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/err.h> -#include <linux/interrupt.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/platform_device.h> - -#include "omapfb.h" -#include "dispc.h" - -/* To work around an RFBI transfer rate limitation */ -#define OMAP_RFBI_RATE_LIMIT 1 - -#define RFBI_BASE 0x48050800 -#define RFBI_REVISION 0x0000 -#define RFBI_SYSCONFIG 0x0010 -#define RFBI_SYSSTATUS 0x0014 -#define RFBI_CONTROL 0x0040 -#define RFBI_PIXEL_CNT 0x0044 -#define RFBI_LINE_NUMBER 0x0048 -#define RFBI_CMD 0x004c -#define RFBI_PARAM 0x0050 -#define RFBI_DATA 0x0054 -#define RFBI_READ 0x0058 -#define RFBI_STATUS 0x005c -#define RFBI_CONFIG0 0x0060 -#define RFBI_ONOFF_TIME0 0x0064 -#define RFBI_CYCLE_TIME0 0x0068 -#define RFBI_DATA_CYCLE1_0 0x006c -#define RFBI_DATA_CYCLE2_0 0x0070 -#define RFBI_DATA_CYCLE3_0 0x0074 -#define RFBI_VSYNC_WIDTH 0x0090 -#define RFBI_HSYNC_WIDTH 0x0094 - -#define DISPC_BASE 0x48050400 -#define DISPC_CONTROL 0x0040 -#define DISPC_IRQ_FRAMEMASK 0x0001 - -static struct { - void __iomem *base; - void (*lcdc_callback)(void *data); - void *lcdc_callback_data; - unsigned long l4_khz; - int bits_per_cycle; - struct omapfb_device *fbdev; - struct clk *dss_ick; - struct clk *dss1_fck; - unsigned tearsync_pin_cnt; - unsigned tearsync_mode; -} rfbi; - -static inline void rfbi_write_reg(int idx, u32 val) -{ - __raw_writel(val, rfbi.base + idx); -} - -static inline u32 rfbi_read_reg(int idx) -{ - return __raw_readl(rfbi.base + idx); -} - -static int rfbi_get_clocks(void) -{ - rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick"); - if (IS_ERR(rfbi.dss_ick)) { - dev_err(rfbi.fbdev->dev, "can't get ick\n"); - return PTR_ERR(rfbi.dss_ick); - } - - rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "fck"); - if (IS_ERR(rfbi.dss1_fck)) { - dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); - clk_put(rfbi.dss_ick); - return PTR_ERR(rfbi.dss1_fck); - } - - return 0; -} - -static void rfbi_put_clocks(void) -{ - clk_put(rfbi.dss1_fck); - clk_put(rfbi.dss_ick); -} - -static void rfbi_enable_clocks(int enable) -{ - if (enable) { - clk_enable(rfbi.dss_ick); - clk_enable(rfbi.dss1_fck); - } else { - clk_disable(rfbi.dss1_fck); - clk_disable(rfbi.dss_ick); - } -} - - -#ifdef VERBOSE -static void rfbi_print_timings(void) -{ - u32 l; - u32 time; - - l = rfbi_read_reg(RFBI_CONFIG0); - time = 1000000000 / rfbi.l4_khz; - if (l & (1 << 4)) - time *= 2; - - dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time); - l = rfbi_read_reg(RFBI_ONOFF_TIME0); - dev_dbg(rfbi.fbdev->dev, - "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " - "REONTIME %d, REOFFTIME %d\n", - l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f, - (l >> 20) & 0x0f, (l >> 24) & 0x3f); - - l = rfbi_read_reg(RFBI_CYCLE_TIME0); - dev_dbg(rfbi.fbdev->dev, - "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " - "ACCESSTIME %d\n", - (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, - (l >> 22) & 0x3f); -} -#else -static void rfbi_print_timings(void) {} -#endif - -static void rfbi_set_timings(const struct extif_timings *t) -{ - u32 l; - - BUG_ON(!t->converted); - - rfbi_enable_clocks(1); - rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]); - rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]); - - l = rfbi_read_reg(RFBI_CONFIG0); - l &= ~(1 << 4); - l |= (t->tim[2] ? 1 : 0) << 4; - rfbi_write_reg(RFBI_CONFIG0, l); - - rfbi_print_timings(); - rfbi_enable_clocks(0); -} - -static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) -{ - *clk_period = 1000000000 / rfbi.l4_khz; - *max_clk_div = 2; -} - -static int ps_to_rfbi_ticks(int time, int div) -{ - unsigned long tick_ps; - int ret; - - /* Calculate in picosecs to yield more exact results */ - tick_ps = 1000000000 / (rfbi.l4_khz) * div; - - ret = (time + tick_ps - 1) / tick_ps; - - return ret; -} - -#ifdef OMAP_RFBI_RATE_LIMIT -static unsigned long rfbi_get_max_tx_rate(void) -{ - unsigned long l4_rate, dss1_rate; - int min_l4_ticks = 0; - int i; - - /* According to TI this can't be calculated so make the - * adjustments for a couple of known frequencies and warn for - * others. - */ - static const struct { - unsigned long l4_clk; /* HZ */ - unsigned long dss1_clk; /* HZ */ - unsigned long min_l4_ticks; - } ftab[] = { - { 55, 132, 7, }, /* 7.86 MPix/s */ - { 110, 110, 12, }, /* 9.16 MPix/s */ - { 110, 132, 10, }, /* 11 Mpix/s */ - { 120, 120, 10, }, /* 12 Mpix/s */ - { 133, 133, 10, }, /* 13.3 Mpix/s */ - }; - - l4_rate = rfbi.l4_khz / 1000; - dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000; - - for (i = 0; i < ARRAY_SIZE(ftab); i++) { - /* Use a window instead of an exact match, to account - * for different DPLL multiplier / divider pairs. - */ - if (abs(ftab[i].l4_clk - l4_rate) < 3 && - abs(ftab[i].dss1_clk - dss1_rate) < 3) { - min_l4_ticks = ftab[i].min_l4_ticks; - break; - } - } - if (i == ARRAY_SIZE(ftab)) { - /* Can't be sure, return anyway the maximum not - * rate-limited. This might cause a problem only for the - * tearing synchronisation. - */ - dev_err(rfbi.fbdev->dev, - "can't determine maximum RFBI transfer rate\n"); - return rfbi.l4_khz * 1000; - } - return rfbi.l4_khz * 1000 / min_l4_ticks; -} -#else -static int rfbi_get_max_tx_rate(void) -{ - return rfbi.l4_khz * 1000; -} -#endif - - -static int rfbi_convert_timings(struct extif_timings *t) -{ - u32 l; - int reon, reoff, weon, weoff, cson, csoff, cs_pulse; - int actim, recyc, wecyc; - int div = t->clk_div; - - if (div <= 0 || div > 2) - return -1; - - /* Make sure that after conversion it still holds that: - * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, - * csoff > cson, csoff >= max(weoff, reoff), actim > reon - */ - weon = ps_to_rfbi_ticks(t->we_on_time, div); - weoff = ps_to_rfbi_ticks(t->we_off_time, div); - if (weoff <= weon) - weoff = weon + 1; - if (weon > 0x0f) - return -1; - if (weoff > 0x3f) - return -1; - - reon = ps_to_rfbi_ticks(t->re_on_time, div); - reoff = ps_to_rfbi_ticks(t->re_off_time, div); - if (reoff <= reon) - reoff = reon + 1; - if (reon > 0x0f) - return -1; - if (reoff > 0x3f) - return -1; - - cson = ps_to_rfbi_ticks(t->cs_on_time, div); - csoff = ps_to_rfbi_ticks(t->cs_off_time, div); - if (csoff <= cson) - csoff = cson + 1; - if (csoff < max(weoff, reoff)) - csoff = max(weoff, reoff); - if (cson > 0x0f) - return -1; - if (csoff > 0x3f) - return -1; - - l = cson; - l |= csoff << 4; - l |= weon << 10; - l |= weoff << 14; - l |= reon << 20; - l |= reoff << 24; - - t->tim[0] = l; - - actim = ps_to_rfbi_ticks(t->access_time, div); - if (actim <= reon) - actim = reon + 1; - if (actim > 0x3f) - return -1; - - wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div); - if (wecyc < weoff) - wecyc = weoff; - if (wecyc > 0x3f) - return -1; - - recyc = ps_to_rfbi_ticks(t->re_cycle_time, div); - if (recyc < reoff) - recyc = reoff; - if (recyc > 0x3f) - return -1; - - cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div); - if (cs_pulse > 0x3f) - return -1; - - l = wecyc; - l |= recyc << 6; - l |= cs_pulse << 12; - l |= actim << 22; - - t->tim[1] = l; - - t->tim[2] = div - 1; - - t->converted = 1; - - return 0; -} - -static int rfbi_setup_tearsync(unsigned pin_cnt, - unsigned hs_pulse_time, unsigned vs_pulse_time, - int hs_pol_inv, int vs_pol_inv, int extif_div) -{ - int hs, vs; - int min; - u32 l; - - if (pin_cnt != 1 && pin_cnt != 2) - return -EINVAL; - - hs = ps_to_rfbi_ticks(hs_pulse_time, 1); - vs = ps_to_rfbi_ticks(vs_pulse_time, 1); - if (hs < 2) - return -EDOM; - if (pin_cnt == 2) - min = 2; - else - min = 4; - if (vs < min) - return -EDOM; - if (vs == hs) - return -EINVAL; - rfbi.tearsync_pin_cnt = pin_cnt; - dev_dbg(rfbi.fbdev->dev, - "setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n", - pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv); - - rfbi_enable_clocks(1); - rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); - rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); - - l = rfbi_read_reg(RFBI_CONFIG0); - if (hs_pol_inv) - l &= ~(1 << 21); - else - l |= 1 << 21; - if (vs_pol_inv) - l &= ~(1 << 20); - else - l |= 1 << 20; - rfbi_enable_clocks(0); - - return 0; -} - -static int rfbi_enable_tearsync(int enable, unsigned line) -{ - u32 l; - - dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n", - enable, line, rfbi.tearsync_mode); - if (line > (1 << 11) - 1) - return -EINVAL; - - rfbi_enable_clocks(1); - l = rfbi_read_reg(RFBI_CONFIG0); - l &= ~(0x3 << 2); - if (enable) { - rfbi.tearsync_mode = rfbi.tearsync_pin_cnt; - l |= rfbi.tearsync_mode << 2; - } else - rfbi.tearsync_mode = 0; - rfbi_write_reg(RFBI_CONFIG0, l); - rfbi_write_reg(RFBI_LINE_NUMBER, line); - rfbi_enable_clocks(0); - - return 0; -} - -static void rfbi_write_command(const void *buf, unsigned int len) -{ - rfbi_enable_clocks(1); - if (rfbi.bits_per_cycle == 16) { - const u16 *w = buf; - BUG_ON(len & 1); - for (; len; len -= 2) - rfbi_write_reg(RFBI_CMD, *w++); - } else { - const u8 *b = buf; - BUG_ON(rfbi.bits_per_cycle != 8); - for (; len; len--) - rfbi_write_reg(RFBI_CMD, *b++); - } - rfbi_enable_clocks(0); -} - -static void rfbi_read_data(void *buf, unsigned int len) -{ - rfbi_enable_clocks(1); - if (rfbi.bits_per_cycle == 16) { - u16 *w = buf; - BUG_ON(len & ~1); - for (; len; len -= 2) { - rfbi_write_reg(RFBI_READ, 0); - *w++ = rfbi_read_reg(RFBI_READ); - } - } else { - u8 *b = buf; - BUG_ON(rfbi.bits_per_cycle != 8); - for (; len; len--) { - rfbi_write_reg(RFBI_READ, 0); - *b++ = rfbi_read_reg(RFBI_READ); - } - } - rfbi_enable_clocks(0); -} - -static void rfbi_write_data(const void *buf, unsigned int len) -{ - rfbi_enable_clocks(1); - if (rfbi.bits_per_cycle == 16) { - const u16 *w = buf; - BUG_ON(len & 1); - for (; len; len -= 2) - rfbi_write_reg(RFBI_PARAM, *w++); - } else { - const u8 *b = buf; - BUG_ON(rfbi.bits_per_cycle != 8); - for (; len; len--) - rfbi_write_reg(RFBI_PARAM, *b++); - } - rfbi_enable_clocks(0); -} - -static void rfbi_transfer_area(int width, int height, - void (callback)(void * data), void *data) -{ - u32 w; - - BUG_ON(callback == NULL); - - rfbi_enable_clocks(1); - omap_dispc_set_lcd_size(width, height); - - rfbi.lcdc_callback = callback; - rfbi.lcdc_callback_data = data; - - rfbi_write_reg(RFBI_PIXEL_CNT, width * height); - - w = rfbi_read_reg(RFBI_CONTROL); - w |= 1; /* enable */ - if (!rfbi.tearsync_mode) - w |= 1 << 4; /* internal trigger, reset by HW */ - rfbi_write_reg(RFBI_CONTROL, w); - - omap_dispc_enable_lcd_out(1); -} - -static inline void _stop_transfer(void) -{ - u32 w; - - w = rfbi_read_reg(RFBI_CONTROL); - rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0)); - rfbi_enable_clocks(0); -} - -static void rfbi_dma_callback(void *data) -{ - _stop_transfer(); - rfbi.lcdc_callback(rfbi.lcdc_callback_data); -} - -static void rfbi_set_bits_per_cycle(int bpc) -{ - u32 l; - - rfbi_enable_clocks(1); - l = rfbi_read_reg(RFBI_CONFIG0); - l &= ~(0x03 << 0); - - switch (bpc) { - case 8: - break; - case 16: - l |= 3; - break; - default: - BUG(); - } - rfbi_write_reg(RFBI_CONFIG0, l); - rfbi.bits_per_cycle = bpc; - rfbi_enable_clocks(0); -} - -static int rfbi_init(struct omapfb_device *fbdev) -{ - u32 l; - int r; - - rfbi.fbdev = fbdev; - rfbi.base = ioremap(RFBI_BASE, SZ_1K); - if (!rfbi.base) { - dev_err(fbdev->dev, "can't ioremap RFBI\n"); - return -ENOMEM; - } - - if ((r = rfbi_get_clocks()) < 0) - return r; - rfbi_enable_clocks(1); - - rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000; - - /* Reset */ - rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1); - while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0))); - - l = rfbi_read_reg(RFBI_SYSCONFIG); - /* Enable autoidle and smart-idle */ - l |= (1 << 0) | (2 << 3); - rfbi_write_reg(RFBI_SYSCONFIG, l); - - /* 16-bit interface, ITE trigger mode, 16-bit data */ - l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7); - l |= (0 << 9) | (1 << 20) | (1 << 21); - rfbi_write_reg(RFBI_CONFIG0, l); - - rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010); - - l = rfbi_read_reg(RFBI_CONTROL); - /* Select CS0, clear bypass mode */ - l = (0x01 << 2); - rfbi_write_reg(RFBI_CONTROL, l); - - r = omap_dispc_request_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, - NULL); - if (r < 0) { - dev_err(fbdev->dev, "can't get DISPC irq\n"); - rfbi_enable_clocks(0); - return r; - } - - l = rfbi_read_reg(RFBI_REVISION); - pr_info("omapfb: RFBI version %d.%d initialized\n", - (l >> 4) & 0x0f, l & 0x0f); - - rfbi_enable_clocks(0); - - return 0; -} - -static void rfbi_cleanup(void) -{ - omap_dispc_free_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, NULL); - rfbi_put_clocks(); - iounmap(rfbi.base); -} - -const struct lcd_ctrl_extif omap2_ext_if = { - .init = rfbi_init, - .cleanup = rfbi_cleanup, - .get_clk_info = rfbi_get_clk_info, - .get_max_tx_rate = rfbi_get_max_tx_rate, - .set_bits_per_cycle = rfbi_set_bits_per_cycle, - .convert_timings = rfbi_convert_timings, - .set_timings = rfbi_set_timings, - .write_command = rfbi_write_command, - .read_data = rfbi_read_data, - .write_data = rfbi_write_data, - .transfer_area = rfbi_transfer_area, - .setup_tearsync = rfbi_setup_tearsync, - .enable_tearsync = rfbi_enable_tearsync, - - .max_transmit_size = (u32) ~0, -}; - diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c deleted file mode 100644 index f79c137753d..00000000000 --- a/drivers/video/omap/sossi.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - * OMAP1 Special OptimiSed Screen Interface support - * - * Copyright (C) 2004-2005 Nokia Corporation - * Author: Juha Yrjölä <juha.yrjola@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. - */ -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/clk.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/interrupt.h> - -#include <plat/dma.h> - -#include "omapfb.h" -#include "lcdc.h" - -#define MODULE_NAME "omapfb-sossi" - -#define OMAP_SOSSI_BASE 0xfffbac00 -#define SOSSI_ID_REG 0x00 -#define SOSSI_INIT1_REG 0x04 -#define SOSSI_INIT2_REG 0x08 -#define SOSSI_INIT3_REG 0x0c -#define SOSSI_FIFO_REG 0x10 -#define SOSSI_REOTABLE_REG 0x14 -#define SOSSI_TEARING_REG 0x18 -#define SOSSI_INIT1B_REG 0x1c -#define SOSSI_FIFOB_REG 0x20 - -#define DMA_GSCR 0xfffedc04 -#define DMA_LCD_CCR 0xfffee3c2 -#define DMA_LCD_CTRL 0xfffee3c4 -#define DMA_LCD_LCH_CTRL 0xfffee3ea - -#define CONF_SOSSI_RESET_R (1 << 23) - -#define RD_ACCESS 0 -#define WR_ACCESS 1 - -#define SOSSI_MAX_XMIT_BYTES (512 * 1024) - -static struct { - void __iomem *base; - struct clk *fck; - unsigned long fck_hz; - spinlock_t lock; - int bus_pick_count; - int bus_pick_width; - int tearsync_mode; - int tearsync_line; - void (*lcdc_callback)(void *data); - void *lcdc_callback_data; - int vsync_dma_pending; - /* timing for read and write access */ - int clk_div; - u8 clk_tw0[2]; - u8 clk_tw1[2]; - /* - * if last_access is the same as current we don't have to change - * the timings - */ - int last_access; - - struct omapfb_device *fbdev; -} sossi; - -static inline u32 sossi_read_reg(int reg) -{ - return readl(sossi.base + reg); -} - -static inline u16 sossi_read_reg16(int reg) -{ - return readw(sossi.base + reg); -} - -static inline u8 sossi_read_reg8(int reg) -{ - return readb(sossi.base + reg); -} - -static inline void sossi_write_reg(int reg, u32 value) -{ - writel(value, sossi.base + reg); -} - -static inline void sossi_write_reg16(int reg, u16 value) -{ - writew(value, sossi.base + reg); -} - -static inline void sossi_write_reg8(int reg, u8 value) -{ - writeb(value, sossi.base + reg); -} - -static void sossi_set_bits(int reg, u32 bits) -{ - sossi_write_reg(reg, sossi_read_reg(reg) | bits); -} - -static void sossi_clear_bits(int reg, u32 bits) -{ - sossi_write_reg(reg, sossi_read_reg(reg) & ~bits); -} - -#define HZ_TO_PS(x) (1000000000 / (x / 1000)) - -static u32 ps_to_sossi_ticks(u32 ps, int div) -{ - u32 clk_period = HZ_TO_PS(sossi.fck_hz) * div; - return (clk_period + ps - 1) / clk_period; -} - -static int calc_rd_timings(struct extif_timings *t) -{ - u32 tw0, tw1; - int reon, reoff, recyc, actim; - int div = t->clk_div; - - /* - * Make sure that after conversion it still holds that: - * reoff > reon, recyc >= reoff, actim > reon - */ - reon = ps_to_sossi_ticks(t->re_on_time, div); - /* reon will be exactly one sossi tick */ - if (reon > 1) - return -1; - - reoff = ps_to_sossi_ticks(t->re_off_time, div); - - if (reoff <= reon) - reoff = reon + 1; - - tw0 = reoff - reon; - if (tw0 > 0x10) - return -1; - - recyc = ps_to_sossi_ticks(t->re_cycle_time, div); - if (recyc <= reoff) - recyc = reoff + 1; - - tw1 = recyc - tw0; - /* values less then 3 result in the SOSSI block resetting itself */ - if (tw1 < 3) - tw1 = 3; - if (tw1 > 0x40) - return -1; - - actim = ps_to_sossi_ticks(t->access_time, div); - if (actim < reoff) - actim++; - /* - * access time (data hold time) will be exactly one sossi - * tick - */ - if (actim - reoff > 1) - return -1; - - t->tim[0] = tw0 - 1; - t->tim[1] = tw1 - 1; - - return 0; -} - -static int calc_wr_timings(struct extif_timings *t) -{ - u32 tw0, tw1; - int weon, weoff, wecyc; - int div = t->clk_div; - - /* - * Make sure that after conversion it still holds that: - * weoff > weon, wecyc >= weoff - */ - weon = ps_to_sossi_ticks(t->we_on_time, div); - /* weon will be exactly one sossi tick */ - if (weon > 1) - return -1; - - weoff = ps_to_sossi_ticks(t->we_off_time, div); - if (weoff <= weon) - weoff = weon + 1; - tw0 = weoff - weon; - if (tw0 > 0x10) - return -1; - - wecyc = ps_to_sossi_ticks(t->we_cycle_time, div); - if (wecyc <= weoff) - wecyc = weoff + 1; - - tw1 = wecyc - tw0; - /* values less then 3 result in the SOSSI block resetting itself */ - if (tw1 < 3) - tw1 = 3; - if (tw1 > 0x40) - return -1; - - t->tim[2] = tw0 - 1; - t->tim[3] = tw1 - 1; - - return 0; -} - -static void _set_timing(int div, int tw0, int tw1) -{ - u32 l; - -#ifdef VERBOSE - dev_dbg(sossi.fbdev->dev, "Using TW0 = %d, TW1 = %d, div = %d\n", - tw0 + 1, tw1 + 1, div); -#endif - - clk_set_rate(sossi.fck, sossi.fck_hz / div); - clk_enable(sossi.fck); - l = sossi_read_reg(SOSSI_INIT1_REG); - l &= ~((0x0f << 20) | (0x3f << 24)); - l |= (tw0 << 20) | (tw1 << 24); - sossi_write_reg(SOSSI_INIT1_REG, l); - clk_disable(sossi.fck); -} - -static void _set_bits_per_cycle(int bus_pick_count, int bus_pick_width) -{ - u32 l; - - l = sossi_read_reg(SOSSI_INIT3_REG); - l &= ~0x3ff; - l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f); - sossi_write_reg(SOSSI_INIT3_REG, l); -} - -static void _set_tearsync_mode(int mode, unsigned line) -{ - u32 l; - - l = sossi_read_reg(SOSSI_TEARING_REG); - l &= ~(((1 << 11) - 1) << 15); - l |= line << 15; - l &= ~(0x3 << 26); - l |= mode << 26; - sossi_write_reg(SOSSI_TEARING_REG, l); - if (mode) - sossi_set_bits(SOSSI_INIT2_REG, 1 << 6); /* TE logic */ - else - sossi_clear_bits(SOSSI_INIT2_REG, 1 << 6); -} - -static inline void set_timing(int access) -{ - if (access != sossi.last_access) { - sossi.last_access = access; - _set_timing(sossi.clk_div, - sossi.clk_tw0[access], sossi.clk_tw1[access]); - } -} - -static void sossi_start_transfer(void) -{ - /* WE */ - sossi_clear_bits(SOSSI_INIT2_REG, 1 << 4); - /* CS active low */ - sossi_clear_bits(SOSSI_INIT1_REG, 1 << 30); -} - -static void sossi_stop_transfer(void) -{ - /* WE */ - sossi_set_bits(SOSSI_INIT2_REG, 1 << 4); - /* CS active low */ - sossi_set_bits(SOSSI_INIT1_REG, 1 << 30); -} - -static void wait_end_of_write(void) -{ - /* Before reading we must check if some writings are going on */ - while (!(sossi_read_reg(SOSSI_INIT2_REG) & (1 << 3))); -} - -static void send_data(const void *data, unsigned int len) -{ - while (len >= 4) { - sossi_write_reg(SOSSI_FIFO_REG, *(const u32 *) data); - len -= 4; - data += 4; - } - while (len >= 2) { - sossi_write_reg16(SOSSI_FIFO_REG, *(const u16 *) data); - len -= 2; - data += 2; - } - while (len) { - sossi_write_reg8(SOSSI_FIFO_REG, *(const u8 *) data); - len--; - data++; - } -} - -static void set_cycles(unsigned int len) -{ - unsigned long nr_cycles = len / (sossi.bus_pick_width / 8); - - BUG_ON((nr_cycles - 1) & ~0x3ffff); - - sossi_clear_bits(SOSSI_INIT1_REG, 0x3ffff); - sossi_set_bits(SOSSI_INIT1_REG, (nr_cycles - 1) & 0x3ffff); -} - -static int sossi_convert_timings(struct extif_timings *t) -{ - int r = 0; - int div = t->clk_div; - - t->converted = 0; - - if (div <= 0 || div > 8) - return -1; - - /* no CS on SOSSI, so ignore cson, csoff, cs_pulsewidth */ - if ((r = calc_rd_timings(t)) < 0) - return r; - - if ((r = calc_wr_timings(t)) < 0) - return r; - - t->tim[4] = div; - - t->converted = 1; - - return 0; -} - -static void sossi_set_timings(const struct extif_timings *t) -{ - BUG_ON(!t->converted); - - sossi.clk_tw0[RD_ACCESS] = t->tim[0]; - sossi.clk_tw1[RD_ACCESS] = t->tim[1]; - - sossi.clk_tw0[WR_ACCESS] = t->tim[2]; - sossi.clk_tw1[WR_ACCESS] = t->tim[3]; - - sossi.clk_div = t->tim[4]; -} - -static void sossi_get_clk_info(u32 *clk_period, u32 *max_clk_div) -{ - *clk_period = HZ_TO_PS(sossi.fck_hz); - *max_clk_div = 8; -} - -static void sossi_set_bits_per_cycle(int bpc) -{ - int bus_pick_count, bus_pick_width; - - /* - * We set explicitly the the bus_pick_count as well, although - * with remapping/reordering disabled it will be calculated by HW - * as (32 / bus_pick_width). - */ - switch (bpc) { - case 8: - bus_pick_count = 4; - bus_pick_width = 8; - break; - case 16: - bus_pick_count = 2; - bus_pick_width = 16; - break; - default: - BUG(); - return; - } - sossi.bus_pick_width = bus_pick_width; - sossi.bus_pick_count = bus_pick_count; -} - -static int sossi_setup_tearsync(unsigned pin_cnt, - unsigned hs_pulse_time, unsigned vs_pulse_time, - int hs_pol_inv, int vs_pol_inv, int div) -{ - int hs, vs; - u32 l; - - if (pin_cnt != 1 || div < 1 || div > 8) - return -EINVAL; - - hs = ps_to_sossi_ticks(hs_pulse_time, div); - vs = ps_to_sossi_ticks(vs_pulse_time, div); - if (vs < 8 || vs <= hs || vs >= (1 << 12)) - return -EDOM; - vs /= 8; - vs--; - if (hs > 8) - hs = 8; - if (hs) - hs--; - - dev_dbg(sossi.fbdev->dev, - "setup_tearsync: hs %d vs %d hs_inv %d vs_inv %d\n", - hs, vs, hs_pol_inv, vs_pol_inv); - - clk_enable(sossi.fck); - l = sossi_read_reg(SOSSI_TEARING_REG); - l &= ~((1 << 15) - 1); - l |= vs << 3; - l |= hs; - if (hs_pol_inv) - l |= 1 << 29; - else - l &= ~(1 << 29); - if (vs_pol_inv) - l |= 1 << 28; - else - l &= ~(1 << 28); - sossi_write_reg(SOSSI_TEARING_REG, l); - clk_disable(sossi.fck); - - return 0; -} - -static int sossi_enable_tearsync(int enable, unsigned line) -{ - int mode; - - dev_dbg(sossi.fbdev->dev, "tearsync %d line %d\n", enable, line); - if (line >= 1 << 11) - return -EINVAL; - if (enable) { - if (line) - mode = 2; /* HS or VS */ - else - mode = 3; /* VS only */ - } else - mode = 0; - sossi.tearsync_line = line; - sossi.tearsync_mode = mode; - - return 0; -} - -static void sossi_write_command(const void *data, unsigned int len) -{ - clk_enable(sossi.fck); - set_timing(WR_ACCESS); - _set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width); - /* CMD#/DATA */ - sossi_clear_bits(SOSSI_INIT1_REG, 1 << 18); - set_cycles(len); - sossi_start_transfer(); - send_data(data, len); - sossi_stop_transfer(); - wait_end_of_write(); - clk_disable(sossi.fck); -} - -static void sossi_write_data(const void *data, unsigned int len) -{ - clk_enable(sossi.fck); - set_timing(WR_ACCESS); - _set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width); - /* CMD#/DATA */ - sossi_set_bits(SOSSI_INIT1_REG, 1 << 18); - set_cycles(len); - sossi_start_transfer(); - send_data(data, len); - sossi_stop_transfer(); - wait_end_of_write(); - clk_disable(sossi.fck); -} - -static void sossi_transfer_area(int width, int height, - void (callback)(void *data), void *data) -{ - BUG_ON(callback == NULL); - - sossi.lcdc_callback = callback; - sossi.lcdc_callback_data = data; - - clk_enable(sossi.fck); - set_timing(WR_ACCESS); - _set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width); - _set_tearsync_mode(sossi.tearsync_mode, sossi.tearsync_line); - /* CMD#/DATA */ - sossi_set_bits(SOSSI_INIT1_REG, 1 << 18); - set_cycles(width * height * sossi.bus_pick_width / 8); - - sossi_start_transfer(); - if (sossi.tearsync_mode) { - /* - * Wait for the sync signal and start the transfer only - * then. We can't seem to be able to use HW sync DMA for - * this since LCD DMA shows huge latencies, as if it - * would ignore some of the DMA requests from SoSSI. - */ - unsigned long flags; - - spin_lock_irqsave(&sossi.lock, flags); - sossi.vsync_dma_pending++; - spin_unlock_irqrestore(&sossi.lock, flags); - } else - /* Just start the transfer right away. */ - omap_enable_lcd_dma(); -} - -static void sossi_dma_callback(void *data) -{ - omap_stop_lcd_dma(); - sossi_stop_transfer(); - clk_disable(sossi.fck); - sossi.lcdc_callback(sossi.lcdc_callback_data); -} - -static void sossi_read_data(void *data, unsigned int len) -{ - clk_enable(sossi.fck); - set_timing(RD_ACCESS); - _set_bits_per_cycle(sossi.bus_pick_count, sossi.bus_pick_width); - /* CMD#/DATA */ - sossi_set_bits(SOSSI_INIT1_REG, 1 << 18); - set_cycles(len); - sossi_start_transfer(); - while (len >= 4) { - *(u32 *) data = sossi_read_reg(SOSSI_FIFO_REG); - len -= 4; - data += 4; - } - while (len >= 2) { - *(u16 *) data = sossi_read_reg16(SOSSI_FIFO_REG); - len -= 2; - data += 2; - } - while (len) { - *(u8 *) data = sossi_read_reg8(SOSSI_FIFO_REG); - len--; - data++; - } - sossi_stop_transfer(); - clk_disable(sossi.fck); -} - -static irqreturn_t sossi_match_irq(int irq, void *data) -{ - unsigned long flags; - - spin_lock_irqsave(&sossi.lock, flags); - if (sossi.vsync_dma_pending) { - sossi.vsync_dma_pending--; - omap_enable_lcd_dma(); - } - spin_unlock_irqrestore(&sossi.lock, flags); - return IRQ_HANDLED; -} - -static int sossi_init(struct omapfb_device *fbdev) -{ - u32 l, k; - struct clk *fck; - struct clk *dpll1out_ck; - int r; - - sossi.base = ioremap(OMAP_SOSSI_BASE, SZ_1K); - if (!sossi.base) { - dev_err(fbdev->dev, "can't ioremap SoSSI\n"); - return -ENOMEM; - } - - sossi.fbdev = fbdev; - spin_lock_init(&sossi.lock); - - dpll1out_ck = clk_get(fbdev->dev, "ck_dpll1out"); - if (IS_ERR(dpll1out_ck)) { - dev_err(fbdev->dev, "can't get DPLL1OUT clock\n"); - return PTR_ERR(dpll1out_ck); - } - /* - * We need the parent clock rate, which we might divide further - * depending on the timing requirements of the controller. See - * _set_timings. - */ - sossi.fck_hz = clk_get_rate(dpll1out_ck); - clk_put(dpll1out_ck); - - fck = clk_get(fbdev->dev, "ck_sossi"); - if (IS_ERR(fck)) { - dev_err(fbdev->dev, "can't get SoSSI functional clock\n"); - return PTR_ERR(fck); - } - sossi.fck = fck; - - /* Reset and enable the SoSSI module */ - l = omap_readl(MOD_CONF_CTRL_1); - l |= CONF_SOSSI_RESET_R; - omap_writel(l, MOD_CONF_CTRL_1); - l &= ~CONF_SOSSI_RESET_R; - omap_writel(l, MOD_CONF_CTRL_1); - - clk_enable(sossi.fck); - l = omap_readl(ARM_IDLECT2); - l &= ~(1 << 8); /* DMACK_REQ */ - omap_writel(l, ARM_IDLECT2); - - l = sossi_read_reg(SOSSI_INIT2_REG); - /* Enable and reset the SoSSI block */ - l |= (1 << 0) | (1 << 1); - sossi_write_reg(SOSSI_INIT2_REG, l); - /* Take SoSSI out of reset */ - l &= ~(1 << 1); - sossi_write_reg(SOSSI_INIT2_REG, l); - - sossi_write_reg(SOSSI_ID_REG, 0); - l = sossi_read_reg(SOSSI_ID_REG); - k = sossi_read_reg(SOSSI_ID_REG); - - if (l != 0x55555555 || k != 0xaaaaaaaa) { - dev_err(fbdev->dev, - "invalid SoSSI sync pattern: %08x, %08x\n", l, k); - r = -ENODEV; - goto err; - } - - if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) { - dev_err(fbdev->dev, "can't get LCDC IRQ\n"); - r = -ENODEV; - goto err; - } - - l = sossi_read_reg(SOSSI_ID_REG); /* Component code */ - l = sossi_read_reg(SOSSI_ID_REG); - dev_info(fbdev->dev, "SoSSI version %d.%d initialized\n", - l >> 16, l & 0xffff); - - l = sossi_read_reg(SOSSI_INIT1_REG); - l |= (1 << 19); /* DMA_MODE */ - l &= ~(1 << 31); /* REORDERING */ - sossi_write_reg(SOSSI_INIT1_REG, l); - - if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq, - IRQ_TYPE_EDGE_FALLING, - "sossi_match", sossi.fbdev->dev)) < 0) { - dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n"); - goto err; - } - - clk_disable(sossi.fck); - return 0; - -err: - clk_disable(sossi.fck); - clk_put(sossi.fck); - return r; -} - -static void sossi_cleanup(void) -{ - omap_lcdc_free_dma_callback(); - clk_put(sossi.fck); - iounmap(sossi.base); -} - -struct lcd_ctrl_extif omap1_ext_if = { - .init = sossi_init, - .cleanup = sossi_cleanup, - .get_clk_info = sossi_get_clk_info, - .convert_timings = sossi_convert_timings, - .set_timings = sossi_set_timings, - .set_bits_per_cycle = sossi_set_bits_per_cycle, - .setup_tearsync = sossi_setup_tearsync, - .enable_tearsync = sossi_enable_tearsync, - .write_command = sossi_write_command, - .read_data = sossi_read_data, - .write_data = sossi_write_data, - .transfer_area = sossi_transfer_area, - - .max_transmit_size = SOSSI_MAX_XMIT_BYTES, -}; - |
