void display_init(void) { struct fbcon_config *fb_cfg; #if DISPLAY_TYPE_LCDC struct lcdc_timing_parameters *lcd_timing; mdp_clock_init(); if (board_machtype() == LINUX_MACHTYPE_8660_FLUID) { mmss_pixel_clock_configure(PIXEL_CLK_INDEX_25M); } else { mmss_pixel_clock_configure(PIXEL_CLK_INDEX_54M); } lcd_timing = get_lcd_timing(); fb_cfg = lcdc_init_set( lcd_timing ); fbcon_setup(fb_cfg); fbcon_clear(); panel_poweron(); #endif #if DISPLAY_TYPE_MIPI mdp_clock_init(); configure_dsicore_dsiclk(); configure_dsicore_byteclk(); configure_dsicore_pclk(); fb_cfg = mipi_init(); fbcon_setup(fb_cfg); #endif }
/** * Load images from EMMC */ static struct mdtp_fbimage* mdtp_read_mmc_image(uint32_t offset, uint32_t width, uint32_t height) { int index = INVALID_PTN; unsigned long long ptn = 0; struct mdtp_fbimage *logo = &g_mdtp_header; uint32_t block_size = mmc_get_device_blocksize(); index = partition_get_index("mdtp"); if (index == 0) { dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n"); return NULL; } ptn = partition_get_offset(index); if (ptn == 0) { dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n"); return NULL; } if (fb_config) { uint8_t *base = logo->image; unsigned bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE); if (mmc_read(ptn+offset, (void*)base, ROUNDUP(width*height*bytes_per_bpp, block_size))) { fbcon_clear(); dprintf(CRITICAL, "ERROR: mdtp image read failed\n"); return NULL; } logo->width = width; logo->height = height; } return logo; }
/** * Display error message and stop boot process. */ void display_error_msg() { fb_config = fbcon_display(); if (fb_config) { fbcon_clear(); display_error_message(); // No point in checking the return value here } // Invalid state. Nothing to be done but contacting the OEM. // Stop boot process. dprintf(CRITICAL,"ERROR: blocking boot process\n"); for(;;); }
void fbcon_setup(struct fbcon_config *_config) { uint32_t bg; uint32_t fg; ASSERT(_config); config = _config; switch (config->format) { case FB_FORMAT_RGB565: fg = RGB565_WHITE; bg = RGB565_BLACK; break; case FB_FORMAT_RGB888: fg = RGB888_WHITE; bg = RGB888_BLACK; break; default: dprintf(CRITICAL, "unknown framebuffer pixel format\n"); ASSERT(0); break; } #if DISPLAY_TYPE_TOUCHPAD fbcon_set_colors(0, 0, 0, 0, 0, 255); #else fbcon_set_colors(bg, fg); #endif cur_pos.x = 0; cur_pos.y = 0; #if DISPLAY_TYPE_TOUCHPAD max_pos.x = config->width - FONT_WIDTH; max_pos.y = config->height - FONT_HEIGHT; #else max_pos.x = config->width / (FONT_WIDTH+1); max_pos.y = (config->height - 1) / FONT_HEIGHT; #endif #if !DISPLAY_SPLASH_SCREEN fbcon_clear(); #endif }
/** * Display the basic layout of the screen (done only once). */ static void display_initial_screen(uint32_t pin_length) { if (g_initial_screen_displayed == true) return; fb_config = fbcon_display(); if (fb_config) { fbcon_clear(); if (display_error_message()) display_error_msg(); /* This will never return */ display_initial_delay(); mdelay(INITIAL_DELAY_MSECONDS); g_pin_frames_y_location = ((fb_config->height)*PIN_RELATIVE_Y_LOCATION); uint32_t total_pin_length = pin_length*MDTP_PIN_DIGIT_WIDTH + DIGIT_SPACE*(pin_length - 1); uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2; for (uint32_t i=0; i<pin_length; i++) { g_pin_frames_x_location[i] = complete_pin_centered + i*(DIGIT_SPACE+MDTP_PIN_DIGIT_WIDTH); } for (uint32_t i=0; i<pin_length; i++) { display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0); } display_ok_button(); g_initial_screen_displayed = true; } else { dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n"); display_error_msg(); /* This will never return */ } }
void display_image_on_screen(void) { unsigned i = 0; unsigned total_x = config->width; unsigned total_y = config->height; unsigned bytes_per_bpp = ((config->bpp) / 8); unsigned image_base = ((((total_y/2) - (SPLASH_IMAGE_WIDTH / 2) - 1) * (config->width)) + (total_x/2 - (SPLASH_IMAGE_HEIGHT / 2))); fbcon_clear(); #if DISPLAY_TYPE_MIPI if (bytes_per_bpp == 3) { for (i = 0; i < SPLASH_IMAGE_WIDTH; i++) { memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp), imageBuffer_rgb888 + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp), SPLASH_IMAGE_HEIGHT * bytes_per_bpp); } } fbcon_flush(); #if DISPLAY_MIPI_PANEL_NOVATEK_BLUE if(is_cmd_mode_enabled()) mipi_dsi_cmd_mode_trigger(); #endif #elif DISPLAY_TYPE_TOUCHPAD /* not supported yet */ return; #else if (bytes_per_bpp == 2) { for (i = 0; i < SPLASH_IMAGE_WIDTH; i++) { memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp), imageBuffer + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp), SPLASH_IMAGE_HEIGHT * bytes_per_bpp); } } fbcon_flush(); #endif }
void moboot_init(const struct app_descriptor *app) { int rv, keys_pressed; unsigned act; char *entries[10]; keys_pressed = 0; if (gpiokeys_poll(KEY_ALL)) { keys_pressed = 1; printf("\nPlease release key(s)...\n"); while (1) { thread_sleep(20); if (!gpiokeys_poll(KEY_ALL)) { break; } } } fbcon_clear(); fbcon_setpos(0,0); printf("welcome to moboot\n"); entries[0] = "Recover"; entries[1] = "Reboot"; entries[2] = "Shutdown"; act = moboot_menu(0, 2, entries, 0, 3, keys_pressed ? 0 : 9); fbcon_setpos(0, 2 + 3 + 2); /* y_start + num_entries + 2 */ if (act == 0) { reboot_device(RESTART_REASON_RECOVER); } else if (act == 1) { reboot_device(RESTART_REASON_REBOOT); } else if (act == 2) { reboot_device(RESTART_REASON_SHUTDOWN); } }
void display_clear(void) { fbcon_clear(); }
static void menu_renderer(int keycode) { int y = 1; unsigned i; int fh = pf2font_get_fontheight(); struct fbcon_config *config = fbcon_display(); // input handling if(!block_user) { // handle keypress if(keycode==KEY_RIGHT && menu_stack->entries[selection].execute) { menu_execute_entry(menu_stack->entries[selection].execute); return; } if(keycode==KEY_DOWN) { int first_visible = -1; int next_visible = -1; for(i=0; menu_stack->entries[i].name; i++) { if(!menu_stack->entries[i].hide || !menu_stack->entries[i].hide()) { if(first_visible==-1) first_visible = i; if(next_visible==-1 && i>selection) next_visible = i; } } if(next_visible!=-1) selection = next_visible; else selection=first_visible; } if(keycode==KEY_UP) { int last_visible = -1; int previous_visible = -1; for(i=0; menu_stack->entries[i].name; i++) { if(!menu_stack->entries[i].hide || !menu_stack->entries[i].hide()) { last_visible = i; if(i<selection) previous_visible = i; } } if(previous_visible!=-1) selection = previous_visible; else selection=last_visible; } } // clear fbcon_clear(); // title menu_set_color(NORMAL_TEXT_COLOR); pf2font_printf(0, fh*y++, "Fastboot Flash Mode (%s)", ABOOT_VERSION); // USB status if(usb_is_connected()) pf2font_printf(0, fh*y++, "Transfer Mode: USB Connected"); else pf2font_printf(0, fh*y++, "Connect USB Data Cable"); // device info char sn_buf[13]; target_serialno((unsigned char*)sn_buf); pf2font_printf(0, fh*y++, "CPU: %s Serial: %s", TARGET, sn_buf); #if WITH_DEV_PMIC_PM8921 // time unsigned long time; struct rtc_time tm; pm8xxx_rtc_read_time(&time); rtc_time_to_tm(time, &tm); pf2font_printf(0, fh*y++, "Time: %d-%02d-%02d %02d:%02d", tm.tm_year+1900, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min); #endif // divider 1 menu_set_color(DIVIDER_COLOR); menu_draw_divider(fh*y++ - pf2font_get_ascent()/2, 3); // draw interactive UI if(!block_user) { // menu header menu_set_color(NORMAL_TEXT_COLOR); pf2font_printf(0, fh*y++, "Boot Mode Selection Menu"); pf2font_printf(0, fh*y++, " Power Selects, Vol Up/Down Scrolls"); // menu entries for(i=0; menu_stack->entries[i].name; i++) { if(menu_stack->entries[i].hide && menu_stack->entries[i].hide()) continue; char* buf = NULL; if(menu_stack->entries[i].format) menu_stack->entries[i].format(&buf); else buf = strdup(menu_stack->entries[i].name); menu_draw_item(fh*y++, buf, selection==i); if(buf) free(buf); } // divider 2 menu_set_color(DIVIDER_COLOR); menu_draw_divider(fh*y++ - pf2font_get_ascent()/2, 3); } // draw log menu_set_color(LOG_COLOR_NORMAL); mutex_acquire(&logbuf_mutex); int log_top = y; int log_bottom = config->height/fh; int log_size = log_bottom-log_top; int start = (logbuf_row-log_size); for(i=(start>=0?start:0); i<=logbuf_row; i++) { pf2font_printf(0, fh*y++, logbuf[i]); } mutex_release(&logbuf_mutex); // flush fbcon_flush(); };