astro display lights up

Change-Id: Iad71d3edf018981993152a48a37f9196655603ed
diff --git a/zircon/system/dev/board/astro/astro-display.c b/zircon/system/dev/board/astro/astro-display.c
index a668394..823ccf7 100644
--- a/zircon/system/dev/board/astro/astro-display.c
+++ b/zircon/system/dev/board/astro/astro-display.c
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <ddk/binding.h>
 #include <ddk/debug.h>
 #include <ddk/device.h>
 #include <ddk/platform-defs.h>
@@ -14,6 +15,7 @@
 #include <limits.h>
 
 #include "astro.h"
+#include "astro-gpios.h"
 
 static const pbus_mmio_t display_mmios[] = {
     {
@@ -59,21 +61,6 @@
     },
 };
 
-static const pbus_gpio_t display_gpios[] = {
-    {
-        // Backlight Enable
-        .gpio = S905D2_GPIOA(10),
-    },
-    {
-        // LCD Reset
-        .gpio = S905D2_GPIOH(6),
-    },
-    {
-        // Panel detection
-        .gpio = S905D2_GPIOH(5),
-    },
-};
-
 static const display_driver_t display_driver_info[] = {
     {
         .vid = PDEV_VID_AMLOGIC,
@@ -84,7 +71,7 @@
 
 static const pbus_metadata_t display_metadata[] = {
     {
-        .type = DEVICE_METADATA_PRIVATE,
+        .type = DEVICE_METADATA_DISPLAY_DEVICE,
         .data_buffer = &display_driver_info,
         .data_size = sizeof(display_driver_t),
     },
@@ -97,13 +84,6 @@
     },
 };
 
-static const pbus_i2c_channel_t display_i2c_channels[] = {
-    {
-        .bus_id = ASTRO_I2C_3,
-        .address = I2C_BACKLIGHT_ADDR,
-    },
-};
-
 static const pbus_mmio_t dsi_mmios[] = {
     {
         // DSI Host Controller
@@ -112,23 +92,20 @@
     },
 };
 
-static pbus_dev_t display_dev[] = {
-    {
-        .name = "display",
-        .mmio_list = display_mmios,
-        .mmio_count = countof(display_mmios),
-        .irq_list = display_irqs,
-        .irq_count = countof(display_irqs),
-        .gpio_list = display_gpios,
-        .gpio_count = countof(display_gpios),
-        .i2c_channel_list = display_i2c_channels,
-        .i2c_channel_count = countof(display_i2c_channels),
-        .bti_list = display_btis,
-        .bti_count = countof(display_btis),
-    },
+static const pbus_dev_t display_dev = {
+    .name = "display",
+    .vid = PDEV_VID_AMLOGIC,
+    .pid = PDEV_PID_AMLOGIC_S905D2,
+    .did = PDEV_DID_AMLOGIC_DISPLAY,
+    .mmio_list = display_mmios,
+    .mmio_count = countof(display_mmios),
+    .irq_list = display_irqs,
+    .irq_count = countof(display_irqs),
+    .bti_list = display_btis,
+    .bti_count = countof(display_btis),
 };
 
-static pbus_dev_t dsi_dev = {
+static const pbus_dev_t dsi_dev = {
     .name = "dw-dsi",
     .vid = PDEV_VID_GENERIC,
     .pid = PDEV_PID_GENERIC,
@@ -137,15 +114,72 @@
     .metadata_count = countof(display_metadata),
     .mmio_list = dsi_mmios,
     .mmio_count =countof(dsi_mmios),
-    .child_list = display_dev,
-    .child_count = countof(display_dev),
+};
+
+// Composite binding rules for display driver.
+static const zx_bind_inst_t root_match[] = {
+    BI_MATCH(),
+};
+static const zx_bind_inst_t dsi_match[]  = {
+    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_DSI_IMPL),
+    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
+    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_S905D2),
+    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_DISPLAY),
+};
+static const zx_bind_inst_t panel_gpio_match[] = {
+    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+    BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_PANEL_DETECT),
+};
+static const zx_bind_inst_t lcd_gpio_match[] = {
+    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+    BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_LCD_RESET),
+};
+static const zx_bind_inst_t sysmem_match[] = {
+    BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_SYSMEM),
+};
+static const zx_bind_inst_t canvas_match[] = {
+    BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_AMLOGIC_CANVAS),
+};
+static const device_component_part_t dsi_component[] = {
+    { countof(root_match), root_match },
+    { countof(dsi_match), dsi_match },
+};
+static const device_component_part_t panel_gpio_component[] = {
+    { countof(root_match), root_match },
+    { countof(panel_gpio_match), panel_gpio_match },
+};
+static const device_component_part_t lcd_gpio_component[] = {
+    { countof(root_match), root_match },
+    { countof(lcd_gpio_match), lcd_gpio_match },
+};
+static const device_component_part_t sysmem_component[] = {
+    { countof(root_match), root_match },
+    { countof(sysmem_match), sysmem_match },
+};
+static const device_component_part_t canvas_component[] = {
+    { countof(root_match), root_match },
+    { countof(canvas_match), canvas_match },
+};
+static const device_component_t components[] = {
+    { countof(dsi_component), dsi_component },
+    { countof(panel_gpio_component), panel_gpio_component },
+    { countof(lcd_gpio_component), lcd_gpio_component },
+    { countof(sysmem_component), sysmem_component },
+    { countof(canvas_component), canvas_component },
 };
 
 zx_status_t aml_display_init(aml_bus_t* bus) {
     zx_status_t status = pbus_device_add(&bus->pbus, &dsi_dev);
     if (status != ZX_OK) {
-        zxlogf(ERROR, "%s: Could not add display dev: %d\n", __FUNCTION__, status);
+        zxlogf(ERROR, "%s: Could not add dsi dev: %d\n", __FUNCTION__, status);
         return status;
     }
+
+    status = pbus_composite_device_add(&bus->pbus, &display_dev, components, countof(components), 1);
+    if (status != ZX_OK) {
+        zxlogf(ERROR, "%s: pbus_composite_device_add failed: %d\n", __FUNCTION__, status);
+        return status;
+    }
+
     return ZX_OK;
 }
