📄 sed135x_16bit.c
字号:
//==========================================================================
//
// sed135x_16bit.c
//
// Author(s): Michael Kelly - Cogent Computer Systems, Inc.
// Date: 05-24-2002
// Description: Init Code for SED135x Display Controller
//
//==========================================================================
#include "config.h"
#include "cpuio.h"
#include "genlib.h"
#include "stddefs.h"
#include "sed1356_16bit.h"
#include "font8x16.h"
#include "sed_lut.h"
//--------------------------------------------------------------------------
// function prototypes
//
ulong sed135x_init(void);
void sed135x_on(void);
void sed135x_off(void);
void sed_lcd_bkl(uchar bright);
void sed_putchar(char c);
void sed_writechar(uchar c);
void sed_clr_row(int char_row);
int sed_tst(int argc,char *argv[]);
int sed(int argc,char *argv[]);
extern int udelay(int delay);
extern void lcd_bkl(uchar bright);
extern void fs6377_init(int);
extern ulong i2c_rd_device(uchar dev, uchar reg, uchar *data);
// global flags to determine what, if anything, was found
int sed135x_ok;
int sed135x_tst = 0; // flag to indicate we are testing to disable sed_puchar
int sed_disp_mode_crt;
// globals to keep track of foreground, background colors and x,y position
int sed_color_depth; // 4, 8 or 16
int sed_fg_color; // 0 to 15, used as lookup into VGA color table
int sed_bg_color; // 0 to 15, used as lookup into VGA color table
int sed_col; // current column, 0 to COLS_PER_SCREEN - 1
int sed_row; // current row, 0 to (ROWS_PER_SCREEN * 2) - 1
ulong sed_fb_offset; // current offset into frame buffer for sed_putchar
// GPIO1 is used to control the LCD backlight on many CSB's
#define SED1356_BKL_ON SED1356_REG_GPIO_CTL |= H2SED(SED1356_GPIO_GPIO1) // GPIO1 = 1
#define SED1356_BKL_OFF SED1356_REG_GPIO_CTL &= H2SED(~SED1356_GPIO_GPIO1) // GPIO1 = 0
// GPIO2 is used to sense the presence of a monitor. 0 = monitor connected, 1 = no monitor
// we invert the sense to make it easier to test and more logical.
//#define SED1356_CRT SED1356_REG_GPIO_CTL & H2SED(SED1356_GPIO_GPIO2)
#define SED_FB_SIZE(_depth_) (((PIXELS_PER_COL * PIXELS_PER_ROW) * _depth_) / 8)
#define SED_ROW_SIZE(_depth_) ((PIXELS_PER_ROW * _depth_) / 8)
#define SED_GET_ADD(_row_, _col_, _depth_) (((((_row_ * PIXELS_PER_ROW) * FONT_HEIGHT) \
+ (_col_ * FONT_WIDTH)) \
* _depth_) / 8)
//--------------------------------------------------------------------------
// sed135x_on
//
// This function turns on the SED1355 or SED1356 LCD and/or CRT
//
void sed135x_on()
{
sed135x_off();
// Turn on the LCD and/or CRT
// The SED1356 supports seperate LCD and CRT timing registers
// that have already been setup. We just blank the side we
// aren't using and enable the other.
if (sed_disp_mode_crt) { // 1 = CRT Mode
// Blank the LCD and CRT
SED1356_REG_LCD_DISP_MODE_and_MISC |= H2SED(SED1356_LCD_DISP_BLANK);
SED1356_REG_CRT_DISP_MODE |= H2SED(SED1356_CRT_DISP_BLANK);
// turn the LCD backlight off
lcd_bkl(0);
// Set the SED1356 to CRT Mode
SED1356_REG_DISP_MODE = H2SED(SED1356_DISP_SWIV_NORM | SED1356_DISP_MODE_CRT);
// Turn on the CRT
SED1356_REG_CRT_DISP_MODE &= ~H2SED(SED1356_CRT_DISP_BLANK);
} // if CRT mode
else { // 0 = LCD Mode
// Blank the LCD and CRT
SED1356_REG_LCD_DISP_MODE_and_MISC |= H2SED(SED1356_LCD_DISP_BLANK);
SED1356_REG_CRT_DISP_MODE |= H2SED(SED1356_CRT_DISP_BLANK);
// Set the SED1356 to LCD Mode
SED1356_REG_DISP_MODE = H2SED(SED1356_DISP_SWIV_NORM | SED1356_DISP_MODE_LCD);
// Turn on the LCD
SED1356_REG_LCD_DISP_MODE_and_MISC &= ~H2SED(SED1356_LCD_DISP_BLANK);
lcd_bkl(0xff); // turn the LCD backlight on/full brightness
} // else LCD Mode
monDelay(10); // wait for Power-up sequence to complete
}
//--------------------------------------------------------------------------
// sed_lcd_bkl()
//
// This function turns on the LCD backlight connected to GPIO1. This is
// not used if the board has a different method of controlling the
// backlight. Since the Sed has only a single GPIO bit and no way
// to modulate it, we use any non-zero value of bright to turn it on.
//
void sed_lcd_bkl(uchar bright)
{
// Any non-zero value for bright means on
if (bright) SED1356_BKL_ON;
else SED1356_BKL_OFF;
}
//--------------------------------------------------------------------------
// sed135x_off
//
// This function turns off the SED1356 LCD and/or CRT and the display
// fifo. It can also turn off the clocks if mode is true, thus allowing
// the programmable clock generator to be changed.
//
void sed135x_off()
{
SED1356_REG_DISP_MODE = H2SED(SED1356_DISP_SWIV_NORM | SED1356_DISP_MODE_OFF);
lcd_bkl(0); // turn the LCD backlight off
}
//--------------------------------------------------------------------------
// sed135x_init
//
// This function sets up the sed1355 or sed1356 whichever is found
//
vulong sed135x_init()
{
vushort temp16;
int i;
sed135x_ok = 0;
sed_disp_mode_crt = 0; // assume LCD
// enable host access
SED1356_REG_REV_and_MISC = 0x0000;
// Check the ID to make sure we even have a SED1356 installed
temp16 = SED1356_REG_REV_and_MISC & H2SED(SED1356_REV_ID_MASK);
if (temp16 != H2SED(SED1356_REV_ID_1356)){
#ifdef LCD_DEBUG
printf("SED1356 Not Found! SED_REG_REV = %04x.\n", temp16);
#endif
return -1;
}
// Disable the display
SED1356_REG_DISP_MODE = H2SED(SED1356_DISP_SWIV_NORM | SED1356_DISP_MODE_OFF);
// Test for the presence of a CRT
SED1356_REG_GPIO_CTL = 0x0000; // Disable Backlight
SED1356_REG_GPIO_CFG = H2SED(SED1356_GPIO_GPIO1); // GPIO1 Out, GPIO2 In
if (SED1356_CRT)
{
sed_disp_mode_crt = 0;
#ifdef LCD_DEBUG
printf("SED1356 is in LCD Mode.\n");
#endif
}
else
{
sed_disp_mode_crt = 1;
#ifdef LCD_DEBUG
printf("SED1356 is in CRT Mode.\n");
#endif
}
// Enable Power Save Mode before we mess with the clocks
SED1356_REG_MEM_CFG_and_REF_RATE = H2SED(SED1356_REF_TYPE_SELF); // set dram to self refresh first
// shut off MCLK
SED1356_REG_PWR_CFG_and_STAT = H2SED(SED1356_PWR_MCLK);
// Wait until power is down - when MCLK bit goes true
while ((SED1356_REG_PWR_CFG_and_STAT & H2SED(SED1356_PWR_MCLK)) == 0){}
// Change the programmable clock generator to the desired timing
if (sed_disp_mode_crt) fs6377_init(SED_DISP_MODE_CRT);
else fs6377_init(SED_DISP_MODE_LCD);
// Re-enable Power
SED1356_REG_PWR_CFG_and_STAT = 0x0000;
// Common Control Registers
SED1356_REG_MCLK_CFG = H2SED(SED1356_MCLK_SRC_BCLK);
SED1356_REG_LCD_PCLK_CFG = H2SED(SED1356_PCLK_SRC_CLKI);
SED1356_REG_CRT_PCLK_CFG = H2SED(SED1356_PCLK_SRC_CLKI);
SED1356_REG_MEDIA_PCLK_CFG = 0x0000;
SED1356_REG_WAIT_STATE = H2SED(0x0001);
SED1356_REG_MEM_CFG_and_REF_RATE = H2SED(SED1356_MEM_CFG_2CAS_EDO | SED1356_REF_RATE_2048);
SED1356_REG_MEM_TMG0_and_1 = H2SED(SED1356_MEM_TMG0_EDO50_MCLK33 | SED1356_MEM_TMG1_EDO50_MCLK33);
SED1356_REG_PANEL_TYPE_and_MOD_RATE = H2SED(SED1356_PANEL_TYPE_16 | SED1356_PANEL_TYPE_CLR | SED1356_PANEL_TYPE_TFT);
// LCD Specific Registers
SED1356_REG_LCD_HOR_DISP = H2SED((PIXELS_PER_ROW/8) - 1);
SED1356_REG_LCD_HOR_NONDISP_and_START = H2SED(SED_HOR_NONDISP_LCD | (SED_HOR_PULSE_START_LCD << 8));
SED1356_REG_LCD_HOR_PULSE = H2SED(SED1356_PULSE_WID(SED_HOR_PULSE_WIDTH_LCD) | SED1356_PULSE_POL_LOW);
SED1356_REG_LCD_VER_DISP_HT_LO_and_HI = H2SED((PIXELS_PER_COL - 1) & 0x3ff);
SED1356_REG_LCD_VER_NONDISP_and_START = H2SED(SED_VER_NONDISP_LCD | (SED_VER_PULSE_START_LCD << 8));
SED1356_REG_LCD_VER_PULSE = H2SED(SED1356_PULSE_WID(SED_VER_PULSE_WIDTH_LCD) | SED1356_PULSE_POL_LOW);
switch (sed_color_depth) {
case 4: SED1356_REG_LCD_DISP_MODE_and_MISC = H2SED(SED1356_LCD_DISP_BLANK | SED1356_LCD_DISP_SWIV_NORM | SED1356_LCD_DISP_4BPP); break;
case 8: SED1356_REG_LCD_DISP_MODE_and_MISC = H2SED(SED1356_LCD_DISP_BLANK | SED1356_LCD_DISP_SWIV_NORM | SED1356_LCD_DISP_8BPP); break;
default: SED1356_REG_LCD_DISP_MODE_and_MISC = H2SED(SED1356_LCD_DISP_BLANK | SED1356_LCD_DISP_SWIV_NORM | SED1356_LCD_DISP_16BPP); break;
}
SED1356_REG_LCD_DISP_START_LO_and_MID = 0x0000;
SED1356_REG_LCD_DISP_START_HI = 0x0000;
SED1356_REG_LCD_ADD_OFFSET_LO_and_HI = H2SED((SED_ROW_SIZE(sed_color_depth) / 2) & 0x7ff);
SED1356_REG_LCD_PIXEL_PAN = 0x0000;
SED1356_REG_LCD_FIFO_THRESH_LO_and_HI = 0x0000; // auto mode
// CRT Specific Registers
SED1356_REG_CRT_HOR_DISP = H2SED((PIXELS_PER_ROW/8) - 1);
SED1356_REG_CRT_HOR_NONDISP_and_START = H2SED(SED_HOR_NONDISP_CRT | (SED_HOR_PULSE_START_CRT << 8));
SED1356_REG_CRT_HOR_PULSE = H2SED(SED1356_PULSE_WID(SED_HOR_PULSE_WIDTH_CRT) | SED1356_PULSE_POL_LOW);
SED1356_REG_CRT_VER_DISP_HT_LO_and_HI = H2SED((PIXELS_PER_COL - 1) & 0x3ff);
SED1356_REG_CRT_VER_NONDISP_and_START = H2SED(SED_VER_NONDISP_CRT | (SED_VER_PULSE_START_CRT << 8));
SED1356_REG_CRT_VER_PULSE_and_OUT_CTL = H2SED(SED1356_PULSE_WID(SED_VER_PULSE_WIDTH_CRT) | SED1356_PULSE_POL_LOW | SED1356_CRT_OUT_DAC_LVL);
switch (sed_color_depth) {
case 4: SED1356_REG_CRT_DISP_MODE = H2SED(SED1356_CRT_DISP_BLANK | SED1356_CRT_DISP_4BPP); break;
case 8: SED1356_REG_CRT_DISP_MODE = H2SED(SED1356_CRT_DISP_BLANK | SED1356_CRT_DISP_8BPP); break;
default: SED1356_REG_CRT_DISP_MODE = H2SED(SED1356_CRT_DISP_BLANK | SED1356_CRT_DISP_16BPP); break;
}
SED1356_REG_CRT_DISP_START_LO_and_MID = 0x0000;
SED1356_REG_CRT_DISP_START_HI = 0x0000;
SED1356_REG_CRT_ADD_OFFSET_LO_and_HI = H2SED((SED_ROW_SIZE(sed_color_depth) / 2) & 0x7ff);
SED1356_REG_CRT_PIXEL_PAN = 0x0000;
SED1356_REG_CRT_FIFO_THRESH_LO_and_HI = 0x0000; // auto mode
// Disable Cursor
SED1356_REG_LCD_CURSOR_CTL_and_START_ADD = 0x0000;
SED1356_REG_CRT_CURSOR_CTL_and_START_ADD = 0x0000;
// Disable BitBlt
SED1356_REG_BLT_CTL_0_and_1 = 0x0000;
SED1356_REG_BLT_ROP_CODE_and_BLT_OP = 0x0000;
SED1356_REG_BLT_SRC_START_LO_and_MID = 0x0000;
SED1356_REG_BLT_SRC_START_HI = 0x0000;
SED1356_REG_BLT_DEST_START_LO_and_MID = 0x0000;
SED1356_REG_BLT_DEST_START_HI = 0x0000;
SED1356_REG_BLT_ADD_OFFSET_LO_and_HI = 0x0000;
SED1356_REG_BLT_WID_LO_and_HI = 0x0000;
SED1356_REG_BLT_HGT_LO_and_HI = 0x0000;
SED1356_REG_BLT_BG_CLR_LO_and_HI = 0x0000;
SED1356_REG_BLT_FG_CLR_LO_and_HI = 0x0000;
// Fill the LUT, write to both LCD and CRT luts simultaneously
SED1356_REG_LUT_MODE = 0x0000;
for (i = 0; i < 256; i++){
SED1356_REG_LUT_ADD = H2SED(i);
SED1356_REG_LUT_DATA = H2SED(sed_lut_16bit[i][0]); // red
SED1356_REG_LUT_DATA = H2SED(sed_lut_16bit[i][1]); // green
SED1356_REG_LUT_DATA = H2SED(sed_lut_16bit[i][2]); // blue
}
// Disable Power Save Mode
SED1356_REG_PWR_CFG_and_STAT = 0x0000;
// Set Watchdog
SED1356_REG_WATCHDOG_CTL = 0x0000;
// initialize the globals
sed135x_ok = 1;
sed_fg_color = SED_FG_DEF;
sed_bg_color = SED_BG_DEF;
sed_row = 0;
sed_col = 0;
sed_fb_offset = 0x00;
// fill the screen with the background color, remember for the console driver
// we do double buffering, so fill twice as mush as the active screen size
switch (sed_color_depth){
case 4: temp16 = sed_bg_color | sed_bg_color << 4 | sed_bg_color << 8 | sed_bg_color << 12; break;
case 8: temp16 = sed_bg_color | sed_bg_color << 8; break;
default: temp16 = vga_lookup[sed_bg_color]; break;
}
for (i = 0; i < (PIXELS_PER_COL * PIXELS_PER_ROW) * 4; i += 2){
WR_FB16(i, temp16);
}
// turn on the display
sed135x_on();
#ifdef LCD_DEBUG
printf("SED1356 init complete.\n");
#endif
return 0;
}
//--------------------------------------------------------------------------
// sed_pwr_dn()
void sed_pwr_dn(){
// Enable Host Access
SED1356_REG_REV_and_MISC = 0x0000;
// Disable the display
SED1356_REG_DISP_MODE = H2SED(SED1356_DISP_MODE_OFF);
// Enable Power Save Mode
// set dram to self refresh first
SED1356_REG_MEM_CFG_and_REF_RATE = H2SED(SED1356_REF_TYPE_SELF);
// shut off MCLK
SED1356_REG_PWR_CFG_and_STAT = H2SED(SED1356_PWR_MCLK);
// Wait until power is down - when MCLK bit goes true
while ((SED1356_REG_PWR_CFG_and_STAT & H2SED(SED1356_PWR_MCLK)) == 0){}
}
//--------------------------------------------------------------------------
// sed_tst()
//
// This test will initialize the SED135x, do a frame buffer
// test and then display 16 VGA colors full screen until stopped.
//
#define SED_I_OPTION
#define SED_S_OPTION
#define USAGE_STRING "-[cd:ilns]"
#include "sed_tstHelp.c"
int sed_tst(int argc,char *argv[])
{
volatile ushort wr16, rd16, temp16;
int i, x, opt;
int no_wait = 0;
int init_only = 0;
char c;
sed135x_tst = 1;
sed135x_off();
while ((opt=getopt(argc,argv,"clnsid:")) != -1) {
switch(opt) {
case 'l': // Override sed_disp_mode_crt, Run Test in LCD Mode
sed_disp_mode_crt = 0;
printf("Forcing LCD Mode!\n");
break;
case 'c': // Override sed_disp_mode_crt, Run Test in CRT Mode
sed_disp_mode_crt = 1;
printf("Forcing CRT Mode!\n");
break;
case 'd': // set the color depth
switch(*optarg) {
case '4':
sed_color_depth = 4;
printf("Forcing 4bpp Mode!\n");
break;
case '8':
sed_color_depth = 8;
printf("Forcing 8bpp Mode!\n");
break;
case '1':
sed_color_depth = 16;
printf("Forcing 16bpp Mode!\n");
break;
default: // test with current depth
break;
}
break;
case 'n': // no waiting for keypress - fastest operation
no_wait = 1;
printf("No Keypress Mode, Must Reset System to Stop!\n");
break;
case 'i': // init only
no_wait = 1;
printf("Initializing SED, Skipping tests!\n");
init_only = 1;
break;
case 's': // Scope loop
no_wait = 1;
printf("Scope Loop, press any key to Stop!\n");
while(1){
SED1356_REG_REV_and_MISC = 0;
temp16 = SED1356_REG_REV_and_MISC;
if (gotachar()) break;
}
break;
default: // test with current mode
break;
}
}
sed135x_init();
if (sed135x_ok == 0) return -1;
sed135x_on();
if (init_only)
{
sed135x_tst = 0;
return 0;
}
printf("Frame Buffer R/W...");
// do an address=data read/write test on the frame buffer
// PIXELS_PER_COL * PIXELS_PER_ROW is the highest pixel.
// Multiply by bits_per_pixel (sed_color_depth), then
// divide by 8 to get the actual byte count.
for (i = 0; i < SED_FB_SIZE(sed_color_depth); i += 4){
WR_FB16(i, (i & 0xffff));
RD_FB16(i, rd16);
if(rd16 != (i & 0xffff)){
printf("Fail at 0x%08lx, WR 0x%08x, RD 0x%04x!\n",
(long)(SED_MEM_BASE + i), i, rd16);
// return -1;
}
}
printf("OK!\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -