From e563dc81aa01bd8bbb01bc53975a15c398715f62 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 26 Jun 2006 15:57:29 +0300 Subject: [PATCH] ARM: OMAP: omapfb: main and LCD controller module changes - Support for - overlays through separate /dev/fbX nodes - scaling and color space conversion - per-plane memory configuration either in SRAM or SDRAM - Replace custom debug stuff with the default kernel one Signed-off-by: Imre Deak Signed-off-by: Juha Yrjola --- drivers/video/omap/Kconfig | 20 +- drivers/video/omap/Makefile | 2 +- drivers/video/omap/debug.h | 44 -- drivers/video/omap/dispc.c | 626 ++++++++++----------- drivers/video/omap/hwa742.c | 138 ++--- drivers/video/omap/lcdc.c | 386 ++++++------- drivers/video/omap/omapfb_main.c | 844 ++++++++++++++++------------- drivers/video/omap/rfbi.c | 51 +- drivers/video/omap/sossi.c | 316 ++++++----- include/asm-arm/arch-omap/omapfb.h | 128 +++-- 10 files changed, 1258 insertions(+), 1297 deletions(-) delete mode 100644 drivers/video/omap/debug.h diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 6411c95095c..17e94200479 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -27,12 +27,13 @@ config FB_OMAP_MANUAL_UPDATE 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_LPH8923 - bool "Philips LPH8923 LCD support" +config FB_OMAP_LCD_MIPID + bool "MIPI DBI-C/DCS compatible LCD support" depends on FB_OMAP help - Say Y here if you want to have support for the Philips - LPH8923 LCD. + 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 initializaion" @@ -42,6 +43,17 @@ config FB_OMAP_BOOTLOADER_INIT 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 diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index 725ea29c671..444643ef42f 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile @@ -24,7 +24,7 @@ objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o objs-y$(CONFIG_MACH_OMAP_PERSEUS2) += lcd_p2.o objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o -objs-y$(CONFIG_FB_OMAP_LCD_LPH8923) += lcd_lph8923.o +objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o omapfb-objs := $(objs-yy) diff --git a/drivers/video/omap/debug.h b/drivers/video/omap/debug.h deleted file mode 100644 index a280412aeb9..00000000000 --- a/drivers/video/omap/debug.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * File: drivers/video/omap_new/debug.c - * - * Debug support for the omapfb driver - * - * Copyright (C) 2004 Nokia Corporation - * Author: Imre Deak - * - * 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_DEBUG_H -#define __OMAPFB_DEBUG_H - -#ifdef OMAPFB_DBG - -#define DBGPRINT(level, fmt, ...) if (level <= OMAPFB_DBG) do { \ - printk(KERN_DEBUG "%s: "fmt, \ - __FUNCTION__, ## __VA_ARGS__); \ - } while (0) -#define DBGENTER(level) DBGPRINT(level, "Enter\n") -#define DBGLEAVE(level) DBGPRINT(level, "Leave\n") - -#else /* OMAPFB_DBG */ - -#define DBGPRINT(level, format, ...) -#define DBGENTER(level) -#define DBGLEAVE(level) - -#endif /* OMAPFB_DBG */ - -#endif /* __OMAPFB_DEBUG_H */ diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index 3185282887f..67201d2fb77 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c @@ -20,7 +20,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - #include #include #include @@ -34,11 +33,7 @@ #include "dispc.h" -/* #define OMAPFB_DBG 1 */ - -#include "debug.h" - -#define MODULE_NAME "omapfb-dispc" +#define MODULE_NAME "dispc" #define DISPC_BASE 0x48050400 @@ -134,8 +129,6 @@ #define MAX_PALETTE_SIZE (256 * 16) -#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args) - #define FLD_MASK(pos, len) (((1 << len) - 1) << pos) #define MOD_REG_FLD(reg, mask, val) \ @@ -144,22 +137,11 @@ static struct { u32 base; - dma_addr_t fb_sram_paddr; - u32 fb_sram_size; - int fb_sram_lines; - - dma_addr_t fb_sdram_paddr; - void *fb_sdram_vaddr; - u32 fb_sdram_size; - int fb_sdram_lines; + struct omapfb_mem_desc mem_desc; dma_addr_t palette_paddr; void *palette_vaddr; - void *fb_kern_vaddr; - - int multiplane_head; - int ext_mode; int fbmem_allocated; @@ -168,11 +150,16 @@ static struct { void *irq_callback_data; 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 inline dispc_write_reg(int idx, u32 val) @@ -302,22 +289,31 @@ static inline int _setup_plane(int plane, int channel_out, 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_SIZE, - DISPC_VID2_BASE + DISPC_VID_SIZE }; + 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; - DBGPRINT(2, "plane %d channel %d paddr %u scr_width %d pos_x %d pos_y %d " - "width %d height %d color_mode %d\n", +#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; @@ -327,6 +323,7 @@ static inline int _setup_plane(int plane, int channel_out, case OMAPFB_PLANE_VID2: burst_shift = 14; chout_shift = 16; + set_vsize = 1; break; default: return -EINVAL; @@ -343,22 +340,25 @@ static inline int _setup_plane(int plane, int channel_out, 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) + if (plane == 0) return -EINVAL; color_code = DISPC_UYVY_422; + cconv_en = 1; bpp = 16; break; - case OMAPFB_COLOR_YUV420: - if (plane != 0) + case OMAPFB_COLOR_YUY422: + if (plane == 0) return -EINVAL; color_code = DISPC_YUV2_422; - bpp = 12; + cconv_en = 1; + bpp = 16; break; default: return -EINVAL; @@ -368,6 +368,8 @@ static inline int _setup_plane(int plane, int channel_out, l &= ~(0x0f << 1); l |= color_code << 1; + l &= ~(1 << 9); + l |= cconv_en << 9; l &= ~(0x03 << burst_shift); l |= DISPC_BURST_8x32 << burst_shift; @@ -384,53 +386,145 @@ static inline int _setup_plane(int plane, int channel_out, 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_hinc[plane]) + MOD_REG_FLD(vs_reg[plane], + FLD_MASK(16, 11), (height - 1) << 16); + if (!dispc.fir_vinc[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, + unsigned long offset, + int screen_width, int pos_x, int pos_y, int width, int height, int color_mode) { - int yspan; u32 paddr; - int mp_head = -1; - int r; - if (offset > dispc.fb_sram_size + dispc.fb_sdram_size) + if ((unsigned)plane > dispc.mem_desc.region_cnt) return -EINVAL; + paddr = dispc.mem_desc.region[plane].paddr + offset; + return _setup_plane(plane, channel_out, paddr, + screen_width, + pos_x, pos_y, width, height, color_mode); +} - if (offset < dispc.fb_sram_size) { - paddr = dispc.fb_sram_paddr + offset; - yspan = min_t(int, height, dispc.fb_sram_lines); - if (yspan) { - if ((r = _setup_plane(plane, channel_out, paddr, - screen_width, pos_x, pos_y, - width, height, color_mode)) < 0) - return r; - offset += r; - height -= yspan; - pos_y += yspan; - mp_head = plane; - if (++plane > 2) - plane = OMAPFB_PLANE_GFX; - } +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]); } - if (height) { - offset -= dispc.fb_sram_size; - paddr = dispc.fb_sdram_paddr + offset; - yspan = min_t(int, height, dispc.fb_sdram_lines); - if (yspan) { - if ((r = _setup_plane(plane, channel_out, paddr, - screen_width, pos_x, pos_y, - width, height, color_mode)) < 0) - return r; - if (mp_head != -1) - dispc.multiplane_head = mp_head; - } +} + +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; + + 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) + return -EINVAL; + set_upsampling_coef_table(plane); + } else if (orig_width > out_width) { + /* Downsampling not yet supported + */ + 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); return 0; } @@ -439,17 +533,10 @@ 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 }; - DBGENTER(2); - - if ((unsigned int)plane > 2) + DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES }; + if ((unsigned int)plane > dispc.mem_desc.region_cnt) return -EINVAL; MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0); - if (plane == dispc.multiplane_head) { - if (++plane > 2) - plane = OMAPFB_PLANE_GFX; - MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0); - } return 0; } @@ -492,6 +579,14 @@ static int omap_dispc_set_color_key(struct omapfb_color_key *ck) dispc_write_reg(tr_reg, ck->trans_key); dispc_write_reg(df_reg, ck->background); + dispc.color_key = *ck; + + return 0; +} + +static int omap_dispc_get_color_key(struct omapfb_color_key *ck) +{ + *ck = dispc.color_key; return 0; } @@ -503,8 +598,6 @@ static int omap_dispc_set_update_mode(enum omapfb_update_mode mode) { int r = 0; - DBGENTER(1); - if (mode != dispc.update_mode) { switch (mode) { case OMAPFB_AUTO_UPDATE: @@ -517,7 +610,8 @@ static int omap_dispc_set_update_mode(enum omapfb_update_mode mode) omap_dispc_enable_lcd_out(0); if (!wait_for_completion_timeout(&dispc.frame_done, msecs_to_jiffies(500))) { - pr_err("timeout waiting for FRAME DONE\n"); + dev_err(dispc.fbdev->dev, + "timeout waiting for FRAME DONE\n"); } dispc.update_mode = mode; break; @@ -526,16 +620,62 @@ static int omap_dispc_set_update_mode(enum omapfb_update_mode mode) } } - DBGLEAVE(1); - return r; } +static unsigned long omap_dispc_get_caps(void) +{ + return 0; +} + 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, + }; +#if 0 + const struct color_conv_coef ctbl_bt601_5_full = { + 256, 351, 0, 256, -179, -86, 256, 0, 443, 1, + }, ctbl_bt709 = { + 298, 459, 0, 298, -137, -55, 298, 0, 541, 0, + }, ctbl_bt709_f = { + 256, 394, 0, 256, -118, -47, 256, 0, 465, 1, }, +#endif + 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; @@ -556,8 +696,7 @@ static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div) BUG_ON(*lck_div < 1); if (*lck_div > 255) { *lck_div = 255; - printk(KERN_WARNING - MODULE_NAME ": pixclock %d kHz too low.\n", + dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n", pck / 1000); } } @@ -579,8 +718,6 @@ static void set_lcd_timings(void) int is_tft = panel->config & OMAP_LCDC_PANEL_TFT; unsigned long fck; - DBGENTER(1); - 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; @@ -659,16 +796,15 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev, struct pt_regs *re u32 stat = dispc_read_reg(DISPC_IRQSTATUS); static int jabber; - DBGENTER(2); - if (stat & DISPC_IRQ_FRAMEMASK) complete(&dispc.frame_done); if (stat & DISPC_IRQ_MASK_ERROR) { if (jabber++ < 5) { - pr_err("irq error status %04x\n", stat & 0x7fff); + dev_err(dispc.fbdev->dev, "irq error status %04x\n", + stat & 0x7fff); } else { - pr_err("disable irq\n"); + dev_err(dispc.fbdev->dev, "disable irq\n"); dispc_write_reg(DISPC_IRQENABLE, 0); } } @@ -684,19 +820,19 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev, struct pt_regs *re static int get_dss_clocks(void) { if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) { - pr_err("can't get dss_ick"); + dev_err(dispc.fbdev->dev, "can't get dss_ick"); return PTR_ERR(dispc.dss_ick); } if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) { - pr_err("can't get dss1_fck"); + dev_err(dispc.fbdev->dev, "can't get dss1_fck"); clk_put(dispc.dss_ick); return PTR_ERR(dispc.dss1_fck); } if (IS_ERR((dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "dss_54m_fck")))) { - pr_err("can't get dss_54m_fck"); + dev_err(dispc.fbdev->dev, "can't get dss_54m_fck"); clk_put(dispc.dss_ick); clk_put(dispc.dss1_fck); return PTR_ERR(dispc.dss_54m_fck); @@ -733,199 +869,69 @@ static void enable_digit_clocks(int enable) static void omap_dispc_suspend(void) { - DBGENTER(1); - 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))) { - pr_err("timeout waiting for FRAME DONE\n"); + dev_err(dispc.fbdev->dev, + "timeout waiting for FRAME DONE\n"); } enable_lcd_clocks(0); } - - DBGLEAVE(1); } static void omap_dispc_resume(void) { - DBGENTER(1); - if (dispc.update_mode == OMAPFB_AUTO_UPDATE) { enable_lcd_clocks(1); set_lcd_timings(); load_palette(); omap_dispc_enable_lcd_out(1); } - - DBGLEAVE(1); } -static int omap_dispc_update_window(struct omapfb_update_window *win, +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; } -/* Greatest common divisor */ -static int calc_gcd(int a, int b) -{ - int tmp; - - if (a < b) { - tmp = a; - a = b; - b = tmp; - } - for (;;) { - tmp = a % b; - if (tmp != 0) { - a = b; - b = tmp; - } else - break; - } - - return b; -} - -/* Least common multiple */ -static int calc_lcm(int a, int b) -{ - return a * b / calc_gcd(a, b); -} - -static void omap_dispc_get_vram_layout(unsigned long *size, void **virt, - dma_addr_t *phys) -{ - *size = dispc.fb_sram_size + dispc.fb_sdram_size; - *virt = dispc.fb_kern_vaddr; - /* Physical vram might not be contiguous. No one except own mmap - * should use this addr. - */ - *phys = 0; -} - -static int omap_dispc_mmap_user(struct vm_area_struct *vma) -{ - unsigned long len; - unsigned long offset; - unsigned long vaddr; - int r; - - DBGPRINT(1, "vm_pgoff 0x%08lx vm_start 0x%08lx vm_end 0x%08lx\n", - vma->vm_pgoff, vma->vm_start, vma->vm_end); - - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) - return -EINVAL; - offset = vma->vm_pgoff << PAGE_SHIFT; - - if (offset >= dispc.fb_sram_size + dispc.fb_sdram_size) - return -EINVAL; - - len = vma->vm_end - vma->vm_start; - if (offset + len > dispc.fb_sram_size + dispc.fb_sdram_size) - return -EINVAL; - - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - vma->vm_flags |= VM_PFNMAP; - - vaddr = vma->vm_start; - - if (dispc.fb_sram_size) { - if (offset < dispc.fb_sram_size) { - int chunk = min_t(int, dispc.fb_sram_size - offset, len); - DBGPRINT(1, "map sram va %08lx pa %08lx size %d\n", - vaddr, dispc.fb_sram_paddr + offset, chunk); - r = io_remap_pfn_range(vma, vaddr, - (dispc.fb_sram_paddr + - offset) >> PAGE_SHIFT, chunk, - vma->vm_page_prot); - if (r == -EINVAL) - return r; - if (r < 0) - return -EAGAIN; - - vaddr += chunk; - len -= chunk; - offset = 0; - } else - offset -= dispc.fb_sram_size; - } - - if (len) { - DBGPRINT(1, "map sdram va %08lx pa %08lx size %ld\n", - vaddr, dispc.fb_sdram_paddr + offset, len); - BUG_ON(offset > dispc.fb_sdram_size || - offset + len > dispc.fb_sdram_size || - vma->vm_end - vaddr != len); - r = io_remap_pfn_range(vma, vaddr, (dispc.fb_sdram_paddr + - offset) >> PAGE_SHIFT, len, - vma->vm_page_prot); - /* no teardown of the previous mapping here. - * do_mmap_pgoff will take core of that. */ - if (r == -EINVAL) - return r; - if (r < 0) - return -EAGAIN; - } - - return 0; -} - -static int mmap_kern(void) +static int mmap_kern(struct omapfb_mem_region *region) { struct vm_struct *kvma; struct vm_area_struct vma; pgprot_t pgprot; unsigned long vaddr; - DBGENTER(1); - - kvma = get_vm_area(dispc.fb_sram_size + dispc.fb_sdram_size, VM_IOREMAP); + kvma = get_vm_area(region->size, VM_IOREMAP); if (kvma == NULL) { - pr_err("can't get kernel vm area\n"); + dev_err(dispc.fbdev->dev, "can't get kernel vm area\n"); return -ENOMEM; } vma.vm_mm = &init_mm; - dispc.fb_kern_vaddr = kvma->addr; vaddr = (unsigned long)kvma->addr; pgprot = pgprot_writecombine(pgprot_kernel); - if (dispc.fb_sram_size) { - vma.vm_start = vaddr; - vma.vm_end = vaddr + dispc.fb_sram_size; - if (io_remap_pfn_range(&vma, vaddr, - dispc.fb_sram_paddr >> PAGE_SHIFT, - dispc.fb_sram_size, pgprot) < 0) { - pr_err("kernel mmap for FBMEM failed\n"); - return -EAGAIN; - } - vaddr += dispc.fb_sram_size; - } - if (dispc.fb_sdram_size) { - vma.vm_start = vaddr; - vma.vm_end = vaddr + dispc.fb_sdram_size; - if (io_remap_pfn_range(&vma, vaddr, - dispc.fb_sdram_paddr >> PAGE_SHIFT, - dispc.fb_sdram_size, pgprot) < 0) { - pr_err("kernel mmap for FBMEM failed\n"); - return -EAGAIN; - } + 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; } - - DBGLEAVE(1); + region->vaddr = (void *)vaddr; return 0; } -static void unmap_kern(void) +static void unmap_kern(struct omapfb_mem_region *region) { - vunmap(dispc.fb_kern_vaddr); + vunmap(region->vaddr); } static int alloc_palette_ram(void) @@ -933,7 +939,7 @@ 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) { - pr_err("failed to alloc palette memory\n"); + dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n"); return -ENOMEM; } @@ -946,107 +952,76 @@ static void free_palette_ram(void) dispc.palette_vaddr, dispc.palette_paddr); } -static int alloc_fbmem(int req_size) +static int alloc_fbmem(struct omapfb_mem_region *region) { - int frame_size; - struct lcd_panel *panel = dispc.fbdev->panel; + region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev, + region->size, ®ion->paddr, GFP_KERNEL); - frame_size = PAGE_ALIGN(panel->x_res * panel->bpp / 8 * panel->y_res); - if (req_size > frame_size) - frame_size = req_size; - dispc.fb_sdram_size = PAGE_ALIGN(MAX_PALETTE_SIZE) + frame_size; - dispc.fb_kern_vaddr = dma_alloc_writecombine(dispc.fbdev->dev, - dispc.fb_sdram_size, &dispc.fb_sdram_paddr, GFP_KERNEL); - - if (dispc.fb_kern_vaddr == 0) { - pr_err("unable to allocate fb DMA memory\n"); + if (region->vaddr == NULL) { + dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n"); return -ENOMEM; } return 0; } -static void free_fbmem(void) +static void free_fbmem(struct omapfb_mem_region *region) { - dma_free_writecombine(dispc.fbdev->dev, dispc.fb_sdram_size, - dispc.fb_kern_vaddr, dispc.fb_sdram_paddr); + dma_free_writecombine(dispc.fbdev->dev, region->size, + region->vaddr, region->paddr); } -static int setup_fbmem(int req_size) +static int setup_fbmem(struct omapfb_mem_desc *req_md) { - struct lcd_panel *panel = dispc.fbdev->panel; - struct omapfb_platform_data *conf; - unsigned long size_align; - int line_size; - int frame_size; - int lines; + struct omapfb_mem_region *rg; + int i; int r; - conf = dispc.fbdev->dev->platform_data; - - if (conf->fbmem.fb_sram_size + conf->fbmem.fb_sdram_size == 0) { - if ((r = alloc_fbmem(req_size)) < 0) - return r; - dispc.fbmem_allocated = 1; - dispc.fb_sdram_lines = panel->y_res; - return 0; + if (!req_md->region_cnt) { + dev_err(dispc.fbdev->dev, "no memory regions defined\n"); + return -ENOENT; } - dispc.fb_sram_paddr = conf->fbmem.fb_sram_start; - dispc.fb_sram_size = conf->fbmem.fb_sram_size; - dispc.fb_sdram_paddr = conf->fbmem.fb_sdram_start; - dispc.fb_sdram_size = conf->fbmem.fb_sdram_size; - - line_size = panel->x_res * panel->bpp / 8; - frame_size = PAGE_ALIGN(line_size * panel->y_res); + rg = &req_md->region[0]; - size_align = calc_lcm(line_size, PAGE_SIZE); - - if (dispc.fb_sram_size + dispc.fb_sdram_size < frame_size || - (dispc.fb_sdram_size && (dispc.fb_sram_size % size_align))) { - pr_err("Invalid FB memory configuration\n"); - return -EINVAL; - } - - if (dispc.fb_sram_size + dispc.fb_sdram_size < req_size) { - pr_err("%d vram was requested, but only %u is available\n", - req_size, dispc.fb_sram_size + dispc.fb_sdram_size); + for (i = 0; i < req_md->region_cnt; i++, rg++) { + if (rg->paddr) { + rg->alloc = 0; + if ((r = mmap_kern(rg)) < 0) + return r; + } else { + rg->alloc = 1; + if ((r = alloc_fbmem(rg)) < 0) + return r; + } } - lines = dispc.fb_sram_size / line_size; - lines = min_t(int, panel->y_res, lines); - dispc.fb_sram_lines = lines; - lines = panel->y_res - lines; - dispc.fb_sdram_lines = lines; - - if ((r = mmap_kern()) < 0) - return r; - - DBGPRINT(1, "fb_sram %08x size %08x fb_sdram %08x size %08x\n", - dispc.fb_sram_paddr, dispc.fb_sram_size, - dispc.fb_sdram_paddr, dispc.fb_sdram_size); + dispc.mem_desc = *req_md; return 0; } static void cleanup_fbmem(void) { - if (dispc.fbmem_allocated) - free_fbmem(); - else - unmap_kern(); + int i; + + for (i = 0; i < dispc.mem_desc.region_cnt; i++) { + if (dispc.mem_desc.region[i].alloc) + free_fbmem(&dispc.mem_desc.region[i]); + else + unmap_kern(&dispc.mem_desc.region[i]); + } } static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, - int req_vram_size) + struct omapfb_mem_desc *req_vram) { int r; u32 l; struct lcd_panel *panel = fbdev->panel; int tmo = 10000; int skip_init = 0; - - DBGENTER(1); + int i; memset(&dispc, 0, sizeof(dispc)); @@ -1054,13 +1029,6 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, dispc.fbdev = fbdev; dispc.ext_mode = ext_mode; - dispc.multiplane_head = -1; - - if (fbdev->dev->platform_data == NULL) { - pr_err("missing FB configuration\n"); - return -ENOENT; - } - init_completion(&dispc.frame_done); if ((r = get_dss_clocks()) < 0) @@ -1068,14 +1036,11 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, enable_lcd_clocks(1); - l = dispc_read_reg(DISPC_REVISION); - pr_info(MODULE_NAME ": version %d.%d\n", l >> 4 & 0x0f, l & 0x0f); - #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT l = dispc_read_reg(DISPC_CONTROL); /* LCD enabled ? */ if (l & 1) { - pr_info(MODULE_NAME ": skipping hardware initialization\n"); + pr_info("omapfb: skipping hardware initialization\n"); skip_init = 1; } #endif @@ -1089,7 +1054,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) { if (!--tmo) { - pr_err("soft reset failed\n"); + dev_err(dispc.fbdev->dev, "soft reset failed\n"); r = -ENODEV; enable_digit_clocks(0); goto fail1; @@ -1106,8 +1071,8 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK); if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler, - 0, MODULE_NAME, NULL)) < 0) { - pr_err("can't get DSS IRQ\n"); + 0, MODULE_NAME, fbdev)) < 0) { + dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n"); goto fail1; } @@ -1117,12 +1082,14 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, if ((r = alloc_palette_ram()) < 0) goto fail2; - if ((r = setup_fbmem(req_vram_size)) < 0) + if ((r = setup_fbmem(req_vram)) < 0) goto fail3; if (!skip_init) { - memset(dispc.fb_kern_vaddr, 0, - dispc.fb_sram_size + dispc.fb_sdram_size); + 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); @@ -1132,22 +1099,29 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, setup_plane_fifo(1); setup_plane_fifo(2); + setup_color_conv_coef(); + set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT); - set_lcd_data_lines(panel->data_lines); 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); + return 0; fail3: free_palette_ram(); fail2: - free_irq(INT_24XX_DSS_IRQ, NULL); + free_irq(INT_24XX_DSS_IRQ, fbdev); fail1: enable_lcd_clocks(0); put_dss_clocks(); @@ -1164,17 +1138,10 @@ static void omap_dispc_cleanup(void) put_dss_clocks(); } -static unsigned long omap_dispc_get_caps(void) -{ - return 0; -} - -struct lcd_ctrl omap2_int_ctrl = { +const struct lcd_ctrl omap2_int_ctrl = { .name = "internal", .init = omap_dispc_init, .cleanup = omap_dispc_cleanup, - .get_vram_layout = omap_dispc_get_vram_layout, - .mmap = omap_dispc_mmap_user, .get_caps = omap_dispc_get_caps, .set_update_mode = omap_dispc_set_update_mode, .get_update_mode = omap_dispc_get_update_mode, @@ -1182,9 +1149,8 @@ struct lcd_ctrl omap2_int_ctrl = { .suspend = omap_dispc_suspend, .resume = omap_dispc_resume, .setup_plane = omap_dispc_setup_plane, + .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, }; - -MODULE_DESCRIPTION("TI OMAP LCDC controller"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index f466c4b5b2b..0f8e2fbee71 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c @@ -32,11 +32,7 @@ #include #include -/* #define OMAPFB_DBG 1 */ - -#include "debug.h" - -#define MODULE_NAME "omapfb-hwa742" +#define MODULE_NAME "hwa742" #define HWA742_REV_CODE_REG 0x0 #define HWA742_CONFIG_REG 0x2 @@ -80,23 +76,21 @@ #define HWA742_AUTO_UPDATE_TIME (HZ / 20) -#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args) - /* 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; }; -#define REQ_FROM_IRQ_POOL 0x01 - -#define REQ_COMPLETE 0 -#define REQ_PENDING 1 - struct hwa742_request { struct list_head entry; unsigned int flags; @@ -111,7 +105,7 @@ struct hwa742_request { } par; }; -struct hwa742_struct { +struct { enum omapfb_update_mode update_mode; enum omapfb_update_mode update_mode_before_suspend; @@ -140,6 +134,8 @@ struct hwa742_struct { struct lcd_ctrl *int_ctrl; } hwa742; +struct lcd_ctrl hwa742_ctrl; + static u8 hwa742_read_reg(u8 reg) { u8 data; @@ -186,10 +182,14 @@ 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); - DBGPRINT(2, "hwa742: enabled pixel doubling\n"); +#ifdef VERBOSE + dev_dbg(hwa742.fbdev->dev, "hwa742: enabled pixel doubling\n"); +#endif } else { hwa742.window_type = (hwa742.window_type & 0xfc); - DBGPRINT(2, "hwa742: disabled pixel doubling\n"); +#ifdef VERBOSE + dev_dbg(hwa742.fbdev->dev, "hwa742: disabled pixel doubling\n"); +#endif } hwa742_write_reg(HWA742_INPUT_MODE_REG, conv); @@ -239,8 +239,6 @@ static void process_pending_requests(void) { unsigned long flags; - DBGENTER(2); - spin_lock_irqsave(&hwa742.req_lock, flags); while (!list_empty(&hwa742.pending_req_list)) { @@ -266,8 +264,6 @@ static void process_pending_requests(void) } spin_unlock_irqrestore(&hwa742.req_lock, flags); - - DBGLEAVE(2); } static void submit_req_list(struct list_head *head) @@ -275,8 +271,6 @@ static void submit_req_list(struct list_head *head) unsigned long flags; int process = 1; - DBGENTER(2); - spin_lock_irqsave(&hwa742.req_lock, flags); if (likely(!list_empty(&hwa742.pending_req_list))) process = 0; @@ -285,8 +279,6 @@ static void submit_req_list(struct list_head *head) if (process) process_pending_requests(); - - DBGLEAVE(2); } static void request_complete(void *data) @@ -320,8 +312,11 @@ static int send_frame_handler(struct hwa742_request *req) int flags = par->flags; int scr_width = 800; - DBGPRINT(2, "x %d y %d w %d h %d scr_width %d color_mode %d flags %d\n", +#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: @@ -425,13 +420,9 @@ static void create_req_list(struct omapfb_update_window *win, static void auto_update_complete(void *data) { - DBGENTER(2); - if (!hwa742.stop_auto_update) mod_timer(&hwa742.auto_update_timer, jiffies + HWA742_AUTO_UPDATE_TIME); - - DBGLEAVE(2); } static void hwa742_update_window_auto(unsigned long arg) @@ -439,8 +430,6 @@ static void hwa742_update_window_auto(unsigned long arg) LIST_HEAD(req_list); struct hwa742_request *last; - DBGENTER(2); - create_req_list(&hwa742.auto_update_window, &req_list); last = list_entry(req_list.prev, struct hwa742_request, entry); @@ -448,11 +437,10 @@ static void hwa742_update_window_auto(unsigned long arg) last->complete_data = NULL; submit_req_list(&req_list); - - DBGLEAVE(2); } -int hwa742_update_window_async(struct omapfb_update_window *win, +int hwa742_update_window_async(struct fb_info *fbi, + struct omapfb_update_window *win, void (*complete_callback)(void *arg), void *complete_callback_data) { @@ -460,15 +448,13 @@ int hwa742_update_window_async(struct omapfb_update_window *win, struct hwa742_request *last; int r = 0; - DBGENTER(2); - if (hwa742.update_mode != OMAPFB_MANUAL_UPDATE) { - DBGPRINT(1, "invalid update mode\n"); + dev_dbg(hwa742.fbdev->dev, "invalid update mode\n"); r = -EINVAL; goto out; } if (unlikely(win->format & ~(0x03 | OMAPFB_FORMAT_FLAG_DOUBLE))) { - DBGPRINT(1, "invalid window flag"); + dev_dbg(hwa742.fbdev->dev, "invalid window flag"); r = -EINVAL; goto out; } @@ -482,7 +468,6 @@ int hwa742_update_window_async(struct omapfb_update_window *win, submit_req_list(&req_list); out: - DBGLEAVE(2); return r; } EXPORT_SYMBOL(hwa742_update_window_async); @@ -521,8 +506,6 @@ static void hwa742_sync(void) struct hwa742_request *req; struct completion comp; - DBGENTER(2); - req = alloc_req(); req->handler = sync_handler; @@ -534,13 +517,11 @@ static void hwa742_sync(void) submit_req_list(&req_list); wait_for_completion(&comp); - - DBGLEAVE(2); } static void hwa742_bind_client(struct omapfb_notifier_block *nb) { - DBGPRINT(1, "update_mode %d\n", hwa742.update_mode); + 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); } @@ -548,20 +529,14 @@ static void hwa742_bind_client(struct omapfb_notifier_block *nb) static int hwa742_set_update_mode(enum omapfb_update_mode mode) { - int r = 0; - - DBGENTER(1); - if (mode != OMAPFB_MANUAL_UPDATE && mode != OMAPFB_AUTO_UPDATE && - mode != OMAPFB_UPDATE_DISABLED) { - r = -EINVAL; - goto out; - } + mode != OMAPFB_UPDATE_DISABLED) + return -EINVAL; if (mode == hwa742.update_mode) - goto out; + return 0; - printk(KERN_INFO "hwa742: setting update mode to %s\n", + pr_info("omapfb: hwa742: setting update mode to %s\n", mode == OMAPFB_UPDATE_DISABLED ? "disabled" : (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual")); @@ -591,10 +566,8 @@ static int hwa742_set_update_mode(enum omapfb_update_mode mode) case OMAPFB_UPDATE_DISABLED: break; } -out: - DBGLEAVE(1); - return r; + return 0; } static enum omapfb_update_mode hwa742_get_update_mode(void) @@ -622,7 +595,7 @@ static int calc_reg_timing(unsigned long sysclk, int div) * WriteCycle = 2*SYSCLK + 2 ns, * CSPulseWidth = 10 ns */ systim = 1000000000 / (sysclk / 1000); - DBGPRINT(1, "HWA742 systim %lu ps extif_clk_period %u ps" + 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; @@ -643,12 +616,12 @@ static int calc_reg_timing(unsigned long sysclk, int div) t->re_cycle_time = t->re_off_time; t->cs_pulse_width = 0; - DBGPRINT(1, "[reg]cson %d csoff %d reon %d reoff %d\n", + 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); - DBGPRINT(1, "[reg]weon %d weoff %d recyc %d wecyc %d\n", + 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); - DBGPRINT(1, "[reg]rdaccess %d cspulse %d\n", + dev_dbg(hwa742.fbdev->dev, "[reg]rdaccess %d cspulse %d\n", t->access_time, t->cs_pulse_width); return hwa742.extif->convert_timings(t); @@ -669,7 +642,7 @@ static int calc_lut_timing(unsigned long sysclk, int div) * CSPulseWidth = 10 ns */ systim = 1000000000 / (sysclk / 1000); - DBGPRINT(1, "HWA742 systim %lu ps extif_clk_period %u ps" + 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; @@ -694,12 +667,12 @@ static int calc_lut_timing(unsigned long sysclk, int div) t->re_cycle_time = t->re_off_time; t->cs_pulse_width = 0; - DBGPRINT(1, "[lut]cson %d csoff %d reon %d reoff %d\n", + 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); - DBGPRINT(1, "[lut]weon %d weoff %d recyc %d wecyc %d\n", + 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); - DBGPRINT(1, "[lut]rdaccess %d cspulse %d\n", + dev_dbg(hwa742.fbdev->dev, "[lut]rdaccess %d cspulse %d\n", t->access_time, t->cs_pulse_width); return hwa742.extif->convert_timings(t); @@ -727,7 +700,7 @@ static int calc_extif_timings(unsigned long sysclk) return 0; err: - pr_err("can't setup timings\n"); + dev_err(hwa742.fbdev->dev, "can't setup timings\n"); return -1; } @@ -748,7 +721,7 @@ static void hwa742_suspend(void) static void hwa742_resume(void) { if (clk_enable(hwa742.sys_ck) != 0) - pr_err("failed to enable SYS clock\n"); + dev_err(hwa742.fbdev->dev, "failed to enable SYS clock\n"); /* Disable sleep mode */ hwa742_write_reg(HWA742_POWER_SAVE, 0); while (1) { @@ -761,25 +734,24 @@ static void hwa742_resume(void) hwa742_set_update_mode(hwa742.update_mode_before_suspend); } -struct lcd_ctrl hwa742_ctrl; - -static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_size) +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 sysfreq; int div, nd; - DBGENTER(1); + hwa742.fbdev = fbdev; hwa742.sys_ck = clk_get(0, "bclk"); if (IS_ERR(hwa742.sys_ck)) { - pr_err("can't get SYS clock\n"); + dev_err(fbdev->dev, "can't get SYS clock\n"); return PTR_ERR(hwa742.sys_ck); } if ((r = clk_enable(hwa742.sys_ck)) != 0) { - pr_err("can't enable SYS clock\n"); + dev_err(fbdev->dev, "can't enable SYS clock\n"); clk_put(hwa742.sys_ck); return r; } @@ -792,15 +764,12 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_s spin_lock_init(&hwa742.req_lock); - if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram_size)) < 0) + if ((r = hwa742.int_ctrl->init(fbdev, 1, req_vram)) < 0) goto err1; - if ((r = hwa742.extif->init()) < 0) + if ((r = hwa742.extif->init(fbdev)) < 0) goto err2; - hwa742_ctrl.get_vram_layout = hwa742.int_ctrl->get_vram_layout; - hwa742_ctrl.mmap = hwa742.int_ctrl->mmap; - sysfreq = clk_get_rate(hwa742.sys_ck); if ((r = calc_extif_timings(sysfreq)) < 0) goto err3; @@ -816,17 +785,14 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_s rev = hwa742_read_reg(HWA742_REV_CODE_REG); if ((rev & 0xfc) != 0x80) { - pr_err("invalid revision %02x\n", rev); + dev_err(fbdev->dev, "invalid revision %02x\n", rev); r = -ENODEV; goto err3; } - conf = hwa742_read_reg(HWA742_CONFIG_REG); - pr_info(MODULE_NAME ": Epson HWA742 LCD controller rev. %d " - "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); - if (!(hwa742_read_reg(HWA742_PLL_DIV_REG) & 0x80)) { - pr_err("controller not initialized by the bootloader\n"); + dev_err(hwa742.fbdev->dev, + "controller not initialized by the bootloader\n"); r = -ENODEV; goto err2; } @@ -848,8 +814,6 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_s 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++) @@ -857,6 +821,10 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, int req_vram_s BUG_ON(i <= IRQ_REQ_POOL_SIZE); sema_init(&hwa742.req_sema, i - IRQ_REQ_POOL_SIZE); + conf = hwa742_read_reg(HWA742_CONFIG_REG); + pr_info("omapfb: hwa742 LCD controller rev. %d " + "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); + return 0; err3: hwa742.extif->cleanup(); diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c index a86cd73fa91..87ae40b82bc 100644 --- a/drivers/video/omap/lcdc.c +++ b/drivers/video/omap/lcdc.c @@ -20,7 +20,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - #include #include #include @@ -38,11 +37,7 @@ #include -/* #define OMAPFB_DBG 1 */ - -#include "debug.h" - -#define MODULE_NAME "omapfb-lcdc" +#define MODULE_NAME "lcdc" #define OMAP_LCDC_BASE 0xfffec000 #define OMAP_LCDC_SIZE 256 @@ -78,8 +73,6 @@ #define MAX_PALETTE_SIZE PAGE_SIZE -#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args) - enum lcdc_load_mode { OMAP_LCDC_LOAD_PALETTE, OMAP_LCDC_LOAD_FRAME, @@ -115,16 +108,16 @@ static struct omap_lcd_controller { dma_addr_t vram_phys; void *vram_virt; unsigned long vram_size; -} omap_lcdc; +} lcdc; static void inline enable_irqs(int mask) { - omap_lcdc.irq_mask |= mask; + lcdc.irq_mask |= mask; } static void inline disable_irqs(int mask) { - omap_lcdc.irq_mask &= ~mask; + lcdc.irq_mask &= ~mask; } static void set_load_mode(enum lcdc_load_mode mode) @@ -155,7 +148,7 @@ static void enable_controller(void) l = omap_readl(OMAP_LCDC_CONTROL); l |= OMAP_LCDC_CTRL_LCD_EN; l &= ~OMAP_LCDC_IRQ_MASK; - l |= omap_lcdc.irq_mask | OMAP_LCDC_IRQ_DONE; /* enabled IRQs */ + l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE; /* enabled IRQs */ omap_writel(l, OMAP_LCDC_CONTROL); } @@ -176,11 +169,11 @@ static void disable_controller_async(void) static void disable_controller(void) { - init_completion(&omap_lcdc.last_frame_complete); + init_completion(&lcdc.last_frame_complete); disable_controller_async(); - if (!wait_for_completion_timeout(&omap_lcdc.last_frame_complete, + if (!wait_for_completion_timeout(&lcdc.last_frame_complete, msecs_to_jiffies(500))) - pr_err("timeout waiting for FRAME DONE\n"); + dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n"); } static void reset_controller(u32 status) @@ -191,7 +184,8 @@ static void reset_controller(u32 status) disable_controller_async(); reset_count++; if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) { - pr_err("resetting (status %#010x,reset count %lu)\n", + dev_err(lcdc.fbdev->dev, + "resetting (status %#010x,reset count %lu)\n", status, reset_count); last_jiffies = jiffies; } @@ -199,12 +193,13 @@ static void reset_controller(u32 status) enable_controller(); } else { reset_count = 0; - pr_err("too many reset attempts, giving up.\n"); + 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 omap_lcdc.fbdev and fbdev->var. + * in lcdc.fbdev and fbdev->var. */ static void setup_lcd_dma(void) { @@ -215,22 +210,23 @@ static void setup_lcd_dma(void) 0, OMAP_DMA_DATA_TYPE_S32, }; - struct fb_var_screeninfo *var = &omap_lcdc.fbdev->fb_info->var; + 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 = omap_lcdc.vram_phys + omap_lcdc.frame_offset; + src = lcdc.vram_phys + lcdc.frame_offset; switch (var->rotate) { case 0: - if (omap_lcdc.fbdev->mirror || (src & 3) || - omap_lcdc.color_mode == OMAPFB_COLOR_YUV420 || - (omap_lcdc.xres & 1)) + if (plane->info.mirror || (src & 3) || + lcdc.color_mode == OMAPFB_COLOR_YUV420 || + (lcdc.xres & 1)) esize = 2; else esize = 4; - xelem = omap_lcdc.xres * omap_lcdc.bpp / 8 / esize; - yelem = omap_lcdc.yres; + xelem = lcdc.xres * lcdc.bpp / 8 / esize; + yelem = lcdc.yres; break; case 90: case 180: @@ -239,30 +235,33 @@ static void setup_lcd_dma(void) BUG(); } esize = 2; - xelem = omap_lcdc.yres * omap_lcdc.bpp / 16; - yelem = omap_lcdc.xres; + xelem = lcdc.yres * lcdc.bpp / 16; + yelem = lcdc.xres; break; default: BUG(); return; } - DBGPRINT(2, "setup_dma: src %#010lx esize %d xelem %d yelem %d\n", +#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 = omap_lcdc.bpp; + int bpp = lcdc.bpp; /* YUV support is only for external mode when we have the * YUV window embedded in a 16bpp frame buffer. */ - if (omap_lcdc.color_mode == OMAPFB_COLOR_YUV420) + if (lcdc.color_mode == OMAPFB_COLOR_YUV420) bpp = 16; /* Set virtual xres elem size */ omap_set_lcd_dma_b1_vxres( - omap_lcdc.screen_width * bpp / 8 / esize); + lcdc.screen_width * bpp / 8 / esize); /* Setup transformations */ omap_set_lcd_dma_b1_rotation(var->rotate); - omap_set_lcd_dma_b1_mirror(omap_lcdc.fbdev->mirror); + omap_set_lcd_dma_b1_mirror(plane->info.mirror); } omap_setup_lcd_dma(); } @@ -286,11 +285,11 @@ static irqreturn_t lcdc_irq_handler(int irq, void *dev_id, struct pt_regs *fp) l = omap_readl(OMAP_LCDC_CONTROL); l &= ~OMAP_LCDC_IRQ_DONE; omap_writel(l, OMAP_LCDC_CONTROL); - complete(&omap_lcdc.last_frame_complete); + complete(&lcdc.last_frame_complete); } if (status & OMAP_LCDC_STAT_LOADED_PALETTE) { disable_controller_async(); - complete(&omap_lcdc.palette_load_complete); + complete(&lcdc.palette_load_complete); } } @@ -319,12 +318,10 @@ static int omap_lcdc_setup_plane(int plane, int channel_out, int pos_x, int pos_y, int width, int height, int color_mode) { - struct fb_var_screeninfo *var = &omap_lcdc.fbdev->fb_info->var; - struct lcd_panel *panel = omap_lcdc.fbdev->panel; + struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var; + struct lcd_panel *panel = lcdc.fbdev->panel; int rot_x, rot_y; - DBGENTER(2); - if (var->rotate == 0) { rot_x = panel->x_res; rot_y = panel->y_res; @@ -334,43 +331,45 @@ static int omap_lcdc_setup_plane(int plane, int channel_out, } if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 || width > rot_x || height > rot_y) { - DBGPRINT(1, "invalid plane params plane %d pos_x %d " - "pos_y %d w %d h %d\n", plane, pos_x, pos_y, - width, height); +#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; } - omap_lcdc.frame_offset = offset; - omap_lcdc.xres = width; - omap_lcdc.yres = height; - omap_lcdc.screen_width = screen_width; - omap_lcdc.color_mode = color_mode; + 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: - omap_lcdc.bpp = 8; - omap_lcdc.palette_code = 0x3000; - omap_lcdc.palette_size = 512; + lcdc.bpp = 8; + lcdc.palette_code = 0x3000; + lcdc.palette_size = 512; break; case OMAPFB_COLOR_RGB565: - omap_lcdc.bpp = 16; - omap_lcdc.palette_code = 0x4000; - omap_lcdc.palette_size = 32; + lcdc.bpp = 16; + lcdc.palette_code = 0x4000; + lcdc.palette_size = 32; break; case OMAPFB_COLOR_RGB444: - omap_lcdc.bpp = 16; - omap_lcdc.palette_code = 0x4000; - omap_lcdc.palette_size = 32; + lcdc.bpp = 16; + lcdc.palette_code = 0x4000; + lcdc.palette_size = 32; break; case OMAPFB_COLOR_YUV420: - if (omap_lcdc.ext_mode) { - omap_lcdc.bpp = 12; + if (lcdc.ext_mode) { + lcdc.bpp = 12; break; } /* fallthrough */ case OMAPFB_COLOR_YUV422: - if (omap_lcdc.ext_mode) { - omap_lcdc.bpp = 16; + if (lcdc.ext_mode) { + lcdc.bpp = 16; break; } /* fallthrough */ @@ -381,32 +380,31 @@ static int omap_lcdc_setup_plane(int plane, int channel_out, * bpp4: code 0x2000 size 256 * bpp12: code 0x4000 size 32 */ - DBGPRINT(1, "invalid color mode %d\n", color_mode); + dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode); + BUG(); return -1; } - if (omap_lcdc.ext_mode) { + if (lcdc.ext_mode) { setup_lcd_dma(); return 0; } - if (omap_lcdc.update_mode == OMAPFB_AUTO_UPDATE) { + if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) { disable_controller(); omap_stop_lcd_dma(); setup_lcd_dma(); enable_controller(); } - DBGLEAVE(2); - return 0; } static int omap_lcdc_enable_plane(int plane, int enable) { - DBGPRINT(2, "plane %d enable %d update_mode %d ext_mode %d\n", - plane, enable, omap_lcdc.update_mode, - omap_lcdc.ext_mode); + 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; @@ -421,33 +419,29 @@ static void load_palette(void) { u16 *palette; - DBGENTER(1); - - palette = (u16 *)omap_lcdc.palette_virt; + palette = (u16 *)lcdc.palette_virt; *(u16 *)palette &= 0x0fff; - *(u16 *)palette |= omap_lcdc.palette_code; + *(u16 *)palette |= lcdc.palette_code; - omap_set_lcd_dma_b1(omap_lcdc.palette_phys, - omap_lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32); + 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(&omap_lcdc.palette_load_complete); + 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(&omap_lcdc.palette_load_complete, + if (!wait_for_completion_timeout(&lcdc.palette_load_complete, msecs_to_jiffies(500))) - pr_err("timeout waiting for FRAME DONE\n"); + 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(omap_lcdc.ext_mode); - - DBGLEAVE(1); + omap_set_lcd_dma_single_transfer(lcdc.ext_mode); } /* Used only in internal controller mode */ @@ -456,10 +450,10 @@ static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue, { u16 *palette; - if (omap_lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255) + if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255) return -EINVAL; - palette = (u16 *)omap_lcdc.palette_virt; + palette = (u16 *)lcdc.palette_virt; palette[regno] &= ~0x0fff; palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) | @@ -482,7 +476,7 @@ static void calc_ck_div(int is_tft, int pck, int *pck_div) unsigned long lck; pck = max(1, pck); - lck = clk_get_rate(omap_lcdc.lcd_ck); + lck = clk_get_rate(lcdc.lcd_ck); *pck_div = (lck + pck - 1) / pck; if (is_tft) *pck_div = max(2, *pck_div); @@ -491,15 +485,15 @@ static void calc_ck_div(int is_tft, int pck, int *pck_div) if (*pck_div > 255) { /* FIXME: try to adjust logic clock divider as well */ *pck_div = 255; - printk(KERN_WARNING MODULE_NAME ": pixclock %d kHz too low.\n", - pck / 1000); + 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 = omap_lcdc.fbdev->panel; + struct lcd_panel *panel = lcdc.fbdev->panel; int is_tft = panel->config & OMAP_LCDC_PANEL_TFT; unsigned long lck; int pcd; @@ -535,14 +529,14 @@ static void inline setup_regs(void) l = omap_readl(OMAP_LCDC_TIMING2); l &= ~0xff; - lck = clk_get_rate(omap_lcdc.lcd_ck); + lck = clk_get_rate(lcdc.lcd_ck); if (!panel->pcd) calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd); else { - printk(KERN_WARNING - MODULE_NAME ": Pixel clock divider value is obsolete.\n" - MODULE_NAME ": Try to set pixel_clock to %lu and pcd to 0 " + 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); @@ -564,9 +558,7 @@ static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode) { int r = 0; - DBGENTER(1); - - if (mode != omap_lcdc.update_mode) { + if (mode != lcdc.update_mode) { switch (mode) { case OMAPFB_AUTO_UPDATE: setup_regs(); @@ -579,31 +571,30 @@ static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode) enable_irqs(OMAP_LCDC_IRQ_DONE); /* This will start the actual DMA transfer */ enable_controller(); - omap_lcdc.update_mode = mode; + lcdc.update_mode = mode; break; case OMAPFB_UPDATE_DISABLED: disable_controller(); omap_stop_lcd_dma(); - omap_lcdc.update_mode = mode; + lcdc.update_mode = mode; break; default: r = -EINVAL; } } - DBGLEAVE(1); return r; } static enum omapfb_update_mode omap_lcdc_get_update_mode(void) { - return omap_lcdc.update_mode; + return lcdc.update_mode; } /* PM code called only in internal controller mode */ static void omap_lcdc_suspend(void) { - if (omap_lcdc.update_mode == OMAPFB_AUTO_UPDATE) { + if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) { disable_controller(); omap_stop_lcd_dma(); } @@ -611,7 +602,7 @@ static void omap_lcdc_suspend(void) static void omap_lcdc_resume(void) { - if (omap_lcdc.update_mode == OMAPFB_AUTO_UPDATE) { + if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) { setup_regs(); load_palette(); setup_lcd_dma(); @@ -626,23 +617,15 @@ static unsigned long omap_lcdc_get_caps(void) return 0; } -static void omap_lcdc_get_vram_layout(unsigned long *size, void **virt, - dma_addr_t *phys) -{ - *size = omap_lcdc.vram_size; - *virt = (u8 *)omap_lcdc.vram_virt; - *phys = omap_lcdc.vram_phys; -} - int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data) { BUG_ON(callback == NULL); - if (omap_lcdc.dma_callback) + if (lcdc.dma_callback) return -EBUSY; else { - omap_lcdc.dma_callback = callback; - omap_lcdc.dma_callback_data = data; + lcdc.dma_callback = callback; + lcdc.dma_callback_data = data; } return 0; } @@ -650,15 +633,14 @@ EXPORT_SYMBOL(omap_lcdc_set_dma_callback); void omap_lcdc_free_dma_callback(void) { - omap_lcdc.dma_callback = NULL; + lcdc.dma_callback = NULL; } EXPORT_SYMBOL(omap_lcdc_free_dma_callback); static void lcdc_dma_handler(u16 status, void *data) { - DBGENTER(2); - if (omap_lcdc.dma_callback) - omap_lcdc.dma_callback(omap_lcdc.dma_callback_data); + if (lcdc.dma_callback) + lcdc.dma_callback(lcdc.dma_callback_data); } static int mmap_kern(void) @@ -668,158 +650,141 @@ static int mmap_kern(void) pgprot_t pgprot; unsigned long vaddr; - DBGENTER(1); - - kvma = get_vm_area(omap_lcdc.vram_size, VM_IOREMAP); + kvma = get_vm_area(lcdc.vram_size, VM_IOREMAP); if (kvma == NULL) { - pr_err("can't get kernel vm area\n"); + 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 + omap_lcdc.vram_size; + vma.vm_end = vaddr + lcdc.vram_size; pgprot = pgprot_writecombine(pgprot_kernel); if (io_remap_pfn_range(&vma, vaddr, - omap_lcdc.vram_phys >> PAGE_SHIFT, - omap_lcdc.vram_size, pgprot) < 0) { - pr_err("kernel mmap for FB memory failed\n"); + lcdc.vram_phys >> PAGE_SHIFT, + lcdc.vram_size, pgprot) < 0) { + dev_err(lcdc.fbdev->dev, "kernel mmap for FB memory failed\n"); return -EAGAIN; } - omap_lcdc.vram_virt = (void *)vaddr; - - DBGLEAVE(1); + lcdc.vram_virt = (void *)vaddr; return 0; } static void unmap_kern(void) { - vunmap(omap_lcdc.vram_virt); + vunmap(lcdc.vram_virt); } static int alloc_palette_ram(void) { - omap_lcdc.palette_virt = dma_alloc_writecombine(omap_lcdc.fbdev->dev, - MAX_PALETTE_SIZE, &omap_lcdc.palette_phys, GFP_KERNEL); - if (omap_lcdc.palette_virt == NULL) { - pr_err("failed to alloc palette memory\n"); + 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(omap_lcdc.palette_virt, 0, MAX_PALETTE_SIZE); + memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE); return 0; } static void free_palette_ram(void) { - dma_free_writecombine(omap_lcdc.fbdev->dev, MAX_PALETTE_SIZE, - omap_lcdc.palette_virt, omap_lcdc.palette_phys); + dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE, + lcdc.palette_virt, lcdc.palette_phys); } -static int alloc_fbmem(int req_size) +static int alloc_fbmem(struct omapfb_mem_region *region) { + int bpp; int frame_size; - struct lcd_panel *panel = omap_lcdc.fbdev->panel; - - frame_size = PAGE_ALIGN(panel->x_res * panel->bpp / 8 * panel->y_res); - if (req_size > frame_size) - frame_size = req_size; - omap_lcdc.vram_size = frame_size; - omap_lcdc.vram_virt = dma_alloc_writecombine(omap_lcdc.fbdev->dev, - omap_lcdc.vram_size, &omap_lcdc.vram_phys, GFP_KERNEL); - - if (omap_lcdc.vram_virt == NULL) { - pr_err("unable to allocate FB DMA memory\n"); + 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->alloc = 1; - memset(omap_lcdc.vram_virt, 0, omap_lcdc.vram_size); + memset(lcdc.vram_virt, 0, lcdc.vram_size); return 0; } static void free_fbmem(void) { - dma_free_writecombine(omap_lcdc.fbdev->dev, omap_lcdc.vram_size, - omap_lcdc.vram_virt, omap_lcdc.vram_phys); + dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size, + lcdc.vram_virt, lcdc.vram_phys); } -static int setup_fbmem(int req_size) +static int setup_fbmem(struct omapfb_mem_desc *req_md) { - struct lcd_panel *panel = omap_lcdc.fbdev->panel; - struct omapfb_platform_data *conf; - int frame_size; int r; - conf = omap_lcdc.fbdev->dev->platform_data; - - if (conf->fbmem.fb_sram_size) { - pr_err("can't use FB SRAM in OMAP1\n"); + if (!req_md->region_cnt) { + dev_err(lcdc.fbdev->dev, "no memory regions defined\n"); return -EINVAL; } - if (conf->fbmem.fb_sdram_size == 0) { - omap_lcdc.fbmem_allocated = 1; - if ((r = alloc_fbmem(req_size)) < 0) - return r; - return 0; - } - - if (panel->bpp == 12) - frame_size = PAGE_ALIGN(panel->x_res * 16 / 8 * panel->y_res); - else - frame_size = PAGE_ALIGN(panel->x_res * panel->bpp / 8 * panel->y_res); - - if (conf->fbmem.fb_sdram_size < frame_size) { - pr_err("invalid FB memory configuration\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 (conf->fbmem.fb_sdram_size < req_size) { - pr_err("%d vram was requested, but only %u is available\n", - req_size, conf->fbmem.fb_sdram_size); + if (req_md->region[0].paddr == 0) { + lcdc.fbmem_allocated = 1; + if ((r = alloc_fbmem(&req_md->region[0])) < 0) + return r; + return 0; } - omap_lcdc.vram_phys = conf->fbmem.fb_sdram_start; - omap_lcdc.vram_size = conf->fbmem.fb_sdram_size; + lcdc.vram_phys = req_md->region[0].paddr; + lcdc.vram_size = req_md->region[0].size; if ((r = mmap_kern()) < 0) return r; - DBGPRINT(1, "vram at %08x size %08lx mapped to 0x%p\n", - omap_lcdc.vram_phys, omap_lcdc.vram_size, omap_lcdc.vram_virt); + 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 (omap_lcdc.fbmem_allocated) + if (lcdc.fbmem_allocated) free_fbmem(); else unmap_kern(); } static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode, - int req_vram_size) + struct omapfb_mem_desc *req_vram) { int r; u32 l; int rate; struct clk *tc_ck; - DBGENTER(1); - - omap_lcdc.irq_mask = 0; + lcdc.irq_mask = 0; - omap_lcdc.fbdev = fbdev; - omap_lcdc.ext_mode = ext_mode; - - pr_info(MODULE_NAME ": init\n"); + lcdc.fbdev = fbdev; + lcdc.ext_mode = ext_mode; l = 0; omap_writel(l, OMAP_LCDC_CONTROL); @@ -827,16 +792,16 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode, /* FIXME: * According to errata some platforms have a clock rate limitiation */ - omap_lcdc.lcd_ck = clk_get(NULL, "lcd_ck"); - if (IS_ERR(omap_lcdc.lcd_ck)) { - pr_err("unable to access LCD clock\n"); - r = PTR_ERR(omap_lcdc.lcd_ck); + lcdc.lcd_ck = clk_get(NULL, "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(NULL, "tc_ck"); if (IS_ERR(tc_ck)) { - pr_err("unable to access TC clock\n"); + dev_err(fbdev->dev, "unable to access TC clock\n"); r = PTR_ERR(tc_ck); goto fail1; } @@ -846,23 +811,22 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode, if (machine_is_omap_h3()) rate /= 3; - r = clk_set_rate(omap_lcdc.lcd_ck, rate); + r = clk_set_rate(lcdc.lcd_ck, rate); if (r) { - pr_err("failed to adjust LCD rate\n"); + dev_err(fbdev->dev, "failed to adjust LCD rate\n"); goto fail1; } - clk_enable(omap_lcdc.lcd_ck); + clk_enable(lcdc.lcd_ck); - r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, "omap-lcdc", - omap_lcdc.fbdev); + r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev); if (r) { - pr_err("unable to get IRQ\n"); + dev_err(fbdev->dev, "unable to get IRQ\n"); goto fail2; } r = omap_request_lcd_dma(lcdc_dma_handler, NULL); if (r) { - pr_err("unable to get LCD DMA\n"); + dev_err(fbdev->dev, "unable to get LCD DMA\n"); goto fail3; } @@ -873,12 +837,11 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode, if ((r = alloc_palette_ram()) < 0) goto fail4; - req_vram_size = 1024 * 1024; - if ((r = setup_fbmem(req_vram_size)) < 0) + if ((r = setup_fbmem(req_vram)) < 0) goto fail5; + pr_info("omapfb: LCDC initialized\n"); - DBGLEAVE(1); return 0; fail5: if (!ext_mode) @@ -886,32 +849,30 @@ fail5: fail4: omap_free_lcd_dma(); fail3: - free_irq(OMAP_LCDC_IRQ, omap_lcdc.fbdev); + free_irq(OMAP_LCDC_IRQ, lcdc.fbdev); fail2: - clk_disable(omap_lcdc.lcd_ck); + clk_disable(lcdc.lcd_ck); fail1: - clk_put(omap_lcdc.lcd_ck); + clk_put(lcdc.lcd_ck); fail0: - DBGLEAVE(1); return r; } static void omap_lcdc_cleanup(void) { - if (!omap_lcdc.ext_mode) + if (!lcdc.ext_mode) free_palette_ram(); cleanup_fbmem(); omap_free_lcd_dma(); - free_irq(OMAP_LCDC_IRQ, omap_lcdc.fbdev); - clk_disable(omap_lcdc.lcd_ck); - clk_put(omap_lcdc.lcd_ck); + free_irq(OMAP_LCDC_IRQ, lcdc.fbdev); + clk_disable(lcdc.lcd_ck); + clk_put(lcdc.lcd_ck); } -struct lcd_ctrl omap1_int_ctrl = { +const struct lcd_ctrl omap1_int_ctrl = { .name = "internal", .init = omap_lcdc_init, .cleanup = omap_lcdc_cleanup, - .get_vram_layout = omap_lcdc_get_vram_layout, .get_caps = omap_lcdc_get_caps, .set_update_mode = omap_lcdc_set_update_mode, .get_update_mode = omap_lcdc_get_update_mode, @@ -922,6 +883,3 @@ struct lcd_ctrl omap1_int_ctrl = { .enable_plane = omap_lcdc_enable_plane, .setcolreg = omap_lcdc_setcolreg, }; - -MODULE_DESCRIPTION("TI OMAP LCDC controller"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 5a013b6eaca..4e73cd49be6 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -26,36 +26,19 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - #include -#include -#include -#include -#include #include -#include #include -#include #include - #include -#include -#include -#include #include -/* #define OMAPFB_DBG 1 */ - -#include "debug.h" - -#define OMAPFB_DRIVER "omapfb" #define MODULE_NAME "omapfb" -#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args) - static unsigned int def_accel; -static unsigned long def_vram; +static unsigned long def_vram[OMAPFB_PLANE_NUM]; +static int def_vram_cnt; static unsigned long def_vxres; static unsigned long def_vyres; static unsigned int def_rotate; @@ -87,7 +70,6 @@ static struct caps_table_struct { extern struct lcd_ctrl omap1_int_ctrl; extern struct lcd_ctrl omap2_int_ctrl; extern struct lcd_ctrl hwa742_ctrl; -extern struct lcd_ctrl blizzard_ctrl; static struct lcd_ctrl *ctrls[] = { #ifdef CONFIG_ARCH_OMAP1 @@ -103,9 +85,9 @@ static struct lcd_ctrl *ctrls[] = { #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL #ifdef CONFIG_ARCH_OMAP1 -extern struct lcd_ctrl_extif sossi_extif; +extern struct lcd_ctrl_extif omap1_ext_if; #else -extern struct lcd_ctrl_extif rfbi_extif; +extern struct lcd_ctrl_extif omap2_ext_if; #endif #endif @@ -141,27 +123,48 @@ static const int dma_elem_type[] = { static int ctrl_init(struct omapfb_device *fbdev) { int r; + int i; - DBGENTER(1); + /* 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 = def_vram[i]; + fbdev->mem_desc.region_cnt = i; + } else { + struct omapfb_platform_data *conf; - r = fbdev->ctrl->init(fbdev, 0, def_vram); - if (r < 0) { - pr_err("controller initialization failed\n"); - goto exit; + conf = fbdev->dev->platform_data; + fbdev->mem_desc = conf->mem_desc; } - fbdev->ctrl->get_vram_layout(&fbdev->vram_size, &fbdev->vram_virt_base, - &fbdev->vram_phys_base); - - DBGPRINT(1, "vram_phys %08x vram_virt %p vram_size=%lu\n", - fbdev->vram_phys_base, fbdev->vram_virt_base, - fbdev->vram_size); + 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 = 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; + } - DBGLEAVE(1); +#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; -exit: - DBGLEAVE(1); - return r; } static void ctrl_cleanup(struct omapfb_device *fbdev) @@ -169,21 +172,28 @@ static void ctrl_cleanup(struct omapfb_device *fbdev) fbdev->ctrl->cleanup(); } -static int ctrl_change_mode(struct omapfb_device *fbdev) +static int ctrl_change_mode(struct fb_info *fbi) { int r; unsigned long offset; - struct fb_var_screeninfo *var = &fbdev->fb_info->var; + struct omapfb_plane_struct *plane = fbi->par; + struct omapfb_device *fbdev = plane->fbdev; + struct fb_var_screeninfo *var = &fbi->var; - DBGPRINT(1, "xoffset %d yoffset %d line_length %d bits_per_pixel %d\n", - var->xoffset, var->yoffset, fbdev->fb_info->fix.line_length, - var->bits_per_pixel); - offset = var->yoffset * fbdev->fb_info->fix.line_length + + offset = var->yoffset * fbi->fix.line_length + var->xoffset * var->bits_per_pixel / 8; - r = fbdev->ctrl->setup_plane(OMAPFB_PLANE_GFX, OMAPFB_CHANNEL_OUT_LCD, - offset, var->xres_virtual, 0, 0, var->xres, - var->yres, fbdev->color_mode); - DBGLEAVE(1); + + omapfb_rqueue_lock(fbdev); + 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 (fbdev->ctrl->set_scale != NULL) + r = fbdev->ctrl->set_scale(plane->idx, + var->xres, var->yres, + plane->info.out_width, + plane->info.out_height); + omapfb_rqueue_unlock(fbdev); return r; } @@ -196,8 +206,6 @@ static int ctrl_change_mode(struct omapfb_device *fbdev) /* Called each time the omapfb device is opened */ static int omapfb_open(struct fb_info *info, int user) { - DBGENTER(1); - DBGLEAVE(1); return 0; } @@ -207,11 +215,7 @@ static void omapfb_sync(struct fb_info *info); * gfx DMA operations are ended, before we return. */ static int omapfb_release(struct fb_info *info, int user) { - DBGENTER(1); - omapfb_sync(info); - - DBGLEAVE(1); return 0; } @@ -222,13 +226,15 @@ static int omapfb_release(struct fb_info *info, int user) 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_device *fbdev = (struct omapfb_device *)info->par; + struct omapfb_plane_struct *plane = info->par; + struct omapfb_device *fbdev = plane->fbdev; struct fb_var_screeninfo *var = &info->var; int r = 0; - switch (fbdev->color_mode) { + switch (plane->color_mode) { case OMAPFB_COLOR_YUV422: case OMAPFB_COLOR_YUV420: + case OMAPFB_COLOR_YUY422: r = -EINVAL; break; case OMAPFB_COLOR_CLUT_8BPP: @@ -251,9 +257,11 @@ static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green, 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)); + 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; @@ -266,15 +274,7 @@ static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green, static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { - int r = 0; - - DBGENTER(2); - - _setcolreg(info, regno, red, green, blue, transp, 1); - - DBGLEAVE(2); - - return r; + return _setcolreg(info, regno, red, green, blue, transp, 1); } static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) @@ -301,35 +301,22 @@ static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) return 0; } -static int omapfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - struct omapfb_device *fbdev = info->par; - int r; - - omapfb_rqueue_lock(fbdev); - r = fbdev->ctrl->mmap(vma); - omapfb_rqueue_unlock(fbdev); - - return r; -} - -static void omapfb_update_full_screen(struct omapfb_device *fbdev); +static int omapfb_update_full_screen(struct fb_info *fbi); static int omapfb_blank(int blank, struct fb_info *fbi) { - struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; + struct omapfb_plane_struct *plane = fbi->par; + struct omapfb_device *fbdev = plane->fbdev; int do_update = 0; int r = 0; - DBGENTER(1); - omapfb_rqueue_lock(fbdev); switch (blank) { case VESA_NO_BLANKING: if (fbdev->state == OMAPFB_SUSPENDED) { if (fbdev->ctrl->resume) fbdev->ctrl->resume(); - fbdev->panel->enable(); + fbdev->panel->enable(fbdev->panel); fbdev->state = OMAPFB_ACTIVE; if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) @@ -338,7 +325,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi) break; case VESA_POWERDOWN: if (fbdev->state == OMAPFB_ACTIVE) { - fbdev->panel->disable(); + fbdev->panel->disable(fbdev->panel); if (fbdev->ctrl->suspend) fbdev->ctrl->suspend(); fbdev->state = OMAPFB_SUSPENDED; @@ -349,16 +336,16 @@ static int omapfb_blank(int blank, struct fb_info *fbi) } omapfb_rqueue_unlock(fbdev); - if (do_update) - omapfb_update_full_screen(fbdev); + if (r == 0 && do_update) + r = omapfb_update_full_screen(fbi); - DBGLEAVE(1); return r; } static void omapfb_sync(struct fb_info *fbi) { - struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; + struct omapfb_plane_struct *plane = fbi->par; + struct omapfb_device *fbdev = plane->fbdev; omapfb_rqueue_lock(fbdev); if (fbdev->ctrl->sync) @@ -369,17 +356,22 @@ static void omapfb_sync(struct fb_info *fbi) /* 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 omapfb_device *fbdev) +static void set_fb_fix(struct fb_info *fbi) { - struct fb_info *fbi = fbdev->fb_info; struct fb_fix_screeninfo *fix = &fbi->fix; struct fb_var_screeninfo *var = &fbi->var; + int bpp; - strncpy(fix->id, OMAPFB_DRIVER, sizeof(fix->id)); fix->type = FB_TYPE_PACKED_PIXELS; - switch (var->bits_per_pixel) { + 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: @@ -389,61 +381,118 @@ static void set_fb_fix(struct omapfb_device *fbdev) break; } fix->accel = FB_ACCEL_OMAP1610; - fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; - fix->smem_len = fbdev->vram_size; - fix->smem_start = fbdev->vram_phys_base; + 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: + plane->color_mode = OMAPFB_COLOR_RGB444; + return 0; + case 16: + 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 omapfb_device *fbdev, +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 (panel->bpp == 12) - bpp = var->bits_per_pixel = 16; /* 12-bit bpp mode stores colours in 16-bits */ - else - bpp = var->bits_per_pixel = panel->bpp; - - switch (panel->bpp) { - case 16: - fbdev->color_mode = OMAPFB_COLOR_RGB565; - break; - case 12: - fbdev->color_mode = OMAPFB_COLOR_RGB444; - break; - case 8: - fbdev->color_mode = OMAPFB_COLOR_CLUT_8BPP; - break; - default: - /* FIXME: other BPPs not yet supported */ + 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: - var->xres = fbdev->panel->x_res; - var->yres = fbdev->panel->y_res; + 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_omap1510()) { + var->xres = panel->x_res; + var->yres = panel->y_res; + } break; case 90: case 270: - var->xres = fbdev->panel->y_res; - var->yres = fbdev->panel->x_res; + 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_omap1510()) { + 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->vram_size; + 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 */ @@ -462,23 +511,25 @@ static int set_fb_var(struct omapfb_device *fbdev, var->yoffset = var->yres_virtual - var->yres; line_size = var->xres * bpp / 8; - if (fbdev->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; + 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; - var->nonstd = 0; /* pixclock in ps, the rest in pixclock */ var->pixclock = 10000000 / (panel->pixel_clock / 100); @@ -501,21 +552,15 @@ static struct fb_var_screeninfo new_var; /* 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_device *fbdev = (struct omapfb_device *)fbi->par; - - DBGENTER(1); - - if (cpu_is_omap1510() && rotate != fbdev->fb_info->var.rotate) { + if (cpu_is_omap1510() && rotate != fbi->var.rotate) { memcpy(&new_var, &fbi->var, sizeof(new_var)); new_var.rotate = rotate; - if (set_fb_var(fbdev, &new_var) == 0 && + 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(fbdev); + ctrl_change_mode(fbi); } } - - DBGLEAVE(1); } /* Set new x,y offsets in the virtual display for the visible area and switch @@ -524,44 +569,38 @@ static void omapfb_rotate(struct fb_info *fbi, int rotate) static int omapfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi) { - struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; int r = 0; - DBGENTER(1); - if (var->xoffset != fbi->var.xoffset || var->yoffset != fbi->var.yoffset) { memcpy(&new_var, &fbi->var, sizeof(new_var)); new_var.xoffset = var->xoffset; new_var.yoffset = var->yoffset; - if (set_fb_var(fbdev, &new_var)) + if (set_fb_var(fbi, &new_var)) r = -EINVAL; else { memcpy(&fbi->var, &new_var, sizeof(new_var)); - ctrl_change_mode(fbdev); + ctrl_change_mode(fbi); } } - DBGLEAVE(1); return r; } /* Set mirror to vertical axis and switch to the new mode. */ -static int omapfb_mirror(struct omapfb_device *fbdev, int mirror) +static int omapfb_mirror(struct fb_info *fbi, int mirror) { + struct omapfb_plane_struct *plane = fbi->par; int r = 0; - DBGENTER(1); - mirror = mirror ? 1 : 0; if (cpu_is_omap1510()) r = -EINVAL; - else if (mirror != fbdev->mirror) { - fbdev->mirror = mirror; - r = ctrl_change_mode(fbdev); + else if (mirror != plane->info.mirror) { + plane->info.mirror = mirror; + r = ctrl_change_mode(fbi); } - DBGLEAVE(1); return r; } @@ -570,15 +609,7 @@ static int omapfb_mirror(struct omapfb_device *fbdev, int mirror) */ static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) { - struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; - int r; - - DBGENTER(1); - - r = set_fb_var(fbdev, var); - - DBGLEAVE(1); - return r; + return set_fb_var(fbi, var); } /* Switch to a new mode. The parameters for it has been check already by @@ -586,139 +617,158 @@ static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) */ static int omapfb_set_par(struct fb_info *fbi) { - int r; - struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; - - DBGENTER(1); - - set_fb_fix(fbdev); - r = ctrl_change_mode(fbdev); - - DBGLEAVE(1); - return r; + set_fb_fix(fbi); + return ctrl_change_mode(fbi); } -int omapfb_update_window_async(struct omapfb_update_window *win, - void (*callback)(void *), - void *callback_data) +int omapfb_update_window_async(struct fb_info *fbi, + struct omapfb_update_window *win, + void (*callback)(void *), + void *callback_data) { - struct omapfb_device *fbdev = omapfb_dev; + struct omapfb_plane_struct *plane = fbi->par; + struct omapfb_device *fbdev = plane->fbdev; struct fb_var_screeninfo *var; - DBGENTER(2); - if (fbdev == NULL) { - DBGPRINT(1, "no fbdev\n"); - return -ENODEV; - } - - var = &fbdev->fb_info->var; + var = &fbi->var; - if (win->x >= var->xres || win->y >= var->yres) { - DBGPRINT(1, "invalid x %d, y %d\n", win->x, win->y); + if (win->x >= var->xres || win->y >= var->yres) return -EINVAL; - } if (!fbdev->ctrl->update_window || - fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE) { - DBGPRINT(1, "invalid update mode\n"); + fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE) return -ENODEV; - } if (win->x + win->width >= var->xres) win->width = var->xres - win->x; if (win->y + win->height >= var->yres) win->height = var->yres - win->y; - if (!win->width || !win->height) { - DBGPRINT(1, "zero size window\n"); + if (!win->width || !win->height) return 0; - } - return fbdev->ctrl->update_window(win, callback, callback_data); + return fbdev->ctrl->update_window(fbi, win, callback, callback_data); } EXPORT_SYMBOL(omapfb_update_window_async); -static int omapfb_update_win(struct omapfb_device *fbdev, +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(fbdev); - ret = omapfb_update_window_async(win, NULL, 0); - omapfb_rqueue_unlock(fbdev); + omapfb_rqueue_lock(plane->fbdev); + ret = omapfb_update_window_async(fbi, win, NULL, 0); + omapfb_rqueue_unlock(plane->fbdev); return ret; } -static void omapfb_update_full_screen(struct omapfb_device *fbdev) +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 = fbdev->panel->x_res; - win.height = fbdev->panel->y_res; + win.width = fbi->var.xres; + win.height = fbi->var.yres; win.format = 0; omapfb_rqueue_lock(fbdev); - fbdev->ctrl->update_window(&win, NULL, 0); + r = fbdev->ctrl->update_window(fbi, &win, NULL, 0); omapfb_rqueue_unlock(fbdev); + + return r; } -static int omapfb_setup_plane(struct omapfb_device *fbdev, - struct omapfb_setup_plane *sp) +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; int r; - omapfb_rqueue_lock(fbdev); - r = fbdev->ctrl->setup_plane(sp->plane, sp->channel_out, sp->offset, - sp->width, sp->pos_x, sp->pos_y, sp->width, - sp->height, sp->color_mode); - omapfb_rqueue_unlock(fbdev); + plane->info = *pi; + r = ctrl_change_mode(fbi); + if (r < 0) + return r; + return fbdev->ctrl->enable_plane(plane->idx, pi->enabled); +} - 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_enable_plane(struct omapfb_device *fbdev, int plane, - int enable) +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->enable_plane(plane, enable); + r = fbdev->ctrl->set_color_key(ck); omapfb_rqueue_unlock(fbdev); return r; } -static int omapfb_set_color_key(struct omapfb_device *fbdev, +static int omapfb_get_color_key(struct omapfb_device *fbdev, struct omapfb_color_key *ck) { int r; - if (!fbdev->ctrl->set_color_key) + if (!fbdev->ctrl->get_color_key) return -ENODEV; omapfb_rqueue_lock(fbdev); - r = fbdev->ctrl->set_color_key(ck); + r = fbdev->ctrl->get_color_key(ck); omapfb_rqueue_unlock(fbdev); return r; } -static BLOCKING_NOTIFIER_HEAD(omapfb_notifier_list); +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) + omapfb_notifier_callback_t callback, + void *callback_data) { int r; - DBGENTER(1); + 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_notifier_list, &omapfb_nb->nb); + r = blocking_notifier_chain_register( + &omapfb_client_list[omapfb_nb->plane_idx], + &omapfb_nb->nb); if (r) return r; if (omapfb_dev != NULL && @@ -732,15 +782,22 @@ EXPORT_SYMBOL(omapfb_register_client); int omapfb_unregister_client(struct omapfb_notifier_block *omapfb_nb) { - return blocking_notifier_chain_unregister(&omapfb_notifier_list, - &omapfb_nb->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) { - DBGENTER(1); - blocking_notifier_call_chain(&omapfb_notifier_list, event, fbdev); + 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); @@ -767,13 +824,12 @@ static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbde return r; } -static unsigned long omapfb_get_caps(struct fb_info *fbi) +static unsigned long omapfb_get_caps(struct omapfb_device *fbdev) { - struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; unsigned long caps; caps = 0; - caps |= fbdev->panel->get_caps(); + caps |= fbdev->panel->get_caps(fbdev->panel); caps |= fbdev->ctrl->get_caps(); return caps; } @@ -782,7 +838,7 @@ static unsigned long omapfb_get_caps(struct fb_info *fbi) void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval) { omapfb_rqueue_lock(fbdev); - *(u16 *)fbdev->vram_virt_base = pixval; + *(u16 *)fbdev->mem_desc.region[0].vaddr = pixval; if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) { struct omapfb_update_window win; @@ -791,42 +847,41 @@ void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval) win.width = 1; win.height = 1; win.format = 0; - fbdev->ctrl->update_window(&win, NULL, 0); + fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0); } 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. In addition transparent copy - * graphics transformations, frame flipping support is provided through this - * interface. + * here to be accessible by user mode code. */ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) { - struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; + 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_setup_plane setup_plane; - struct omapfb_enable_plane enable_plane; + struct omapfb_plane_info plane_info; struct omapfb_color_key color_key; enum omapfb_update_mode update_mode; unsigned long caps; unsigned int mirror; + int plane_out; + int enable_plane; } p; int r = 0; BUG_ON(!ops); - DBGPRINT(2, "cmd=%010x\n", cmd); switch (cmd) { case OMAPFB_MIRROR: if (get_user(p.mirror, (int __user *)arg)) r = -EFAULT; else - omapfb_mirror(fbdev, p.mirror); + omapfb_mirror(fbi, p.mirror); break; case OMAPFB_SYNC_GFX: omapfb_sync(fbi); @@ -851,7 +906,7 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, r = -EFAULT; else { p.update_window.format = 0; - r = omapfb_update_win(fbdev, &p.update_window); + r = omapfb_update_win(fbi, &p.update_window); } break; case OMAPFB_UPDATE_WINDOW: @@ -859,22 +914,21 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, sizeof(p.update_window))) r = -EFAULT; else - r = omapfb_update_win(fbdev, &p.update_window); + r = omapfb_update_win(fbi, &p.update_window); break; case OMAPFB_SETUP_PLANE: - if (copy_from_user(&p.setup_plane, (void __user *)arg, - sizeof(p.setup_plane))) + if (copy_from_user(&p.plane_info, (void __user *)arg, + sizeof(p.plane_info))) r = -EFAULT; else - r = omapfb_setup_plane(fbdev, &p.setup_plane); + r = omapfb_setup_plane(fbi, &p.plane_info); break; - case OMAPFB_ENABLE_PLANE: - if (copy_from_user(&p.enable_plane, (void __user *)arg, - sizeof(p.enable_plane))) + 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; - else - r = omapfb_enable_plane(fbdev, - p.enable_plane.plane, p.enable_plane.enable); break; case OMAPFB_SET_COLOR_KEY: if (copy_from_user(&p.color_key, (void __user *)arg, @@ -883,9 +937,11 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, else r = omapfb_set_color_key(fbdev, &p.color_key); break; - case OMAPFB_GET_CAPS: - p.caps = omapfb_get_caps(fbi); - if (put_user(p.caps, (unsigned long __user *)arg)) + 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_LCD_TEST: @@ -900,7 +956,7 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, r = -EINVAL; break; } - r = fbdev->panel->run_test(test_num); + r = fbdev->panel->run_test(fbdev->panel, test_num); break; } case OMAPFB_CTRL_TEST: @@ -922,7 +978,6 @@ static int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, r = -EINVAL; } - DBGLEAVE(2); return r; } @@ -956,8 +1011,7 @@ static ssize_t omapfb_show_caps_num(struct device *dev, struct device_attribute { struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; - return snprintf(buf, PAGE_SIZE, "%#010lx\n", - omapfb_get_caps(fbdev->fb_info)); + return snprintf(buf, PAGE_SIZE, "%#010lx\n", omapfb_get_caps(fbdev)); } static ssize_t omapfb_show_caps_text(struct device *dev, struct device_attribute *attr, char *buf) @@ -967,7 +1021,7 @@ static ssize_t omapfb_show_caps_text(struct device *dev, struct device_attribute int i; unsigned long caps; - caps = omapfb_get_caps(fbdev->fb_info); + caps = omapfb_get_caps(fbdev); for (i = 0; i < ARRAY_SIZE(omapfb_caps_table) && pos < PAGE_SIZE; i++) { if (omapfb_caps_table[i].flag & caps) { pos += snprintf(&buf[pos], PAGE_SIZE - pos, "%s\n", @@ -998,7 +1052,7 @@ static ssize_t omapfb_show_bklight_level(struct device *dev, if (fbdev->panel->get_bklight_level) { r = snprintf(buf, PAGE_SIZE, "%d\n", - fbdev->panel->get_bklight_level()); + fbdev->panel->get_bklight_level(fbdev->panel)); } else r = -ENODEV; return r; @@ -1015,7 +1069,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev, unsigned int level; if (sscanf(buf, "%10d", &level) == 1) { - r = fbdev->panel->set_bklight_level(level); + r = fbdev->panel->set_bklight_level(fbdev->panel, level); } else r = -EINVAL; } else @@ -1031,7 +1085,7 @@ static ssize_t omapfb_show_bklight_max(struct device *dev, if (fbdev->panel->get_bklight_level) { r = snprintf(buf, PAGE_SIZE, "%d\n", - fbdev->panel->get_bklight_max()); + fbdev->panel->get_bklight_max(fbdev->panel)); } else r = -ENODEV; return r; @@ -1101,7 +1155,7 @@ fail2: fail1: device_remove_file(fbdev->dev, &dev_attr_caps_num); fail0: - pr_err("unable to register sysfs interface\n"); + dev_err(fbdev->dev, "unable to register sysfs interface\n"); return r; } @@ -1121,48 +1175,92 @@ static void omapfb_unregister_sysfs(struct omapfb_device *fbdev) /* 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) +static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info, + struct omapfb_mem_region *region) { - struct fb_info *info = fbdev->fb_info; struct fb_var_screeninfo *var = &info->var; + struct fb_fix_screeninfo *fix = &info->fix; int r = 0; - DBGENTER(1); - - BUG_ON(!fbdev->vram_virt_base); - info->fbops = &omapfb_ops; info->flags = FBINFO_FLAG_DEFAULT; - info->screen_base = (char __iomem *)fbdev->vram_virt_base; + + strncpy(fix->id, MODULE_NAME, sizeof(fix->id)); + + info->screen_base = (char __iomem *)region->vaddr; + fix->smem_start = region->paddr; + fix->smem_len = region->size; 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; - fbdev->mirror = def_mirror; - - set_fb_var(fbdev, var); - set_fb_fix(fbdev); + set_fb_var(info, var); + set_fb_fix(info); r = fb_alloc_cmap(&info->cmap, 16, 0); if (r != 0) - pr_err("unable to allocate color map memory\n"); + dev_err(fbdev->dev, "unable to allocate color map memory\n"); - DBGLEAVE(1); return r; } /* Release the fb_info object */ -static void fbinfo_cleanup(struct omapfb_device *fbdev) +static void fbinfo_cleanup(struct omapfb_device *fbdev, struct fb_info *fbi) { - DBGENTER(1); + fb_dealloc_cmap(&fbi->cmap); +} - fb_dealloc_cmap(&fbdev->fb_info->cmap); +static void planes_cleanup(struct omapfb_device *fbdev) +{ + int i; - DBGLEAVE(1); + 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, + &fbdev->mem_desc.region[i])) < 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 @@ -1170,24 +1268,27 @@ static void fbinfo_cleanup(struct omapfb_device *fbdev) */ static void omapfb_free_resources(struct omapfb_device *fbdev, int state) { + int i; + switch (state) { case OMAPFB_ACTIVE: - unregister_framebuffer(fbdev->fb_info); + 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->disable(fbdev->panel); case 5: omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED); case 4: - fbinfo_cleanup(fbdev); + planes_cleanup(fbdev); case 3: ctrl_cleanup(fbdev); case 2: - fbdev->panel->cleanup(); + fbdev->panel->cleanup(fbdev->panel); case 1: dev_set_drvdata(fbdev->dev, NULL); - framebuffer_release(fbdev->fb_info); + kfree(fbdev); case 0: /* nothing to free */ break; @@ -1202,13 +1303,9 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev) char name[17]; int i; - conf = (struct omapfb_platform_data *)fbdev->dev->platform_data; + conf = fbdev->dev->platform_data; fbdev->ctrl = NULL; - if (conf == NULL) { - DBGPRINT(1, "omap_lcd_config not found\n"); - return -1; - } strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1); name[sizeof(name) - 1] = '\0'; @@ -1219,7 +1316,7 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev) } for (i = 0; i < ARRAY_SIZE(ctrls); i++) { - DBGPRINT(1, "ctrl %s\n", ctrls[i]->name); + dev_dbg(fbdev->dev, "ctrl %s\n", ctrls[i]->name); if (strcmp(ctrls[i]->name, name) == 0) { fbdev->ctrl = ctrls[i]; break; @@ -1227,7 +1324,7 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev) } if (fbdev->ctrl == NULL) { - DBGPRINT(1, "ctrl %s not supported\n", name); + dev_dbg(fbdev->dev, "ctrl %s not supported\n", name); return -1; } @@ -1249,44 +1346,48 @@ static void check_required_callbacks(struct omapfb_device *fbdev) /* Called by LDM binding to probe and attach a new device. * Initialization sequence: - * 1. allocate system fb_info structure - * select panel type according to machine type - * 2. init LCD panel + * 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 - * 5. init gfx DMA + * 4. init system fb_info structure for all planes + * 5. setup video mode for first plane and enable it * 6. enable LCD panel - * start LCD frame transfer - * 7. register system fb_info structure + * 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; - struct fb_info *fbi; int init_state; unsigned long phz, hhz, vhz; + unsigned long vram; + int i; int r = 0; - DBGENTER(1); - init_state = 0; if (pdev->num_resources != 0) { - pr_err("probed for an unknown device\n"); + dev_err(&pdev->dev, "probed for an unknown device\n"); r = -ENODEV; goto cleanup; } - fbi = framebuffer_alloc(sizeof(struct omapfb_device), &pdev->dev); - if (fbi == NULL) { - pr_err("unable to allocate memory for device info\n"); + 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 = (struct omapfb_device *)fbi->par; - fbdev->fb_info = fbi; fbdev->dev = &pdev->dev; fbdev->panel = panel; platform_set_drvdata(pdev, fbdev); @@ -1296,25 +1397,30 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel #ifdef CONFIG_ARCH_OMAP1 fbdev->int_ctrl = &omap1_int_ctrl; #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL - fbdev->ext_if = &sossi_extif; + fbdev->ext_if = &omap1_ext_if; #endif #else /* OMAP2 */ fbdev->int_ctrl = &omap2_int_ctrl; #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL - fbdev->ext_if = &rfbi_extif; + fbdev->ext_if = &omap2_ext_if; #endif #endif if (omapfb_find_ctrl(fbdev) < 0) { - pr_err("LCD controller not found, board not supported\n"); + dev_err(fbdev->dev, + "LCD controller not found, board not supported\n"); r = -ENODEV; goto cleanup; } - pr_info(MODULE_NAME ": configured for panel %s\n", fbdev->panel->name); - - r = fbdev->panel->init(fbdev); + 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 ? : fbdev->panel->x_res; + def_vyres = def_vyres ? : fbdev->panel->y_res; + init_state++; r = ctrl_init(fbdev); @@ -1322,15 +1428,9 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel goto cleanup; init_state++; - /* We depend on doing this after ctrl_init, since it can redefine - * member functions. - */ - if (fbdev->ctrl->mmap) - omapfb_ops.fb_mmap = omapfb_mmap; - check_required_callbacks(fbdev); - r = fbinfo_init(fbdev); + r = planes_init(fbdev); if (r) goto cleanup; init_state++; @@ -1338,23 +1438,25 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel #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); + omap_set_dma_priority(OMAP_DMA_PORT_EMIFF, 15); #endif - r = ctrl_change_mode(fbdev); + r = ctrl_change_mode(fbdev->fb_info[0]); if (r) { - pr_err("mode setting failed\n"); + dev_err(fbdev->dev, "mode setting failed\n"); goto cleanup; } - if (!manual_update) - omapfb_enable_plane(fbdev, OMAPFB_PLANE_GFX, 1); + /* 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(); + r = fbdev->panel->enable(fbdev->panel); if (r) goto cleanup; init_state++; @@ -1364,10 +1466,15 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel goto cleanup; init_state++; - r = register_framebuffer(fbdev->fb_info); - if (r != 0) { - pr_err("register_framebuffer failed\n"); - goto cleanup; + 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; @@ -1379,18 +1486,17 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel omapfb_dev = fbdev; - pr_info(MODULE_NAME ": initialized vram=%lu " - "pixclock %lu kHz hfreq %lu.%lu kHz vfreq %lu.%lu Hz\n", - fbdev->vram_size, + 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); - DBGLEAVE(1); return 0; cleanup: omapfb_free_resources(fbdev, init_state); - DBGLEAVE(1); return r; } @@ -1398,7 +1504,7 @@ static int omapfb_probe(struct platform_device *pdev) { BUG_ON(fbdev_pdev != NULL); - DBGENTER(1); + /* Delay actual initialization until the LCD is registered */ fbdev_pdev = pdev; if (fbdev_panel != NULL) omapfb_do_probe(fbdev_pdev, fbdev_panel); @@ -1409,7 +1515,6 @@ void omapfb_register_panel(struct lcd_panel *panel) { BUG_ON(fbdev_panel != NULL); - DBGENTER(1); fbdev_panel = panel; if (fbdev_pdev != NULL) omapfb_do_probe(fbdev_pdev, fbdev_panel); @@ -1421,13 +1526,11 @@ static int omapfb_remove(struct platform_device *pdev) struct omapfb_device *fbdev = platform_get_drvdata(pdev); enum omapfb_state saved_state = fbdev->state; - DBGENTER(1); /* FIXME: wait till completion of pending events */ fbdev->state = OMAPFB_DISABLED; omapfb_free_resources(fbdev, saved_state); - DBGLEAVE(1); return 0; } @@ -1436,11 +1539,7 @@ static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg) { struct omapfb_device *fbdev = platform_get_drvdata(pdev); - DBGENTER(1); - - omapfb_blank(VESA_POWERDOWN, fbdev->fb_info); - - DBGLEAVE(1); + omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]); return 0; } @@ -1450,11 +1549,7 @@ static int omapfb_resume(struct platform_device *pdev) { struct omapfb_device *fbdev = platform_get_drvdata(pdev); - DBGENTER(1); - - omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info); - - DBGLEAVE(1); + omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]); return 0; } @@ -1464,7 +1559,7 @@ static struct platform_driver omapfb_driver = { .suspend = omapfb_suspend, .resume = omapfb_resume, .driver = { - .name = OMAPFB_DRIVER, + .name = MODULE_NAME, .owner = THIS_MODULE, }, }; @@ -1477,32 +1572,35 @@ static int __init omapfb_setup(char *options) char *this_opt = NULL; int r = 0; - DBGENTER(1); + pr_debug("omapfb: options %s\n", options); if (!options || !*options) - goto exit; + 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; - def_vram = (simple_strtoul(this_opt + 5, &suffix, 0)); + unsigned long vram; + vram = (simple_strtoul(this_opt + 5, &suffix, 0)); switch (suffix[0]) { case '\0': break; case 'm': case 'M': - def_vram *= 1024; + vram *= 1024; /* Fall through */ case 'k': case 'K': - def_vram *= 1024; + vram *= 1024; break; default: - pr_err("invalid vram suffix\n"); + 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); @@ -1515,12 +1613,11 @@ static int __init omapfb_setup(char *options) else if (!strncmp(this_opt, "manual_update", 13)) manual_update = 1; else { - pr_err("invalid option\n"); + pr_debug("omapfb: invalid option\n"); r = -1; } } -exit: - DBGLEAVE(1); + return r; } @@ -1529,44 +1626,29 @@ exit: /* Register both the driver and the device */ static int __init omapfb_init(void) { - int r = 0; - - DBGENTER(1); - #ifndef MODULE - { - char *option; + char *option; - if (fb_get_options("omapfb", &option)) { - r = -ENODEV; - goto exit; - } - omapfb_setup(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_err("failed to register omapfb driver\n"); - r = -ENODEV; - goto exit; + pr_debug("failed to register omapfb driver\n"); + return -ENODEV; } -exit: - DBGLEAVE(1); - return r; + return 0; } static void __exit omapfb_cleanup(void) { - DBGENTER(1); - platform_driver_unregister(&omapfb_driver); - - DBGLEAVE(1); } module_param_named(accel, def_accel, uint, 0664); -module_param_named(vram, def_vram, ulong, 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); diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c index 82415f50a69..5347e9b9d22 100644 --- a/drivers/video/omap/rfbi.c +++ b/drivers/video/omap/rfbi.c @@ -21,7 +21,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - #include #include #include @@ -35,14 +34,6 @@ #include "dispc.h" -/* #define OMAPFB_DBG 1 */ - -#include "debug.h" - -#define MODULE_NAME "omapfb-rfbi" - -#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args) - #define RFBI_BASE 0x48050800 #define RFBI_REVISION 0x0000 #define RFBI_SYSCONFIG 0x0010 @@ -73,10 +64,9 @@ static struct { void *lcdc_callback_data; unsigned long l4_khz; int bits_per_cycle; + struct omapfb_device *fbdev; } rfbi; -struct lcd_ctrl_extif rfbi_extif; - static inline void rfbi_write_reg(int idx, u32 val) { __raw_writel(val, rfbi.base + idx); @@ -87,7 +77,7 @@ static inline u32 rfbi_read_reg(int idx) return __raw_readl(rfbi.base + idx); } -#ifdef OMAPFB_DBG +#ifdef VERBOSE static void rfbi_print_timings(void) { u32 l; @@ -98,16 +88,20 @@ static void rfbi_print_timings(void) if (l & (1 << 4)) time *= 2; - DBGPRINT(1, "Tick time %u ps\n", time); + dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time); l = rfbi_read_reg(RFBI_ONOFF_TIME0); - DBGPRINT(1, "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); + 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); - DBGPRINT(1, "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " - "ACCESSTIME %d\n", - (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, (l >> 22) & 0x3f); + 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) {} @@ -341,20 +335,18 @@ static void rfbi_set_bits_per_cycle(int bpc) rfbi.bits_per_cycle = bpc; } -static int rfbi_init(void) +static int rfbi_init(struct omapfb_device *fbdev) { u32 l; int r; struct clk *dss_ick; + rfbi.fbdev = fbdev; rfbi.base = io_p2v(RFBI_BASE); - l = rfbi_read_reg(RFBI_REVISION); - pr_info(MODULE_NAME ": version %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); - dss_ick = clk_get(NULL, "dss_ick"); if (IS_ERR(dss_ick)) { - pr_err("can't get dss_ick\n"); + dev_err(fbdev->dev, "can't get dss_ick\n"); return PTR_ERR(dss_ick); } @@ -383,10 +375,14 @@ static int rfbi_init(void) rfbi_write_reg(RFBI_CONTROL, l); if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) { - pr_err("can't get DISPC irq\n"); + dev_err(fbdev->dev, "can't get DISPC irq\n"); return r; } + l = rfbi_read_reg(RFBI_REVISION); + pr_info("omapfb: RFBI version %d.%d initialized\n", + (l >> 4) & 0x0f, l & 0x0f); + return 0; } @@ -395,7 +391,7 @@ static void rfbi_cleanup(void) omap_dispc_free_irq(); } -struct lcd_ctrl_extif rfbi_extif = { +const struct lcd_ctrl_extif omap2_ext_if = { .init = rfbi_init, .cleanup = rfbi_cleanup, .get_clk_info = rfbi_get_clk_info, @@ -406,6 +402,7 @@ struct lcd_ctrl_extif rfbi_extif = { .read_data = rfbi_read_data, .write_data = rfbi_write_data, .transfer_area = rfbi_transfer_area, + .max_transmit_size = (u32)~0, }; diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c index 64dd0a46e51..447989f7221 100644 --- a/drivers/video/omap/sossi.c +++ b/drivers/video/omap/sossi.c @@ -20,7 +20,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - #include #include #include @@ -33,10 +32,6 @@ #include "lcdc.h" -/* #define OMAPFB_DBG 1 */ - -#include "debug.h" - #define MODULE_NAME "omapfb-sossi" #define OMAP_SOSSI_BASE 0xfffbac00 @@ -60,10 +55,8 @@ #define SOSSI_MAX_XMIT_BYTES (512 * 1024) -#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args) - -static struct sossi { - int base; +static struct { + void __iomem *base; unsigned long dpll_khz; int bus_pick_width; void (*lcdc_callback)(void *data); @@ -76,9 +69,10 @@ static struct sossi { * the timings */ int last_access; -} sossi; -struct lcd_ctrl_extif sossi_extif; + struct omapfb_device *fbdev; + struct lcd_ctrl_extif *extif; +} sossi; static inline u32 sossi_read_reg(int reg) { @@ -126,86 +120,8 @@ static void sossi_clear_bits(int reg, u32 bits) static void sossi_dma_callback(void *data); -static int sossi_init(void) -{ - u32 l, k; - struct clk *dpll_clk; - int r; - - sossi.base = IO_ADDRESS(OMAP_SOSSI_BASE); - - dpll_clk = clk_get(NULL, "ck_dpll1"); - if (IS_ERR(dpll_clk)) { - pr_err("can't get dpll1 clock\n"); - return PTR_ERR(dpll_clk); - } - - sossi.dpll_khz = clk_get_rate(dpll_clk) / 1000; - clk_put(dpll_clk); - - sossi_extif.max_transmit_size = SOSSI_MAX_XMIT_BYTES; - - /* 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); - - l |= CONF_MOD_SOSSI_CLK_EN_R; - omap_writel(l, MOD_CONF_CTRL_1); - - omap_writel(omap_readl(ARM_IDLECT2) | (1 << 11), ARM_IDLECT2); - omap_writel(omap_readl(ARM_IDLECT1) | (1 << 6), ARM_IDLECT1); - - 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) { - pr_err("Invalid SoSSI sync pattern: %08x, %08x\n", l, k); - return -ENODEV; - } - - if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) { - pr_err("can't get LCDC IRQ\n"); - return r; - } - - l = sossi_read_reg(SOSSI_ID_REG); /* Component code */ - l = sossi_read_reg(SOSSI_ID_REG); - pr_info(KERN_INFO MODULE_NAME ": 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); - - return 0; -} - -static void sossi_cleanup(void) -{ - omap_lcdc_free_dma_callback(); -} - #define KHZ_TO_PS(x) (1000000000 / (x)) -static void sossi_get_clk_info(u32 *clk_period, u32 *max_clk_div) -{ - *clk_period = KHZ_TO_PS(sossi.dpll_khz); - *max_clk_div = 8; -} - static u32 ps_to_sossi_ticks(u32 ps, int div) { u32 clk_period = KHZ_TO_PS(sossi.dpll_khz) * div; @@ -299,49 +215,14 @@ static int calc_wr_timings(struct extif_timings *t) return 0; } -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 - 1; - - 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 _set_timing(int div, int tw0, int tw1) { u32 l; - DBGPRINT(2, "Using TW0 = %d, TW1 = %d, div = %d\n", +#ifdef VERBOSE + dev_dbg(sossi.fbdev->dev, "Using TW0 = %d, TW1 = %d, div = %d\n", tw0 + 1, tw1 + 1, div + 1); +#endif l = omap_readl(MOD_CONF_CTRL_1); l &= ~(7 << 17); @@ -363,36 +244,6 @@ static inline void set_timing(int access) } } -static void sossi_set_bits_per_cycle(int bpc) -{ - u32 l; - int bus_pick_count, bus_pick_width; - - DBGPRINT(2, "bits_per_cycle %d\n", bpc); - /* 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; - } - l = sossi_read_reg(SOSSI_INIT3_REG); - sossi.bus_pick_width = bus_pick_width; - l &= ~0x3ff; - l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f); - sossi_write_reg(SOSSI_INIT3_REG, l); -} - static void sossi_start_transfer(void) { /* WE */ @@ -446,6 +297,78 @@ static void set_cycles(unsigned int len) 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 - 1; + + 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 = KHZ_TO_PS(sossi.dpll_khz); + *max_clk_div = 8; +} + +static void sossi_set_bits_per_cycle(int bpc) +{ + u32 l; + 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; + } + l = sossi_read_reg(SOSSI_INIT3_REG); + sossi.bus_pick_width = bus_pick_width; + l &= ~0x3ff; + l |= ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f); + sossi_write_reg(SOSSI_INIT3_REG, l); +} + static void sossi_write_command(const void *data, unsigned int len) { set_timing(WR_ACCESS); @@ -483,8 +406,6 @@ static void sossi_transfer_area(int width, int height, sossi_set_bits(SOSSI_INIT1_REG, 1 << 18); set_cycles(width * height * sossi.bus_pick_width / 8); - DBGPRINT(2, "SOSSI_INIT1_REG %08x\n", sossi_read_reg(SOSSI_INIT1_REG)); - sossi_start_transfer(); omap_enable_lcd_dma(); } @@ -521,7 +442,79 @@ static void sossi_read_data(void *data, unsigned int len) sossi_stop_transfer(); } -struct lcd_ctrl_extif sossi_extif = { +static int sossi_init(struct omapfb_device *fbdev) +{ + u32 l, k; + struct clk *dpll_clk; + int r; + + sossi.fbdev = fbdev; + + sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE); + dpll_clk = clk_get(fbdev->dev, "ck_dpll1"); + if (IS_ERR(dpll_clk)) { + dev_err(fbdev->dev, "can't get dpll1 clock\n"); + return PTR_ERR(dpll_clk); + } + + sossi.dpll_khz = clk_get_rate(dpll_clk) / 1000; + clk_put(dpll_clk); + + /* 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); + + l |= CONF_MOD_SOSSI_CLK_EN_R; + omap_writel(l, MOD_CONF_CTRL_1); + + omap_writel(omap_readl(ARM_IDLECT2) | (1 << 11), ARM_IDLECT2); + omap_writel(omap_readl(ARM_IDLECT1) | (1 << 6), ARM_IDLECT1); + + 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); + return -ENODEV; + } + + if ((r = omap_lcdc_set_dma_callback(sossi_dma_callback, NULL)) < 0) { + dev_err(fbdev->dev, "can't get LCDC IRQ\n"); + return r; + } + + l = sossi_read_reg(SOSSI_ID_REG); /* Component code */ + l = sossi_read_reg(SOSSI_ID_REG); + pr_info("omapfb: 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); + + return 0; +} + +static void sossi_cleanup(void) +{ + omap_lcdc_free_dma_callback(); +} + +const struct lcd_ctrl_extif omap1_ext_if = { .init = sossi_init, .cleanup = sossi_cleanup, .get_clk_info = sossi_get_clk_info, @@ -532,4 +525,7 @@ struct lcd_ctrl_extif sossi_extif = { .read_data = sossi_read_data, .write_data = sossi_write_data, .transfer_area = sossi_transfer_area, + + .max_transmit_size = SOSSI_MAX_XMIT_BYTES, }; + diff --git a/include/asm-arm/arch-omap/omapfb.h b/include/asm-arm/arch-omap/omapfb.h index 196b5350aec..de1ded5677b 100644 --- a/include/asm-arm/arch-omap/omapfb.h +++ b/include/asm-arm/arch-omap/omapfb.h @@ -24,6 +24,9 @@ #ifndef __OMAPFB_H #define __OMAPFB_H +#include +#include + /* IOCTL commands. */ #define OMAP_IOW(num, dtype) _IOW('O', num, dtype) @@ -36,14 +39,14 @@ #define OMAPFB_VSYNC OMAP_IO(38) #define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) #define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(41, struct omapfb_update_window_old) -#define OMAPFB_GET_CAPS OMAP_IOR(42, unsigned long) #define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) #define OMAPFB_LCD_TEST OMAP_IOW(45, int) #define OMAPFB_CTRL_TEST OMAP_IOW(46, int) #define OMAPFB_UPDATE_WINDOW OMAP_IOW(47, struct omapfb_update_window) -#define OMAPFB_SETUP_PLANE OMAP_IOW(48, struct omapfb_setup_plane) -#define OMAPFB_ENABLE_PLANE OMAP_IOW(49, struct omapfb_enable_plane) #define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) +#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) +#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) +#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) #define OMAPFB_CAPS_GENERIC_MASK 0x00000fff #define OMAPFB_CAPS_LCDC_MASK 0x00fff000 @@ -56,6 +59,9 @@ #define OMAPFB_FORMAT_MASK 0x00ff #define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 +#define OMAPFB_EVENT_READY 1 +#define OMAPFB_EVENT_DISABLED 2 + enum omapfb_color_format { OMAPFB_COLOR_RGB565 = 0, OMAPFB_COLOR_YUV422, @@ -65,6 +71,7 @@ enum omapfb_color_format { OMAPFB_COLOR_CLUT_2BPP, OMAPFB_COLOR_CLUT_1BPP, OMAPFB_COLOR_RGB444, + OMAPFB_COLOR_YUY422, }; struct omapfb_update_window { @@ -89,18 +96,16 @@ enum omapfb_channel_out { OMAPFB_CHANNEL_OUT_DIGIT, }; -struct omapfb_setup_plane { - __u8 plane; +struct omapfb_plane_info { + __u32 pos_x; + __u32 pos_y; + __u8 enabled; __u8 channel_out; - __u32 offset; - __u32 pos_x, pos_y; - __u32 width, height; - __u32 color_mode; -}; - -struct omapfb_enable_plane { - __u8 plane; - __u8 enable; + __u8 mirror; + __u8 reserved1; + __u32 out_width; + __u32 out_height; + __u32 reserved2[12]; }; enum omapfb_color_key_type { @@ -142,6 +147,9 @@ enum omapfb_update_mode { #define OMAP_LCDC_PANEL_TFT 0x0100 +#define OMAPFB_PLANE_XRES_MIN 8 +#define OMAPFB_PLANE_YRES_MIN 8 + #ifdef CONFIG_ARCH_OMAP1 #define OMAPFB_PLANE_NUM 1 #else @@ -170,15 +178,17 @@ struct lcd_panel { int pcd; /* pixel clock divider. Obsolete use pixel_clock instead */ - int (*init) (struct omapfb_device *fbdev); - void (*cleanup) (void); - int (*enable) (void); - void (*disable) (void); - unsigned long (*get_caps) (void); - int (*set_bklight_level)(unsigned int level); - unsigned int (*get_bklight_level)(void); - unsigned int (*get_bklight_max) (void); - int (*run_test) (int test_num); + 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 omapfb_device; @@ -203,7 +213,7 @@ struct extif_timings { }; struct lcd_ctrl_extif { - int (*init) (void); + int (*init) (struct omapfb_device *fbdev); void (*cleanup) (void); void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div); int (*convert_timings) (struct extif_timings *timings); @@ -214,30 +224,41 @@ struct lcd_ctrl_extif { void (*write_data) (const void *buf, unsigned int len); void (*transfer_area) (int width, int height, void (callback)(void * data), void *data); + 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 omapfb_notifier_block *, - unsigned long event, - struct omapfb_device *fbdev); +typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, + unsigned long event, + void *fbi); + +struct omapfb_mem_region { + dma_addr_t paddr; + void *vaddr; + unsigned long size; + int alloc:1; +}; + +struct omapfb_mem_desc { + int region_cnt; + struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; +}; struct lcd_ctrl { const char *name; void *data; int (*init) (struct omapfb_device *fbdev, - int ext_mode, int req_vram_size); + int ext_mode, + struct omapfb_mem_desc *req_md); void (*cleanup) (void); void (*bind_client) (struct omapfb_notifier_block *nb); - void (*get_vram_layout)(unsigned long *size, - void **virt_base, - dma_addr_t *phys_base); - int (*mmap) (struct vm_area_struct *vma); unsigned long (*get_caps) (void); int (*set_update_mode)(enum omapfb_update_mode mode); enum omapfb_update_mode (*get_update_mode)(void); @@ -246,8 +267,12 @@ struct lcd_ctrl { int screen_width, int pos_x, int pos_y, int width, int height, int color_mode); + 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 omapfb_update_window *win, + int (*update_window) (struct fb_info *fbi, + struct omapfb_update_window *win, void (*callback)(void *), void *callback_data); void (*sync) (void); @@ -258,6 +283,7 @@ struct lcd_ctrl { 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); }; @@ -267,19 +293,20 @@ enum omapfb_state { 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; - void *vram_virt_base; - dma_addr_t vram_phys_base; - unsigned long vram_size; - - int color_mode; int palette_size; - int mirror; u32 pseudo_palette[17]; struct lcd_panel *panel; /* LCD panel */ @@ -287,19 +314,17 @@ struct omapfb_device { struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ struct lcd_ctrl_extif *ext_if; /* LCD ctrl external interface */ - struct fb_info *fb_info; - struct device *dev; + + struct omapfb_mem_desc mem_desc; + struct fb_info *fb_info[OMAPFB_PLANE_NUM]; }; struct omapfb_platform_data { - struct omap_lcd_config lcd; - struct omap_fbmem_config fbmem; + struct omap_lcd_config lcd; + struct omapfb_mem_desc mem_desc; }; -#define OMAPFB_EVENT_READY 1 -#define OMAPFB_EVENT_DISABLED 2 - #ifdef CONFIG_ARCH_OMAP1 extern struct lcd_ctrl omap1_lcd_ctrl; #else @@ -311,12 +336,13 @@ 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); + 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 omapfb_update_window *win, - void (*callback)(void *), - void *callback_data); +extern int omapfb_update_window_async(struct fb_info *fbi, + struct omapfb_update_window *win, + void (*callback)(void *), + void *callback_data); /* in arch/arm/plat-omap/devices.c */ extern void omapfb_reserve_mem(void); -- 2.41.0