diff --git a/zircon/system/dev/board/astro/astro-gpio.c b/zircon/system/dev/board/astro/astro-gpio.c
index 7372c50..d2c8327 100644
--- a/zircon/system/dev/board/astro/astro-gpio.c
+++ b/zircon/system/dev/board/astro/astro-gpio.c
@@ -15,6 +15,7 @@
 #include <limits.h>
 
 #include "astro.h"
+#include "astro-gpios.h"
 
 // uncomment to disable LED blinky test
 // #define GPIO_TEST 1
@@ -75,6 +76,9 @@
 static const gpio_pin_t gpio_pins[] = {
     // For wifi.
     { S905D2_WIFI_SDIO_WAKE_HOST },
+    // For display.
+    { GPIO_PANEL_DETECT },
+    { GPIO_LCD_RESET },
 };
 
 static const pbus_metadata_t gpio_metadata[] = {
diff --git a/zircon/system/dev/board/astro/astro-gpios.h b/zircon/system/dev/board/astro/astro-gpios.h
new file mode 100644
index 0000000..cb8a0dd
--- /dev/null
+++ b/zircon/system/dev/board/astro/astro-gpios.h
@@ -0,0 +1,11 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <soc/aml-s905d2/s905d2-gpio.h>
+
+#define GPIO_BACKLIGHT_ENABLE   S905D2_GPIOA(10)
+#define GPIO_LCD_RESET          S905D2_GPIOH(6)
+#define GPIO_PANEL_DETECT       S905D2_GPIOH(5)
diff --git a/zircon/system/dev/board/sherlock/sherlock-gpios.h b/zircon/system/dev/board/sherlock/sherlock-gpios.h
new file mode 100644
index 0000000..444eb05
--- /dev/null
+++ b/zircon/system/dev/board/sherlock/sherlock-gpios.h
@@ -0,0 +1,11 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <soc/aml-t931/t931-gpio.h>
+
+#define GPIO_BACKLIGHT_ENABLE   T931_GPIOA(10)
+#define GPIO_LCD_RESET          T931_GPIOH(6)
+#define GPIO_PANEL_DETECT       T931_GPIOH(0)
diff --git a/zircon/system/dev/display/aml-canvas/aml-canvas.c b/zircon/system/dev/display/aml-canvas/aml-canvas.c
index b77b6b5..3bb56a5 100644
--- a/zircon/system/dev/display/aml-canvas/aml-canvas.c
+++ b/zircon/system/dev/display/aml-canvas/aml-canvas.c
@@ -208,7 +208,8 @@
         .name = "aml-canvas",
         .ctx = canvas,
         .ops = &aml_canvas_device_protocol,
-        .flags = DEVICE_ADD_NON_BINDABLE,
+        .proto_id = ZX_PROTOCOL_AMLOGIC_CANVAS,
+        .proto_ops = &canvas_ops,
     };
 
     status = device_add(parent, &args, &canvas->zxdev);
