/*
|
* dma_buffer.cpp - DMA Buffer Implementation
|
*
|
* Copyright (c) 2021 Rockchip Electronics Co., Ltd
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*
|
* Author: Cody Xie <cody.xie@rock-chips.com>
|
*/
|
#include "dma_buffer.h"
|
|
#include <fcntl.h>
|
#include <linux/dma-buf.h>
|
#include <sys/ioctl.h>
|
#include <sys/mman.h>
|
|
#include <cassert>
|
|
#include "xcam_log.h"
|
#include "xcam_std.h"
|
|
namespace XCam {
|
|
DmaBuffer::DmaBuffer(int fd, size_t size) : fd_(fd), size_(size), ptr_(nullptr) {}
|
|
DmaBuffer::~DmaBuffer() {
|
if (ptr_ != nullptr) {
|
unmap();
|
}
|
}
|
|
XCamReturn DmaBuffer::sync(int fd, DmaBufferDirection direction, bool start) {
|
int ret;
|
struct dma_buf_sync sync = {0};
|
|
XCAM_ASSERT(fd >= 0);
|
|
if (direction == DmaBufferDirection::kDeviceToCPU) {
|
sync.flags = DMA_BUF_SYNC_READ;
|
} else if (direction == DmaBufferDirection::kCPUToDevice) {
|
sync.flags = DMA_BUF_SYNC_WRITE;
|
} else {
|
sync.flags = DMA_BUF_SYNC_RW;
|
}
|
|
if (start) {
|
sync.flags |= DMA_BUF_SYNC_START;
|
} else {
|
sync.flags |= DMA_BUF_SYNC_END;
|
}
|
|
ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync);
|
if (ret) {
|
LOGE("DMA_BUF_IOCTL_SYNC ioctl failed %s", strerror(errno));
|
return XCAM_RETURN_ERROR_IOCTL;
|
}
|
|
LOGI("%s CPU access dir %d for BO fd %d", start ? "start" : "end", direction, fd);
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn DmaBuffer::beginCpuAccess(DmaBufferDirection direction) {
|
XCAM_ASSERT(ptr_ != nullptr);
|
return sync(fd_.Get(), direction, true);
|
}
|
|
XCamReturn DmaBuffer::endCpuAccess(DmaBufferDirection direction) {
|
XCAM_ASSERT(ptr_ != nullptr);
|
return sync(fd_.Get(), direction, false);
|
}
|
|
void* DmaBuffer::map() {
|
int ret;
|
|
assert(((void)"could not map invalid dma_buf", fd_.Get() > 0 && ptr_ == nullptr && size_ > 0));
|
|
ptr_ = mmap(0, size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_.Get(), 0);
|
if (ptr_ == MAP_FAILED) {
|
LOGE("dma_buf map failed %s", strerror(errno));
|
return nullptr;
|
}
|
|
return ptr_;
|
}
|
|
void DmaBuffer::unmap() {
|
assert(((void)"unmap dma_buf in wrong state", fd_.Get() > 0 && ptr_ != nullptr));
|
|
munmap(ptr_, size_);
|
ptr_ = nullptr;
|
}
|
|
int DmaBuffer::getFd() { return fd_.Get(); }
|
|
size_t DmaBuffer::getSize() { return size_; }
|
|
int DmaBuffer::release() { return fd_.Release(); }
|
|
bool DmaBuffer::mapped() { return ptr_ == nullptr ? false : true; }
|
|
} // namespace XCam
|