blob: 0cf84b610a21719582dea044b1044a3f28ddb4ea [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 "dma-mgr.h"
#include "../pingpong_regs.h"
#include "dma-format.h"
#include <cstdint>
namespace camera {
auto DmaManager::GetPrimaryMisc() {
if (ping_reg_block_) {
if (downscaled_) {
return ping::DownScaled::Primary::DmaWriter_Misc::Get();
} else {
return ping::FullResolution::Primary::DmaWriter_Misc::Get();
}
} else {
if (downscaled_) {
return pong::DownScaled::Primary::DmaWriter_Misc::Get();
} else {
return pong::FullResolution::Primary::DmaWriter_Misc::Get();
}
}
}
auto DmaManager::GetUvMisc() {
if (ping_reg_block_) {
if (downscaled_) {
return ping::DownScaled::Uv::DmaWriter_Misc::Get();
} else {
return ping::FullResolution::Uv::DmaWriter_Misc::Get();
}
} else {
if (downscaled_) {
return pong::DownScaled::Uv::DmaWriter_Misc::Get();
} else {
return pong::FullResolution::Uv::DmaWriter_Misc::Get();
}
}
}
auto DmaManager::GetPrimaryBank0() {
if (ping_reg_block_) {
if (downscaled_) {
return ping::DownScaled::Primary::DmaWriter_Bank0Base::Get();
} else {
return ping::FullResolution::Primary::DmaWriter_Bank0Base::Get();
}
} else {
if (downscaled_) {
return pong::DownScaled::Primary::DmaWriter_Bank0Base::Get();
} else {
return pong::FullResolution::Primary::DmaWriter_Bank0Base::Get();
}
}
}
auto DmaManager::GetUvBank0() {
if (ping_reg_block_) {
if (downscaled_) {
return ping::DownScaled::Uv::DmaWriter_Bank0Base::Get();
} else {
return ping::FullResolution::Uv::DmaWriter_Bank0Base::Get();
}
} else {
if (downscaled_) {
return pong::DownScaled::Uv::DmaWriter_Bank0Base::Get();
} else {
return pong::FullResolution::Uv::DmaWriter_Bank0Base::Get();
}
}
}
auto DmaManager::GetPrimaryLineOffset() {
if (ping_reg_block_) {
if (downscaled_) {
return ping::DownScaled::Primary::DmaWriter_LineOffset::Get();
} else {
return ping::FullResolution::Primary::DmaWriter_LineOffset::Get();
}
} else {
if (downscaled_) {
return pong::DownScaled::Primary::DmaWriter_LineOffset::Get();
} else {
return pong::FullResolution::Primary::DmaWriter_LineOffset::Get();
}
}
}
auto DmaManager::GetUvLineOffset() {
if (ping_reg_block_) {
if (downscaled_) {
return ping::DownScaled::Uv::DmaWriter_LineOffset::Get();
} else {
return ping::FullResolution::Uv::DmaWriter_LineOffset::Get();
}
} else {
if (downscaled_) {
return pong::DownScaled::Uv::DmaWriter_LineOffset::Get();
} else {
return pong::FullResolution::Uv::DmaWriter_LineOffset::Get();
}
}
}
auto DmaManager::GetPrimaryActiveDim() {
if (ping_reg_block_) {
if (downscaled_) {
return ping::DownScaled::Primary::DmaWriter_ActiveDim::Get();
} else {
return ping::FullResolution::Primary::DmaWriter_ActiveDim::Get();
}
} else {
if (downscaled_) {
return pong::DownScaled::Primary::DmaWriter_ActiveDim::Get();
} else {
return pong::FullResolution::Primary::DmaWriter_ActiveDim::Get();
}
}
}
auto DmaManager::GetUvActiveDim() {
if (ping_reg_block_) {
if (downscaled_) {
return ping::DownScaled::Uv::DmaWriter_ActiveDim::Get();
} else {
return ping::FullResolution::Uv::DmaWriter_ActiveDim::Get();
}
} else {
if (downscaled_) {
return pong::DownScaled::Uv::DmaWriter_ActiveDim::Get();
} else {
return pong::FullResolution::Uv::DmaWriter_ActiveDim::Get();
}
}
}
// Called as one of the later steps when a new frame arrives.
void DmaManager::OnNewFrame() {
// 1) Publish last frame
if (buffers_.HasBufferInProgress()) {
uint32_t buffer_index;
buffers_.BufferCompleted(&buffer_index);
if (publish_buffer_callback_) {
publish_buffer_callback_(buffer_index);
}
}
// 2) Get another buffer
buffers_.GetNewBuffer();
// 3) Optional? Set the DMA settings again... seems unnecessary
// 4) Set the DMA address
uint32_t memory_address = static_cast<uint32_t>(
reinterpret_cast<uintptr_t>(buffers_.CurrentBufferAddress()));
GetPrimaryBank0().FromValue(0)
.set_value(memory_address + current_format_.GetBank0Offset())
.WriteTo(isp_mmio_);
if (current_format_.HasSecondaryChannel()) {
GetUvBank0().FromValue(0)
.set_value(memory_address + current_format_.GetBank0OffsetUv())
.WriteTo(isp_mmio_);
}
// 5) Optional? Enable Write_on
GetPrimaryMisc().ReadFrom(isp_mmio_).set_frame_write_on(1).WriteTo(isp_mmio_);
if (current_format_.HasSecondaryChannel()) {
GetUvMisc().ReadFrom(isp_mmio_).set_frame_write_on(1).WriteTo(isp_mmio_);
}
}
void DmaManager::ReleaseFrame(uint32_t buffer_index) {
buffers_.BufferRelease(buffer_index);
}
void DmaManager::SetFormat(DmaFormat format) {
current_format_ = format;
// Write format to registers
GetPrimaryMisc().ReadFrom(isp_mmio_)
.set_base_mode(format.GetBaseMode())
.set_plane_select(format.GetPlaneSelect())
.WriteTo(isp_mmio_);
GetPrimaryActiveDim().ReadFrom(isp_mmio_)
.set_active_width(format.width_)
.set_active_height(format.height_)
.WriteTo(isp_mmio_);
GetPrimaryLineOffset().ReadFrom(isp_mmio_)
.set_value(format.GetLineOffset())
.WriteTo(isp_mmio_);
if (format.HasSecondaryChannel()) {
// TODO: should there be a format.WidthUv() ?
GetUvMisc().ReadFrom(isp_mmio_)
.set_base_mode(format.GetBaseMode())
.set_plane_select(format.GetPlaneSelect())
.WriteTo(isp_mmio_);
GetUvActiveDim().ReadFrom(isp_mmio_)
.set_active_width(format.width_)
.set_active_height(format.height_)
.WriteTo(isp_mmio_);
GetUvLineOffset().ReadFrom(isp_mmio_)
.set_value(format.GetLineOffset())
.WriteTo(isp_mmio_);
}
}
} // namespace camera