sdm: Add support for SSPP Tonemapping
- Add interfaces in SDM to support SSPP Tonemapping.
- Get the SSPP tonemap caps from the drm interface and
populate the SDM private interfaces.
- Add support to set the sspp tonemap config to drm planes.
- Handle Idle PowerCollapse event for SSPP luts.
Crs-fixed: 2200881
Change-Id: I38590915fd05e5cc77f38cd1df4724f43990045b
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index afa120e..f85a337 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -193,6 +193,10 @@
uint32_t flip_buffer: 1; //!< This flag will be set by SDM when the layer needs FBT flip
uint32_t dest_tone_map : 1; //!< This flag will be set by SDM when the layer needs
//!< destination tone map
+ uint32_t src_3d_tone_map: 1; //!< This flag will be set by SDM when the layer needs
+ //!< 3d tonemap
+ uint32_t src_1d_tone_map: 1; //!< This flag will be set by SDM when the layer needs
+ //!< 1d tone map
};
uint32_t request_flags = 0; //!< For initialization purpose only.
//!< Shall not be refered directly.
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index c9b5782..7526544 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -32,6 +32,7 @@
#include <map>
#include <string>
#include <bitset>
+#include <memory>
namespace sdm {
using std::string;
@@ -44,6 +45,11 @@
#define MINOR 16
#define SDEVERSION(major, minor, hw_rev) ((major) << MAJOR) | ((minor) << MINOR) | (hw_rev)
+// CSC Max Size
+#define MAX_CSC_MATRIX_COEFF_SIZE 9
+#define MAX_CSC_CLAMP_SIZE 6
+#define MAX_CSC_BIAS_SIZE 3
+
enum HWDeviceType {
kDevicePrimary,
kDeviceHDMI,
@@ -131,6 +137,25 @@
kHdrEOTFHLG = 0x8,
};
+enum HWSrcTonemap {
+ kSrcTonemap1d, // DMA
+ kSrcTonemap3d, // VIG
+};
+
+enum HWToneMapLut {
+ kLutNone, // No valid lut
+ kDma1dIgc, // DMA IGC Lut
+ kDma1dGc, // DMA GC Lut
+ kVig1dIgc, // VIG IGC Lut
+ kVig3dGamut, // 3D Gamut Lut
+};
+
+enum HWWriteOperation {
+ kNoOp, // No-op, previously set config holds good
+ kSet, // Sets the new config
+ kReset, // Resets/Clears the previously set config
+};
+
typedef std::map<HWSubBlockType, std::vector<LayerBufferFormat>> FormatsMap;
typedef std::map<LayerBufferFormat, float> CompRatioMap;
@@ -158,6 +183,9 @@
uint32_t id = 0;
uint32_t master_pipe_id = 0;
uint32_t max_rects = 1;
+ bool inverse_pma = 0;
+ uint32_t dgm_csc_version = 0;
+ std::map<HWToneMapLut, uint32_t> tm_lut_version_map = {};
};
struct HWRotatorInfo {
@@ -257,6 +285,7 @@
HWQseedStepVersion pipe_qseed3_version = kQseed3v2; // only valid when has_qseed3=true
uint32_t min_prefill_lines = 0;
InlineRotationVersion inrot_version = kInlineRotationNone;
+ std::bitset<32> src_tone_map = 0; //!< Stores the bit mask of src tone map capability
};
struct HWSplitInfo {
@@ -447,6 +476,14 @@
uint32_t src_height = 0;
};
+struct HWCsc {
+ int64_t ctm_coeff[MAX_CSC_MATRIX_COEFF_SIZE] = {0};
+ uint32_t pre_bias[MAX_CSC_BIAS_SIZE] = {0};
+ uint32_t post_bias[MAX_CSC_BIAS_SIZE] = {0};
+ uint32_t pre_clamp[MAX_CSC_CLAMP_SIZE] = {0};
+ uint32_t post_clamp[MAX_CSC_CLAMP_SIZE] = {0};
+};
+
struct HWScaleData {
struct enable {
uint8_t scale = 0;
@@ -495,6 +532,22 @@
HWAVRModes mode = kContinuousMode; // Specifies the AVR mode
};
+struct HWPipeCscInfo {
+ HWWriteOperation op = kNoOp;
+ HWCsc csc = {};
+};
+
+struct HWPipeTonemapLutInfo {
+ HWWriteOperation op = kNoOp;
+ HWToneMapLut type = kLutNone;
+ std::shared_ptr<PPFeatureInfo> pay_load = nullptr;
+};
+
+struct HWPipeTonemapInversePma {
+ HWWriteOperation op = kNoOp;
+ bool inverse_pma = false;
+};
+
struct HWPipeInfo {
HWPipeInfo *pair = NULL;
uint8_t rect = 255;
@@ -510,6 +563,9 @@
uint8_t flags = 0;
bool valid = false;
bool is_virtual = 0;
+ HWPipeTonemapInversePma inverse_pma_info = {};
+ HWPipeCscInfo dgm_csc_info = {};
+ std::vector<HWPipeTonemapLutInfo> lut_info = {};
};
struct HWSolidfillStage {
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 1e75298..b9d047c 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2018, 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:
@@ -33,7 +33,7 @@
class ResourceInterface {
public:
enum ResourceCmd {
- kCmdResetScalarLUT,
+ kCmdResetLUT,
kCmdMax,
};
diff --git a/sdm/include/utils/utils.h b/sdm/include/utils/utils.h
index b1c55c4..b10fd6b 100644
--- a/sdm/include/utils/utils.h
+++ b/sdm/include/utils/utils.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016 - 2018, 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
@@ -30,6 +30,8 @@
#ifndef __UTILS_H__
#define __UTILS_H__
+#include <cstring>
+
namespace sdm {
float gcd(float a, float b);
@@ -43,6 +45,11 @@
DriverType GetDriverType();
+template<class T>
+bool SameConfig(T *t1, T *t2, unsigned int size) {
+ return !(std::memcmp(t1, t2, size));
+}
+
} // namespace sdm
#endif // __UTILS_H__
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 3acdcf0..45fc57d 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -426,7 +426,7 @@
reinterpret_cast<DisplayCompositionContext *>(display_ctx);
if (display_comp_ctx) {
- resource_intf_->Perform(ResourceInterface::kCmdResetScalarLUT,
+ resource_intf_->Perform(ResourceInterface::kCmdResetLUT,
display_comp_ctx->display_resource_ctx);
}
}
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index fa413bb..18de450 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -102,6 +102,24 @@
namespace sdm {
+static PPBlock GetPPBlock(const HWToneMapLut &lut_type) {
+ PPBlock pp_block = kPPBlockMax;
+ switch (lut_type) {
+ case kDma1dIgc:
+ case kDma1dGc:
+ pp_block = kDGM;
+ break;
+ case kVig1dIgc:
+ case kVig3dGamut:
+ pp_block = kVIG;
+ break;
+ default:
+ DLOGE("Unknown PP Block");
+ break;
+ }
+ return pp_block;
+}
+
static void GetDRMFormat(LayerBufferFormat format, uint32_t *drm_format,
uint64_t *drm_format_modifier) {
switch (format) {
@@ -951,6 +969,8 @@
DRMMultiRectMode multirect_mode;
SetMultiRectMode(pipe_info->flags, &multirect_mode);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_MULTIRECT_MODE, pipe_id, multirect_mode);
+
+ SetSsppTonemapFeatures(pipe_info);
}
}
}
@@ -1608,6 +1628,7 @@
}
}
+
void HWDeviceDRM::SetMultiRectMode(const uint32_t flags, DRMMultiRectMode *target) {
*target = DRMMultiRectMode::NONE;
if (flags & kMultiRect) {
@@ -1618,4 +1639,74 @@
}
}
+void HWDeviceDRM::SetSsppTonemapFeatures(HWPipeInfo *pipe_info) {
+ if (pipe_info->dgm_csc_info.op != kNoOp) {
+ SDECsc csc = {};
+ SetDGMCsc(pipe_info->dgm_csc_info, &csc);
+ DLOGV_IF(kTagDriverConfig, "Call Perform DGM CSC Op = %s",
+ (pipe_info->dgm_csc_info.op == kSet) ? "Set" : "Reset");
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DGM_CSC_CONFIG, pipe_info->pipe_id,
+ reinterpret_cast<uint64_t>(&csc.csc_v1));
+ }
+ if (pipe_info->inverse_pma_info.op != kNoOp) {
+ DLOGV_IF(kTagDriverConfig, "Call Perform Inverse PMA Op = %s",
+ (pipe_info->inverse_pma_info.op == kSet) ? "Set" : "Reset");
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_INVERSE_PMA, pipe_info->pipe_id,
+ (pipe_info->inverse_pma_info.inverse_pma) ? 1: 0);
+ }
+ SetSsppLutFeatures(pipe_info);
+}
+
+void HWDeviceDRM::SetDGMCsc(const HWPipeCscInfo &dgm_csc_info, SDECsc *csc) {
+ SetDGMCscV1(dgm_csc_info.csc, &csc->csc_v1);
+}
+
+void HWDeviceDRM::SetDGMCscV1(const HWCsc &dgm_csc, sde_drm_csc_v1 *csc_v1) {
+ uint32_t i = 0;
+ for (i = 0; i < MAX_CSC_MATRIX_COEFF_SIZE; i++) {
+ csc_v1->ctm_coeff[i] = dgm_csc.ctm_coeff[i];
+ DLOGV_IF(kTagDriverConfig, " DGM csc_v1[%d] = %d", i, csc_v1->ctm_coeff[i]);
+ }
+ for (i = 0; i < MAX_CSC_BIAS_SIZE; i++) {
+ csc_v1->pre_bias[i] = dgm_csc.pre_bias[i];
+ csc_v1->post_bias[i] = dgm_csc.post_bias[i];
+ }
+ for (i = 0; i < MAX_CSC_CLAMP_SIZE; i++) {
+ csc_v1->pre_clamp[i] = dgm_csc.pre_clamp[i];
+ csc_v1->post_clamp[i] = dgm_csc.post_clamp[i];
+ }
+}
+
+void HWDeviceDRM::SetSsppLutFeatures(HWPipeInfo *pipe_info) {
+ for (HWPipeTonemapLutInfo &lut_info : pipe_info->lut_info) {
+ if (lut_info.op != kNoOp) {
+ std::shared_ptr<PPFeatureInfo> feature = lut_info.pay_load;
+ if (feature == nullptr) {
+ DLOGE("Null Pointer for Op = %d lut type = %d", lut_info.op, lut_info.type);
+ continue;
+ }
+ DRMPPFeatureInfo kernel_params = {};
+ std::vector<DRMPPFeatureID> drm_id = {};
+ PPBlock pp_block = GetPPBlock(lut_info.type);
+ hw_color_mgr_->ToDrmFeatureId(pp_block, feature->feature_id_, &drm_id);
+ for (DRMPPFeatureID id : drm_id) {
+ kernel_params.id = id;
+ bool disable = (lut_info.op == kReset);
+ DLOGV_IF(kTagDriverConfig, "Lut Type = %d PPBlock = %d Op = %s Disable = %d Feature = %p",
+ lut_info.type, pp_block, (lut_info.op ==kSet) ? "Set" : "Reset", disable,
+ feature.get());
+ int ret = hw_color_mgr_->GetDrmFeature(feature.get(), &kernel_params, disable);
+ if (!ret) {
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_POST_PROC, pipe_info->pipe_id,
+ &kernel_params);
+ hw_color_mgr_->FreeDrmFeatureData(&kernel_params);
+ } else {
+ DLOGE("GetDrmFeature failed for Lut type = %d", lut_info.type);
+ }
+ }
+ drm_id.clear();
+ }
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index a5ed40b..a0782c4 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -49,6 +49,11 @@
namespace sdm {
class HWInfoInterface;
+struct SDECsc {
+ struct sde_drm_csc_v1 csc_v1 = {};
+ // More here, maybe in a union
+};
+
class HWDeviceDRM : public HWInterface {
public:
HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
@@ -135,6 +140,10 @@
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);
class Registry {
public:
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index dc5a557..f15749a 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -73,6 +73,7 @@
using sde_drm::DRMPlanesInfo;
using sde_drm::DRMCrtcInfo;
using sde_drm::DRMPlaneType;
+using sde_drm::DRMTonemapLutType;
using std::vector;
using std::map;
@@ -225,6 +226,7 @@
DLOGI("Has QSEED3 = %d", hw_resource->has_qseed3);
DLOGI("Has UBWC = %d", hw_resource->has_ubwc);
DLOGI("Has Concurrent Writeback = %d", hw_resource->has_concurrent_writeback);
+ DLOGI("Has Src Tonemap = %d", hw_resource->src_tone_map);
DLOGI("Max Low Bw = %" PRIu64 "", hw_resource->max_bandwidth_low);
DLOGI("Max High Bw = % " PRIu64 "", hw_resource->max_bandwidth_high);
DLOGI("Max Pipe Bw = %" PRIu64 " KBps", hw_resource->max_pipe_bw);
@@ -329,6 +331,8 @@
uint32_t vig_pipe_count = 0;
uint32_t dma_pipe_count = 0;
uint32_t virtual_pipe_count = 0;
+ int disable_src_tonemap = 0;
+ Debug::Get()->GetProperty("sdm.disable_src_tonemap", &disable_src_tonemap);
for (auto &pipe_obj : planes) {
if (max_vig_pipes && max_dma_pipes) {
@@ -392,6 +396,39 @@
pipe_caps.master_pipe_id = pipe_obj.second.master_plane_id;
DLOGI("Adding %s Pipe : Id %x, master_pipe_id : Id %x",
name.c_str(), pipe_obj.first, pipe_obj.second.master_plane_id);
+ pipe_caps.inverse_pma = pipe_obj.second.inverse_pma;
+ pipe_caps.dgm_csc_version = pipe_obj.second.dgm_csc_version;
+ // disable src tonemap feature if its disabled using property.
+ if (!disable_src_tonemap) {
+ for (auto &it : pipe_obj.second.tonemap_lut_version_map) {
+ HWToneMapLut tonemap_lut = kLutNone;
+ switch (it.first) {
+ case DRMTonemapLutType::DMA_1D_IGC:
+ tonemap_lut = kDma1dIgc;
+ break;
+ case DRMTonemapLutType::DMA_1D_GC:
+ tonemap_lut = kDma1dGc;
+ break;
+ case DRMTonemapLutType::VIG_1D_IGC:
+ tonemap_lut = kVig1dIgc;
+ break;
+ case DRMTonemapLutType::VIG_3D_GAMUT:
+ tonemap_lut = kVig3dGamut;
+ break;
+ default:
+ DLOGE("Unknown Tonemap Lut");
+ break;
+ }
+ if (tonemap_lut != kLutNone) {
+ pipe_caps.tm_lut_version_map[tonemap_lut] = it.second;
+ if (pipe_caps.type == kPipeTypeVIG) {
+ hw_resource->src_tone_map[kSrcTonemap3d] = 1;
+ } else if (pipe_caps.type == kPipeTypeDMA) {
+ hw_resource->src_tone_map[kSrcTonemap1d] = 1;
+ }
+ }
+ }
+ }
hw_resource->hw_pipes.push_back(std::move(pipe_caps));
}
hw_resource->has_excl_rect = planes[0].second.has_excl_rect;