1 /* 2 * Copyright (c) 2016, The Linux Foundation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without modification, are permitted 5 * provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright notice, this list of 7 * conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright notice, this list of 9 * conditions and the following disclaimer in the documentation and/or other materials provided 10 * with the distribution. 11 * * Neither the name of The Linux Foundation nor the names of its contributors may be used to 12 * endorse or promote products derived from this software without specific prior written 13 * permission. 14 * 15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 21 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include <stdio.h> 26 #include <utils/debug.h> 27 #include "hw_scale.h" 28 29 #define __CLASS__ "HWScale" 30 31 namespace sdm { 32 33 DisplayError HWScale::Create(HWScale **intf, bool has_qseed3) { 34 if (has_qseed3) { 35 *intf = new HWScaleV2(); 36 } else { 37 *intf = new HWScaleV1(); 38 } 39 40 return kErrorNone; 41 } 42 43 DisplayError HWScale::Destroy(HWScale *intf) { 44 delete intf; 45 46 return kErrorNone; 47 } 48 49 void HWScaleV1::SetHWScaleData(const HWScaleData &scale_data, uint32_t index, 50 mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) { 51 if (!scale_data.enable.scale) { 52 return; 53 } 54 55 if (sub_block_type == kHWDestinationScalar) { 56 return; 57 } 58 59 mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index]; 60 mdp_layer->flags |= MDP_LAYER_ENABLE_PIXEL_EXT; 61 mdp_scale_data *mdp_scale = &scale_data_v1_.at(index); 62 mdp_scale->enable_pxl_ext = scale_data.enable.scale; 63 for (int i = 0; i < MAX_PLANES; i++) { 64 const HWPlane &plane = scale_data.plane[i]; 65 mdp_scale->init_phase_x[i] = plane.init_phase_x; 66 mdp_scale->phase_step_x[i] = plane.phase_step_x; 67 mdp_scale->init_phase_y[i] = plane.init_phase_y; 68 mdp_scale->phase_step_y[i] = plane.phase_step_y; 69 70 mdp_scale->num_ext_pxls_left[i] = plane.left.extension; 71 mdp_scale->left_ftch[i] = plane.left.overfetch; 72 mdp_scale->left_rpt[i] = plane.left.repeat; 73 74 mdp_scale->num_ext_pxls_top[i] = plane.top.extension; 75 mdp_scale->top_ftch[i] = plane.top.overfetch; 76 mdp_scale->top_rpt[i] = plane.top.repeat; 77 78 mdp_scale->num_ext_pxls_right[i] = plane.right.extension; 79 mdp_scale->right_ftch[i] = plane.right.overfetch; 80 mdp_scale->right_rpt[i] = plane.right.repeat; 81 82 mdp_scale->num_ext_pxls_btm[i] = plane.bottom.extension; 83 mdp_scale->btm_ftch[i] = plane.bottom.overfetch; 84 mdp_scale->btm_rpt[i] = plane.bottom.repeat; 85 86 mdp_scale->roi_w[i] = plane.roi_width; 87 } 88 89 return; 90 } 91 92 void* HWScaleV1::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) { 93 if (sub_block_type != kHWDestinationScalar) { 94 return &scale_data_v1_.at(index); 95 } 96 97 return NULL; 98 } 99 100 void HWScaleV1::DumpScaleData(void *mdp_scale) { 101 if (!mdp_scale) { 102 return; 103 } 104 105 mdp_scale_data *scale = reinterpret_cast<mdp_scale_data *>(mdp_scale); 106 if (scale->enable_pxl_ext) { 107 DLOGV_IF(kTagDriverConfig, "Scale Enable = %d", scale->enable_pxl_ext); 108 for (int j = 0; j < MAX_PLANES; j++) { 109 DLOGV_IF(kTagDriverConfig, "Scale Data[%d] : Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]", 110 j, scale->init_phase_x[j], scale->phase_step_x[j], scale->init_phase_y[j], 111 scale->phase_step_y[j], scale->num_ext_pxls_left[j], scale->num_ext_pxls_top[j], 112 scale->num_ext_pxls_right[j], scale->num_ext_pxls_btm[j]); 113 DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d] Repeat=[%d %d %d %d] roi_width = %d", 114 scale->left_ftch[j], scale->top_ftch[j], scale->right_ftch[j], scale->btm_ftch[j], 115 scale->left_rpt[j], scale->top_rpt[j], scale->right_rpt[j], scale->btm_rpt[j], 116 scale->roi_w[j]); 117 } 118 } 119 120 return; 121 } 122 123 void HWScaleV2::SetHWScaleData(const HWScaleData &scale_data, uint32_t index, 124 mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) { 125 if (!scale_data.enable.scale && !scale_data.enable.direction_detection && 126 !scale_data.enable.detail_enhance ) { 127 return; 128 } 129 130 mdp_scale_data_v2 *mdp_scale; 131 if (sub_block_type != kHWDestinationScalar) { 132 mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index]; 133 mdp_layer->flags |= MDP_LAYER_ENABLE_QSEED3_SCALE; 134 mdp_scale = &scale_data_v2_.at(index); 135 } else { 136 mdp_scale_data_v2 mdp_dest_scale; 137 mdp_destination_scaler_data *dest_scalar = 138 reinterpret_cast<mdp_destination_scaler_data *>(mdp_commit->dest_scaler); 139 140 dest_scalar[index].flags = MDP_DESTSCALER_ENABLE; 141 142 if (scale_data.enable.detail_enhance) { 143 dest_scalar[index].flags |= MDP_DESTSCALER_ENHANCER_UPDATE; 144 } 145 146 dest_scale_data_v2_.insert(std::make_pair(index, mdp_dest_scale)); 147 mdp_scale = &dest_scale_data_v2_[index]; 148 } 149 150 mdp_scale->enable = (scale_data.enable.scale ? ENABLE_SCALE : 0) | 151 (scale_data.enable.direction_detection ? ENABLE_DIRECTION_DETECTION : 0) | 152 (scale_data.enable.detail_enhance ? ENABLE_DETAIL_ENHANCE : 0); 153 154 for (int i = 0; i < MAX_PLANES; i++) { 155 const HWPlane &plane = scale_data.plane[i]; 156 mdp_scale->init_phase_x[i] = plane.init_phase_x; 157 mdp_scale->phase_step_x[i] = plane.phase_step_x; 158 mdp_scale->init_phase_y[i] = plane.init_phase_y; 159 mdp_scale->phase_step_y[i] = plane.phase_step_y; 160 161 mdp_scale->num_ext_pxls_left[i] = UINT32(plane.left.extension); 162 mdp_scale->left_ftch[i] = plane.left.overfetch; 163 mdp_scale->left_rpt[i] = plane.left.repeat; 164 165 mdp_scale->num_ext_pxls_top[i] = UINT32(plane.top.extension); 166 mdp_scale->top_ftch[i] = UINT32(plane.top.overfetch); 167 mdp_scale->top_rpt[i] = UINT32(plane.top.repeat); 168 169 mdp_scale->num_ext_pxls_right[i] = UINT32(plane.right.extension); 170 mdp_scale->right_ftch[i] = plane.right.overfetch; 171 mdp_scale->right_rpt[i] = plane.right.repeat; 172 173 mdp_scale->num_ext_pxls_btm[i] = UINT32(plane.bottom.extension); 174 mdp_scale->btm_ftch[i] = UINT32(plane.bottom.overfetch); 175 mdp_scale->btm_rpt[i] = UINT32(plane.bottom.repeat); 176 177 mdp_scale->roi_w[i] = plane.roi_width; 178 179 mdp_scale->preload_x[i] = UINT32(plane.preload_x); 180 mdp_scale->preload_y[i] = UINT32(plane.preload_y); 181 182 mdp_scale->src_width[i] = plane.src_width; 183 mdp_scale->src_height[i] = plane.src_height; 184 } 185 186 mdp_scale->dst_width = scale_data.dst_width; 187 mdp_scale->dst_height = scale_data.dst_height; 188 189 mdp_scale->y_rgb_filter_cfg = GetMDPScalingFilter(scale_data.y_rgb_filter_cfg); 190 mdp_scale->uv_filter_cfg = GetMDPScalingFilter(scale_data.uv_filter_cfg); 191 mdp_scale->alpha_filter_cfg = GetMDPAlphaInterpolation(scale_data.alpha_filter_cfg); 192 mdp_scale->blend_cfg = scale_data.blend_cfg; 193 194 mdp_scale->lut_flag = (scale_data.lut_flag.lut_swap ? SCALER_LUT_SWAP : 0) | 195 (scale_data.lut_flag.lut_dir_wr ? SCALER_LUT_DIR_WR : 0) | 196 (scale_data.lut_flag.lut_y_cir_wr ? SCALER_LUT_Y_CIR_WR : 0) | 197 (scale_data.lut_flag.lut_uv_cir_wr ? SCALER_LUT_UV_CIR_WR : 0) | 198 (scale_data.lut_flag.lut_y_sep_wr ? SCALER_LUT_Y_SEP_WR : 0) | 199 (scale_data.lut_flag.lut_uv_sep_wr ? SCALER_LUT_UV_SEP_WR : 0); 200 201 // lut indicies - index starts from 0, hence subtract by 1 when > 0 202 mdp_scale->dir_lut_idx = (scale_data.dir_lut_idx > 0) ? scale_data.dir_lut_idx - 1 : 203 scale_data.dir_lut_idx; 204 mdp_scale->y_rgb_cir_lut_idx = (scale_data.y_rgb_cir_lut_idx > 0) ? 205 scale_data.y_rgb_cir_lut_idx - 1 : scale_data.y_rgb_cir_lut_idx; 206 mdp_scale->uv_cir_lut_idx = (scale_data.uv_cir_lut_idx > 0) ? scale_data.uv_cir_lut_idx - 1 : 207 scale_data.uv_cir_lut_idx; 208 mdp_scale->y_rgb_sep_lut_idx = (scale_data.y_rgb_sep_lut_idx > 0) ? 209 scale_data.y_rgb_sep_lut_idx - 1 : scale_data.y_rgb_sep_lut_idx; 210 mdp_scale->uv_sep_lut_idx = (scale_data.uv_sep_lut_idx > 0) ? scale_data.uv_sep_lut_idx - 1 : 211 scale_data.uv_sep_lut_idx; 212 213 if (mdp_scale->enable & ENABLE_DETAIL_ENHANCE) { 214 mdp_det_enhance_data *mdp_det_enhance = &mdp_scale->detail_enhance; 215 mdp_det_enhance->enable = scale_data.detail_enhance.enable; 216 mdp_det_enhance->sharpen_level1 = scale_data.detail_enhance.sharpen_level1; 217 mdp_det_enhance->sharpen_level2 = scale_data.detail_enhance.sharpen_level2; 218 mdp_det_enhance->clip = scale_data.detail_enhance.clip; 219 mdp_det_enhance->limit = scale_data.detail_enhance.limit; 220 mdp_det_enhance->thr_quiet = scale_data.detail_enhance.thr_quiet; 221 mdp_det_enhance->thr_dieout = scale_data.detail_enhance.thr_dieout; 222 mdp_det_enhance->thr_low = scale_data.detail_enhance.thr_low; 223 mdp_det_enhance->thr_high = scale_data.detail_enhance.thr_high; 224 mdp_det_enhance->prec_shift = scale_data.detail_enhance.prec_shift; 225 226 for (int i = 0; i < MAX_DET_CURVES; i++) { 227 mdp_det_enhance->adjust_a[i] = scale_data.detail_enhance.adjust_a[i]; 228 mdp_det_enhance->adjust_b[i] = scale_data.detail_enhance.adjust_b[i]; 229 mdp_det_enhance->adjust_c[i] = scale_data.detail_enhance.adjust_c[i]; 230 } 231 } 232 233 return; 234 } 235 236 void* HWScaleV2::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) { 237 if (sub_block_type != kHWDestinationScalar) { 238 return &scale_data_v2_.at(index); 239 } else { 240 return &dest_scale_data_v2_[index]; 241 } 242 } 243 244 uint32_t HWScaleV2::GetMDPScalingFilter(ScalingFilterConfig filter_cfg) { 245 switch (filter_cfg) { 246 case kFilterEdgeDirected: 247 return FILTER_EDGE_DIRECTED_2D; 248 case kFilterCircular: 249 return FILTER_CIRCULAR_2D; 250 case kFilterSeparable: 251 return FILTER_SEPARABLE_1D; 252 case kFilterBilinear: 253 return FILTER_BILINEAR; 254 default: 255 DLOGE("Invalid Scaling Filter"); 256 return kFilterMax; 257 } 258 } 259 260 uint32_t HWScaleV2::GetMDPAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg) { 261 switch (alpha_filter_cfg) { 262 case kInterpolationPixelRepeat: 263 return FILTER_ALPHA_DROP_REPEAT; 264 case kInterpolationBilinear: 265 return FILTER_ALPHA_BILINEAR; 266 default: 267 DLOGE("Invalid Alpha Interpolation"); 268 return kInterpolationMax; 269 } 270 } 271 272 void HWScaleV2::DumpScaleData(void *mdp_scale) { 273 if (!mdp_scale) { 274 return; 275 } 276 277 mdp_scale_data_v2 *scale = reinterpret_cast<mdp_scale_data_v2 *>(mdp_scale); 278 if (scale->enable) { 279 DLOGV_IF(kTagDriverConfig, "Scale Enable = %d", scale->enable); 280 for (int j = 0; j < MAX_PLANES; j++) { 281 DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase_init[x y]=[%x %x] Phase_step:[x y]=[%x %x]", 282 j, scale->init_phase_x[j], scale->init_phase_y[j], scale->phase_step_x[j], 283 scale->phase_step_y[j]); 284 DLOGV_IF(kTagDriverConfig, "Preload[x y]=[%x %x], Pixel Ext=[%d %d] Ovfetch=[%d %d %d %d]", 285 scale->preload_x[j], scale->preload_y[j], scale->num_ext_pxls_left[j], 286 scale->num_ext_pxls_top[j], scale->left_ftch[j], scale->top_ftch[j], scale->right_ftch[j], 287 scale->btm_ftch[j]); 288 DLOGV_IF(kTagDriverConfig, "Repeat=[%d %d %d %d] Src[w x h]=[%d %d] roi_width = %d", 289 scale->left_rpt[j], scale->top_rpt[j], scale->right_rpt[j], scale->btm_rpt[j], 290 scale->src_width[j], scale->src_height[j], scale->roi_w[j]); 291 } 292 293 DLOGV_IF(kTagDriverConfig, "LUT flags = %d", scale->lut_flag); 294 DLOGV_IF(kTagDriverConfig, "y_rgb_filter=%d, uv_filter=%d, alpha_filter=%d, blend_cfg=%d", 295 scale->y_rgb_filter_cfg, scale->uv_filter_cfg, scale->alpha_filter_cfg, scale->blend_cfg); 296 DLOGV_IF(kTagDriverConfig, "dir_lut=%d, y_rgb_cir=%d, uv_cir=%d, y_rgb_sep=%d, uv_sep=%d", 297 scale->dir_lut_idx, scale->y_rgb_cir_lut_idx, scale->uv_cir_lut_idx, 298 scale->y_rgb_sep_lut_idx, scale->uv_sep_lut_idx); 299 if (scale->enable & ENABLE_DETAIL_ENHANCE) { 300 mdp_det_enhance_data *de = &scale->detail_enhance; 301 DLOGV_IF(kTagDriverConfig, "Detail Enhance: enable: %d sharpen_level1: %d sharpen_level2: %d", 302 de->enable, de->sharpen_level1, de->sharpen_level2); 303 DLOGV_IF(kTagDriverConfig, "clip: %d limit:%d thr_quiet: %d thr_dieout: %d", 304 de->clip, de->limit, de->thr_quiet, de->thr_dieout); 305 DLOGV_IF(kTagDriverConfig, "thr_low: %d thr_high: %d prec_shift: %d", de->thr_low, 306 de->thr_high, de->prec_shift); 307 for (uint32_t i = 0; i < MAX_DET_CURVES; i++) { 308 DLOGV_IF(kTagDriverConfig, "adjust_a[%d]: %d adjust_b[%d]: %d adjust_c[%d]: %d", i, 309 de->adjust_a[i], i, de->adjust_b[i], i, de->adjust_c[i]); 310 } 311 } 312 } 313 314 return; 315 } 316 317 } // namespace sdm 318