1 /*
2 * dma_buffer.cpp - DMA Buffer Implementation
3 *
4 * Copyright (c) 2021 Rockchip Electronics Co., Ltd
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Cody Xie <cody.xie@rock-chips.com>
19 */
20 #include "dma_buffer.h"
21
22 #include <fcntl.h>
23 #include <linux/dma-buf.h>
24 #include <sys/ioctl.h>
25 #include <sys/mman.h>
26
27 #include <cassert>
28
29 #include "xcam_log.h"
30 #include "xcam_std.h"
31
32 namespace XCam {
33
DmaBuffer(int fd,size_t size)34 DmaBuffer::DmaBuffer(int fd, size_t size) : fd_(fd), size_(size), ptr_(nullptr) {}
35
~DmaBuffer()36 DmaBuffer::~DmaBuffer() {
37 if (ptr_ != nullptr) {
38 unmap();
39 }
40 }
41
sync(int fd,DmaBufferDirection direction,bool start)42 XCamReturn DmaBuffer::sync(int fd, DmaBufferDirection direction, bool start) {
43 int ret;
44 struct dma_buf_sync sync = {0};
45
46 XCAM_ASSERT(fd >= 0);
47
48 if (direction == DmaBufferDirection::kDeviceToCPU) {
49 sync.flags = DMA_BUF_SYNC_READ;
50 } else if (direction == DmaBufferDirection::kCPUToDevice) {
51 sync.flags = DMA_BUF_SYNC_WRITE;
52 } else {
53 sync.flags = DMA_BUF_SYNC_RW;
54 }
55
56 if (start) {
57 sync.flags |= DMA_BUF_SYNC_START;
58 } else {
59 sync.flags |= DMA_BUF_SYNC_END;
60 }
61
62 ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync);
63 if (ret) {
64 LOGE("DMA_BUF_IOCTL_SYNC ioctl failed %s", strerror(errno));
65 return XCAM_RETURN_ERROR_IOCTL;
66 }
67
68 LOGI("%s CPU access dir %d for BO fd %d", start ? "start" : "end", direction, fd);
69 return XCAM_RETURN_NO_ERROR;
70 }
71
beginCpuAccess(DmaBufferDirection direction)72 XCamReturn DmaBuffer::beginCpuAccess(DmaBufferDirection direction) {
73 XCAM_ASSERT(ptr_ != nullptr);
74 return sync(fd_.Get(), direction, true);
75 }
76
endCpuAccess(DmaBufferDirection direction)77 XCamReturn DmaBuffer::endCpuAccess(DmaBufferDirection direction) {
78 XCAM_ASSERT(ptr_ != nullptr);
79 return sync(fd_.Get(), direction, false);
80 }
81
map()82 void* DmaBuffer::map() {
83 int ret;
84
85 assert(((void)"could not map invalid dma_buf", fd_.Get() > 0 && ptr_ == nullptr && size_ > 0));
86
87 ptr_ = mmap(0, size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_.Get(), 0);
88 if (ptr_ == MAP_FAILED) {
89 LOGE("dma_buf map failed %s", strerror(errno));
90 return nullptr;
91 }
92
93 return ptr_;
94 }
95
unmap()96 void DmaBuffer::unmap() {
97 assert(((void)"unmap dma_buf in wrong state", fd_.Get() > 0 && ptr_ != nullptr));
98
99 munmap(ptr_, size_);
100 ptr_ = nullptr;
101 }
102
getFd()103 int DmaBuffer::getFd() { return fd_.Get(); }
104
getSize()105 size_t DmaBuffer::getSize() { return size_; }
106
release()107 int DmaBuffer::release() { return fd_.Release(); }
108
mapped()109 bool DmaBuffer::mapped() { return ptr_ == nullptr ? false : true; }
110
111 } // namespace XCam
112