[sherlock][camera] Add initial ISP driver support

- Re-write Camera Driver according to
  https://docs.google.com/document/d/113kjqX6IN8wyALSyzBBZtZFrt4g6F3Cdi0dCQtYDZIU/edit?usp=sharing
- Implement phase 2
- Add ISP protocol dummy driver
- Add ISP_IMPL protocol
- Remove Camera Sensor FIDL protocol
- Remove Camera test which are irrelevant now
- Remove IOCTLs

Test: "dm dump" shows all 3 drivers loaded

Change-Id: Ida8c38b93b8325f9190ff8175061bc9c91a236b3
diff --git a/system/banjo/ddk-protocol-isp/isp.banjo b/system/banjo/ddk-protocol-isp/isp.banjo
new file mode 100644
index 0000000..6d7e947
--- /dev/null
+++ b/system/banjo/ddk-protocol-isp/isp.banjo
@@ -0,0 +1,11 @@
+// Copyright 2018 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.
+
+library ddk.protocol.isp;
+using zx;
+
+[Layout = "ddk-protocol"]
+interface Isp {
+    DummyCall() -> ();
+};
diff --git a/system/fidl/fuchsia-hardware-camera/rules.mk b/system/banjo/ddk-protocol-isp/rules.mk
similarity index 61%
rename from system/fidl/fuchsia-hardware-camera/rules.mk
rename to system/banjo/ddk-protocol-isp/rules.mk
index 58e40e8..cf1ed9b 100644
--- a/system/fidl/fuchsia-hardware-camera/rules.mk
+++ b/system/banjo/ddk-protocol-isp/rules.mk
@@ -6,13 +6,14 @@
 
 MODULE := $(LOCAL_DIR)
 
-MODULE_TYPE := fidl
+MODULE_TYPE := banjo
 
-MODULE_PACKAGE := fidl
+MODULE_PACKAGE := banjo
 
-MODULE_FIDL_LIBRARY := fuchsia.hardware.camera
+MODULE_BANJO_LIBRARY := ddk.protocol.isp
 
-MODULE_SRCS += \
-    $(LOCAL_DIR)/camera_sensor.fidl \
+MODULE_BANJO_NAME := isp
+
+MODULE_SRCS += $(LOCAL_DIR)/isp.banjo
 
 include make/module.mk
diff --git a/system/banjo/ddk-protocol-ispimpl/isp-impl.banjo b/system/banjo/ddk-protocol-ispimpl/isp-impl.banjo
new file mode 100644
index 0000000..da82c7c
--- /dev/null
+++ b/system/banjo/ddk-protocol-ispimpl/isp-impl.banjo
@@ -0,0 +1,111 @@
+// Copyright 2018 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.
+
+library ddk.protocol.ispimpl;
+using zx;
+
+// This structure represents image resolution.
+struct ImageResolution {
+    uint32 width;
+    uint32 height;
+};
+
+// A sensor can support several different predefined modes.
+struct SensorMode {
+    // Frames per milliseconds. NOTE: (Reference code has fps * 256)
+    uint32 fpms;
+    // Resolution of the mode.
+    ImageResolution resolution;
+    // How many exposures this mode supports.
+    uint8 exposures;
+    // The wdr mode.
+    uint8 wdr_mode;
+    // Bit depth of data from sensor.
+    uint8 bits;
+    // Lane count.
+    uint8 lanes;
+    // MBps per lane.
+    uint32 mbps;
+    // The setting idx in seq.
+    uint8 idx;
+    // The setting bayer pattern
+    uint8 bayer;
+};
+
+struct SensorInfo {
+    // Total resolution of the image with blanking.
+    ImageResolution total;
+    // Active resolution without blanking.
+    ImageResolution active;
+    // Actual pixels per line after scaling/binning.
+    uint32 pixels_per_line;
+    // Maximum analog gain value in log2 format.
+    int32 again_log2_max;
+    // Maximum digital gain value in log2 format.
+    int32 dgain_log2_max;
+    // Precision of the gain - If required gain step
+    // is less then this do not try to allocate it.
+    int32 again_accuracy;
+    // Minimum integration time for the sensor in lines.
+    uint32 integration_time_min;
+    // Maximum integration time for the sensor in lines
+    // without dropping fps.
+    uint32 integration_time_max;
+    // Maximum integration time for long in lines.
+    uint32 integration_time_long_max;
+    // Maximum possible integration time for the sensor in lines.
+    uint32 integration_time_limit;
+    // Limit of integration time for non-flickering light source.
+    uint16 day_light_integration_time_max;
+    // Delay to apply integration time in frames.
+    uint8 integration_time_apply_delay;
+    // Select which WDR exposure channel gain
+    // is delayed 0-none, 1-long, 2-medium, 3-short
+    //  (only 0 and 1 implemented)
+    uint8 isp_exposure_channel_delay;
+    // Used for image stabilization.
+    int32 xoffset;
+    // Used for image stabilization.
+    int32 yoffset;
+    // Number of lines per second used for antiflicker.
+    uint32 lines_per_second;
+    // Number of different exposures supported by the sensor.
+    int32 sensor_exp_number;
+    // Current mode. This value is from the range [ 0 : countof(supported_modes) - 1 ].
+    uint8 mode;
+    // sensor setting bayer pattern.
+    uint8 bayer;
+};
+
+[Layout = "ddk-interface"]
+interface IspCallbacks {
+    // Initializes the Camera Sensor.
+    Init() -> (zx.status s);
+    // De-Initializes the Camera Sensor.
+    DeInit() -> ();
+    // Sets the Camera Sensor Mode to one of the supported modes.
+    SetMode(uint8 mode) -> (zx.status s);
+    // Start streaming from the camera sensor.
+    StartStreaming() -> ();
+    // Stop steaming.
+    StopStreaming() -> ();
+    // Change Analog Gain.
+    SetAnalogGain(int32 gain) -> (int32 gain);
+    // Change Digital Gain.
+    SetDigitalGain(int32 gain) -> (int32 gain);
+    // Set Integration Time.
+    SetIntegrationTime(int32 int_time, int32 int_time_M, int32 int_time_L) -> ();
+    // Update the sensor with new parameters.
+    Update() -> (zx.status s);
+    // Gets the Sensor Parameters.
+    GetInfo() -> (zx.status s, SensorInfo info);
+    // Get the supported modes.
+    // GetSupportedModes() ->()
+};
+
+[Layout = "ddk-protocol"]
+interface IspImpl {
+    RegisterCallbacks(IspCallbacks cb) -> (zx.status s);
+    DeRegisterCallbacks() -> (zx.status s);
+};
diff --git a/system/banjo/ddk-protocol-ispimpl/rules.mk b/system/banjo/ddk-protocol-ispimpl/rules.mk
new file mode 100644
index 0000000..772ac7c
--- /dev/null
+++ b/system/banjo/ddk-protocol-ispimpl/rules.mk
@@ -0,0 +1,19 @@
+# Copyright 2018 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.
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_TYPE := banjo
+
+MODULE_PACKAGE := banjo
+
+MODULE_BANJO_LIBRARY := ddk.protocol.ispimpl
+
+MODULE_BANJO_NAME := ispimpl
+
+MODULE_SRCS += $(LOCAL_DIR)/isp-impl.banjo
+
+include make/module.mk
diff --git a/system/banjo/ddk-protocol-mipicsi/mipicsi.banjo b/system/banjo/ddk-protocol-mipicsi/mipicsi.banjo
index 9f4e8da..33c5a2e 100644
--- a/system/banjo/ddk-protocol-mipicsi/mipicsi.banjo
+++ b/system/banjo/ddk-protocol-mipicsi/mipicsi.banjo
@@ -3,14 +3,9 @@
 // found in the LICENSE file.
 
 library ddk.protocol.mipicsi;
