1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <hardware/exynos/ion.h>
18 #include "ExynosDisplayDrmInterfaceModule.h"
19 #include "ExynosPrimaryDisplayModule.h"
20
21 using namespace gs201;
22
23 /////////////////////////////////////////////////// ExynosDisplayDrmInterfaceModule //////////////////////////////////////////////////////////////////
ExynosDisplayDrmInterfaceModule(ExynosDisplay * exynosDisplay)24 ExynosDisplayDrmInterfaceModule::ExynosDisplayDrmInterfaceModule(ExynosDisplay *exynosDisplay)
25 : gs101::ExynosDisplayDrmInterfaceModule(exynosDisplay)
26 {
27 }
28
~ExynosDisplayDrmInterfaceModule()29 ExynosDisplayDrmInterfaceModule::~ExynosDisplayDrmInterfaceModule()
30 {
31 for (auto p: mCGCDataInfos) {
32 if (p.second != nullptr)
33 munmap(p.second, sizeCgcDmaLut);
34
35 if (p.first > 0)
36 close(p.first);
37 }
38 }
39
initDrmDevice(DrmDevice * drmDevice)40 int32_t ExynosDisplayDrmInterfaceModule::initDrmDevice(DrmDevice *drmDevice)
41 {
42 int ret = gs101::ExynosDisplayDrmInterfaceModule::initDrmDevice(drmDevice);
43 if (ret != NO_ERROR)
44 return ret;
45
46 /* create file descriptors for CGC DMA */
47 int32_t fd;
48 struct cgc_dma_lut *buf;
49
50 int ionFd = exynos_ion_open();
51 if (ionFd >= 0) {
52 while (mCGCDataInfos.size() < sizeCgCDataInfo) {
53 fd = exynos_ion_alloc(ionFd, sizeCgcDmaLut, EXYNOS_ION_HEAP_SYSTEM_MASK, 0);
54 if (fd >= 0) {
55 buf = (struct cgc_dma_lut *)mmap(0, sizeCgcDmaLut, PROT_READ | PROT_WRITE,
56 MAP_SHARED, fd, 0);
57 if (buf == nullptr) {
58 ALOGE("Failed to map buffer for CGC_DMA LUT");
59 close(fd);
60 ret = -ENOMEM;
61 break;
62 } else {
63 memset(buf, 0, sizeCgcDmaLut);
64 mCGCDataInfos.emplace_back(CGCDataInfo(fd, buf));
65 }
66 } else {
67 ALOGE("Failed to allocate ION for CGC_DMA LUT");
68 ret = -ENOMEM;
69 break;
70 }
71 }
72
73 exynos_ion_close(ionFd);
74 } else
75 ALOGE("Failed to open ION for CGC_DMA LUT");
76
77 return ret;
78 }
79
createCgcDMAFromIDqe(const GsInterfaceType::IDqe::CgcData & cgcData)80 int32_t ExynosDisplayDrmInterfaceModule::createCgcDMAFromIDqe(
81 const GsInterfaceType::IDqe::CgcData &cgcData)
82 {
83 if ((cgcData.config->r_values.size() != DRM_SAMSUNG_CGC_LUT_REG_CNT) ||
84 (cgcData.config->g_values.size() != DRM_SAMSUNG_CGC_LUT_REG_CNT) ||
85 (cgcData.config->b_values.size() != DRM_SAMSUNG_CGC_LUT_REG_CNT)) {
86 ALOGE("CGC data size is not same (r: %zu, g: %zu: b: %zu)",
87 cgcData.config->r_values.size(),
88 cgcData.config->g_values.size(),
89 cgcData.config->b_values.size());
90 return -EINVAL;
91 }
92
93 if (iCGCDataInfo >= mCGCDataInfos.size()) {
94 ALOGE("CGC Data Infos is empty");
95 return -EINVAL;
96 }
97
98 struct cgc_dma_lut *buf = mCGCDataInfos.at(iCGCDataInfo).second;
99 uint32_t i = 0;
100 for (; i < (DRM_SAMSUNG_CGC_LUT_REG_CNT - 1); i++) {
101 buf[i * 2].r_value = (uint16_t)(cgcData.config->r_values[i]);
102 buf[i * 2].g_value = (uint16_t)(cgcData.config->g_values[i]);
103 buf[i * 2].b_value = (uint16_t)(cgcData.config->b_values[i]);
104 buf[i * 2 + 1].r_value = (uint16_t)(cgcData.config->r_values[i] >> 16);
105 buf[i * 2 + 1].g_value = (uint16_t)(cgcData.config->g_values[i] >> 16);
106 buf[i * 2 + 1].b_value = (uint16_t)(cgcData.config->b_values[i] >> 16);
107 }
108 buf[i * 2].r_value = (uint16_t)cgcData.config->r_values[i];
109 buf[i * 2].g_value = (uint16_t)cgcData.config->g_values[i];
110 buf[i * 2].b_value = (uint16_t)cgcData.config->b_values[i];
111
112 return mCGCDataInfos.at(iCGCDataInfo).first;
113 }
114
setCgcLutDmaProperty(const DrmProperty & prop,ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)115 int32_t ExynosDisplayDrmInterfaceModule::setCgcLutDmaProperty(
116 const DrmProperty &prop,
117 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq)
118 {
119 if (!prop.id())
120 return NO_ERROR;
121
122 ExynosDeviceModule* device = static_cast<ExynosDeviceModule*>(mExynosDisplay->mDevice);
123 gs101::ColorManager* colorManager = device->getDisplayColorManager(mExynosDisplay);
124 if (!colorManager) return NO_ERROR;
125 const GsInterfaceType::IDqe &dqe = colorManager->getDqe();
126 const GsInterfaceType::IDqe::CgcData &cgcData = dqe.Cgc();
127
128 /* dirty bit is valid only if enable is true */
129 if (!mForceDisplayColorSetting && cgcData.enable && !cgcData.dirty)
130 return NO_ERROR;
131
132 int32_t ret = 0;
133 int32_t cgcLutFd = disabledCgc;
134
135 if (cgcData.enable) {
136 if (cgcData.config == nullptr) {
137 ALOGE("no CGC config");
138 return NO_ERROR;
139 }
140
141 cgcLutFd = createCgcDMAFromIDqe(cgcData);
142 if (cgcLutFd < 0) {
143 HWC_LOGE(mExynosDisplay, "%s: create CGC DMA FD fail", __func__);
144 return cgcLutFd;
145 }
146
147 iCGCDataInfo = (iCGCDataInfo + 1) % sizeCgCDataInfo;
148 }
149
150 /* CGC Disabled information should not be delivered at every frame */
151 if (cgcLutFd == disabledCgc && !mCgcEnabled)
152 return NO_ERROR;
153
154 /* CGC setting when cgc is enabled and dirty */
155 if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), prop, cgcLutFd, true)) < 0) {
156 HWC_LOGE(mExynosDisplay, "%s: Fail to set cgc_dma_fd property", __func__);
157 return ret;
158 }
159 dqe.Cgc().NotifyDataApplied();
160
161 mCgcEnabled = (cgcLutFd != disabledCgc);
162
163 return NO_ERROR;
164 }
165
setDisplayColorSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)166 int32_t ExynosDisplayDrmInterfaceModule::setDisplayColorSetting(
167 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq)
168 {
169 if (!mForceDisplayColorSetting && !mColorSettingChanged)
170 return NO_ERROR;
171
172 int32_t ret = gs101::ExynosDisplayDrmInterfaceModule::setDisplayColorSetting(drmReq);
173 if (ret != NO_ERROR)
174 return ret;
175
176 return setCgcLutDmaProperty(mDrmCrtc->cgc_lut_fd_property(), drmReq);
177 }
178
setHistoPosProperty(const DrmProperty & prop,ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)179 int32_t ExynosDisplayDrmInterfaceModule::setHistoPosProperty(
180 const DrmProperty &prop,
181 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq) {
182 if (!prop.id()) return NO_ERROR;
183
184 int32_t ret = 0;
185
186 if ((ret = drmReq.atomicAddProperty(
187 mDrmCrtc->id(), prop, (uint64_t)mHistogramInfo->getHistogramPos(),
188 true)) < 0) {
189 HWC_LOGE(mExynosDisplay, "%s: Fail to set histogram position property",
190 __func__);
191 return ret;
192 }
193
194 return NO_ERROR;
195 }
196
setDisplayHistogramSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)197 int32_t ExynosDisplayDrmInterfaceModule::setDisplayHistogramSetting(
198 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq) {
199 if ((isHistogramInfoRegistered() == false) || (isPrimary() == false)) return NO_ERROR;
200
201 int32_t ret =
202 gs101::ExynosDisplayDrmInterfaceModule::setDisplayHistogramSetting(
203 drmReq);
204 if (ret != NO_ERROR) return ret;
205
206 ret = setHistoPosProperty(mDrmCrtc->histogram_position_property(), drmReq);
207
208 return ret;
209 }
210
registerHistogramInfo(const std::shared_ptr<IDLHistogram> & info)211 void ExynosDisplayDrmInterfaceModule::registerHistogramInfo(
212 const std::shared_ptr<IDLHistogram> &info) {
213 gs101::ExynosDisplayDrmInterfaceModule::registerHistogramInfo(info);
214 mHistogramInfo = info;
215 }
216
217 //////////////////////////////////////////////////// ExynosPrimaryDisplayDrmInterfaceModule //////////////////////////////////////////////////////////////////
ExynosPrimaryDisplayDrmInterfaceModule(ExynosDisplay * exynosDisplay)218 ExynosPrimaryDisplayDrmInterfaceModule::ExynosPrimaryDisplayDrmInterfaceModule(ExynosDisplay *exynosDisplay)
219 : ExynosDisplayDrmInterfaceModule(exynosDisplay)
220 {
221 }
222
~ExynosPrimaryDisplayDrmInterfaceModule()223 ExynosPrimaryDisplayDrmInterfaceModule::~ExynosPrimaryDisplayDrmInterfaceModule()
224 {
225 }
226