diff --git a/zircon/system/dev/display/astro-display/BUILD.gn b/zircon/system/dev/display/astro-display/BUILD.gn
index f7fe53e..a7f5658 100644
--- a/zircon/system/dev/display/astro-display/BUILD.gn
+++ b/zircon/system/dev/display/astro-display/BUILD.gn
@@ -14,6 +14,7 @@
   ]
   deps = [
     "$zx/system/banjo/ddk-protocol-amlogiccanvas",
+    "$zx/system/banjo/ddk-protocol-composite",
     "$zx/system/banjo/ddk-protocol-display-controller",
     "$zx/system/banjo/ddk-protocol-dsiimpl",
     "$zx/system/banjo/ddk-protocol-gpio",
diff --git a/zircon/system/dev/display/astro-display/aml-dsi-host.cpp b/zircon/system/dev/display/astro-display/aml-dsi-host.cpp
index e6b0832..c1c2657 100644
--- a/zircon/system/dev/display/astro-display/aml-dsi-host.cpp
+++ b/zircon/system/dev/display/astro-display/aml-dsi-host.cpp
@@ -100,7 +100,7 @@
         DISP_ERROR("Could not create AmlMipiPhy object\n");
         return ZX_ERR_NO_MEMORY;
     }
-    zx_status_t status = phy_->Init(parent_, disp_setting.lane_num);
+    zx_status_t status = phy_->Init(pdev_dev_, dsi_dev_, disp_setting.lane_num);
     if (status != ZX_OK) {
         DISP_ERROR("MIPI PHY Init failed!\n");
         return status;
@@ -145,7 +145,7 @@
         return ZX_ERR_NO_MEMORY;
     }
 
-    status = lcd_->Init(parent_);
+    status = lcd_->Init(dsi_dev_, lcd_gpio_dev_);
     if (status != ZX_OK) {
         DISP_ERROR("Error during LCD Initialization! %d\n", status);
         return status;
@@ -170,13 +170,13 @@
         return ZX_OK;
     }
 
-    zx_status_t status = device_get_protocol(parent_, ZX_PROTOCOL_PDEV, &pdev_);
+    zx_status_t status = device_get_protocol(pdev_dev_, ZX_PROTOCOL_PDEV, &pdev_);
     if (status != ZX_OK) {
         DISP_ERROR("AmlDsiHost: Could not get ZX_PROTOCOL_PDEV protocol\n");
         return status;
     }
 
-    dsiimpl_ = parent_;
+    dsiimpl_ = dsi_dev_;
 
     // Map MIPI DSI and HHI registers
     mmio_buffer_t mmio;