+using ddk.protocol.ispimpl;
 using zx;
 
-// This structure represents image resolution.
-struct ImageResolution {
-    uint32 width;
-    uint32 height;
-};
-
 struct MipiInfo {
     // Number of channels used.
     uint32 channel;
@@ -48,7 +43,7 @@
 };
 
 struct MipiAdapInfo {
-    ImageResolution resolution;
+    ddk.protocol.ispimpl.ImageResolution resolution;
     ImageFormat format;
     MipiModes mode;
     MipiPath path;
diff --git a/system/banjo/ddk-protocol-mipicsi/rules.mk b/system/banjo/ddk-protocol-mipicsi/rules.mk
index ba180f6..408e091 100644
--- a/system/banjo/ddk-protocol-mipicsi/rules.mk
+++ b/system/banjo/ddk-protocol-mipicsi/rules.mk
@@ -14,6 +14,8 @@
 
 MODULE_BANJO_NAME := mipicsi
 
+MODULE_BANJO_DEPS := system/banjo/ddk-protocol-ispimpl
+
 MODULE_SRCS += $(LOCAL_DIR)/mipicsi.banjo
 
 include make/module.mk
diff --git a/system/dev/board/sherlock/sherlock-camera.cpp b/system/dev/board/sherlock/sherlock-camera.cpp
index 9335848..0fb1639 100644
--- a/system/dev/board/sherlock/sherlock-camera.cpp
+++ b/system/dev/board/sherlock/sherlock-camera.cpp
@@ -67,6 +67,14 @@
     },
 };
 
+constexpr camera_sensor_t isp_mipi[] = {
+    {
+        .vid = PDEV_VID_AMLOGIC,
+        .pid = PDEV_PID_AMLOGIC_T931,
+        .did = PDEV_DID_AMLOGIC_MIPI,
+    },
+};
+
 constexpr camera_sensor_t mipi_sensor[] = {
     {
         .vid = PDEV_VID_SONY,
@@ -96,6 +104,14 @@
     },
 };
 
