blob: 18e46999c6d388a3224c3592a59f1e889becf576 [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-format.h"
#define ALIGN(x, y) (((x) + (y)-1) & -(y))
namespace camera {
uint32_t DmaFormat::BytesPerPixel() {
switch (pixel_format_) {
case PixelType::A2R10G10B10:
case PixelType::RGB32:
case PixelType::GEN32:
case PixelType::AYUV:
case PixelType::Y410:
case PixelType::Y210:
return 4;
case PixelType::RGB24:
return 3;
case PixelType::RGB565:
case PixelType::RAW16:
case PixelType::YUY2:
case PixelType::UYVY:
case PixelType::RAW12:
return 2;
case PixelType::NV12:
case PixelType::YV12:
return 1;
}
return 0;
}
bool DmaFormat::HasSecondaryChannel() {
return secondary_plane_select_ > 0;
}
void DmaFormat::Set(uint32_t width, uint32_t height, PixelType pixel_format, bool vflip) {
width_ = width;
height_ = height;
flip_vertical_ = vflip;
pixel_format_ = pixel_format;
// Collapse all the YV12 and NV12 formats to their base_mode:
if (pixel_format == PixelType::NV12_YUV ||
pixel_format == PixelType::NV12_YVU ||
pixel_format == PixelType::NV12_GREY) {
pixel_format_ = PixelType::NV12;
}
if (pixel_format == PixelType::YV12_YU || pixel_format == PixelType::YV12_YV) {
pixel_format_ = PixelType::YV12;
}
// pull the plane select information into a different variable:
secondary_plane_select_ = 0;
if (pixel_format == PixelType::NV12_YVU || pixel_format == PixelType::YV12_YV) {
secondary_plane_select_ = 2;
}
if (pixel_format == PixelType::NV12_YUV || pixel_format == PixelType::YV12_YU) {
secondary_plane_select_ = 1;
}
}
uint8_t DmaFormat::GetPlaneSelectUv() {
return secondary_plane_select_;
}
// Get the value that should be written into the line_offset register.
// Note that the register expects a negative value if the frame is vertically flipped.
uint32_t DmaFormat::GetLineOffset() {
uint32_t line_offset = ALIGN(BytesPerPixel() * width_, 128);
if (flip_vertical_) {
return -line_offset;
}
return line_offset;
}
// This is added to the address of the memory we are DMAing to.
uint32_t DmaFormat::GetBank0Offset() {
if (flip_vertical_) {
uint32_t line_offset = ALIGN(BytesPerPixel() * width_, 128);
return (height_ - 1) * line_offset;
}
return 0;
}
uint32_t DmaFormat::GetBank0OffsetUv() {
// TODO(garratt): Make this actually offset to the correct place in memory
// for a buffercollection.
if (flip_vertical_) {
uint32_t line_offset = ALIGN(BytesPerPixel() * width_, 128);
if (pixel_format_ & PixelType::NV12) {
return (height_ - 2) * line_offset / 2; // UV is half the size
}
return (height_ - 1) * line_offset;
}
return 0;
}
} // namespace camera