[mipi][sherlock] Adding proxy for ZX_PROTOCOL_MIPI_CSI

- This is the first step towards converting camera driver
  to composite devices
- This is not yet tested

Test: Compiles & boot up on sherlock

Change-Id: I2b350119f9c86ce20fd566ad8c11129020aae884
diff --git a/zircon/system/core/devmgr/component/BUILD.gn b/zircon/system/core/devmgr/component/BUILD.gn
index 2228772..6fab0fc 100644
--- a/zircon/system/core/devmgr/component/BUILD.gn
+++ b/zircon/system/core/devmgr/component/BUILD.gn
@@ -15,6 +15,7 @@
     "$zx/system/banjo/ddk-protocol-ethernet-board",
     "$zx/system/banjo/ddk-protocol-gpio",
     "$zx/system/banjo/ddk-protocol-i2c",
+    "$zx/system/banjo/ddk-protocol-mipicsi",
     "$zx/system/banjo/ddk-protocol-platform-device",
     "$zx/system/banjo/ddk-protocol-power",
     "$zx/system/banjo/ddk-protocol-sysmem",
@@ -39,6 +40,7 @@
     "$zx/system/banjo/ddk-protocol-ethernet-board",
     "$zx/system/banjo/ddk-protocol-gpio",
     "$zx/system/banjo/ddk-protocol-i2c",
+    "$zx/system/banjo/ddk-protocol-mipicsi",
     "$zx/system/banjo/ddk-protocol-platform-device",
     "$zx/system/banjo/ddk-protocol-power",
     "$zx/system/banjo/ddk-protocol-sysmem",
diff --git a/zircon/system/core/devmgr/component/component-proxy.cpp b/zircon/system/core/devmgr/component/component-proxy.cpp
index 66fad91..3786a29 100644
--- a/zircon/system/core/devmgr/component/component-proxy.cpp
+++ b/zircon/system/core/devmgr/component/component-proxy.cpp
@@ -43,6 +43,9 @@
     case ZX_PROTOCOL_I2C:
         proto->ops = &i2c_protocol_ops_;
         return ZX_OK;
+    case ZX_PROTOCOL_MIPI_CSI:
+        proto->ops = &mipi_csi_protocol_ops_;
+        return ZX_OK;
     case ZX_PROTOCOL_PDEV:
         proto->ops = &pdev_protocol_ops_;
         return ZX_OK;
@@ -117,8 +120,8 @@
 }
 
 zx_status_t ComponentProxy::AmlogicCanvasConfig(zx::vmo vmo, size_t offset,
-                                                    const canvas_info_t* info,
-                                                    uint8_t* out_canvas_idx) {
+                                                const canvas_info_t* info,
+                                                uint8_t* out_canvas_idx) {
     AmlogicCanvasProxyRequest req = {};
     AmlogicCanvasProxyResponse resp = {};
     req.header.proto_id = ZX_PROTOCOL_AMLOGIC_CANVAS;
@@ -175,6 +178,27 @@
     return Rpc(&req.header, sizeof(req), &resp, sizeof(resp));
 }
 