diff --git a/zircon/system/dev/display/astro-display/aml-dsi-host.h b/zircon/system/dev/display/astro-display/aml-dsi-host.h
index c0cf5ea..88ee797 100644
--- a/zircon/system/dev/display/astro-display/aml-dsi-host.h
+++ b/zircon/system/dev/display/astro-display/aml-dsi-host.h
@@ -26,8 +26,10 @@
 
 class AmlDsiHost {
 public:
-    AmlDsiHost(zx_device_t* parent, uint32_t bitrate, uint8_t panel_type)
-        : parent_(parent), bitrate_(bitrate), panel_type_(panel_type) {}
+    AmlDsiHost(zx_device_t* pdev_dev, zx_device_t* dsi_dev, zx_device_t* lcd_gpio_dev,
+               uint32_t bitrate, uint8_t panel_type)
+        : pdev_dev_(pdev_dev), dsi_dev_(dsi_dev), lcd_gpio_dev_(lcd_gpio_dev), bitrate_(bitrate),
+          panel_type_(panel_type) {}
 
     // This function sets up mipi dsi interface. It includes both DWC and AmLogic blocks
     // The DesignWare setup could technically be moved to the dw_mipi_dsi driver. However,
@@ -52,7 +54,9 @@
 
     ddk::DsiImplProtocolClient dsiimpl_;
 
-    zx_device_t* parent_;
+    zx_device_t* pdev_dev_;
+    zx_device_t* dsi_dev_;
+    zx_device_t* lcd_gpio_dev_;
 
     uint32_t bitrate_;
     uint8_t panel_type_;
diff --git a/zircon/system/dev/display/astro-display/aml-mipi-phy.cpp b/zircon/system/dev/display/astro-display/aml-mipi-phy.cpp
index f63ce84..03f7b2d 100644
--- a/zircon/system/dev/display/astro-display/aml-mipi-phy.cpp
+++ b/zircon/system/dev/display/astro-display/aml-mipi-phy.cpp
@@ -211,20 +211,20 @@
     return ZX_OK;
 }
 
