📄 voyager.c
字号:
: FIELD_SET(0, CURRENT_POWER_CLOCK, V2XCLK_DIVIDER, 3))
| FIELD_VALUE(0, CURRENT_POWER_CLOCK, V2XCLK_SHIFT, clock.shift);
// Set control register value.
register_table->control
= (mode->vertical_sync_polarity == POSITIVE
? FIELD_SET(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, ACTIVE_HIGH)
: FIELD_SET(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, ACTIVE_LOW))
| (mode->horizontal_sync_polarity == POSITIVE
? FIELD_SET(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, ACTIVE_HIGH)
: FIELD_SET(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, ACTIVE_LOW))
| FIELD_SET(0, CRT_DISPLAY_CTRL, SELECT, CRT)
| FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE)
| FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE)
| (bpp == 8
? FIELD_SET(0, CRT_DISPLAY_CTRL, FORMAT, 8)
: (bpp == 16
? FIELD_SET(0, CRT_DISPLAY_CTRL, FORMAT, 16)
: FIELD_SET(0, CRT_DISPLAY_CTRL, FORMAT, 32)));
// Set timing registers.
register_table->horizontal_total
= FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL,
mode->horizontal_total - 1)
| FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END,
mode->horizontal_display_end - 1);
register_table->horizontal_sync
= FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH,
mode->horizontal_sync_width)
| FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START,
mode->horizontal_sync_start - 1);
register_table->vertical_total
= FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL,
mode->vertical_total - 1)
| FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END,
mode->vertical_display_end - 1);
register_table->vertical_sync
= FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT,
mode->vertical_sync_height)
| FIELD_VALUE(0, CRT_VERTICAL_SYNC, START,
mode->vertical_sync_start - 1);
}
// Calculate frame buffer width and height.
register_table->fb_width = mode->horizontal_display_end * (bpp / 8);
register_table->width = mode->horizontal_display_end;
register_table->height = mode->vertical_display_end;
// Save display type.
register_table->display = display;
}
// Program the mode with the registers specified.
void programMode(reg_table_t *register_table)
{
unsigned long value, gate, clock;
unsigned long palette_ram;
unsigned long fb_size, offset;
// Get current power configuration.
gate = regRead32(CURRENT_POWER_GATE);
clock = regRead32(CURRENT_POWER_CLOCK);
// Program panel.
if (register_table->display == PANEL)
{
// Program clock, enable display controller.
gate = FIELD_SET(gate, CURRENT_POWER_GATE, DISPLAY, ENABLE);
clock &= FIELD_CLEAR(CURRENT_POWER_CLOCK, P2XCLK_SELECT)
& FIELD_CLEAR(CURRENT_POWER_CLOCK, P2XCLK_DIVIDER)
& FIELD_CLEAR(CURRENT_POWER_CLOCK, P2XCLK_SHIFT);
// Set engine clock to 72Mhz, memory clock to 144MHz
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_SELECT, 288); //MCLK=72MHz
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_DIVIDER, 1);
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_SHIFT, 2);
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_SELECT, 288); //M2XCLK=144MHz
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_DIVIDER, 1);
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_SHIFT, 1);
setPower(gate, clock | register_table->clock);
// Calculate frame buffer address.
value = 0;
fb_size = register_table->fb_width * register_table->height;
if (FIELD_GET(regRead32(CRT_DISPLAY_CTRL),
CRT_DISPLAY_CTRL,
PLANE) == CRT_DISPLAY_CTRL_PLANE_ENABLE)
{
value = FIELD_GET(regRead32(CRT_FB_ADDRESS),
CRT_FB_ADDRESS,
ADDRESS);
if (fb_size < value)
{
value = 0;
}
else
{
value += FIELD_GET(regRead32(CRT_FB_WIDTH),
CRT_FB_WIDTH,
OFFSET)
* (FIELD_GET(regRead32(CRT_VERTICAL_TOTAL),
CRT_VERTICAL_TOTAL,
DISPLAY_END) + 1);
}
}
// Program panel registers.
regWrite32(PANEL_FB_ADDRESS,
FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, PENDING) |
FIELD_SET(0, PANEL_FB_ADDRESS, EXT, LOCAL) |
FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, value) );
regWrite32(PANEL_FB_WIDTH,
FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH,
register_table->fb_width) |
FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET,
register_table->fb_width) );
regWrite32(PANEL_WINDOW_WIDTH,
FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH,
register_table->width) |
FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, 0) );
regWrite32(PANEL_WINDOW_HEIGHT,
FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT,
register_table->height) |
FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, Y, 0) );
regWrite32(PANEL_PLANE_TL,
FIELD_VALUE(0, PANEL_PLANE_TL, TOP, 0) |
FIELD_VALUE(0, PANEL_PLANE_TL, LEFT, 0) );
regWrite32(PANEL_PLANE_BR,
FIELD_VALUE(0, PANEL_PLANE_BR, BOTTOM,
register_table->height - 1) |
FIELD_VALUE(0, PANEL_PLANE_BR, RIGHT,
register_table->width - 1) );
regWrite32(PANEL_HORIZONTAL_TOTAL,
register_table->horizontal_total);
regWrite32(PANEL_HORIZONTAL_SYNC,
register_table->horizontal_sync);
regWrite32(PANEL_VERTICAL_TOTAL,
register_table->vertical_total);
regWrite32(PANEL_VERTICAL_SYNC,
register_table->vertical_sync);
// Program panel display control register.
value = regRead32(PANEL_DISPLAY_CTRL)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, FORMAT);
regWrite32(PANEL_DISPLAY_CTRL,
value | register_table->control);
// Palette RAM.
palette_ram = PANEL_PALETTE_RAM;
// Turn on panel.
panelPowerSequence(PANEL_ON, 4);
}
// Program CRT.
else
{
// Program clock, enable display controller.
gate = FIELD_SET(gate, CURRENT_POWER_GATE, DISPLAY, ENABLE);
clock &= FIELD_CLEAR(CURRENT_POWER_CLOCK, V2XCLK_SELECT)
& FIELD_CLEAR(CURRENT_POWER_CLOCK, V2XCLK_DIVIDER)
& FIELD_CLEAR(CURRENT_POWER_CLOCK, V2XCLK_SHIFT);
// Set engine clock to 72Mhz, memory clock to 144MHz
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_SELECT, 288); //MCLK=72MHz
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_DIVIDER, 1);
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, MCLK_SHIFT, 2);
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_SELECT, 288); //M2XCLK=144MHz
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_DIVIDER, 1);
clock = FIELD_SET(clock, CURRENT_POWER_CLOCK, M2XCLK_SHIFT, 1);
setPower(gate, clock | register_table->clock);
// Turn on DAC.
regWrite32(MISC_CTRL, FIELD_SET(regRead32(MISC_CTRL),
MISC_CTRL,
DAC_POWER,
ENABLE));
// Calculate frame buffer address.
value = 0;
fb_size = register_table->fb_width * register_table->height;
if (FIELD_GET(regRead32(PANEL_DISPLAY_CTRL),
PANEL_DISPLAY_CTRL,
PLANE) == PANEL_DISPLAY_CTRL_PLANE_ENABLE)
{
value = FIELD_GET(regRead32(PANEL_FB_ADDRESS),
PANEL_FB_ADDRESS,
ADDRESS);
if (fb_size < value)
{
value = 0;
}
else
{
value += FIELD_GET(regRead32(PANEL_FB_WIDTH),
PANEL_FB_WIDTH,
OFFSET)
* FIELD_GET(regRead32(PANEL_WINDOW_HEIGHT),
PANEL_WINDOW_HEIGHT,
HEIGHT);
}
}
// Program CRT registers.
regWrite32(CRT_FB_ADDRESS,
FIELD_SET(0, CRT_FB_ADDRESS, STATUS, PENDING) |
FIELD_SET(0, CRT_FB_ADDRESS, EXT, LOCAL) |
FIELD_VALUE(0, CRT_FB_ADDRESS, ADDRESS, value) );
regWrite32(CRT_FB_WIDTH,
FIELD_VALUE(0, CRT_FB_WIDTH, WIDTH,
register_table->fb_width) |
FIELD_VALUE(0, CRT_FB_WIDTH, OFFSET,
register_table->fb_width) );
regWrite32(CRT_HORIZONTAL_TOTAL,
register_table->horizontal_total);
regWrite32(CRT_HORIZONTAL_SYNC,
register_table->horizontal_sync);
regWrite32(CRT_VERTICAL_TOTAL,
register_table->vertical_total);
regWrite32(CRT_VERTICAL_SYNC,
register_table->vertical_sync);
// Program CRT display control register.
value = regRead32(CRT_DISPLAY_CTRL)
& FIELD_CLEAR(CRT_DISPLAY_CTRL, VSYNC_PHASE)
& FIELD_CLEAR(CRT_DISPLAY_CTRL, HSYNC_PHASE)
& FIELD_CLEAR(CRT_DISPLAY_CTRL, SELECT)
& FIELD_CLEAR(CRT_DISPLAY_CTRL, TIMING)
& FIELD_CLEAR(CRT_DISPLAY_CTRL, PLANE)
& FIELD_CLEAR(CRT_DISPLAY_CTRL, FORMAT);
regWrite32(CRT_DISPLAY_CTRL,
value | register_table->control);
// Palette RAM.
palette_ram = CRT_PALETTE_RAM;
// Turn on CRT.
setDPMS(DPMS_ON);
}
// In case of 8-bpp, fill palette.
if (FIELD_GET(register_table->control,
PANEL_DISPLAY_CTRL,
FORMAT) == PANEL_DISPLAY_CTRL_FORMAT_8)
{
// Start with RGB = 0,0,0.
unsigned char red = 0, green = 0, blue = 0;
unsigned long gray = 0;
for (offset = 0; offset < 256 * 4; offset += 4)
{
// Store current RGB value.
regWrite32(palette_ram + offset, gray
? RGB((gray + 50) / 100,
(gray + 50) / 100,
(gray + 50) / 100)
: RGB(red, green, blue));
if (gray)
{
// Walk through grays (40 in total).
gray += 654;
}
else
{
// Walk through colors (6 per base color).
if (blue != 255)
{
blue += 51;
}
else if (green != 255)
{
blue = 0;
green += 51;
}
else if (red != 255)
{
green = blue = 0;
red += 51;
}
else
{
gray = 1;
}
}
}
}
// For 16- and 32-bpp, fill palette with gamma values.
else
{
// Start with RGB = 0,0,0.
value = 0x000000;
for (offset = 0; offset < 256 * 4; offset += 4)
{
regWrite32(palette_ram + offset, value);
// Advance RGB by 1,1,1.
value += 0x010101;
}
}
}
void SetMode(unsigned long dst_width, unsigned long dst_height, unsigned long fMode, unsigned long nHertz, display_t display, int bpp)
{
mode_table_t mode;
pmode_table_t vesaMode;
reg_table_t register_table;
// Locate the mode
vesaMode = findMode(mode_table, dst_width, dst_height, nHertz);
if (vesaMode != NULL)
{
// Convert VESA timing into Voyager timing
adjustMode(vesaMode, &mode, display);
// Fill the register structure
setModeRegisters(®ister_table, &mode, display, bpp);
// Program the registers
programMode(®ister_table);
}
}
void panelSetMode(unsigned long dst_width, unsigned long dst_height, unsigned long fMode, unsigned long nHertz, int bpp)
{
SetMode(dst_width, dst_height, fMode, nHertz, PANEL, bpp);
}
void crtSetMode(unsigned long dst_width, unsigned long dst_height, unsigned long fMode, unsigned long nHertz, int bpp)
{
SetMode(dst_width, dst_height, fMode, nHertz, CRT, bpp);
}
static void smi_set_timing(struct smifb_info *sfb,struct par_info *hw)
{
panelSetMode(hw->width, hw->height, 0, hw->hz, sfb->fb.var.bits_per_pixel);
// Turn on CRT DAC. for simultanous display
regWrite32(MISC_CTRL, FIELD_SET(regRead32(MISC_CTRL), MISC_CTRL, DAC_POWER, ENABLE));
}
static void sm501_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
{
red >>= 8;
green >>= 8;
blue >>= 8;
regWrite32(PANEL_PALETTE_RAM+regno*4, red<<16 | green<<8 | blue);
regWrite32(CRT_PALETTE_RAM+regno*4, red<<16 | green<<8 | blue); //for dual display only
}
#ifdef CONFIG_FB_SM501_KERNEL_2_4_X
static void fbcon_SMI8_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width)
{
sx *= 8; dx *= 8; width *= 8;
deCopy(0, 0, 8,
dx, dy*fontheight(p), width, height*fontheight(p),
0, 0, sx, sy*fontheight(p), 0, 0xC);
}
static void fbcon_SMI8_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
unsigned char color;
color = attr_bgcol_ec(p,conp);
deFillRect(0, 0, sx*8, sy*fontheight(p), width*8, height*fontheight(p), color);
}
static void fbcon_SMI8_putc(struct vc_data *conp, struct display *p, int c, int yy,
int xx)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb8_putc(conp, p, c, yy, xx);
}
static void fbcon_SMI8_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
}
static void fbcon_SMI8_revc(struct display *p, int xx, int yy)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb8_revc(p, xx, yy);
}
static void fbcon_SMI8_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb8_clear_margins(conp, p, bottom_only);
}
static struct display_switch fbcon_SMI8 = {
setup: fbcon_cfb8_setup,
bmove: fbcon_SMI8_bmove,
clear: fbcon_SMI8_clear,
putc: fbcon_SMI8_putc,
putcs: fbcon_SMI8_putcs,
revc: fbcon_SMI8_revc,
clear_margins: fbcon_SMI8_clear_margins,
fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
static void fbcon_SMI16_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width)
{
sx *= 8; dx *= 8; width *= 8;
deCopy(0, 0, 16,
dx, dy*fontheight(p), width, height*fontheight(p),
0, 0, sx, sy*fontheight(p), 0, 0xC);
}
static void fbcon_SMI16_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
unsigned long color;
color = attr_bgcol_ec(p,conp);
deFillRect(0, 0, sx*8, sy*fontheight(p), width*8, height*fontheight(p), color);
}
static void fbcon_SMI16_putc(struct vc_data *conp, struct display *p, int c, int yy,
int xx)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb16_putc(conp, p, c, yy, xx);
}
static void fbcon_SMI16_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
}
static void fbcon_SMI16_revc(struct display *p, int xx, int yy)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -