📄 sm501.c
字号:
// Get current power mode. control_value = FIELD_GET(regRead32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE); switch (control_value) { case POWER_MODE_CTRL_MODE_MODE0: // Switch from mode 0 to mode 1. gate_reg = POWER_MODE1_GATE; clock_reg = POWER_MODE1_CLOCK; control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE1); break; case POWER_MODE_CTRL_MODE_MODE1: case POWER_MODE_CTRL_MODE_SLEEP: // Switch from mode 1 or sleep to mode 0. gate_reg = POWER_MODE0_GATE; clock_reg = POWER_MODE0_CLOCK; control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE0); break; default: // Invalid mode return; } // Program new power mode. nGates = 0x2000f; regWrite32(gate_reg, nGates); regWrite32(clock_reg, Clock); regWrite32(POWER_MODE_CTRL, control_value); // When returning from sleep, wait until finished. while (FIELD_GET(regRead32(POWER_MODE_CTRL), POWER_MODE_CTRL, SLEEP_STATUS) == POWER_MODE_CTRL_SLEEP_STATUS_ACTIVE) ;}/********************************************************************** * * panelWaitVSync * * Purpose * Wait for the specified number of panel Vsyncs * * Parameters * [in] * vsync_count - Number of Vsyncs to wait * * [out] * None * * Returns * Nothing * **********************************************************************/static void panelWaitVSync(int vsync_count){ unsigned long status; unsigned long timeout; while (vsync_count-- > 0) { /* Wait for end of vsync */ timeout = 0; do { status = FIELD_GET(regRead32(CMD_INTPR_STATUS), CMD_INTPR_STATUS, PANEL_SYNC); if (++timeout == VSYNCTIMEOUT) break; } while (status == CMD_INTPR_STATUS_PANEL_SYNC_ACTIVE); /* Wait for start of vsync */ timeout = 0; do { status = FIELD_GET(regRead32(CMD_INTPR_STATUS), CMD_INTPR_STATUS, PANEL_SYNC); if (++timeout == VSYNCTIMEOUT) break; } while (status == CMD_INTPR_STATUS_PANEL_SYNC_INACTIVE); }}/********************************************************************** * * panelPowerSequence * * Purpose * Turn the panel On/Off * * Parameters * [in] * on_off - Turn panel On/Off. Can be: * PANEL_ON * PANEL_OFF * vsync_delay - Number of Vsyncs to wait after each signal is * turned on/off * * [out] * None * * Returns * Nothing * **********************************************************************/static void panelPowerSequence(panel_state_t on_off, int vsync_delay){ unsigned long panelControl = regRead32(PANEL_DISPLAY_CTRL); if (on_off == PANEL_ON) { // Turn on FPVDDEN. panelControl = FIELD_SET(panelControl, PANEL_DISPLAY_CTRL, FPVDDEN, HIGH); regWrite32(PANEL_DISPLAY_CTRL, panelControl); panelWaitVSync(vsync_delay); // Turn on FPDATA. panelControl = FIELD_SET(panelControl, PANEL_DISPLAY_CTRL, DATA, ENABLE); regWrite32(PANEL_DISPLAY_CTRL, panelControl); panelWaitVSync(vsync_delay); // Turn on FPVBIAS. panelControl = FIELD_SET(panelControl, PANEL_DISPLAY_CTRL, VBIASEN, HIGH); regWrite32(PANEL_DISPLAY_CTRL, panelControl); panelWaitVSync(vsync_delay); // Turn on FPEN. panelControl = FIELD_SET(panelControl, PANEL_DISPLAY_CTRL, FPEN, HIGH); regWrite32(PANEL_DISPLAY_CTRL, panelControl); } else { // Turn off FPEN. panelControl = FIELD_SET(panelControl, PANEL_DISPLAY_CTRL, FPEN, LOW); regWrite32(PANEL_DISPLAY_CTRL, panelControl); panelWaitVSync(vsync_delay); // Turn off FPVBIASEN. panelControl = FIELD_SET(panelControl, PANEL_DISPLAY_CTRL, VBIASEN, LOW); regWrite32(PANEL_DISPLAY_CTRL, panelControl); panelWaitVSync(vsync_delay); // Turn off FPDATA. panelControl = FIELD_SET(panelControl, PANEL_DISPLAY_CTRL, DATA, DISABLE); regWrite32(PANEL_DISPLAY_CTRL, panelControl); panelWaitVSync(vsync_delay); // Turn off FPVDDEN. panelControl = FIELD_SET(panelControl, PANEL_DISPLAY_CTRL, FPVDDEN, LOW); regWrite32(PANEL_DISPLAY_CTRL, panelControl); }}// Set DPMS state.void setDPMS(DPMS_t state){ unsigned long value; value = regRead32(SYSTEM_CTRL); switch (state) { case DPMS_ON: value = FIELD_SET(value, SYSTEM_CTRL, DPMS, VPHP); break; case DPMS_STANDBY: value = FIELD_SET(value, SYSTEM_CTRL, DPMS, VPHN); break; case DPMS_SUSPEND: value = FIELD_SET(value, SYSTEM_CTRL, DPMS, VNHP); break; case DPMS_OFF: value = FIELD_SET(value, SYSTEM_CTRL, DPMS, VNHN); break; } regWrite32(SYSTEM_CTRL, value);}/********************************************************************** * * panelOn * * Purpose * Turn the panel ON * * Parameters * [in] * nVSyncDelay - Number of Vsyncs to wait after each signal is * turned on * * [out] * None * * Returns * Nothing * **********************************************************************/void panelOn(unsigned long nVSyncDelay){ panelPowerSequence(PANEL_ON, nVSyncDelay);}// 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); 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); } } // need add? modify by kavin very important regWrite32(MISC_CTRL, FIELD_SET(0, MISC_CTRL, DAC_POWER, ENABLE) | FIELD_SET(0, MISC_CTRL, CRYSTAL, 12) | FIELD_SET(0, MISC_CTRL, HOST_BUS, XSCALE)); // 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); setPower(gate, clock | register_table->clock); // Turn on DAC. modify by kavin very important regWrite32(MISC_CTRL, FIELD_SET(0, MISC_CTRL, DAC_POWER, ENABLE) | FIELD_SET(0, MISC_CTRL, CRYSTAL, 12) | FIELD_SET(0, MISC_CTRL, HOST_BUS, XSCALE)); // 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, CURRENT) | FIELD_SET(0, CRT_FB_ADDRESS, EXT, LOCAL) | FIELD_SET(0, CRT_FB_ADDRESS, CS, 1) | 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -