| // 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. |
| |
| #ifndef SRC_CAMERA_DRIVERS_HW_ACCEL_GE2D_GE2D_H_ |
| #define SRC_CAMERA_DRIVERS_HW_ACCEL_GE2D_GE2D_H_ |
| |
| #include <lib/ddk/platform-defs.h> |
| #ifndef _ALL_SOURCE |
| #define _ALL_SOURCE // Enables thrd_create_with_name in <threads.h>. |
| #include <threads.h> |
| #endif |
| #include <fuchsia/hardware/amlogiccanvas/cpp/banjo.h> |
| #include <fuchsia/hardware/platform/bus/c/banjo.h> |
| #include <fuchsia/hardware/platform/device/c/banjo.h> |
| #include <lib/device-protocol/pdev.h> |
| #include <lib/device-protocol/platform-device.h> |
| #include <lib/mmio/mmio.h> |
| #include <lib/zx/event.h> |
| #include <lib/zx/interrupt.h> |
| #include <zircon/fidl.h> |
| |
| #include <atomic> |
| #include <deque> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include <ddktl/device.h> |
| #include <fbl/auto_lock.h> |
| #include <fbl/condition_variable.h> |
| #include <fbl/mutex.h> |
| |
| #include "src/camera/drivers/hw_accel/ge2d/ge2d_task.h" |
| |
| namespace ge2d { |
| // |Ge2dDevice| is spawned by the driver in |ge2d.cc| |
| namespace { |
| |
| constexpr uint64_t kPortKeyIrqMsg = 0x00; |
| constexpr uint64_t kPortKeyDebugFakeInterrupt = 0x01; |
| |
| // Expected maximum size (in bytes) of the watermark image. |
| constexpr uint32_t kWatermarkMaxSize = 144 * 84 * 4; |
| |
| // Expected count of input watermark buffers (one for each supported watermark image resolution). |
| constexpr uint32_t kWatermarkInputBufferCount = 3; |
| |
| } // namespace |
| |
| // This provides ZX_PROTOCOL_GE2D. |
| class Ge2dDevice; |
| using Ge2dDeviceType = ddk::Device<Ge2dDevice, ddk::Unbindable>; |
| |
| class Ge2dDevice : public Ge2dDeviceType, public ddk::Ge2dProtocol<Ge2dDevice, ddk::base_protocol> { |
| public: |
| DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Ge2dDevice); |
| explicit Ge2dDevice(zx_device_t* parent, fdf::MmioBuffer ge2d_mmio, zx::interrupt ge2d_irq, |
| zx::bti bti, zx::port port, |
| std::vector<zx::vmo> watermark_input_contiguous_vmos, |
| zx::vmo watermark_blended_contiguous_vmo, amlogic_canvas_protocol_t canvas) |
| : Ge2dDeviceType(parent), |
| port_(std::move(port)), |
| ge2d_mmio_(std::move(ge2d_mmio)), |
| ge2d_irq_(std::move(ge2d_irq)), |
| bti_(std::move(bti)), |
| watermark_input_contiguous_vmos_(std::move(watermark_input_contiguous_vmos)), |
| watermark_blended_contiguous_vmo_(std::move(watermark_blended_contiguous_vmo)), |
| canvas_(canvas) {} |
| |
| // Setup() is used to create an instance of Ge2dDevice. |
| static zx_status_t Setup(zx_device_t* parent, std::unique_ptr<Ge2dDevice>* out); |
| |
| // Methods required by the ddk. |
| void DdkRelease(); |
| void DdkUnbind(ddk::UnbindTxn txn); |
| |
| // ZX_PROTOCOL_GE2DC (Refer to ge2d.banjo for documentation). |
| zx_status_t Ge2dInitTaskResize(const buffer_collection_info_2_t* input_buffer_collection, |
| const buffer_collection_info_2_t* output_buffer_collection, |
| const resize_info_t* info, |
| const image_format_2_t* input_image_format, |
| const image_format_2_t* output_image_format_table_list, |
| size_t output_image_format_table_count, |
| uint32_t output_image_format_index, |
| const hw_accel_frame_callback_t* frame_callback, |
| const hw_accel_res_change_callback_t* res_callback, |
| const hw_accel_remove_task_callback_t* task_remove_callback, |
| uint32_t* out_task_index); |
| |
| // See ge2d_task.h for description of args. |
| zx_status_t Ge2dInitTaskWaterMark(const buffer_collection_info_2_t* input_buffer_collection, |
| const buffer_collection_info_2_t* output_buffer_collection, |
| const water_mark_info_t* info_list, size_t info_count, |
| const image_format_2_t* image_format_table_list, |
| size_t image_format_table_count, uint32_t image_format_index, |
| const hw_accel_frame_callback_t* frame_callback, |
| const hw_accel_res_change_callback_t* res_callback, |
| const hw_accel_remove_task_callback_t* task_remove_callback, |
| uint32_t* out_task_index); |
| |
| // See ge2d_task.h for description of args. |
| zx_status_t Ge2dInitTaskInPlaceWaterMark( |
| const buffer_collection_info_2_t* buffer_collection, const water_mark_info_t* info_list, |
| size_t info_count, const image_format_2_t* image_format_table_list, |
| size_t image_format_table_count, uint32_t image_format_index, |
| const hw_accel_frame_callback_t* frame_callback, |
| const hw_accel_res_change_callback_t* res_callback, |
| const hw_accel_remove_task_callback_t* task_remove_callback, uint32_t* out_task_index); |
| |
| zx_status_t Ge2dProcessFrame(uint32_t task_index, uint32_t input_buffer_index, |
| uint64_t capture_timestamp); |
| void Ge2dRemoveTask(uint32_t task_index); |
| void Ge2dReleaseFrame(uint32_t task_index, uint32_t buffer_index); |
| |
| // Note that this is only supported on Watermark Tasks. The new format applies to both |
| // input AND output formats. |
| zx_status_t Ge2dSetInputAndOutputResolution(uint32_t task_index, uint32_t new_image_format_index); |
| |
| // Note that this is only supported on Resize Tasks. |
| zx_status_t Ge2dSetOutputResolution(uint32_t task_index, uint32_t new_output_image_format_index); |
| |
| void Ge2dSetCropRect(uint32_t task_index, const rect_t* crop); |
| |
| // Used for unit tests. |
| const fdf::MmioBuffer* ge2d_mmio() const { return &ge2d_mmio_; } |
| zx_status_t StartThread(); |
| zx_status_t StopThread(); |
| const zx::bti& bti() const { return bti_; } |
| amlogic_canvas_protocol_t canvas() const { return canvas_; } |
| |
| protected: |
| enum Ge2dOp { |
| GE2D_OP_SETOUTPUTRES, |
| GE2D_OP_SETINPUTOUTPUTRES, |
| GE2D_OP_FRAME, |
| GE2D_OP_SETCROPRECT, |
| GE2D_OP_REMOVETASK, |
| }; |
| |
| struct TaskInfo { |
| Ge2dOp op; |
| Ge2dTask* task; |
| uint32_t index; |
| rect_t crop_rect; |
| uint32_t task_index; |
| uint64_t capture_timestamp = 0; |
| }; |
| |
| zx::port port_; |
| |
| private: |
| friend class Ge2dDeviceTester; |
| |
| // All necessary clean up is done here in ShutDown(). |
| void ShutDown(); |
| int FrameProcessingThread(); |
| int JoinThread() { return thrd_join(processing_thread_, nullptr); } |
| |
| void InitializeScalingCoefficients(); |
| void InitializeScaler(uint32_t input_width, uint32_t input_height, uint32_t output_width, |
| uint32_t output_height); |
| void ProcessSetCropRect(TaskInfo& info); |
| void ProcessTask(TaskInfo& info); |
| void ProcessChangeResolution(TaskInfo& info); |
| void ProcessFrame(TaskInfo& info); |
| void ProcessRemoveTask(TaskInfo& info); |
| void SetupInputOutputFormats(bool scaling_enabled, const image_format_2_t& input_format, |
| const image_format_2_t& output_format, |
| const image_format_2_t& src2_format = {}); |
| void SetInputRect(const rect_t& rect); |
| void SetOutputRect(const rect_t& rect); |
| void SetSrc2InputRect(const rect_t& rect); |
| void SetRects(const rect_t& input_rect, const rect_t& output_rect); |
| void SetBlending(bool enable); |
| zx_status_t WaitForInterrupt(zx_port_packet_t* packet); |
| void ProcessAndWaitForIdle(); |
| void SetSrc1Input(const image_canvas_id_t& canvas); |
| void SetSrc2Input(const image_canvas_id_t& canvas); |
| void SetDstOutput(const image_canvas_id_t& canvas); |
| void ProcessResizeTask(Ge2dTask* task, uint32_t input_buffer_index, |
| const fzl::VmoPool::Buffer& output_buffer); |
| void ProcessWatermarkTask(Ge2dTask* task, uint32_t input_buffer_index, |
| const fzl::VmoPool::Buffer& output_buffer); |
| void ProcessInPlaceWatermarkTask(Ge2dTask* task, uint32_t input_buffer_index); |
| |
| // Used to access the processing queue. |
| fbl::Mutex lock_; |
| // Used to access the GE2D's banjo interface. |
| fbl::Mutex interface_lock_; |
| |
| fdf::MmioBuffer ge2d_mmio_; |
| zx::interrupt ge2d_irq_; |
| zx::bti bti_; |
| |
| // Vector of VMOs to hold watermark image data in contiguous memory. |
| std::vector<zx::vmo> watermark_input_contiguous_vmos_; |
| |
| // VMO to hold blended watermark image in contiguous memory. |
| zx::vmo watermark_blended_contiguous_vmo_; |
| |
| uint32_t next_task_index_ __TA_GUARDED(interface_lock_) = 0; |
| std::unordered_map<uint32_t, std::unique_ptr<Ge2dTask>> task_map_ __TA_GUARDED(interface_lock_); |
| std::deque<TaskInfo> processing_queue_ __TA_GUARDED(lock_); |
| thrd_t processing_thread_; |
| fbl::ConditionVariable frame_processing_signal_ __TA_GUARDED(lock_); |
| bool shutdown_ __TA_GUARDED(lock_) = false; |
| amlogic_canvas_protocol_t canvas_ = {}; |
| }; |
| } // namespace ge2d |
| |
| #endif // SRC_CAMERA_DRIVERS_HW_ACCEL_GE2D_GE2D_H_ |