-zx_status_t AmlMipiPhy::Init(zx_device_t* parent, uint32_t lane_num) {
+zx_status_t AmlMipiPhy::Init(zx_device_t* pdev_dev, zx_device_t* dsi_dev, uint32_t lane_num) {
     if (initialized_) {
         return ZX_OK;
     }
 
     num_of_lanes_ = lane_num;
 
-    zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev_);
+    zx_status_t status = device_get_protocol(pdev_dev, ZX_PROTOCOL_PDEV, &pdev_);
     if (status != ZX_OK) {
         DISP_ERROR("AmlMipiPhy: Could not get ZX_PROTOCOL_PDEV protocol\n");
         return status;
     }
 
-    dsiimpl_ = parent;
+    dsiimpl_ = dsi_dev;
 
     // Map Mipi Dsi and Dsi Phy registers
     mmio_buffer_t mmio;
diff --git a/zircon/system/dev/display/astro-display/aml-mipi-phy.h b/zircon/system/dev/display/astro-display/aml-mipi-phy.h
index 793126c..91ec53f 100644
--- a/zircon/system/dev/display/astro-display/aml-mipi-phy.h
+++ b/zircon/system/dev/display/astro-display/aml-mipi-phy.h
@@ -23,7 +23,7 @@
 public:
     AmlMipiPhy() {}
     // This function initializes internal state of the object
-    zx_status_t Init(zx_device_t* parent, uint32_t lane_num);
+    zx_status_t Init(zx_device_t* pdev_dev, zx_device_t* dsi_dev, uint32_t lane_num);
     // This function enables and starts up the Mipi Phy
     zx_status_t Startup();
     // This function stops Mipi Phy
diff --git a/zircon/system/dev/display/astro-display/astro-display.cpp b/zircon/system/dev/display/astro-display/astro-display.cpp
index 4617917..94332ba 100644
--- a/zircon/system/dev/display/astro-display/astro-display.cpp
+++ b/zircon/system/dev/display/astro-display/astro-display.cpp
@@ -4,6 +4,8 @@
 #include "astro-display.h"
 #include <ddk/binding.h>
 #include <ddk/platform-defs.h>
+#include <ddk/protocol/composite.h>
+#include <fbl/algorithm.h>
 #include <fbl/auto_call.h>
 #include <fbl/vector.h>
 #include <fuchsia/sysmem/c/fidl.h>
@@ -12,6 +14,7 @@
 namespace astro_display {
 
 namespace {
+
 // List of supported pixel formats
 zx_pixel_format_t kSupportedPixelFormats[] = { ZX_PIXEL_FORMAT_RGB_x888 };
 
@@ -155,7 +158,7 @@
         if (!ac.check()) {
             return ZX_ERR_NO_MEMORY;
         }
-        status = vpu_->Init(parent_);
+        status = vpu_->Init(components_[COMPONENT_PDEV]);
         if (status != ZX_OK) {
             DISP_ERROR("Could not initialize VPU object\n");
             return status;
@@ -168,7 +171,7 @@
         if (!ac.check()) {
             return ZX_ERR_NO_MEMORY;
         }
-        status = clock_->Init(parent_);
+        status = clock_->Init(components_[COMPONENT_PDEV]);
         if (status != ZX_OK) {
             DISP_ERROR("Could not initialize Clock object\n");
             return status;
@@ -183,7 +186,9 @@
 
         // Program and Enable DSI Host Interface
         dsi_host_ = fbl::make_unique_checked<astro_display::AmlDsiHost>(&ac,
-                                                                        parent_,
+                                                                        components_[COMPONENT_PDEV],
+                                                                        components_[COMPONENT_DSI],
+                                                                        components_[COMPONENT_LCD_GPIO],
                                                                         clock_->GetBitrate(),
                                                                         panel_type_);
         if (!ac.check()) {
@@ -211,7 +216,7 @@
     }
 
     // Initialize osd object
-    status = osd_->Init(parent_);
+    status = osd_->Init(components_[COMPONENT_PDEV]);
     if (status != ZX_OK) {
         DISP_ERROR("Could not initialize OSD object\n");
         return status;
@@ -603,20 +608,36 @@
 
 // TODO(payamm): make sure unbind/release are called if we return error
 zx_status_t AstroDisplay::Bind() {
-    zx_status_t status;
+printf("AstroDisplay::Bind  1\n");
+    composite_protocol_t composite;
 
-    status = device_get_protocol(parent_, ZX_PROTOCOL_PDEV, &pdev_);
-    if (status !=  ZX_OK) {
-        DISP_ERROR("Could not get parent protocol\n");
+    auto status = device_get_protocol(parent_, ZX_PROTOCOL_COMPOSITE, &composite);
+    if (status != ZX_OK) {
+        DISP_ERROR("Could not get composite protocol\n");
         return status;
     }
 
-    // Make sure DSI IMPL is valid
-    if (!dsiimpl_.is_valid()) {
-        DISP_ERROR("DSI Protocol Not implemented\n");
-        return ZX_ERR_NO_RESOURCES;
+    size_t actual;
+    composite_get_components(&composite, components_, fbl::count_of(components_), &actual);
+    if (actual != fbl::count_of(components_)) {
+        DISP_ERROR("could not get components\n");
+        return ZX_ERR_NOT_SUPPORTED;
     }
 
+    status = device_get_protocol(components_[COMPONENT_PDEV], ZX_PROTOCOL_PDEV, &pdev_);
+    if (status !=  ZX_OK) {
+        DISP_ERROR("Could not get PDEV protocol\n");
+        return status;
+    }
+
+    dsi_impl_protocol_t dsi;
+    status = device_get_protocol(components_[COMPONENT_DSI], ZX_PROTOCOL_DSI_IMPL, &dsi);
+    if (status !=  ZX_OK) {
+        DISP_ERROR("Could not get DSI_IMPL protocol\n");
+        return status;
+    }
+    dsiimpl_ = &dsi;
+
     // Get board info
     status = pdev_get_board_info(&pdev_, &board_info_);
     if (status != ZX_OK) {
@@ -635,29 +656,20 @@
     }
 
     // Obtain GPIO Protocol for Panel reset
-    size_t actual;
-    status = pdev_get_protocol(&pdev_, ZX_PROTOCOL_GPIO, GPIO_PANEL_DETECT,
-                               &gpio_,
-                               sizeof(gpio_),
-                               &actual);
+    status = device_get_protocol(components_[COMPONENT_PANEL_GPIO], ZX_PROTOCOL_GPIO, &gpio_);
     if (status != ZX_OK) {
         DISP_ERROR("Could not obtain GPIO protocol.\n");
         return status;
     }
 
-    status = pdev_get_protocol(&pdev_, ZX_PROTOCOL_SYSMEM, 0,
-                               &sysmem_,
-                               sizeof(sysmem_),
-                               &actual);
+    status = device_get_protocol(components_[COMPONENT_SYSMEM], ZX_PROTOCOL_SYSMEM, &sysmem_);
     if (status != ZX_OK) {
         DISP_ERROR("Could not get Display SYSMEM protocol\n");
         return status;
     }
 
-    status = pdev_get_protocol(&pdev_, ZX_PROTOCOL_AMLOGIC_CANVAS, 0,
-                               &canvas_,
-                               sizeof(canvas_),
-                               &actual);
+    status = device_get_protocol(components_[COMPONENT_CANVAS], ZX_PROTOCOL_AMLOGIC_CANVAS,
+                                 &canvas_);
     if (status != ZX_OK) {
         DISP_ERROR("Could not obtain CANVAS protocol\n");
         return status;
@@ -698,6 +710,7 @@
         return status;
     }
 
+printf("AstroDisplay::Bind ZX_OK\n");
     cleanup.cancel();
     return ZX_OK;
 }
@@ -760,7 +773,8 @@
 
 } // namespace astro_display
 
-ZIRCON_DRIVER_BEGIN(astro_display, astro_display::astro_display_ops, "zircon", "0.1", 3)
+ZIRCON_DRIVER_BEGIN(astro_display, astro_display::astro_display_ops, "zircon", "0.1", 4)
+    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_COMPOSITE),
     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_S905D2),
     BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_DISPLAY),
diff --git a/zircon/system/dev/display/astro-display/astro-display.h b/zircon/system/dev/display/astro-display/astro-display.h
index cba5dcd..e6b82bc 100644
--- a/zircon/system/dev/display/astro-display/astro-display.h
+++ b/zircon/system/dev/display/astro-display/astro-display.h
@@ -50,7 +50,7 @@
                      public ddk::DisplayControllerImplProtocol<AstroDisplay, ddk::base_protocol> {
 public:
     AstroDisplay(zx_device_t* parent)
-        : DeviceType(parent), dsiimpl_(parent) {}
+        : DeviceType(parent) {}
 
     // This function is called from the c-bind function upon driver matching
     zx_status_t Bind();
@@ -85,6 +85,17 @@
     void Dump();
 
 private:
+    enum {
+        COMPONENT_PDEV,
+        COMPONENT_DSI,
+        COMPONENT_PANEL_GPIO,
+        COMPONENT_LCD_GPIO,
+        COMPONENT_SYSMEM,
+        COMPONENT_CANVAS,
+        COMPONENT_COUNT,
+    };
+    zx_device_t* components_[COMPONENT_COUNT];
+
     zx_status_t SetupDisplayInterface();
     int VSyncThread();
     void CopyDisplaySettings();
@@ -151,7 +162,7 @@
     ImportedImageBitmap imported_images_ TA_GUARDED(image_lock_);
 
     // DSIIMPL Protocol
-    ddk::DsiImplProtocolClient dsiimpl_;
+    ddk::DsiImplProtocolClient dsiimpl_ = {};
 
     // Objects
     fbl::unique_ptr<astro_display::Vpu> vpu_;
diff --git a/zircon/system/dev/display/astro-display/lcd.cpp b/zircon/system/dev/display/astro-display/lcd.cpp
index eee5d77..b443346 100644
--- a/zircon/system/dev/display/astro-display/lcd.cpp
+++ b/zircon/system/dev/display/astro-display/lcd.cpp
@@ -1249,22 +1249,14 @@
     return status;
 }
 
-zx_status_t Lcd::Init(zx_device_t* parent) {
+zx_status_t Lcd::Init(zx_device_t* dsi_dev, zx_device_t* gpio_dev) {
     if (initialized_) {
         return ZX_OK;
     }
-    pdev_protocol_t pdev;
-    zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev);
-    if (status != ZX_OK) {
-        DISP_ERROR("Could not obtain platform device protocol\n");
-        return status;
-    }
 
-    dsiimpl_ = parent;
+    dsiimpl_ = dsi_dev;
 
-    // Obtain GPIO protocol
-    size_t actual;
-    status = pdev_get_protocol(&pdev, ZX_PROTOCOL_GPIO, GPIO_LCD, &gpio_, sizeof(gpio_), &actual);
+    zx_status_t status = device_get_protocol(gpio_dev, ZX_PROTOCOL_GPIO, &gpio_);
     if (status != ZX_OK) {
         DISP_ERROR("Could not obtain GPIO protocol\n");
         return status;
diff --git a/zircon/system/dev/display/astro-display/lcd.h b/zircon/system/dev/display/astro-display/lcd.h
index f2090de..0e2f6ab 100644
--- a/zircon/system/dev/display/astro-display/lcd.h
+++ b/zircon/system/dev/display/astro-display/lcd.h
@@ -18,7 +18,7 @@
 public:
     Lcd(uint8_t panel_type) : panel_type_(panel_type) {}
 
-    zx_status_t Init(zx_device_t* parent);
+    zx_status_t Init(zx_device_t* dsi_dev, zx_device_t* gpio_dev);
     zx_status_t Enable();
     zx_status_t Disable();
 private:
diff --git a/zircon/system/dev/display/astro-display/vpu.h b/zircon/system/dev/display/astro-display/vpu.h
index 3168c3b..90ad234 100644
--- a/zircon/system/dev/display/astro-display/vpu.h
+++ b/zircon/system/dev/display/astro-display/vpu.h
@@ -38,7 +38,7 @@
     std::optional<ddk::MmioBuffer>    hhi_mmio_;
     std::optional<ddk::MmioBuffer>    aobus_mmio_;
     std::optional<ddk::MmioBuffer>    cbus_mmio_;
-    pdev_protocol_t        pdev_ = {};
+    pdev_protocol_t                   pdev_ = {};
 
     bool                              initialized_ = false;
 
diff --git a/zircon/system/dev/display/dsi-dw/dsi-dw.cpp b/zircon/system/dev/display/dsi-dw/dsi-dw.cpp
index 3cb6e8d..d031e11 100644
--- a/zircon/system/dev/display/dsi-dw/dsi-dw.cpp
+++ b/zircon/system/dev/display/dsi-dw/dsi-dw.cpp
@@ -853,7 +853,7 @@
     // Obtain display metadata needed to load the proper display driver
     display_driver_t display_info;
     size_t actual;
-    status = device_get_metadata(parent_, DEVICE_METADATA_PRIVATE,
+    status = device_get_metadata(parent_, DEVICE_METADATA_DISPLAY_DEVICE,
                                  &display_info,
                                  sizeof(display_driver_t),
                                  &actual);
@@ -868,17 +868,7 @@
         {BIND_PLATFORM_DEV_DID, 0, display_info.did},
     };
 
-    device_add_args_t args = {};
-    args.version = DEVICE_ADD_ARGS_VERSION;
-    args.name = "dw-dsi";
-    args.ctx = this;
-    args.ops = &ddk_device_proto_;
-    args.proto_id = ddk_proto_id_;
-    args.proto_ops = ddk_proto_ops_;
-    args.props = props;
-    args.prop_count = countof(props);
-
-    status = pdev_.DeviceAdd(0, &args, &zxdev_);
+    status = DdkAdd("dw-dsi", 0, props, countof(props));
     if (status != ZX_OK) {
         DSI_ERROR("could not add device %d\n", status);
     }
diff --git a/zircon/system/dev/sysmem/sysmem/device.cpp b/zircon/system/dev/sysmem/sysmem/device.cpp
index 11b1262..cc34e29 100644
--- a/zircon/system/dev/sysmem/sysmem/device.cpp
+++ b/zircon/system/dev/sysmem/sysmem/device.cpp
@@ -133,7 +133,7 @@
     // callback used is sysmem_device_ops.message, not
     // sysmem_protocol_ops.message.
     device_add_args.proto_id = ZX_PROTOCOL_SYSMEM;
-    device_add_args.proto_ops = &out_of_proc_sysmem_protocol_ops;
+    device_add_args.proto_ops = &in_proc_sysmem_protocol_ops;
     device_add_args.flags = DEVICE_ADD_INVISIBLE;
 
     status = device_add(parent_device_, &device_add_args, &device_);
diff --git a/zircon/system/ulib/ddk/include/ddk/metadata.h b/zircon/system/ulib/ddk/include/ddk/metadata.h
index 6729839..baf80c1 100644
--- a/zircon/system/ulib/ddk/include/ddk/metadata.h
+++ b/zircon/system/ulib/ddk/include/ddk/metadata.h
@@ -87,6 +87,9 @@
 // type: array of i2c_channel_t
 #define DEVICE_METADATA_I2C_CHANNELS              0x43433249 // I2CC
 
+// type: display_driver_t
+#define DEVICE_METADATA_DISPLAY_DEVICE            0x4C505344 // DSPL
+
 // Metadata types that have least significant byte set to lowercase 'd'
 // signify private driver data.
 // This allows creating metadata types to be defined local to a particular