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