blob: 4b01d183da234d8de9036fec5d75c36960a5c3f6 [file] [log] [blame]
// Copyright 2024 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 "src/graphics/display/drivers/amlogic-display/display-device-driver-dfv2.h"
#include <fidl/fuchsia.driver.framework/cpp/wire.h>
#include <fidl/fuchsia.hardware.platform.device/cpp/wire.h>
#include <lib/ddk/driver.h>
#include <lib/driver/compat/cpp/banjo_server.h>
#include <lib/driver/compat/cpp/device_server.h>
#include <lib/driver/compat/cpp/logging.h>
#include <lib/driver/component/cpp/driver_export.h>
#include <lib/driver/component/cpp/node_add_args.h>
#include <lib/driver/outgoing/cpp/outgoing_directory.h>
#include <lib/inspect/component/cpp/component.h>
#include <lib/inspect/cpp/inspector.h>
#include <lib/mmio/mmio-buffer.h>
#include <lib/zx/bti.h>
#include <lib/zx/result.h>
#include <zircon/assert.h>
#include <zircon/status.h>
#include <cinttypes>
#include <cstdint>
#include <memory>
#include <bind/fuchsia/cpp/bind.h>
#include <bind/fuchsia/display/cpp/bind.h>
#include <fbl/alloc_checker.h>
#include "fidl/fuchsia.driver.framework/cpp/natural_types.h"
#include "src/graphics/display/drivers/amlogic-display/display-engine.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/dispatcher/dispatcher-factory.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/dispatcher/driver-runtime-backed-dispatcher-factory.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/metadata/metadata-getter-dfv2.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/metadata/metadata-getter.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/namespace/namespace-dfv2.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/namespace/namespace.h"
namespace amlogic_display {
DisplayDeviceDriverDfv2::DisplayDeviceDriverDfv2(
fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
: fdf::DriverBase("amlogic-display", std::move(start_args), std::move(driver_dispatcher)) {}
void DisplayDeviceDriverDfv2::Stop() {}
zx::result<std::unique_ptr<inspect::ComponentInspector>>
DisplayDeviceDriverDfv2::CreateComponentInspector(inspect::Inspector inspector) {
zx::result<fidl::ClientEnd<fuchsia_inspect::InspectSink>> inspect_sink_connect_result =
incoming()->Connect<fuchsia_inspect::InspectSink>();
if (inspect_sink_connect_result.is_error()) {
FDF_LOG(ERROR, "Failed to connect to InspectSink protocol: %s",
inspect_sink_connect_result.status_string());
return inspect_sink_connect_result.take_error();
}
fbl::AllocChecker alloc_checker;
auto component_inspector = fbl::make_unique_checked<inspect::ComponentInspector>(
&alloc_checker, fdf::Dispatcher::GetCurrent()->async_dispatcher(),
inspect::PublishOptions{.inspector = std::move(inspector),
.client_end = std::move(inspect_sink_connect_result).value()});
if (!alloc_checker.check()) {
FDF_LOG(ERROR, "Failed to allocate memory for ComponentInspector");
return zx::error(ZX_ERR_NO_MEMORY);
}
return zx::ok(std::move(component_inspector));
}
zx::result<DisplayDeviceDriverDfv2::DriverFrameworkMigrationUtils>
DisplayDeviceDriverDfv2::CreateDriverFrameworkMigrationUtils() {
zx::result<std::unique_ptr<display::Namespace>> create_namespace_result =
display::NamespaceDfv2::Create(incoming().get());
if (create_namespace_result.is_error()) {
FDF_LOG(ERROR, "Failed to create incoming Namespace: %s",
create_namespace_result.status_string());
return create_namespace_result.take_error();
}
std::unique_ptr<display::Namespace> incoming_namespace =
std::move(create_namespace_result).value();
zx::result<std::unique_ptr<display::MetadataGetter>> create_metadata_getter_result =
display::MetadataGetterDfv2::Create(incoming());
if (create_metadata_getter_result.is_error()) {
FDF_LOG(ERROR, "Failed to create Metadata getter: %s",
create_metadata_getter_result.status_string());
return create_metadata_getter_result.take_error();
}
std::unique_ptr<display::MetadataGetter> metadata_getter =
std::move(create_metadata_getter_result).value();
zx::result<std::unique_ptr<display::DispatcherFactory>> create_dispatcher_factory_result =
display::DriverRuntimeBackedDispatcherFactory::Create();
if (create_dispatcher_factory_result.is_error()) {
FDF_LOG(ERROR, "Failed to create Dispatcher factory: %s",
create_dispatcher_factory_result.status_string());
return create_dispatcher_factory_result.take_error();
}
std::unique_ptr<display::DispatcherFactory> dispatcher_factory =
std::move(create_dispatcher_factory_result).value();
return zx::ok(DriverFrameworkMigrationUtils{
.incoming = std::move(incoming_namespace),
.metadata_getter = std::move(metadata_getter),
.dispatcher_factory = std::move(dispatcher_factory),
});
}
zx::result<> DisplayDeviceDriverDfv2::Start() {
zx::result<DisplayDeviceDriverDfv2::DriverFrameworkMigrationUtils>
create_driver_framework_migration_utils_result = CreateDriverFrameworkMigrationUtils();
if (create_driver_framework_migration_utils_result.is_error()) {
FDF_LOG(ERROR, "Failed to create driver framework migration utilities: %s",
create_driver_framework_migration_utils_result.status_string());
return create_driver_framework_migration_utils_result.take_error();
}
driver_framework_migration_utils_ =
std::move(create_driver_framework_migration_utils_result).value();
zx::result<std::unique_ptr<DisplayEngine>> create_display_engine_result =
DisplayEngine::Create(driver_framework_migration_utils_.incoming.get(),
driver_framework_migration_utils_.metadata_getter.get(),
driver_framework_migration_utils_.dispatcher_factory.get());
if (create_display_engine_result.is_error()) {
FDF_LOG(ERROR, "Failed to create DisplayEngine: %s",
create_display_engine_result.status_string());
return create_display_engine_result.take_error();
}
display_engine_ = std::move(create_display_engine_result).value();
zx::result<std::unique_ptr<inspect::ComponentInspector>> inspector_result =
CreateComponentInspector(display_engine_->inspector());
if (inspector_result.is_error()) {
FDF_LOG(ERROR, "Failed to create component inspector: %s", inspector_result.status_string());
return inspector_result.take_error();
}
component_inspector_ = std::move(inspector_result).value();
// Serves the [`fuchsia.hardware.display.controller/ControllerImpl`] protocol
// over the compatibility server.
banjo_server_ =
compat::BanjoServer(ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL, /*ctx=*/display_engine_.get(),
/*ops=*/display_engine_->display_controller_impl_protocol_ops());
compat::DeviceServer::BanjoConfig banjo_config;
banjo_config.callbacks[ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL] = banjo_server_->callback();
zx::result<> compat_server_init_result =
compat_server_.Initialize(incoming(), outgoing(), node_name(), name(),
/*forward_metadata=*/compat::ForwardMetadata::None(),
/*banjo_config=*/std::move(banjo_config));
if (compat_server_init_result.is_error()) {
return compat_server_init_result.take_error();
}
const std::vector<fuchsia_driver_framework::NodeProperty> node_properties = {
fdf::MakeProperty(bind_fuchsia::PROTOCOL,
bind_fuchsia_display::BIND_PROTOCOL_CONTROLLER_IMPL),
};
const std::vector<fuchsia_driver_framework::Offer> node_offers = compat_server_.CreateOffers2();
zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>> controller_client_result =
AddChild(name(), node_properties, node_offers);
if (controller_client_result.is_error()) {
FDF_LOG(ERROR, "Failed to add child node: %s", controller_client_result.status_string());
return controller_client_result.take_error();
}
controller_ = fidl::WireSyncClient(std::move(controller_client_result).value());
return zx::ok();
}
} // namespace amlogic_display
FUCHSIA_DRIVER_EXPORT(amlogic_display::DisplayDeviceDriverDfv2);