+zx_status_t ComponentProxy::MipiCsiInit(const mipi_info_t* mipi_info,
+                                        const mipi_adap_info_t* adap_info) {
+    MipiCsiProxyRequest req = {};
+    ProxyResponse resp = {};
+    req.header.proto_id = ZX_PROTOCOL_MIPI_CSI;
+    req.op = MipiCsiOp::INIT;
+    req.mipi_info = *mipi_info;
+    req.adap_info = *adap_info;
+
+    return Rpc(&req.header, sizeof(req), &resp, sizeof(resp));
+}
+
+zx_status_t ComponentProxy::MipiCsiDeInit() {
+    MipiCsiProxyRequest req = {};
+    ProxyResponse resp = {};
+    req.header.proto_id = ZX_PROTOCOL_MIPI_CSI;
+    req.op = MipiCsiOp::DEINIT;
+
+    return Rpc(&req.header, sizeof(req), &resp, sizeof(resp));
+}
+
 zx_status_t ComponentProxy::GpioConfigIn(uint32_t flags) {
     GpioProxyRequest req = {};
     GpioProxyResponse resp = {};
@@ -311,8 +335,8 @@
     auto* rsp = reinterpret_cast<I2cProxyResponse*>(resp_buffer);
     size_t actual;
     auto status = Rpc(&req->header, static_cast<uint32_t>(req_length),
-                              &rsp->header, static_cast<uint32_t>(resp_length), nullptr, 0, nullptr,
-                              0, &actual);
+                      &rsp->header, static_cast<uint32_t>(resp_length), nullptr, 0, nullptr,
+                      0, &actual);
     if (status != ZX_OK) {
         callback(cookie, status, nullptr, 0);
         return;
diff --git a/zircon/system/core/devmgr/component/component-proxy.h b/zircon/system/core/devmgr/component/component-proxy.h
index 5e92362..7ebbdfc 100644
--- a/zircon/system/core/devmgr/component/component-proxy.h
+++ b/zircon/system/core/devmgr/component/component-proxy.h
@@ -13,6 +13,7 @@
 #include <ddktl/protocol/ethernet/board.h>
 #include <ddktl/protocol/gpio.h>
 #include <ddktl/protocol/i2c.h>
+#include <ddktl/protocol/mipicsi.h>
 #include <ddktl/protocol/platform/device.h>
 #include <ddktl/protocol/power.h>
 #include <ddktl/protocol/sysmem.h>
@@ -32,6 +33,7 @@
                        public ddk::EthBoardProtocol<ComponentProxy>,
                        public ddk::GpioProtocol<ComponentProxy>,
                        public ddk::I2cProtocol<ComponentProxy>,
+                       public ddk::MipiCsiProtocol<ComponentProxy>,
                        public ddk::PDevProtocol<ComponentProxy>,
                        public ddk::PowerProtocol<ComponentProxy>,
                        public ddk::SysmemProtocol<ComponentProxy>,
@@ -92,6 +94,9 @@
     zx_status_t PowerWritePmicCtrlReg(uint32_t reg_addr, uint32_t value);
     zx_status_t PowerReadPmicCtrlReg(uint32_t reg_addr, uint32_t* out_value);
     zx_status_t SysmemConnect(zx::channel allocator2_request);
+    zx_status_t MipiCsiInit(const mipi_info_t* mipi_info,
+                            const mipi_adap_info_t* adap_info);
+    zx_status_t MipiCsiDeInit();
 
     // USB Mode Switch
     zx_status_t UsbModeSwitchSetMode(usb_mode_t mode);
diff --git a/zircon/system/core/devmgr/component/component.cpp b/zircon/system/core/devmgr/component/component.cpp
index e5c3bfb..a5af246 100644
--- a/zircon/system/core/devmgr/component/component.cpp
+++ b/zircon/system/core/devmgr/component/component.cpp
@@ -14,7 +14,7 @@
 namespace component {
 
 Component::Component(zx_device_t* parent)
-        : ComponentBase(parent) {
+    : ComponentBase(parent) {
 
     // These protocols are all optional, so no error checking is necessary here.
     device_get_protocol(parent, ZX_PROTOCOL_AMLOGIC_CANVAS, &canvas_);
@@ -22,6 +22,7 @@
     device_get_protocol(parent, ZX_PROTOCOL_ETH_BOARD, &eth_board_);
     device_get_protocol(parent, ZX_PROTOCOL_GPIO, &gpio_);
     device_get_protocol(parent, ZX_PROTOCOL_I2C, &i2c_);
+    device_get_protocol(parent, ZX_PROTOCOL_MIPI_CSI, &mipicsi_);
     device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev_);
     device_get_protocol(parent, ZX_PROTOCOL_POWER, &power_);
     device_get_protocol(parent, ZX_PROTOCOL_SYSMEM, &sysmem_);
@@ -47,7 +48,7 @@
                                  uint32_t* out_resp_size, const zx_handle_t* req_handles,
                                  uint32_t req_handle_count, zx_handle_t* resp_handles,
                                  uint32_t* resp_handle_count) {
-   if (canvas_.ops == nullptr) {
+    if (canvas_.ops == nullptr) {
         return ZX_ERR_NOT_SUPPORTED;
     }
     auto* req = reinterpret_cast<const AmlogicCanvasProxyRequest*>(req_buf);
@@ -65,7 +66,7 @@
             return ZX_ERR_INTERNAL;
         }
         return amlogic_canvas_config(&canvas_, req_handles[0], req->offset, &req->info,
-                                       &resp->canvas_idx);
+                                     &resp->canvas_idx);
     case AmlogicCanvasOp::FREE:
         if (req_handle_count != 0) {
             zxlogf(ERROR, "%s received %u handles, expecting 0\n", __func__, req_handle_count);
@@ -82,7 +83,7 @@
                                 uint32_t* out_resp_size, const zx_handle_t* req_handles,
                                 uint32_t req_handle_count, zx_handle_t* resp_handles,
                                 uint32_t* resp_handle_count) {
-   if (clock_.ops == nullptr) {
+    if (clock_.ops == nullptr) {
         return ZX_ERR_NOT_SUPPORTED;
     }
     auto* req = reinterpret_cast<const ClockProxyRequest*>(req_buf);
@@ -337,7 +338,7 @@
     case PowerOp::WRITE_PMIC_CTRL_REG:
         return power_write_pmic_ctrl_reg(&power_, req->reg_addr, req->reg_value);
     case PowerOp::READ_PMIC_CTRL_REG:
-        return power_read_pmic_ctrl_reg(&power_,req->reg_addr, &resp->reg_value);
+        return power_read_pmic_ctrl_reg(&power_, req->reg_addr, &resp->reg_value);
     default:
         zxlogf(ERROR, "%s: unknown Power op %u\n", __func__, static_cast<uint32_t>(req->op));
         return ZX_ERR_INTERNAL;
@@ -396,6 +397,35 @@
     }
 }
 
+zx_status_t Component::RpcMipiCsi(const uint8_t* req_buf, uint32_t req_size, uint8_t* resp_buf,
+                                  uint32_t* out_resp_size, const zx_handle_t* req_handles,
+                                  uint32_t req_handle_count, zx_handle_t* resp_handles,
+                                  uint32_t* resp_handle_count) {
+    if (mipicsi_.ops == nullptr) {
+        return ZX_ERR_NOT_SUPPORTED;
+    }
+
+    ddk::MipiCsiProtocolClient mipicsi(&mipicsi_);
+
+    auto* req = reinterpret_cast<const MipiCsiProxyRequest*>(req_buf);
+    if (req_size < sizeof(*req)) {
+        zxlogf(ERROR, "%s received %u, expecting %zu\n", __func__, req_size, sizeof(*req));
+        return ZX_ERR_INTERNAL;
+    }
+    auto* resp = reinterpret_cast<ProxyResponse*>(resp_buf);
+    *out_resp_size = sizeof(*resp);
+
+    switch (req->op) {
+    case MipiCsiOp::INIT:
+        return mipicsi.Init(&req->mipi_info, &req->adap_info);
+    case MipiCsiOp::DEINIT:
+        return mipicsi.DeInit();
+    default:
+        zxlogf(ERROR, "%s: unknown MIPI_CSI op %u\n", __func__, static_cast<uint32_t>(req->op));
+        return ZX_ERR_INTERNAL;
+    }
+}
+
 zx_status_t Component::DdkRxrpc(zx_handle_t raw_channel) {
     zx::unowned_channel channel(raw_channel);
     if (!channel->is_valid()) {
@@ -442,7 +472,7 @@
         break;
     case ZX_PROTOCOL_I2C:
         status = RpcI2c(req_buf, actual, resp_buf, &resp_len, req_handles, req_handle_count,
-                         resp_handles, &resp_handle_count);
+                        resp_handles, &resp_handle_count);
         break;
     case ZX_PROTOCOL_PDEV:
         status = RpcPdev(req_buf, actual, resp_buf, &resp_len, req_handles, req_handle_count,
@@ -460,6 +490,10 @@
         status = RpcUms(req_buf, actual, resp_buf, &resp_len, req_handles, req_handle_count,
                         resp_handles, &resp_handle_count);
         break;
+    case ZX_PROTOCOL_MIPI_CSI:
+        status = RpcMipiCsi(req_buf, actual, resp_buf, &resp_len, req_handles, req_handle_count,
+                            resp_handles, &resp_handle_count);
+        break;
     default:
         zxlogf(ERROR, "%s: unknown protocol %u\n", __func__, req_header->proto_id);
         return ZX_ERR_INTERNAL;
diff --git a/zircon/system/core/devmgr/component/component.h b/zircon/system/core/devmgr/component/component.h
index c6ef9b0..0494048 100644
--- a/zircon/system/core/devmgr/component/component.h
+++ b/zircon/system/core/devmgr/component/component.h
@@ -17,6 +17,7 @@
 #include <ddk/protocol/sysmem.h>
 #include <ddk/protocol/usb/modeswitch.h>
 #include <ddktl/device.h>
+#include <ddktl/protocol/mipicsi.h>
 #include <lib/sync/completion.h>
 #include <lib/zx/channel.h>
 
@@ -76,9 +77,13 @@
                           uint32_t req_handle_count, zx_handle_t* resp_handles,
                           uint32_t* resp_handle_count);
     zx_status_t RpcUms(const uint8_t* req_buf, uint32_t req_size, uint8_t* resp_buf,
-                      uint32_t* out_resp_size, const zx_handle_t* req_handles,
-                      uint32_t req_handle_count, zx_handle_t* resp_handles,
-                      uint32_t* resp_handle_count);
+                       uint32_t* out_resp_size, const zx_handle_t* req_handles,
+                       uint32_t req_handle_count, zx_handle_t* resp_handles,
+                       uint32_t* resp_handle_count);
+    zx_status_t RpcMipiCsi(const uint8_t* req_buf, uint32_t req_size, uint8_t* resp_buf,
+                           uint32_t* out_resp_size, const zx_handle_t* req_handles,
+                           uint32_t req_handle_count, zx_handle_t* resp_handles,
+                           uint32_t* resp_handle_count);
 
     static void I2cTransactCallback(void* cookie, zx_status_t status, const i2c_op_t* op_list,
                                     size_t op_count);
@@ -88,6 +93,7 @@
     eth_board_protocol_t eth_board_ = {};
     gpio_protocol_t gpio_ = {};
     i2c_protocol_t i2c_ = {};
+    mipi_csi_protocol_t mipicsi_ = {};
     pdev_protocol_t pdev_ = {};
     power_protocol_t power_ = {};
     sysmem_protocol_t sysmem_ = {};
diff --git a/zircon/system/core/devmgr/component/proxy-protocol.h b/zircon/system/core/devmgr/component/proxy-protocol.h
index ec540ab..7868593 100644
--- a/zircon/system/core/devmgr/component/proxy-protocol.h
+++ b/zircon/system/core/devmgr/component/proxy-protocol.h
@@ -56,6 +56,19 @@
     uint8_t metadata[PROXY_MAX_METADATA_SIZE];
 };
 
+// ZX_PROTOCOL_MIPI_CSI proxy support.
+enum class MipiCsiOp {
+    INIT,
+    DEINIT,
+};
+
+struct MipiCsiProxyRequest {
+    ProxyRequest header;
+    MipiCsiOp op;
+    mipi_info_t mipi_info;
+    mipi_adap_info_t adap_info;
+};
+
 // ZX_PROTOCOL_GPIO proxy support.
 enum class GpioOp {
     CONFIG_IN,