blob: ee73a9950cc1a50a35161ce2adccdd27aa319516 [file] [log] [blame]
// 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)