blob: 1653b6b989d0cc4465beeb0eaa76bd3e94588707 [file] [log] [blame]
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef __HW_DEVICE_DRM_H__
#define __HW_DEVICE_DRM_H__
#include <utils/formats.h>
#include <private/hw_interface.h>
#include <drm_interface.h>
#include <errno.h>
#include <pthread.h>
#include <xf86drmMode.h>
#include <atomic>
#include <string>
#include <unordered_map>
#include <vector>
#include <memory>
#include <mutex>
#include "hw_scale_drm.h"
#include "hw_color_manager_drm.h"
#define IOCTL_LOGE(ioctl, type) \
DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, type, errno, strerror(errno))
#define UI_FBID_LIMIT 4
#define VIDEO_FBID_LIMIT 32
#define OFFLINE_ROTATOR_FBID_LIMIT 2
using sde_drm::DRMPowerMode;
namespace sdm {
class HWInfoInterface;
struct SDECsc {
struct sde_drm_csc_v1 csc_v1 = {};
// More here, maybe in a union
};
struct HWCwbConfig {
bool enabled = false;
int32_t cwb_disp_id = -1; // set only in CWB setup or CWB teardown frame. Set to
// display id of the cwb setup/teardown performing display.
sde_drm::DRMDisplayToken token = {}; // display token to be used for virtual connector while CWB
};
class HWDeviceDRM : public HWInterface {
public:
HWDeviceDRM(BufferAllocator *buffer_allocator, HWInfoInterface *hw_info_intf);
virtual ~HWDeviceDRM() {}
virtual DisplayError Init();
virtual DisplayError Deinit();
void GetDRMDisplayToken(sde_drm::DRMDisplayToken *token) const;
bool IsPrimaryDisplay() const { return hw_panel_info_.is_primary_panel; }
virtual PanelFeaturePropertyIntf *GetPanelFeaturePropertyIntf() { return nullptr; }
virtual DisplayError GetPanelBrightnessBasePath(std::string *base_path) const {
return kErrorNotSupported;
}
protected:
// From HWInterface
virtual DisplayError GetDisplayId(int32_t *display_id);
virtual DisplayError GetActiveConfig(uint32_t *active_config);
virtual DisplayError GetDefaultConfig(uint32_t *default_config) { return kErrorNotSupported; }
virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
virtual DisplayError GetDisplayAttributes(uint32_t index,
HWDisplayAttributes *display_attributes);
virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
virtual DisplayError PowerOn(const HWQosData &qos_data, SyncPoints *sync_points);
virtual DisplayError PowerOff(bool teardown, SyncPoints *sync_points);
virtual DisplayError Doze(const HWQosData &qos_data, SyncPoints *sync_points);
virtual DisplayError DozeSuspend(const HWQosData &qos_data, SyncPoints *sync_points);
virtual DisplayError Standby(SyncPoints *sync_points);
virtual DisplayError Validate(HWLayersInfo *hw_layers_info);
virtual DisplayError Commit(HWLayersInfo *hw_layers_info);
virtual DisplayError Flush(HWLayersInfo *hw_layers_info);
DisplayError SetupConcurrentWritebackModes();
bool SetupConcurrentWriteback(const HWLayersInfo &hw_layer_info, bool validate,
int64_t *release_fence_fd);
DisplayError TeardownConcurrentWriteback(void);
void ConfigureConcurrentWriteback(const HWLayersInfo &hw_layer_info);
void PostCommitConcurrentWriteback(std::shared_ptr<LayerBuffer> output_buffer);
virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
virtual DisplayError SetPPFeature(PPFeatureInfo *feature);
// This API is no longer supported, expectation is to call the correct API on HWEvents
virtual DisplayError SetVSyncState(bool enable);
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
virtual DisplayError SetPanelBrightness(int level) { return kErrorNotSupported; }
virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info);
virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format);
virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
virtual DisplayError SetCursorPosition(HWLayersInfo *hw_layers_info, int x, int y);
virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
virtual DisplayError GetPanelBrightness(int *level) { return kErrorNotSupported; }
virtual void GetHWPanelMaxBrightness() { return; }
virtual DisplayError SetAutoRefresh(bool enable) { autorefresh_ = enable; return kErrorNone; }
virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
virtual DisplayError UnsetScaleLutConfig();
virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
virtual void InitializeConfigs();
virtual DisplayError DumpDebugData();
virtual void PopulateHWPanelInfo();
virtual DisplayError SetDppsFeature(void *payload, size_t size) { return kErrorNotSupported; }
virtual DisplayError GetDppsFeatureInfo(void *payload, size_t size) { return kErrorNotSupported; }
virtual DisplayError HandleSecureEvent(SecureEvent secure_event, const HWQosData &qos_data) {
switch (secure_event) {
case kTUITransitionPrepare:
case kTUITransitionUnPrepare:
tui_state_ = kTUIStateInProgress;
break;
case kTUITransitionStart:
tui_state_ = kTUIStateStart;
break;
case kTUITransitionEnd:
tui_state_ = kTUIStateEnd;
break;
default:
break;
}
return kErrorNone;
}
virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
return kErrorNotSupported;
}
virtual DisplayError SetDisplayDppsAdROI(void *payload) { return kErrorNotSupported; }
virtual DisplayError SetJitterConfig(uint32_t jitter_type, float value, uint32_t time);
virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate);
virtual DisplayError GetDynamicDSIClock(uint64_t *bit_clk_rate);
virtual DisplayError GetDisplayIdentificationData(uint8_t *out_port, uint32_t *out_data_size,
uint8_t *out_data);
virtual DisplayError SetFrameTrigger(FrameTriggerMode mode) { return kErrorNotSupported; }
virtual DisplayError SetBLScale(uint32_t level) { return kErrorNotSupported; }
virtual DisplayError SetBlendSpace(const PrimariesTransfer &blend_space);
virtual DisplayError EnableSelfRefresh(SelfRefreshState self_refresh_state) {
return kErrorNotSupported;
}
virtual DisplayError GetFeatureSupportStatus(const HWFeature feature, uint32_t *status);
virtual void FlushConcurrentWriteback();
virtual DisplayError UpdateTransferTime(uint32_t transfer_time);
virtual DisplayError SetAlternateDisplayConfig(uint32_t *alt_config) {
return kErrorNotSupported;
}
virtual DisplayError CancelDeferredPowerMode();
virtual void HandleCwbTeardown();
enum {
kHWEventVSync,
kHWEventBlank,
};
enum TUIState {
kTUIStateNone,
kTUIStateStart,
kTUIStateInProgress,
kTUIStateEnd,
};
static const int kMaxStringLength = 1024;
static const int kNumPhysicalDisplays = 2;
static const int kMaxSysfsCommandLength = 12;
DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format, uint32_t width,
uint32_t *target);
DisplayError PopulateDisplayAttributes(uint32_t index);
void GetHWDisplayPortAndMode();
bool EnableHotPlugDetection(int enable);
void UpdateMixerAttributes();
void SetSolidfillStages();
void AddSolidfillStage(const HWSolidfillStage &sf, uint32_t plane_alpha);
void ClearSolidfillStages();
void SetNoiseLayerConfig(const NoiseLayerConfig &noise_config);
void ApplyNoiseLayerConfig();
void ClearNoiseLayerConfig();
void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
void SetSrcConfig(const LayerBuffer &input_buffer, const HWRotatorMode &mode, uint32_t *config);
void SelectCscType(const LayerBuffer &input_buffer, sde_drm::DRMCscType *type);
void SelectFp16Config(const LayerBuffer &input_buffer, int *igc_en, int *unmult_en,
sde_drm::DRMFp16CscType *csc_type, drm_msm_fp16_gc *gc,
LayerBlending blend);
void SetRect(const LayerRect &source, sde_drm::DRMRect *target);
void SetRotation(LayerTransform transform, const HWLayerConfig &layer_config,
uint32_t* rot_bit_mask);
DisplayError DefaultCommit(HWLayersInfo *hw_layers_info);
DisplayError AtomicCommit(HWLayersInfo *hw_layers_info);
void SetupAtomic(Fence::ScopedRef &scoped_ref, HWLayersInfo *hw_layers_info, bool validate,
int64_t *release_fence_fd, int64_t *retire_fence_fd);
void SetSecureConfig(const LayerBuffer &input_buffer, sde_drm::DRMSecureMode *fb_secure_mode,
sde_drm::DRMSecurityLevel *security_level);
bool IsResolutionSwitchEnabled() const { return resolution_switch_enabled_; }
void SetTopology(sde_drm::DRMTopology drm_topology, HWTopology *hw_topology);
void SetMultiRectMode(const uint32_t flags, sde_drm::DRMMultiRectMode *target);
void SetSsppTonemapFeatures(HWPipeInfo *pipe_info);
void SetDGMCsc(const HWPipeCscInfo &dgm_csc_info, SDECsc *csc);
void SetDGMCscV1(const HWCsc &dgm_csc, sde_drm_csc_v1 *csc_v1);
void SetSsppLutFeatures(HWPipeInfo *pipe_info);
void AddDimLayerIfNeeded();
DisplayError NullCommit(bool synchronous, bool retain_planes);
void DumpConnectorModeInfo();
void ResetROI();
void SetQOSData(const HWQosData &qos_data);
void DumpHWLayers(HWLayersInfo *hw_layers_info);
bool IsFullFrameUpdate(const HWLayersInfo &hw_layer_info);
DisplayError GetDRMPowerMode(const HWPowerState &power_state, DRMPowerMode *drm_power_mode);
void SetTUIState();
DisplayError ConfigureCWBDither(void *payload, uint32_t conn_id,
sde_drm::DRMCWbCaptureMode mode);
void SetTopologySplit(HWTopology hw_topology, uint32_t *split_number);
uint64_t GetSupportedBitClkRate(uint32_t new_mode_index,
uint64_t bit_clk_rate_request);
DisplayError GetPanelBlMaxLvl(uint32_t *bl_max);
DisplayError SetPPConfig(void *payload, size_t size);
DisplayError GetQsyncFps(uint32_t *qsync_fps) { return kErrorNotSupported; }
class Registry {
public:
explicit Registry(BufferAllocator *buffer_allocator);
// Called on each Validate and Commit to map the handle_id to fb_id of each layer buffer.
void Register(HWLayersInfo *hw_layers_info);
// Called on display disconnect to clear output buffer map and remove fb_ids.
void Clear();
// Create the fd_id for the given buffer.
int CreateFbId(const LayerBuffer &buffer, uint32_t *fb_id);
// Find handle_id in the layer map. Else create fb_id and add <handle_id,fb_id> in map.
void MapBufferToFbId(Layer* layer, const LayerBuffer &buffer);
// Find handle_id in output buffer map. Else create fb_id and add <handle_id,fb_id> in map.
void MapOutputBufferToFbId(std::shared_ptr<LayerBuffer> buffer);
// Find fb_id for given handle_id in the layer map.
uint32_t GetFbId(Layer *layer, uint64_t handle_id);
// Find fb_id for given handle_id in output buffer map.
uint32_t GetOutputFbId(uint64_t handle_id);
private:
bool disable_fbid_cache_ = false;
std::unordered_map<uint64_t, std::shared_ptr<LayerBufferObject>> output_buffer_map_ {};
BufferAllocator *buffer_allocator_ = {};
uint8_t fbid_cache_limit_ = UI_FBID_LIMIT;
};
protected:
void SetDisplaySwitchMode(uint32_t index);
bool IsSeamlessTransition() {
return (hw_panel_info_.dynamic_fps && (vrefresh_ || seamless_mode_switch_)) ||
panel_mode_changed_ || bit_clk_rate_;
}
const char *device_name_ = {};
bool default_mode_ = false;
int32_t display_id_ = -1;
sde_drm::DRMDisplayType disp_type_ = {};
HWInfoInterface *hw_info_intf_ = {};
int dev_fd_ = -1;
Registry registry_;
sde_drm::DRMDisplayToken token_ = {};
HWResourceInfo hw_resource_ = {};
HWPanelInfo hw_panel_info_ = {};
HWScaleDRM *hw_scale_ = {};
sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
sde_drm::DRMAtomicReqInterface *drm_atomic_intf_ = {};
std::vector<HWDisplayAttributes> display_attributes_ = {};
uint32_t current_mode_index_ = 0;
sde_drm::DRMConnectorInfo connector_info_ = {};
bool first_cycle_ = true;
bool first_null_cycle_ = true;
HWMixerAttributes mixer_attributes_ = {};
std::vector<sde_drm::DRMSolidfillStage> solid_fills_ {};
sde_drm::DRMNoiseLayerConfig noise_cfg_ = {};
bool secure_display_active_ = false;
TUIState tui_state_ = kTUIStateNone;
uint64_t debug_dump_count_ = 0;
bool synchronous_commit_ = false;
uint32_t topology_control_ = 0;
uint32_t vrefresh_ = 0;
uint32_t panel_mode_changed_ = 0;
uint32_t panel_compression_changed_ = 0;
bool reset_output_fence_offset_ = false;
uint64_t bit_clk_rate_ = 0;
bool update_mode_ = false;
HWPowerState pending_power_state_ = kPowerStateNone;
uint32_t video_mode_index_ = 0;
uint32_t cmd_mode_index_ = 0;
bool switch_mode_valid_ = false;
bool doze_poms_switch_done_ = false;
bool pending_poms_switch_ = false;
bool active_ = false;
bool pending_cwb_teardown_ = false;
PrimariesTransfer blend_space_ = {};
DRMPowerMode last_power_mode_ = DRMPowerMode::OFF;
uint32_t dest_scaler_blocks_used_ = 0; // Dest scaler blocks in use by this HWDeviceDRM instance.
// Destination scaler blocks in use by all HWDeviceDRM instances.
static std::atomic<uint32_t> hw_dest_scaler_blocks_used_;
static bool reset_planes_luts_;
bool has_cwb_crop_ = false; // virtual connector supports CWB ROI feature.
bool has_dedicated_cwb_ = false; // virtual connector supports dedicated CWB feature.
bool has_cwb_dither_ = false; // virtual connector supports CWB Dither feature.
static HWCwbConfig cwb_config_;
static std::mutex cwb_state_lock_; // cwb state lock. Set before accesing or updating cwb_config_
uint32_t transfer_time_updated_ = 0;
bool force_tonemapping_ = false;
private:
void GetCWBCapabilities();
std::string interface_str_ = "DSI";
bool resolution_switch_enabled_ = false;
bool autorefresh_ = false;
std::unique_ptr<HWColorManagerDrm> hw_color_mgr_ = {};
bool seamless_mode_switch_ = false;
float aspect_ratio_threshold_ = 1.0;
};
} // namespace sdm
#endif // __HW_DEVICE_DRM_H__