powerpc: use 'video-mode' environment variable to configure DIU

Use the 'video-mode' environment variable (for Freescale chips that have a
DIU display controller) to designate the full video configuration.  Previously,
the DIU driver used the 'monitor' variable, and it was used only to determine
the output video port.

The old definition of the "monitor" environment variable only determines
which video port to use for output.  This variable was set to a number (0,
1, or sometimes 2) to specify a DVI, LVDS, or Dual-LVDS port.  The
resolution was hard-coded into board-specific code.  The Linux command-line
arguments needed to be hard-coded to the proper video definition string.

Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
This commit is contained in:
Timur Tabi 2011-04-11 14:18:22 -05:00 committed by Anatolij Gustschin
parent a5dbdc81ea
commit ba8e76bd49
10 changed files with 291 additions and 425 deletions

11
README
View File

@ -1096,13 +1096,10 @@ The following options need to be configured:
CONFIG_VIDEO_LOGO CONFIG_VIDEO_LOGO
CONFIG_VIDEO_BMP_LOGO CONFIG_VIDEO_BMP_LOGO
The DIU driver will look for the 'monitor' environment variable, The DIU driver will look for the 'video-mode' environment
and if defined, enable the DIU as a console during boot. This variable, and if defined, enable the DIU as a console during
variable should be set to one of these values: boot. See the documentation file README.video for a
description of this variable.
'0' Output video to the DVI connector
'1' Output video to the LVDS connector
'2' Output video to the Dual-Link LVDS connector
- Keyboard Support: - Keyboard Support:
CONFIG_KEYBOARD CONFIG_KEYBOARD

View File

@ -51,20 +51,10 @@ void diu_set_pixel_clock(unsigned int pixclock)
debug("DIU: Modified value of CLKDVDR = 0x%08x\n", in_be32(clkdvdr)); debug("DIU: Modified value of CLKDVDR = 0x%08x\n", in_be32(clkdvdr));
} }
int platform_diu_init(unsigned int *xres, unsigned int *yres) int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)
{ {
unsigned int pixel_format; unsigned int pixel_format = 0x88883316;
#if defined(CONFIG_VIDEO_XRES) & defined(CONFIG_VIDEO_YRES)
*xres = CONFIG_VIDEO_XRES;
*yres = CONFIG_VIDEO_YRES;
#else
*xres = 1024;
*yres = 768;
#endif
pixel_format = 0x88883316;
debug("mpc5121_diu_init\n"); debug("mpc5121_diu_init\n");
return fsl_diu_init(xres, pixel_format, 0);
return fsl_diu_init(*xres, pixel_format, 0);
} }

View File

@ -1,6 +1,7 @@
/* /*
* Copyright 2007 Freescale Semiconductor, Inc. * Copyright 2007-2011 Freescale Semiconductor, Inc.
* York Sun <yorksun@freescale.com> * Authors: York Sun <yorksun@freescale.com>
* Timur Tabi <timur@freescale.com>
* *
* FSL DIU Framebuffer driver * FSL DIU Framebuffer driver
* *
@ -27,6 +28,10 @@
#include <command.h> #include <command.h>
#include <asm/io.h> #include <asm/io.h>
#include <fsl_diu_fb.h> #include <fsl_diu_fb.h>
#include "../common/pixis.h"
#define PX_BRDCFG0_DLINK 0x10
#define PX_BRDCFG0_DVISEL 0x08
void diu_set_pixel_clock(unsigned int pixclock) void diu_set_pixel_clock(unsigned int pixclock)
{ {
@ -49,50 +54,34 @@ void diu_set_pixel_clock(unsigned int pixclock)
debug("DIU: Modified value of CLKDVDR = 0x%08x\n", *guts_clkdvdr); debug("DIU: Modified value of CLKDVDR = 0x%08x\n", *guts_clkdvdr);
} }
int platform_diu_init(unsigned int *xres, unsigned int *yres) int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)
{ {
char *monitor_port; const char *name;
int gamma_fix; int gamma_fix = 0;
unsigned int pixel_format; u32 pixel_format = 0x88883316;
unsigned char tmp_val; u8 temp;
unsigned char pixis_arch;
u8 *pixis_base = (u8 *)PIXIS_BASE;
tmp_val = in_8(pixis_base + PIXIS_BRDCFG0); temp = in_8(&pixis->brdcfg0);
pixis_arch = in_8(pixis_base + PIXIS_VER);
monitor_port = getenv("monitor"); if (strncmp(port, "dlvds", 5) == 0) {
if (!strncmp(monitor_port, "0", 1)) { /* 0 - DVI */ /* Dual link LVDS */
*xres = 1280;
*yres = 1024;
if (pixis_arch == 0x01)
pixel_format = 0x88882317;
else
pixel_format = 0x88883316;
gamma_fix = 0;
out_8(pixis_base + PIXIS_BRDCFG0, tmp_val | 0x08);
} else if (!strncmp(monitor_port, "1", 1)) { /* 1 - Single link LVDS */
*xres = 1024;
*yres = 768;
pixel_format = 0x88883316;
gamma_fix = 0;
out_8(pixis_base + PIXIS_BRDCFG0, (tmp_val & 0xf7) | 0x10);
} else if (!strncmp(monitor_port, "2", 1)) { /* 2 - Double link LVDS */
*xres = 1280;
*yres = 1024;
pixel_format = 0x88883316;
gamma_fix = 1; gamma_fix = 1;
out_8(pixis_base + PIXIS_BRDCFG0, tmp_val & 0xe7); temp &= ~(PX_BRDCFG0_DLINK | PX_BRDCFG0_DVISEL);
name = "Dual-Link LVDS";
} else { /* DVI */ } else if (strncmp(port, "lvds", 4) == 0) {
*xres = 1280; /* Single link LVDS */
*yres = 1024; temp = (temp & ~PX_BRDCFG0_DVISEL) | PX_BRDCFG0_DLINK;
name = "Single-Link LVDS";
} else {
/* DVI */
if (in_8(&pixis->ver) == 1) /* Board version */
pixel_format = 0x88882317; pixel_format = 0x88882317;
gamma_fix = 0; temp |= PX_BRDCFG0_DVISEL;
out_8(pixis_base + PIXIS_BRDCFG0, tmp_val | 0x08); name = "DVI";
} }
return fsl_diu_init(*xres, pixel_format, gamma_fix); printf("DIU: Switching to %s monitor @ %ux%u\n", name, xres, yres);
out_8(&pixis->brdcfg0, temp);
return fsl_diu_init(xres, pixel_format, gamma_fix);
} }

