• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *    * Redistributions of source code must retain the above copyright
8 *      notice, this list of conditions and the following disclaimer.
9 *    * Redistributions in binary form must reproduce the above
10 *      copyright notice, this list of conditions and the following
11 *      disclaimer in the documentation and/or other materials provided
12 *      with the distribution.
13 *    * Neither the name of The Linux Foundation nor the names of its
14 *      contributors may be used to endorse or promote products derived
15 *      from this software without specific prior written permission.
16 
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
30 
31 #include <cutils/trace.h>
32 #include <drm_logger.h>
33 
34 #include "drm_atomic_req.h"
35 #include "drm_connector.h"
36 #include "drm_crtc.h"
37 #include "drm_manager.h"
38 #include "drm_plane.h"
39 #include "string.h"
40 
41 #define __CLASS__ "DRMAtomicReq"
42 
43 namespace sde_drm {
44 
DRMAtomicReq(int fd,DRMManager * drm_mgr)45 DRMAtomicReq::DRMAtomicReq(int fd, DRMManager *drm_mgr) : drm_mgr_(drm_mgr), fd_(fd) {}
46 
~DRMAtomicReq()47 DRMAtomicReq::~DRMAtomicReq() {
48   if (drm_atomic_req_) {
49     drmModeAtomicFree(drm_atomic_req_);
50     drm_atomic_req_ = nullptr;
51   }
52 }
53 
Init(const DRMDisplayToken & tok)54 int DRMAtomicReq::Init(const DRMDisplayToken &tok) {
55   token_ = tok;
56   drm_atomic_req_ = drmModeAtomicAlloc();
57   if (!drm_atomic_req_) {
58     return -ENOMEM;
59   }
60 
61   return 0;
62 }
63 
Perform(DRMOps opcode,uint32_t obj_id,...)64 int DRMAtomicReq::Perform(DRMOps opcode, uint32_t obj_id, ...) {
65   va_list args;
66   va_start(args, obj_id);
67   switch (opcode) {
68     case DRMOps::PLANE_SET_SRC_RECT:
69     case DRMOps::PLANE_SET_DST_RECT:
70     case DRMOps::PLANE_SET_ZORDER:
71     case DRMOps::PLANE_SET_ROTATION:
72     case DRMOps::PLANE_SET_ALPHA:
73     case DRMOps::PLANE_SET_BLEND_TYPE:
74     case DRMOps::PLANE_SET_H_DECIMATION:
75     case DRMOps::PLANE_SET_V_DECIMATION:
76     case DRMOps::PLANE_SET_FB_ID:
77     case DRMOps::PLANE_SET_ROT_FB_ID:
78     case DRMOps::PLANE_SET_CRTC:
79     case DRMOps::PLANE_SET_SRC_CONFIG:
80     case DRMOps::PLANE_SET_INPUT_FENCE:
81     case DRMOps::PLANE_SET_SCALER_CONFIG:
82     case DRMOps::PLANE_SET_FB_SECURE_MODE:
83     case DRMOps::PLANE_SET_CSC_CONFIG:
84     case DRMOps::PLANE_SET_MULTIRECT_MODE:
85     case DRMOps::PLANE_SET_EXCL_RECT:
86     case DRMOps::PLANE_SET_INVERSE_PMA:
87     case DRMOps::PLANE_SET_DGM_CSC_CONFIG:
88     case DRMOps::PLANE_SET_POST_PROC:
89     case DRMOps::PLANE_SET_SSPP_LAYOUT: {
90       drm_mgr_->GetPlaneMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
91     } break;
92     case DRMOps::CRTC_SET_POST_PROC:
93     case DRMOps::CRTC_SET_MODE:
94     case DRMOps::CRTC_SET_ACTIVE:
95     case DRMOps::CRTC_SET_OUTPUT_FENCE_OFFSET:
96     case DRMOps::CRTC_SET_CORE_CLK:
97     case DRMOps::CRTC_SET_CORE_AB:
98     case DRMOps::CRTC_SET_CORE_IB:
99     case DRMOps::CRTC_SET_LLCC_AB:
100     case DRMOps::CRTC_SET_LLCC_IB:
101     case DRMOps::CRTC_SET_DRAM_AB:
102     case DRMOps::CRTC_SET_DRAM_IB:
103     case DRMOps::CRTC_SET_ROT_PREFILL_BW:
104     case DRMOps::CRTC_SET_ROT_CLK:
105     case DRMOps::CRTC_GET_RELEASE_FENCE:
106     case DRMOps::CRTC_SET_ROI:
107     case DRMOps::CRTC_SET_SECURITY_LEVEL:
108     case DRMOps::CRTC_SET_SOLIDFILL_STAGES:
109     case DRMOps::CRTC_SET_IDLE_TIMEOUT:
110     case DRMOps::CRTC_SET_DEST_SCALER_CONFIG:
111     case DRMOps::CRTC_SET_CAPTURE_MODE:
112     case DRMOps::CRTC_SET_IDLE_PC_STATE: {
113       drm_mgr_->GetCrtcMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
114     } break;
115     case DRMOps::CONNECTOR_SET_CRTC:
116     case DRMOps::CONNECTOR_GET_RETIRE_FENCE:
117     case DRMOps::CONNECTOR_SET_OUTPUT_RECT:
118     case DRMOps::CONNECTOR_SET_OUTPUT_FB_ID:
119     case DRMOps::CONNECTOR_SET_POWER_MODE:
120     case DRMOps::CONNECTOR_SET_ROI:
121     case DRMOps::CONNECTOR_SET_AUTOREFRESH:
122     case DRMOps::CONNECTOR_SET_FB_SECURE_MODE:
123     case DRMOps::CONNECTOR_SET_POST_PROC:
124     case DRMOps::CONNECTOR_SET_HDR_METADATA:
125     case DRMOps::CONNECTOR_SET_QSYNC_MODE:
126     case DRMOps::CONNECTOR_SET_TOPOLOGY_CONTROL:
127     case DRMOps::CONNECTOR_SET_FRAME_TRIGGER:
128     case DRMOps::CONNECTOR_SET_COLORSPACE: {
129       drm_mgr_->GetConnectorMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
130     } break;
131     case DRMOps::DPPS_CACHE_FEATURE: {
132       drm_mgr_->GetDppsMgrIntf()->CacheDppsFeature(obj_id, args);
133     } break;
134     case DRMOps::DPPS_COMMIT_FEATURE: {
135       drm_mgr_->GetDppsMgrIntf()->CommitDppsFeatures(drm_atomic_req_, token_);
136     } break;
137     case DRMOps::COMMIT_PANEL_FEATURES: {
138       drm_mgr_->GetPanelFeatureMgrIntf()->CommitPanelFeatures(drm_atomic_req_, token_);
139     } break;
140     default:
141       DRM_LOGE("Invalid opcode %d", opcode);
142   }
143   va_end(args);
144   return 0;
145 }
146 
CallAtomic(DRMCrtc * crtc,uint32_t flags)147 int DRMAtomicReq::CallAtomic(DRMCrtc *crtc, uint32_t flags)
148 {
149   auto plane_mgr = drm_mgr_->GetPlaneMgr();
150   size_t cnt;
151 
152   cnt = plane_mgr->ApplyDirtyProperties(drm_atomic_req_);
153   ATRACE_INT("dirtyPlaneProps", cnt);
154   cnt = crtc->ApplyDirtyProperties(drm_atomic_req_);
155   ATRACE_INT("dirtyCrtcProps", cnt);
156 
157   int ret = drmModeAtomicCommit(fd_, drm_atomic_req_, flags, nullptr);
158   if (ret) {
159     DRM_LOGE("drmModeAtomicCommit failed with error %d (%s).", errno, strerror(errno));
160     /* reset all properties so next atomic commit applies all values */
161     crtc->ClearProperties();
162     plane_mgr->ClearProperties();
163   }
164 
165   // reset the drm_atomic_req_ for next call
166   drmModeAtomicSetCursor(drm_atomic_req_, 0);
167 
168   return ret;
169 }
170 
Validate()171 int DRMAtomicReq::Validate() {
172   auto crtc = drm_mgr_->GetCrtcMgr()->GetObject(token_.crtc_id);
173   if (crtc == nullptr) {
174     DRM_LOGE("Invalid crtc %d", token_.crtc_id);
175     return -EINVAL;
176   }
177 
178   drm_mgr_->GetPlaneMgr()->UnsetUnusedResources(token_.crtc_id, false /*is_commit*/,
179                                                 drm_atomic_req_);
180   int ret = CallAtomic(crtc, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_TEST_ONLY);
181   if (!ret)
182     crtc->PostValidate();
183 
184   // reset any dirty properties, all properties should be set again before Commit
185   crtc->DiscardDirtyProperties();
186   drm_mgr_->GetPlaneMgr()->PostValidate(token_.crtc_id);
187 
188   return ret;
189 }
190 
Commit(bool synchronous,bool retain_planes)191 int DRMAtomicReq::Commit(bool synchronous, bool retain_planes) {
192   DTRACE_SCOPED();
193   auto crtc = drm_mgr_->GetCrtcMgr()->GetObject(token_.crtc_id);
194   if (crtc == nullptr) {
195     DRM_LOGE("Invalid crtc %d", token_.crtc_id);
196     return -EINVAL;
197   }
198 
199   if (retain_planes) {
200     // It is not enough to simply avoid calling UnsetUnusedPlanes, since state transitons have to
201     // be correct when CommitPlaneState is called
202     drm_mgr_->GetPlaneMgr()->RetainPlanes(token_.crtc_id);
203   }
204 
205   drm_mgr_->GetPlaneMgr()->UnsetUnusedResources(token_.crtc_id, true /*is_commit*/,
206                                                 drm_atomic_req_);
207 
208   uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
209 
210   if (!synchronous) {
211     flags |= DRM_MODE_ATOMIC_NONBLOCK;
212   }
213 
214   int ret = CallAtomic(crtc, flags);
215 
216   drm_mgr_->GetPlaneMgr()->PostCommit(token_.crtc_id, !ret);
217   crtc->PostCommit(!ret);
218 
219   ATRACE_INT("dirtyPlaneProps", 0);
220   ATRACE_INT("dirtyCrtcProps", 0);
221 
222   return ret;
223 }
224 
225 }  // namespace sde_drm
226