📄 blizzard.c
字号:
/* * 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 <mach/dma.h>#include <mach/omapfb.h>#include <mach/blizzard.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_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 1struct blizzard_reg_list { int start; int end;};/* These need to be saved / restored separately from the rest. */static struct blizzard_reg_list blizzard_pll_regs[] = { { .start = 0x04, /* Don't save PLL ctrl (0x0C) */ .end = 0x0a, }, { .start = 0x0e, /* Clock configuration */ .end = 0x0e, },};static 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 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; 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_del(&req->entry); list_add(&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;}/* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -