blob: 0aaeb9374f3e46124e630b4d5fc13241439ec07c [file] [log] [blame]
Saurabh Shah82b06f42017-09-06 16:43:49 -07001/*
Varun Arora6ba9eda2019-02-07 17:59:32 -08002Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
Saurabh Shah82b06f42017-09-06 16:43:49 -07003
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
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
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
Varun Arora75c05f02019-05-14 14:53:37 -070030#include <fcntl.h>
Saurabh Shah82b06f42017-09-06 16:43:49 -070031#include <utils/debug.h>
Varun Arora75c05f02019-05-14 14:53:37 -070032#include <utils/sys.h>
Sushil Chauhan06521582018-03-19 14:00:23 -070033#include <vector>
Varun Arora75c05f02019-05-14 14:53:37 -070034#include <string>
Ramkumar Radhakrishnan07438bb2018-07-25 19:30:54 -070035#include <cstring>
Saurabh Shah82b06f42017-09-06 16:43:49 -070036
37#include "hw_peripheral_drm.h"
38
39#define __CLASS__ "HWPeripheralDRM"
40
41using sde_drm::DRMDisplayType;
42using sde_drm::DRMOps;
Saurabh Shah82b06f42017-09-06 16:43:49 -070043using sde_drm::DRMPowerMode;
Ping Li6a74d892018-05-02 15:54:58 -070044using sde_drm::DppsFeaturePayload;
Xu Yang32e58c22017-11-20 09:58:11 +080045using sde_drm::DRMDppsFeatureInfo;
Sushil Chauhan06521582018-03-19 14:00:23 -070046using sde_drm::DRMSecureMode;
47using sde_drm::DRMCWbCaptureMode;
Saurabh Shah82b06f42017-09-06 16:43:49 -070048
49namespace sdm {
50
Mathew Joseph Karimpanal731bc932017-11-22 10:04:56 +053051HWPeripheralDRM::HWPeripheralDRM(int32_t display_id, BufferSyncHandler *buffer_sync_handler,
52 BufferAllocator *buffer_allocator, HWInfoInterface *hw_info_intf)
Saurabh Shah82b06f42017-09-06 16:43:49 -070053 : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf) {
54 disp_type_ = DRMDisplayType::PERIPHERAL;
Varun Arora7c8ee542018-05-01 20:58:16 -070055 device_name_ = "Peripheral";
Mathew Joseph Karimpanal731bc932017-11-22 10:04:56 +053056 display_id_ = display_id;
Saurabh Shah82b06f42017-09-06 16:43:49 -070057}
58
59DisplayError HWPeripheralDRM::Init() {
60 DisplayError ret = HWDeviceDRM::Init();
61 if (ret != kErrorNone) {
62 DLOGE("Init failed for %s", device_name_);
63 return ret;
64 }
65
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +053066 scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
Ramkumar Radhakrishnan07438bb2018-07-25 19:30:54 -070067 dest_scalar_cache_.resize(hw_resource_.hw_dest_scalar_info.count);
Pullakavi Srinivas9189e602018-12-19 16:58:07 +053068 PopulateBitClkRates();
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +053069
Mathew Joseph Karimpanalb7f20c62018-10-09 12:17:20 +053070 topology_control_ = UINT32(sde_drm::DRMTopologyControl::DSPP);
71 if (hw_panel_info_.is_primary_panel) {
72 topology_control_ |= UINT32(sde_drm::DRMTopologyControl::DEST_SCALER);
73 }
Pullakavi Srinivas9189e602018-12-19 16:58:07 +053074
75 return kErrorNone;
76}
77
78void HWPeripheralDRM::PopulateBitClkRates() {
79 if (!hw_panel_info_.dyn_bitclk_support) {
80 return;
81 }
82
83 // Group all bit_clk_rates corresponding to DRM_PREFERRED mode.
84 uint32_t width = connector_info_.modes[current_mode_index_].mode.hdisplay;
85 uint32_t height = connector_info_.modes[current_mode_index_].mode.vdisplay;
86
87 for (auto &mode_info : connector_info_.modes) {
88 auto &mode = mode_info.mode;
89 if (mode.hdisplay == width && mode.vdisplay == height) {
90 bitclk_rates_.push_back(mode_info.bit_clk_rate);
91 DLOGI("Possible bit_clk_rates %d", mode_info.bit_clk_rate);
92 }
93 }
94
95 hw_panel_info_.bitclk_rates = bitclk_rates_;
96 DLOGI("bit_clk_rates Size %d", bitclk_rates_.size());
97}
98
99DisplayError HWPeripheralDRM::SetDynamicDSIClock(uint64_t bit_clk_rate) {
100 bit_clk_rate_ = bit_clk_rate;
101 update_mode_ = true;
102
103 return kErrorNone;
104}
105
106DisplayError HWPeripheralDRM::GetDynamicDSIClock(uint64_t *bit_clk_rate) {
107 // Update bit_rate corresponding to current refresh rate.
108 *bit_clk_rate = (uint32_t)connector_info_.modes[current_mode_index_].bit_clk_rate;
109
Saurabh Shah82b06f42017-09-06 16:43:49 -0700110 return kErrorNone;
111}
112
113DisplayError HWPeripheralDRM::Validate(HWLayers *hw_layers) {
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530114 HWLayersInfo &hw_layer_info = hw_layers->info;
Ramkumar Radhakrishnanb72f9af2019-06-03 23:30:57 -0700115 SetDestScalarData(hw_layer_info);
Sushil Chauhan06521582018-03-19 14:00:23 -0700116 SetupConcurrentWriteback(hw_layer_info, true);
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700117 SetIdlePCState();
Saurabh Shah82b06f42017-09-06 16:43:49 -0700118
119 return HWDeviceDRM::Validate(hw_layers);
120}
121
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530122DisplayError HWPeripheralDRM::Commit(HWLayers *hw_layers) {
123 HWLayersInfo &hw_layer_info = hw_layers->info;
Ramkumar Radhakrishnanb72f9af2019-06-03 23:30:57 -0700124 SetDestScalarData(hw_layer_info);
Sushil Chauhan06521582018-03-19 14:00:23 -0700125 SetupConcurrentWriteback(hw_layer_info, false);
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700126 SetIdlePCState();
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530127
Sushil Chauhan06521582018-03-19 14:00:23 -0700128 DisplayError error = HWDeviceDRM::Commit(hw_layers);
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700129 if (error != kErrorNone) {
130 return error;
131 }
Sushil Chauhan06521582018-03-19 14:00:23 -0700132
Ramkumar Radhakrishnanb72f9af2019-06-03 23:30:57 -0700133 CacheDestScalarData(hw_layer_info);
Sushil Chauhan06521582018-03-19 14:00:23 -0700134 if (cwb_config_.enabled && (error == kErrorNone)) {
135 PostCommitConcurrentWriteback(hw_layer_info.stack->output_buffer);
136 }
137
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700138 // Initialize to default after successful commit
139 synchronous_commit_ = false;
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700140 idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700141
Sushil Chauhan06521582018-03-19 14:00:23 -0700142 return error;
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530143}
144
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530145void HWPeripheralDRM::ResetDisplayParams() {
146 sde_dest_scalar_data_ = {};
147 for (uint32_t j = 0; j < scalar_data_.size(); j++) {
148 scalar_data_[j] = {};
Ramkumar Radhakrishnan07438bb2018-07-25 19:30:54 -0700149 dest_scalar_cache_[j] = {};
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530150 }
151}
152
Ramkumar Radhakrishnanb72f9af2019-06-03 23:30:57 -0700153void HWPeripheralDRM::SetDestScalarData(const HWLayersInfo &hw_layer_info) {
Alex Sarraf4446cd72018-05-16 15:23:57 -0700154 if (!hw_scale_ || !hw_resource_.hw_dest_scalar_info.count) {
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530155 return;
156 }
157
Ramkumar Radhakrishnanb72f9af2019-06-03 23:30:57 -0700158 for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
159 auto it = hw_layer_info.dest_scale_info_map.find(i);
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530160
161 if (it == hw_layer_info.dest_scale_info_map.end()) {
162 continue;
163 }
164
165 HWDestScaleInfo *dest_scale_info = it->second;
Ramkumar Radhakrishnan2d1a21e2018-09-18 19:41:55 -0700166 SDEScaler *scale = &scalar_data_[i];
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530167 hw_scale_->SetScaler(dest_scale_info->scale_data, scale);
Ramkumar Radhakrishnan07438bb2018-07-25 19:30:54 -0700168
Ramkumar Radhakrishnan2d1a21e2018-09-18 19:41:55 -0700169 sde_drm_dest_scaler_cfg *dest_scalar_data = &sde_dest_scalar_data_.ds_cfg[i];
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530170 dest_scalar_data->flags = 0;
171 if (scale->scaler_v2.enable) {
172 dest_scalar_data->flags |= SDE_DRM_DESTSCALER_ENABLE;
173 }
174 if (scale->scaler_v2.de.enable) {
175 dest_scalar_data->flags |= SDE_DRM_DESTSCALER_ENHANCER_UPDATE;
176 }
177 if (dest_scale_info->scale_update) {
178 dest_scalar_data->flags |= SDE_DRM_DESTSCALER_SCALE_UPDATE;
179 }
Ramkumar Radhakrishnan07438bb2018-07-25 19:30:54 -0700180 if (hw_panel_info_.partial_update) {
181 dest_scalar_data->flags |= SDE_DRM_DESTSCALER_PU_ENABLE;
182 }
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530183 dest_scalar_data->index = i;
184 dest_scalar_data->lm_width = dest_scale_info->mixer_width;
185 dest_scalar_data->lm_height = dest_scale_info->mixer_height;
186 dest_scalar_data->scaler_cfg = reinterpret_cast<uint64_t>(&scale->scaler_v2);
Ramkumar Radhakrishnan2d1a21e2018-09-18 19:41:55 -0700187
188 if (std::memcmp(&dest_scalar_cache_[i].scalar_data, scale, sizeof(SDEScaler)) ||
189 dest_scalar_cache_[i].flags != dest_scalar_data->flags) {
190 needs_ds_update_ = true;
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530191 }
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530192 }
Ramkumar Radhakrishnan2d1a21e2018-09-18 19:41:55 -0700193
194 if (needs_ds_update_) {
Ramkumar Radhakrishnan2d1a21e2018-09-18 19:41:55 -0700195 sde_dest_scalar_data_.num_dest_scaler = UINT32(hw_layer_info.dest_scale_info_map.size());
Ramkumar Radhakrishnan07438bb2018-07-25 19:30:54 -0700196 drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DEST_SCALER_CONFIG, token_.crtc_id,
197 reinterpret_cast<uint64_t>(&sde_dest_scalar_data_));
198 }
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530199}
200
Ramkumar Radhakrishnanb72f9af2019-06-03 23:30:57 -0700201void HWPeripheralDRM::CacheDestScalarData(const HWLayersInfo &hw_layer_info) {
202 if (needs_ds_update_) {
203 // Cache the destination scalar data during commit
204 for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
205 auto it = hw_layer_info.dest_scale_info_map.find(i);
206 if (it == hw_layer_info.dest_scale_info_map.end()) {
207 continue;
208 }
209 dest_scalar_cache_[i].flags = sde_dest_scalar_data_.ds_cfg[i].flags;
210 dest_scalar_cache_[i].scalar_data = scalar_data_[i];
211 }
212 needs_ds_update_ = false;
213 }
214}
215
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +0530216DisplayError HWPeripheralDRM::Flush(HWLayers *hw_layers) {
217 DisplayError err = HWDeviceDRM::Flush(hw_layers);
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530218 if (err != kErrorNone) {
219 return err;
220 }
221
222 ResetDisplayParams();
223 return kErrorNone;
224}
225
Ping Li6a74d892018-05-02 15:54:58 -0700226DisplayError HWPeripheralDRM::SetDppsFeature(void *payload, size_t size) {
227 uint32_t obj_id = 0, object_type = 0, feature_id = 0;
228 uint64_t value = 0;
Xu Yang32e58c22017-11-20 09:58:11 +0800229
Ping Li6a74d892018-05-02 15:54:58 -0700230 if (size != sizeof(DppsFeaturePayload)) {
231 DLOGE("invalid payload size %d, expected %d", size, sizeof(DppsFeaturePayload));
232 return kErrorParameters;
233 }
234
235 DppsFeaturePayload *feature_payload = reinterpret_cast<DppsFeaturePayload *>(payload);
236 object_type = feature_payload->object_type;
237 feature_id = feature_payload->feature_id;
238 value = feature_payload->value;
Yuchao Ma577f0f72018-07-09 11:20:00 +0800239
240 if (feature_id == sde_drm::kFeatureAd4Roi) {
241 if (feature_payload->value) {
242 DisplayDppsAd4RoiCfg *params = reinterpret_cast<DisplayDppsAd4RoiCfg *>
243 (feature_payload->value);
244 if (!params) {
245 DLOGE("invalid playload value %d", feature_payload->value);
246 return kErrorNotSupported;
247 }
248
249 ad4_roi_cfg_.h_x = params->h_start;
250 ad4_roi_cfg_.h_y = params->h_end;
251 ad4_roi_cfg_.v_x = params->v_start;
252 ad4_roi_cfg_.v_y = params->v_end;
253 ad4_roi_cfg_.factor_in = params->factor_in;
254 ad4_roi_cfg_.factor_out = params->factor_out;
255
256 value = (uint64_t)&ad4_roi_cfg_;
257 }
258 }
259
Xu Yang32e58c22017-11-20 09:58:11 +0800260 if (object_type == DRM_MODE_OBJECT_CRTC) {
261 obj_id = token_.crtc_id;
262 } else if (object_type == DRM_MODE_OBJECT_CONNECTOR) {
263 obj_id = token_.conn_id;
264 } else {
265 DLOGE("invalid object type 0x%x", object_type);
266 return kErrorUndefined;
267 }
268
269 drm_atomic_intf_->Perform(DRMOps::DPPS_CACHE_FEATURE, obj_id, feature_id, value);
270 return kErrorNone;
271}
272
Ping Li6a74d892018-05-02 15:54:58 -0700273DisplayError HWPeripheralDRM::GetDppsFeatureInfo(void *payload, size_t size) {
274 if (size != sizeof(DRMDppsFeatureInfo)) {
275 DLOGE("invalid payload size %d, expected %d", size, sizeof(DRMDppsFeatureInfo));
276 return kErrorParameters;
277 }
278 DRMDppsFeatureInfo *feature_info = reinterpret_cast<DRMDppsFeatureInfo *>(payload);
Yuchao Maf08d4262019-06-07 17:18:42 +0800279 feature_info->obj_id = token_.crtc_id;
Xu Yang32e58c22017-11-20 09:58:11 +0800280 drm_mgr_intf_->GetDppsFeatureInfo(feature_info);
281 return kErrorNone;
282}
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530283
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +0530284DisplayError HWPeripheralDRM::HandleSecureEvent(SecureEvent secure_event, HWLayers *hw_layers) {
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -0700285 switch (secure_event) {
286 case kSecureDisplayStart: {
287 secure_display_active_ = true;
288 if (hw_panel_info_.mode != kModeCommand) {
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +0530289 DisplayError err = Flush(hw_layers);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -0700290 if (err != kErrorNone) {
291 return err;
292 }
293 }
294 }
295 break;
296
297 case kSecureDisplayEnd: {
298 if (hw_panel_info_.mode != kModeCommand) {
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +0530299 DisplayError err = Flush(hw_layers);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -0700300 if (err != kErrorNone) {
301 return err;
302 }
303 }
304 secure_display_active_ = false;
Ramkumar Radhakrishnand25d30e2018-08-17 11:06:27 -0700305 synchronous_commit_ = true;
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -0700306 }
307 break;
308
309 default:
310 DLOGE("Invalid secure event %d", secure_event);
311 return kErrorNotSupported;
312 }
313
314 return kErrorNone;
315}
316
Sushil Chauhan06521582018-03-19 14:00:23 -0700317void HWPeripheralDRM::SetupConcurrentWriteback(const HWLayersInfo &hw_layer_info, bool validate) {
318 bool enable = hw_resource_.has_concurrent_writeback && hw_layer_info.stack->output_buffer;
319 if (!(enable || cwb_config_.enabled)) {
320 return;
321 }
322
323 bool setup_modes = enable && !cwb_config_.enabled && validate;
324 if (setup_modes && (SetupConcurrentWritebackModes() == kErrorNone)) {
325 cwb_config_.enabled = true;
326 }
327
328 if (cwb_config_.enabled) {
329 if (enable) {
330 // Set DRM properties for Concurrent Writeback.
331 ConfigureConcurrentWriteback(hw_layer_info.stack);
Prabhanjan Kandula9e9c2322018-06-06 18:07:15 -0700332
333 if (!validate) {
334 // Set GET_RETIRE_FENCE property to get Concurrent Writeback fence.
335 int *fence = &hw_layer_info.stack->output_buffer->release_fence_fd;
336 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE,
337 cwb_config_.token.conn_id, fence);
338 }
Gurpreet Singh Dhamif8a9b842018-12-21 17:36:29 -0500339 } else {
340 // Tear down the Concurrent Writeback topology.
341 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, 0);
Sushil Chauhan06521582018-03-19 14:00:23 -0700342 }
343 }
344}
345
Gurpreet Singh Dhami1207e462018-12-27 20:02:02 -0500346DisplayError HWPeripheralDRM::TeardownConcurrentWriteback(void) {
347 if (cwb_config_.enabled) {
Varun Arora6ba9eda2019-02-07 17:59:32 -0800348 drm_mgr_intf_->UnregisterDisplay(&(cwb_config_.token));
Gurpreet Singh Dhami1207e462018-12-27 20:02:02 -0500349 cwb_config_.enabled = false;
350 registry_.Clear();
351 }
352
353 return kErrorNone;
354}
355
Sushil Chauhan06521582018-03-19 14:00:23 -0700356DisplayError HWPeripheralDRM::SetupConcurrentWritebackModes() {
357 // To setup Concurrent Writeback topology, get the Connector ID of Virtual display
358 if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::VIRTUAL, &cwb_config_.token)) {
359 DLOGE("RegisterDisplay failed for Concurrent Writeback");
360 return kErrorResources;
361 }
362
363 // Set the modes based on Primary display.
364 std::vector<drmModeModeInfo> modes;
365 for (auto &item : connector_info_.modes) {
366 modes.push_back(item.mode);
367 }
368
369 // Inform the mode list to driver.
370 struct sde_drm_wb_cfg cwb_cfg = {};
371 cwb_cfg.connector_id = cwb_config_.token.conn_id;
372 cwb_cfg.flags = SDE_DRM_WB_CFG_FLAGS_CONNECTED;
373 cwb_cfg.count_modes = UINT32(modes.size());
374 cwb_cfg.modes = (uint64_t)modes.data();
375
376 int ret = -EINVAL;
377#ifdef DRM_IOCTL_SDE_WB_CONFIG
378 ret = drmIoctl(dev_fd_, DRM_IOCTL_SDE_WB_CONFIG, &cwb_cfg);
379#endif
380 if (ret) {
Varun Arora6ba9eda2019-02-07 17:59:32 -0800381 drm_mgr_intf_->UnregisterDisplay(&(cwb_config_.token));
Sushil Chauhan06521582018-03-19 14:00:23 -0700382 DLOGE("Dump CWBConfig: mode_count %d flags %x", cwb_cfg.count_modes, cwb_cfg.flags);
383 DumpConnectorModeInfo();
384 return kErrorHardware;
385 }
386
387 return kErrorNone;
388}
389
390void HWPeripheralDRM::ConfigureConcurrentWriteback(LayerStack *layer_stack) {
391 LayerBuffer *output_buffer = layer_stack->output_buffer;
Sushil Chauhanabc5b272018-06-20 16:18:13 -0700392 registry_.MapOutputBufferToFbId(output_buffer);
Sushil Chauhan06521582018-03-19 14:00:23 -0700393
394 // Set the topology for Concurrent Writeback: [CRTC_PRIMARY_DISPLAY - CONNECTOR_VIRTUAL_DISPLAY].
395 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, token_.crtc_id);
396
397 // Set CRTC Capture Mode
398 DRMCWbCaptureMode capture_mode = layer_stack->flags.post_processed_output ?
399 DRMCWbCaptureMode::DSPP_OUT : DRMCWbCaptureMode::MIXER_OUT;
400 drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CAPTURE_MODE, token_.crtc_id, capture_mode);
401
402 // Set Connector Output FB
Sushil Chauhanabc5b272018-06-20 16:18:13 -0700403 uint32_t fb_id = registry_.GetOutputFbId(output_buffer->handle_id);
Sushil Chauhan06521582018-03-19 14:00:23 -0700404 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_FB_ID, cwb_config_.token.conn_id, fb_id);
405
406 // Set Connector Secure Mode
407 bool secure = output_buffer->flags.secure;
408 DRMSecureMode mode = secure ? DRMSecureMode::SECURE : DRMSecureMode::NON_SECURE;
409 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_FB_SECURE_MODE, cwb_config_.token.conn_id, mode);
410
411 // Set Connector Output Rect
412 sde_drm::DRMRect dst = {};
413 dst.left = 0;
414 dst.top = 0;
415 dst.right = display_attributes_[current_mode_index_].x_pixels;
416 dst.bottom = display_attributes_[current_mode_index_].y_pixels;
417 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_RECT, cwb_config_.token.conn_id, dst);
418}
419
420void HWPeripheralDRM::PostCommitConcurrentWriteback(LayerBuffer *output_buffer) {
421 bool enabled = hw_resource_.has_concurrent_writeback && output_buffer;
422
Gurpreet Singh Dhamif8a9b842018-12-21 17:36:29 -0500423 if (!enabled) {
Gurpreet Singh Dhami1207e462018-12-27 20:02:02 -0500424 TeardownConcurrentWriteback();
Sushil Chauhan06521582018-03-19 14:00:23 -0700425 }
426}
427
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700428DisplayError HWPeripheralDRM::ControlIdlePowerCollapse(bool enable, bool synchronous) {
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700429 if (enable == idle_pc_enabled_) {
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700430 return kErrorNone;
431 }
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700432 idle_pc_state_ = enable ? sde_drm::DRMIdlePCState::ENABLE : sde_drm::DRMIdlePCState::DISABLE;
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700433 // As idle PC is disabled after subsequent commit, Make sure to have synchrounous commit and
434 // ensure TA accesses the display_cc registers after idle PC is disabled.
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700435 synchronous_commit_ = !enable ? synchronous : false;
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700436 idle_pc_enabled_ = enable;
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700437 return kErrorNone;
438}
439
440DisplayError HWPeripheralDRM::PowerOn(const HWQosData &qos_data, int *release_fence) {
441 DTRACE_SCOPED();
442 if (!drm_atomic_intf_) {
443 DLOGE("DRM Atomic Interface is null!");
444 return kErrorUndefined;
445 }
446
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700447 if (!idle_pc_enabled_) {
448 drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_IDLE_PC_STATE, token_.crtc_id,
449 sde_drm::DRMIdlePCState::ENABLE);
450 }
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700451 DisplayError err = HWDeviceDRM::PowerOn(qos_data, release_fence);
452 if (err != kErrorNone) {
453 return err;
454 }
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700455 idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
456 idle_pc_enabled_ = true;
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700457
458 return kErrorNone;
459}
460
Pullakavi Srinivas9189e602018-12-19 16:58:07 +0530461DisplayError HWPeripheralDRM::SetDisplayAttributes(uint32_t index) {
462 HWDeviceDRM::SetDisplayAttributes(index);
463 // update bit clk rates.
464 hw_panel_info_.bitclk_rates = bitclk_rates_;
465
466 return kErrorNone;
467}
468
Yuchao Ma577f0f72018-07-09 11:20:00 +0800469DisplayError HWPeripheralDRM::SetDisplayDppsAdROI(void *payload) {
470 DisplayError err = kErrorNone;
471 struct sde_drm::DppsFeaturePayload feature_payload = {};
472
473 if (!payload) {
474 DLOGE("Invalid payload parameter");
475 return kErrorParameters;
476 }
477
478 feature_payload.object_type = DRM_MODE_OBJECT_CRTC;
479 feature_payload.feature_id = sde_drm::kFeatureAd4Roi;
480 feature_payload.value = (uint64_t)(payload);
481
482 err = SetDppsFeature(&feature_payload, sizeof(feature_payload));
483 if (err != kErrorNone) {
484 DLOGE("Faid to SetDppsFeature feature_id = %d, err = %d",
485 sde_drm::kFeatureAd4Roi, err);
486 }
487
488 return err;
489}
490
Xu Yang27aaea32018-12-19 15:53:56 +0800491DisplayError HWPeripheralDRM::SetFrameTrigger(FrameTriggerMode mode) {
492 sde_drm::DRMFrameTriggerMode drm_mode = sde_drm::DRMFrameTriggerMode::FRAME_DONE_WAIT_DEFAULT;
493 switch (mode) {
494 case kFrameTriggerDefault:
495 drm_mode = sde_drm::DRMFrameTriggerMode::FRAME_DONE_WAIT_DEFAULT;
496 break;
497 case kFrameTriggerSerialize:
498 drm_mode = sde_drm::DRMFrameTriggerMode::FRAME_DONE_WAIT_SERIALIZE;
499 break;
500 case kFrameTriggerPostedStart:
501 drm_mode = sde_drm::DRMFrameTriggerMode::FRAME_DONE_WAIT_POSTED_START;
502 break;
503 default:
504 DLOGE("Invalid frame trigger mode %d", (int32_t)mode);
505 return kErrorParameters;
506 }
507
508 int ret = drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_FRAME_TRIGGER,
509 token_.conn_id, drm_mode);
510 if (ret) {
511 DLOGE("Failed to perform CONNECTOR_SET_FRAME_TRIGGER, drm_mode %d, ret %d", drm_mode, ret);
512 return kErrorUndefined;
513 }
514 return kErrorNone;
515}
516
Varun Arora75c05f02019-05-14 14:53:37 -0700517DisplayError HWPeripheralDRM::SetPanelBrightness(int level) {
518 char buffer[kMaxSysfsCommandLength] = {0};
519
520 if (brightness_base_path_.empty()) {
521 return kErrorHardware;
522 }
523
524 std::string brightness_node(brightness_base_path_ + "brightness");
525 int fd = Sys::open_(brightness_node.c_str(), O_RDWR);
526 if (fd < 0) {
527 DLOGE("Failed to open node = %s, error = %s ", brightness_node.c_str(),
528 strerror(errno));
529 return kErrorFileDescriptor;
530 }
531
532 int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level);
533 ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);
534 if (ret <= 0) {
535 DLOGE("Failed to write to node = %s, error = %s ", brightness_node.c_str(),
536 strerror(errno));
537 Sys::close_(fd);
538 return kErrorHardware;
539 }
540
541 Sys::close_(fd);
542
543 return kErrorNone;
544}
545
546DisplayError HWPeripheralDRM::GetPanelBrightness(int *level) {
547 char value[kMaxStringLength] = {0};
548
549 if (!level) {
550 DLOGE("Invalid input, null pointer.");
551 return kErrorParameters;
552 }
553
554 if (brightness_base_path_.empty()) {
555 return kErrorHardware;
556 }
557
558 std::string brightness_node(brightness_base_path_ + "brightness");
559 int fd = Sys::open_(brightness_node.c_str(), O_RDWR);
560 if (fd < 0) {
561 DLOGE("Failed to open brightness node = %s, error = %s", brightness_node.c_str(),
562 strerror(errno));
563 return kErrorFileDescriptor;
564 }
565
566 if (Sys::pread_(fd, value, sizeof(value), 0) > 0) {
567 *level = atoi(value);
568 } else {
569 DLOGE("Failed to read panel brightness");
570 Sys::close_(fd);
571 return kErrorHardware;
572 }
573
574 Sys::close_(fd);
575
576 return kErrorNone;
577}
578
579void HWPeripheralDRM::GetHWPanelMaxBrightness() {
580 char value[kMaxStringLength] = {0};
581 hw_panel_info_.panel_max_brightness = 255.0f;
582
583 // Panel nodes, driver connector creation, and DSI probing all occur in sync, for each DSI. This
584 // means that the connector_type_id - 1 will reflect the same # as the panel # for panel node.
585 char s[kMaxStringLength] = {};
586 snprintf(s, sizeof(s), "/sys/class/backlight/panel%d-backlight/",
587 static_cast<int>(connector_info_.type_id - 1));
588 brightness_base_path_.assign(s);
589
590 std::string brightness_node(brightness_base_path_ + "max_brightness");
591 int fd = Sys::open_(brightness_node.c_str(), O_RDONLY);
592 if (fd < 0) {
593 DLOGE("Failed to open max brightness node = %s, error = %s", brightness_node.c_str(),
594 strerror(errno));
595 return;
596 }
597
598 if (Sys::pread_(fd, value, sizeof(value), 0) > 0) {
599 hw_panel_info_.panel_max_brightness = static_cast<float>(atof(value));
600 DLOGI_IF(kTagDriverConfig, "Max brightness = %f", hw_panel_info_.panel_max_brightness);
601 } else {
602 DLOGE("Failed to read max brightness. error = %s", strerror(errno));
603 }
604
605 Sys::close_(fd);
606 return;
607}
Saurabh Shah82b06f42017-09-06 16:43:49 -0700608} // namespace sdm