blob: 8779304219deab82a9e27ae53979aab875023483 [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.
#ifndef SRC_CAMERA_DRIVERS_ISP_MALI_009_ARM_ISP_H_
#define SRC_CAMERA_DRIVERS_ISP_MALI_009_ARM_ISP_H_
#include <fuchsia/hardware/camera/c/fidl.h>
#include <lib/device-protocol/pdev.h>
#include <lib/device-protocol/platform-device.h>
#include <lib/fidl-utils/bind.h>
#include <lib/fit/function.h>
#include <lib/sync/completion.h>
#include <lib/zx/interrupt.h>
#include <atomic>
#include <ddk/metadata/camera.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/platform/bus.h>
#include <ddk/protocol/platform/device.h>
#include <ddktl/device.h>
#include <ddktl/protocol/composite.h>
#include <ddktl/protocol/isp.h>
#include <fbl/mutex.h>
#include <fbl/unique_ptr.h>
#include <hw/reg.h>
#include "../modules/dma-mgr.h"
#include "../modules/gamma-rgb-registers.h"
#include "../modules/stats-mgr.h"
#include "arm-isp-test.h"
#include "global_regs.h"
#include "pingpong_regs.h"
#ifndef _ALL_SOURCE
#define _ALL_SOURCE // Enables thrd_create_with_name in <threads.h>.
#endif
#include <threads.h>
#include <zircon/fidl.h>
namespace camera {
namespace {
// TODO(CAM-87): Formalize isp sub-block start address style.
constexpr uint32_t kGammaRgbPingFrAddr = 0x1c064;
constexpr uint32_t kGammaRgbPingDsAddr = 0x1c1d8;
} // namespace
// |ArmIspDevice| is spawned by the driver in |arm-isp.cc|
// This provides the interface provided in camera.fidl in Zircon.
class ArmIspDevice;
using IspDeviceType = ddk::Device<ArmIspDevice, ddk::Unbindable>;
class ArmIspDevice : public IspDeviceType,
public ddk::IspProtocol<ArmIspDevice, ddk::base_protocol> {
public:
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ArmIspDevice);
explicit ArmIspDevice(zx_device_t* parent, ddk ::MmioBuffer hiu_mmio, ddk ::MmioBuffer power_mmio,
ddk ::MmioBuffer memory_pd_mmio, ddk ::MmioBuffer reset_mmio,
ddk ::MmioBuffer isp_mmio, mmio_buffer_t local_mmio, zx::interrupt isp_irq,
zx::bti bti, zx_device_t* camera_sensor)
: IspDeviceType(parent),
pdev_(parent),
hiu_mmio_(std::move(hiu_mmio)),
power_mmio_(std::move(power_mmio)),
memory_pd_mmio_(std::move(memory_pd_mmio)),
reset_mmio_(std::move(reset_mmio)),
isp_mmio_(std::move(isp_mmio)),
isp_mmio_local_(local_mmio, 0),
isp_irq_(std::move(isp_irq)),
bti_(std::move(bti)),
camera_sensor_(camera_sensor),
gamma_rgb_fr_regs_(ddk::MmioView(local_mmio, kGammaRgbPingFrAddr)),
gamma_rgb_ds_regs_(ddk::MmioView(local_mmio, kGammaRgbPingDsAddr)) {}
~ArmIspDevice();
static zx_status_t Init(void** ctx_out);
static zx_status_t Create(void* ctx, zx_device_t* parent);
// Methods required by the ddk.
void DdkRelease();
void DdkUnbind();
// +++++++++ ZX_PROTOCOL_ISP +++++++++++++++++++++++
// This is the interface that is used by the Camera Controller
// to set the format for the ISP output streams, provide buffers
// for the frames that the ISP writes to, and establishes a control and
// response interface between the camera controller and the ISP.
// |buffer_collection| : Hold the format and pool of VMOs that the ISP will
// produce
// |stream| : The protocol which calls a function when the ISP is done
// writing to a buffer.
// |rate| : The frame rate of the output
// |type| : The stream type (full resolution or downscaled)
// |out_s| : (output) Protocol over which the flow of frames is controlled.
// @Return : indicates if the stream was created.
zx_status_t IspCreateOutputStream(const buffer_collection_info_t* buffer_collection,
const frame_rate_t* rate, stream_type_t type,
const output_stream_callback_t* stream,
output_stream_protocol_t* out_s);
// Functions to service the output_stream_protocol interface:
// Releases a frame that was being used by a consumer
// |buffer_id| : the buffer_id that was sent with FrameReady
// |type| : Either STREAM_TYPE_FULL_RESOLUTION or STREAM_TYPE_DOWNSCALED
// @Return : indicates if the frame was released.
zx_status_t ReleaseFrame(uint32_t buffer_id, stream_type_t type);
// Starts streaming one of the stream types.
// |type| : Either STREAM_TYPE_FULL_RESOLUTION or STREAM_TYPE_DOWNSCALED
// @Return : indicates if the stream was started.
zx_status_t StartStream(stream_type_t type);
// Stops streaming one of the stream types.
// |type| : Either STREAM_TYPE_FULL_RESOLUTION or STREAM_TYPE_DOWNSCALED
// @Return : indicates if the stream was stopped.
zx_status_t StopStream(stream_type_t type);
// --------------- End ZX_PROTOCOL_ISP ---------------
// ISP Init Sequences (init_sequences.cc)
void IspLoadSeq_linear();
void IspLoadSeq_settings();
void IspLoadSeq_fs_lin_2exp();
void IspLoadSeq_fs_lin_3exp();
void IspLoadSeq_fs_lin_4exp();
void IspLoadSeq_settings_context();
void IspLoadCustomSequence();
bool IsIspConfigInitialized() { return initialized_; }
private:
zx_status_t InitIsp();
zx_status_t IspContextInit();
// A skeleton function for testing the ISP with the ISPDeviceTester:
zx_status_t RunTests() { return ZX_OK; }
void ShutDown();
void PowerUpIsp();
void IspHWReset(bool reset);
int IspIrqHandler();
void HandleDmaError();
zx_status_t ErrorRoutine();
void CopyContextInfo(uint8_t config_space, uint8_t direction);
void CopyMeteringInfo(uint8_t config_space);
zx_status_t SetPort(uint8_t kMode);
bool IsFrameProcessingInProgress();
zx_status_t SetupIspConfig();
zx_status_t StartStreaming();
zx_status_t StopStreaming();
// Get the DMA Manager associated with stream type |type|.
DmaManager* GetStream(stream_type_t type);
// Functions used by the debugging / testing interface:
// Returns all the current registers written into a struct for analysis.
ArmIspRegisterDump DumpRegisters();
ddk::PDev pdev_;
ddk::MmioBuffer hiu_mmio_;
ddk::MmioBuffer power_mmio_;
ddk::MmioBuffer memory_pd_mmio_;
ddk::MmioBuffer reset_mmio_;
ddk::MmioBuffer isp_mmio_;
// MmioView is currently used and created using a custom mmio_buffer_t
// populated with malloced memory.
// We can switch to using the actual mmio_buffer_t
// when we plan to use SW-HW context, in order to make a easy switch.
ddk::MmioView isp_mmio_local_;
zx::interrupt isp_irq_;
thrd_t irq_thread_;
zx::bti bti_;
std::atomic<bool> running_;
bool initialized_ = false;
// Thread for processing work for each frame.
int FrameProcessingThread();
thrd_t frame_processing_thread_;
std::atomic<bool> running_frame_processing_;
// Some work upon a NewFrame signal is for dealing with previous frame data.
// We should stop using this variable when we handle other signals.
bool first_frame_ = true;
ddk::CameraSensorProtocolClient camera_sensor_;
fbl::unique_ptr<camera::StatsManager> statsMgr_;
fbl::unique_ptr<camera::DmaManager> full_resolution_dma_;
fbl::unique_ptr<camera::DmaManager> downscaled_dma_;
bool streaming_ = false;
// TODO(CAM-88): Formalize isp sub-block ownership.
GammaRgbRegisters gamma_rgb_fr_regs_;
GammaRgbRegisters gamma_rgb_ds_regs_;
sync_completion_t frame_processing_signal_;
// Callback to call when calling DdkUnbind,
// so the ArmIspDeviceTester (if it exists) stops interfacing
// with this class.
fit::callback<void()> on_isp_unbind_;
// This lock prevents this class from being unbound while it's child is being
// set up:
fbl::Mutex unbind_lock_;
friend class ArmIspDeviceTester;
};
} // namespace camera
#endif // SRC_CAMERA_DRIVERS_ISP_MALI_009_ARM_ISP_H_