View File

@ -12,6 +12,7 @@
#include <common.h> #include <common.h>
#include <command.h> #include <command.h>
#include <linux/ctype.h>
#include <asm/io.h> #include <asm/io.h>
#include <stdio_dev.h> #include <stdio_dev.h>
#include <video_fb.h> #include <video_fb.h>
@ -81,10 +82,10 @@ void diu_set_pixel_clock(unsigned int pixclock)
out_be32(&gur->clkdvdr, temp | 0x80000000 | ((pixval & 0x1F) << 16)); out_be32(&gur->clkdvdr, temp | 0x80000000 | ((pixval & 0x1F) << 16));
} }
int platform_diu_init(unsigned int *xres, unsigned int *yres) int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)
{ {
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
char *monitor_port; const char *name;
u32 pixel_format; u32 pixel_format;
u8 temp; u8 temp;
@ -100,21 +101,23 @@ int platform_diu_init(unsigned int *xres, unsigned int *yres)
temp = in_8(&pixis->brdcfg1); temp = in_8(&pixis->brdcfg1);
monitor_port = getenv("monitor"); if (strncmp(port, "lvds", 4) == 0) {
if (!strncmp(monitor_port, "1", 1)) { /* 1 - Single link LVDS */ /* Single link LVDS */
*xres = 1024; temp &= ~PX_BRDCFG1_DVIEN;
*yres = 768; /*
/* Enable the DFP port, disable the DVI and the backlight */ * LVDS also needs backlight enabled, otherwise the display
temp &= ~(PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT); * will be blank.
temp |= PX_BRDCFG1_DFPEN; */
temp |= (PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
name = "Single-Link LVDS";
} else { /* DVI */ } else { /* DVI */
*xres = 1280;
*yres = 1024;
/* Enable the DVI port, disable the DFP and the backlight */ /* Enable the DVI port, disable the DFP and the backlight */
temp &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT); temp &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
temp |= PX_BRDCFG1_DVIEN; temp |= PX_BRDCFG1_DVIEN;
name = "DVI";
} }
printf("DIU: Switching to %s monitor @ %ux%u\n", name, xres, yres);
out_8(&pixis->brdcfg1, temp); out_8(&pixis->brdcfg1, temp);
/* /*
@ -136,7 +139,7 @@ int platform_diu_init(unsigned int *xres, unsigned int *yres)
clrsetbits_be32(&gur->pmuxcr, PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_DIU); clrsetbits_be32(&gur->pmuxcr, PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_DIU);
pmuxcr = in_be32(&gur->pmuxcr); pmuxcr = in_be32(&gur->pmuxcr);
return fsl_diu_init(*xres, pixel_format, 0); return fsl_diu_init(xres, pixel_format, 0);
} }
/* /*

View File

@ -28,7 +28,7 @@ LIB := $(obj)libvideo.o
COBJS-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o COBJS-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o
COBJS-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o COBJS-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o
COBJS-$(CONFIG_CFB_CONSOLE) += cfb_console.o COBJS-$(CONFIG_CFB_CONSOLE) += cfb_console.o
COBJS-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o COBJS-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o
COBJS-$(CONFIG_S6E63D6) += s6e63d6.o COBJS-$(CONFIG_S6E63D6) += s6e63d6.o
COBJS-$(CONFIG_VIDEO_AMBA) += amba.o COBJS-$(CONFIG_VIDEO_AMBA) += amba.o
COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o

View File

@ -1,6 +1,7 @@
/* /*
* Copyright 2007, 2010 Freescale Semiconductor, Inc. * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc.
* York Sun <yorksun@freescale.com> * Authors: York Sun <yorksun@freescale.com>
* Timur Tabi <timur@freescale.com>
* *
* FSL DIU Framebuffer driver * FSL DIU Framebuffer driver
* *
@ -24,12 +25,42 @@
*/ */
#include <common.h> #include <common.h>
#include <i2c.h>
#include <malloc.h> #include <malloc.h>
#include <asm/io.h> #include <asm/io.h>
#include "videomodes.h"
#include <video_fb.h>
#include <fsl_diu_fb.h> #include <fsl_diu_fb.h>
struct fb_var_screeninfo {
unsigned int xres; /* visible resolution */
unsigned int yres;
unsigned int bits_per_pixel; /* guess what */
/* Timing: All values in pixclocks, except pixclock (of course) */
unsigned int pixclock; /* pixel clock in ps (pico seconds) */
unsigned int left_margin; /* time from sync to picture */
unsigned int right_margin; /* time from picture to sync */
unsigned int upper_margin; /* time from sync to picture */
unsigned int lower_margin;
unsigned int hsync_len; /* length of horizontal sync */
unsigned int vsync_len; /* length of vertical sync */
unsigned int sync; /* see FB_SYNC_* */
unsigned int vmode; /* see FB_VMODE_* */
unsigned int rotate; /* angle we rotate counter clockwise */
};
struct fb_info {
struct fb_var_screeninfo var; /* Current var */
unsigned int smem_len; /* Length of frame buffer mem */
unsigned int type; /* see FB_TYPE_* */
unsigned int line_length; /* length of a line in bytes */
void *screen_base;
unsigned long screen_size;
};
struct fb_videomode { struct fb_videomode {
const char *name; /* optional */ const char *name; /* optional */
unsigned int refresh; /* optional */ unsigned int refresh; /* optional */
@ -53,6 +84,7 @@ struct fb_videomode {
/* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */ /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */
static struct fb_videomode fsl_diu_mode_800 = { static struct fb_videomode fsl_diu_mode_800 = {
.name = "800x600-60",
.refresh = 60, .refresh = 60,
.xres = 800, .xres = 800,
.yres = 480, .yres = 480,
@ -74,6 +106,7 @@ static struct fb_videomode fsl_diu_mode_800 = {
* hsync 31.5kHz, vsync 60Hz * hsync 31.5kHz, vsync 60Hz
*/ */
static struct fb_videomode fsl_diu_mode_1024 = { static struct fb_videomode fsl_diu_mode_1024 = {
.name = "1024x768-60",
.refresh = 60, .refresh = 60,
.xres = 1024, .xres = 1024,
.yres = 768, .yres = 768,
@ -109,120 +142,137 @@ static struct fb_videomode fsl_diu_mode_1280 = {
*/ */
struct diu_ad { struct diu_ad {
/* Word 0(32-bit) in DDR memory */ /* Word 0(32-bit) in DDR memory */
unsigned int pix_fmt; /* hard coding pixel format */ __le32 pix_fmt; /* hard coding pixel format */
/* Word 1(32-bit) in DDR memory */ /* Word 1(32-bit) in DDR memory */
unsigned int addr; __le32 addr;
/* Word 2(32-bit) in DDR memory */ /* Word 2(32-bit) in DDR memory */
unsigned int src_size_g_alpha; __le32 src_size_g_alpha;
/* Word 3(32-bit) in DDR memory */ /* Word 3(32-bit) in DDR memory */
unsigned int aoi_size; __le32 aoi_size;
/* Word 4(32-bit) in DDR memory */ /* Word 4(32-bit) in DDR memory */
unsigned int offset_xyi; __le32 offset_xyi;
/* Word 5(32-bit) in DDR memory */ /* Word 5(32-bit) in DDR memory */
unsigned int offset_xyd; __le32 offset_xyd;
/* Word 6(32-bit) in DDR memory */ /* Word 6(32-bit) in DDR memory */
unsigned int ckmax_r:8; __le32 ckmax_r:8;
unsigned int ckmax_g:8; __le32 ckmax_g:8;
unsigned int ckmax_b:8; __le32 ckmax_b:8;
unsigned int res9:8; __le32 res9:8;
/* Word 7(32-bit) in DDR memory */ /* Word 7(32-bit) in DDR memory */
unsigned int ckmin_r:8; __le32 ckmin_r:8;
unsigned int ckmin_g:8; __le32 ckmin_g:8;
unsigned int ckmin_b:8; __le32 ckmin_b:8;
unsigned int res10:8; __le32 res10:8;
/* Word 8(32-bit) in DDR memory */ /* Word 8(32-bit) in DDR memory */
unsigned int next_ad; __le32 next_ad;
/* Word 9(32-bit) in DDR memory, just for 64-bit aligned */ /* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
unsigned int res1; __le32 res[3];
unsigned int res2;
unsigned int res3;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* /*
* DIU register map * DIU register map
*/ */
struct diu { struct diu {
unsigned int desc[3]; __be32 desc[3];
unsigned int gamma; __be32 gamma;
unsigned int pallete; __be32 pallete;
unsigned int cursor; __be32 cursor;
unsigned int curs_pos; __be32 curs_pos;
unsigned int diu_mode; __be32 diu_mode;
unsigned int bgnd; __be32 bgnd;
unsigned int bgnd_wb; __be32 bgnd_wb;
unsigned int disp_size; __be32 disp_size;
unsigned int wb_size; __be32 wb_size;
unsigned int wb_mem_addr; __be32 wb_mem_addr;
unsigned int hsyn_para; __be32 hsyn_para;
unsigned int vsyn_para; __be32 vsyn_para;
unsigned int syn_pol; __be32 syn_pol;
unsigned int thresholds; __be32 thresholds;
unsigned int int_status; __be32 int_status;
unsigned int int_mask; __be32 int_mask;
unsigned int colorbar[8]; __be32 colorbar[8];
unsigned int filling; __be32 filling;
unsigned int plut; __be32 plut;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct diu_hw { struct diu_addr {
struct diu *diu_reg; void *vaddr; /* Virtual address */
volatile unsigned int mode; /* DIU operation mode */ u32 paddr; /* 32-bit physical address */
unsigned int offset; /* Alignment offset */
}; };
struct diu_addr { static struct fb_info info;
unsigned char * paddr; /* Virtual address */
unsigned int offset;
};
/* /*
* Modes of operation of DIU * Align to 64-bit(8-byte), 32-byte, etc.
*/ */
#define MFB_MODE0 0 /* DIU off */ static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
#define MFB_MODE1 1 /* All three planes output to display */ {
#define MFB_MODE2 2 /* Plane 1 to display, u32 offset, ssize;
* planes 2+3 written back to memory */ u32 mask;
#define MFB_MODE3 3 /* All three planes written back to memory */
#define MFB_MODE4 4 /* Color bar generation */
#define MAX_CURS 32 ssize = size + bytes_align;
buf->vaddr = malloc(ssize);
if (!buf->vaddr)
return -1;
static struct fb_info fsl_fb_info; memset(buf->vaddr, 0, ssize);
static struct diu_addr gamma, cursor; mask = bytes_align - 1;
static struct diu_ad fsl_diu_fb_ad __attribute__ ((aligned(32))); offset = (u32)buf->vaddr & mask;
static struct diu_ad dummy_ad __attribute__ ((aligned(32))); if (offset) {
static unsigned char *dummy_fb; buf->offset = bytes_align - offset;
static struct diu_hw dr = { buf->vaddr += offset;
.mode = MFB_MODE1, } else
}; buf->offset = 0;
int fb_enabled = 0; buf->paddr = virt_to_phys(buf->vaddr);
int fb_initialized = 0; return 0;
const int default_xres = 1280; }
const int default_pixel_format = 0x88882317;
static int map_video_memory(struct fb_info *info, unsigned long bytes_align); /*
static void enable_lcdc(void); * Allocate a framebuffer and an Area Descriptor that points to it. Both
static void disable_lcdc(void); * are created in the same memory block. The Area Descriptor is updated to
static int fsl_diu_enable_panel(struct fb_info *info); * point to the framebuffer memory. Memory is aligned as needed.
static int fsl_diu_disable_panel(struct fb_info *info); */
static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align); static struct diu_ad *allocate_fb(unsigned int xres, unsigned int yres,
void diu_set_pixel_clock(unsigned int pixclock); unsigned int depth, void **fb)
{
unsigned long size = xres * yres * depth;
struct diu_addr addr;
struct diu_ad *ad;
size_t ad_size = roundup(sizeof(struct diu_ad), 32);
int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix) /*
* Allocate a memory block that holds the Area Descriptor and the
* frame buffer right behind it. To keep the code simple, everything
* is aligned on a 32-byte address.
*/
if (allocate_buf(&addr, ad_size + size, 32) < 0)
return NULL;
ad = addr.vaddr;
ad->addr = cpu_to_le32(addr.paddr + ad_size);
ad->aoi_size = cpu_to_le32((yres << 16) | xres);
ad->src_size_g_alpha = cpu_to_le32((yres << 12) | xres);
ad->offset_xyi = 0;
ad->offset_xyd = 0;
if (fb)
*fb = addr.vaddr + ad_size;
return ad;
}
int fsl_diu_init(int xres, u32 pixel_format, int gamma_fix)
{ {
struct fb_videomode *fsl_diu_mode_db; struct fb_videomode *fsl_diu_mode_db;
struct diu_ad *ad = &fsl_diu_fb_ad; struct diu_ad *ad;
struct diu *hw; struct diu *hw = (struct diu *)CONFIG_SYS_DIU_ADDR;
struct fb_info *info = &fsl_fb_info; u8 *gamma_table_base;
struct fb_var_screeninfo *var = &info->var;
unsigned char *gamma_table_base;
unsigned int i, j; unsigned int i, j;
struct diu_ad *dummy_ad;
debug("Enter fsl_diu_init\n"); struct diu_addr gamma;
dr.diu_reg = (struct diu *) (CONFIG_SYS_DIU_ADDR); struct diu_addr cursor;
hw = (struct diu *) dr.diu_reg;
disable_lcdc();
switch (xres) { switch (xres) {
case 800: case 800:
@ -235,65 +285,40 @@ int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix)
fsl_diu_mode_db = &fsl_diu_mode_1024; fsl_diu_mode_db = &fsl_diu_mode_1024;
} }
if (0 == fb_initialized) { /* The AD struct for the dummy framebuffer and the FB itself */
allocate_buf(&gamma, 768, 32); dummy_ad = allocate_fb(2, 4, 4, NULL);
debug("gamma is allocated @ 0x%x\n", if (!dummy_ad) {
(unsigned int)gamma.paddr); printf("DIU: Out of memory\n");
allocate_buf(&cursor, MAX_CURS * MAX_CURS * 2, 32);
debug("curosr is allocated @ 0x%x\n",
(unsigned int)cursor.paddr);
/* create a dummy fb and dummy ad */
dummy_fb = malloc(64);
if (NULL == dummy_fb) {
printf("Cannot allocate dummy fb\n");
return -1; return -1;
} }
dummy_ad.addr = cpu_to_le32((unsigned int)dummy_fb); dummy_ad->pix_fmt = 0x88883316;
dummy_ad.pix_fmt = 0x88882317;
dummy_ad.src_size_g_alpha = 0x04400000; /* alpha = 0 */
dummy_ad.aoi_size = 0x02000400;
dummy_ad.offset_xyi = 0;
dummy_ad.offset_xyd = 0;
dummy_ad.next_ad = 0;
/* Memory allocation for framebuffer */
if (map_video_memory(info, 32)) {
printf("Unable to allocate fb memory 1\n");
return -1;
}
}
memset(info->screen_base, 0, info->smem_len);
out_be32(&dr.diu_reg->desc[0], (int)&dummy_ad);
out_be32(&dr.diu_reg->desc[1], (int)&dummy_ad);
out_be32(&dr.diu_reg->desc[2], (int)&dummy_ad);
debug("dummy dr.diu_reg->desc[0] = 0x%x\n", dr.diu_reg->desc[0]);
debug("dummy desc[0] = 0x%x\n", hw->desc[0]);
/* read mode info */ /* read mode info */
var->xres = fsl_diu_mode_db->xres; info.var.xres = fsl_diu_mode_db->xres;
var->yres = fsl_diu_mode_db->yres; info.var.yres = fsl_diu_mode_db->yres;
var->bits_per_pixel = 32; info.var.bits_per_pixel = 32;
var->pixclock = fsl_diu_mode_db->pixclock; info.var.pixclock = fsl_diu_mode_db->pixclock;
var->left_margin = fsl_diu_mode_db->left_margin; info.var.left_margin = fsl_diu_mode_db->left_margin;
var->right_margin = fsl_diu_mode_db->right_margin; info.var.right_margin = fsl_diu_mode_db->right_margin;
var->upper_margin = fsl_diu_mode_db->upper_margin; info.var.upper_margin = fsl_diu_mode_db->upper_margin;
var->lower_margin = fsl_diu_mode_db->lower_margin; info.var.lower_margin = fsl_diu_mode_db->lower_margin;
var->hsync_len = fsl_diu_mode_db->hsync_len; info.var.hsync_len = fsl_diu_mode_db->hsync_len;
var->vsync_len = fsl_diu_mode_db->vsync_len; info.var.vsync_len = fsl_diu_mode_db->vsync_len;
var->sync = fsl_diu_mode_db->sync; info.var.sync = fsl_diu_mode_db->sync;
var->vmode = fsl_diu_mode_db->vmode; info.var.vmode = fsl_diu_mode_db->vmode;
info->line_length = var->xres * var->bits_per_pixel / 8; info.line_length = info.var.xres * info.var.bits_per_pixel / 8;
/* Memory allocation for framebuffer */
info.smem_len =
info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8);
ad = allocate_fb(info.var.xres, info.var.yres,
info.var.bits_per_pixel / 8, &info.screen_base);
if (!ad) {
printf("DIU: Out of memory\n");
return -1;
}
ad->pix_fmt = pixel_format; ad->pix_fmt = pixel_format;
ad->addr = cpu_to_le32((unsigned int)info->screen_base);
ad->src_size_g_alpha
= cpu_to_le32((var->yres << 12) | var->xres);
/* fix me. AOI should not be greater than display size */
ad->aoi_size = cpu_to_le32(( var->yres << 16) | var->xres);
ad->offset_xyi = 0;
ad->offset_xyd = 0;
/* Disable chroma keying function */ /* Disable chroma keying function */
ad->ckmax_r = 0; ad->ckmax_r = 0;
@ -304,195 +329,91 @@ int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix)
ad->ckmin_g = 255; ad->ckmin_g = 255;
ad->ckmin_b = 255; ad->ckmin_b = 255;
gamma_table_base = gamma.paddr; /* Initialize the gamma table */
debug("gamma_table_base is allocated @ 0x%x\n", if (allocate_buf(&gamma, 256 * 3, 32) < 0) {
(unsigned int)gamma_table_base); printf("DIU: Out of memory\n");
return -1;
/* Prep for DIU init - gamma table */ }
gamma_table_base = gamma.vaddr;
for (i = 0; i <= 2; i++) for (i = 0; i <= 2; i++)
for (j = 0; j <= 255; j++) for (j = 0; j < 256; j++)
*gamma_table_base++ = j; *gamma_table_base++ = j;
if (gamma_fix == 1) { /* fix the gamma */ if (gamma_fix == 1) { /* fix the gamma */
debug("Fix gamma table\n"); gamma_table_base = gamma.vaddr;
gamma_table_base = gamma.paddr;
for (i = 0; i < 256 * 3; i++) { for (i = 0; i < 256 * 3; i++) {
gamma_table_base[i] = (gamma_table_base[i] << 2) gamma_table_base[i] = (gamma_table_base[i] << 2)
| ((gamma_table_base[i] >> 6) & 0x03); | ((gamma_table_base[i] >> 6) & 0x03);
} }
} }
debug("update-lcdc: HW - %p\n Disabling DIU\n", hw); /* Initialize the cursor */
if (allocate_buf(&cursor, 32 * 32 * 2, 32) < 0) {
printf("DIU: Can't alloc cursor data\n");
return -1;
}
/* Program DIU registers */ /* Program DIU registers */
out_be32(&hw->diu_mode, 0); /* Temporarily disable the DIU */
out_be32(&hw->gamma, (int)gamma.paddr); out_be32(&hw->gamma, gamma.paddr);
out_be32(&hw->cursor, (int)cursor.paddr); out_be32(&hw->cursor, cursor.paddr);
out_be32(&hw->bgnd, 0x007F7F7F); out_be32(&hw->bgnd, 0x007F7F7F);
out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ out_be32(&hw->bgnd_wb, 0);
out_be32(&hw->disp_size, var->yres << 16 | var->xres); /* DISP SIZE */ out_be32(&hw->disp_size, info.var.yres << 16 | info.var.xres);
out_be32(&hw->wb_size, 0); /* WB SIZE */ out_be32(&hw->wb_size, 0);
out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ out_be32(&hw->wb_mem_addr, 0);
out_be32(&hw->hsyn_para, var->left_margin << 22 | /* BP_H */ out_be32(&hw->hsyn_para, info.var.left_margin << 22 |
var->hsync_len << 11 | /* PW_H */ info.var.hsync_len << 11 |
var->right_margin); /* FP_H */ info.var.right_margin);
out_be32(&hw->vsyn_para, var->upper_margin << 22 | /* BP_V */ out_be32(&hw->vsyn_para, info.var.upper_margin << 22 |
var->vsync_len << 11 | /* PW_V */ info.var.vsync_len << 11 |
var->lower_margin); /* FP_V */ info.var.lower_margin);
out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ out_be32(&hw->syn_pol, 0);
out_be32(&hw->thresholds, 0x00037800); /* The Thresholds */ out_be32(&hw->thresholds, 0x00037800);
out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */ out_be32(&hw->int_status, 0);
out_be32(&hw->int_mask, 0); /* INT MASK */ out_be32(&hw->int_mask, 0);
out_be32(&hw->plut, 0x01F5F666); out_be32(&hw->plut, 0x01F5F666);
/* Pixel Clock configuration */ /* Pixel Clock configuration */
debug("DIU pixclock in ps - %d\n", var->pixclock); diu_set_pixel_clock(info.var.pixclock);
diu_set_pixel_clock(var->pixclock);
fb_initialized = 1; /* Set the frame buffers */
out_be32(&hw->desc[0], virt_to_phys(ad));
out_be32(&hw->desc[1], virt_to_phys(dummy_ad));
out_be32(&hw->desc[2], virt_to_phys(dummy_ad));
/* Enable the DIU */ /* Enable the DIU, set display to all three planes */
fsl_diu_enable_panel(info); out_be32(&hw->diu_mode, 1);
enable_lcdc();
return 0; return 0;
} }
char *fsl_fb_open(struct fb_info **info)
{
*info = &fsl_fb_info;
return fsl_fb_info.screen_base;
}
void fsl_diu_close(void)
{
struct fb_info *info = &fsl_fb_info;
fsl_diu_disable_panel(info);
}
static int fsl_diu_enable_panel(struct fb_info *info)
{
struct diu *hw = dr.diu_reg;
struct diu_ad *ad = &fsl_diu_fb_ad;
debug("Entered: enable_panel\n");
if (in_be32(&hw->desc[0]) != (unsigned)ad)
out_be32(&hw->desc[0], (unsigned)ad);
debug("desc[0] = 0x%x\n", hw->desc[0]);
return 0;
}
static int fsl_diu_disable_panel(struct fb_info *info)
{
struct diu *hw = dr.diu_reg;
debug("Entered: disable_panel\n");
if (in_be32(&hw->desc[0]) != (unsigned)&dummy_ad)
out_be32(&hw->desc[0], (unsigned)&dummy_ad);
return 0;
}
static int map_video_memory(struct fb_info *info, unsigned long bytes_align)
{
unsigned long offset;
unsigned long mask;
debug("Entered: map_video_memory\n");
/* allocate maximum 1280*1024 with 32bpp */
info->smem_len = 1280 * 4 *1024 + bytes_align;
debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->smem_len);
info->screen_base = malloc(info->smem_len);
if (info->screen_base == NULL) {
printf("Unable to allocate fb memory\n");
return -1;
}
info->smem_start = (unsigned int) info->screen_base;
mask = bytes_align - 1;
offset = (unsigned long)info->screen_base & mask;
if (offset) {
info->screen_base += (bytes_align - offset);
info->smem_len = info->smem_len - (bytes_align - offset);
} else
info->smem_len = info->smem_len - bytes_align;
info->screen_size = info->smem_len;
debug("Allocated fb @ 0x%08lx, size=%d.\n",
info->smem_start, info->smem_len);
return 0;
}
static void enable_lcdc(void)
{
struct diu *hw = dr.diu_reg;
debug("Entered: enable_lcdc, fb_enabled = %d\n", fb_enabled);
if (!fb_enabled) {
out_be32(&hw->diu_mode, dr.mode);
fb_enabled++;
}
debug("diu_mode = %d\n", hw->diu_mode);
}
static void disable_lcdc(void)
{
struct diu *hw = dr.diu_reg;
debug("Entered: disable_lcdc, fb_enabled = %d\n", fb_enabled);
if (fb_enabled) {
out_be32(&hw->diu_mode, 0);
fb_enabled = 0;
}
}
/*
* Align to 64-bit(8-byte), 32-byte, etc.
*/
static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
{
u32 offset, ssize;
u32 mask;
debug("Entered: allocate_buf\n");
ssize = size + bytes_align;
buf->paddr = malloc(ssize);
if (!buf->paddr)
return -1;
memset(buf->paddr, 0, ssize);
mask = bytes_align - 1;
offset = (u32)buf->paddr & mask;
if (offset) {
buf->offset = bytes_align - offset;
buf->paddr = (unsigned char *) ((u32)buf->paddr + offset);
} else
buf->offset = 0;
return 0;
}
#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
#include <stdio_dev.h>
#include <video_fb.h>
/*
* The Graphic Device
*/
static GraphicDevice ctfb;
void *video_hw_init(void) void *video_hw_init(void)
{ {
struct fb_info *info; static GraphicDevice ctfb;
const char *options;
unsigned int depth = 0, freq = 0;
if (platform_diu_init(&ctfb.winSizeX, &ctfb.winSizeY) < 0) if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq,
&options))
return NULL;
/* Find the monitor port, which is a required option */
if (!options)
return NULL;
if (strncmp(options, "monitor=", 8) != 0)
return NULL;
if (platform_diu_init(ctfb.winSizeX, ctfb.winSizeY, options + 8) < 0)
return NULL; return NULL;
/* fill in Graphic device struct */ /* fill in Graphic device struct */
sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz", sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz",
ctfb.winSizeX, ctfb.winSizeY, 32, 64, 60); ctfb.winSizeX, ctfb.winSizeY, depth, 64, freq);
ctfb.frameAdrs = (unsigned int)fsl_fb_open(&info); ctfb.frameAdrs = (unsigned int)info.screen_base;
ctfb.plnSizeX = ctfb.winSizeX; ctfb.plnSizeX = ctfb.winSizeX;
ctfb.plnSizeY = ctfb.winSizeY; ctfb.plnSizeY = ctfb.winSizeY;
@ -501,7 +422,7 @@ void *video_hw_init(void)
ctfb.isaBase = 0; ctfb.isaBase = 0;
ctfb.pciBase = 0; ctfb.pciBase = 0;
ctfb.memSize = info->screen_size; ctfb.memSize = info.screen_size;
/* Cursor Start Address */ /* Cursor Start Address */
ctfb.dprBase = 0; ctfb.dprBase = 0;
@ -510,4 +431,3 @@ void *video_hw_init(void)
return &ctfb; return &ctfb;
} }
#endif /* defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2007, 2010 Freescale Semiconductor, Inc. * Copyright 2007-2011 Freescale Semiconductor, Inc.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -23,6 +23,8 @@
/* video */ /* video */
#define CONFIG_FSL_DIU_FB
#ifdef CONFIG_FSL_DIU_FB #ifdef CONFIG_FSL_DIU_FB
#define CONFIG_SYS_DIU_ADDR (CONFIG_SYS_CCSRBAR + 0x2c000) #define CONFIG_SYS_DIU_ADDR (CONFIG_SYS_CCSRBAR + 0x2c000)
#define CONFIG_VIDEO #define CONFIG_VIDEO
@ -625,8 +627,6 @@
"diuregs=md e002c000 1d\0" \ "diuregs=md e002c000 1d\0" \
"dium=mw e002c01c\0" \ "dium=mw e002c01c\0" \
"diuerr=md e002c014 1\0" \ "diuerr=md e002c014 1\0" \
"othbootargs=diufb=15M video=fslfb:1280x1024-32@60,monitor=0 debug\0" \
"monitor=0-DVI\0" \
"pmregs=md e00e1000 2b\0" \ "pmregs=md e00e1000 2b\0" \
"lawregs=md e0000c08 4b\0" \ "lawregs=md e0000c08 4b\0" \
"lbcregs=md e0005000 36\0" \ "lbcregs=md e0005000 36\0" \
@ -646,9 +646,7 @@
"ramdiskfile=8610hpcd/ramdisk.uboot\0" \ "ramdiskfile=8610hpcd/ramdisk.uboot\0" \
"fdtaddr=c00000\0" \ "fdtaddr=c00000\0" \
"fdtfile=8610hpcd/mpc8610_hpcd.dtb\0" \ "fdtfile=8610hpcd/mpc8610_hpcd.dtb\0" \
"bdev=sda3\0" \ "bdev=sda3\0"
"othbootargs=diufb=15M video=fslfb:1280x1024-32@60,monitor=0\0"\
"monitor=0-DVI\0"
#endif #endif
#define CONFIG_NFSBOOTCOMMAND \ #define CONFIG_NFSBOOTCOMMAND \

View File

@ -202,6 +202,8 @@
#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " #define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
/* Video */ /* Video */
#define CONFIG_FSL_DIU_FB
#ifdef CONFIG_FSL_DIU_FB #ifdef CONFIG_FSL_DIU_FB
#define CONFIG_SYS_DIU_ADDR (CONFIG_SYS_CCSRBAR + 0x10000) #define CONFIG_SYS_DIU_ADDR (CONFIG_SYS_CCSRBAR + 0x10000)
#define CONFIG_VIDEO #define CONFIG_VIDEO
@ -219,7 +221,7 @@
#undef CONFIG_SYS_FLASH_EMPTY_INFO #undef CONFIG_SYS_FLASH_EMPTY_INFO
#endif #endif
#ifndef CONFIG_DIU #ifndef CONFIG_FSL_DIU_FB
#define CONFIG_ATI #define CONFIG_ATI
#endif #endif
@ -507,9 +509,7 @@
"diuregs=md e002c000 1d\0" \ "diuregs=md e002c000 1d\0" \
"dium=mw e002c01c\0" \ "dium=mw e002c01c\0" \
"diuerr=md e002c014 1\0" \ "diuerr=md e002c014 1\0" \
"othbootargs=diufb=15M video=fslfb:1280x1024-32@60,monitor=0 tty0\0" \ "hwconfig=esdhc;audclk:12\0"
"hwconfig=esdhc;audclk:12\0" \
"monitor=0-DVI\0"
#define CONFIG_HDBOOT \ #define CONFIG_HDBOOT \
"setenv bootargs root=/dev/$bdev rw " \ "setenv bootargs root=/dev/$bdev rw " \

View File

@ -64,8 +64,6 @@
#define CONFIG_SPLASH_SCREEN #define CONFIG_SPLASH_SCREEN
#define CONFIG_VIDEO_LOGO #define CONFIG_VIDEO_LOGO
#define CONFIG_VIDEO_BMP_RLE8 #define CONFIG_VIDEO_BMP_RLE8
#define CONFIG_VIDEO_XRES 800
#define CONFIG_VIDEO_YRES 480
#endif #endif
#define CONFIG_SYS_MPC512X_CLKIN 33333333 /* in Hz */ #define CONFIG_SYS_MPC512X_CLKIN 33333333 /* in Hz */

View File

@ -1,6 +1,7 @@
/* /*
* Copyright 2007 Freescale Semiconductor, Inc. * Copyright 2007, 2011 Freescale Semiconductor, Inc.
* York Sun <yorksun@freescale.com> * Authors: York Sun <yorksun@freescale.com>
* Timur Tabi <timur@freescale.com>
* *
* FSL DIU Framebuffer driver * FSL DIU Framebuffer driver
* *
@ -23,38 +24,8 @@
* MA 02111-1307 USA * MA 02111-1307 USA
*/ */
struct fb_var_screeninfo { int fsl_diu_init(int xres, u32 pixel_format, int gamma_fix);
unsigned int xres; /* visible resolution */
unsigned int yres;
unsigned int bits_per_pixel; /* guess what */ /* Prototypes for external board-specific functions */
int platform_diu_init(unsigned int xres, unsigned int yres, const char *port);
/* Timing: All values in pixclocks, except pixclock (of course) */ void diu_set_pixel_clock(unsigned int pixclock);
unsigned int pixclock; /* pixel clock in ps (pico seconds) */
unsigned int left_margin; /* time from sync to picture */
unsigned int right_margin; /* time from picture to sync */
unsigned int upper_margin; /* time from sync to picture */
unsigned int lower_margin;
unsigned int hsync_len; /* length of horizontal sync */
unsigned int vsync_len; /* length of vertical sync */
unsigned int sync; /* see FB_SYNC_* */
unsigned int vmode; /* see FB_VMODE_* */
unsigned int rotate; /* angle we rotate counter clockwise */
};
struct fb_info {
struct fb_var_screeninfo var; /* Current var */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
unsigned int smem_len; /* Length of frame buffer mem */
unsigned int type; /* see FB_TYPE_* */
unsigned int line_length; /* length of a line in bytes */
char *screen_base;
unsigned long screen_size;
};
extern char *fsl_fb_open(struct fb_info **info);
int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix);
int platform_diu_init(unsigned int *xres, unsigned int *yres);