+constexpr pbus_metadata_t isp_metadata[] = {
+    {
+        .type = DEVICE_METADATA_PRIVATE,
+        .data_buffer = &isp_mipi,
+        .data_size = sizeof(isp_mipi),
+    },
+};
+
 constexpr pbus_i2c_channel_t sensor_i2c[] = {
     {
         .bus_id = SHERLOCK_I2C_3,
@@ -137,12 +153,10 @@
     return dev;
 }();
 
-static pbus_dev_t mipi_dev = []() {
+static const pbus_dev_t isp_children = []() {
+    // MIPI CSI PHY ADAPTER
     pbus_dev_t dev;
     dev.name = "mipi-csi2";
-    dev.vid = PDEV_VID_AMLOGIC;
-    dev.pid = PDEV_PID_AMLOGIC_T931;
-    dev.did = PDEV_DID_AMLOGIC_MIPI;
     dev.mmio_list = mipi_mmios;
     dev.mmio_count = countof(mipi_mmios);
     dev.metadata_list = mipi_metadata;
@@ -156,8 +170,31 @@
     return dev;
 }();
 
+static pbus_dev_t isp_dev = []() {
+    // ISP
+    pbus_dev_t dev;
+    dev.name = "isp";
+    dev.vid = PDEV_VID_ARM;
+    dev.pid = PDEV_PID_ISP;
+    dev.did = PDEV_DID_ARM_MALI_IV009;
+    dev.metadata_list = isp_metadata;
+    dev.metadata_count = countof(isp_metadata);
+    dev.child_list = &isp_children;
+    dev.child_count = 1;
+    return dev;
+}();
+
 } // namespace
 
+// Camera Board Driver loads the following three drivers
+// with parent -> child -> child relationship
+// ISP
+//  |
+//  |
+//  -> MIPI
+//      |
+//      |
+//      -> IMX227
 zx_status_t Sherlock::CameraInit() {
 
     // Set GPIO alternate functions.
@@ -166,7 +203,7 @@
     gpio_impl_.SetAltFunction(T931_GPIOA(14), kI2cSDAAltFunc);
     gpio_impl_.SetAltFunction(T931_GPIOA(15), kI2cSCLAltFunc);
 
-    zx_status_t status = pbus_.DeviceAdd(&mipi_dev);
+    zx_status_t status = pbus_.DeviceAdd(&isp_dev);
     if (status != ZX_OK) {
         zxlogf(ERROR, "%s: DeviceAdd failed %d\n", __func__, status);
         return status;
diff --git a/system/dev/camera/aml-mipicsi/aml-mipi.cpp b/system/dev/camera/aml-mipicsi/aml-mipi.cpp
index d912bf4..de8e185 100644
--- a/system/dev/camera/aml-mipicsi/aml-mipi.cpp
+++ b/system/dev/camera/aml-mipicsi/aml-mipi.cpp
@@ -11,6 +11,7 @@
 #include <fbl/auto_call.h>
 #include <fbl/unique_ptr.h>
 #include <hw/reg.h>
+#include <memory>
 #include <stdint.h>
 #include <threads.h>
 #include <zircon/types.h>
@@ -269,6 +270,24 @@
     delete this;
 }
 
+zx_status_t AmlMipiDevice::DdkGetProtocol(uint32_t proto_id, void* out_protocol) {
+    switch (proto_id) {
+    case ZX_PROTOCOL_ISP_IMPL: {
+        if (!parent_protocol_.is_valid()) {
+            return ZX_ERR_NOT_SUPPORTED;
+        }
+        parent_protocol_.GetProto(static_cast<isp_impl_protocol_t*>(out_protocol));
+        return ZX_OK;
+    }
+    case ZX_PROTOCOL_MIPI_CSI: {
+        self_protocol_.GetProto(static_cast<mipi_csi_protocol_t*>(out_protocol));
+        return ZX_OK;
+    }
+    default:
+        return ZX_ERR_NOT_SUPPORTED;
+    }
+}
+
 zx_status_t AmlMipiDevice::Bind(camera_sensor_t* sensor_info) {
 
     zx_device_prop_t props[] = {
@@ -293,7 +312,7 @@
 // static
 zx_status_t AmlMipiDevice::Create(zx_device_t* parent) {
     fbl::AllocChecker ac;
-    auto mipi_device = fbl::make_unique_checked<AmlMipiDevice>(&ac, parent);
+    auto mipi_device = std::unique_ptr<AmlMipiDevice>(new (&ac) AmlMipiDevice(parent));
     if (!ac.check()) {
         return ZX_ERR_NO_MEMORY;
     }
diff --git a/system/dev/camera/aml-mipicsi/aml-mipi.h b/system/dev/camera/aml-mipicsi/aml-mipi.h
index 5b3de64..36e7fbf 100644
--- a/system/dev/camera/aml-mipicsi/aml-mipi.h
+++ b/system/dev/camera/aml-mipicsi/aml-mipi.h
@@ -11,6 +11,7 @@
 #include <ddktl/device.h>
 #include <ddktl/mmio.h>
 #include <ddktl/pdev.h>
+#include <ddktl/protocol/ispimpl.h>
 #include <ddktl/protocol/mipicsi.h>
 #include <fbl/unique_ptr.h>
 
@@ -19,9 +20,12 @@
 #include <threads.h>
 
 namespace camera {
-
+// |AmlMipiDevice| is spawned by the driver in |aml-mipi.cpp|
+// to which the IMX 277 Sensor driver binds to.
+// This class provides the ZX_PROTOCOL_MIPICSI ops for all of it's
+// children.
 class AmlMipiDevice;
-using DeviceType = ddk::Device<AmlMipiDevice, ddk::Unbindable>;
+using DeviceType = ddk::Device<AmlMipiDevice, ddk::Unbindable, ddk::GetProtocolable>;
 
 class AmlMipiDevice : public DeviceType,
                       public ddk::MipiCsiProtocol<AmlMipiDevice, ddk::base_protocol> {
@@ -29,7 +33,10 @@
     DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AmlMipiDevice);
 
     explicit AmlMipiDevice(zx_device_t* parent)
-        : DeviceType(parent), pdev_(parent) {}
+        : DeviceType(parent), pdev_(parent), parent_protocol_(parent) {
+        mipi_csi_protocol_t self{&mipi_csi_protocol_ops_, this};
+        self_protocol_ = ddk::MipiCsiProtocolClient(&self);
+    }
 
     static zx_status_t Create(zx_device_t* parent);
 
@@ -38,6 +45,7 @@
     // Methods required by the ddk.
     void DdkRelease();
     void DdkUnbind();
+    zx_status_t DdkGetProtocol(uint32_t proto_id, void* out_protocol);
 
     // Methods for ZX_PROTOCOL_MIPI_CSI.
     zx_status_t MipiCsiInit(const mipi_info_t* mipi_info,
@@ -100,6 +108,8 @@
     std::optional<ddk::MmioBuffer> reset_mmio_;
 
     ddk::PDev pdev_;
+    ddk::MipiCsiProtocolClient self_protocol_;
+    ddk::IspImplProtocolClient parent_protocol_;
 
     zx::bti bti_;
     zx::interrupt adap_irq_;
diff --git a/system/dev/camera/aml-mipicsi/rules.mk b/system/dev/camera/aml-mipicsi/rules.mk
index f6485e5..3fb2590 100644
--- a/system/dev/camera/aml-mipicsi/rules.mk
+++ b/system/dev/camera/aml-mipicsi/rules.mk
@@ -37,6 +37,7 @@
     system/banjo/ddk-protocol-mipicsi \
     system/banjo/ddk-protocol-i2c \
     system/banjo/ddk-protocol-gpio \
+    system/banjo/ddk-protocol-ispimpl \
 
 include make/module.mk
 
diff --git a/system/dev/camera/arm-isp/arm-isp-impl.cpp b/system/dev/camera/arm-isp/arm-isp-impl.cpp
new file mode 100644
index 0000000..ee73a99
--- /dev/null
+++ b/system/dev/camera/arm-isp/arm-isp-impl.cpp
@@ -0,0 +1,160 @@
+// 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.
+
+#include "arm-isp-impl.h"
+#include "arm-isp.h"
+#include <ddk/binding.h>
+#include <ddk/debug.h>
+#include <ddk/metadata.h>
+#include <fbl/alloc_checker.h>
+#include <fbl/auto_call.h>
+#include <fbl/unique_ptr.h>
+#include <hw/reg.h>
+#include <memory>
+#include <stdint.h>
+#include <threads.h>
+#include <zircon/types.h>
+
+namespace camera {
+
+zx_status_t ArmISPImplDevice::InitPdev(zx_device_t* parent) {
+    // TODO(braval): Implement this.
+    return ZX_OK;
+}
+
+void ArmISPImplDevice::DdkUnbind() {
+    ShutDown();
+    DdkRemove();
+}
+
+void ArmISPImplDevice::DdkRelease() {
+    delete this;
+}
+
+void ArmISPImplDevice::ShutDown() {
+}
+
+zx_status_t ArmISPImplDevice::IspImplRegisterCallbacks(const isp_callbacks_t* cbs) {
+    if (cbs == nullptr) {
+        return ZX_ERR_INVALID_ARGS;
+    }
+
+    cbs_ = *cbs;
+
+    sync_completion_signal(&cb_registered_signal_);
+    return ZX_OK;
+}
+
+zx_status_t ArmISPImplDevice::IspImplDeRegisterCallbacks() {
+    return ZX_ERR_NOT_SUPPORTED;
+}
+
+zx_status_t ArmISPImplDevice::Bind(mipi_adapter_t* mipi_info) {
+
+    zx_device_prop_t props[] = {
+        {BIND_PLATFORM_DEV_VID, 0, mipi_info->vid},
+        {BIND_PLATFORM_DEV_PID, 0, mipi_info->pid},
+        {BIND_PLATFORM_DEV_DID, 0, mipi_info->did},
+    };
+
+    device_add_args_t args = {};
+    args.version = DEVICE_ADD_ARGS_VERSION;
+    args.name = "arm-isp";
+    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);
+
+    return pdev_.DeviceAdd(0, &args, &zxdev_);
+}
+
+int ArmISPImplDevice::WorkerThread() {
+    // Note: Need to wait here for all sensors to register
+    //       their callbacks before proceeding further.
+    //       Currently only supporting single sensor, we can add
+    //       support for multiple sensors easily when needed.
+    sync_completion_wait(&cb_registered_signal_, ZX_TIME_INFINITE);
+
+    return camera::ArmIspDevice::Create(parent_);
+}
+
+// static
+zx_status_t ArmISPImplDevice::Create(zx_device_t* parent) {
+    fbl::AllocChecker ac;
+    auto isp_impl_device = std::unique_ptr<ArmISPImplDevice>(new (&ac) ArmISPImplDevice(parent));
+    if (!ac.check()) {
+        return ZX_ERR_NO_MEMORY;
+    }
+
+    zx_status_t status = isp_impl_device->InitPdev(parent);
+    if (status != ZX_OK) {
+        return status;
+    }
+
+    isp_impl_device->parent_ = parent;
+
+    // Populate mipi specific information
+    mipi_adapter_t mipi_info;
+    size_t actual;
+    status = device_get_metadata(parent, DEVICE_METADATA_PRIVATE,
+                                 &mipi_info,
+                                 sizeof(mipi_adapter_t),
+                                 &actual);
+    if (status != ZX_OK || actual != sizeof(mipi_adapter_t)) {
+        zxlogf(ERROR, "arm-isp: Could not get Mipi Info metadata %d\n", status);
+        return status;
+    }
+
+    sync_completion_reset(&isp_impl_device->cb_registered_signal_);
+    auto cleanup = fbl::MakeAutoCall([&]() { isp_impl_device->ShutDown(); });
+
+    status = isp_impl_device->Bind(&mipi_info);
+    if (status != ZX_OK) {
+        zxlogf(ERROR, "arm-isp-impl driver failed to get added\n");
+        return status;
+    } else {
+        zxlogf(INFO, "arm-isp-impl driver added\n");
+    }
+
+    auto worker_thunk = [](void* arg) -> int {
+        return reinterpret_cast<ArmISPImplDevice*>(arg)->WorkerThread();
+    };
+
+    int ret = thrd_create_with_name(&isp_impl_device->worker_thread_, worker_thunk,
+                                    reinterpret_cast<void*>(isp_impl_device.get()),
+                                    "ispimpl-worker-thread");
+    ZX_DEBUG_ASSERT(ret == thrd_success);
+
+    cleanup.cancel();
+
+    // isp_impl_device intentionally leaked as it is now held by DevMgr.
+    __UNUSED auto ptr = isp_impl_device.release();
+
+    return status;
+}
+
+ArmISPImplDevice::~ArmISPImplDevice() {
+}
+
+zx_status_t isp_bind(void* ctx, zx_device_t* device) {
+    return camera::ArmISPImplDevice::Create(device);
+}
+
+static zx_driver_ops_t driver_ops = []() {
+    zx_driver_ops_t ops;
+    ops.version = DRIVER_OPS_VERSION;
+    ops.bind = isp_bind;
+    return ops;
+}();
+
+} // namespace camera
+
+// clang-format off
+ZIRCON_DRIVER_BEGIN(arm_isp, camera::driver_ops, "arm-isp", "0.1", 3)
+    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_ARM),
+    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_ISP),
+    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_ARM_MALI_IV009),
+ZIRCON_DRIVER_END(arm_isp)
diff --git a/system/dev/camera/arm-isp/arm-isp-impl.h b/system/dev/camera/arm-isp/arm-isp-impl.h
new file mode 100644
index 0000000..3f266bc
--- /dev/null
+++ b/system/dev/camera/arm-isp/arm-isp-impl.h
@@ -0,0 +1,63 @@
+// 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.
+
+#include <atomic>
+#include <ddk/metadata/camera.h>
+#include <ddk/platform-defs.h>
+#include <ddk/protocol/platform-device-lib.h>
+#include <ddk/protocol/platform/bus.h>
+#include <ddk/protocol/platform/device.h>
+#include <ddktl/device.h>
+#include <ddktl/pdev.h>
+#include <ddktl/protocol/ispimpl.h>
+#include <fbl/unique_ptr.h>
+#include <threads.h>
+
+namespace camera {
+
+// |ArmISPImplDevice| is spawned by the driver in |arm-isp-impl.cpp|
+// to which the MIPI CSI driver binds to.
+// This class provides the ZX_PROTOCOL_ISP_IMPL ops for all of it's
+// children.
+class ArmISPImplDevice;
+using DeviceType = ddk::Device<ArmISPImplDevice, ddk::Unbindable>;
+
+class ArmISPImplDevice : public DeviceType,
+                         public ddk::IspImplProtocol<ArmISPImplDevice, ddk::base_protocol> {
+public:
+    DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ArmISPImplDevice);
+
+    explicit ArmISPImplDevice(zx_device_t* parent)
+        : DeviceType(parent), pdev_(parent) {}
+
+    static zx_status_t Create(zx_device_t* parent);
+
+    ~ArmISPImplDevice();
+
+    // Methods required by the ddk.
+    void DdkRelease();
+    void DdkUnbind();
+
+    // ZX_PROTOCOL_ISP_IMPL ops.
+    zx_status_t IspImplRegisterCallbacks(const isp_callbacks_t* cb);
+    zx_status_t IspImplDeRegisterCallbacks();
+
+private:
+    zx_status_t InitPdev(zx_device_t* parent);
+    zx_status_t Bind(mipi_adapter_t* mipi_info);
+    void ShutDown();
+    int WorkerThread();
+
+    ddk::PDev pdev_;
+
+    thrd_t worker_thread_;
+
+    isp_callbacks_t cbs_;
+
+    sync_completion_t cb_registered_signal_;
+
+    zx_device_t* parent_;
+};
+
+} // namespace camera
diff --git a/system/dev/camera/arm-isp/arm-isp.cpp b/system/dev/camera/arm-isp/arm-isp.cpp
new file mode 100644
index 0000000..bb332ed
--- /dev/null
+++ b/system/dev/camera/arm-isp/arm-isp.cpp
@@ -0,0 +1,58 @@
+// 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.
+
+#include "arm-isp.h"
+#include <ddk/binding.h>
+#include <ddk/debug.h>
+#include <ddk/metadata.h>
+#include <fbl/alloc_checker.h>
+#include <fbl/auto_call.h>
+#include <fbl/unique_ptr.h>
+#include <hw/reg.h>
+#include <memory>
+#include <stdlib.h>
+#include <threads.h>
+#include <unistd.h>
+#include <zircon/types.h>
+
+namespace camera {
+
+// static
+zx_status_t ArmIspDevice::Create(zx_device_t* parent) {
+    fbl::AllocChecker ac;
+    auto isp_device = std::unique_ptr<ArmIspDevice>(new (&ac) ArmIspDevice(parent));
+    if (!ac.check()) {
+        return ZX_ERR_NO_MEMORY;
+    }
+
+    zx_status_t status = isp_device->DdkAdd("arm-isp");
+    if (status != ZX_OK) {
+        zxlogf(ERROR, "arm-isp: Could not create arm-isp device: %d\n", status);
+        return status;
+    } else {
+        zxlogf(INFO, "arm-isp: Added arm-isp device\n");
+    }
+
+    // isp_device intentionally leaked as it is now held by DevMgr.
+    __UNUSED auto ptr = isp_device.release();
+
+    return status;
+}
+
+ArmIspDevice::~ArmIspDevice() {
+}
+
+void ArmIspDevice::DdkUnbind() {
+    ShutDown();
+    DdkRemove();
+}
+
+void ArmIspDevice::DdkRelease() {
+    delete this;
+}
+
+void ArmIspDevice::ShutDown() {
+}
+
+} // namespace camera
diff --git a/system/dev/camera/arm-isp/arm-isp.h b/system/dev/camera/arm-isp/arm-isp.h
new file mode 100644
index 0000000..9e3f6be
--- /dev/null
+++ b/system/dev/camera/arm-isp/arm-isp.h
@@ -0,0 +1,50 @@
+// 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.
+
+#include <atomic>
+#include <ddk/metadata/camera.h>
+#include <ddk/platform-defs.h>
+#include <ddk/protocol/platform-device-lib.h>
+#include <ddk/protocol/platform/bus.h>
+#include <ddk/protocol/platform/device.h>
+#include <ddktl/device.h>
+#include <ddktl/pdev.h>
+#include <ddktl/protocol/ispimpl.h>
+#include <ddktl/protocol/isp.h>
+#include <fbl/unique_ptr.h>
+#include <threads.h>
+
+namespace camera {
+// |ArmIspDevice| is spawned by the driver in |arm-isp.cpp|
+// This class provides the ZX_PROTOCOL_ISP ops for all of it's
+// children. This is TBD as to which protocol it will provide.
+// Most likely its the ZX_PROTOCOL_CAMERA once we move it from
+// Garnet to Zircon.
+class ArmIspDevice;
+using IspDeviceType = ddk::Device<ArmIspDevice, ddk::Unbindable>;
+
+class ArmIspDevice : public IspDeviceType,
+                     public ddk::IspProtocol<ArmIspDevice, ddk::base_protocol> {
+public:
+    DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ArmIspDevice);
+
+    explicit ArmIspDevice(zx_device_t* parent)
+        : IspDeviceType(parent) {}
+
+    ~ArmIspDevice();
+
+    static zx_status_t Create(zx_device_t* parent);
+
+    // Methods required by the ddk.
+    void DdkRelease();
+    void DdkUnbind();
+
+    // ZX_PROTOCOL_ISP ops.
+    void IspDummyCall() {};
+
+private:
+    void ShutDown();
+};
+
+} // namespace camera
diff --git a/system/dev/camera/arm-isp/rules.mk b/system/dev/camera/arm-isp/rules.mk
new file mode 100644
index 0000000..2cc0206
--- /dev/null
+++ b/system/dev/camera/arm-isp/rules.mk
@@ -0,0 +1,43 @@
+# Copyright 2018 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.
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_TYPE := driver
+
+MODULE_SRCS := \
+    $(LOCAL_DIR)/arm-isp.cpp \
+    $(LOCAL_DIR)/arm-isp-impl.cpp \
+
+MODULE_HEADER_DEPS := \
+    system/dev/lib/amlogic
+
+MODULE_STATIC_LIBS := \
+    system/ulib/ddk \
+    system/ulib/ddktl \
+    system/ulib/fbl \
+    system/ulib/fzl \
+    system/ulib/sync \
+    system/ulib/zx \
+    system/ulib/zxcpp \
+
+MODULE_LIBS := \
+    system/ulib/driver \
+    system/ulib/zircon \
+    system/ulib/c
+
+MODULE_BANJO_LIBS := \
+    system/banjo/ddk-protocol-clk \
+    system/banjo/ddk-protocol-platform-bus \
+    system/banjo/ddk-protocol-platform-device \
+    system/banjo/ddk-protocol-mipicsi \
+    system/banjo/ddk-protocol-i2c \
+    system/banjo/ddk-protocol-gpio \
+    system/banjo/ddk-protocol-ispimpl \
+    system/banjo/ddk-protocol-isp \
+
+include make/module.mk
+
diff --git a/system/dev/camera/imx227/imx227-seq.h b/system/dev/camera/imx227/imx227-seq.h
index 1392d91..81480ff 100644
--- a/system/dev/camera/imx227/imx227-seq.h
+++ b/system/dev/camera/imx227/imx227-seq.h
@@ -588,7 +588,7 @@
     setting_2400_2720_2lane_1g_28fps,
 };
 
