[astro][display] Add a late init to the driver
Currently, we are skipping display initialization and depending on
u-boot. This change introduces a late init function that will be called
the first time apply_config is called.
Test: Tested on Astro hardware and pave was succesfully. Netbooting was
also successfull.
Change-Id: Iebdb15ef7dd6aa1b42121a75926a81582ff64ab2
diff --git a/system/dev/display/astro-display/astro-display.cpp b/system/dev/display/astro-display/astro-display.cpp
index 5068047..c3a49c0 100644
--- a/system/dev/display/astro-display/astro-display.cpp
+++ b/system/dev/display/astro-display/astro-display.cpp
@@ -81,6 +81,119 @@
args->cursor_info_count = 0;
}
+zx_status_t AstroDisplay::DisplayInit() {
+ zx_status_t status;
+ fbl::AllocChecker ac;
+ if (!skip_disp_init_) {
+ // Detect panel type
+ PopulatePanelType();
+
+ if (panel_type_ == PANEL_TV070WSM_FT) {
+ init_disp_table_ = &kDisplaySettingTV070WSM_FT;
+ } else if (panel_type_ == PANEL_P070ACB_FT) {
+ init_disp_table_ = &kDisplaySettingP070ACB_FT;
+ } else {
+ DISP_ERROR("Unsupported panel detected!\n");
+ status = ZX_ERR_NOT_SUPPORTED;
+ return status;
+ }
+
+ // Populated internal structures based on predefined tables
+ CopyDisplaySettings();
+
+ // Ensure Max Bit Rate / pixel clock ~= 8 (8.xxx). This is because the clock calculation
+ // part of code assumes a clock factor of 1. All the LCD tables from Astro have this
+ // relationship established. We'll have to revisit the calculation if this ratio cannot
+ // be met.
+ if (init_disp_table_->bit_rate_max / (init_disp_table_->lcd_clock / 1000 / 1000) != 8) {
+ DISP_ERROR("Max Bit Rate / pixel clock != 8\n");
+ status = ZX_ERR_INVALID_ARGS;
+ return status;
+ }
+
+ // Setup VPU and VPP units first
+ vpu_ = fbl::make_unique_checked<astro_display::Vpu>(&ac);
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
+ status = vpu_->Init(parent_);
+ if (status != ZX_OK) {
+ DISP_ERROR("Could not initialize VPU object\n");
+ return status;
+ }
+
+ vpu_->PowerOff();
+ vpu_->PowerOn();
+ vpu_->VppInit();
+
+ clock_ = fbl::make_unique_checked<astro_display::AstroDisplayClock>(&ac);
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
+ status = clock_->Init(parent_);
+ if (status != ZX_OK) {
+ DISP_ERROR("Could not initialize Clock object\n");
+ return status;
+ }
+
+ // Enable all display related clocks
+ status = clock_->Enable(disp_setting_);
+ if (status != ZX_OK) {
+ DISP_ERROR("Could not enable display clocks!\n");
+ return status;
+ }
+
+ // Program and Enable DSI Host Interface
+ dsi_host_ = fbl::make_unique_checked<astro_display::AmlDsiHost>(&ac,
+ parent_,
+ clock_->GetBitrate(),
+ panel_type_);
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
+ status = dsi_host_->Init();
+ if (status != ZX_OK) {
+ DISP_ERROR("Could not initialize DSI Host\n");
+ return status;
+ }
+
+ status = dsi_host_->HostOn(disp_setting_);
+ if (status != ZX_OK) {
+ DISP_ERROR("DSI Host On failed! %d\n", status);
+ return status;
+ }
+ }
+ osd_ = fbl::make_unique_checked<astro_display::Osd>(&ac,
+ width_,
+ height_,
+ disp_setting_.h_active,
+ disp_setting_.v_active);
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
+
+ // Initialize osd object
+ status = osd_->Init(parent_);
+ if (status != ZX_OK) {
+ DISP_ERROR("Could not initialize OSD object\n");
+ return status;
+ }
+
+ if (!skip_disp_init_) {
+ osd_->HwInit();
+ }
+
+ // Configure osd layer
+ current_image_valid_= false;
+ status = osd_->Configure();
+ if (status != ZX_OK) {
+ DISP_ERROR("OSD configuration failed!\n");
+ return status;
+ }
+
+ return ZX_OK;
+}
+
// part of ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL ops
uint32_t AstroDisplay::DisplayControllerImplComputeLinearStride(uint32_t width,
zx_pixel_format_t format) {
@@ -195,6 +308,15 @@
uint8_t addr;
if (display_count == 1 && display_configs[0]->layer_count) {
+ if (!full_init_done_) {
+ zx_status_t status;
+ if ((status = DisplayInit()) != ZX_OK) {
+ DISP_ERROR("Display Hardware Initialization failed! %d\n", status);
+ ZX_ASSERT(0);
+ }
+ full_init_done_ = true;
+ }
+
// Since Astro does not support plug'n play (fixed display), there is no way
// a checked configuration could be invalid at this point.
addr = (uint8_t) (uint64_t) display_configs[0]->layer_list[0]->cfg.primary.image.handle;
@@ -203,7 +325,9 @@
osd_->FlipOnVsync(addr);
} else {
current_image_valid_= false;
- osd_->Disable();
+ if (full_init_done_) {
+ osd_->Disable();
+ }
}
}
@@ -240,15 +364,12 @@
}
zx_status_t AstroDisplay::SetupDisplayInterface() {
- zx_status_t status;
fbl::AutoLock lock(&display_lock_);
// Figure out board rev and panel type for Astro only
if (board_info_.pid == PDEV_PID_ASTRO) {
- //TODO(payamm): set to true for now until we figure out bootloader to userspace handoff
- skip_disp_init_ = true;
panel_type_ = PANEL_UNKNOWN;
-
+ skip_disp_init_ = false;
if (board_info_.board_revision < BOARD_REV_EVT_1) {
DISP_INFO("Unsupported Board REV (%d). Will skip display driver initialization\n",
board_info_.board_revision);
@@ -258,121 +379,9 @@
skip_disp_init_ = true;
}
- if (!skip_disp_init_) {
- // Detect panel type
- PopulatePanelType();
-
- if (panel_type_ == PANEL_TV070WSM_FT) {
- init_disp_table_ = &kDisplaySettingTV070WSM_FT;
- } else if (panel_type_ == PANEL_P070ACB_FT) {
- init_disp_table_ = &kDisplaySettingP070ACB_FT;
- } else {
- DISP_ERROR("Unsupported panel detected!\n");
- status = ZX_ERR_NOT_SUPPORTED;
- return status;
- }
-
- // Populated internal structures based on predefined tables
- CopyDisplaySettings();
- }
-
format_ = ZX_PIXEL_FORMAT_RGB_x888;
stride_ = DisplayControllerImplComputeLinearStride(width_, format_);
- if (!skip_disp_init_) {
- // Ensure Max Bit Rate / pixel clock ~= 8 (8.xxx). This is because the clock calculation
- // part of code assumes a clock factor of 1. All the LCD tables from Astro have this
- // relationship established. We'll have to revisit the calculation if this ratio cannot
- // be met.
- if (init_disp_table_->bit_rate_max / (init_disp_table_->lcd_clock / 1000 / 1000) != 8) {
- DISP_ERROR("Max Bit Rate / pixel clock != 8\n");
- status = ZX_ERR_INVALID_ARGS;
- return status;
- }
-
- // Setup VPU and VPP units first
- fbl::AllocChecker ac;
- vpu_ = fbl::make_unique_checked<astro_display::Vpu>(&ac);
- if (!ac.check()) {
- return ZX_ERR_NO_MEMORY;
- }
- status = vpu_->Init(parent_);
- if (status != ZX_OK) {
- DISP_ERROR("Could not initialize VPU object\n");
- return status;
- }
- vpu_->PowerOff();
- vpu_->PowerOn();
- vpu_->VppInit();
-
- clock_ = fbl::make_unique_checked<astro_display::AstroDisplayClock>(&ac);
- if (!ac.check()) {
- return ZX_ERR_NO_MEMORY;
- }
- status = clock_->Init(parent_);
- if (status != ZX_OK) {
- DISP_ERROR("Could not initialize Clock object\n");
- return status;
- }
-
- // Enable all display related clocks
- status = clock_->Enable(disp_setting_);
- if (status != ZX_OK) {
- DISP_ERROR("Could not enable display clocks!\n");
- return status;
- }
-
- // Program and Enable DSI Host Interface
- dsi_host_ = fbl::make_unique_checked<astro_display::AmlDsiHost>(&ac,
- parent_,
- clock_->GetBitrate(),
- panel_type_);
- if (!ac.check()) {
- return ZX_ERR_NO_MEMORY;
- }
- status = dsi_host_->Init();
- if (status != ZX_OK) {
- DISP_ERROR("Could not initialize DSI Host\n");
- return status;
- }
-
- status = dsi_host_->HostOn(disp_setting_);
- if (status != ZX_OK) {
- DISP_ERROR("DSI Host On failed! %d\n", status);
- return status;
- }
- }
-
- /// OSD
- // Create internal osd object
- fbl::AllocChecker ac;
- osd_ = fbl::make_unique_checked<astro_display::Osd>(&ac,
- width_,
- height_,
- disp_setting_.h_active,
- disp_setting_.v_active);
- if (!ac.check()) {
- return ZX_ERR_NO_MEMORY;
- }
- // Initialize osd object
- status = osd_->Init(parent_);
- if (status != ZX_OK) {
- DISP_ERROR("Could not initialize OSD object\n");
- return status;
- }
-
- if (!skip_disp_init_) {
- osd_->HwInit();
- }
-
- // Configure osd layer
- current_image_valid_= false;
- status = osd_->Configure();
- if (status != ZX_OK) {
- DISP_ERROR("OSD configuration failed!\n");
- return status;
- }
-
{
// Reset imported_images_ bitmap
fbl::AutoLock lock(&image_lock_);
diff --git a/system/dev/display/astro-display/astro-display.h b/system/dev/display/astro-display/astro-display.h
index 017a828..effb486 100644
--- a/system/dev/display/astro-display/astro-display.h
+++ b/system/dev/display/astro-display/astro-display.h
@@ -79,6 +79,10 @@
void PopulateAddedDisplayArgs(added_display_args_t* args);
void PopulatePanelType() TA_REQ(display_lock_);
+ // This function enables the display hardware. This function is disruptive and causes
+ // unexpected pixels to be visible on the screen.
+ zx_status_t DisplayInit() TA_REQ(display_lock_);
+
// Zircon handles
zx::bti bti_;
zx::interrupt inth_;
@@ -119,6 +123,8 @@
// to set things up
bool skip_disp_init_ TA_GUARDED(display_lock_);
+ bool full_init_done_ = false;
+
// board revision and panel type detected by the display driver
uint8_t panel_type_ TA_GUARDED(display_lock_);