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"
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
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)
+++ /dev/null
-/*
- * File: drivers/video/omap_new/debug.c
- *
- * Debug support for the omapfb driver
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __OMAPFB_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 */
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
#include <linux/vmalloc.h>
#include "dispc.h"
-/* #define OMAPFB_DBG 1 */
-
-#include "debug.h"
-
-#define MODULE_NAME "omapfb-dispc"
+#define MODULE_NAME "dispc"
#define DISPC_BASE 0x48050400
#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) \
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;
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)
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;
case OMAPFB_PLANE_VID2:
burst_shift = 14;
chout_shift = 16;
+ set_vsize = 1;
break;
default:
return -EINVAL;
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;
l &= ~(0x0f << 1);
l |= color_code << 1;
+ l &= ~(1 << 9);
+ l |= cconv_en << 9;
l &= ~(0x03 << burst_shift);
l |= DISPC_BURST_8x32 << burst_shift;
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;
}
{
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;
}
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;
}
{
int r = 0;
- DBGENTER(1);
-
if (mode != dispc.update_mode) {
switch (mode) {
case OMAPFB_AUTO_UPDATE:
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;
}
}
- 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;
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);
}
}
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;
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);
}
}
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);
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)
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;
}
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));
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)
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
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;
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;
}
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);
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();
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,
.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");
#include <asm/arch/dma.h>
#include <asm/arch/omapfb.h>
-/* #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
#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;
} par;
};
-struct hwa742_struct {
+struct {
enum omapfb_update_mode update_mode;
enum omapfb_update_mode update_mode_before_suspend;
struct lcd_ctrl *int_ctrl;
} hwa742;
+struct lcd_ctrl hwa742_ctrl;
+
static u8 hwa742_read_reg(u8 reg)
{
u8 data;
{
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);
{
unsigned long flags;
- DBGENTER(2);
-
spin_lock_irqsave(&hwa742.req_lock, flags);
while (!list_empty(&hwa742.pending_req_list)) {
}
spin_unlock_irqrestore(&hwa742.req_lock, flags);
-
- DBGLEAVE(2);
}
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;
if (process)
process_pending_requests();
-
- DBGLEAVE(2);
}
static void request_complete(void *data)
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:
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)
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);
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)
{
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;
}
submit_req_list(&req_list);
out:
- DBGLEAVE(2);
return r;
}
EXPORT_SYMBOL(hwa742_update_window_async);
struct hwa742_request *req;
struct completion comp;
- DBGENTER(2);
-
req = alloc_req();
req->handler = sync_handler;
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);
}
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"));
case OMAPFB_UPDATE_DISABLED:
break;
}
-out:
- DBGLEAVE(1);
- return r;
+ return 0;
}
static enum omapfb_update_mode hwa742_get_update_mode(void)
* 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;
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);
* 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;
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);
return 0;
err:
- pr_err("can't setup timings\n");
+ dev_err(hwa742.fbdev->dev, "can't setup timings\n");
return -1;
}
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) {
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;
}
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;
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;
}
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++)
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();
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/device.h>
#include <asm/mach-types.h>
-/* #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
#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,
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)
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);
}
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)
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;
}
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)
{
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:
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();
}
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);
}
}
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;
}
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 */
* 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;
{
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 */
{
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 ) |
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);
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;
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);
{
int r = 0;
- DBGENTER(1);
-
- if (mode != omap_lcdc.update_mode) {
+ if (mode != lcdc.update_mode) {
switch (mode) {
case OMAPFB_AUTO_UPDATE:
setup_regs();
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();
}
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();
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;
}
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)
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);
/* 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;
}
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;
}
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)
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,
.enable_plane = omap_lcdc_enable_plane,
.setcolreg = omap_lcdc_setcolreg,
};
-
-MODULE_DESCRIPTION("TI OMAP LCDC controller");
-MODULE_LICENSE("GPL");
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
#include <asm/uaccess.h>
-#include <asm/atomic.h>
#include <asm/mach-types.h>
-
#include <asm/arch/dma.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/board.h>
#include <asm/arch/omapfb.h>
-/* #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;
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
#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
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)
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;
}
/* Called each time the omapfb device is opened */
static int omapfb_open(struct fb_info *info, int user)
{
- DBGENTER(1);
- DBGLEAVE(1);
return 0;
}
* 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;
}
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:
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;
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)
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)
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;
}
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)
/* 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:
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 */
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);
/* 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
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;
}
*/
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
*/
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 &&
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);
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;
}
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;
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);
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:
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,
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:
r = -EINVAL;
break;
}
- r = fbdev->panel->run_test(test_num);
+ r = fbdev->panel->run_test(fbdev->panel, test_num);
break;
}
case OMAPFB_CTRL_TEST:
r = -EINVAL;
}
- DBGLEAVE(2);
return r;
}
{
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)
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",
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;
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
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;
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;
}
/* 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
*/
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;
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';
}
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;
}
if (fbdev->ctrl == NULL) {
- DBGPRINT(1, "ctrl %s not supported\n", name);
+ dev_dbg(fbdev->dev, "ctrl %s not supported\n", name);
return -1;
}
/* 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);
#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);
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++;
#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++;
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;
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;
}
{
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);
{
BUG_ON(fbdev_panel != NULL);
- DBGENTER(1);
fbdev_panel = panel;
if (fbdev_pdev != NULL)
omapfb_do_probe(fbdev_pdev, fbdev_panel);
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;
}
{
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;
}
{
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;
}
.suspend = omapfb_suspend,
.resume = omapfb_resume,
.driver = {
- .name = OMAPFB_DRIVER,
+ .name = MODULE_NAME,
.owner = THIS_MODULE,
},
};
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);
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;
}
/* 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);
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include "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
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);
return __raw_readl(rfbi.base + idx);
}
-#ifdef OMAPFB_DBG
+#ifdef VERBOSE
static void rfbi_print_timings(void)
{
u32 l;
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) {}
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);
}
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;
}
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,
.read_data = rfbi_read_data,
.write_data = rfbi_write_data,
.transfer_area = rfbi_transfer_area,
+
.max_transmit_size = (u32)~0,
};
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/mm.h>
#include "lcdc.h"
-/* #define OMAPFB_DBG 1 */
-
-#include "debug.h"
-
#define MODULE_NAME "omapfb-sossi"
#define OMAP_SOSSI_BASE 0xfffbac00
#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);
* 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)
{
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;
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);
}
}
-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 */
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);
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();
}
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,
.read_data = sossi_read_data,
.write_data = sossi_write_data,
.transfer_area = sossi_transfer_area,
+
+ .max_transmit_size = SOSSI_MAX_XMIT_BYTES,
};
+
#ifndef __OMAPFB_H
#define __OMAPFB_H
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
/* IOCTL commands. */
#define OMAP_IOW(num, dtype) _IOW('O', num, dtype)
#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
#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,
OMAPFB_COLOR_CLUT_2BPP,
OMAPFB_COLOR_CLUT_1BPP,
OMAPFB_COLOR_RGB444,
+ OMAPFB_COLOR_YUY422,
};
struct omapfb_update_window {
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 {
#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
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;
};
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);
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);
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);
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);
};
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 */
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
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);