| // 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 <fidl/fuchsia.hardware.platform.bus/cpp/driver/fidl.h> |
| #include <fidl/fuchsia.hardware.platform.bus/cpp/fidl.h> |
| #include <lib/ddk/debug.h> |
| #include <lib/ddk/device.h> |
| #include <lib/ddk/metadata.h> |
| #include <lib/ddk/platform-defs.h> |
| #include <lib/driver/component/cpp/composite_node_spec.h> |
| #include <lib/driver/component/cpp/node_add_args.h> |
| |
| #include <bind/fuchsia/amlogic/platform/cpp/bind.h> |
| #include <bind/fuchsia/amlogic/platform/meson/cpp/bind.h> |
| #include <bind/fuchsia/amlogic/platform/t931/cpp/bind.h> |
| #include <bind/fuchsia/arm/platform/cpp/bind.h> |
| #include <bind/fuchsia/camera/cpp/bind.h> |
| #include <bind/fuchsia/clock/cpp/bind.h> |
| #include <bind/fuchsia/cpp/bind.h> |
| #include <bind/fuchsia/gpio/cpp/bind.h> |
| #include <bind/fuchsia/hardware/amlogiccanvas/cpp/bind.h> |
| #include <bind/fuchsia/hardware/clock/cpp/bind.h> |
| #include <bind/fuchsia/hardware/gpio/cpp/bind.h> |
| #include <bind/fuchsia/hardware/i2c/cpp/bind.h> |
| #include <bind/fuchsia/hardware/registers/cpp/bind.h> |
| #include <bind/fuchsia/hardware/sysmem/cpp/bind.h> |
| #include <bind/fuchsia/i2c/cpp/bind.h> |
| #include <bind/fuchsia/isp/cpp/bind.h> |
| #include <bind/fuchsia/register/cpp/bind.h> |
| #include <bind/fuchsia/sony/platform/cpp/bind.h> |
| #include <soc/aml-common/aml-registers.h> |
| #include <soc/aml-meson/g12b-clk.h> |
| #include <soc/aml-t931/t931-gpio.h> |
| #include <soc/aml-t931/t931-hw.h> |
| |
| #include "sherlock-gpios.h" |
| #include "sherlock.h" |
| |
| namespace sherlock { |
| namespace fpbus = fuchsia_hardware_platform_bus; |
| |
| namespace { |
| |
| constexpr uint32_t kClk24MAltFunc = 7; |
| constexpr uint32_t kClkGpioDriveStrengthUa = 4000; |
| |
| static const std::vector<fpbus::Mmio> ge2d_mmios{ |
| {{ |
| .base = T931_GE2D_BASE, |
| .length = T931_GE2D_LENGTH, |
| }}, |
| }; |
| |
| static const std::vector<fpbus::Bti> ge2d_btis{ |
| {{ |
| .iommu_index = 0, |
| .bti_id = BTI_GE2D, |
| }}, |
| }; |
| |
| // IRQ for GE2D |
| static const std::vector<fpbus::Irq> ge2d_irqs{ |
| {{ |
| .irq = T931_MALI_GE2D_IRQ, |
| .mode = ZX_INTERRUPT_MODE_EDGE_HIGH, |
| }}, |
| }; |
| |
| static const fpbus::Node ge2d_dev = []() { |
| // GE2D |
| fpbus::Node dev = {}; |
| dev.name() = "ge2d"; |
| dev.vid() = bind_fuchsia_amlogic_platform::BIND_PLATFORM_DEV_VID_AMLOGIC; |
| dev.pid() = bind_fuchsia_amlogic_platform::BIND_PLATFORM_DEV_PID_T931; |
| dev.did() = bind_fuchsia_amlogic_platform::BIND_PLATFORM_DEV_DID_GE2D; |
| dev.mmio() = ge2d_mmios; |
| dev.bti() = ge2d_btis; |
| dev.irq() = ge2d_irqs; |
| return dev; |
| }(); |
| |
| static const std::vector<fpbus::Mmio> gdc_mmios{ |
| {{ |
| .base = T931_HIU_BASE, |
| .length = T931_HIU_LENGTH, |
| }}, |
| {{ |
| .base = T931_GDC_BASE, |
| .length = T931_GDC_LENGTH, |
| }}, |
| }; |
| |
| static const std::vector<fpbus::Bti> gdc_btis{ |
| {{ |
| .iommu_index = 0, |
| .bti_id = BTI_GDC, |
| }}, |
| }; |
| |
| // IRQ for ISP |
| static const std::vector<fpbus::Irq> gdc_irqs{ |
| {{ |
| .irq = T931_MALI_GDC_IRQ, |
| .mode = ZX_INTERRUPT_MODE_EDGE_HIGH, |
| }}, |
| }; |
| |
| static const fpbus::Node gdc_dev = []() { |
| // GDC |
| fpbus::Node dev = {}; |
| dev.name() = "gdc"; |
| dev.vid() = bind_fuchsia_arm_platform::BIND_PLATFORM_DEV_VID_ARM; |
| dev.pid() = bind_fuchsia_arm_platform::BIND_PLATFORM_DEV_PID_GDC; |
| dev.did() = bind_fuchsia_arm_platform::BIND_PLATFORM_DEV_DID_MALI_IV010; |
| dev.mmio() = gdc_mmios; |
| dev.bti() = gdc_btis; |
| dev.irq() = gdc_irqs; |
| return dev; |
| }(); |
| |
| static const std::vector<fpbus::Bti> isp_btis{ |
| {{ |
| .iommu_index = 0, |
| .bti_id = BTI_ISP, |
| }}, |
| }; |
| |
| static const std::vector<fpbus::Mmio> isp_mmios{ |
| {{ |
| .base = T931_HIU_BASE, |
| .length = T931_HIU_LENGTH, |
| }}, |
| {{ |
| .base = T931_POWER_DOMAIN_BASE, |
| .length = T931_POWER_DOMAIN_LENGTH, |
| }}, |
| {{ |
| .base = T931_MEMORY_PD_BASE, |
| .length = T931_MEMORY_PD_LENGTH, |
| }}, |
| {{ |
| .base = T931_ISP_BASE, |
| .length = T931_ISP_LENGTH, |
| }}, |
| }; |
| |
| // IRQ for ISP |
| static const std::vector<fpbus::Irq> isp_irqs{ |
| {{ |
| .irq = T931_MALI_ISP_IRQ, |
| .mode = ZX_INTERRUPT_MODE_LEVEL_HIGH, |
| }}, |
| }; |
| |
| static const fpbus::Node isp_dev = []() { |
| // ISP |
| fpbus::Node dev = {}; |
| dev.name() = "isp"; |
| dev.vid() = PDEV_VID_ARM; |
| dev.pid() = PDEV_PID_ARM_ISP; |
| dev.did() = PDEV_DID_ARM_MALI_IV009; |
| dev.mmio() = isp_mmios; |
| dev.bti() = isp_btis; |
| dev.irq() = isp_irqs; |
| return dev; |
| }(); |
| |
| static const std::vector<fpbus::Mmio> mipi_mmios{ |
| {{ |
| .base = T931_CSI_PHY0_BASE, |
| .length = T931_CSI_PHY0_LENGTH, |
| }}, |
| {{ |
| .base = T931_APHY_BASE, |
| .length = T931_APHY_LENGTH, |
| }}, |
| {{ |
| .base = T931_CSI_HOST0_BASE, |
| .length = T931_CSI_HOST0_LENGTH, |
| }}, |
| {{ |
| .base = T931_MIPI_ADAPTER_BASE, |
| .length = T931_MIPI_ADAPTER_LENGTH, |
| }}, |
| {{ |
| .base = T931_HIU_BASE, |
| .length = T931_HIU_LENGTH, |
| }}, |
| }; |
| |
| static const std::vector<fpbus::Bti> mipi_btis{ |
| {{ |
| .iommu_index = 0, |
| .bti_id = BTI_MIPI, |
| }}, |
| }; |
| |
| static const std::vector<fpbus::Irq> mipi_irqs{ |
| {{ |
| .irq = T931_MIPI_ADAPTER_IRQ, |
| .mode = ZX_INTERRUPT_MODE_EDGE_HIGH, |
| }}, |
| }; |
| |
| // Binding rules for MIPI Driver |
| static const fpbus::Node mipi_dev = []() { |
| // MIPI CSI PHY ADAPTER |
| fpbus::Node dev = {}; |
| dev.name() = "mipi-csi2"; |
| dev.vid() = PDEV_VID_AMLOGIC; |
| dev.pid() = PDEV_PID_AMLOGIC_T931; |
| dev.did() = PDEV_DID_AMLOGIC_MIPI_CSI; |
| dev.mmio() = mipi_mmios; |
| dev.bti() = mipi_btis; |
| dev.irq() = mipi_irqs; |
| return dev; |
| }(); |
| |
| // Binding rules for Sensor Driver |
| static const fpbus::Node sensor_dev_sherlock = []() { |
| fpbus::Node dev = {}; |
| dev.name() = "imx227-sensor"; |
| dev.vid() = bind_fuchsia_sony_platform::BIND_PLATFORM_DEV_VID_SONY; |
| dev.pid() = bind_fuchsia_sony_platform::BIND_PLATFORM_DEV_PID_IMX227; |
| dev.did() = bind_fuchsia_sony_platform::BIND_PLATFORM_DEV_DID_CAMERA_SENSOR; |
| return dev; |
| }(); |
| |
| } // namespace |
| |
| // Refer to camera design document for driver |
| // design and layout details. |
| zx_status_t Sherlock::CameraInit() { |
| // Set GPIO alternate functions. |
| gpio_init_steps_.push_back({T931_GPIOAO(10), GpioSetAltFunction(kClk24MAltFunc)}); |
| gpio_init_steps_.push_back({T931_GPIOAO(10), GpioSetDriveStrength(kClkGpioDriveStrengthUa)}); |
| |
| fidl::Arena<> fidl_arena; |
| fdf::Arena arena('CAME'); |
| { |
| auto result = pbus_.buffer(arena)->NodeAdd(fidl::ToWire(fidl_arena, mipi_dev)); |
| if (!result.ok()) { |
| zxlogf(ERROR, "%s: NodeAdd Camera(mipi_dev) request failed: %s", __func__, |
| result.FormatDescription().data()); |
| return result.status(); |
| } |
| if (result->is_error()) { |
| zxlogf(ERROR, "%s: NodeAdd Camera(mipi_dev) failed: %s", __func__, |
| zx_status_get_string(result->error_value())); |
| return result->error_value(); |
| } |
| } |
| |
| auto imx227_sensor_mipicsi_spec = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = std::vector{fdf::MakeAcceptBindRule( |
| bind_fuchsia::PROTOCOL, bind_fuchsia_camera::BIND_PROTOCOL_MIPICSI)}, |
| .properties = {fdf::MakeProperty(bind_fuchsia::PROTOCOL, |
| bind_fuchsia_camera::BIND_PROTOCOL_MIPICSI)}, |
| }}; |
| |
| auto imx227_sensor_i2c_spec = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia_hardware_i2c::SERVICE, |
| bind_fuchsia_hardware_i2c::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeAcceptBindRule(bind_fuchsia::I2C_BUS_ID, |
| bind_fuchsia_i2c::BIND_I2C_BUS_ID_I2C_3), |
| fdf::MakeAcceptBindRule(bind_fuchsia::I2C_ADDRESS, |
| bind_fuchsia_i2c::BIND_I2C_ADDRESS_SHERLOCK), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia_hardware_i2c::SERVICE, |
| bind_fuchsia_hardware_i2c::SERVICE_ZIRCONTRANSPORT), |
| }, |
| }}; |
| |
| auto imx227_sensor_gpio_reset_spec = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia_hardware_gpio::SERVICE, |
| bind_fuchsia_hardware_gpio::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeAcceptBindRule(bind_fuchsia::GPIO_PIN, |
| bind_fuchsia_amlogic_platform_t931::GPIOZ_PIN_ID_PIN_0), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia_hardware_gpio::SERVICE, |
| bind_fuchsia_hardware_gpio::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeProperty(bind_fuchsia_gpio::FUNCTION, bind_fuchsia_gpio::FUNCTION_CAM_RESET), |
| }, |
| }}; |
| |
| auto imx227_sensor_gpio_vana_spec = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia_hardware_gpio::SERVICE, |
| bind_fuchsia_hardware_gpio::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeAcceptBindRule(bind_fuchsia::GPIO_PIN, |
| bind_fuchsia_amlogic_platform_t931::GPIOA_PIN_ID_PIN_6), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia_hardware_gpio::SERVICE, |
| bind_fuchsia_hardware_gpio::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeProperty(bind_fuchsia_gpio::FUNCTION, |
| bind_fuchsia_gpio::FUNCTION_VANA_ENABLE), |
| }, |
| }}; |
| |
| auto imx227_sensor_gpio_vdig_spec = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia_hardware_gpio::SERVICE, |
| bind_fuchsia_hardware_gpio::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeAcceptBindRule(bind_fuchsia::GPIO_PIN, |
| bind_fuchsia_amlogic_platform_t931::GPIOZ_PIN_ID_PIN_12), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia_hardware_gpio::SERVICE, |
| bind_fuchsia_hardware_gpio::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeProperty(bind_fuchsia_gpio::FUNCTION, |
| bind_fuchsia_gpio::FUNCTION_VDIG_ENABLE), |
| }, |
| }}; |
| |
| auto imx227_sensor_clock_sensor_spec = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia_hardware_clock::SERVICE, |
| bind_fuchsia_hardware_clock::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeAcceptBindRule( |
| bind_fuchsia::CLOCK_ID, |
| bind_fuchsia_amlogic_platform_meson::G12B_CLK_ID_CLK_CAM_INCK_24M), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia_hardware_clock::SERVICE, |
| bind_fuchsia_hardware_clock::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeProperty(bind_fuchsia_clock::FUNCTION, |
| bind_fuchsia_clock::FUNCTION_CAMERA_SENSOR), |
| }, |
| }}; |
| |
| auto imx227_sensor_gpio_init_spec = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia::INIT_STEP, |
| bind_fuchsia_gpio::BIND_INIT_STEP_GPIO), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia::INIT_STEP, bind_fuchsia_gpio::BIND_INIT_STEP_GPIO), |
| }, |
| }}; |
| |
| auto composite_spec = fuchsia_driver_framework::CompositeNodeSpec{{ |
| .name = "imx227_sensor", |
| .parents = {{ |
| imx227_sensor_mipicsi_spec, |
| imx227_sensor_i2c_spec, |
| imx227_sensor_gpio_reset_spec, |
| imx227_sensor_gpio_vana_spec, |
| imx227_sensor_gpio_vdig_spec, |
| imx227_sensor_clock_sensor_spec, |
| imx227_sensor_gpio_init_spec, |
| }}, |
| }}; |
| |
| fdf::WireUnownedResult spec_result = pbus_.buffer(arena)->AddCompositeNodeSpec( |
| fidl::ToWire(fidl_arena, sensor_dev_sherlock), fidl::ToWire(fidl_arena, composite_spec)); |
| |
| if (!spec_result.ok()) { |
| zxlogf(ERROR, "%s: AddCompositeNodeSpec Camera(sensor_dev_sherlock) request failed: %s", |
| __func__, spec_result.FormatDescription().data()); |
| return spec_result.status(); |
| } |
| if (spec_result->is_error()) { |
| zxlogf(ERROR, "%s: AddCompositeNodeSpec Camera(sensor_dev_sherlock) failed: %s", __func__, |
| zx_status_get_string(spec_result->error_value())); |
| return spec_result->error_value(); |
| } |
| |
| auto bind_rules = std::vector{ |
| fdf::MakeAcceptBindRule(bind_fuchsia::PROTOCOL, |
| bind_fuchsia_camera::BIND_PROTOCOL_CAMERA_SENSOR_2), |
| }; |
| |
| auto properties = std::vector{ |
| fdf::MakeProperty(bind_fuchsia::PROTOCOL, bind_fuchsia_camera::BIND_PROTOCOL_CAMERA_SENSOR_2), |
| }; |
| |
| auto parents = std::vector{ |
| fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = bind_rules, |
| .properties = properties, |
| }}, |
| }; |
| |
| composite_spec = fuchsia_driver_framework::CompositeNodeSpec{{.name = "gdc", .parents = parents}}; |
| |
| spec_result = pbus_.buffer(arena)->AddCompositeNodeSpec(fidl::ToWire(fidl_arena, gdc_dev), |
| fidl::ToWire(fidl_arena, composite_spec)); |
| if (!spec_result.ok()) { |
| zxlogf(ERROR, "%s: AddCompositeNodeSpec Camera(gdc_dev) request failed: %s", __func__, |
| spec_result.FormatDescription().data()); |
| return spec_result.status(); |
| } |
| if (spec_result->is_error()) { |
| zxlogf(ERROR, "%s: AddCompositeNodeSpec Camera(gdc_dev) failed: %s", __func__, |
| zx_status_get_string(spec_result->error_value())); |
| return spec_result->error_value(); |
| } |
| |
| auto ge2d_sensor_node = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia::PROTOCOL, |
| bind_fuchsia_camera::BIND_PROTOCOL_CAMERA_SENSOR_2), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia::PROTOCOL, |
| bind_fuchsia_camera::BIND_PROTOCOL_CAMERA_SENSOR_2), |
| }, |
| }}; |
| |
| auto ge2d_canvas_node = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia_hardware_amlogiccanvas::SERVICE, |
| bind_fuchsia_hardware_amlogiccanvas::SERVICE_ZIRCONTRANSPORT), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia_hardware_amlogiccanvas::SERVICE, |
| bind_fuchsia_hardware_amlogiccanvas::SERVICE_ZIRCONTRANSPORT), |
| }, |
| }}; |
| |
| composite_spec = fuchsia_driver_framework::CompositeNodeSpec{{ |
| .name = "ge2d", |
| .parents = {{ge2d_sensor_node, ge2d_canvas_node}}, |
| }}; |
| |
| spec_result = pbus_.buffer(arena)->AddCompositeNodeSpec(fidl::ToWire(fidl_arena, ge2d_dev), |
| fidl::ToWire(fidl_arena, composite_spec)); |
| if (!spec_result.ok()) { |
| zxlogf(ERROR, "%s: AddCompositeNodeSpec Camera(ge2d_dev) request failed: %s", __func__, |
| spec_result.FormatDescription().data()); |
| return spec_result.status(); |
| } |
| if (spec_result->is_error()) { |
| zxlogf(ERROR, "%s: AddCompositeNodeSpec Camera(ge2d_dev) failed: %s", __func__, |
| zx_status_get_string(spec_result->error_value())); |
| return spec_result->error_value(); |
| } |
| |
| auto isp_sensor_node = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia::PROTOCOL, |
| bind_fuchsia_camera::BIND_PROTOCOL_CAMERA_SENSOR_2), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia::PROTOCOL, |
| bind_fuchsia_camera::BIND_PROTOCOL_CAMERA_SENSOR_2), |
| }, |
| }}; |
| |
| auto isp_reset_node = fuchsia_driver_framework::ParentSpec{{ |
| .bind_rules = |
| { |
| fdf::MakeAcceptBindRule(bind_fuchsia_hardware_registers::SERVICE, |
| bind_fuchsia_hardware_registers::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeAcceptBindRule(bind_fuchsia_register::NAME, |
| bind_fuchsia_amlogic_platform::NAME_REGISTER_ISP_RESET), |
| }, |
| .properties = |
| { |
| fdf::MakeProperty(bind_fuchsia_hardware_registers::SERVICE, |
| bind_fuchsia_hardware_registers::SERVICE_ZIRCONTRANSPORT), |
| fdf::MakeProperty(bind_fuchsia_register::NAME, |
| bind_fuchsia_amlogic_platform::NAME_REGISTER_ISP_RESET), |
| }, |
| }}; |
| |
| composite_spec = fuchsia_driver_framework::CompositeNodeSpec{ |
| {.name = "isp", .parents = {{isp_sensor_node, isp_reset_node}}}}; |
| |
| // Add a composite device for ARM ISP |
| spec_result = pbus_.buffer(arena)->AddCompositeNodeSpec(fidl::ToWire(fidl_arena, isp_dev), |
| fidl::ToWire(fidl_arena, composite_spec)); |
| if (!spec_result.ok()) { |
| zxlogf(ERROR, "AddCompositeNodeSpec Camera(isp_dev) request failed: %s", |
| spec_result.FormatDescription().data()); |
| return spec_result.status(); |
| } |
| if (spec_result->is_error()) { |
| zxlogf(ERROR, "AddCompositeNodeSpec Camera(isp_dev) failed: %s", |
| zx_status_get_string(spec_result->error_value())); |
| return spec_result->error_value(); |
| } |
| |
| const ddk::BindRule kIspRules[] = { |
| ddk::MakeAcceptBindRule(bind_fuchsia::PROTOCOL, bind_fuchsia_isp::BIND_PROTOCOL_DEVICE), |
| |
| }; |
| |
| const ddk::BindRule kGdcRules[] = { |
| ddk::MakeAcceptBindRule(bind_fuchsia::PROTOCOL, bind_fuchsia_camera::BIND_PROTOCOL_GDC), |
| }; |
| |
| const ddk::BindRule kGe2dRules[] = { |
| ddk::MakeAcceptBindRule(bind_fuchsia::PROTOCOL, bind_fuchsia_camera::BIND_PROTOCOL_GE2D), |
| |
| }; |
| |
| const ddk::BindRule kSysmemRules[] = { |
| ddk::MakeAcceptBindRule(bind_fuchsia_hardware_sysmem::SERVICE, |
| bind_fuchsia_hardware_sysmem::SERVICE_ZIRCONTRANSPORT), |
| |
| }; |
| |
| const device_bind_prop_t kIspProperties[] = { |
| ddk::MakeProperty(bind_fuchsia::PROTOCOL, bind_fuchsia_isp::BIND_PROTOCOL_DEVICE), |
| }; |
| |
| const device_bind_prop_t kGdcProperties[] = { |
| ddk::MakeProperty(bind_fuchsia::PROTOCOL, bind_fuchsia_camera::BIND_PROTOCOL_GDC), |
| }; |
| |
| const device_bind_prop_t kGe2dProperties[] = { |
| ddk::MakeProperty(bind_fuchsia::PROTOCOL, bind_fuchsia_camera::BIND_PROTOCOL_GE2D), |
| }; |
| |
| const device_bind_prop_t kSysmemProperties[] = { |
| ddk::MakeProperty(bind_fuchsia_hardware_sysmem::SERVICE, |
| bind_fuchsia_hardware_sysmem::SERVICE_ZIRCONTRANSPORT), |
| }; |
| |
| auto node_group = ddk::CompositeNodeSpec(kIspRules, kIspProperties) |
| .AddParentSpec(kGdcRules, kGdcProperties) |
| .AddParentSpec(kGe2dRules, kGe2dProperties) |
| .AddParentSpec(kSysmemRules, kSysmemProperties); |
| |
| zx_status_t status = DdkAddCompositeNodeSpec("camera_controller", node_group); |
| if (status != ZX_OK) { |
| zxlogf(ERROR, "%s: Camera Controller DdkAddCompositeNodeSpec failed %d", __func__, status); |
| return status; |
| } |
| |
| return status; |
| } |
| |
| } // namespace sherlock |