📄 s1d13706_16bit.c
字号:
//==========================================================================
//
// s1d13706_16bit.c
//
// Author(s): Michael Kelly - Cogent Computer Systems, Inc.
// Date: 09/14/03
// Description: Init Code for S1D13706 Display Controller
//
//==========================================================================
#include "config.h"
#include "cpuio.h"
#include "genlib.h"
#include "stddefs.h"
#include "s1d13706_16bit.h"
#include "sed_lut.h"
//--------------------------------------------------------------------------
// function prototypes
//
void s1d_init(void);
void lcd_bkl(uchar bright);
void lcd_pwr(uchar bright);
extern int udelay(int delay);
// Global array to hold LCD parameters
typedef struct
{
ushort type; // 0 = passive, 1 = TFT, 2 = HR-TFT
ushort pclk; // pixel clock divider
ushort hor_total // horizontal total time PCLK's
ushort hor_fpw // horizontal front porch width in PCLK's
ushort hor_bpw // horizontal back porch width in PCLK's
ushort hor_spw // horizontal sync pulse width in PCLK's
ushort VERT_TOTAL
ushort VERT_PERIOD
ushort VERT_START
ushort LP_WIDTH
ushort LP_START
ushort FP_WIDTH
ushort FP_START
ushort DISP_MODE_EFFECTS = s1d_reg[12]; // Display Mode and Effects
} LCD_INFO *lcd_info;
ushort s1d_reg[14]; // 0-12 hold registers values, 13 = default pwm duty cycle
// S1D13706 GPIO's used to control power and backlighting:
// CVOUT = Backlight, 0 = off, 1 = on, duty cycle for intensity control
// PWMOUT = Vee (50% to 100% duty cycle for SW contrast control, 0 or 1 for analog control)
// GPIO4 = LCD Enable - High True
// DRDY = ACBIAS for Passive Displays, Display Enable for Active Displays
//--------------------------------------------------------------------------
// s1d_init
//
// This function enables the lcd controller and the lcd
//
void s1d_init()
{
// setup the lcd from the global structure (it must be initialzed by the
// calling function before we are called)
S1D_REG_MCLK_PCLK = s1d_reg[0]; // MCLK Config
S1D_REG_PANEL_AND_MOD_RATE = s1d_reg[1]; // Panel Type
S1D_REG_HOR_TOTAL = s1d_reg[2]; // Horizontal Total
S1D_REG_HOR_PERIOD = s1d_reg[3]; // Horizontal Period
S1D_REG_HOR_START = s1d_reg[4]; // Horizontal Start
S1D_REG_VERT_TOTAL = s1d_reg[5]; // Vertical Total
S1D_REG_VERT_PERIOD = s1d_reg[6]; // Vertical Period
S1D_REG_VERT_START = s1d_reg[7]; // Vertical Start
S1D_REG_LP_WIDTH = s1d_reg[8]; // Line Pulse Width
S1D_REG_LP_START = s1d_reg[9]; // Line Pulse Start
S1D_REG_FP_WIDTH = s1d_reg[10]; // Frame Pulse Width
S1D_REG_FP_START = s1d_reg[11]; // Frame Pulse Start
S1D_REG_DISP_MODE_EFFECTS = s1d_reg[12]; // Display Mode and Effects
// turn the LCD backlight off
lcd_bkl(0);
// Turn on the LCD and then the backlight
SED1356_REG_LCD_DISP_MODE_and_MISC &= ~H2S1D(SED1356_LCD_DISP_BLANK);
lcd_bkl(0xff); // turn the LCD backlight on/full brightness
udelay(10000); // 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 = H2S1D(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 & H2S1D(SED1356_REV_ID_MASK);
if (temp16 != H2S1D(SED1356_REV_ID_1356)){
printf("SED1356 Not Found! SED_REG_REV = %04x.\n", temp16);
return -1;
}
// Disable the display
SED1356_REG_DISP_MODE = H2S1D(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 = H2S1D(SED1356_GPIO_GPIO1); // GPIO1 Out, GPIO2 In
if (SED1356_CRT) sed_disp_mode_crt = 0;
else sed_disp_mode_crt = 1;
// Enable Power Save Mode before we mess with the clocks
SED1356_REG_MEM_CFG_and_REF_RATE = H2S1D(SED1356_REF_TYPE_SELF); // set dram to self refresh first
// shut off MCLK
SED1356_REG_PWR_CFG_and_STAT = H2S1D(SED1356_PWR_MCLK);
// Wait until power is down - when MCLK bit goes true
while ((SED1356_REG_PWR_CFG_and_STAT & H2S1D(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 = H2S1D(SED1356_MCLK_SRC_BCLK);
SED1356_REG_LCD_PCLK_CFG = H2S1D(SED1356_PCLK_SRC_CLKI);
SED1356_REG_CRT_PCLK_CFG = H2S1D(SED1356_PCLK_SRC_CLKI);
SED1356_REG_MEDIA_PCLK_CFG = 0x0000;
SED1356_REG_WAIT_STATE = H2S1D(0x0001);
SED1356_REG_MEM_CFG_and_REF_RATE = H2S1D(SED1356_MEM_CFG_2CAS_EDO | SED1356_REF_RATE_2048);
SED1356_REG_MEM_TMG0_and_1 = H2S1D(SED1356_MEM_TMG0_EDO50_MCLK33 | SED1356_MEM_TMG1_EDO50_MCLK33);
SED1356_REG_PANEL_TYPE_and_MOD_RATE = H2S1D(SED1356_PANEL_TYPE_16 | SED1356_PANEL_TYPE_CLR | SED1356_PANEL_TYPE_TFT);
// LCD Specific Registers
SED1356_REG_LCD_HOR_DISP = H2S1D((PIXELS_PER_ROW/8) - 1);
SED1356_REG_LCD_HOR_NONDISP_and_START = H2S1D(SED_HOR_NONDISP_LCD | (SED_HOR_PULSE_START_LCD << 8));
SED1356_REG_LCD_HOR_PULSE = H2S1D(SED1356_PULSE_WID(SED_HOR_PULSE_WIDTH_LCD) | SED1356_PULSE_POL_LOW);
SED1356_REG_LCD_VER_DISP_HT_LO_and_HI = H2S1D((PIXELS_PER_COL - 1) & 0x3ff);
SED1356_REG_LCD_VER_NONDISP_and_START = H2S1D(SED_VER_NONDISP_LCD | (SED_VER_PULSE_START_LCD << 8));
SED1356_REG_LCD_VER_PULSE = H2S1D(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 = H2S1D(SED1356_LCD_DISP_BLANK | SED1356_LCD_DISP_SWIV_NORM | SED1356_LCD_DISP_4BPP); break;
case 8: SED1356_REG_LCD_DISP_MODE_and_MISC = H2S1D(SED1356_LCD_DISP_BLANK | SED1356_LCD_DISP_SWIV_NORM | SED1356_LCD_DISP_8BPP); break;
default: SED1356_REG_LCD_DISP_MODE_and_MISC = H2S1D(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 = H2S1D((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
// LCD Specific Registers
SED1356_REG_CRT_HOR_DISP = H2S1D((PIXELS_PER_ROW/8) - 1);
SED1356_REG_CRT_HOR_NONDISP_and_START = H2S1D(SED_HOR_NONDISP_CRT | (SED_HOR_PULSE_START_CRT << 8));
SED1356_REG_CRT_HOR_PULSE = H2S1D(SED1356_PULSE_WID(SED_HOR_PULSE_WIDTH_CRT) | SED1356_PULSE_POL_LOW);
SED1356_REG_CRT_VER_DISP_HT_LO_and_HI = H2S1D((PIXELS_PER_COL - 1) & 0x3ff);
SED1356_REG_CRT_VER_NONDISP_and_START = H2S1D(SED_VER_NONDISP_CRT | (SED_VER_PULSE_START_CRT << 8));
SED1356_REG_CRT_VER_PULSE_and_OUT_CTL = H2S1D(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 = H2S1D(SED1356_CRT_DISP_BLANK | SED1356_CRT_DISP_4BPP); break;
case 8: SED1356_REG_CRT_DISP_MODE = H2S1D(SED1356_CRT_DISP_BLANK | SED1356_CRT_DISP_8BPP); break;
default: SED1356_REG_CRT_DISP_MODE = H2S1D(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 = H2S1D((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 = H2S1D(i);
SED1356_REG_LUT_DATA = H2S1D(sed_lut_16bit[i][0]); // red
SED1356_REG_LUT_DATA = H2S1D(sed_lut_16bit[i][1]); // green
SED1356_REG_LUT_DATA = H2S1D(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 = 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();
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 = H2S1D(SED1356_DISP_MODE_OFF);
// Enable Power Save Mode
// set dram to self refresh first
SED1356_REG_MEM_CFG_and_REF_RATE = H2S1D(SED1356_REF_TYPE_SELF);
// shut off MCLK
SED1356_REG_PWR_CFG_and_STAT = H2S1D(SED1356_PWR_MCLK);
// Wait until power is down - when MCLK bit goes true
while ((SED1356_REG_PWR_CFG_and_STAT & H2S1D(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) 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");
printf("Frame Buffer Start: 0x%08lx, End 0x%08lx\n",(long)SED_MEM_BASE,
(long)(SED_MEM_BASE + SED_FB_SIZE(sed_color_depth)));
if (no_wait)
{
printf("Begin Full Screen Color Test.\n");
while(1){
// fill the frame buffer with incrementing color values
for (x = 0; x < 16; x++){
switch (sed_color_depth){
case 4: wr16 = x | x << 4 | x << 8 | x << 12; break;
case 8: wr16 = x | x << 8; break;
default: wr16 = vga_lookup[x]; break; // 16-bits bypasses the lookup table
}
for (i = 0; i < SED_FB_SIZE(sed_color_depth); i += 2){
WR_FB16(i, wr16);
}
} // for x
} // while
} // no_wait
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -