sdm: Add support for qseed3 scalar(v2)
- Read qseed3 capabilities from the HW
- Update the HWScaleData interface to include scale_data_v2(qseed3)
parameters
- Move scale data handling to new HWScale Interface
Change-Id: Id5377037b99b0c3bd2fb2edf71f3b7167300bc6c
Crs-fixed: 990559
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 5ecb75d..148de7c 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -35,6 +35,9 @@
namespace sdm {
const int kMaxSDELayers = 16; // Maximum number of layers that can be handled by hardware in a
// given layer stack.
+#define MAX_PLANES 4
+
+#define MAX_DETAIL_ENHANCE_CURVE 3
enum HWDeviceType {
kDevicePrimary,
@@ -84,9 +87,31 @@
kHWRotatorInput,
kHWRotatorOutput,
kHWWBIntfOutput,
+ kHWDestinationScalar,
kHWSubBlockMax,
};
+// y/RGB & UV Scaling Filters
+enum HWScalingFilter {
+ kScalingFilterEdgeDirected,
+ kScalingFilterCircular,
+ kScalingFilterSeparable,
+ kScalingFilterBilinear,
+ kScalingFilterMax,
+};
+
+enum HWAlphaInterpolation {
+ kInterpolationPixelRepeat,
+ kInterpolationBilinear,
+ kInterpolationMax,
+};
+
+enum HWBlendingFilter {
+ kBlendFilterCircular,
+ kBlendFilterSeparable,
+ kBlendFilterMax,
+};
+
typedef std::map<HWSubBlockType, std::vector<LayerBufferFormat>> FormatsMap;
struct HWDynBwLimitInfo {
@@ -148,6 +173,7 @@
bool perf_calc = false;
bool has_dyn_bw_support = false;
bool separate_rotator = false;
+ bool has_qseed3 = false;
HWDynBwLimitInfo dyn_bw_info;
std::vector<HWPipeCaps> hw_pipes;
FormatsMap supported_formats_map;
@@ -263,44 +289,101 @@
bool is_buffer_cached = false;
};
+struct HWScaleLutInfo {
+ uint32_t dir_lut_size = 0;
+ uint32_t cir_lut_size = 0;
+ uint32_t sep_lut_size = 0;
+ uint64_t dir_lut = 0;
+ uint64_t cir_lut = 0;
+ uint64_t sep_lut = 0;
+};
+
+struct HWDetailEnhanceData {
+ uint32_t enable = 0;
+ int16_t sharpen_level1 = 0;
+ int16_t sharpen_level2 = 0;
+ uint16_t clip = 0;
+ uint16_t limit = 0;
+ uint16_t thr_quiet = 0;
+ uint16_t thr_dieout = 0;
+ uint16_t thr_low = 0;
+ uint16_t thr_high = 0;
+ uint16_t prec_shift = 0;
+ int16_t adjust_a[MAX_DETAIL_ENHANCE_CURVE] = {0};
+ int16_t adjust_b[MAX_DETAIL_ENHANCE_CURVE] = {0};
+ int16_t adjust_c[MAX_DETAIL_ENHANCE_CURVE] = {0};
+};
+
struct HWPixelExtension {
- int extension; // Number of pixels extension in left, right, top and bottom directions for all
- // color components. This pixel value for each color component should be sum of
- // fetch and repeat pixels.
+ int32_t extension = 0; // Number of pixels extension in left, right, top and bottom directions
+ // for all color components. This pixel value for each color component
+ // should be sum of fetch and repeat pixels.
- int overfetch; // Number of pixels need to be overfetched in left, right, top and bottom
- // directions from source image for scaling.
+ int32_t overfetch = 0; // Number of pixels need to be overfetched in left, right, top and bottom
+ // directions from source image for scaling.
- int repeat; // Number of pixels need to be repeated in left, right, top and bottom directions
- // for scaling.
+ int32_t repeat = 0; // Number of pixels need to be repeated in left, right, top and bottom
+ // directions for scaling.
};
struct HWPlane {
- int init_phase_x = 0;
- int phase_step_x = 0;
- int init_phase_y = 0;
- int phase_step_y = 0;
+ int32_t init_phase_x = 0;
+ int32_t phase_step_x = 0;
+ int32_t init_phase_y = 0;
+ int32_t phase_step_y = 0;
HWPixelExtension left;
HWPixelExtension top;
HWPixelExtension right;
HWPixelExtension bottom;
uint32_t roi_width = 0;
-};
-
-struct ScaleData {
- uint8_t enable_pixel_ext;
+ int32_t preload_x = 0;
+ int32_t preload_y = 0;
uint32_t src_width = 0;
uint32_t src_height = 0;
- HWPlane plane[4];
+};
+
+struct HWScaleData {
+ struct enable {
+ uint8_t scale = 0;
+ uint8_t direction_detection = 0;
+ uint8_t detail_enhance = 0;
+ } enable;
+ uint32_t dst_width = 0;
+ uint32_t dst_height = 0;
+ HWPlane plane[MAX_PLANES];
+ // scale_v2_data fields
+ HWScalingFilter y_rgb_filter_cfg = kScalingFilterEdgeDirected;
+ HWScalingFilter uv_filter_cfg = kScalingFilterEdgeDirected;
+ HWAlphaInterpolation alpha_filter_cfg = kInterpolationPixelRepeat;
+ HWBlendingFilter blend_cfg = kBlendFilterCircular;
+
+ struct lut_flags {
+ uint8_t lut_swap = 0;
+ uint8_t lut_dir_wr = 0;
+ uint8_t lut_y_cir_wr = 0;
+ uint8_t lut_uv_cir_wr = 0;
+ uint8_t lut_y_sep_wr = 0;
+ uint8_t lut_uv_sep_wr = 0;
+ } lut_flag;
+
+ uint32_t dir_lut_idx = 0;
+ /* for Y(RGB) and UV planes*/
+ uint32_t y_rgb_cir_lut_idx = 0;
+ uint32_t uv_cir_lut_idx = 0;
+ uint32_t y_rgb_sep_lut_idx = 0;
+ uint32_t uv_sep_lut_idx = 0;
+
+ HWDetailEnhanceData detail_enhance;
};
struct HWPipeInfo {
uint32_t pipe_id = 0;
+ HWSubBlockType sub_block_type = kHWSubBlockMax;
LayerRect src_roi;
LayerRect dst_roi;
uint8_t horizontal_decimation = 0;
uint8_t vertical_decimation = 0;
- ScaleData scale_data;
+ HWScaleData scale_data;
uint32_t z_order = 0;
bool set_igc = false;
bool valid = false;
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 9a5aaea..c350460 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2016, 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:
@@ -52,6 +52,7 @@
virtual DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
int x, int y) = 0;
virtual DisplayError SetMaxBandwidthMode(HWBwModes mode) = 0;
+ virtual DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
protected:
virtual ~ResourceInterface() { }
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index 3cc57d2..c468420 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -29,6 +29,7 @@
$(LOCAL_HW_INTF_PATH)/hw_primary.cpp \
$(LOCAL_HW_INTF_PATH)/hw_hdmi.cpp \
$(LOCAL_HW_INTF_PATH)/hw_virtual.cpp \
- $(LOCAL_HW_INTF_PATH)/hw_color_manager.cpp
+ $(LOCAL_HW_INTF_PATH)/hw_color_manager.cpp \
+ $(LOCAL_HW_INTF_PATH)/hw_scale.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index dc1e29e..a7f137a 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -475,5 +475,9 @@
return false;
}
+DisplayError CompManager::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
+ return resource_intf_->GetScaleLutConfig(lut_info);
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 7744070..d6d45c1 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -61,6 +61,7 @@
bool SupportLayerAsCursor(Handle display_ctx, HWLayers *hw_layers);
bool CanSetIdleTimeout(Handle display_ctx);
DisplayError SetMaxBandwidthMode(HWBwModes mode);
+ DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
// DumpImpl method
virtual void AppendDump(char *buffer, uint32_t length);
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index c2973e0..5a155b7 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -54,6 +54,16 @@
hw_intf_->GetActiveConfig(&active_index);
hw_intf_->GetDisplayAttributes(active_index, &display_attrib);
+ HWScaleLutInfo lut_info = {};
+ error = comp_manager_->GetScaleLutConfig(&lut_info);
+ if (error == kErrorNone) {
+ error = hw_intf_->SetScaleLutConfig(&lut_info);
+ }
+
+ if (error != kErrorNone) {
+ goto CleanupOnError;
+ }
+
error = comp_manager_->RegisterDisplay(display_type_, display_attrib,
hw_panel_info_, &display_comp_ctx_);
if (error != kErrorNone) {
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index e4f8dae..fe157a2 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -59,7 +59,6 @@
}
DisplayError HWDevice::Init(HWEventHandler *eventhandler) {
- DisplayError error = kErrorNone;
char device_name[64] = {0};
event_handler_ = eventhandler;
@@ -84,10 +83,12 @@
return kErrorResources;
}
- return error;
+ return HWScale::Create(&hw_scale_, hw_resource_.has_qseed3);
}
DisplayError HWDevice::Deinit() {
+ HWScale::Destroy(hw_scale_);
+
if (device_fd_ >= 0) {
Sys::close_(device_fd_);
device_fd_ = -1;
@@ -232,13 +233,9 @@
}
mdp_layer.bg_color = layer.solid_fill_color;
- if (pipe_info->scale_data.enable_pixel_ext) {
- SetHWScaleData(pipe_info->scale_data, mdp_layer_count);
- mdp_layer.flags |= MDP_LAYER_ENABLE_PIXEL_EXT;
- }
-
- // Send scale data to MDP driver
- mdp_layer.scale = GetScaleDataRef(mdp_layer_count);
+ // HWScaleData to MDP driver
+ hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_layer);
+ mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count);
mdp_layer_count++;
DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
@@ -253,17 +250,7 @@
mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
- for (int j = 0; j < 4; j++) {
- mdp_scale_data *scale = reinterpret_cast<mdp_scale_data*>(mdp_layer.scale);
- DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
- j, scale->init_phase_x[j], scale->phase_step_x[j], scale->init_phase_y[j],
- scale->phase_step_y[j], scale->num_ext_pxls_left[j], scale->num_ext_pxls_top[j],
- scale->num_ext_pxls_right[j], scale->num_ext_pxls_btm[j]);
- DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d] Repeat=[%d %d %d %d] roi_width = %d",
- scale->left_ftch[j], scale->top_ftch[j], scale->right_ftch[j], scale->btm_ftch[j],
- scale->left_rpt[j], scale->top_rpt[j], scale->right_rpt[j], scale->btm_rpt[j],
- scale->roi_w[j]);
- }
+ hw_scale_->DumpScaleData(mdp_layer.scale);
DLOGV_IF(kTagDriverConfig, "*************************************************************");
}
}
@@ -958,7 +945,7 @@
memset(&mdp_disp_commit_, 0, sizeof(mdp_disp_commit_));
memset(&mdp_in_layers_, 0, sizeof(mdp_in_layers_));
memset(&mdp_out_layer_, 0, sizeof(mdp_out_layer_));
- memset(&scale_data_, 0, sizeof(scale_data_));
+ hw_scale_->ResetScaleParams();
memset(&pp_params_, 0, sizeof(pp_params_));
memset(&igc_lut_data_, 0, sizeof(igc_lut_data_));
@@ -973,37 +960,6 @@
mdp_disp_commit_.commit_v1.retire_fence = -1;
}
-void HWDevice::SetHWScaleData(const ScaleData &scale, uint32_t index) {
- mdp_scale_data *mdp_scale = GetScaleDataRef(index);
- mdp_scale->enable_pxl_ext = scale.enable_pixel_ext;
-
- for (int i = 0; i < 4; i++) {
- const HWPlane &plane = scale.plane[i];
- mdp_scale->init_phase_x[i] = plane.init_phase_x;
- mdp_scale->phase_step_x[i] = plane.phase_step_x;
- mdp_scale->init_phase_y[i] = plane.init_phase_y;
- mdp_scale->phase_step_y[i] = plane.phase_step_y;
-
- mdp_scale->num_ext_pxls_left[i] = plane.left.extension;
- mdp_scale->left_ftch[i] = plane.left.overfetch;
- mdp_scale->left_rpt[i] = plane.left.repeat;
-
- mdp_scale->num_ext_pxls_top[i] = plane.top.extension;
- mdp_scale->top_ftch[i] = plane.top.overfetch;
- mdp_scale->top_rpt[i] = plane.top.repeat;
-
- mdp_scale->num_ext_pxls_right[i] = plane.right.extension;
- mdp_scale->right_ftch[i] = plane.right.overfetch;
- mdp_scale->right_rpt[i] = plane.right.repeat;
-
- mdp_scale->num_ext_pxls_btm[i] = plane.bottom.extension;
- mdp_scale->btm_ftch[i] = plane.bottom.overfetch;
- mdp_scale->btm_rpt[i] = plane.bottom.repeat;
-
- mdp_scale->roi_w[i] = plane.roi_width;
- }
-}
-
void HWDevice::SetCSC(LayerCSC source, mdp_color_space *color_space) {
switch (source) {
case kCSCLimitedRange601: *color_space = MDP_CSC_ITU_R_601; break;
@@ -1133,5 +1089,40 @@
return kErrorNotSupported;
}
+DisplayError HWDevice::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
+ STRUCT_VAR(mdp_scale_luts_info, mdp_lut_info);
+ STRUCT_VAR(mdp_set_cfg, cfg);
+
+ if (!hw_resource_.has_qseed3) {
+ DLOGV_IF(kTagDriverConfig, "No support for QSEED3 luts");
+ return kErrorNone;
+ }
+
+ if (!lut_info->dir_lut_size && !lut_info->dir_lut && !lut_info->cir_lut_size &&
+ !lut_info->cir_lut && !lut_info->sep_lut_size && !lut_info->sep_lut) {
+ // HWSupports QSEED3, but LutInfo is invalid as scalar is disabled by property or
+ // its loading failed. Driver will use default settings/filter
+ return kErrorNone;
+ }
+
+ mdp_lut_info.dir_lut_size = lut_info->dir_lut_size;
+ mdp_lut_info.dir_lut = lut_info->dir_lut;
+ mdp_lut_info.cir_lut_size = lut_info->cir_lut_size;
+ mdp_lut_info.cir_lut = lut_info->cir_lut;
+ mdp_lut_info.sep_lut_size = lut_info->sep_lut_size;
+ mdp_lut_info.sep_lut = lut_info->sep_lut;
+
+ cfg.flags = MDP_QSEED3_LUT_CFG;
+ cfg.len = sizeof(mdp_scale_luts_info);
+ cfg.payload = reinterpret_cast<uint64_t>(&mdp_lut_info);
+
+ if (Sys::ioctl_(device_fd_, MSMFB_MDP_SET_CFG, &cfg) < 0) {
+ IOCTL_LOGE(MSMFB_MDP_SET_CFG, device_type_);
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index a0eeca6..82a9ee6 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, 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:
@@ -31,6 +31,7 @@
#include <pthread.h>
#include "hw_interface.h"
+#include "hw_scale.h"
#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \
type, errno, strerror(errno))
@@ -74,6 +75,7 @@
virtual DisplayError GetPanelBrightness(int *level);
virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
+ virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
// For HWDevice derivatives
virtual DisplayError Init(HWEventHandler *eventhandler);
@@ -108,8 +110,6 @@
int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
int ParseLine(char *input, const char *delim, char *tokens[],
const uint32_t max_token, uint32_t *count);
- mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data_[index]; }
- void SetHWScaleData(const ScaleData &scale, uint32_t index);
void ResetDisplayParams();
void SetCSC(LayerCSC source, mdp_color_space *color_space);
void SetIGC(const Layer &layer, uint32_t index);
@@ -130,7 +130,7 @@
HWDeviceType device_type_;
mdp_layer_commit mdp_disp_commit_;
mdp_input_layer mdp_in_layers_[kMaxSDELayers * 2]; // split panel (left + right)
- mdp_scale_data scale_data_[kMaxSDELayers * 2];
+ HWScale *hw_scale_ = NULL;
mdp_overlay_pp_params pp_params_[kMaxSDELayers * 2];
mdp_igc_lut_data_v1_7 igc_lut_data_[kMaxSDELayers * 2];
mdp_output_layer mdp_out_layer_;
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
index 7db0a47..7b707c1 100644
--- a/sdm/libs/core/fb/hw_info.cpp
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -255,6 +255,8 @@
hw_resource->has_dyn_bw_support = true;
} else if (!strncmp(tokens[i], "separate_rotator", strlen("separate_rotator"))) {
hw_resource->separate_rotator = true;
+ } else if (!strncmp(tokens[i], "qseed3", strlen("qseed3"))) {
+ hw_resource->has_qseed3 = true;
}
}
} else if (!strncmp(tokens[0], "pipe_count", strlen("pipe_count"))) {
@@ -315,7 +317,7 @@
hw_resource->max_scale_down, hw_resource->num_blending_stages);
DLOGI("BWC = %d, UBWC = %d, Decimation = %d, Tile Format = %d", hw_resource->has_bwc,
hw_resource->has_ubwc, hw_resource->has_decimation, hw_resource->has_macrotile);
- DLOGI("SourceSplit = %d", hw_resource->is_src_split);
+ DLOGI("SourceSplit = %d QSEED3 = %d", hw_resource->is_src_split, hw_resource->has_qseed3);
DLOGI("MaxLowBw = %" PRIu64 " , MaxHighBw = % " PRIu64 "", hw_resource->max_bandwidth_low,
hw_resource->max_bandwidth_high);
DLOGI("MaxPipeBw = %" PRIu64 " KBps, MaxSDEClock = % " PRIu64 " Hz, ClockFudgeFactor = %f",
diff --git a/sdm/libs/core/fb/hw_scale.cpp b/sdm/libs/core/fb/hw_scale.cpp
new file mode 100644
index 0000000..f18727f
--- /dev/null
+++ b/sdm/libs/core/fb/hw_scale.cpp
@@ -0,0 +1,286 @@
+/*
+* Copyright (c) 2016, 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.
+*/
+
+#include <stdio.h>
+#include <utils/debug.h>
+#include "hw_scale.h"
+
+#define __CLASS__ "HWScale"
+
+namespace sdm {
+
+DisplayError HWScale::Create(HWScale **intf, bool has_qseed3) {
+ if (has_qseed3) {
+ *intf = new HWScaleV2();
+ } else {
+ *intf = new HWScaleV1();
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWScale::Destroy(HWScale *intf) {
+ delete intf;
+
+ return kErrorNone;
+}
+
+void HWScaleV1::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
+ mdp_input_layer *mdp_layer) {
+ if (!scale_data.enable.scale) {
+ return;
+ }
+
+ mdp_layer->flags |= MDP_LAYER_ENABLE_PIXEL_EXT;
+ mdp_scale_data *mdp_scale = &scale_data_v1_.at(index);
+ mdp_scale->enable_pxl_ext = scale_data.enable.scale;
+ for (int i = 0; i < MAX_PLANES; i++) {
+ const HWPlane &plane = scale_data.plane[i];
+ mdp_scale->init_phase_x[i] = plane.init_phase_x;
+ mdp_scale->phase_step_x[i] = plane.phase_step_x;
+ mdp_scale->init_phase_y[i] = plane.init_phase_y;
+ mdp_scale->phase_step_y[i] = plane.phase_step_y;
+
+ mdp_scale->num_ext_pxls_left[i] = plane.left.extension;
+ mdp_scale->left_ftch[i] = plane.left.overfetch;
+ mdp_scale->left_rpt[i] = plane.left.repeat;
+
+ mdp_scale->num_ext_pxls_top[i] = plane.top.extension;
+ mdp_scale->top_ftch[i] = plane.top.overfetch;
+ mdp_scale->top_rpt[i] = plane.top.repeat;
+
+ mdp_scale->num_ext_pxls_right[i] = plane.right.extension;
+ mdp_scale->right_ftch[i] = plane.right.overfetch;
+ mdp_scale->right_rpt[i] = plane.right.repeat;
+
+ mdp_scale->num_ext_pxls_btm[i] = plane.bottom.extension;
+ mdp_scale->btm_ftch[i] = plane.bottom.overfetch;
+ mdp_scale->btm_rpt[i] = plane.bottom.repeat;
+
+ mdp_scale->roi_w[i] = plane.roi_width;
+ }
+
+ return;
+}
+
+void* HWScaleV1::GetScaleDataRef(uint32_t index) {
+ return &scale_data_v1_.at(index);
+}
+
+void HWScaleV1::DumpScaleData(void *mdp_scale) {
+ if (!mdp_scale) {
+ return;
+ }
+
+ mdp_scale_data *scale = reinterpret_cast<mdp_scale_data *>(mdp_scale);
+ if (scale->enable_pxl_ext) {
+ DLOGV_IF(kTagDriverConfig, "Scale Enable = %d", scale->enable_pxl_ext);
+ for (int j = 0; j < MAX_PLANES; j++) {
+ DLOGV_IF(kTagDriverConfig, "Scale Data[%d] : Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
+ j, scale->init_phase_x[j], scale->phase_step_x[j], scale->init_phase_y[j],
+ scale->phase_step_y[j], scale->num_ext_pxls_left[j], scale->num_ext_pxls_top[j],
+ scale->num_ext_pxls_right[j], scale->num_ext_pxls_btm[j]);
+ DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d] Repeat=[%d %d %d %d] roi_width = %d",
+ scale->left_ftch[j], scale->top_ftch[j], scale->right_ftch[j], scale->btm_ftch[j],
+ scale->left_rpt[j], scale->top_rpt[j], scale->right_rpt[j], scale->btm_rpt[j],
+ scale->roi_w[j]);
+ }
+ }
+
+ return;
+}
+
+void HWScaleV2::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
+ mdp_input_layer *mdp_layer) {
+ if (!scale_data.enable.scale && !scale_data.enable.direction_detection &&
+ !scale_data.enable.detail_enhance ) {
+ return;
+ }
+
+ mdp_scale_data_v2 *mdp_scale = &scale_data_v2_.at(index);
+ mdp_layer->flags |= MDP_LAYER_ENABLE_QSEED3_SCALE;
+ mdp_scale->enable = (scale_data.enable.scale ? ENABLE_SCALE : 0) |
+ (scale_data.enable.direction_detection ? ENABLE_DIRECTION_DETECTION : 0) |
+ (scale_data.enable.detail_enhance ? ENABLE_DETAIL_ENHANCE : 0);
+
+ for (int i = 0; i < MAX_PLANES; i++) {
+ const HWPlane &plane = scale_data.plane[i];
+ mdp_scale->init_phase_x[i] = plane.init_phase_x;
+ mdp_scale->phase_step_x[i] = plane.phase_step_x;
+ mdp_scale->init_phase_y[i] = plane.init_phase_y;
+ mdp_scale->phase_step_y[i] = plane.phase_step_y;
+
+ mdp_scale->num_ext_pxls_left[i] = UINT32(plane.left.extension);
+ mdp_scale->left_ftch[i] = plane.left.overfetch;
+ mdp_scale->left_rpt[i] = plane.left.repeat;
+
+ mdp_scale->num_ext_pxls_top[i] = UINT32(plane.top.extension);
+ mdp_scale->top_ftch[i] = UINT32(plane.top.overfetch);
+ mdp_scale->top_rpt[i] = UINT32(plane.top.repeat);
+
+ mdp_scale->num_ext_pxls_right[i] = UINT32(plane.right.extension);
+ mdp_scale->right_ftch[i] = plane.right.overfetch;
+ mdp_scale->right_rpt[i] = plane.right.repeat;
+
+ mdp_scale->num_ext_pxls_btm[i] = UINT32(plane.bottom.extension);
+ mdp_scale->btm_ftch[i] = UINT32(plane.bottom.overfetch);
+ mdp_scale->btm_rpt[i] = UINT32(plane.bottom.repeat);
+
+ mdp_scale->roi_w[i] = plane.roi_width;
+
+ mdp_scale->preload_x[i] = UINT32(plane.preload_x);
+ mdp_scale->preload_y[i] = UINT32(plane.preload_y);
+
+ mdp_scale->src_width[i] = plane.src_width;
+ mdp_scale->src_height[i] = plane.src_height;
+ }
+
+ mdp_scale->dst_width = scale_data.dst_width;
+ mdp_scale->dst_height = scale_data.dst_height;
+
+ mdp_scale->y_rgb_filter_cfg = GetMDPScalingFilter(scale_data.y_rgb_filter_cfg);
+ mdp_scale->uv_filter_cfg = GetMDPScalingFilter(scale_data.uv_filter_cfg);
+ mdp_scale->alpha_filter_cfg = GetMDPAlphaInterpolation(scale_data.alpha_filter_cfg);
+ mdp_scale->blend_cfg = scale_data.blend_cfg;
+
+ mdp_scale->lut_flag = (scale_data.lut_flag.lut_swap ? SCALER_LUT_SWAP : 0) |
+ (scale_data.lut_flag.lut_dir_wr ? SCALER_LUT_DIR_WR : 0) |
+ (scale_data.lut_flag.lut_y_cir_wr ? SCALER_LUT_Y_CIR_WR : 0) |
+ (scale_data.lut_flag.lut_uv_cir_wr ? SCALER_LUT_UV_CIR_WR : 0) |
+ (scale_data.lut_flag.lut_y_sep_wr ? SCALER_LUT_Y_SEP_WR : 0) |
+ (scale_data.lut_flag.lut_uv_sep_wr ? SCALER_LUT_UV_SEP_WR : 0);
+
+ // lut indicies - index starts from 0, hence subtract by 1 when > 0
+ mdp_scale->dir_lut_idx = (scale_data.dir_lut_idx > 0) ? scale_data.dir_lut_idx - 1 :
+ scale_data.dir_lut_idx;
+ mdp_scale->y_rgb_cir_lut_idx = (scale_data.y_rgb_cir_lut_idx > 0) ?
+ scale_data.y_rgb_cir_lut_idx - 1 : scale_data.y_rgb_cir_lut_idx;
+ mdp_scale->uv_cir_lut_idx = (scale_data.uv_cir_lut_idx > 0) ? scale_data.uv_cir_lut_idx - 1 :
+ scale_data.uv_cir_lut_idx;
+ mdp_scale->y_rgb_sep_lut_idx = (scale_data.y_rgb_sep_lut_idx > 0) ?
+ scale_data.y_rgb_sep_lut_idx - 1 : scale_data.y_rgb_sep_lut_idx;
+ mdp_scale->uv_sep_lut_idx = (scale_data.uv_sep_lut_idx > 0) ? scale_data.uv_sep_lut_idx - 1 :
+ scale_data.uv_sep_lut_idx;
+
+ if (mdp_scale->enable & ENABLE_DETAIL_ENHANCE) {
+ mdp_det_enhance_data *mdp_det_enhance = &mdp_scale->detail_enhance;
+ mdp_det_enhance->enable = scale_data.detail_enhance.enable;
+ mdp_det_enhance->sharpen_level1 = scale_data.detail_enhance.sharpen_level1;
+ mdp_det_enhance->sharpen_level2 = scale_data.detail_enhance.sharpen_level2;
+ mdp_det_enhance->clip = scale_data.detail_enhance.clip;
+ mdp_det_enhance->limit = scale_data.detail_enhance.limit;
+ mdp_det_enhance->thr_quiet = scale_data.detail_enhance.thr_quiet;
+ mdp_det_enhance->thr_dieout = scale_data.detail_enhance.thr_dieout;
+ mdp_det_enhance->thr_low = scale_data.detail_enhance.thr_low;
+ mdp_det_enhance->thr_high = scale_data.detail_enhance.thr_high;
+ mdp_det_enhance->prec_shift = scale_data.detail_enhance.prec_shift;
+
+ for (int i = 0; i < MAX_DET_CURVES; i++) {
+ mdp_det_enhance->adjust_a[i] = scale_data.detail_enhance.adjust_a[i];
+ mdp_det_enhance->adjust_b[i] = scale_data.detail_enhance.adjust_b[i];
+ mdp_det_enhance->adjust_c[i] = scale_data.detail_enhance.adjust_c[i];
+ }
+ }
+
+ return;
+}
+
+void* HWScaleV2::GetScaleDataRef(uint32_t index) {
+ return &scale_data_v2_.at(index);
+}
+
+uint32_t HWScaleV2::GetMDPScalingFilter(HWScalingFilter filter_cfg) {
+ switch (filter_cfg) {
+ case kScalingFilterEdgeDirected:
+ return FILTER_EDGE_DIRECTED_2D;
+ case kScalingFilterCircular:
+ return FILTER_CIRCULAR_2D;
+ case kScalingFilterSeparable:
+ return FILTER_SEPARABLE_1D;
+ case kScalingFilterBilinear:
+ return FILTER_BILINEAR;
+ default:
+ DLOGE("Invalid Scaling Filter");
+ return kScalingFilterMax;
+ }
+}
+
+uint32_t HWScaleV2::GetMDPAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg) {
+ switch (alpha_filter_cfg) {
+ case kInterpolationPixelRepeat:
+ return FILTER_ALPHA_DROP_REPEAT;
+ case kInterpolationBilinear:
+ return FILTER_ALPHA_BILINEAR;
+ default:
+ DLOGE("Invalid Alpha Interpolation");
+ return kInterpolationMax;
+ }
+}
+
+void HWScaleV2::DumpScaleData(void *mdp_scale) {
+ if (!mdp_scale) {
+ return;
+ }
+
+ mdp_scale_data_v2 *scale = reinterpret_cast<mdp_scale_data_v2 *>(mdp_scale);
+ if (scale->enable) {
+ DLOGV_IF(kTagDriverConfig, "Scale Enable = %d", scale->enable);
+ for (int j = 0; j < MAX_PLANES; j++) {
+ DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase_init[x y]=[%x %x] Phase_step:[x y]=[%x %x]",
+ j, scale->init_phase_x[j], scale->init_phase_y[j], scale->phase_step_x[j],
+ scale->phase_step_y[j]);
+ DLOGV_IF(kTagDriverConfig, "Preload[x y]=[%x %x], Pixel Ext=[%d %d] Ovfetch=[%d %d %d %d]",
+ scale->preload_x[j], scale->preload_y[j], scale->num_ext_pxls_left[j],
+ scale->num_ext_pxls_top[j], scale->left_ftch[j], scale->top_ftch[j], scale->right_ftch[j],
+ scale->btm_ftch[j]);
+ DLOGV_IF(kTagDriverConfig, "Repeat=[%d %d %d %d] Src[w x h]=[%d %d] roi_width = %d",
+ scale->left_rpt[j], scale->top_rpt[j], scale->right_rpt[j], scale->btm_rpt[j],
+ scale->src_width[j], scale->src_height[j], scale->roi_w[j]);
+ }
+
+ DLOGV_IF(kTagDriverConfig, "LUT flags = %d", scale->lut_flag);
+ DLOGV_IF(kTagDriverConfig, "y_rgb_filter=%d, uv_filter=%d, alpha_filter=%d, blend_cfg=%d",
+ scale->y_rgb_filter_cfg, scale->uv_filter_cfg, scale->alpha_filter_cfg, scale->blend_cfg);
+ DLOGV_IF(kTagDriverConfig, "dir_lut=%d, y_rgb_cir=%d, uv_cir=%d, y_rgb_sep=%d, uv_sep=%d",
+ scale->dir_lut_idx, scale->y_rgb_cir_lut_idx, scale->uv_cir_lut_idx,
+ scale->y_rgb_sep_lut_idx, scale->uv_sep_lut_idx);
+ if (scale->enable & ENABLE_DETAIL_ENHANCE) {
+ mdp_det_enhance_data *de = &scale->detail_enhance;
+ DLOGV_IF(kTagDriverConfig, "Detail Enhance: enable: %d sharpen_level1: %d sharpen_level2: %d",
+ de->enable, de->sharpen_level1, de->sharpen_level2);
+ DLOGV_IF(kTagDriverConfig, "clip: %d limit:%d thr_quiet: %d thr_dieout: %d",
+ de->clip, de->limit, de->thr_quiet, de->thr_dieout);
+ DLOGV_IF(kTagDriverConfig, "thr_low: %d thr_high: %d prec_shift: %d", de->thr_low,
+ de->thr_high, de->prec_shift);
+ for (uint32_t i = 0; i < MAX_DET_CURVES; i++) {
+ DLOGV_IF(kTagDriverConfig, "adjust_a[%d]: %d adjust_b[%d]: %d adjust_c[%d]: %d", i,
+ de->adjust_a[i], i, de->adjust_b[i], i, de->adjust_c[i]);
+ }
+ }
+ }
+
+ return;
+}
+
+} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_scale.h b/sdm/libs/core/fb/hw_scale.h
new file mode 100644
index 0000000..0891d42
--- /dev/null
+++ b/sdm/libs/core/fb/hw_scale.h
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2016, 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.
+*/
+
+#ifndef __HW_SCALE_H__
+#define __HW_SCALE_H__
+
+#include <linux/msm_mdp_ext.h>
+#include <private/hw_info_types.h>
+
+#include <cstring>
+#include <array>
+
+namespace sdm {
+
+class HWScale {
+ public:
+ static DisplayError Create(HWScale **intf, bool has_qseed3);
+ static DisplayError Destroy(HWScale *intf);
+
+ virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
+ mdp_input_layer *mdp_layer) = 0;
+ virtual void* GetScaleDataRef(uint32_t index) = 0;
+ virtual void DumpScaleData(void *mdp_scale) = 0;
+ virtual void ResetScaleParams() = 0;
+ protected:
+ virtual ~HWScale() { }
+};
+
+class HWScaleV1 : public HWScale {
+ public:
+ virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
+ mdp_input_layer *mdp_layer);
+ virtual void* GetScaleDataRef(uint32_t index);
+ virtual void DumpScaleData(void *mdp_scale);
+ virtual void ResetScaleParams() { scale_data_v1_ = {}; }
+
+ protected:
+ ~HWScaleV1() {}
+ std::array<mdp_scale_data, (kMaxSDELayers * 2)> scale_data_v1_ = {};
+};
+
+class HWScaleV2 : public HWScale {
+ public:
+ virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
+ mdp_input_layer *mdp_layer);
+ virtual void* GetScaleDataRef(uint32_t index);
+ virtual void DumpScaleData(void *mdp_scale);
+ virtual void ResetScaleParams() { scale_data_v2_ = {}; }
+
+ protected:
+ ~HWScaleV2() {}
+ std::array<mdp_scale_data_v2, (kMaxSDELayers * 2)> scale_data_v2_ = {};
+
+ private:
+ uint32_t GetMDPAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg);
+ uint32_t GetMDPScalingFilter(HWScalingFilter filter_cfg);
+};
+
+} // namespace sdm
+
+#endif // __HW_SCALE_H__
+
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 9e9114f..7779350 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, 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:
@@ -92,6 +92,7 @@
virtual DisplayError GetPanelBrightness(int *level) = 0;
virtual DisplayError SetAutoRefresh(bool enable) = 0;
virtual DisplayError SetS3DMode(HWS3DMode s3d_mode) = 0;
+ virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
protected:
virtual ~HWInterface() { }
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index b2e928e..9a6eb52 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -893,4 +893,8 @@
return kErrorNotSupported;
}
+DisplayError ResourceDefault::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index cb633c0..23d7dfa 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -118,6 +118,7 @@
DisplayError AlignPipeConfig(const Layer &layer, HWPipeInfo *left_pipe, HWPipeInfo *right_pipe);
void ResourceStateLog(void);
DisplayError CalculateDecimation(float downscale, uint8_t *decimation);
+ DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
Locker locker_;
HWResourceInfo hw_res_info_;