blob: f70984eb34a3f516bdc9e759f6a6452b1cf71de7 [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);
Xu Yang32e58c22017-11-20 09:58:11 +0800279 drm_mgr_intf_->GetDppsFeatureInfo(feature_info);
280 return kErrorNone;
281}
Ramkumar Radhakrishnan7e971e02017-08-17 14:19:15 +0530282
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +0530283DisplayError HWPeripheralDRM::HandleSecureEvent(SecureEvent secure_event, HWLayers *hw_layers) {
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -0700284 switch (secure_event) {
285 case kSecureDisplayStart: {
286 secure_display_active_ = true;
287 if (hw_panel_info_.mode != kModeCommand) {
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +0530288 DisplayError err = Flush(hw_layers);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -0700289 if (err != kErrorNone) {
290 return err;
291 }
292 }
293 }
294 break;
295
296 case kSecureDisplayEnd: {
297 if (hw_panel_info_.mode != kModeCommand) {
Pullakavi Srinivas0a1dba62018-07-02 15:49:11 +0530298 DisplayError err = Flush(hw_layers);
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -0700299 if (err != kErrorNone) {
300 return err;
301 }
302 }
303 secure_display_active_ = false;
Ramkumar Radhakrishnand25d30e2018-08-17 11:06:27 -0700304 synchronous_commit_ = true;
Ramkumar Radhakrishnana38b7602018-03-15 14:49:52 -0700305 }
306 break;
307
308 default:
309 DLOGE("Invalid secure event %d", secure_event);
310 return kErrorNotSupported;
311 }
312
313 return kErrorNone;
314}
315
Sushil Chauhan06521582018-03-19 14:00:23 -0700316void HWPeripheralDRM::SetupConcurrentWriteback(const HWLayersInfo &hw_layer_info, bool validate) {
317 bool enable = hw_resource_.has_concurrent_writeback && hw_layer_info.stack->output_buffer;
318 if (!(enable || cwb_config_.enabled)) {
319 return;
320 }
321
322 bool setup_modes = enable && !cwb_config_.enabled && validate;
323 if (setup_modes && (SetupConcurrentWritebackModes() == kErrorNone)) {
324 cwb_config_.enabled = true;
325 }
326
327 if (cwb_config_.enabled) {
328 if (enable) {
329 // Set DRM properties for Concurrent Writeback.
330 ConfigureConcurrentWriteback(hw_layer_info.stack);
Prabhanjan Kandula9e9c2322018-06-06 18:07:15 -0700331
332 if (!validate) {
333 // Set GET_RETIRE_FENCE property to get Concurrent Writeback fence.
334 int *fence = &hw_layer_info.stack->output_buffer->release_fence_fd;
335 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE,
336 cwb_config_.token.conn_id, fence);
337 }
Gurpreet Singh Dhamif8a9b842018-12-21 17:36:29 -0500338 } else {
339 // Tear down the Concurrent Writeback topology.
340 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, 0);
Sushil Chauhan06521582018-03-19 14:00:23 -0700341 }
342 }
343}
344
Gurpreet Singh Dhami1207e462018-12-27 20:02:02 -0500345DisplayError HWPeripheralDRM::TeardownConcurrentWriteback(void) {
346 if (cwb_config_.enabled) {
Varun Arora6ba9eda2019-02-07 17:59:32 -0800347 drm_mgr_intf_->UnregisterDisplay(&(cwb_config_.token));
Gurpreet Singh Dhami1207e462018-12-27 20:02:02 -0500348 cwb_config_.enabled = false;
349 registry_.Clear();
350 }
351
352 return kErrorNone;
353}
354
Sushil Chauhan06521582018-03-19 14:00:23 -0700355DisplayError HWPeripheralDRM::SetupConcurrentWritebackModes() {
356 // To setup Concurrent Writeback topology, get the Connector ID of Virtual display
357 if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::VIRTUAL, &cwb_config_.token)) {
358 DLOGE("RegisterDisplay failed for Concurrent Writeback");
359 return kErrorResources;
360 }
361
362 // Set the modes based on Primary display.
363 std::vector<drmModeModeInfo> modes;
364 for (auto &item : connector_info_.modes) {
365 modes.push_back(item.mode);
366 }
367
368 // Inform the mode list to driver.
369 struct sde_drm_wb_cfg cwb_cfg = {};
370 cwb_cfg.connector_id = cwb_config_.token.conn_id;
371 cwb_cfg.flags = SDE_DRM_WB_CFG_FLAGS_CONNECTED;
372 cwb_cfg.count_modes = UINT32(modes.size());
373 cwb_cfg.modes = (uint64_t)modes.data();
374
375 int ret = -EINVAL;
376#ifdef DRM_IOCTL_SDE_WB_CONFIG
377 ret = drmIoctl(dev_fd_, DRM_IOCTL_SDE_WB_CONFIG, &cwb_cfg);
378#endif
379 if (ret) {
Varun Arora6ba9eda2019-02-07 17:59:32 -0800380 drm_mgr_intf_->UnregisterDisplay(&(cwb_config_.token));
Sushil Chauhan06521582018-03-19 14:00:23 -0700381 DLOGE("Dump CWBConfig: mode_count %d flags %x", cwb_cfg.count_modes, cwb_cfg.flags);
382 DumpConnectorModeInfo();
383 return kErrorHardware;
384 }
385
386 return kErrorNone;
387}
388
389void HWPeripheralDRM::ConfigureConcurrentWriteback(LayerStack *layer_stack) {
390 LayerBuffer *output_buffer = layer_stack->output_buffer;
Sushil Chauhanabc5b272018-06-20 16:18:13 -0700391 registry_.MapOutputBufferToFbId(output_buffer);
Sushil Chauhan06521582018-03-19 14:00:23 -0700392
393 // Set the topology for Concurrent Writeback: [CRTC_PRIMARY_DISPLAY - CONNECTOR_VIRTUAL_DISPLAY].
394 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, token_.crtc_id);
395
396 // Set CRTC Capture Mode
397 DRMCWbCaptureMode capture_mode = layer_stack->flags.post_processed_output ?
398 DRMCWbCaptureMode::DSPP_OUT : DRMCWbCaptureMode::MIXER_OUT;
399 drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CAPTURE_MODE, token_.crtc_id, capture_mode);
400
401 // Set Connector Output FB
Sushil Chauhanabc5b272018-06-20 16:18:13 -0700402 uint32_t fb_id = registry_.GetOutputFbId(output_buffer->handle_id);
Sushil Chauhan06521582018-03-19 14:00:23 -0700403 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_FB_ID, cwb_config_.token.conn_id, fb_id);
404
405 // Set Connector Secure Mode
406 bool secure = output_buffer->flags.secure;
407 DRMSecureMode mode = secure ? DRMSecureMode::SECURE : DRMSecureMode::NON_SECURE;
408 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_FB_SECURE_MODE, cwb_config_.token.conn_id, mode);
409
410 // Set Connector Output Rect
411 sde_drm::DRMRect dst = {};
412 dst.left = 0;
413 dst.top = 0;
414 dst.right = display_attributes_[current_mode_index_].x_pixels;
415 dst.bottom = display_attributes_[current_mode_index_].y_pixels;
416 drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_RECT, cwb_config_.token.conn_id, dst);
417}
418
419void HWPeripheralDRM::PostCommitConcurrentWriteback(LayerBuffer *output_buffer) {
420 bool enabled = hw_resource_.has_concurrent_writeback && output_buffer;
421
Gurpreet Singh Dhamif8a9b842018-12-21 17:36:29 -0500422 if (!enabled) {
Gurpreet Singh Dhami1207e462018-12-27 20:02:02 -0500423 TeardownConcurrentWriteback();
Sushil Chauhan06521582018-03-19 14:00:23 -0700424 }
425}
426
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700427DisplayError HWPeripheralDRM::ControlIdlePowerCollapse(bool enable, bool synchronous) {
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700428 if (enable == idle_pc_enabled_) {
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700429 return kErrorNone;
430 }
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700431 idle_pc_state_ = enable ? sde_drm::DRMIdlePCState::ENABLE : sde_drm::DRMIdlePCState::DISABLE;
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700432 // As idle PC is disabled after subsequent commit, Make sure to have synchrounous commit and
433 // ensure TA accesses the display_cc registers after idle PC is disabled.
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700434 synchronous_commit_ = !enable ? synchronous : false;
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700435 idle_pc_enabled_ = enable;
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700436 return kErrorNone;
437}
438
439DisplayError HWPeripheralDRM::PowerOn(const HWQosData &qos_data, int *release_fence) {
440 DTRACE_SCOPED();
441 if (!drm_atomic_intf_) {
442 DLOGE("DRM Atomic Interface is null!");
443 return kErrorUndefined;
444 }
445
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700446 if (!idle_pc_enabled_) {
447 drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_IDLE_PC_STATE, token_.crtc_id,
448 sde_drm::DRMIdlePCState::ENABLE);
449 }
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700450 DisplayError err = HWDeviceDRM::PowerOn(qos_data, release_fence);
451 if (err != kErrorNone) {
452 return err;
453 }
Ramkumar Radhakrishnan4998e4f2019-04-24 18:50:51 -0700454 idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
455 idle_pc_enabled_ = true;
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700456
457 return kErrorNone;
458}
459
Pullakavi Srinivas9189e602018-12-19 16:58:07 +0530460DisplayError HWPeripheralDRM::SetDisplayAttributes(uint32_t index) {
461 HWDeviceDRM::SetDisplayAttributes(index);
462 // update bit clk rates.
463 hw_panel_info_.bitclk_rates = bitclk_rates_;
464
465 return kErrorNone;
466}
467
Yuchao Ma577f0f72018-07-09 11:20:00 +0800468DisplayError HWPeripheralDRM::SetDisplayDppsAdROI(void *payload) {
469 DisplayError err = kErrorNone;
470 struct sde_drm::DppsFeaturePayload feature_payload = {};
471
472 if (!payload) {
473 DLOGE("Invalid payload parameter");
474 return kErrorParameters;
475 }
476
477 feature_payload.object_type = DRM_MODE_OBJECT_CRTC;
478 feature_payload.feature_id = sde_drm::kFeatureAd4Roi;
479 feature_payload.value = (uint64_t)(payload);
480
481 err = SetDppsFeature(&feature_payload, sizeof(feature_payload));
482 if (err != kErrorNone) {
483 DLOGE("Faid to SetDppsFeature feature_id = %d, err = %d",
484 sde_drm::kFeatureAd4Roi, err);
485 }
486
487 return err;
488}
489
Xu Yang27aaea32018-12-19 15:53:56 +0800490DisplayError HWPeripheralDRM::SetFrameTrigger(FrameTriggerMode mode) {
491 sde_drm::DRMFrameTriggerMode drm_mode = sde_drm::DRMFrameTriggerMode::FRAME_DONE_WAIT_DEFAULT;
492 switch (mode) {
493 case kFrameTriggerDefault:
494 drm_mode = sde_drm::DRMFrameTriggerMode::FRAME_DONE_WAIT_DEFAULT;
495 break;
496 case kFrameTriggerSerialize:
497 drm_mode = sde_drm::DRMFrameTriggerMode::FRAME_DONE_WAIT_SERIALIZE;
498 break;
499 case kFrameTriggerPostedStart:
500 drm_mode = sde_drm::DRMFrameTriggerMode::FRAME_DONE_WAIT_POSTED_START;
501 break;
502 default:
503 DLOGE("Invalid frame trigger mode %d", (int32_t)mode);
504 return kErrorParameters;
505 }
506
507 int ret = drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_FRAME_TRIGGER,
508 token_.conn_id, drm_mode);
509 if (ret) {
510 DLOGE("Failed to perform CONNECTOR_SET_FRAME_TRIGGER, drm_mode %d, ret %d", drm_mode, ret);
511 return kErrorUndefined;
512 }
513 return kErrorNone;
514}
515
Varun Arora75c05f02019-05-14 14:53:37 -0700516DisplayError HWPeripheralDRM::SetPanelBrightness(int level) {
517 char buffer[kMaxSysfsCommandLength] = {0};
518
519 if (brightness_base_path_.empty()) {
520 return kErrorHardware;
521 }
522
523 std::string brightness_node(brightness_base_path_ + "brightness");
524 int fd = Sys::open_(brightness_node.c_str(), O_RDWR);
525 if (fd < 0) {
526 DLOGE("Failed to open node = %s, error = %s ", brightness_node.c_str(),
527 strerror(errno));
528 return kErrorFileDescriptor;
529 }
530
531 int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level);
532 ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);
533 if (ret <= 0) {
534 DLOGE("Failed to write to node = %s, error = %s ", brightness_node.c_str(),
535 strerror(errno));
536 Sys::close_(fd);
537 return kErrorHardware;
538 }
539
540 Sys::close_(fd);
541
542 return kErrorNone;
543}
544
545DisplayError HWPeripheralDRM::GetPanelBrightness(int *level) {
546 char value[kMaxStringLength] = {0};
547
548 if (!level) {
549 DLOGE("Invalid input, null pointer.");
550 return kErrorParameters;
551 }
552
553 if (brightness_base_path_.empty()) {
554 return kErrorHardware;
555 }
556
557 std::string brightness_node(brightness_base_path_ + "brightness");
558 int fd = Sys::open_(brightness_node.c_str(), O_RDWR);
559 if (fd < 0) {
560 DLOGE("Failed to open brightness node = %s, error = %s", brightness_node.c_str(),
561 strerror(errno));
562 return kErrorFileDescriptor;
563 }
564
565 if (Sys::pread_(fd, value, sizeof(value), 0) > 0) {
566 *level = atoi(value);
567 } else {
568 DLOGE("Failed to read panel brightness");
569 Sys::close_(fd);
570 return kErrorHardware;
571 }
572
573 Sys::close_(fd);
574
575 return kErrorNone;
576}
577
578void HWPeripheralDRM::GetHWPanelMaxBrightness() {
579 char value[kMaxStringLength] = {0};
580 hw_panel_info_.panel_max_brightness = 255.0f;
581
582 // Panel nodes, driver connector creation, and DSI probing all occur in sync, for each DSI. This
583 // means that the connector_type_id - 1 will reflect the same # as the panel # for panel node.
584 char s[kMaxStringLength] = {};
585 snprintf(s, sizeof(s), "/sys/class/backlight/panel%d-backlight/",
586 static_cast<int>(connector_info_.type_id - 1));
587 brightness_base_path_.assign(s);
588
589 std::string brightness_node(brightness_base_path_ + "max_brightness");
590 int fd = Sys::open_(brightness_node.c_str(), O_RDONLY);
591 if (fd < 0) {
592 DLOGE("Failed to open max brightness node = %s, error = %s", brightness_node.c_str(),
593 strerror(errno));
594 return;
595 }
596
597 if (Sys::pread_(fd, value, sizeof(value), 0) > 0) {
598 hw_panel_info_.panel_max_brightness = static_cast<float>(atof(value));
599 DLOGI_IF(kTagDriverConfig, "Max brightness = %f", hw_panel_info_.panel_max_brightness);
600 } else {
601 DLOGE("Failed to read max brightness. error = %s", strerror(errno));
602 }
603
604 Sys::close_(fd);
605 return;
606}
Saurabh Shah82b06f42017-09-06 16:43:49 -0700607} // namespace sdm