-constexpr fuchsia_hardware_camera_SensorMode supported_modes[] = {
+constexpr sensor_mode_t supported_modes[] = {
     {
         // NOTE: SW reference consumes this as (30fps * 256)
         //       We are representing this as fpms.
diff --git a/system/dev/camera/imx227/imx227.cpp b/system/dev/camera/imx227/imx227.cpp
index 2c3aee1..7bdb03d 100644
--- a/system/dev/camera/imx227/imx227.cpp
+++ b/system/dev/camera/imx227/imx227.cpp
@@ -14,9 +14,9 @@
 #include <fbl/auto_lock.h>
 #include <fbl/unique_ptr.h>
 #include <hw/reg.h>
+#include <memory>
 #include <stdint.h>
 #include <threads.h>
-#include <zircon/device/camera.h>
 #include <zircon/types.h>
 
 namespace camera {
@@ -64,6 +64,11 @@
         return ZX_ERR_NO_RESOURCES;
     }
 
+    // IspImpl for registering callbacks.
+    if (!ispimpl_.is_valid()) {
+        return ZX_ERR_NO_RESOURCES;
+    }
+
     return ZX_OK;
 }
 
@@ -180,7 +185,7 @@
     mipi_.DeInit();
 }
 
-zx_status_t Imx227Device::GetInfo(fuchsia_hardware_camera_SensorInfo* out_info) {
+zx_status_t Imx227Device::GetInfo(sensor_info_t* out_info) {
     return ZX_ERR_NOT_SUPPORTED;
 }
 
@@ -284,102 +289,13 @@
                                       int32_t int_time_L) {
 }
 
-void Imx227Device::Update() {
-}
-
-zx_status_t Imx227Device::DdkIoctl(uint32_t op, const void* in_buf, size_t in_len,
-                                   void* out_buf, size_t out_len, size_t* out_actual) {
-    switch (op) {
-    case CAMERA_IOCTL_GET_SUPPORTED_MODES: {
-        if (out_len < sizeof(fuchsia_hardware_camera_SensorMode) * MAX_SUPPORTED_MODES) {
-            return ZX_ERR_BUFFER_TOO_SMALL;
-        }
-        memcpy(out_buf, &supported_modes, sizeof(supported_modes));
-        *out_actual = sizeof(supported_modes);
-        return ZX_OK;
-    }
-
-    default:
-        return ZX_ERR_NOT_SUPPORTED;
-    }
-}
-
-static zx_status_t Init(void* ctx, fidl_txn_t* txn) {
-    auto& self = *static_cast<Imx227Device*>(ctx);
-    zx_status_t status = self.Init();
-    return fuchsia_hardware_camera_CameraSensorInit_reply(txn, status);
-}
-
-static zx_status_t DeInit(void* ctx) {
-    auto& self = *static_cast<Imx227Device*>(ctx);
-    self.DeInit();
-    return ZX_OK;
-}
-
-static zx_status_t SetMode(void* ctx, uint8_t mode, fidl_txn_t* txn) {
-    auto& self = *static_cast<Imx227Device*>(ctx);
-    zx_status_t status = self.SetMode(mode);
-    return fuchsia_hardware_camera_CameraSensorSetMode_reply(txn, status);
-}
-
-static zx_status_t StartStreaming(void* ctx) {
-    auto& self = *static_cast<Imx227Device*>(ctx);
-    self.StartStreaming();
-    return ZX_OK;
-}
-
-static zx_status_t StopStreaming(void* ctx) {
-    auto& self = *static_cast<Imx227Device*>(ctx);
-    self.StopStreaming();
-    return ZX_OK;
-}
-
-static zx_status_t SetAnalogGain(void* ctx, int32_t gain, fidl_txn_t* txn) {
-    auto& self = *static_cast<Imx227Device*>(ctx);
-    int32_t actual_gain = self.SetAnalogGain(gain);
-    return fuchsia_hardware_camera_CameraSensorSetAnalogGain_reply(txn, actual_gain);
-}
-
-static zx_status_t SetDigitalGain(void* ctx, int32_t gain, fidl_txn_t* txn) {
-    auto& self = *static_cast<Imx227Device*>(ctx);
-    int32_t actual_gain = self.SetDigitalGain(gain);
-    return fuchsia_hardware_camera_CameraSensorSetDigitalGain_reply(txn, actual_gain);
-}
-
-static zx_status_t SetIntegrationTime(void* ctx,
-                                      int32_t int_time,
-                                      int32_t int_time_M,
-                                      int32_t int_time_L) {
-    auto& self = *static_cast<Imx227Device*>(ctx);
-    self.SetIntegrationTime(int_time, int_time_M, int_time_L);
-    return ZX_OK;
-}
-
-static zx_status_t Update(void* ctx) {
-    auto& self = *static_cast<Imx227Device*>(ctx);
-    self.Update();
-    return ZX_OK;
-}
-
-fuchsia_hardware_camera_CameraSensor_ops_t fidl_ops = {
-    .Init = Init,
-    .DeInit = DeInit,
-    .SetMode = SetMode,
-    .StartStreaming = StartStreaming,
-    .StopStreaming = StopStreaming,
-    .SetAnalogGain = SetAnalogGain,
-    .SetDigitalGain = SetDigitalGain,
-    .SetIntegrationTime = SetIntegrationTime,
-    .Update = Update,
-};
-
-zx_status_t Imx227Device::DdkMessage(fidl_msg_t* msg, fidl_txn_t* txn) {
-    return fuchsia_hardware_camera_CameraSensor_dispatch(this, txn, msg, &fidl_ops);
+zx_status_t Imx227Device::Update() {
+    return ZX_ERR_NOT_SUPPORTED;
 }
 
 zx_status_t Imx227Device::Create(zx_device_t* parent) {
     fbl::AllocChecker ac;
-    auto sensor_device = fbl::make_unique_checked<Imx227Device>(&ac, parent);
+    auto sensor_device = std::unique_ptr<Imx227Device>(new (&ac) Imx227Device(parent));
     if (!ac.check()) {
         return ZX_ERR_NO_MEMORY;
     }
@@ -390,11 +306,57 @@
     }
 
     status = sensor_device->DdkAdd("imx227");
+    if (status != ZX_OK) {
+        zxlogf(ERROR, "imx227: Could not create imx227 sensor device: %d\n", status);
+        return status;
+    }
 
     // sensor_device intentionally leaked as it is now held by DevMgr.
-    __UNUSED auto ptr = sensor_device.release();
+    auto* dev = sensor_device.release();
 
-    return status;
+    isp_callbacks_t cb;
+    isp_callbacks_ops ops;
+
+    ops.init = [](void* ctx) {
+        return static_cast<Imx227Device*>(ctx)->Init();
+    };
+    ops.de_init = [](void* ctx) {
+        return static_cast<Imx227Device*>(ctx)->DeInit();
+    };
+    ops.set_mode = [](void* ctx, uint8_t mode) {
+        return static_cast<Imx227Device*>(ctx)->SetMode(mode);
+    };
+    ops.start_streaming = [](void* ctx) {
+        return static_cast<Imx227Device*>(ctx)->StartStreaming();
+    };
+    ops.stop_streaming = [](void* ctx) {
+        return static_cast<Imx227Device*>(ctx)->StopStreaming();
+    };
+    ops.set_analog_gain = [](void* ctx, int32_t gain) {
+        return static_cast<Imx227Device*>(ctx)->SetAnalogGain(gain);
+    };
+    ops.set_digital_gain = [](void* ctx, int32_t gain) {
+        return static_cast<Imx227Device*>(ctx)->SetDigitalGain(gain);
+    };
+    ops.set_integration_time = [](void* ctx,
+                                  int32_t int_time,
+                                  int32_t int_time_M,
+                                  int32_t int_time_L) {
+        return static_cast<Imx227Device*>(ctx)->SetIntegrationTime(int_time,
+                                                                   int_time_M,
+                                                                   int_time_L);
+    };
+    ops.get_info = [](void* ctx, sensor_info_t* out_info) {
+        return static_cast<Imx227Device*>(ctx)->GetInfo(out_info);
+    };
+    ops.update = [](void* ctx) {
+        return static_cast<Imx227Device*>(ctx)->Update();
+    };
+
+    cb.ops = &ops;
+    cb.ctx = dev;
+    return dev->ispimpl_.RegisterCallbacks(&cb);
+    return ZX_OK;
 }
 
 void Imx227Device::ShutDown() {
diff --git a/system/dev/camera/imx227/imx227.h b/system/dev/camera/imx227/imx227.h
index 100a5b4..f0d1f29 100644
--- a/system/dev/camera/imx227/imx227.h
+++ b/system/dev/camera/imx227/imx227.h
@@ -9,8 +9,8 @@
 #include <ddktl/protocol/clk.h>
 #include <ddktl/protocol/empty-protocol.h>
 #include <ddktl/protocol/gpio.h>
+#include <ddktl/protocol/ispimpl.h>
 #include <ddktl/protocol/mipicsi.h>
-#include <fuchsia/hardware/camera/c/fidl.h>
 
 namespace camera {
 
@@ -41,17 +41,13 @@
     uint8_t dgain_change;
     uint8_t change_flag;
     uint8_t hdr_flag;
-    fuchsia_hardware_camera_SensorInfo param;
+    sensor_info_t param;
 } sensor_context_t;
 
 class Imx227Device;
-using DeviceType = ddk::Device<Imx227Device,
-                               ddk::Unbindable,
-                               ddk::Ioctlable,
-                               ddk::Messageable>;
+using DeviceType = ddk::Device<Imx227Device, ddk::Unbindable>;
 
-class Imx227Device : public DeviceType,
-                     public ddk::EmptyProtocol<ZX_PROTOCOL_CAMERA> {
+class Imx227Device : public DeviceType {
 public:
     // GPIO Indexes.
     enum {
@@ -63,20 +59,14 @@
 
     static zx_status_t Create(zx_device_t* parent);
     Imx227Device(zx_device_t* device)
-        : DeviceType(device), pdev_(device), i2c_(device), clk_(device), mipi_(device) {}
+        : DeviceType(device), pdev_(device), i2c_(device),
+          clk_(device), mipi_(device), ispimpl_(device) {}
 
     // Methods required by the ddk mixins.
     void DdkUnbind();
     void DdkRelease();
-    zx_status_t DdkIoctl(uint32_t op, const void* in_buf, size_t in_len,
-                         void* out_buf, size_t out_len, size_t* out_actual);
-    zx_status_t DdkMessage(fidl_msg_t* msg, fidl_txn_t* txn);
 
-    // Methods for IOCTLs.
-    zx_status_t GetInfo(fuchsia_hardware_camera_SensorInfo* out_info);
-    void GetSupportedModes(void* out_buf, size_t* out_actual);
-
-    // Methods for FIDL Message.
+    // Methods for callbacks.
     zx_status_t Init();
     void DeInit();
     zx_status_t SetMode(uint8_t mode);
@@ -85,7 +75,9 @@
     int32_t SetAnalogGain(int32_t gain);
     int32_t SetDigitalGain(int32_t gain);
     void SetIntegrationTime(int32_t int_time, int32_t int_time_M, int32_t int_time_L);
-    void Update();
+    zx_status_t Update();
+    zx_status_t GetInfo(sensor_info_t* out_info);
+    void GetSupportedModes(void* out_buf, size_t* out_actual);
 
 private:
     // Sensor Context
@@ -97,6 +89,7 @@
     ddk::GpioProtocolClient gpios_[GPIO_COUNT];
     ddk::ClkProtocolClient clk_;
     ddk::MipiCsiProtocolClient mipi_;
+    ddk::IspImplProtocolClient ispimpl_;
 
     // I2C Helpers.
     uint8_t ReadReg(uint16_t addr);
diff --git a/system/dev/camera/imx227/rules.mk b/system/dev/camera/imx227/rules.mk
index 82bb75c..198f2b8 100644
--- a/system/dev/camera/imx227/rules.mk
+++ b/system/dev/camera/imx227/rules.mk
@@ -28,9 +28,6 @@
     system/ulib/zircon \
     system/ulib/c \
 
-MODULE_FIDL_LIBS := \
-    system/fidl/fuchsia-hardware-camera \
-
 MODULE_BANJO_LIBS := \
     system/banjo/ddk-protocol-clk \
     system/banjo/ddk-protocol-gpio \
@@ -38,6 +35,7 @@
     system/banjo/ddk-protocol-platform-bus \
     system/banjo/ddk-protocol-platform-device \
     system/banjo/ddk-protocol-mipicsi \
+    system/banjo/ddk-protocol-ispimpl \
 
 include make/module.mk
 
diff --git a/system/fidl/fuchsia-hardware-camera/camera_sensor.fidl b/system/fidl/fuchsia-hardware-camera/camera_sensor.fidl
deleted file mode 100644
index cfe44e1..0000000
--- a/system/fidl/fuchsia-hardware-camera/camera_sensor.fidl
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2018 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.
-
-library fuchsia.hardware.camera;
-
-using zx;
-
-// This structure represents image resolution.
-struct ImageResolution {
-    uint32 width;
-    uint32 height;
-};
-
-// A sensor can support several different predefined modes.
-struct SensorMode {
-    // Frames per milliseconds. NOTE: (Reference code has fps * 256)
-    uint32 fpms;
-    // Resolution of the mode.
-    ImageResolution resolution;
-    // How many exposures this mode supports.
-    uint8 exposures;
-    // The wdr mode.
-    uint8 wdr_mode;
-    // Bit depth of data from sensor.
-    uint8 bits;
-    // Lane count.
-    uint8 lanes;
-    // MBps per lane.
-    uint32 mbps;
-    // The setting idx in seq.
-    uint8 idx;
-    // The setting bayer pattern
-    uint8 bayer;
-};
-
-struct SensorInfo {
-    // Total resolution of the image with blanking.
-    ImageResolution total;
-    // Active resolution without blanking.
-    ImageResolution active;
-    // Actual pixels per line after scaling/binning.
-    uint32 pixels_per_line;
-    // Maximum analog gain value in log2 format.
-    int32 again_log2_max;
-    // Maximum digital gain value in log2 format.
-    int32 dgain_log2_max;
-    // Precision of the gain - If required gain step
-    // is less then this do not try to allocate it.
-    int32 again_accuracy;
-    // Minimum integration time for the sensor in lines.
-    uint32 integration_time_min;
-    // Maximum integration time for the sensor in lines
-    // without dropping fps.
-    uint32 integration_time_max;
-    // Maximum integration time for long in lines.
-    uint32 integration_time_long_max;
-    // Maximum possible integration time for the sensor in lines.
-    uint32 integration_time_limit;
-    // Limit of integration time for non-flickering light source.
-    uint16 day_light_integration_time_max;
-    // Delay to apply integration time in frames.
-    uint8 integration_time_apply_delay;
-    // Select which WDR exposure channel gain
-    // is delayed 0-none, 1-long, 2-medium, 3-short
-    //  (only 0 and 1 implemented)
-    uint8 isp_exposure_channel_delay;
-    // Used for image stabilization.
-    int32 xoffset;
-    // Used for image stabilization.
-    int32 yoffset;
-    // Number of lines per second used for antiflicker.
-    uint32 lines_per_second;
-    // Number of different exposures supported by the sensor.
-    int32 sensor_exp_number;
-    // Current mode. This value is from the range [ 0 : countof(supported_modes) - 1 ].
-    uint8 mode;
-    // sensor setting bayer pattern.
-    uint8 bayer;
-};
-
-
-[Layout = "Simple"]
-interface CameraSensor {
-  // Initializes the Camera Sensor.
-  1: Init() -> (zx.status s);
-
-  // De-Initializes the Camera Sensor.
-  2: DeInit();
-
-  // Sets the Camera Sensor Mode to one of the supported modes.
-  3: SetMode(uint8 mode) -> (zx.status s);
-
-  // Stop sensor data output.
-  // This function is called from system to enable video stream from sensor.
-  4: StartStreaming();
-
-  // Stop sensor data output.
-  // This function is called from system to disable video stream from sensor.
-  5: StopStreaming();
-
-  // Set analog gain.
-  // This function sets the sensor digital gain.
-  // Gain should be just saved here for the future.
-  // The real sensor digital gain update must be implemented in
-  // Update() routine.
-  // @param gain - analog gain value in log2 format precision is defined by LOG2_GAIN_SHIFT
-  // @return the real digital gain which will be applied
-  6: SetAnalogGain(int32 gain) -> (int32 actual_gain);
-
-  // Set digital gain.
-  // This function sets the sensor digital gain.
-  // Gain should be just saved here for the future.
-  // The real sensor digital gain update must be implemented in
-  // Update() routine.
-  // @param gain - analog gain value in log2 format precision is defined by LOG2_GAIN_SHIFT
-  // @return the real digital gain which will be applied
-  7: SetDigitalGain(int32 gain) -> (int32 actual_gain);
-
-  // Set integration time
-  // This function sets the sensor integration time.
-  // Integration time should be just saved here for the future.
-  // The real time update must be implemented in
-  // sensor_update routine.
-  // @param int_time - integration time if one exposure is used or short exposure for multi-expsoure sensors.
-  //        int_time_M - medium integration time if several exposures are supported.
-  //        int_time_L - long integration time if several exposures are supported.
-  8: SetIntegrationTime(int32 int_time, int32 int_time_M, int32 int_time_L);
-
-  // Update all sensor parameters
-  // The function is called from IRQ thread in vertical blanking.
-  // All sensor parameters must be updated here.
-  9: Update();
-
-  // Get supported sensor modes.
-  // 10: GetSupportedModes() -> (vector<SensorMode> supported_modes, uint32 num);
-
-  // Gets the Sensor Parameters.
-  // Note: This is not supported in Zircon yet under "Simple" layout.
-  // 11: GetInfo() -> (zx.status s, SensorInfo info);
-};
-
diff --git a/system/public/zircon/device/camera.h b/system/public/zircon/device/camera.h
deleted file mode 100644
index 36889a9..0000000
--- a/system/public/zircon/device/camera.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 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 <fuchsia/hardware/camera/c/fidl.h>
-#include <zircon/device/ioctl-wrapper.h>
-#include <zircon/device/ioctl.h>
-#include <zircon/types.h>
-
-#define MAX_SUPPORTED_MODES 3
-
-#define CAMERA_IOCTL_GET_SUPPORTED_MODES \
-    IOCTL(IOCTL_KIND_DEFAULT, IOCTL_FAMILY_CAMERA, 0)
-
-// ssize_t ioctl_camera_get_supported_modes(int fd, fuchsia_hardware_camera_SensorMode* modes,
-//                                          size_t out_len);
-IOCTL_WRAPPER_VAROUT(ioctl_camera_get_supported_modes, CAMERA_IOCTL_GET_SUPPORTED_MODES,
-                     fuchsia_hardware_camera_SensorMode);
diff --git a/system/ulib/ddk/include/ddk/metadata/camera.h b/system/ulib/ddk/include/ddk/metadata/camera.h
index 6bd7bcc..43be164 100644
--- a/system/ulib/ddk/include/ddk/metadata/camera.h
+++ b/system/ulib/ddk/include/ddk/metadata/camera.h
@@ -11,3 +11,9 @@
     uint32_t pid;
     uint32_t did;
 } camera_sensor_t;
+
+typedef struct {
+    uint32_t vid;
+    uint32_t pid;
+    uint32_t did;
+} mipi_adapter_t;
diff --git a/system/ulib/ddk/include/ddk/platform-defs.h b/system/ulib/ddk/include/ddk/platform-defs.h
index 01b507c..6950861 100644
--- a/system/ulib/ddk/include/ddk/platform-defs.h
+++ b/system/ulib/ddk/include/ddk/platform-defs.h
@@ -170,7 +170,6 @@
 #define PDEV_PID_TI_LP8556          1
 #define PDEV_DID_TI_BACKLIGHT       1
 
-
 // Test
 #define PDEV_VID_TEST               17
 #define PDEV_PID_PBUS_TEST          1
@@ -181,8 +180,13 @@
 #define PDEV_DID_TEST_CHILD_3       4
 #define PDEV_DID_TEST_GPIO          5
 
+// ARM
+#define PDEV_VID_ARM                18
+#define PDEV_PID_ISP                1
+#define PDEV_DID_ARM_MALI_IV009     1
+
 // Qualcomm
-#define PDEV_VID_QUALCOMM           18
+#define PDEV_VID_QUALCOMM           19
 #define PDEV_PID_QUALCOMM_MSM8X53    1
 
 __END_CDECLS;
diff --git a/system/ulib/ddk/include/ddk/protodefs.h b/system/ulib/ddk/include/ddk/protodefs.h
index 372112b..2a624dc 100644
--- a/system/ulib/ddk/include/ddk/protodefs.h
+++ b/system/ulib/ddk/include/ddk/protodefs.h
@@ -98,6 +98,8 @@
 DDK_PROTOCOL_DEF(QMI_TRANSPORT,  'pQMI', "qmi-transport", 0)
 DDK_PROTOCOL_DEF(MIPI_CSI,       'pMIP', "mipi-csi", PF_NOPUB)
 DDK_PROTOCOL_DEF(LIGHT,          'pLIG', "light", 0)
+DDK_PROTOCOL_DEF(ISP_IMPL,       'pIPL', "isp-impl", PF_NOPUB)
+DDK_PROTOCOL_DEF(ISP,            'pISP', "isp", 0)
 // Protocol definition at garnet/magma/src/magma_util/platform/zircon/zircon_platform_ioctl.h
 DDK_PROTOCOL_DEF(GPU,            'pGPU', "gpu", 0)
 DDK_PROTOCOL_DEF(RTC,            'pRTC', "rtc", 0)
diff --git a/system/utest/camera/camera.cpp b/system/utest/camera/camera.cpp
deleted file mode 100644
index 8ae6c49..0000000
--- a/system/utest/camera/camera.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2018 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.
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <fuchsia/hardware/camera/c/fidl.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <unittest/unittest.h>
-#include <zircon/device/camera.h>
-
-namespace {
-
-const char kCameraDir[] = "/dev/class/camera";
-
-zx_status_t StartCameraTest(int* fd) {
-    struct dirent* de;
-    DIR* dir = opendir(kCameraDir);
-    if (!dir) {
-        printf("Error opening %s\n", kCameraDir);
-        return -1;
-    }
-
-    while ((de = readdir(dir)) != NULL) {
-        char devname[128];
-
-        snprintf(devname, sizeof(devname), "%s/%s", kCameraDir, de->d_name);
-        printf("\nOpening %s\n", devname);
-        *fd = open(devname, O_RDWR);
-        if (*fd < 0) {
-            printf("Error opening device%s\n", devname);
-            return -1;
-        }
-
-        closedir(dir);
-        return ZX_OK;
-    }
-    closedir(dir);
-    return -1;
-}
-
-bool TestSupportedModes(void) {
-    BEGIN_TEST;
-
-    int fd;
-    // Open the camera sensor.
-    ASSERT_EQ(StartCameraTest(&fd), ZX_OK, "");
-
-    // Get the modes supported.
-    auto* supported_modes = new fuchsia_hardware_camera_SensorMode[MAX_SUPPORTED_MODES];
-    ASSERT_NE(supported_modes, nullptr, "");
-
-    ssize_t rc = ioctl_camera_get_supported_modes(
-        fd, supported_modes, sizeof(fuchsia_hardware_camera_SensorMode) * MAX_SUPPORTED_MODES);
-    ASSERT_GE(rc, 0, "");
-
-    close(fd);
-    END_TEST;
-}
-
-} // namespace
-
-BEGIN_TEST_CASE(camera_tests)
-RUN_TEST(TestSupportedModes)
-END_TEST_CASE(camera_tests)
-
-int main(int argc, char* argv[]) {
-    // Disabling since this test is intended
-    // to be tested on HW manually.
-    return 0;
-
-    bool success = unittest_run_all_tests(argc, argv);
-    return success ? 0 : -1;
-}
diff --git a/system/utest/camera/rules.mk b/system/utest/camera/rules.mk
deleted file mode 100644
index e95216c..0000000
--- a/system/utest/camera/rules.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2018 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.
-
-LOCAL_DIR := $(GET_LOCAL_DIR)
-
-MODULE := $(LOCAL_DIR)
-
-MODULE_TYPE := usertest
-
-MODULE_NAME := camera-test
-
-MODULE_SRCS := \
-    $(LOCAL_DIR)/camera.cpp \
-
-
-MODULE_STATIC_LIBS := \
-    system/ulib/ddk \
-    system/ulib/ddktl \
-    system/ulib/fbl \
-    system/ulib/fidl \
-    system/ulib/sync \
-    system/ulib/zx \
-    system/ulib/zxcpp \
-
-MODULE_LIBS := \
-    system/ulib/async.default \
-    system/ulib/c \
-    system/ulib/fdio \
-    system/ulib/fs-management \
-    system/ulib/memfs \
-    system/ulib/trace-engine \
-    system/ulib/unittest \
-    system/ulib/zircon \
-
-MODULE_FIDL_LIBS := \
-    system/fidl/fuchsia-hardware-camera \
-
-include make/module.mk
diff --git a/system/utest/device-enumeration/main.cpp b/system/utest/device-enumeration/main.cpp
index 2cdec88..e95130a 100644
--- a/system/utest/device-enumeration/main.cpp
+++ b/system/utest/device-enumeration/main.cpp
@@ -252,7 +252,8 @@
         "sys/platform/05:00:6/aml-sd-emmc/sdmmc/sdmmc-block/block/part-010/block",
         //"sys/platform/05:00:6/aml-sd-emmc/sdio",
         //"sys/platform/05:00:3/aml-uart/serial/bt-transport/uart/bcm-hci",
-        "sys/platform/05:06:13/aml-mipi",
+        "sys/platform/11:01:1/arm-isp/aml-mipi/imx227",
+        "sys/platform/11:01:1/arm-isp",
         "sys/platform/05:06:c/ProxyClient[7043414e]/aml-canvas-proxy",
         "sys/platform/05:06:c/aml-video",
         "sys/platform/05:06:d/aml-gpu",